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