OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [rx-parse.y] - Blame information for rev 241

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.