aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorYoshinori Sato <ysato@users.sourceforge.jp>2018-12-25 20:52:53 +0900
committerYoshinori Sato <ysato@users.sourceforge.jp>2019-01-05 22:51:41 +0900
commit6a25bee8d049d3b51cea9e10f487fc04c792dd66 (patch)
tree742fe49961d63c6cd241d94e3a7a970e5b75eac2 /gas/config
parent59581069b4d070ab0ac61047177ee119110d678e (diff)
downloadbinutils-6a25bee8d049d3b51cea9e10f487fc04c792dd66.zip
binutils-6a25bee8d049d3b51cea9e10f487fc04c792dd66.tar.gz
binutils-6a25bee8d049d3b51cea9e10f487fc04c792dd66.tar.bz2
RX: gas - Add RXv3 instruction support.
Instruction manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01us0316ej0100-rxv3sm.pdf * config/rx-defs.h (rx_cpu_types): Add type RXV3 and RXV3FPU. (rx_bfield): Add prototype. (rx_post): Likewise. * config/rx-parse.y: Add v3 instructions and Double FPU registers. (DSIZE): Define. (POST): Define. (rx_check_v3): New. check v3 type. (rx_check_dfpu): New. check have double support. (double_condition_table): New. dcmp<cond> contiditon. (check_condition): Multiple condition support. (rx_lex): RXv3 instructions support. Add parse dcmp<cond> instruction and Double FPU registers. (immediate): Disable optimize in dmov #imm case. (displacement): Add double displacement in dmov instraction. * config/tc-rx.c (rx_use_conventional_section_names): Invert default value in rx-*-linux target. (cpu_type): Add additional ELF flags. (cpu_type_list): Add RXv3. (md_parse_option): Refer elf_flags from cpu_type_list. (md_show_usage): Add rxv3 and rxv3-dfpu. (rx_bytesT): Add post byte. (rx_bfield): New. generate bfmov / bfmovz "imm" field. (rx_post): New. Set instruction post byte. (md_assemble): Add post byte. doc/c-rx.texi: Add cpu types. * testsuite/gas/rx/Xtod.d: New. * testsuite/gas/rx/Xtod.sm: New. * testsuite/gas/rx/bfmov.d: New. * testsuite/gas/rx/bfmov.sm: New. * testsuite/gas/rx/dabs.d: New. * testsuite/gas/rx/dabs.sm: New. * testsuite/gas/rx/dadd.d: New. * testsuite/gas/rx/dadd.sm: New. * testsuite/gas/rx/dcmp.d: New. * testsuite/gas/rx/dcmp.sm: New. * testsuite/gas/rx/ddiv.d: New. * testsuite/gas/rx/ddiv.sm: New. * testsuite/gas/rx/dmov.d: New. * testsuite/gas/rx/dmov.sm: New. * testsuite/gas/rx/dmul.d: New. * testsuite/gas/rx/dmul.sm: New. * testsuite/gas/rx/dneg.d: New. * testsuite/gas/rx/dneg.sm: New. * testsuite/gas/rx/dpopm.d: New. * testsuite/gas/rx/dpopm.sm: New. * testsuite/gas/rx/dpushm.d: New. * testsuite/gas/rx/dpushm.sm: New. * testsuite/gas/rx/dround.d: New. * testsuite/gas/rx/dround.sm: New. * testsuite/gas/rx/dsqrt.d: New. * testsuite/gas/rx/dsqrt.sm: New. * testsuite/gas/rx/dsub.d: New. * testsuite/gas/rx/dsub.sm: New. * testsuite/gas/rx/dtoX.d: New. * testsuite/gas/rx/dtoX.sm: New. * testsuite/gas/rx/macros.inc: Add double FPU registers. * testsuite/gas/rx/mvfdc.d: New. * testsuite/gas/rx/mvfdc.sm: New. * testsuite/gas/rx/mvfdr.d: New. * testsuite/gas/rx/mvfdr.sm: New. * testsuite/gas/rx/mvtdc.d: New. * testsuite/gas/rx/mvtdc.sm: New. * testsuite/gas/rx/rstr.d: New. * testsuite/gas/rx/rstr.sm: New. * testsuite/gas/rx/rx.exp: Use rxv3-dfpu option. * testsuite/gas/rx/save.d: New. * testsuite/gas/rx/save.sm: New. * testsuite/gas/rx/xor.d: New. * testsuite/gas/rx/xor.sm: Add pattern.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/rx-defs.h6
-rw-r--r--gas/config/rx-parse.y325
-rw-r--r--gas/config/tc-rx.c57
3 files changed, 338 insertions, 50 deletions
diff --git a/gas/config/rx-defs.h b/gas/config/rx-defs.h
index 508e6cf..9d114f5 100644
--- a/gas/config/rx-defs.h
+++ b/gas/config/rx-defs.h
@@ -39,7 +39,9 @@ enum rx_cpu_types
RX610,
RX200,
RX100,
- RXV2
+ RXV2,
+ RXV3,
+ RXV3FPU,
};
extern int rx_pid_register;
@@ -57,6 +59,7 @@ extern void rx_op (expressionS, int, int);
extern void rx_disp3 (expressionS, int);
extern void rx_field5s (expressionS);
extern void rx_field5s2 (expressionS);
+extern void rx_bfield (expressionS, expressionS, expressionS);
extern void rx_relax (int, int);
extern void rx_linkrelax_dsp (int);
extern void rx_linkrelax_imm (int);
@@ -64,6 +67,7 @@ extern void rx_linkrelax_branch (void);
extern int rx_parse (void);
extern int rx_wrap (void);
extern void rx_note_string_insn_use (void);
+extern void rx_post (char);
extern char * rx_lex_start;
extern char * rx_lex_end;
diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y
index ab5b7e7..4a5ee15 100644
--- a/gas/config/rx-parse.y
+++ b/gas/config/rx-parse.y
@@ -33,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 };
@@ -90,6 +91,8 @@ 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 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 IMM(v,pos) IMM_ (v, pos, 32)
@@ -116,6 +119,8 @@ 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;
@@ -137,36 +142,37 @@ static int sub_op2;
expressionS exp;
}
-%type <regno> REG FLAG CREG BCND BMCND SCCND ACC
+%type <regno> REG FLAG CREG BCND BMCND SCCND ACC DREG DREGH DREGL DCREG DCMP
%type <regno> flag bwl bw memex
%type <exp> EXPR disp
-%token REG FLAG CREG ACC
+%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 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 FTOI FTOU
-%token INT ITOF
+%token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOD FTOI FTOU
+%token INT ITOD ITOF
%token JMP JSR
%token MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL
-%token MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVTACGU
-%token MVTACHI MVTACLO MVTC MVTIPL
+%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 RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND
-%token RTE RTFI RTS RTSD
-%token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
+%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 UTOF
+%token UTOD UTOF
%token WAIT
%token XCHG XOR
@@ -630,7 +636,7 @@ 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
+ | 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
@@ -738,17 +744,17 @@ statement :
| 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) && $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"));}
@@ -903,6 +909,99 @@ statement :
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); }
+
+/* ---------------------------------------------------------------------- */
;
@@ -1048,6 +1147,35 @@ mvfa_op
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 (); }
@@ -1135,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 },
@@ -1142,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 },
@@ -1160,6 +1349,8 @@ token_table[] =
{ "and", AND_, IS_OPCODE },
OPC(BCLR),
OPC(BCND),
+ OPC(BFMOV),
+ OPC(BFMOVZ),
OPC(BMCND),
OPC(BNOT),
OPC(BRA),
@@ -1169,9 +1360,23 @@ 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),
@@ -1185,10 +1390,12 @@ token_table[] =
OPC(FMUL),
OPC(FREIT),
OPC(FSQRT),
+ OPC(FTOD),
OPC(FTOU),
OPC(FSUB),
OPC(FTOI),
OPC(INT),
+ OPC(ITOD),
OPC(ITOF),
OPC(JMP),
OPC(JSR),
@@ -1197,6 +1404,9 @@ token_table[] =
OPC(MVFACMI),
OPC(MVFACLO),
OPC(MVFC),
+ OPC(MVFDC),
+ OPC(MVFDR),
+ OPC(MVTDC),
OPC(MVTACGU),
OPC(MVTACHI),
OPC(MVTACLO),
@@ -1243,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),
@@ -1267,6 +1479,7 @@ token_table[] =
OPC(SUNTIL),
OPC(SWHILE),
OPC(TST),
+ OPC(UTOD),
OPC(UTOF),
OPC(WAIT),
OPC(XCHG),
@@ -1289,12 +1502,13 @@ condition_opcode_table[] =
#define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
-static struct
+struct condition_symbol
{
const char * string;
int val;
-}
-condition_table[] =
+};
+
+static struct condition_symbol condition_table[] =
{
{ "z", 0 },
{ "eq", 0 },
@@ -1314,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)
@@ -1333,7 +1556,7 @@ rx_lex_init (char * beginning, char * ending)
}
static int
-check_condition (const char * base)
+check_condition (const char * base, struct condition_symbol *t, unsigned int num)
{
char * cp;
unsigned int i;
@@ -1343,11 +1566,11 @@ check_condition (const 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;
}
}
@@ -1408,14 +1631,25 @@ rx_lex (void)
}
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
@@ -1446,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;
@@ -1654,32 +1888,32 @@ immediate (expressionS exp, int type, int pos, int bits)
rx_error (_("sbb cannot use symbolic immediates"));
}
- if (rx_intop (exp, 8, bits))
+ if (pos >= 0 && rx_intop (exp, 8, bits))
{
rx_op (exp, 1, type);
return 1;
}
- else if (rx_intop (exp, 16, bits))
+ else if (pos >= 0 && rx_intop (exp, 16, bits))
{
rx_op (exp, 2, type);
return 2;
}
- else if (rx_uintop (exp, 16) && bits == 16)
+ else if (pos >= 0 && rx_uintop (exp, 16) && bits == 16)
{
rx_op (exp, 2, type);
return 2;
}
- else if (rx_intop (exp, 24, bits))
+ else if (pos >= 0 && rx_intop (exp, 24, bits))
{
rx_op (exp, 3, type);
return 3;
}
- else if (rx_intop (exp, 32, bits))
+ 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);
@@ -1754,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;
@@ -1828,3 +2067,17 @@ 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"));
+}
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c
index ee2bf40..0a44fc4 100644
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -44,7 +44,11 @@ const char FLT_CHARS[] = "dD";
/* ELF flags to set in the output file header. */
static int elf_flags = E_FLAG_RX_ABI;
+#ifndef TE_LINUX
bfd_boolean rx_use_conventional_section_names = FALSE;
+#else
+bfd_boolean rx_use_conventional_section_names = TRUE;
+#endif
static bfd_boolean rx_use_small_data_limit = FALSE;
static bfd_boolean rx_pid_mode = FALSE;
@@ -108,15 +112,18 @@ struct cpu_type
{
const char *cpu_name;
enum rx_cpu_types type;
+ int flag;
};
struct cpu_type cpu_type_list[] =
{
- {"rx100",RX100},
- {"rx200",RX200},
- {"rx600",RX600},
- {"rx610",RX610},
- {"rxv2",RXV2}
+ {"rx100", RX100, 0},
+ {"rx200", RX200, 0},
+ {"rx600", RX600, 0},
+ {"rx610", RX610, 0},
+ {"rxv2", RXV2, E_FLAG_RX_V2},
+ {"rxv3", RXV3, E_FLAG_RX_V3},
+ {"rxv3-dfpu", RXV3FPU, E_FLAG_RX_V3},
};
int
@@ -181,8 +188,7 @@ md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
if (strcasecmp (arg, cpu_type_list[i].cpu_name) == 0)
{
rx_cpu = cpu_type_list[i].type;
- if (rx_cpu == RXV2)
- elf_flags |= E_FLAG_RX_V2;
+ elf_flags |= cpu_type_list[i].flag;
return 1;
}
}
@@ -212,7 +218,7 @@ md_show_usage (FILE * stream)
fprintf (stream, _(" --mrelax\n"));
fprintf (stream, _(" --mpid\n"));
fprintf (stream, _(" --mint-register=<value>\n"));
- fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2>\n"));
+ fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2|rxv3|rxv3-dfpu>\n"));
fprintf (stream, _(" --mno-allow-string-insns"));
}
@@ -723,6 +729,8 @@ typedef struct rx_bytesT
fixS * fixP;
} fixups[2];
int n_fixups;
+ char post[1];
+ int n_post;
struct
{
char type;
@@ -947,6 +955,24 @@ rx_field5s2 (expressionS exp)
rx_bytes.base[1] |= (val ) & 0x0f;
}
+void
+rx_bfield(expressionS s, expressionS d, expressionS w)
+{
+ int slsb = s.X_add_number;
+ int dlsb = d.X_add_number;
+ int width = w.X_add_number;
+ unsigned int imm =
+ (((dlsb + width) & 0x1f) << 10 | (dlsb << 5) |
+ ((dlsb - slsb) & 0x1f));
+ if ((slsb + width) > 32)
+ as_warn (_("Value %d and %d out of range"), slsb, width);
+ if ((dlsb + width) > 32)
+ as_warn (_("Value %d and %d out of range"), dlsb, width);
+ rx_bytes.ops[0] = imm & 0xff;
+ rx_bytes.ops[1] = (imm >> 8);
+ rx_bytes.n_ops = 2;
+}
+
#define OP(x) rx_bytes.ops[rx_bytes.n_ops++] = (x)
#define F_PRECISION 2
@@ -1008,6 +1034,11 @@ rx_op (expressionS exp, int nbytes, int type)
}
}
+void rx_post(char byte)
+{
+ rx_bytes.post[rx_bytes.n_post++] = byte;
+}
+
int
rx_wrap (void)
{
@@ -1133,21 +1164,22 @@ md_assemble (char * str)
0 /* offset */,
0 /* opcode */);
frag_then->fr_opcode = bytes;
- frag_then->fr_fix += rx_bytes.n_base + rx_bytes.n_ops;
- frag_then->fr_subtype = rx_bytes.n_base + rx_bytes.n_ops;
+ frag_then->fr_fix += rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
+ frag_then->fr_subtype = rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
}
else
{
- bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops);
+ bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post);
frag_then = frag_now;
if (fetchalign_bytes)
- fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops;
+ fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops + rx_bytes.n_post;
}
fetchalign_bytes = NULL;
APPEND (base, n_base);
APPEND (ops, n_ops);
+ APPEND (post, n_post);
if (rx_bytes.link_relax && rx_bytes.n_fixups)
{
@@ -1196,7 +1228,6 @@ md_assemble (char * str)
if (frag_then->tc_frag_data)
frag_then->tc_frag_data->fixups[i].fixP = f;
}
-
dwarf2_emit_insn (idx);
}