X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gas%2Fconfig%2Frx-parse.y;h=dfb04843a50fe995baedb858a539bb5af84b4b7a;hb=c5df7e442e6cdc9303b7373842370d6ee8f67ea5;hp=2d1f85e9f4cc09e8552cbae042715e639dd20240;hpb=e6a3fb4b5cc97668b0822c98d7896a5fca165360;p=binutils-gdb.git diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y index 2d1f85e9f4c..dfb04843a50 100644 --- a/gas/config/rx-parse.y +++ b/gas/config/rx-parse.y @@ -1,6 +1,5 @@ /* rx-parse.y Renesas RX parser - Copyright 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 2008-2021 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -34,6 +33,7 @@ static int rx_lex (void); #define BSIZE 0 #define WSIZE 1 #define LSIZE 2 +#define DSIZE 3 /* .sb .sw .l .uw */ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; @@ -72,14 +72,14 @@ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; #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) -#define O2(v) rx_op (v, 2, RXREL_SIGNED) -#define O3(v) rx_op (v, 3, RXREL_SIGNED) +#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) -#define UO2(v) rx_op (v, 2, RXREL_UNSIGNED) -#define UO3(v) rx_op (v, 3, RXREL_UNSIGNED) +#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) @@ -91,26 +91,36 @@ static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE }; #define PC2(v) rx_op (v, 2, RXREL_PCREL) #define PC3(v) rx_op (v, 3, RXREL_PCREL) -#define IMM(v,pos) F (immediate (v, RXREL_SIGNED, pos), pos, 2); \ +#define POST(v) rx_post (v) + +#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 NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos), pos, 2) -#define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos), pos, 2) +#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) +#define id24(a,b2,b3) B3 (0xfb + a, b2, b3) -static int rx_intop (expressionS, int); +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); +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 void rx_check_v2 (void); +static void rx_check_v3 (void); +static void rx_check_dfpu (void); static int need_flag = 0; static int rx_in_brackets = 0; @@ -132,33 +142,37 @@ static int sub_op2; expressionS exp; } -%type REG FLAG CREG BCND BMCND SCCND +%type REG FLAG CREG BCND BMCND SCCND ACC DREG DREGH DREGL DCREG DCMP %type flag bwl bw memex %type EXPR disp -%token REG FLAG CREG +%token REG FLAG CREG ACC DREG DREGH DREGL DCREG %token EXPR UNKNOWN_OPCODE IS_OPCODE -%token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW +%token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW DOT_D %token ABS ADC ADD AND_ -%token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST +%token BCLR BCND BFMOV BFMOVZ 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 DABS DADD DBT DCMP DDIV DIV DIVU DMOV DMUL DNEG +%token DPOPM DPUSHM DROUND DSQRT DSUB DTOF DTOI DTOU +%token EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU +%token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOD FTOI FTOU +%token INT ITOD 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 MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL +%token MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVFDC +%token MVFDR MVTACGU MVTACHI MVTACLO MVTC MVTDC 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 RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND +%token RSTR RTE RTFI RTS RTSD +%token SAT SATR SAVE SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE %token TST +%token UTOD UTOF %token WAIT %token XCHG XOR @@ -189,11 +203,11 @@ statement : | BRA EXPR { if (rx_disp3op ($2)) { B1 (0x08); rx_disp3 ($2, 5); } - else if (rx_intop ($2, 8)) + else if (rx_intop ($2, 8, 8)) { B1 (0x2e); PC1 ($2); } - else if (rx_intop ($2, 16)) + else if (rx_intop ($2, 16, 16)) { B1 (0x38); PC2 ($2); } - else if (rx_intop ($2, 24)) + else if (rx_intop ($2, 24, 24)) { B1 (0x04); PC3 ($2); } else { rx_relax (RX_RELAX_BRANCH, 0); @@ -210,9 +224,9 @@ statement : /* ---------------------------------------------------------------------- */ | BSR EXPR - { if (rx_intop ($2, 16)) + { if (rx_intop ($2, 16, 16)) { B1 (0x39); PC2 ($2); } - else if (rx_intop ($2, 24)) + else if (rx_intop ($2, 24, 24)) { B1 (0x05); PC3 ($2); } else { rx_relax (RX_RELAX_BRANCH, 0); @@ -266,6 +280,15 @@ statement : /* ---------------------------------------------------------------------- */ + | MOV DOT_B '#' EXPR ',' '[' REG ']' + { B2 (0xf8, 0x04); F ($7, 8, 4); IMMB ($4, 12);} + + | MOV DOT_W '#' EXPR ',' '[' REG ']' + { B2 (0xf8, 0x01); F ($7, 8, 4); IMMW ($4, 12);} + + | MOV DOT_L '#' EXPR ',' '[' REG ']' + { B2 (0xf8, 0x02); F ($7, 8, 4); IMM ($4, 12);} + | 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)) @@ -278,7 +301,7 @@ statement : { 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); IMM ($4, 12); } } + { 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)) @@ -462,7 +485,9 @@ statement : /* ---------------------------------------------------------------------- */ | PUSHC CREG - { if ($2 < 16) + { if ($2 == 13) + { rx_check_v2 (); } + if ($2 < 16) { B2 (0x7e, 0xc0); F ($2, 12, 4); } else as_bad (_("PUSHC can only push the first 16 control registers")); } @@ -470,7 +495,9 @@ statement : /* ---------------------------------------------------------------------- */ | POPC CREG - { if ($2 < 16) + { if ($2 == 13) + { rx_check_v2 (); } + if ($2 < 16) { B2 (0x7e, 0xe0); F ($2, 12, 4); } else as_bad (_("POPC can only pop the first 16 control registers")); } @@ -496,27 +523,27 @@ statement : /* ---------------------------------------------------------------------- */ | SCMPU - { B2 (0x7f, 0x83); } + { B2 (0x7f, 0x83); rx_note_string_insn_use (); } | SMOVU - { B2 (0x7f, 0x87); } + { B2 (0x7f, 0x87); rx_note_string_insn_use (); } | SMOVB - { B2 (0x7f, 0x8b); } + { B2 (0x7f, 0x8b); rx_note_string_insn_use (); } | SMOVF - { B2 (0x7f, 0x8f); } + { B2 (0x7f, 0x8f); rx_note_string_insn_use (); } /* ---------------------------------------------------------------------- */ | SUNTIL bwl - { B2 (0x7f, 0x80); F ($2, 14, 2); } + { B2 (0x7f, 0x80); F ($2, 14, 2); rx_note_string_insn_use (); } | SWHILE bwl - { B2 (0x7f, 0x84); F ($2, 14, 2); } + { B2 (0x7f, 0x84); F ($2, 14, 2); rx_note_string_insn_use (); } | SSTR bwl { B2 (0x7f, 0x88); F ($2, 14, 2); } /* ---------------------------------------------------------------------- */ | RMPA bwl - { B2 (0x7f, 0x8c); F ($2, 14, 2); } + { B2 (0x7f, 0x8c); F ($2, 14, 2); rx_note_string_insn_use (); } /* ---------------------------------------------------------------------- */ @@ -598,10 +625,10 @@ statement : /* ---------------------------------------------------------------------- */ - | SBB { sub_op = 0; } op_dp20_rm - | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rms - | ADC { sub_op = 2; } op_dp20_rim - | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rms + | 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 @@ -609,10 +636,10 @@ statement : | 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_rms - | STZ { sub_op = 14; } op_dp20_i - | STNZ { sub_op = 15; } op_dp20_i + | XOR { sub_op = 13; } op_xor + | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr + | STZ { sub_op = 14; sub_op2 = 0; } op_dp20_ri + | STNZ { sub_op = 15; sub_op2 = 1; } op_dp20_ri /* ---------------------------------------------------------------------- */ @@ -620,6 +647,7 @@ statement : | EMULU { sub_op = 7; } op_xchg | XCHG { sub_op = 16; } op_xchg | ITOF { sub_op = 17; } op_xchg + | UTOF { sub_op = 21; } op_xchg /* ---------------------------------------------------------------------- */ @@ -632,25 +660,30 @@ statement : | BNOT REG ',' REG { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); } - | BSET REG ',' disp '[' REG ']' DOT_B + | BSET REG ',' disp '[' REG ']' opt_b { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BCLR REG ',' disp '[' REG ']' DOT_B + | BCLR REG ',' disp '[' REG ']' opt_b { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BTST REG ',' disp '[' REG ']' DOT_B + | BTST REG ',' disp '[' REG ']' opt_b { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } - | BNOT REG ',' disp '[' REG ']' DOT_B + | BNOT REG ',' disp '[' REG ']' opt_b { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); } /* ---------------------------------------------------------------------- */ - | FSUB { sub_op = 0; } float2_op + | FSUB { sub_op = 0; } float3_op | FCMP { sub_op = 1; } float2_op - | FADD { sub_op = 2; } float2_op - | FMUL { sub_op = 3; } float2_op + | FADD { sub_op = 2; } float3_op + | FMUL { sub_op = 3; } float3_op | FDIV { sub_op = 4; } float2_op + | FSQRT { sub_op = 8; } float2_op_ni | FTOI { sub_op = 5; } float2_op_ni + | FTOU { sub_op = 9; } float2_op_ni | ROUND { sub_op = 6; } float2_op_ni +/* ---------------------------------------------------------------------- */ + + /* ---------------------------------------------------------------------- */ | SCCND DOT_L REG @@ -660,13 +693,13 @@ statement : /* ---------------------------------------------------------------------- */ - | BMCND '#' EXPR ',' disp '[' REG ']' DOT_B + | BMCND '#' EXPR ',' disp '[' REG ']' opt_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 + | BNOT '#' EXPR ',' disp '[' REG ']' opt_b { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4); DSP ($5, 14, BSIZE); } @@ -674,32 +707,54 @@ statement : | MULHI REG ',' REG { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); } + | MULHI REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } | MULLO REG ',' REG { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); } + | MULLO REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } | MACHI REG ',' REG { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); } + | MACHI REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } | MACLO REG ',' REG { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); } + | MACLO REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } /* ---------------------------------------------------------------------- */ /* We don't have syntax for these yet. */ | MVTACHI REG { id24 (2, 0x17, 0x00); F ($2, 20, 4); } + | MVTACHI REG ',' ACC + { rx_check_v2 (); id24 (2, 0x17, 0x00); F ($2, 20, 4); F ($4, 16, 1); } | MVTACLO REG { id24 (2, 0x17, 0x10); F ($2, 20, 4); } + | MVTACLO REG ',' ACC + { rx_check_v2 (); id24 (2, 0x17, 0x10); F ($2, 20, 4); F ($4, 16, 1); } | MVFACHI REG { id24 (2, 0x1f, 0x00); F ($2, 20, 4); } + | MVFACHI { sub_op = 0; } mvfa_op | MVFACMI REG { id24 (2, 0x1f, 0x20); F ($2, 20, 4); } + | MVFACMI { sub_op = 2; } mvfa_op | MVFACLO REG { id24 (2, 0x1f, 0x10); F ($2, 20, 4); } - + | MVFACLO { sub_op = 1; } mvfa_op | RACW '#' EXPR { id24 (2, 0x18, 0x00); - if (rx_uintop ($3, 4) && $3.X_add_number == 1) + if (rx_uintop ($3, 4) && exp_val($3) == 1) ; - else if (rx_uintop ($3, 4) && $3.X_add_number == 2) + else if (rx_uintop ($3, 4) && exp_val($3) == 2) + F (1, 19, 1); + else + as_bad (_("RACW expects #1 or #2"));} + | RACW '#' EXPR ',' ACC + { rx_check_v2 (); id24 (2, 0x18, 0x00); F ($5, 16, 1); + if (rx_uintop ($3, 4) && exp_val($3) == 1) + ; + else if (rx_uintop ($3, 4) && exp_val($3) == 2) F (1, 19, 1); else as_bad (_("RACW expects #1 or #2"));} @@ -735,13 +790,17 @@ statement : /* ---------------------------------------------------------------------- */ | MVTC REG ',' CREG - { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1); + { if ($4 == 13) + rx_check_v2 (); + 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); } + { if ($2 == 13) + rx_check_v2 (); + id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); } /* ---------------------------------------------------------------------- */ @@ -753,7 +812,9 @@ statement : /* ---------------------------------------------------------------------- */ | MVTC '#' EXPR ',' CREG - { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); } + { if ($5 == 13) + rx_check_v2 (); + id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); } /* ---------------------------------------------------------------------- */ @@ -791,6 +852,155 @@ statement : | SBB '#' EXPR ',' REG { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); } +/* ---------------------------------------------------------------------- */ + + | MOVCO REG ',' '[' REG ']' + { rx_check_v2 (); B3 (0xfd, 0x27, 0x00); F ($5, 16, 4); F ($2, 20, 4); } + +/* ---------------------------------------------------------------------- */ + + | MOVLI '[' REG ']' ',' REG + { rx_check_v2 (); B3 (0xfd, 0x2f, 0x00); F ($3, 16, 4); F ($6, 20, 4); } + +/* ---------------------------------------------------------------------- */ + + | EMACA REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x07, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | EMSBA REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x47, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | EMULA REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x03, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MACLH REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x06, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MSBHI REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x44, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MSBLH REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x46, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MSBLO REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x45, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MULLH REG ',' REG ',' ACC + { rx_check_v2 (); id24 (2, 0x02, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); } + | MVFACGU { sub_op = 3; } mvfa_op + | MVTACGU REG ',' ACC + { rx_check_v2 (); id24 (2, 0x17, 0x30); F ($4, 16, 1); F ($2, 20, 4); } + | RACL '#' EXPR ',' ACC + { rx_check_v2 (); id24 (2, 0x19, 0x00); F ($5, 16, 1); + 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 (_("RACL expects #1 or #2"));} + | RDACL '#' EXPR ',' ACC + { rx_check_v2 (); id24 (2, 0x19, 0x40); F ($5, 16, 1); + 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 (_("RDACL expects #1 or #2"));} + | RDACW '#' EXPR ',' ACC + { rx_check_v2 (); id24 (2, 0x18, 0x40); F ($5, 16, 1); + 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 (_("RDACW expects #1 or #2"));} + +/* ---------------------------------------------------------------------- */ + | BFMOV { rx_check_v3(); sub_op = 1; } op_bfield + | BFMOVZ { rx_check_v3(); sub_op = 0; } op_bfield + +/* ---------------------------------------------------------------------- */ + | RSTR { rx_check_v3(); sub_op = 1; } op_save_rstr + | SAVE { rx_check_v3(); sub_op = 0; } op_save_rstr + +/* ---------------------------------------------------------------------- */ + | DABS { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x01; } double2_op + | DNEG { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x02; } double2_op + | DROUND { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0d; } double2_op + | DSQRT { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x00; } double2_op + | DTOF { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0c; } double2_op + | DTOI { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x08;} double2_op + | DTOU { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x09; } double2_op + | DADD { rx_check_dfpu(); sub_op = 0x00; } double3_op + | DDIV { rx_check_dfpu(); sub_op = 0x05; } double3_op + | DMUL { rx_check_dfpu(); sub_op = 0x02; } double3_op + | DSUB { rx_check_dfpu(); sub_op = 0x01; } double3_op + | DCMP DREG ',' DREG { rx_check_dfpu(); + B4(0x76, 0x90, 0x08, 0x00); F($1, 24, 4); F($2, 28, 4); F($4, 16, 4); } + | DMOV DOT_D REG ',' DREGH + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x03); F($3, 20, 4); F($5, 24, 4); } + | DMOV DOT_L REG ',' DREGH + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x02); F($3, 20, 4); F($5, 24, 4); } + | DMOV DOT_L REG ',' DREGL + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x00); F($3, 20, 4); F($5, 24, 4); } + | DMOV DOT_L DREGH ',' REG + { rx_check_dfpu(); + B4(0xfd, 0x75, 0x80, 0x02); F($3, 24, 4); F($5, 20, 4); } + | DMOV DOT_L DREGL ',' REG + { rx_check_dfpu(); + B4(0xfd, 0x75, 0x80, 0x00); F($3, 24, 4); F($5, 20, 4); } + | DMOV DOT_D DREG ',' DREG + { rx_check_dfpu(); + B4(0x76, 0x90, 0x0c, 0x00); F($3, 16, 4); F($5, 24, 4); } + | DMOV DOT_D DREG ',' '[' REG ']' + { rx_check_dfpu(); + B4(0xfc, 0x78, 0x08, 0x00); F($6, 16, 4); F($3, 24, 4); } + | DMOV DOT_D DREG ',' disp '[' REG ']' + { rx_check_dfpu(); + B3(0xfc, 0x78, 0x08); F($7, 16, 4); DSP($5, 14, DSIZE); + POST($3 << 4); } + | DMOV DOT_D '[' REG ']' ',' DREG + { rx_check_dfpu(); + B4(0xfc, 0xc8, 0x08, 0x00); F($4, 16, 4); F($7, 24, 4); } + | DMOV DOT_D disp '[' REG ']' ',' DREG + { rx_check_dfpu(); + B3(0xfc, 0xc8, 0x08); F($5, 16, 4); DSP($3, 14, DSIZE); + POST($8 << 4); } + | DMOV DOT_D '#' EXPR ',' DREGH + { rx_check_dfpu(); + B3(0xf9, 0x03, 0x03); F($6, 16, 4); IMM($4, -1); } + | DMOV DOT_L '#' EXPR ',' DREGH + { rx_check_dfpu(); + B3(0xf9, 0x03, 0x02); F($6, 16, 4); IMM($4, -1); } + | DMOV DOT_L '#' EXPR ',' DREGL + { rx_check_dfpu(); + B3(0xf9, 0x03, 0x00); F($6, 16, 4); IMM($4, -1); } + | DPOPM DOT_D DREG '-' DREG + { rx_check_dfpu(); + B3(0x75, 0xb8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); } + | DPOPM DOT_L DCREG '-' DCREG + { rx_check_dfpu(); + B3(0x75, 0xa8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); } + | DPUSHM DOT_D DREG '-' DREG + { rx_check_dfpu(); + B3(0x75, 0xb0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); } + | DPUSHM DOT_L DCREG '-' DCREG + { rx_check_dfpu(); + B3(0x75, 0xa0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); } + | MVFDC DCREG ',' REG + { rx_check_dfpu(); + B4(0xfd, 0x75, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); } + | MVFDR + { rx_check_dfpu(); B3(0x75, 0x90, 0x1b); } + | MVTDC REG ',' DCREG + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); } + | FTOD REG ',' DREG + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x0a); F($2, 24, 4); F($4, 20, 4); } + | ITOD REG ',' DREG + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x09); F($2, 24, 4); F($4, 20, 4); } + | UTOD REG ',' DREG + { rx_check_dfpu(); + B4(0xfd, 0x77, 0x80, 0x0d); F($2, 24, 4); F($4, 20, 4); } + /* ---------------------------------------------------------------------- */ ; @@ -810,6 +1020,16 @@ op_subadd /* 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); } @@ -830,13 +1050,30 @@ op_dp20_rim | op_dp20_i ; -op_dp20_rms - : op_dp20_rm +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_dp20_r + : REG ',' REG + { id24 (1, 0x4b + (sub_op2<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); } + ; + +op_dp20_ri + : { rx_check_v2 (); } + op_dp20_r + | op_dp20_i + ; + +/* xchg, utof, itof, emul, emulu */ op_xchg : REG ',' REG { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); } @@ -860,20 +1097,85 @@ op_shift | op_shift_rot ; - +float3_op + : '#' EXPR ',' REG + { rx_check_float_support (); id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); } + | REG ',' REG + { rx_check_float_support (); id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); } + | disp '[' REG ']' opt_l ',' REG + { rx_check_float_support (); id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); } + | REG ',' REG ',' REG + { rx_check_v2 (); id24 (4, 0x80 + (sub_op << 4), 0 ); F ($1, 16, 4); F ($3, 20, 4); F ($5, 12, 4); } + ; float2_op - : '#' EXPR ',' REG - { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); } + : { rx_check_float_support (); } + '#' EXPR ',' REG + { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); } | float2_op_ni ; + float2_op_ni - : REG ',' REG - { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); } - | disp '[' REG ']' opt_l ',' REG - { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); } + : { 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); } + ; + +mvfa_op + : { rx_check_v2 (); } + '#' EXPR ',' ACC ',' REG + { id24 (2, 0x1e, sub_op << 4); F ($7, 20, 4); F ($5, 16, 1); + if (rx_uintop ($3, 4)) + { + switch (exp_val ($3)) + { + case 0: + F (1, 15, 1); + break; + case 1: + F (1, 15, 1); + F (1, 17, 1); + break; + case 2: + break; + default: + as_bad (_("IMM expects #0 to #2"));} + } else + as_bad (_("IMM expects #0 to #2"));} + ; + +op_xor + : op_dp20_rim + | REG ',' REG ',' REG + { rx_check_v3(); B3(0xff,0x60,0x00), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); } + ; + +op_bfield + : { rx_check_v3(); } + '#' EXPR ',' '#' EXPR ',' '#' EXPR ',' REG ',' REG + { rx_range($3, 0, 31); rx_range($6, 0, 31); rx_range($9, 1, 31); + B3(0xfc, 0x5a + (sub_op << 2), 0); F($11, 16, 4); F($13, 20, 4); + rx_bfield($3, $6, $9);} + ; + +op_save_rstr + : '#' EXPR + { B3(0xfd,0x76,0xe0 + (sub_op << 4)); UO1($2); } + | REG + { B4(0xfd,0x76,0xc0 + (sub_op << 4), 0x00); F($1, 20, 4); } ; +double2_op + : DREG ',' DREG + { B4(0x76, 0x90, sub_op, sub_op2); F($1, 16, 4); F($3, 24, 4);} + +double3_op + : DREG ',' DREG ',' DREG + { B4(0x76, 0x90, sub_op, 0x00); F($1, 28, 4); F($3, 16,4); F($5, 24, 4);} + /* ====================================================================== */ disp : { $$ = zero_expr (); } @@ -907,6 +1209,10 @@ opt_l : {} | DOT_L {} ; +opt_b : {} + | DOT_B {} + ; + %% /* ====================================================================== */ @@ -949,6 +1255,7 @@ token_table[] = { "isp", CREG, 10 }, { "fintv", CREG, 11 }, { "intb", CREG, 12 }, + { "extb", CREG, 13 }, { "pbp", CREG, 16 }, { "pben", CREG, 17 }, @@ -956,6 +1263,66 @@ token_table[] = { "bbpsw", CREG, 24 }, { "bbpc", CREG, 25 }, + { "dr0", DREG, 0 }, + { "dr1", DREG, 1 }, + { "dr2", DREG, 2 }, + { "dr3", DREG, 3 }, + { "dr4", DREG, 4 }, + { "dr5", DREG, 5 }, + { "dr6", DREG, 6 }, + { "dr7", DREG, 7 }, + { "dr8", DREG, 8 }, + { "dr9", DREG, 9 }, + { "dr10", DREG, 10 }, + { "dr11", DREG, 11 }, + { "dr12", DREG, 12 }, + { "dr13", DREG, 13 }, + { "dr14", DREG, 14 }, + { "dr15", DREG, 15 }, + + { "drh0", DREGH, 0 }, + { "drh1", DREGH, 1 }, + { "drh2", DREGH, 2 }, + { "drh3", DREGH, 3 }, + { "drh4", DREGH, 4 }, + { "drh5", DREGH, 5 }, + { "drh6", DREGH, 6 }, + { "drh7", DREGH, 7 }, + { "drh8", DREGH, 8 }, + { "drh9", DREGH, 9 }, + { "drh10", DREGH, 10 }, + { "drh11", DREGH, 11 }, + { "drh12", DREGH, 12 }, + { "drh13", DREGH, 13 }, + { "drh14", DREGH, 14 }, + { "drh15", DREGH, 15 }, + + { "drl0", DREGL, 0 }, + { "drl1", DREGL, 1 }, + { "drl2", DREGL, 2 }, + { "drl3", DREGL, 3 }, + { "drl4", DREGL, 4 }, + { "drl5", DREGL, 5 }, + { "drl6", DREGL, 6 }, + { "drl7", DREGL, 7 }, + { "drl8", DREGL, 8 }, + { "drl9", DREGL, 9 }, + { "drl10", DREGL, 10 }, + { "drl11", DREGL, 11 }, + { "drl12", DREGL, 12 }, + { "drl13", DREGL, 13 }, + { "drl14", DREGL, 14 }, + { "drl15", DREGL, 15 }, + + { "DPSW", DCREG, 0 }, + { "DCMR", DCREG, 1 }, + { "DCENT", DCREG, 2 }, + { "DEPC", DCREG, 3 }, + { "DCR0", DCREG, 0 }, + { "DCR1", DCREG, 1 }, + { "DCR2", DCREG, 2 }, + { "DCR3", DCREG, 3 }, + { ".s", DOT_S, 0 }, { ".b", DOT_B, 0 }, { ".w", DOT_W, 0 }, @@ -963,6 +1330,7 @@ token_table[] = { ".a", DOT_A , 0}, { ".ub", DOT_UB, 0 }, { ".uw", DOT_UW , 0}, + { ".d", DOT_D , 0}, { "c", FLAG, 0 }, { "z", FLAG, 1 }, @@ -971,6 +1339,9 @@ token_table[] = { "i", FLAG, 8 }, { "u", FLAG, 9 }, + { "a0", ACC, 0 }, + { "a1", ACC, 1 }, + #define OPC(x) { #x, x, IS_OPCODE } OPC(ABS), OPC(ADC), @@ -978,6 +1349,8 @@ token_table[] = { "and", AND_, IS_OPCODE }, OPC(BCLR), OPC(BCND), + OPC(BFMOV), + OPC(BFMOVZ), OPC(BMCND), OPC(BNOT), OPC(BRA), @@ -987,40 +1360,73 @@ token_table[] = OPC(BTST), OPC(CLRPSW), OPC(CMP), + OPC(DABS), + OPC(DADD), OPC(DBT), + OPC(DDIV), OPC(DIV), OPC(DIVU), + OPC(DMOV), + OPC(DMUL), + OPC(DNEG), + OPC(DPOPM), + OPC(DPUSHM), + OPC(DROUND), + OPC(DSQRT), + OPC(DSUB), + OPC(DTOF), + OPC(DTOI), + OPC(DTOU), OPC(EDIV), OPC(EDIVU), + OPC(EMACA), + OPC(EMSBA), OPC(EMUL), + OPC(EMULA), OPC(EMULU), OPC(FADD), OPC(FCMP), OPC(FDIV), OPC(FMUL), OPC(FREIT), + OPC(FSQRT), + OPC(FTOD), + OPC(FTOU), OPC(FSUB), OPC(FTOI), OPC(INT), + OPC(ITOD), OPC(ITOF), OPC(JMP), OPC(JSR), + OPC(MVFACGU), OPC(MVFACHI), OPC(MVFACMI), OPC(MVFACLO), OPC(MVFC), + OPC(MVFDC), + OPC(MVFDR), + OPC(MVTDC), + OPC(MVTACGU), OPC(MVTACHI), OPC(MVTACLO), OPC(MVTC), OPC(MVTIPL), OPC(MACHI), OPC(MACLO), + OPC(MACLH), OPC(MAX), OPC(MIN), OPC(MOV), + OPC(MOVCO), + OPC(MOVLI), OPC(MOVU), + OPC(MSBHI), + OPC(MSBLH), + OPC(MSBLO), OPC(MUL), OPC(MULHI), + OPC(MULLH), OPC(MULLO), OPC(MULU), OPC(NEG), @@ -1034,7 +1440,10 @@ token_table[] = OPC(PUSHA), OPC(PUSHC), OPC(PUSHM), + OPC(RACL), OPC(RACW), + OPC(RDACL), + OPC(RDACW), OPC(REIT), OPC(REVL), OPC(REVW), @@ -1044,12 +1453,14 @@ token_table[] = OPC(ROTL), OPC(ROTR), OPC(ROUND), + OPC(RSTR), OPC(RTE), OPC(RTFI), OPC(RTS), OPC(RTSD), OPC(SAT), OPC(SATR), + OPC(SAVE), OPC(SBB), OPC(SCCND), OPC(SCMPU), @@ -1068,6 +1479,8 @@ token_table[] = OPC(SUNTIL), OPC(SWHILE), OPC(TST), + OPC(UTOD), + OPC(UTOF), OPC(WAIT), OPC(XCHG), OPC(XOR), @@ -1077,7 +1490,7 @@ token_table[] = static struct { - char * string; + const char * string; int token; } condition_opcode_table[] = @@ -1089,12 +1502,13 @@ condition_opcode_table[] = #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0])) -static struct +struct condition_symbol { - char * string; + const char * string; int val; -} -condition_table[] = +}; + +static struct condition_symbol condition_table[] = { { "z", 0 }, { "eq", 0 }, @@ -1114,11 +1528,20 @@ condition_table[] = { "n", 7 }, { "lt", 9 }, { "le", 11 }, - { "no", 13 } + { "no", 13 }, /* never = 15 */ }; +static struct condition_symbol double_condition_table[] = +{ + { "un", 1 }, + { "eq", 2 }, + { "lt", 4 }, + { "le", 6 }, +}; + #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0])) +#define NUM_DOUBLE_CONDITIONS (sizeof (double_condition_table) / sizeof (double_condition_table[0])) void rx_lex_init (char * beginning, char * ending) @@ -1133,7 +1556,7 @@ rx_lex_init (char * beginning, char * ending) } static int -check_condition (char * base) +check_condition (const char * base, struct condition_symbol *t, unsigned int num) { char * cp; unsigned int i; @@ -1143,11 +1566,11 @@ check_condition (char * base) if (memcmp (rx_lex_start, base, strlen (base))) return 0; cp = rx_lex_start + strlen (base); - for (i = 0; i < NUM_CONDITIONS; i ++) + for (i = 0; i < num; i ++) { - if (strcasecmp (cp, condition_table[i].string) == 0) + if (strcasecmp (cp, t[i].string) == 0) { - rx_lval.regno = condition_table[i].val; + rx_lval.regno = t[i].val; return 1; } } @@ -1170,6 +1593,8 @@ rx_lex (void) 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; @@ -1183,15 +1608,48 @@ rx_lex (void) 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)) + { + for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++) + if (check_condition (condition_opcode_table[ci].string, + condition_table, NUM_CONDITIONS)) + { + *e = save; + rx_lex_start = e; + rx_last_token = condition_opcode_table[ci].token; + return condition_opcode_table[ci].token; + } + if (check_condition ("dcmp", double_condition_table, + NUM_DOUBLE_CONDITIONS)) { *e = save; rx_lex_start = e; - rx_last_token = condition_opcode_table[ci].token; - return condition_opcode_table[ci].token; + rx_last_token = DCMP; + return DCMP; } + } for (i = 0; i < NUM_TOKENS; i++) if (strcasecmp (rx_lex_start, token_table[i].string) == 0 @@ -1222,7 +1680,7 @@ rx_lex (void) rx_in_brackets = 0; if (rx_in_brackets - || rx_last_token == REG + || rx_last_token == REG || rx_last_token == DREG || rx_last_token == DCREG || strchr ("[],#", *rx_lex_start)) { rx_last_token = *rx_lex_start; @@ -1253,7 +1711,7 @@ rx_lex (void) } int -rx_error (char * str) +rx_error (const char * str) { int len; @@ -1265,28 +1723,40 @@ rx_error (char * str) } static int -rx_intop (expressionS exp, int nbits) +rx_intop (expressionS exp, int nbits, int opbits) { - long v; + valueT v; + valueT mask, msb; - if (exp.X_op == O_big && nbits == 32) - return 1; - if (exp.X_op != O_constant) + if (exp.X_op == O_big) + { + if (nbits == 32) + return 1; + if (exp.X_add_number == -1) + return 0; + } + else if (exp.X_op != O_constant) return 0; v = exp.X_add_number; + msb = (valueT) 1 << (opbits - 1); + mask = (msb << 1) - 1; + + if ((v & msb) && ! (v & ~mask)) + v -= mask + 1; + switch (nbits) { case 4: - return -0x8 <= v && v <= 0x7; + return v + 0x8 <= 0x7 + 0x8; case 5: - return -0x10 <= v && v <= 0x17; + return v + 0x10 <= 0xf + 0x10; case 8: - return -0x80 <= v && v <= 0x7f; + return v + 0x80 <= 0x7f + 0x80; case 16: - return -0x8000 <= v && v <= 0x7fff; + return v + 0x8000 <= 0x7fff + 0x8000; case 24: - return -0x800000 <= v && v <= 0x7fffff; + return v + 0x800000 <= 0x7fffff + 0x800000; case 32: return 1; default: @@ -1299,7 +1769,7 @@ rx_intop (expressionS exp, int nbits) static int rx_uintop (expressionS exp, int nbits) { - unsigned long v; + valueT v; if (exp.X_op != O_constant) return 0; @@ -1325,7 +1795,7 @@ rx_uintop (expressionS exp, int nbits) static int rx_disp3op (expressionS exp) { - unsigned long v; + valueT v; if (exp.X_op != O_constant) return 0; @@ -1338,7 +1808,7 @@ rx_disp3op (expressionS exp) static int rx_disp5op (expressionS * exp, int msize) { - long v; + valueT v; if (exp->X_op != O_constant) return 0; @@ -1347,13 +1817,13 @@ rx_disp5op (expressionS * exp, int msize) switch (msize) { case BSIZE: - if (0 < v && v <= 31) + if (v <= 31) return 1; break; case WSIZE: if (v & 1) return 0; - if (0 < v && v <= 63) + if (v <= 63) { exp->X_add_number >>= 1; return 1; @@ -1362,7 +1832,7 @@ rx_disp5op (expressionS * exp, int msize) case LSIZE: if (v & 3) return 0; - if (0 < v && v <= 127) + if (v <= 127) { exp->X_add_number >>= 2; return 1; @@ -1405,9 +1875,9 @@ zero_expr (void) } static int -immediate (expressionS exp, int type, int pos) +immediate (expressionS exp, int type, int pos, int bits) { - /* We will emit constants ourself here, so negate them. */ + /* We will emit constants ourselves 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) @@ -1418,27 +1888,32 @@ immediate (expressionS exp, int type, int pos) rx_error (_("sbb cannot use symbolic immediates")); } - if (rx_intop (exp, 8)) + if (pos >= 0 && rx_intop (exp, 8, bits)) { rx_op (exp, 1, type); return 1; } - else if (rx_intop (exp, 16)) + else if (pos >= 0 && rx_intop (exp, 16, bits)) + { + rx_op (exp, 2, type); + return 2; + } + else if (pos >= 0 && rx_uintop (exp, 16) && bits == 16) { rx_op (exp, 2, type); return 2; } - else if (rx_intop (exp, 24)) + else if (pos >= 0 && rx_intop (exp, 24, bits)) { rx_op (exp, 3, type); return 3; } - else if (rx_intop (exp, 32)) + else if (pos < 0 || rx_intop (exp, 32, bits)) { rx_op (exp, 4, type); return 0; } - else if (type == RXREL_SIGNED) + else if (type == RXREL_SIGNED && pos >= 0) { /* This is a symbolic immediate, we will relax it later. */ rx_relax (RX_RELAX_IMM, pos); @@ -1456,7 +1931,7 @@ immediate (expressionS exp, int type, int pos) static int displacement (expressionS exp, int msize) { - int val; + valueT val; int vshift = 0; if (exp.X_op == O_symbol @@ -1482,6 +1957,13 @@ displacement (expressionS exp, int msize) } } + 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")); @@ -1506,6 +1988,11 @@ displacement (expressionS exp, int msize) rx_error (_("long displacement not long-aligned")); vshift = 2; break; + case DSIZE: + if (val & 7) + rx_error (_("double displacement not double-aligned")); + vshift = 3; + break; default: as_bad (_("displacement with unknown size (internal bug?)\n")); break; @@ -1514,18 +2001,18 @@ displacement (expressionS exp, int msize) val >>= vshift; exp.X_add_number = val; - if (0 <= val && val <= 255 ) + if (val <= 255 ) { O1 (exp); return 1; } - if (0 <= val && val <= 65535) + if (val <= 65535) { O2 (exp); return 2; } - if (val < 0) + if ((offsetT) val < 0) rx_error (_("negative displacements not allowed")); else rx_error (_("displacement too large")); @@ -1535,7 +2022,7 @@ displacement (expressionS exp, int msize) static void rtsd_immediate (expressionS exp) { - int val; + valueT val; if (exp.X_op != O_constant) { @@ -1546,10 +2033,51 @@ rtsd_immediate (expressionS exp) if (val & 3) rx_error (_("rtsd size must be multiple of 4")); - if (val < 0 || val > 1020) + if (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) +{ + offsetT val; + + if (exp.X_op != O_constant) + return; + + val = exp.X_add_number; + if (val < minv || val > maxv) + as_warn (_("Value %ld out of range %d..%d"), (long) 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")); +} + +static void +rx_check_v2 (void) +{ + if (rx_cpu < RXV2) + rx_error (_("target CPU type does not support v2 instructions")); +} + +static void +rx_check_v3 (void) +{ + if (rx_cpu < RXV3) + rx_error (_("target CPU type does not support v3 instructions")); +} + +static void +rx_check_dfpu (void) +{ + if (rx_cpu != RXV3FPU) + rx_error (_("target CPU type does not support double float instructions")); +}