diff options
Diffstat (limited to 'binutils-2.24/gas/config/rx-parse.y')
-rw-r--r-- | binutils-2.24/gas/config/rx-parse.y | 1641 |
1 files changed, 0 insertions, 1641 deletions
diff --git a/binutils-2.24/gas/config/rx-parse.y b/binutils-2.24/gas/config/rx-parse.y deleted file mode 100644 index 3933e6b9..00000000 --- a/binutils-2.24/gas/config/rx-parse.y +++ /dev/null @@ -1,1641 +0,0 @@ -/* rx-parse.y Renesas RX parser - Copyright 2008-2013 Free Software Foundation, Inc. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA - 02110-1301, USA. */ -%{ - -#include "as.h" -#include "safe-ctype.h" -#include "rx-defs.h" - -static int rx_lex (void); - -#define COND_EQ 0 -#define COND_NE 1 - -#define MEMEX 0x06 - -#define BSIZE 0 -#define WSIZE 1 -#define LSIZE 2 - -/* .sb .sw .l .uw */ -static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; - -/* Ok, here are the rules for using these macros... - - B*() is used to specify the base opcode bytes. Fields to be filled - in later, leave zero. Call this first. - - F() and FE() are used to fill in fields within the base opcode bytes. You MUST - call B*() before any F() or FE(). - - [UN]*O*(), PC*() appends operands to the end of the opcode. You - must call P() and B*() before any of these, so that the fixups - have the right byte location. - O = signed, UO = unsigned, NO = negated, PC = pcrel - - IMM() adds an immediate and fills in the field for it. - NIMM() same, but negates the immediate. - NBIMM() same, but negates the immediate, for sbb. - DSP() adds a displacement, and fills in the field for it. - - Note that order is significant for the O, IMM, and DSP macros, as - they append their data to the operand buffer in the order that you - call them. - - Use "disp" for displacements whenever possible; this handles the - "0" case properly. */ - -#define B1(b1) rx_base1 (b1) -#define B2(b1, b2) rx_base2 (b1, b2) -#define B3(b1, b2, b3) rx_base3 (b1, b2, b3) -#define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4) - -/* POS is bits from the MSB of the first byte to the LSB of the last byte. */ -#define F(val,pos,sz) rx_field (val, pos, sz) -#define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz); - -#define O1(v) rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255) -#define O2(v) rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536) -#define O3(v) rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216) -#define O4(v) rx_op (v, 4, RXREL_SIGNED) - -#define UO1(v) rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255) -#define UO2(v) rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536) -#define UO3(v) rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216) -#define UO4(v) rx_op (v, 4, RXREL_UNSIGNED) - -#define NO1(v) rx_op (v, 1, RXREL_NEGATIVE) -#define NO2(v) rx_op (v, 2, RXREL_NEGATIVE) -#define NO3(v) rx_op (v, 3, RXREL_NEGATIVE) -#define NO4(v) rx_op (v, 4, RXREL_NEGATIVE) - -#define PC1(v) rx_op (v, 1, RXREL_PCREL) -#define PC2(v) rx_op (v, 2, RXREL_PCREL) -#define PC3(v) rx_op (v, 3, RXREL_PCREL) - -#define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \ - if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos) -#define IMM(v,pos) IMM_ (v, pos, 32) -#define IMMW(v,pos) IMM_ (v, pos, 16); rx_range (v, -32768, 65536) -#define IMMB(v,pos) IMM_ (v, pos, 8); rx_range (v, -128, 255) -#define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2) -#define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2) -#define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \ - else rx_linkrelax_dsp (pos); \ - F (displacement (v, msz), pos, 2) - -#define id24(a,b2,b3) B3 (0xfb+a, b2, b3) - -static void rx_check_float_support (void); -static int rx_intop (expressionS, int, int); -static int rx_uintop (expressionS, int); -static int rx_disp3op (expressionS); -static int rx_disp5op (expressionS *, int); -static int rx_disp5op0 (expressionS *, int); -static int exp_val (expressionS exp); -static expressionS zero_expr (void); -static int immediate (expressionS, int, int, int); -static int displacement (expressionS, int); -static void rtsd_immediate (expressionS); -static void rx_range (expressionS, int, int); - -static int need_flag = 0; -static int rx_in_brackets = 0; -static int rx_last_token = 0; -static char * rx_init_start; -static char * rx_last_exp_start = 0; -static int sub_op; -static int sub_op2; - -#define YYDEBUG 1 -#define YYERROR_VERBOSE 1 - -%} - -%name-prefix="rx_" - -%union { - int regno; - expressionS exp; -} - -%type <regno> REG FLAG CREG BCND BMCND SCCND -%type <regno> flag bwl bw memex -%type <exp> EXPR disp - -%token REG FLAG CREG - -%token EXPR UNKNOWN_OPCODE IS_OPCODE - -%token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW - -%token ABS ADC ADD AND_ -%token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST -%token CLRPSW CMP -%token DBT DIV DIVU -%token EDIV EDIVU EMUL EMULU -%token FADD FCMP FDIV FMUL FREIT FSUB FTOI -%token INT ITOF -%token JMP JSR -%token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO -%token MVFC MVTACHI MVTACLO MVTC MVTIPL -%token NEG NOP NOT -%token OR -%token POP POPC POPM PUSH PUSHA PUSHC PUSHM -%token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD -%token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF -%token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE -%token TST -%token WAIT -%token XCHG XOR - -%% -/* ====================================================================== */ - -statement : - - UNKNOWN_OPCODE - { as_bad (_("Unknown opcode: %s"), rx_init_start); } - -/* ---------------------------------------------------------------------- */ - - | BRK - { B1 (0x00); } - - | DBT - { B1 (0x01); } - - | RTS - { B1 (0x02); } - - | NOP - { B1 (0x03); } - -/* ---------------------------------------------------------------------- */ - - | BRA EXPR - { if (rx_disp3op ($2)) - { B1 (0x08); rx_disp3 ($2, 5); } - else if (rx_intop ($2, 8, 8)) - { B1 (0x2e); PC1 ($2); } - else if (rx_intop ($2, 16, 16)) - { B1 (0x38); PC2 ($2); } - else if (rx_intop ($2, 24, 24)) - { B1 (0x04); PC3 ($2); } - else - { rx_relax (RX_RELAX_BRANCH, 0); - rx_linkrelax_branch (); - /* We'll convert this to a longer one later if needed. */ - B1 (0x08); rx_disp3 ($2, 5); } } - - | BRA DOT_A EXPR - { B1 (0x04); PC3 ($3); } - - | BRA DOT_S EXPR - { B1 (0x08); rx_disp3 ($3, 5); } - -/* ---------------------------------------------------------------------- */ - - | BSR EXPR - { if (rx_intop ($2, 16, 16)) - { B1 (0x39); PC2 ($2); } - else if (rx_intop ($2, 24, 24)) - { B1 (0x05); PC3 ($2); } - else - { rx_relax (RX_RELAX_BRANCH, 0); - rx_linkrelax_branch (); - B1 (0x39); PC2 ($2); } } - | BSR DOT_A EXPR - { B1 (0x05), PC3 ($3); } - -/* ---------------------------------------------------------------------- */ - - | BCND DOT_S EXPR - { if ($1 == COND_EQ || $1 == COND_NE) - { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); } - else - as_bad (_("Only BEQ and BNE may have .S")); } - -/* ---------------------------------------------------------------------- */ - - | BCND DOT_B EXPR - { B1 (0x20); F ($1, 4, 4); PC1 ($3); } - - | BRA DOT_B EXPR - { B1 (0x2e), PC1 ($3); } - -/* ---------------------------------------------------------------------- */ - - | BRA DOT_W EXPR - { B1 (0x38), PC2 ($3); } - | BSR DOT_W EXPR - { B1 (0x39), PC2 ($3); } - | BCND DOT_W EXPR - { if ($1 == COND_EQ || $1 == COND_NE) - { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); } - else - as_bad (_("Only BEQ and BNE may have .W")); } - | BCND EXPR - { if ($1 == COND_EQ || $1 == COND_NE) - { - rx_relax (RX_RELAX_BRANCH, 0); - rx_linkrelax_branch (); - B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5); - } - else - { - rx_relax (RX_RELAX_BRANCH, 0); - /* This is because we might turn it into a - jump-over-jump long branch. */ - rx_linkrelax_branch (); - B1 (0x20); F ($1, 4, 4); PC1 ($2); - } } - -/* ---------------------------------------------------------------------- */ - - | MOV DOT_B '#' EXPR ',' disp '[' REG ']' - /* rx_disp5op changes the value if it succeeds, so keep it last. */ - { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE)) - { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } - else - { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4); - if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } } - - | MOV DOT_W '#' EXPR ',' disp '[' REG ']' - { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE)) - { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } - else - { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } } - - | MOV DOT_L '#' EXPR ',' disp '[' REG ']' - { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE)) - { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); } - else - { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } } - -/* ---------------------------------------------------------------------- */ - - | RTSD '#' EXPR ',' REG '-' REG - { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3); - if ($5 == 0) - rx_error (_("RTSD cannot pop R0")); - if ($5 > $7) - rx_error (_("RTSD first reg must be <= second reg")); } - -/* ---------------------------------------------------------------------- */ - - | CMP REG ',' REG - { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | CMP disp '[' REG ']' DOT_UB ',' REG - { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); } - - | CMP disp '[' REG ']' memex ',' REG - { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); } - -/* ---------------------------------------------------------------------- */ - - | MOVU bw REG ',' REG - { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOVU bw '[' REG ']' ',' REG - { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); } - - | MOVU bw EXPR '[' REG ']' ',' REG - { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2)) - { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); } - else - { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } } - -/* ---------------------------------------------------------------------- */ - - | SUB '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else - /* This is really an add, but we negate the immediate. */ - { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } } - - | CMP '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else if (rx_uintop ($3, 8)) - { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); } - else - { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } } - - | ADD '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else - { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } } - - | MUL '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else - { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } } - - | AND_ '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else - { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } } - - | OR '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else - { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } } - - | MOV DOT_L '#' EXPR ',' REG - { if (rx_uintop ($4, 4)) - { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); } - else if (rx_uintop ($4, 8)) - { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); } - else - { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } } - - | MOV '#' EXPR ',' REG - { if (rx_uintop ($3, 4)) - { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); } - else if (rx_uintop ($3, 8)) - { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); } - else - { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } } - -/* ---------------------------------------------------------------------- */ - - | RTSD '#' EXPR - { B1 (0x67); rtsd_immediate ($3); } - -/* ---------------------------------------------------------------------- */ - - | SHLR { sub_op = 0; } op_shift - | SHAR { sub_op = 1; } op_shift - | SHLL { sub_op = 2; } op_shift - -/* ---------------------------------------------------------------------- */ - - | PUSHM REG '-' REG - { - if ($2 == $4) - { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); } - else - { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); } - if ($2 == 0) - rx_error (_("PUSHM cannot push R0")); - if ($2 > $4) - rx_error (_("PUSHM first reg must be <= second reg")); } - -/* ---------------------------------------------------------------------- */ - - | POPM REG '-' REG - { - if ($2 == $4) - { B2 (0x7e, 0xb0); F ($2, 12, 4); } - else - { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); } - if ($2 == 0) - rx_error (_("POPM cannot pop R0")); - if ($2 > $4) - rx_error (_("POPM first reg must be <= second reg")); } - -/* ---------------------------------------------------------------------- */ - - | ADD '#' EXPR ',' REG ',' REG - { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); } - -/* ---------------------------------------------------------------------- */ - - | INT '#' EXPR - { B2(0x75, 0x60), UO1 ($3); } - -/* ---------------------------------------------------------------------- */ - - | BSET '#' EXPR ',' REG - { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); } - | BCLR '#' EXPR ',' REG - { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | BTST '#' EXPR ',' REG - { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | SAT REG - { B2 (0x7e, 0x30); F ($2, 12, 4); } - | RORC REG - { B2 (0x7e, 0x40); F ($2, 12, 4); } - | ROLC REG - { B2 (0x7e, 0x50); F ($2, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | PUSH bwl REG - { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | POP REG - { B2 (0x7e, 0xb0); F ($2, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | PUSHC CREG - { if ($2 < 16) - { B2 (0x7e, 0xc0); F ($2, 12, 4); } - else - as_bad (_("PUSHC can only push the first 16 control registers")); } - -/* ---------------------------------------------------------------------- */ - - | POPC CREG - { if ($2 < 16) - { B2 (0x7e, 0xe0); F ($2, 12, 4); } - else - as_bad (_("POPC can only pop the first 16 control registers")); } - -/* ---------------------------------------------------------------------- */ - - | SETPSW flag - { B2 (0x7f, 0xa0); F ($2, 12, 4); } - | CLRPSW flag - { B2 (0x7f, 0xb0); F ($2, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | JMP REG - { B2 (0x7f, 0x00); F ($2, 12, 4); } - | JSR REG - { B2 (0x7f, 0x10); F ($2, 12, 4); } - | BRA opt_l REG - { B2 (0x7f, 0x40); F ($3, 12, 4); } - | BSR opt_l REG - { B2 (0x7f, 0x50); F ($3, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | SCMPU - { B2 (0x7f, 0x83); } - | SMOVU - { B2 (0x7f, 0x87); } - | SMOVB - { B2 (0x7f, 0x8b); } - | SMOVF - { B2 (0x7f, 0x8f); } - -/* ---------------------------------------------------------------------- */ - - | SUNTIL bwl - { B2 (0x7f, 0x80); F ($2, 14, 2); } - | SWHILE bwl - { B2 (0x7f, 0x84); F ($2, 14, 2); } - | SSTR bwl - { B2 (0x7f, 0x88); F ($2, 14, 2); } - -/* ---------------------------------------------------------------------- */ - - | RMPA bwl - { B2 (0x7f, 0x8c); F ($2, 14, 2); } - -/* ---------------------------------------------------------------------- */ - - | RTFI - { B2 (0x7f, 0x94); } - | RTE - { B2 (0x7f, 0x95); } - | WAIT - { B2 (0x7f, 0x96); } - | SATR - { B2 (0x7f, 0x93); } - -/* ---------------------------------------------------------------------- */ - - | MVTIPL '#' EXPR - { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - /* rx_disp5op changes the value if it succeeds, so keep it last. */ - | MOV bwl REG ',' EXPR '[' REG ']' - { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2)) - { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); } - else - { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }} - -/* ---------------------------------------------------------------------- */ - - | MOV bwl EXPR '[' REG ']' ',' REG - { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2)) - { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); } - else - { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } } - -/* ---------------------------------------------------------------------- */ - - /* MOV a,b - if a is a reg and b is mem, src and dest are - swapped. */ - - /* We don't use "disp" here because it causes a shift/reduce - conflict with the other displacement-less patterns. */ - - | MOV bwl REG ',' '[' REG ']' - { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl '[' REG ']' ',' disp '[' REG ']' - { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']' - { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl REG ',' REG - { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl '[' REG ']' ',' REG - { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); } - -/* ---------------------------------------------------------------------- */ - - | BSET '#' EXPR ',' disp '[' REG ']' DOT_B - { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } - | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B - { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } - | BTST '#' EXPR ',' disp '[' REG ']' DOT_B - { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); } - -/* ---------------------------------------------------------------------- */ - - | PUSH bwl disp '[' REG ']' - { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); } - -/* ---------------------------------------------------------------------- */ - - | SBB { sub_op = 0; } op_dp20_rm_l - | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rr - | ADC { sub_op = 2; } op_dp20_rim_l - | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rr - | MAX { sub_op = 4; } op_dp20_rim - | MIN { sub_op = 5; } op_dp20_rim - | EMUL { sub_op = 6; } op_dp20_i - | EMULU { sub_op = 7; } op_dp20_i - | DIV { sub_op = 8; } op_dp20_rim - | DIVU { sub_op = 9; } op_dp20_rim - | TST { sub_op = 12; } op_dp20_rim - | XOR { sub_op = 13; } op_dp20_rim - | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr - | STZ { sub_op = 14; } op_dp20_i - | STNZ { sub_op = 15; } op_dp20_i - -/* ---------------------------------------------------------------------- */ - - | EMUL { sub_op = 6; } op_xchg - | EMULU { sub_op = 7; } op_xchg - | XCHG { sub_op = 16; } op_xchg - | ITOF { sub_op = 17; } op_xchg - -/* ---------------------------------------------------------------------- */ - - | BSET REG ',' REG - { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); } - | BCLR REG ',' REG - { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); } - | BTST REG ',' REG - { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); } - | BNOT REG ',' REG - { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); } - - | BSET REG ',' disp '[' REG ']' DOT_B - { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BCLR REG ',' disp '[' REG ']' DOT_B - { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BTST REG ',' disp '[' REG ']' DOT_B - { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BNOT REG ',' disp '[' REG ']' DOT_B - { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - -/* ---------------------------------------------------------------------- */ - - | FSUB { sub_op = 0; } float2_op - | FCMP { sub_op = 1; } float2_op - | FADD { sub_op = 2; } float2_op - | FMUL { sub_op = 3; } float2_op - | FDIV { sub_op = 4; } float2_op - | FTOI { sub_op = 5; } float2_op_ni - | ROUND { sub_op = 6; } float2_op_ni - -/* ---------------------------------------------------------------------- */ - - | SCCND DOT_L REG - { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); } - | SCCND bwl disp '[' REG ']' - { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); } - -/* ---------------------------------------------------------------------- */ - - | BMCND '#' EXPR ',' disp '[' REG ']' DOT_B - { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3); - F ($7, 16, 4); DSP ($5, 14, BSIZE); } - -/* ---------------------------------------------------------------------- */ - - | BNOT '#' EXPR ',' disp '[' REG ']' DOT_B - { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4); - DSP ($5, 14, BSIZE); } - -/* ---------------------------------------------------------------------- */ - - | MULHI REG ',' REG - { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); } - | MULLO REG ',' REG - { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); } - | MACHI REG ',' REG - { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); } - | MACLO REG ',' REG - { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - /* We don't have syntax for these yet. */ - | MVTACHI REG - { id24 (2, 0x17, 0x00); F ($2, 20, 4); } - | MVTACLO REG - { id24 (2, 0x17, 0x10); F ($2, 20, 4); } - | MVFACHI REG - { id24 (2, 0x1f, 0x00); F ($2, 20, 4); } - | MVFACMI REG - { id24 (2, 0x1f, 0x20); F ($2, 20, 4); } - | MVFACLO REG - { id24 (2, 0x1f, 0x10); F ($2, 20, 4); } - - | RACW '#' EXPR - { id24 (2, 0x18, 0x00); - if (rx_uintop ($3, 4) && $3.X_add_number == 1) - ; - else if (rx_uintop ($3, 4) && $3.X_add_number == 2) - F (1, 19, 1); - else - as_bad (_("RACW expects #1 or #2"));} - -/* ---------------------------------------------------------------------- */ - - | MOV bwl REG ',' '[' REG '+' ']' - { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); } - | MOV bwl REG ',' '[' '-' REG ']' - { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl '[' REG '+' ']' ',' REG - { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); } - | MOV bwl '[' '-' REG ']' ',' REG - { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOVU bw '[' REG '+' ']' ',' REG - { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); } - | MOVU bw '[' '-' REG ']' ',' REG - { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | ROTL { sub_op = 6; } op_shift_rot - | ROTR { sub_op = 4; } op_shift_rot - | REVW { sub_op = 5; } op_shift_rot - | REVL { sub_op = 7; } op_shift_rot - -/* ---------------------------------------------------------------------- */ - - | MVTC REG ',' CREG - { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1); - F ($2, 16, 4); } - -/* ---------------------------------------------------------------------- */ - - | MVFC CREG ',' REG - { id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | ROTL '#' EXPR ',' REG - { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); } - | ROTR '#' EXPR ',' REG - { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | MVTC '#' EXPR ',' CREG - { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); } - -/* ---------------------------------------------------------------------- */ - - | BMCND '#' EXPR ',' REG - { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5); - F ($5, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | BNOT '#' EXPR ',' REG - { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | MOV bwl REG ',' '[' REG ',' REG ']' - { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); } - - | MOV bwl '[' REG ',' REG ']' ',' REG - { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); } - - | MOVU bw '[' REG ',' REG ']' ',' REG - { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); } - -/* ---------------------------------------------------------------------- */ - - | SUB { sub_op = 0; } op_subadd - | ADD { sub_op = 2; } op_subadd - | MUL { sub_op = 3; } op_subadd - | AND_ { sub_op = 4; } op_subadd - | OR { sub_op = 5; } op_subadd - -/* ---------------------------------------------------------------------- */ -/* There is no SBB #imm so we fake it with ADC. */ - - | SBB '#' EXPR ',' REG - { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); } - -/* ---------------------------------------------------------------------- */ - - ; - -/* ====================================================================== */ - -op_subadd - : REG ',' REG - { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); } - | disp '[' REG ']' DOT_UB ',' REG - { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); } - | disp '[' REG ']' memex ',' REG - { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); } - | REG ',' REG ',' REG - { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); } - ; - -/* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */ - -op_dp20_rm_l - : REG ',' REG - { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } - | disp '[' REG ']' opt_l ',' REG - { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00); - F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); } - ; - -/* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */ - -op_dp20_rm - : REG ',' REG - { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } - | disp '[' REG ']' DOT_UB ',' REG - { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); } - | disp '[' REG ']' memex ',' REG - { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00); - F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); } - ; - -op_dp20_i - : '#' EXPR ',' REG - { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); } - ; - -op_dp20_rim - : op_dp20_rm - | op_dp20_i - ; - -op_dp20_rim_l - : op_dp20_rm_l - | op_dp20_i - ; - -op_dp20_rr - : REG ',' REG - { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } - | REG - { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); } - ; - -/* xchg, itof, emul, emulu */ -op_xchg - : REG ',' REG - { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); } - | disp '[' REG ']' DOT_UB ',' REG - { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); } - | disp '[' REG ']' memex ',' REG - { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4); - DSP ($1, 14, sizemap[$5]); } - ; - -/* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */ -op_shift_rot - : REG ',' REG - { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); } - ; -op_shift - : '#' EXPR ',' REG - { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); } - | '#' EXPR ',' REG ',' REG - { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); } - | op_shift_rot - ; - - -float2_op - : { rx_check_float_support (); } - '#' EXPR ',' REG - { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); } - | float2_op_ni - ; - -float2_op_ni - : { rx_check_float_support (); } - REG ',' REG - { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); } - | { rx_check_float_support (); } - disp '[' REG ']' opt_l ',' REG - { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); } - ; - -/* ====================================================================== */ - -disp : { $$ = zero_expr (); } - | EXPR { $$ = $1; } - ; - -flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; } - ; - -/* DOT_UB is not listed here, it's handled with a separate pattern. */ -/* Use sizemap[$n] to get LSIZE etc. */ -memex : DOT_B { $$ = 0; } - | DOT_W { $$ = 1; } - | { $$ = 2; } - | DOT_L { $$ = 2; } - | DOT_UW { $$ = 3; } - ; - -bwl : { $$ = LSIZE; } - | DOT_B { $$ = BSIZE; } - | DOT_W { $$ = WSIZE; } - | DOT_L { $$ = LSIZE; } - ; - -bw : { $$ = 1; } - | DOT_B { $$ = 0; } - | DOT_W { $$ = 1; } - ; - -opt_l : {} - | DOT_L {} - ; - -%% -/* ====================================================================== */ - -static struct -{ - const char * string; - int token; - int val; -} -token_table[] = -{ - { "r0", REG, 0 }, - { "r1", REG, 1 }, - { "r2", REG, 2 }, - { "r3", REG, 3 }, - { "r4", REG, 4 }, - { "r5", REG, 5 }, - { "r6", REG, 6 }, - { "r7", REG, 7 }, - { "r8", REG, 8 }, - { "r9", REG, 9 }, - { "r10", REG, 10 }, - { "r11", REG, 11 }, - { "r12", REG, 12 }, - { "r13", REG, 13 }, - { "r14", REG, 14 }, - { "r15", REG, 15 }, - - { "psw", CREG, 0 }, - { "pc", CREG, 1 }, - { "usp", CREG, 2 }, - { "fpsw", CREG, 3 }, - /* reserved */ - /* reserved */ - /* reserved */ - { "wr", CREG, 7 }, - - { "bpsw", CREG, 8 }, - { "bpc", CREG, 9 }, - { "isp", CREG, 10 }, - { "fintv", CREG, 11 }, - { "intb", CREG, 12 }, - - { "pbp", CREG, 16 }, - { "pben", CREG, 17 }, - - { "bbpsw", CREG, 24 }, - { "bbpc", CREG, 25 }, - - { ".s", DOT_S, 0 }, - { ".b", DOT_B, 0 }, - { ".w", DOT_W, 0 }, - { ".l", DOT_L, 0 }, - { ".a", DOT_A , 0}, - { ".ub", DOT_UB, 0 }, - { ".uw", DOT_UW , 0}, - - { "c", FLAG, 0 }, - { "z", FLAG, 1 }, - { "s", FLAG, 2 }, - { "o", FLAG, 3 }, - { "i", FLAG, 8 }, - { "u", FLAG, 9 }, - -#define OPC(x) { #x, x, IS_OPCODE } - OPC(ABS), - OPC(ADC), - OPC(ADD), - { "and", AND_, IS_OPCODE }, - OPC(BCLR), - OPC(BCND), - OPC(BMCND), - OPC(BNOT), - OPC(BRA), - OPC(BRK), - OPC(BSET), - OPC(BSR), - OPC(BTST), - OPC(CLRPSW), - OPC(CMP), - OPC(DBT), - OPC(DIV), - OPC(DIVU), - OPC(EDIV), - OPC(EDIVU), - OPC(EMUL), - OPC(EMULU), - OPC(FADD), - OPC(FCMP), - OPC(FDIV), - OPC(FMUL), - OPC(FREIT), - OPC(FSUB), - OPC(FTOI), - OPC(INT), - OPC(ITOF), - OPC(JMP), - OPC(JSR), - OPC(MVFACHI), - OPC(MVFACMI), - OPC(MVFACLO), - OPC(MVFC), - OPC(MVTACHI), - OPC(MVTACLO), - OPC(MVTC), - OPC(MVTIPL), - OPC(MACHI), - OPC(MACLO), - OPC(MAX), - OPC(MIN), - OPC(MOV), - OPC(MOVU), - OPC(MUL), - OPC(MULHI), - OPC(MULLO), - OPC(MULU), - OPC(NEG), - OPC(NOP), - OPC(NOT), - OPC(OR), - OPC(POP), - OPC(POPC), - OPC(POPM), - OPC(PUSH), - OPC(PUSHA), - OPC(PUSHC), - OPC(PUSHM), - OPC(RACW), - OPC(REIT), - OPC(REVL), - OPC(REVW), - OPC(RMPA), - OPC(ROLC), - OPC(RORC), - OPC(ROTL), - OPC(ROTR), - OPC(ROUND), - OPC(RTE), - OPC(RTFI), - OPC(RTS), - OPC(RTSD), - OPC(SAT), - OPC(SATR), - OPC(SBB), - OPC(SCCND), - OPC(SCMPU), - OPC(SETPSW), - OPC(SHAR), - OPC(SHLL), - OPC(SHLR), - OPC(SMOVB), - OPC(SMOVF), - OPC(SMOVU), - OPC(SSTR), - OPC(STNZ), - OPC(STOP), - OPC(STZ), - OPC(SUB), - OPC(SUNTIL), - OPC(SWHILE), - OPC(TST), - OPC(WAIT), - OPC(XCHG), - OPC(XOR), -}; - -#define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0])) - -static struct -{ - char * string; - int token; -} -condition_opcode_table[] = -{ - { "b", BCND }, - { "bm", BMCND }, - { "sc", SCCND }, -}; - -#define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0])) - -static struct -{ - char * string; - int val; -} -condition_table[] = -{ - { "z", 0 }, - { "eq", 0 }, - { "geu", 2 }, - { "c", 2 }, - { "gtu", 4 }, - { "pz", 6 }, - { "ge", 8 }, - { "gt", 10 }, - { "o", 12}, - /* always = 14 */ - { "nz", 1 }, - { "ne", 1 }, - { "ltu", 3 }, - { "nc", 3 }, - { "leu", 5 }, - { "n", 7 }, - { "lt", 9 }, - { "le", 11 }, - { "no", 13 } - /* never = 15 */ -}; - -#define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0])) - -void -rx_lex_init (char * beginning, char * ending) -{ - rx_init_start = beginning; - rx_lex_start = beginning; - rx_lex_end = ending; - rx_in_brackets = 0; - rx_last_token = 0; - - setbuf (stdout, 0); -} - -static int -check_condition (char * base) -{ - char * cp; - unsigned int i; - - if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1) - return 0; - if (memcmp (rx_lex_start, base, strlen (base))) - return 0; - cp = rx_lex_start + strlen (base); - for (i = 0; i < NUM_CONDITIONS; i ++) - { - if (strcasecmp (cp, condition_table[i].string) == 0) - { - rx_lval.regno = condition_table[i].val; - return 1; - } - } - return 0; -} - -static int -rx_lex (void) -{ - unsigned int ci; - char * save_input_pointer; - - while (ISSPACE (*rx_lex_start) - && rx_lex_start != rx_lex_end) - rx_lex_start ++; - - rx_last_exp_start = rx_lex_start; - - if (rx_lex_start == rx_lex_end) - return 0; - - if (ISALPHA (*rx_lex_start) - || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0) - || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0) - || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1]))) - { - unsigned int i; - char * e; - char save; - - for (e = rx_lex_start + 1; - e < rx_lex_end && ISALNUM (*e); - e ++) - ; - save = *e; - *e = 0; - - if (strcmp (rx_lex_start, "%pidreg") == 0) - { - { - rx_lval.regno = rx_pid_register; - *e = save; - rx_lex_start = e; - rx_last_token = REG; - return REG; - } - } - - if (strcmp (rx_lex_start, "%gpreg") == 0) - { - { - rx_lval.regno = rx_gp_register; - *e = save; - rx_lex_start = e; - rx_last_token = REG; - return REG; - } - } - - if (rx_last_token == 0) - for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) - if (check_condition (condition_opcode_table[ci].string)) - { - *e = save; - rx_lex_start = e; - rx_last_token = condition_opcode_table[ci].token; - return condition_opcode_table[ci].token; - } - - for (i = 0; i < NUM_TOKENS; i++) - if (strcasecmp (rx_lex_start, token_table[i].string) == 0 - && !(token_table[i].val == IS_OPCODE && rx_last_token != 0) - && !(token_table[i].token == FLAG && !need_flag)) - { - rx_lval.regno = token_table[i].val; - *e = save; - rx_lex_start = e; - rx_last_token = token_table[i].token; - return token_table[i].token; - } - *e = save; - } - - if (rx_last_token == 0) - { - rx_last_token = UNKNOWN_OPCODE; - return UNKNOWN_OPCODE; - } - - if (rx_last_token == UNKNOWN_OPCODE) - return 0; - - if (*rx_lex_start == '[') - rx_in_brackets = 1; - if (*rx_lex_start == ']') - rx_in_brackets = 0; - - if (rx_in_brackets - || rx_last_token == REG - || strchr ("[],#", *rx_lex_start)) - { - rx_last_token = *rx_lex_start; - return *rx_lex_start ++; - } - - save_input_pointer = input_line_pointer; - input_line_pointer = rx_lex_start; - rx_lval.exp.X_md = 0; - expression (&rx_lval.exp); - - /* We parse but ignore any :<size> modifier on expressions. */ - if (*input_line_pointer == ':') - { - char *cp; - - for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++) - if (!ISDIGIT (*cp)) - break; - if (cp > input_line_pointer+1) - input_line_pointer = cp; - } - - rx_lex_start = input_line_pointer; - input_line_pointer = save_input_pointer; - rx_last_token = EXPR; - return EXPR; -} - -int -rx_error (const char * str) -{ - int len; - - len = rx_last_exp_start - rx_init_start; - - as_bad ("%s", rx_init_start); - as_bad ("%*s^ %s", len, "", str); - return 0; -} - -static int -rx_intop (expressionS exp, int nbits, int opbits) -{ - long v; - long mask, msb; - - if (exp.X_op == O_big && nbits == 32) - return 1; - if (exp.X_op != O_constant) - return 0; - v = exp.X_add_number; - - msb = 1UL << (opbits - 1); - mask = (1UL << opbits) - 1; - - if ((v & msb) && ! (v & ~mask)) - v -= 1UL << opbits; - - switch (nbits) - { - case 4: - return -0x8 <= v && v <= 0x7; - case 5: - return -0x10 <= v && v <= 0x17; - case 8: - return -0x80 <= v && v <= 0x7f; - case 16: - return -0x8000 <= v && v <= 0x7fff; - case 24: - return -0x800000 <= v && v <= 0x7fffff; - case 32: - return 1; - default: - printf ("rx_intop passed %d\n", nbits); - abort (); - } - return 1; -} - -static int -rx_uintop (expressionS exp, int nbits) -{ - unsigned long v; - - if (exp.X_op != O_constant) - return 0; - v = exp.X_add_number; - - switch (nbits) - { - case 4: - return v <= 0xf; - case 8: - return v <= 0xff; - case 16: - return v <= 0xffff; - case 24: - return v <= 0xffffff; - default: - printf ("rx_uintop passed %d\n", nbits); - abort (); - } - return 1; -} - -static int -rx_disp3op (expressionS exp) -{ - unsigned long v; - - if (exp.X_op != O_constant) - return 0; - v = exp.X_add_number; - if (v < 3 || v > 10) - return 0; - return 1; -} - -static int -rx_disp5op (expressionS * exp, int msize) -{ - long v; - - if (exp->X_op != O_constant) - return 0; - v = exp->X_add_number; - - switch (msize) - { - case BSIZE: - if (0 < v && v <= 31) - return 1; - break; - case WSIZE: - if (v & 1) - return 0; - if (0 < v && v <= 63) - { - exp->X_add_number >>= 1; - return 1; - } - break; - case LSIZE: - if (v & 3) - return 0; - if (0 < v && v <= 127) - { - exp->X_add_number >>= 2; - return 1; - } - break; - } - return 0; -} - -/* Just like the above, but allows a zero displacement. */ - -static int -rx_disp5op0 (expressionS * exp, int msize) -{ - if (exp->X_op != O_constant) - return 0; - if (exp->X_add_number == 0) - return 1; - return rx_disp5op (exp, msize); -} - -static int -exp_val (expressionS exp) -{ - if (exp.X_op != O_constant) - { - rx_error (_("constant expected")); - return 0; - } - return exp.X_add_number; -} - -static expressionS -zero_expr (void) -{ - /* Static, so program load sets it to all zeros, which is what we want. */ - static expressionS zero; - zero.X_op = O_constant; - return zero; -} - -static int -immediate (expressionS exp, int type, int pos, int bits) -{ - /* We will emit constants ourself here, so negate them. */ - if (type == RXREL_NEGATIVE && exp.X_op == O_constant) - exp.X_add_number = - exp.X_add_number; - if (type == RXREL_NEGATIVE_BORROW) - { - if (exp.X_op == O_constant) - exp.X_add_number = - exp.X_add_number - 1; - else - rx_error (_("sbb cannot use symbolic immediates")); - } - - if (rx_intop (exp, 8, bits)) - { - rx_op (exp, 1, type); - return 1; - } - else if (rx_intop (exp, 16, bits)) - { - rx_op (exp, 2, type); - return 2; - } - else if (rx_uintop (exp, 16) && bits == 16) - { - rx_op (exp, 2, type); - return 2; - } - else if (rx_intop (exp, 24, bits)) - { - rx_op (exp, 3, type); - return 3; - } - else if (rx_intop (exp, 32, bits)) - { - rx_op (exp, 4, type); - return 0; - } - else if (type == RXREL_SIGNED) - { - /* This is a symbolic immediate, we will relax it later. */ - rx_relax (RX_RELAX_IMM, pos); - rx_op (exp, linkrelax ? 4 : 1, type); - return 1; - } - else - { - /* Let the linker deal with it. */ - rx_op (exp, 4, type); - return 0; - } -} - -static int -displacement (expressionS exp, int msize) -{ - int val; - int vshift = 0; - - if (exp.X_op == O_symbol - && exp.X_md) - { - switch (exp.X_md) - { - case BFD_RELOC_GPREL16: - switch (msize) - { - case BSIZE: - exp.X_md = BFD_RELOC_RX_GPRELB; - break; - case WSIZE: - exp.X_md = BFD_RELOC_RX_GPRELW; - break; - case LSIZE: - exp.X_md = BFD_RELOC_RX_GPRELL; - break; - } - O2 (exp); - return 2; - } - } - - if (exp.X_op == O_subtract) - { - exp.X_md = BFD_RELOC_RX_DIFF; - O2 (exp); - return 2; - } - - if (exp.X_op != O_constant) - { - rx_error (_("displacements must be constants")); - return -1; - } - val = exp.X_add_number; - - if (val == 0) - return 0; - - switch (msize) - { - case BSIZE: - break; - case WSIZE: - if (val & 1) - rx_error (_("word displacement not word-aligned")); - vshift = 1; - break; - case LSIZE: - if (val & 3) - rx_error (_("long displacement not long-aligned")); - vshift = 2; - break; - default: - as_bad (_("displacement with unknown size (internal bug?)\n")); - break; - } - - val >>= vshift; - exp.X_add_number = val; - - if (0 <= val && val <= 255 ) - { - O1 (exp); - return 1; - } - - if (0 <= val && val <= 65535) - { - O2 (exp); - return 2; - } - if (val < 0) - rx_error (_("negative displacements not allowed")); - else - rx_error (_("displacement too large")); - return -1; -} - -static void -rtsd_immediate (expressionS exp) -{ - int val; - - if (exp.X_op != O_constant) - { - rx_error (_("rtsd size must be constant")); - return; - } - val = exp.X_add_number; - if (val & 3) - rx_error (_("rtsd size must be multiple of 4")); - - if (val < 0 || val > 1020) - rx_error (_("rtsd size must be 0..1020")); - - val >>= 2; - exp.X_add_number = val; - O1 (exp); -} - -static void -rx_range (expressionS exp, int minv, int maxv) -{ - int val; - - if (exp.X_op != O_constant) - return; - - val = exp.X_add_number; - if (val < minv || val > maxv) - as_warn (_("Value %d out of range %d..%d"), val, minv, maxv); -} - -static void -rx_check_float_support (void) -{ - if (rx_cpu == RX100 || rx_cpu == RX200) - rx_error (_("target CPU type does not support floating point instructions")); -} |