rx-parse.y revision 1.1 1 1.1 christos /* rx-parse.y Renesas RX parser
2 1.1 christos Copyright 2008, 2009
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GAS, the GNU Assembler.
6 1.1 christos
7 1.1 christos GAS is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos GAS is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with GAS; see the file COPYING. If not, write to the Free
19 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 1.1 christos 02110-1301, USA. */
21 1.1 christos %{
22 1.1 christos
23 1.1 christos #include "as.h"
24 1.1 christos #include "safe-ctype.h"
25 1.1 christos #include "rx-defs.h"
26 1.1 christos
27 1.1 christos static int rx_lex (void);
28 1.1 christos
29 1.1 christos #define COND_EQ 0
30 1.1 christos #define COND_NE 1
31 1.1 christos
32 1.1 christos #define MEMEX 0x06
33 1.1 christos
34 1.1 christos #define BSIZE 0
35 1.1 christos #define WSIZE 1
36 1.1 christos #define LSIZE 2
37 1.1 christos
38 1.1 christos /* .sb .sw .l .uw */
39 1.1 christos static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
40 1.1 christos
41 1.1 christos /* Ok, here are the rules for using these macros...
42 1.1 christos
43 1.1 christos B*() is used to specify the base opcode bytes. Fields to be filled
44 1.1 christos in later, leave zero. Call this first.
45 1.1 christos
46 1.1 christos F() and FE() are used to fill in fields within the base opcode bytes. You MUST
47 1.1 christos call B*() before any F() or FE().
48 1.1 christos
49 1.1 christos [UN]*O*(), PC*() appends operands to the end of the opcode. You
50 1.1 christos must call P() and B*() before any of these, so that the fixups
51 1.1 christos have the right byte location.
52 1.1 christos O = signed, UO = unsigned, NO = negated, PC = pcrel
53 1.1 christos
54 1.1 christos IMM() adds an immediate and fills in the field for it.
55 1.1 christos NIMM() same, but negates the immediate.
56 1.1 christos NBIMM() same, but negates the immediate, for sbb.
57 1.1 christos DSP() adds a displacement, and fills in the field for it.
58 1.1 christos
59 1.1 christos Note that order is significant for the O, IMM, and DSP macros, as
60 1.1 christos they append their data to the operand buffer in the order that you
61 1.1 christos call them.
62 1.1 christos
63 1.1 christos Use "disp" for displacements whenever possible; this handles the
64 1.1 christos "0" case properly. */
65 1.1 christos
66 1.1 christos #define B1(b1) rx_base1 (b1)
67 1.1 christos #define B2(b1, b2) rx_base2 (b1, b2)
68 1.1 christos #define B3(b1, b2, b3) rx_base3 (b1, b2, b3)
69 1.1 christos #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
70 1.1 christos
71 1.1 christos /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
72 1.1 christos #define F(val,pos,sz) rx_field (val, pos, sz)
73 1.1 christos #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz);
74 1.1 christos
75 1.1 christos #define O1(v) rx_op (v, 1, RXREL_SIGNED)
76 1.1 christos #define O2(v) rx_op (v, 2, RXREL_SIGNED)
77 1.1 christos #define O3(v) rx_op (v, 3, RXREL_SIGNED)
78 1.1 christos #define O4(v) rx_op (v, 4, RXREL_SIGNED)
79 1.1 christos
80 1.1 christos #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED)
81 1.1 christos #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED)
82 1.1 christos #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED)
83 1.1 christos #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED)
84 1.1 christos
85 1.1 christos #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE)
86 1.1 christos #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE)
87 1.1 christos #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE)
88 1.1 christos #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE)
89 1.1 christos
90 1.1 christos #define PC1(v) rx_op (v, 1, RXREL_PCREL)
91 1.1 christos #define PC2(v) rx_op (v, 2, RXREL_PCREL)
92 1.1 christos #define PC3(v) rx_op (v, 3, RXREL_PCREL)
93 1.1 christos
94 1.1 christos #define IMM(v,pos) F (immediate (v, RXREL_SIGNED, pos), pos, 2); \
95 1.1 christos if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
96 1.1 christos #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos), pos, 2)
97 1.1 christos #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos), pos, 2)
98 1.1 christos #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
99 1.1 christos else rx_linkrelax_dsp (pos); \
100 1.1 christos F (displacement (v, msz), pos, 2)
101 1.1 christos
102 1.1 christos #define id24(a,b2,b3) B3 (0xfb+a, b2, b3)
103 1.1 christos
104 1.1 christos static int rx_intop (expressionS, int);
105 1.1 christos static int rx_uintop (expressionS, int);
106 1.1 christos static int rx_disp3op (expressionS);
107 1.1 christos static int rx_disp5op (expressionS *, int);
108 1.1 christos static int rx_disp5op0 (expressionS *, int);
109 1.1 christos static int exp_val (expressionS exp);
110 1.1 christos static expressionS zero_expr (void);
111 1.1 christos static int immediate (expressionS, int, int);
112 1.1 christos static int displacement (expressionS, int);
113 1.1 christos static void rtsd_immediate (expressionS);
114 1.1 christos
115 1.1 christos static int need_flag = 0;
116 1.1 christos static int rx_in_brackets = 0;
117 1.1 christos static int rx_last_token = 0;
118 1.1 christos static char * rx_init_start;
119 1.1 christos static char * rx_last_exp_start = 0;
120 1.1 christos static int sub_op;
121 1.1 christos static int sub_op2;
122 1.1 christos
123 1.1 christos #define YYDEBUG 1
124 1.1 christos #define YYERROR_VERBOSE 1
125 1.1 christos
126 1.1 christos %}
127 1.1 christos
128 1.1 christos %name-prefix="rx_"
129 1.1 christos
130 1.1 christos %union {
131 1.1 christos int regno;
132 1.1 christos expressionS exp;
133 1.1 christos }
134 1.1 christos
135 1.1 christos %type <regno> REG FLAG CREG BCND BMCND SCCND
136 1.1 christos %type <regno> flag bwl bw memex
137 1.1 christos %type <exp> EXPR disp
138 1.1 christos
139 1.1 christos %token REG FLAG CREG
140 1.1 christos
141 1.1 christos %token EXPR UNKNOWN_OPCODE IS_OPCODE
142 1.1 christos
143 1.1 christos %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
144 1.1 christos
145 1.1 christos %token ABS ADC ADD AND_
146 1.1 christos %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST
147 1.1 christos %token CLRPSW CMP
148 1.1 christos %token DBT DIV DIVU
149 1.1 christos %token EDIV EDIVU EMUL EMULU
150 1.1 christos %token FADD FCMP FDIV FMUL FREIT FSUB FTOI
151 1.1 christos %token INT ITOF
152 1.1 christos %token JMP JSR
153 1.1 christos %token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO
154 1.1 christos %token MVFC MVTACHI MVTACLO MVTC MVTIPL
155 1.1 christos %token NEG NOP NOT
156 1.1 christos %token OR
157 1.1 christos %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
158 1.1 christos %token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD
159 1.1 christos %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
160 1.1 christos %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
161 1.1 christos %token TST
162 1.1 christos %token WAIT
163 1.1 christos %token XCHG XOR
164 1.1 christos
165 1.1 christos %%
166 1.1 christos /* ====================================================================== */
167 1.1 christos
168 1.1 christos statement :
169 1.1 christos
170 1.1 christos UNKNOWN_OPCODE
171 1.1 christos { as_bad (_("Unknown opcode: %s"), rx_init_start); }
172 1.1 christos
173 1.1 christos /* ---------------------------------------------------------------------- */
174 1.1 christos
175 1.1 christos | BRK
176 1.1 christos { B1 (0x00); }
177 1.1 christos
178 1.1 christos | DBT
179 1.1 christos { B1 (0x01); }
180 1.1 christos
181 1.1 christos | RTS
182 1.1 christos { B1 (0x02); }
183 1.1 christos
184 1.1 christos | NOP
185 1.1 christos { B1 (0x03); }
186 1.1 christos
187 1.1 christos /* ---------------------------------------------------------------------- */
188 1.1 christos
189 1.1 christos | BRA EXPR
190 1.1 christos { if (rx_disp3op ($2))
191 1.1 christos { B1 (0x08); rx_disp3 ($2, 5); }
192 1.1 christos else if (rx_intop ($2, 8))
193 1.1 christos { B1 (0x2e); PC1 ($2); }
194 1.1 christos else if (rx_intop ($2, 16))
195 1.1 christos { B1 (0x38); PC2 ($2); }
196 1.1 christos else if (rx_intop ($2, 24))
197 1.1 christos { B1 (0x04); PC3 ($2); }
198 1.1 christos else
199 1.1 christos { rx_relax (RX_RELAX_BRANCH, 0);
200 1.1 christos rx_linkrelax_branch ();
201 1.1 christos /* We'll convert this to a longer one later if needed. */
202 1.1 christos B1 (0x08); rx_disp3 ($2, 5); } }
203 1.1 christos
204 1.1 christos | BRA DOT_A EXPR
205 1.1 christos { B1 (0x04); PC3 ($3); }
206 1.1 christos
207 1.1 christos | BRA DOT_S EXPR
208 1.1 christos { B1 (0x08); rx_disp3 ($3, 5); }
209 1.1 christos
210 1.1 christos /* ---------------------------------------------------------------------- */
211 1.1 christos
212 1.1 christos | BSR EXPR
213 1.1 christos { if (rx_intop ($2, 16))
214 1.1 christos { B1 (0x39); PC2 ($2); }
215 1.1 christos else if (rx_intop ($2, 24))
216 1.1 christos { B1 (0x05); PC3 ($2); }
217 1.1 christos else
218 1.1 christos { rx_relax (RX_RELAX_BRANCH, 0);
219 1.1 christos rx_linkrelax_branch ();
220 1.1 christos B1 (0x39); PC2 ($2); } }
221 1.1 christos | BSR DOT_A EXPR
222 1.1 christos { B1 (0x05), PC3 ($3); }
223 1.1 christos
224 1.1 christos /* ---------------------------------------------------------------------- */
225 1.1 christos
226 1.1 christos | BCND DOT_S EXPR
227 1.1 christos { if ($1 == COND_EQ || $1 == COND_NE)
228 1.1 christos { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
229 1.1 christos else
230 1.1 christos as_bad (_("Only BEQ and BNE may have .S")); }
231 1.1 christos
232 1.1 christos /* ---------------------------------------------------------------------- */
233 1.1 christos
234 1.1 christos | BCND DOT_B EXPR
235 1.1 christos { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
236 1.1 christos
237 1.1 christos | BRA DOT_B EXPR
238 1.1 christos { B1 (0x2e), PC1 ($3); }
239 1.1 christos
240 1.1 christos /* ---------------------------------------------------------------------- */
241 1.1 christos
242 1.1 christos | BRA DOT_W EXPR
243 1.1 christos { B1 (0x38), PC2 ($3); }
244 1.1 christos | BSR DOT_W EXPR
245 1.1 christos { B1 (0x39), PC2 ($3); }
246 1.1 christos | BCND DOT_W EXPR
247 1.1 christos { if ($1 == COND_EQ || $1 == COND_NE)
248 1.1 christos { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
249 1.1 christos else
250 1.1 christos as_bad (_("Only BEQ and BNE may have .W")); }
251 1.1 christos | BCND EXPR
252 1.1 christos { if ($1 == COND_EQ || $1 == COND_NE)
253 1.1 christos {
254 1.1 christos rx_relax (RX_RELAX_BRANCH, 0);
255 1.1 christos rx_linkrelax_branch ();
256 1.1 christos B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
257 1.1 christos }
258 1.1 christos else
259 1.1 christos {
260 1.1 christos rx_relax (RX_RELAX_BRANCH, 0);
261 1.1 christos /* This is because we might turn it into a
262 1.1 christos jump-over-jump long branch. */
263 1.1 christos rx_linkrelax_branch ();
264 1.1 christos B1 (0x20); F ($1, 4, 4); PC1 ($2);
265 1.1 christos } }
266 1.1 christos
267 1.1 christos /* ---------------------------------------------------------------------- */
268 1.1 christos
269 1.1 christos | MOV DOT_B '#' EXPR ',' disp '[' REG ']'
270 1.1 christos /* rx_disp5op changes the value if it succeeds, so keep it last. */
271 1.1 christos { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
272 1.1 christos { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
273 1.1 christos else
274 1.1 christos { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
275 1.1 christos if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
276 1.1 christos
277 1.1 christos | MOV DOT_W '#' EXPR ',' disp '[' REG ']'
278 1.1 christos { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
279 1.1 christos { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
280 1.1 christos else
281 1.1 christos { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMM ($4, 12); } }
282 1.1 christos
283 1.1 christos | MOV DOT_L '#' EXPR ',' disp '[' REG ']'
284 1.1 christos { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
285 1.1 christos { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
286 1.1 christos else
287 1.1 christos { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
288 1.1 christos
289 1.1 christos /* ---------------------------------------------------------------------- */
290 1.1 christos
291 1.1 christos | RTSD '#' EXPR ',' REG '-' REG
292 1.1 christos { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
293 1.1 christos if ($5 == 0)
294 1.1 christos rx_error (_("RTSD cannot pop R0"));
295 1.1 christos if ($5 > $7)
296 1.1 christos rx_error (_("RTSD first reg must be <= second reg")); }
297 1.1 christos
298 1.1 christos /* ---------------------------------------------------------------------- */
299 1.1 christos
300 1.1 christos | CMP REG ',' REG
301 1.1 christos { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
302 1.1 christos
303 1.1 christos /* ---------------------------------------------------------------------- */
304 1.1 christos
305 1.1 christos | CMP disp '[' REG ']' DOT_UB ',' REG
306 1.1 christos { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
307 1.1 christos
308 1.1 christos | CMP disp '[' REG ']' memex ',' REG
309 1.1 christos { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
310 1.1 christos
311 1.1 christos /* ---------------------------------------------------------------------- */
312 1.1 christos
313 1.1 christos | MOVU bw REG ',' REG
314 1.1 christos { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
315 1.1 christos
316 1.1 christos /* ---------------------------------------------------------------------- */
317 1.1 christos
318 1.1 christos | MOVU bw '[' REG ']' ',' REG
319 1.1 christos { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
320 1.1 christos
321 1.1 christos | MOVU bw EXPR '[' REG ']' ',' REG
322 1.1 christos { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
323 1.1 christos { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
324 1.1 christos else
325 1.1 christos { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
326 1.1 christos
327 1.1 christos /* ---------------------------------------------------------------------- */
328 1.1 christos
329 1.1 christos | SUB '#' EXPR ',' REG
330 1.1 christos { if (rx_uintop ($3, 4))
331 1.1 christos { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
332 1.1 christos else
333 1.1 christos /* This is really an add, but we negate the immediate. */
334 1.1 christos { B2 (0x38, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } } /* ? */
335 1.1 christos
336 1.1 christos | CMP '#' EXPR ',' REG
337 1.1 christos { if (rx_uintop ($3, 4))
338 1.1 christos { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
339 1.1 christos else if (rx_uintop ($3, 8))
340 1.1 christos { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
341 1.1 christos else
342 1.1 christos { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
343 1.1 christos
344 1.1 christos | ADD '#' EXPR ',' REG
345 1.1 christos { if (rx_uintop ($3, 4))
346 1.1 christos { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
347 1.1 christos else
348 1.1 christos { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
349 1.1 christos
350 1.1 christos | MUL '#' EXPR ',' REG
351 1.1 christos { if (rx_uintop ($3, 4))
352 1.1 christos { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
353 1.1 christos else
354 1.1 christos { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
355 1.1 christos
356 1.1 christos | AND_ '#' EXPR ',' REG
357 1.1 christos { if (rx_uintop ($3, 4))
358 1.1 christos { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
359 1.1 christos else
360 1.1 christos { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
361 1.1 christos
362 1.1 christos | OR '#' EXPR ',' REG
363 1.1 christos { if (rx_uintop ($3, 4))
364 1.1 christos { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
365 1.1 christos else
366 1.1 christos { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
367 1.1 christos
368 1.1 christos | MOV DOT_L '#' EXPR ',' REG
369 1.1 christos { if (rx_uintop ($4, 4))
370 1.1 christos { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
371 1.1 christos else if (rx_uintop ($4, 8))
372 1.1 christos { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
373 1.1 christos else
374 1.1 christos { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
375 1.1 christos
376 1.1 christos | MOV '#' EXPR ',' REG
377 1.1 christos { if (rx_uintop ($3, 4))
378 1.1 christos { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
379 1.1 christos else if (rx_uintop ($3, 8))
380 1.1 christos { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
381 1.1 christos else
382 1.1 christos { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
383 1.1 christos
384 1.1 christos /* ---------------------------------------------------------------------- */
385 1.1 christos
386 1.1 christos | RTSD '#' EXPR
387 1.1 christos { B1 (0x67); rtsd_immediate ($3); }
388 1.1 christos
389 1.1 christos /* ---------------------------------------------------------------------- */
390 1.1 christos
391 1.1 christos | SHLR { sub_op = 0; } op_shift
392 1.1 christos | SHAR { sub_op = 1; } op_shift
393 1.1 christos | SHLL { sub_op = 2; } op_shift
394 1.1 christos
395 1.1 christos /* ---------------------------------------------------------------------- */
396 1.1 christos
397 1.1 christos | PUSHM REG '-' REG
398 1.1 christos {
399 1.1 christos if ($2 == $4)
400 1.1 christos { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
401 1.1 christos else
402 1.1 christos { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
403 1.1 christos if ($2 == 0)
404 1.1 christos rx_error (_("PUSHM cannot push R0"));
405 1.1 christos if ($2 > $4)
406 1.1 christos rx_error (_("PUSHM first reg must be <= second reg")); }
407 1.1 christos
408 1.1 christos /* ---------------------------------------------------------------------- */
409 1.1 christos
410 1.1 christos | POPM REG '-' REG
411 1.1 christos {
412 1.1 christos if ($2 == $4)
413 1.1 christos { B2 (0x7e, 0xb0); F ($2, 12, 4); }
414 1.1 christos else
415 1.1 christos { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
416 1.1 christos if ($2 == 0)
417 1.1 christos rx_error (_("POPM cannot pop R0"));
418 1.1 christos if ($2 > $4)
419 1.1 christos rx_error (_("POPM first reg must be <= second reg")); }
420 1.1 christos
421 1.1 christos /* ---------------------------------------------------------------------- */
422 1.1 christos
423 1.1 christos | ADD '#' EXPR ',' REG ',' REG
424 1.1 christos { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
425 1.1 christos
426 1.1 christos /* ---------------------------------------------------------------------- */
427 1.1 christos
428 1.1 christos | INT '#' EXPR
429 1.1 christos { B2(0x75, 0x60), UO1 ($3); }
430 1.1 christos
431 1.1 christos /* ---------------------------------------------------------------------- */
432 1.1 christos
433 1.1 christos | BSET '#' EXPR ',' REG
434 1.1 christos { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
435 1.1 christos | BCLR '#' EXPR ',' REG
436 1.1 christos { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
437 1.1 christos
438 1.1 christos /* ---------------------------------------------------------------------- */
439 1.1 christos
440 1.1 christos | BTST '#' EXPR ',' REG
441 1.1 christos { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
442 1.1 christos
443 1.1 christos /* ---------------------------------------------------------------------- */
444 1.1 christos
445 1.1 christos | SAT REG
446 1.1 christos { B2 (0x7e, 0x30); F ($2, 12, 4); }
447 1.1 christos | RORC REG
448 1.1 christos { B2 (0x7e, 0x40); F ($2, 12, 4); }
449 1.1 christos | ROLC REG
450 1.1 christos { B2 (0x7e, 0x50); F ($2, 12, 4); }
451 1.1 christos
452 1.1 christos /* ---------------------------------------------------------------------- */
453 1.1 christos
454 1.1 christos | PUSH bwl REG
455 1.1 christos { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
456 1.1 christos
457 1.1 christos /* ---------------------------------------------------------------------- */
458 1.1 christos
459 1.1 christos | POP REG
460 1.1 christos { B2 (0x7e, 0xb0); F ($2, 12, 4); }
461 1.1 christos
462 1.1 christos /* ---------------------------------------------------------------------- */
463 1.1 christos
464 1.1 christos | PUSHC CREG
465 1.1 christos { if ($2 < 16)
466 1.1 christos { B2 (0x7e, 0xc0); F ($2, 12, 4); }
467 1.1 christos else
468 1.1 christos as_bad (_("PUSHC can only push the first 16 control registers")); }
469 1.1 christos
470 1.1 christos /* ---------------------------------------------------------------------- */
471 1.1 christos
472 1.1 christos | POPC CREG
473 1.1 christos { if ($2 < 16)
474 1.1 christos { B2 (0x7e, 0xe0); F ($2, 12, 4); }
475 1.1 christos else
476 1.1 christos as_bad (_("POPC can only pop the first 16 control registers")); }
477 1.1 christos
478 1.1 christos /* ---------------------------------------------------------------------- */
479 1.1 christos
480 1.1 christos | SETPSW flag
481 1.1 christos { B2 (0x7f, 0xa0); F ($2, 12, 4); }
482 1.1 christos | CLRPSW flag
483 1.1 christos { B2 (0x7f, 0xb0); F ($2, 12, 4); }
484 1.1 christos
485 1.1 christos /* ---------------------------------------------------------------------- */
486 1.1 christos
487 1.1 christos | JMP REG
488 1.1 christos { B2 (0x7f, 0x00); F ($2, 12, 4); }
489 1.1 christos | JSR REG
490 1.1 christos { B2 (0x7f, 0x10); F ($2, 12, 4); }
491 1.1 christos | BRA opt_l REG
492 1.1 christos { B2 (0x7f, 0x40); F ($3, 12, 4); }
493 1.1 christos | BSR opt_l REG
494 1.1 christos { B2 (0x7f, 0x50); F ($3, 12, 4); }
495 1.1 christos
496 1.1 christos /* ---------------------------------------------------------------------- */
497 1.1 christos
498 1.1 christos | SCMPU
499 1.1 christos { B2 (0x7f, 0x83); }
500 1.1 christos | SMOVU
501 1.1 christos { B2 (0x7f, 0x87); }
502 1.1 christos | SMOVB
503 1.1 christos { B2 (0x7f, 0x8b); }
504 1.1 christos | SMOVF
505 1.1 christos { B2 (0x7f, 0x8f); }
506 1.1 christos
507 1.1 christos /* ---------------------------------------------------------------------- */
508 1.1 christos
509 1.1 christos | SUNTIL bwl
510 1.1 christos { B2 (0x7f, 0x80); F ($2, 14, 2); }
511 1.1 christos | SWHILE bwl
512 1.1 christos { B2 (0x7f, 0x84); F ($2, 14, 2); }
513 1.1 christos | SSTR bwl
514 1.1 christos { B2 (0x7f, 0x88); F ($2, 14, 2); }
515 1.1 christos
516 1.1 christos /* ---------------------------------------------------------------------- */
517 1.1 christos
518 1.1 christos | RMPA bwl
519 1.1 christos { B2 (0x7f, 0x8c); F ($2, 14, 2); }
520 1.1 christos
521 1.1 christos /* ---------------------------------------------------------------------- */
522 1.1 christos
523 1.1 christos | RTFI
524 1.1 christos { B2 (0x7f, 0x94); }
525 1.1 christos | RTE
526 1.1 christos { B2 (0x7f, 0x95); }
527 1.1 christos | WAIT
528 1.1 christos { B2 (0x7f, 0x96); }
529 1.1 christos | SATR
530 1.1 christos { B2 (0x7f, 0x93); }
531 1.1 christos
532 1.1 christos /* ---------------------------------------------------------------------- */
533 1.1 christos
534 1.1 christos | MVTIPL '#' EXPR
535 1.1 christos { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
536 1.1 christos
537 1.1 christos /* ---------------------------------------------------------------------- */
538 1.1 christos
539 1.1 christos /* rx_disp5op changes the value if it succeeds, so keep it last. */
540 1.1 christos | MOV bwl REG ',' EXPR '[' REG ']'
541 1.1 christos { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
542 1.1 christos { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
543 1.1 christos else
544 1.1 christos { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
545 1.1 christos
546 1.1 christos /* ---------------------------------------------------------------------- */
547 1.1 christos
548 1.1 christos | MOV bwl EXPR '[' REG ']' ',' REG
549 1.1 christos { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
550 1.1 christos { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
551 1.1 christos else
552 1.1 christos { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
553 1.1 christos
554 1.1 christos /* ---------------------------------------------------------------------- */
555 1.1 christos
556 1.1 christos /* MOV a,b - if a is a reg and b is mem, src and dest are
557 1.1 christos swapped. */
558 1.1 christos
559 1.1 christos /* We don't use "disp" here because it causes a shift/reduce
560 1.1 christos conflict with the other displacement-less patterns. */
561 1.1 christos
562 1.1 christos | MOV bwl REG ',' '[' REG ']'
563 1.1 christos { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
564 1.1 christos
565 1.1 christos /* ---------------------------------------------------------------------- */
566 1.1 christos
567 1.1 christos | MOV bwl '[' REG ']' ',' disp '[' REG ']'
568 1.1 christos { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
569 1.1 christos
570 1.1 christos /* ---------------------------------------------------------------------- */
571 1.1 christos
572 1.1 christos | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
573 1.1 christos { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
574 1.1 christos
575 1.1 christos /* ---------------------------------------------------------------------- */
576 1.1 christos
577 1.1 christos | MOV bwl REG ',' REG
578 1.1 christos { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
579 1.1 christos
580 1.1 christos /* ---------------------------------------------------------------------- */
581 1.1 christos
582 1.1 christos | MOV bwl '[' REG ']' ',' REG
583 1.1 christos { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
584 1.1 christos
585 1.1 christos /* ---------------------------------------------------------------------- */
586 1.1 christos
587 1.1 christos | BSET '#' EXPR ',' disp '[' REG ']' DOT_B
588 1.1 christos { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
589 1.1 christos | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
590 1.1 christos { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
591 1.1 christos | BTST '#' EXPR ',' disp '[' REG ']' DOT_B
592 1.1 christos { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
593 1.1 christos
594 1.1 christos /* ---------------------------------------------------------------------- */
595 1.1 christos
596 1.1 christos | PUSH bwl disp '[' REG ']'
597 1.1 christos { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
598 1.1 christos
599 1.1 christos /* ---------------------------------------------------------------------- */
600 1.1 christos
601 1.1 christos | SBB { sub_op = 0; } op_dp20_rm
602 1.1 christos | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rms
603 1.1 christos | ADC { sub_op = 2; } op_dp20_rim
604 1.1 christos | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rms
605 1.1 christos | MAX { sub_op = 4; } op_dp20_rim
606 1.1 christos | MIN { sub_op = 5; } op_dp20_rim
607 1.1 christos | EMUL { sub_op = 6; } op_dp20_i
608 1.1 christos | EMULU { sub_op = 7; } op_dp20_i
609 1.1 christos | DIV { sub_op = 8; } op_dp20_rim
610 1.1 christos | DIVU { sub_op = 9; } op_dp20_rim
611 1.1 christos | TST { sub_op = 12; } op_dp20_rim
612 1.1 christos | XOR { sub_op = 13; } op_dp20_rim
613 1.1 christos | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rms
614 1.1 christos | STZ { sub_op = 14; } op_dp20_i
615 1.1 christos | STNZ { sub_op = 15; } op_dp20_i
616 1.1 christos
617 1.1 christos /* ---------------------------------------------------------------------- */
618 1.1 christos
619 1.1 christos | EMUL { sub_op = 6; } op_xchg
620 1.1 christos | EMULU { sub_op = 7; } op_xchg
621 1.1 christos | XCHG { sub_op = 16; } op_xchg
622 1.1 christos | ITOF { sub_op = 17; } op_xchg
623 1.1 christos
624 1.1 christos /* ---------------------------------------------------------------------- */
625 1.1 christos
626 1.1 christos | BSET REG ',' REG
627 1.1 christos { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
628 1.1 christos | BCLR REG ',' REG
629 1.1 christos { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
630 1.1 christos | BTST REG ',' REG
631 1.1 christos { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
632 1.1 christos | BNOT REG ',' REG
633 1.1 christos { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
634 1.1 christos
635 1.1 christos | BSET REG ',' disp '[' REG ']' DOT_B
636 1.1 christos { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
637 1.1 christos | BCLR REG ',' disp '[' REG ']' DOT_B
638 1.1 christos { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
639 1.1 christos | BTST REG ',' disp '[' REG ']' DOT_B
640 1.1 christos { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
641 1.1 christos | BNOT REG ',' disp '[' REG ']' DOT_B
642 1.1 christos { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
643 1.1 christos
644 1.1 christos /* ---------------------------------------------------------------------- */
645 1.1 christos
646 1.1 christos | FSUB { sub_op = 0; } float2_op
647 1.1 christos | FCMP { sub_op = 1; } float2_op
648 1.1 christos | FADD { sub_op = 2; } float2_op
649 1.1 christos | FMUL { sub_op = 3; } float2_op
650 1.1 christos | FDIV { sub_op = 4; } float2_op
651 1.1 christos | FTOI { sub_op = 5; } float2_op_ni
652 1.1 christos | ROUND { sub_op = 6; } float2_op_ni
653 1.1 christos
654 1.1 christos /* ---------------------------------------------------------------------- */
655 1.1 christos
656 1.1 christos | SCCND DOT_L REG
657 1.1 christos { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
658 1.1 christos | SCCND bwl disp '[' REG ']'
659 1.1 christos { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
660 1.1 christos
661 1.1 christos /* ---------------------------------------------------------------------- */
662 1.1 christos
663 1.1 christos | BMCND '#' EXPR ',' disp '[' REG ']' DOT_B
664 1.1 christos { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
665 1.1 christos F ($7, 16, 4); DSP ($5, 14, BSIZE); }
666 1.1 christos
667 1.1 christos /* ---------------------------------------------------------------------- */
668 1.1 christos
669 1.1 christos | BNOT '#' EXPR ',' disp '[' REG ']' DOT_B
670 1.1 christos { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
671 1.1 christos DSP ($5, 14, BSIZE); }
672 1.1 christos
673 1.1 christos /* ---------------------------------------------------------------------- */
674 1.1 christos
675 1.1 christos | MULHI REG ',' REG
676 1.1 christos { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
677 1.1 christos | MULLO REG ',' REG
678 1.1 christos { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
679 1.1 christos | MACHI REG ',' REG
680 1.1 christos { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
681 1.1 christos | MACLO REG ',' REG
682 1.1 christos { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
683 1.1 christos
684 1.1 christos /* ---------------------------------------------------------------------- */
685 1.1 christos
686 1.1 christos /* We don't have syntax for these yet. */
687 1.1 christos | MVTACHI REG
688 1.1 christos { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
689 1.1 christos | MVTACLO REG
690 1.1 christos { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
691 1.1 christos | MVFACHI REG
692 1.1 christos { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
693 1.1 christos | MVFACMI REG
694 1.1 christos { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
695 1.1 christos | MVFACLO REG
696 1.1 christos { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
697 1.1 christos
698 1.1 christos | RACW '#' EXPR
699 1.1 christos { id24 (2, 0x18, 0x00);
700 1.1 christos if (rx_uintop ($3, 4) && $3.X_add_number == 1)
701 1.1 christos ;
702 1.1 christos else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
703 1.1 christos F (1, 19, 1);
704 1.1 christos else
705 1.1 christos as_bad (_("RACW expects #1 or #2"));}
706 1.1 christos
707 1.1 christos /* ---------------------------------------------------------------------- */
708 1.1 christos
709 1.1 christos | MOV bwl REG ',' '[' REG '+' ']'
710 1.1 christos { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
711 1.1 christos | MOV bwl REG ',' '[' '-' REG ']'
712 1.1 christos { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
713 1.1 christos
714 1.1 christos /* ---------------------------------------------------------------------- */
715 1.1 christos
716 1.1 christos | MOV bwl '[' REG '+' ']' ',' REG
717 1.1 christos { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
718 1.1 christos | MOV bwl '[' '-' REG ']' ',' REG
719 1.1 christos { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
720 1.1 christos
721 1.1 christos /* ---------------------------------------------------------------------- */
722 1.1 christos
723 1.1 christos | MOVU bw '[' REG '+' ']' ',' REG
724 1.1 christos { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
725 1.1 christos | MOVU bw '[' '-' REG ']' ',' REG
726 1.1 christos { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
727 1.1 christos
728 1.1 christos /* ---------------------------------------------------------------------- */
729 1.1 christos
730 1.1 christos | ROTL { sub_op = 6; } op_shift_rot
731 1.1 christos | ROTR { sub_op = 4; } op_shift_rot
732 1.1 christos | REVW { sub_op = 5; } op_shift_rot
733 1.1 christos | REVL { sub_op = 7; } op_shift_rot
734 1.1 christos
735 1.1 christos /* ---------------------------------------------------------------------- */
736 1.1 christos
737 1.1 christos | MVTC REG ',' CREG
738 1.1 christos { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
739 1.1 christos F ($2, 16, 4); }
740 1.1 christos
741 1.1 christos /* ---------------------------------------------------------------------- */
742 1.1 christos
743 1.1 christos | MVFC CREG ',' REG
744 1.1 christos { id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
745 1.1 christos
746 1.1 christos /* ---------------------------------------------------------------------- */
747 1.1 christos
748 1.1 christos | ROTL '#' EXPR ',' REG
749 1.1 christos { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
750 1.1 christos | ROTR '#' EXPR ',' REG
751 1.1 christos { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
752 1.1 christos
753 1.1 christos /* ---------------------------------------------------------------------- */
754 1.1 christos
755 1.1 christos | MVTC '#' EXPR ',' CREG
756 1.1 christos { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
757 1.1 christos
758 1.1 christos /* ---------------------------------------------------------------------- */
759 1.1 christos
760 1.1 christos | BMCND '#' EXPR ',' REG
761 1.1 christos { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
762 1.1 christos F ($5, 20, 4); }
763 1.1 christos
764 1.1 christos /* ---------------------------------------------------------------------- */
765 1.1 christos
766 1.1 christos | BNOT '#' EXPR ',' REG
767 1.1 christos { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
768 1.1 christos
769 1.1 christos /* ---------------------------------------------------------------------- */
770 1.1 christos
771 1.1 christos | MOV bwl REG ',' '[' REG ',' REG ']'
772 1.1 christos { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
773 1.1 christos
774 1.1 christos | MOV bwl '[' REG ',' REG ']' ',' REG
775 1.1 christos { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
776 1.1 christos
777 1.1 christos | MOVU bw '[' REG ',' REG ']' ',' REG
778 1.1 christos { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
779 1.1 christos
780 1.1 christos /* ---------------------------------------------------------------------- */
781 1.1 christos
782 1.1 christos | SUB { sub_op = 0; } op_subadd
783 1.1 christos | ADD { sub_op = 2; } op_subadd
784 1.1 christos | MUL { sub_op = 3; } op_subadd
785 1.1 christos | AND_ { sub_op = 4; } op_subadd
786 1.1 christos | OR { sub_op = 5; } op_subadd
787 1.1 christos
788 1.1 christos /* ---------------------------------------------------------------------- */
789 1.1 christos /* There is no SBB #imm so we fake it with ADC. */
790 1.1 christos
791 1.1 christos | SBB '#' EXPR ',' REG
792 1.1 christos { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
793 1.1 christos
794 1.1 christos /* ---------------------------------------------------------------------- */
795 1.1 christos
796 1.1 christos ;
797 1.1 christos
798 1.1 christos /* ====================================================================== */
799 1.1 christos
800 1.1 christos op_subadd
801 1.1 christos : REG ',' REG
802 1.1 christos { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
803 1.1 christos | disp '[' REG ']' DOT_UB ',' REG
804 1.1 christos { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
805 1.1 christos | disp '[' REG ']' memex ',' REG
806 1.1 christos { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
807 1.1 christos | REG ',' REG ',' REG
808 1.1 christos { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
809 1.1 christos ;
810 1.1 christos
811 1.1 christos /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
812 1.1 christos
813 1.1 christos op_dp20_rm
814 1.1 christos : REG ',' REG
815 1.1 christos { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
816 1.1 christos | disp '[' REG ']' DOT_UB ',' REG
817 1.1 christos { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
818 1.1 christos | disp '[' REG ']' memex ',' REG
819 1.1 christos { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
820 1.1 christos F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
821 1.1 christos ;
822 1.1 christos
823 1.1 christos op_dp20_i
824 1.1 christos : '#' EXPR ',' REG
825 1.1 christos { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
826 1.1 christos ;
827 1.1 christos
828 1.1 christos op_dp20_rim
829 1.1 christos : op_dp20_rm
830 1.1 christos | op_dp20_i
831 1.1 christos ;
832 1.1 christos
833 1.1 christos op_dp20_rms
834 1.1 christos : op_dp20_rm
835 1.1 christos | REG
836 1.1 christos { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
837 1.1 christos ;
838 1.1 christos
839 1.1 christos /* xchg, itof, emul, emulu */
840 1.1 christos op_xchg
841 1.1 christos : REG ',' REG
842 1.1 christos { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
843 1.1 christos | disp '[' REG ']' DOT_UB ',' REG
844 1.1 christos { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
845 1.1 christos | disp '[' REG ']' memex ',' REG
846 1.1 christos { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
847 1.1 christos DSP ($1, 14, sizemap[$5]); }
848 1.1 christos ;
849 1.1 christos
850 1.1 christos /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
851 1.1 christos op_shift_rot
852 1.1 christos : REG ',' REG
853 1.1 christos { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
854 1.1 christos ;
855 1.1 christos op_shift
856 1.1 christos : '#' EXPR ',' REG
857 1.1 christos { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
858 1.1 christos | '#' EXPR ',' REG ',' REG
859 1.1 christos { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
860 1.1 christos | op_shift_rot
861 1.1 christos ;
862 1.1 christos
863 1.1 christos
864 1.1 christos
865 1.1 christos float2_op
866 1.1 christos : '#' EXPR ',' REG
867 1.1 christos { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
868 1.1 christos | float2_op_ni
869 1.1 christos ;
870 1.1 christos float2_op_ni
871 1.1 christos : REG ',' REG
872 1.1 christos { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
873 1.1 christos | disp '[' REG ']' opt_l ',' REG
874 1.1 christos { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
875 1.1 christos ;
876 1.1 christos
877 1.1 christos /* ====================================================================== */
878 1.1 christos
879 1.1 christos disp : { $$ = zero_expr (); }
880 1.1 christos | EXPR { $$ = $1; }
881 1.1 christos ;
882 1.1 christos
883 1.1 christos flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
884 1.1 christos ;
885 1.1 christos
886 1.1 christos /* DOT_UB is not listed here, it's handled with a separate pattern. */
887 1.1 christos /* Use sizemap[$n] to get LSIZE etc. */
888 1.1 christos memex : DOT_B { $$ = 0; }
889 1.1 christos | DOT_W { $$ = 1; }
890 1.1 christos | { $$ = 2; }
891 1.1 christos | DOT_L { $$ = 2; }
892 1.1 christos | DOT_UW { $$ = 3; }
893 1.1 christos ;
894 1.1 christos
895 1.1 christos bwl : { $$ = LSIZE; }
896 1.1 christos | DOT_B { $$ = BSIZE; }
897 1.1 christos | DOT_W { $$ = WSIZE; }
898 1.1 christos | DOT_L { $$ = LSIZE; }
899 1.1 christos ;
900 1.1 christos
901 1.1 christos bw : { $$ = 1; }
902 1.1 christos | DOT_B { $$ = 0; }
903 1.1 christos | DOT_W { $$ = 1; }
904 1.1 christos ;
905 1.1 christos
906 1.1 christos opt_l : {}
907 1.1 christos | DOT_L {}
908 1.1 christos ;
909 1.1 christos
910 1.1 christos %%
911 1.1 christos /* ====================================================================== */
912 1.1 christos
913 1.1 christos static struct
914 1.1 christos {
915 1.1 christos const char * string;
916 1.1 christos int token;
917 1.1 christos int val;
918 1.1 christos }
919 1.1 christos token_table[] =
920 1.1 christos {
921 1.1 christos { "r0", REG, 0 },
922 1.1 christos { "r1", REG, 1 },
923 1.1 christos { "r2", REG, 2 },
924 1.1 christos { "r3", REG, 3 },
925 1.1 christos { "r4", REG, 4 },
926 1.1 christos { "r5", REG, 5 },
927 1.1 christos { "r6", REG, 6 },
928 1.1 christos { "r7", REG, 7 },
929 1.1 christos { "r8", REG, 8 },
930 1.1 christos { "r9", REG, 9 },
931 1.1 christos { "r10", REG, 10 },
932 1.1 christos { "r11", REG, 11 },
933 1.1 christos { "r12", REG, 12 },
934 1.1 christos { "r13", REG, 13 },
935 1.1 christos { "r14", REG, 14 },
936 1.1 christos { "r15", REG, 15 },
937 1.1 christos
938 1.1 christos { "psw", CREG, 0 },
939 1.1 christos { "pc", CREG, 1 },
940 1.1 christos { "usp", CREG, 2 },
941 1.1 christos { "fpsw", CREG, 3 },
942 1.1 christos /* reserved */
943 1.1 christos /* reserved */
944 1.1 christos /* reserved */
945 1.1 christos { "wr", CREG, 7 },
946 1.1 christos
947 1.1 christos { "bpsw", CREG, 8 },
948 1.1 christos { "bpc", CREG, 9 },
949 1.1 christos { "isp", CREG, 10 },
950 1.1 christos { "fintv", CREG, 11 },
951 1.1 christos { "intb", CREG, 12 },
952 1.1 christos
953 1.1 christos { "pbp", CREG, 16 },
954 1.1 christos { "pben", CREG, 17 },
955 1.1 christos
956 1.1 christos { "bbpsw", CREG, 24 },
957 1.1 christos { "bbpc", CREG, 25 },
958 1.1 christos
959 1.1 christos { ".s", DOT_S, 0 },
960 1.1 christos { ".b", DOT_B, 0 },
961 1.1 christos { ".w", DOT_W, 0 },
962 1.1 christos { ".l", DOT_L, 0 },
963 1.1 christos { ".a", DOT_A , 0},
964 1.1 christos { ".ub", DOT_UB, 0 },
965 1.1 christos { ".uw", DOT_UW , 0},
966 1.1 christos
967 1.1 christos { "c", FLAG, 0 },
968 1.1 christos { "z", FLAG, 1 },
969 1.1 christos { "s", FLAG, 2 },
970 1.1 christos { "o", FLAG, 3 },
971 1.1 christos { "i", FLAG, 8 },
972 1.1 christos { "u", FLAG, 9 },
973 1.1 christos
974 1.1 christos #define OPC(x) { #x, x, IS_OPCODE }
975 1.1 christos OPC(ABS),
976 1.1 christos OPC(ADC),
977 1.1 christos OPC(ADD),
978 1.1 christos { "and", AND_, IS_OPCODE },
979 1.1 christos OPC(BCLR),
980 1.1 christos OPC(BCND),
981 1.1 christos OPC(BMCND),
982 1.1 christos OPC(BNOT),
983 1.1 christos OPC(BRA),
984 1.1 christos OPC(BRK),
985 1.1 christos OPC(BSET),
986 1.1 christos OPC(BSR),
987 1.1 christos OPC(BTST),
988 1.1 christos OPC(CLRPSW),
989 1.1 christos OPC(CMP),
990 1.1 christos OPC(DBT),
991 1.1 christos OPC(DIV),
992 1.1 christos OPC(DIVU),
993 1.1 christos OPC(EDIV),
994 1.1 christos OPC(EDIVU),
995 1.1 christos OPC(EMUL),
996 1.1 christos OPC(EMULU),
997 1.1 christos OPC(FADD),
998 1.1 christos OPC(FCMP),
999 1.1 christos OPC(FDIV),
1000 1.1 christos OPC(FMUL),
1001 1.1 christos OPC(FREIT),
1002 1.1 christos OPC(FSUB),
1003 1.1 christos OPC(FTOI),
1004 1.1 christos OPC(INT),
1005 1.1 christos OPC(ITOF),
1006 1.1 christos OPC(JMP),
1007 1.1 christos OPC(JSR),
1008 1.1 christos OPC(MVFACHI),
1009 1.1 christos OPC(MVFACMI),
1010 1.1 christos OPC(MVFACLO),
1011 1.1 christos OPC(MVFC),
1012 1.1 christos OPC(MVTACHI),
1013 1.1 christos OPC(MVTACLO),
1014 1.1 christos OPC(MVTC),
1015 1.1 christos OPC(MVTIPL),
1016 1.1 christos OPC(MACHI),
1017 1.1 christos OPC(MACLO),
1018 1.1 christos OPC(MAX),
1019 1.1 christos OPC(MIN),
1020 1.1 christos OPC(MOV),
1021 1.1 christos OPC(MOVU),
1022 1.1 christos OPC(MUL),
1023 1.1 christos OPC(MULHI),
1024 1.1 christos OPC(MULLO),
1025 1.1 christos OPC(MULU),
1026 1.1 christos OPC(NEG),
1027 1.1 christos OPC(NOP),
1028 1.1 christos OPC(NOT),
1029 1.1 christos OPC(OR),
1030 1.1 christos OPC(POP),
1031 1.1 christos OPC(POPC),
1032 1.1 christos OPC(POPM),
1033 1.1 christos OPC(PUSH),
1034 1.1 christos OPC(PUSHA),
1035 1.1 christos OPC(PUSHC),
1036 1.1 christos OPC(PUSHM),
1037 1.1 christos OPC(RACW),
1038 1.1 christos OPC(REIT),
1039 1.1 christos OPC(REVL),
1040 1.1 christos OPC(REVW),
1041 1.1 christos OPC(RMPA),
1042 1.1 christos OPC(ROLC),
1043 1.1 christos OPC(RORC),
1044 1.1 christos OPC(ROTL),
1045 1.1 christos OPC(ROTR),
1046 1.1 christos OPC(ROUND),
1047 1.1 christos OPC(RTE),
1048 1.1 christos OPC(RTFI),
1049 1.1 christos OPC(RTS),
1050 1.1 christos OPC(RTSD),
1051 1.1 christos OPC(SAT),
1052 1.1 christos OPC(SATR),
1053 1.1 christos OPC(SBB),
1054 1.1 christos OPC(SCCND),
1055 1.1 christos OPC(SCMPU),
1056 1.1 christos OPC(SETPSW),
1057 1.1 christos OPC(SHAR),
1058 1.1 christos OPC(SHLL),
1059 1.1 christos OPC(SHLR),
1060 1.1 christos OPC(SMOVB),
1061 1.1 christos OPC(SMOVF),
1062 1.1 christos OPC(SMOVU),
1063 1.1 christos OPC(SSTR),
1064 1.1 christos OPC(STNZ),
1065 1.1 christos OPC(STOP),
1066 1.1 christos OPC(STZ),
1067 1.1 christos OPC(SUB),
1068 1.1 christos OPC(SUNTIL),
1069 1.1 christos OPC(SWHILE),
1070 1.1 christos OPC(TST),
1071 1.1 christos OPC(WAIT),
1072 1.1 christos OPC(XCHG),
1073 1.1 christos OPC(XOR),
1074 1.1 christos };
1075 1.1 christos
1076 1.1 christos #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1077 1.1 christos
1078 1.1 christos static struct
1079 1.1 christos {
1080 1.1 christos char * string;
1081 1.1 christos int token;
1082 1.1 christos }
1083 1.1 christos condition_opcode_table[] =
1084 1.1 christos {
1085 1.1 christos { "b", BCND },
1086 1.1 christos { "bm", BMCND },
1087 1.1 christos { "sc", SCCND },
1088 1.1 christos };
1089 1.1 christos
1090 1.1 christos #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1091 1.1 christos
1092 1.1 christos static struct
1093 1.1 christos {
1094 1.1 christos char * string;
1095 1.1 christos int val;
1096 1.1 christos }
1097 1.1 christos condition_table[] =
1098 1.1 christos {
1099 1.1 christos { "z", 0 },
1100 1.1 christos { "eq", 0 },
1101 1.1 christos { "geu", 2 },
1102 1.1 christos { "c", 2 },
1103 1.1 christos { "gtu", 4 },
1104 1.1 christos { "pz", 6 },
1105 1.1 christos { "ge", 8 },
1106 1.1 christos { "gt", 10 },
1107 1.1 christos { "o", 12},
1108 1.1 christos /* always = 14 */
1109 1.1 christos { "nz", 1 },
1110 1.1 christos { "ne", 1 },
1111 1.1 christos { "ltu", 3 },
1112 1.1 christos { "nc", 3 },
1113 1.1 christos { "leu", 5 },
1114 1.1 christos { "n", 7 },
1115 1.1 christos { "lt", 9 },
1116 1.1 christos { "le", 11 },
1117 1.1 christos { "no", 13 }
1118 1.1 christos /* never = 15 */
1119 1.1 christos };
1120 1.1 christos
1121 1.1 christos #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1122 1.1 christos
1123 1.1 christos void
1124 1.1 christos rx_lex_init (char * beginning, char * ending)
1125 1.1 christos {
1126 1.1 christos rx_init_start = beginning;
1127 1.1 christos rx_lex_start = beginning;
1128 1.1 christos rx_lex_end = ending;
1129 1.1 christos rx_in_brackets = 0;
1130 1.1 christos rx_last_token = 0;
1131 1.1 christos
1132 1.1 christos setbuf (stdout, 0);
1133 1.1 christos }
1134 1.1 christos
1135 1.1 christos static int
1136 1.1 christos check_condition (char * base)
1137 1.1 christos {
1138 1.1 christos char * cp;
1139 1.1 christos unsigned int i;
1140 1.1 christos
1141 1.1 christos if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1142 1.1 christos return 0;
1143 1.1 christos if (memcmp (rx_lex_start, base, strlen (base)))
1144 1.1 christos return 0;
1145 1.1 christos cp = rx_lex_start + strlen (base);
1146 1.1 christos for (i = 0; i < NUM_CONDITIONS; i ++)
1147 1.1 christos {
1148 1.1 christos if (strcasecmp (cp, condition_table[i].string) == 0)
1149 1.1 christos {
1150 1.1 christos rx_lval.regno = condition_table[i].val;
1151 1.1 christos return 1;
1152 1.1 christos }
1153 1.1 christos }
1154 1.1 christos return 0;
1155 1.1 christos }
1156 1.1 christos
1157 1.1 christos static int
1158 1.1 christos rx_lex (void)
1159 1.1 christos {
1160 1.1 christos unsigned int ci;
1161 1.1 christos char * save_input_pointer;
1162 1.1 christos
1163 1.1 christos while (ISSPACE (*rx_lex_start)
1164 1.1 christos && rx_lex_start != rx_lex_end)
1165 1.1 christos rx_lex_start ++;
1166 1.1 christos
1167 1.1 christos rx_last_exp_start = rx_lex_start;
1168 1.1 christos
1169 1.1 christos if (rx_lex_start == rx_lex_end)
1170 1.1 christos return 0;
1171 1.1 christos
1172 1.1 christos if (ISALPHA (*rx_lex_start)
1173 1.1 christos || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1174 1.1 christos {
1175 1.1 christos unsigned int i;
1176 1.1 christos char * e;
1177 1.1 christos char save;
1178 1.1 christos
1179 1.1 christos for (e = rx_lex_start + 1;
1180 1.1 christos e < rx_lex_end && ISALNUM (*e);
1181 1.1 christos e ++)
1182 1.1 christos ;
1183 1.1 christos save = *e;
1184 1.1 christos *e = 0;
1185 1.1 christos
1186 1.1 christos if (rx_last_token == 0)
1187 1.1 christos for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1188 1.1 christos if (check_condition (condition_opcode_table[ci].string))
1189 1.1 christos {
1190 1.1 christos *e = save;
1191 1.1 christos rx_lex_start = e;
1192 1.1 christos rx_last_token = condition_opcode_table[ci].token;
1193 1.1 christos return condition_opcode_table[ci].token;
1194 1.1 christos }
1195 1.1 christos
1196 1.1 christos for (i = 0; i < NUM_TOKENS; i++)
1197 1.1 christos if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1198 1.1 christos && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1199 1.1 christos && !(token_table[i].token == FLAG && !need_flag))
1200 1.1 christos {
1201 1.1 christos rx_lval.regno = token_table[i].val;
1202 1.1 christos *e = save;
1203 1.1 christos rx_lex_start = e;
1204 1.1 christos rx_last_token = token_table[i].token;
1205 1.1 christos return token_table[i].token;
1206 1.1 christos }
1207 1.1 christos *e = save;
1208 1.1 christos }
1209 1.1 christos
1210 1.1 christos if (rx_last_token == 0)
1211 1.1 christos {
1212 1.1 christos rx_last_token = UNKNOWN_OPCODE;
1213 1.1 christos return UNKNOWN_OPCODE;
1214 1.1 christos }
1215 1.1 christos
1216 1.1 christos if (rx_last_token == UNKNOWN_OPCODE)
1217 1.1 christos return 0;
1218 1.1 christos
1219 1.1 christos if (*rx_lex_start == '[')
1220 1.1 christos rx_in_brackets = 1;
1221 1.1 christos if (*rx_lex_start == ']')
1222 1.1 christos rx_in_brackets = 0;
1223 1.1 christos
1224 1.1 christos if (rx_in_brackets
1225 1.1 christos || rx_last_token == REG
1226 1.1 christos || strchr ("[],#", *rx_lex_start))
1227 1.1 christos {
1228 1.1 christos rx_last_token = *rx_lex_start;
1229 1.1 christos return *rx_lex_start ++;
1230 1.1 christos }
1231 1.1 christos
1232 1.1 christos save_input_pointer = input_line_pointer;
1233 1.1 christos input_line_pointer = rx_lex_start;
1234 1.1 christos rx_lval.exp.X_md = 0;
1235 1.1 christos expression (&rx_lval.exp);
1236 1.1 christos
1237 1.1 christos /* We parse but ignore any :<size> modifier on expressions. */
1238 1.1 christos if (*input_line_pointer == ':')
1239 1.1 christos {
1240 1.1 christos char *cp;
1241 1.1 christos
1242 1.1 christos for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1243 1.1 christos if (!ISDIGIT (*cp))
1244 1.1 christos break;
1245 1.1 christos if (cp > input_line_pointer+1)
1246 1.1 christos input_line_pointer = cp;
1247 1.1 christos }
1248 1.1 christos
1249 1.1 christos rx_lex_start = input_line_pointer;
1250 1.1 christos input_line_pointer = save_input_pointer;
1251 1.1 christos rx_last_token = EXPR;
1252 1.1 christos return EXPR;
1253 1.1 christos }
1254 1.1 christos
1255 1.1 christos int
1256 1.1 christos rx_error (char * str)
1257 1.1 christos {
1258 1.1 christos int len;
1259 1.1 christos
1260 1.1 christos len = rx_last_exp_start - rx_init_start;
1261 1.1 christos
1262 1.1 christos as_bad ("%s", rx_init_start);
1263 1.1 christos as_bad ("%*s^ %s", len, "", str);
1264 1.1 christos return 0;
1265 1.1 christos }
1266 1.1 christos
1267 1.1 christos static int
1268 1.1 christos rx_intop (expressionS exp, int nbits)
1269 1.1 christos {
1270 1.1 christos long v;
1271 1.1 christos
1272 1.1 christos if (exp.X_op == O_big && nbits == 32)
1273 1.1 christos return 1;
1274 1.1 christos if (exp.X_op != O_constant)
1275 1.1 christos return 0;
1276 1.1 christos v = exp.X_add_number;
1277 1.1 christos
1278 1.1 christos switch (nbits)
1279 1.1 christos {
1280 1.1 christos case 4:
1281 1.1 christos return -0x8 <= v && v <= 0x7;
1282 1.1 christos case 5:
1283 1.1 christos return -0x10 <= v && v <= 0x17;
1284 1.1 christos case 8:
1285 1.1 christos return -0x80 <= v && v <= 0x7f;
1286 1.1 christos case 16:
1287 1.1 christos return -0x8000 <= v && v <= 0x7fff;
1288 1.1 christos case 24:
1289 1.1 christos return -0x800000 <= v && v <= 0x7fffff;
1290 1.1 christos case 32:
1291 1.1 christos return 1;
1292 1.1 christos default:
1293 1.1 christos printf ("rx_intop passed %d\n", nbits);
1294 1.1 christos abort ();
1295 1.1 christos }
1296 1.1 christos return 1;
1297 1.1 christos }
1298 1.1 christos
1299 1.1 christos static int
1300 1.1 christos rx_uintop (expressionS exp, int nbits)
1301 1.1 christos {
1302 1.1 christos unsigned long v;
1303 1.1 christos
1304 1.1 christos if (exp.X_op != O_constant)
1305 1.1 christos return 0;
1306 1.1 christos v = exp.X_add_number;
1307 1.1 christos
1308 1.1 christos switch (nbits)
1309 1.1 christos {
1310 1.1 christos case 4:
1311 1.1 christos return v <= 0xf;
1312 1.1 christos case 8:
1313 1.1 christos return v <= 0xff;
1314 1.1 christos case 16:
1315 1.1 christos return v <= 0xffff;
1316 1.1 christos case 24:
1317 1.1 christos return v <= 0xffffff;
1318 1.1 christos default:
1319 1.1 christos printf ("rx_uintop passed %d\n", nbits);
1320 1.1 christos abort ();
1321 1.1 christos }
1322 1.1 christos return 1;
1323 1.1 christos }
1324 1.1 christos
1325 1.1 christos static int
1326 1.1 christos rx_disp3op (expressionS exp)
1327 1.1 christos {
1328 1.1 christos unsigned long v;
1329 1.1 christos
1330 1.1 christos if (exp.X_op != O_constant)
1331 1.1 christos return 0;
1332 1.1 christos v = exp.X_add_number;
1333 1.1 christos if (v < 3 || v > 10)
1334 1.1 christos return 0;
1335 1.1 christos return 1;
1336 1.1 christos }
1337 1.1 christos
1338 1.1 christos static int
1339 1.1 christos rx_disp5op (expressionS * exp, int msize)
1340 1.1 christos {
1341 1.1 christos long v;
1342 1.1 christos
1343 1.1 christos if (exp->X_op != O_constant)
1344 1.1 christos return 0;
1345 1.1 christos v = exp->X_add_number;
1346 1.1 christos
1347 1.1 christos switch (msize)
1348 1.1 christos {
1349 1.1 christos case BSIZE:
1350 1.1 christos if (0 < v && v <= 31)
1351 1.1 christos return 1;
1352 1.1 christos break;
1353 1.1 christos case WSIZE:
1354 1.1 christos if (v & 1)
1355 1.1 christos return 0;
1356 1.1 christos if (0 < v && v <= 63)
1357 1.1 christos {
1358 1.1 christos exp->X_add_number >>= 1;
1359 1.1 christos return 1;
1360 1.1 christos }
1361 1.1 christos break;
1362 1.1 christos case LSIZE:
1363 1.1 christos if (v & 3)
1364 1.1 christos return 0;
1365 1.1 christos if (0 < v && v <= 127)
1366 1.1 christos {
1367 1.1 christos exp->X_add_number >>= 2;
1368 1.1 christos return 1;
1369 1.1 christos }
1370 1.1 christos break;
1371 1.1 christos }
1372 1.1 christos return 0;
1373 1.1 christos }
1374 1.1 christos
1375 1.1 christos /* Just like the above, but allows a zero displacement. */
1376 1.1 christos
1377 1.1 christos static int
1378 1.1 christos rx_disp5op0 (expressionS * exp, int msize)
1379 1.1 christos {
1380 1.1 christos if (exp->X_op != O_constant)
1381 1.1 christos return 0;
1382 1.1 christos if (exp->X_add_number == 0)
1383 1.1 christos return 1;
1384 1.1 christos return rx_disp5op (exp, msize);
1385 1.1 christos }
1386 1.1 christos
1387 1.1 christos static int
1388 1.1 christos exp_val (expressionS exp)
1389 1.1 christos {
1390 1.1 christos if (exp.X_op != O_constant)
1391 1.1 christos {
1392 1.1 christos rx_error (_("constant expected"));
1393 1.1 christos return 0;
1394 1.1 christos }
1395 1.1 christos return exp.X_add_number;
1396 1.1 christos }
1397 1.1 christos
1398 1.1 christos static expressionS
1399 1.1 christos zero_expr (void)
1400 1.1 christos {
1401 1.1 christos /* Static, so program load sets it to all zeros, which is what we want. */
1402 1.1 christos static expressionS zero;
1403 1.1 christos zero.X_op = O_constant;
1404 1.1 christos return zero;
1405 1.1 christos }
1406 1.1 christos
1407 1.1 christos static int
1408 1.1 christos immediate (expressionS exp, int type, int pos)
1409 1.1 christos {
1410 1.1 christos /* We will emit constants ourself here, so negate them. */
1411 1.1 christos if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1412 1.1 christos exp.X_add_number = - exp.X_add_number;
1413 1.1 christos if (type == RXREL_NEGATIVE_BORROW)
1414 1.1 christos {
1415 1.1 christos if (exp.X_op == O_constant)
1416 1.1 christos exp.X_add_number = - exp.X_add_number - 1;
1417 1.1 christos else
1418 1.1 christos rx_error (_("sbb cannot use symbolic immediates"));
1419 1.1 christos }
1420 1.1 christos
1421 1.1 christos if (rx_intop (exp, 8))
1422 1.1 christos {
1423 1.1 christos rx_op (exp, 1, type);
1424 1.1 christos return 1;
1425 1.1 christos }
1426 1.1 christos else if (rx_intop (exp, 16))
1427 1.1 christos {
1428 1.1 christos rx_op (exp, 2, type);
1429 1.1 christos return 2;
1430 1.1 christos }
1431 1.1 christos else if (rx_intop (exp, 24))
1432 1.1 christos {
1433 1.1 christos rx_op (exp, 3, type);
1434 1.1 christos return 3;
1435 1.1 christos }
1436 1.1 christos else if (rx_intop (exp, 32))
1437 1.1 christos {
1438 1.1 christos rx_op (exp, 4, type);
1439 1.1 christos return 0;
1440 1.1 christos }
1441 1.1 christos else if (type == RXREL_SIGNED)
1442 1.1 christos {
1443 1.1 christos /* This is a symbolic immediate, we will relax it later. */
1444 1.1 christos rx_relax (RX_RELAX_IMM, pos);
1445 1.1 christos rx_op (exp, linkrelax ? 4 : 1, type);
1446 1.1 christos return 1;
1447 1.1 christos }
1448 1.1 christos else
1449 1.1 christos {
1450 1.1 christos /* Let the linker deal with it. */
1451 1.1 christos rx_op (exp, 4, type);
1452 1.1 christos return 0;
1453 1.1 christos }
1454 1.1 christos }
1455 1.1 christos
1456 1.1 christos static int
1457 1.1 christos displacement (expressionS exp, int msize)
1458 1.1 christos {
1459 1.1 christos int val;
1460 1.1 christos int vshift = 0;
1461 1.1 christos
1462 1.1 christos if (exp.X_op == O_symbol
1463 1.1 christos && exp.X_md)
1464 1.1 christos {
1465 1.1 christos switch (exp.X_md)
1466 1.1 christos {
1467 1.1 christos case BFD_RELOC_GPREL16:
1468 1.1 christos switch (msize)
1469 1.1 christos {
1470 1.1 christos case BSIZE:
1471 1.1 christos exp.X_md = BFD_RELOC_RX_GPRELB;
1472 1.1 christos break;
1473 1.1 christos case WSIZE:
1474 1.1 christos exp.X_md = BFD_RELOC_RX_GPRELW;
1475 1.1 christos break;
1476 1.1 christos case LSIZE:
1477 1.1 christos exp.X_md = BFD_RELOC_RX_GPRELL;
1478 1.1 christos break;
1479 1.1 christos }
1480 1.1 christos O2 (exp);
1481 1.1 christos return 2;
1482 1.1 christos }
1483 1.1 christos }
1484 1.1 christos
1485 1.1 christos if (exp.X_op != O_constant)
1486 1.1 christos {
1487 1.1 christos rx_error (_("displacements must be constants"));
1488 1.1 christos return -1;
1489 1.1 christos }
1490 1.1 christos val = exp.X_add_number;
1491 1.1 christos
1492 1.1 christos if (val == 0)
1493 1.1 christos return 0;
1494 1.1 christos
1495 1.1 christos switch (msize)
1496 1.1 christos {
1497 1.1 christos case BSIZE:
1498 1.1 christos break;
1499 1.1 christos case WSIZE:
1500 1.1 christos if (val & 1)
1501 1.1 christos rx_error (_("word displacement not word-aligned"));
1502 1.1 christos vshift = 1;
1503 1.1 christos break;
1504 1.1 christos case LSIZE:
1505 1.1 christos if (val & 3)
1506 1.1 christos rx_error (_("long displacement not long-aligned"));
1507 1.1 christos vshift = 2;
1508 1.1 christos break;
1509 1.1 christos default:
1510 1.1 christos as_bad (_("displacement with unknown size (internal bug?)\n"));
1511 1.1 christos break;
1512 1.1 christos }
1513 1.1 christos
1514 1.1 christos val >>= vshift;
1515 1.1 christos exp.X_add_number = val;
1516 1.1 christos
1517 1.1 christos if (0 <= val && val <= 255 )
1518 1.1 christos {
1519 1.1 christos O1 (exp);
1520 1.1 christos return 1;
1521 1.1 christos }
1522 1.1 christos
1523 1.1 christos if (0 <= val && val <= 65535)
1524 1.1 christos {
1525 1.1 christos O2 (exp);
1526 1.1 christos return 2;
1527 1.1 christos }
1528 1.1 christos if (val < 0)
1529 1.1 christos rx_error (_("negative displacements not allowed"));
1530 1.1 christos else
1531 1.1 christos rx_error (_("displacement too large"));
1532 1.1 christos return -1;
1533 1.1 christos }
1534 1.1 christos
1535 1.1 christos static void
1536 1.1 christos rtsd_immediate (expressionS exp)
1537 1.1 christos {
1538 1.1 christos int val;
1539 1.1 christos
1540 1.1 christos if (exp.X_op != O_constant)
1541 1.1 christos {
1542 1.1 christos rx_error (_("rtsd size must be constant"));
1543 1.1 christos return;
1544 1.1 christos }
1545 1.1 christos val = exp.X_add_number;
1546 1.1 christos if (val & 3)
1547 1.1 christos rx_error (_("rtsd size must be multiple of 4"));
1548 1.1 christos
1549 1.1 christos if (val < 0 || val > 1020)
1550 1.1 christos rx_error (_("rtsd size must be 0..1020"));
1551 1.1 christos
1552 1.1 christos val >>= 2;
1553 1.1 christos exp.X_add_number = val;
1554 1.1 christos O1 (exp);
1555 1.1 christos }
1556