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