This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH][RX] (1/3) Add RXv2 instruction support
- From: Yoshinori Sato <ysato at users dot sourceforge dot jp>
- To: binutils at sourceware dot org
- Date: Mon, 16 Mar 2015 16:27:44 +0900
- Subject: [PATCH][RX] (1/3) Add RXv2 instruction support
- Authentication-results: sourceware.org; auth=none
Hello.
Several instructions were added to the RXv2 (RX64M and RX71M) CPU.
http://documentation.renesas.com/doc/products/mpumcu/doc/rx_family/r01us0071ej0100_rxv2sm.pdf
This patch is supported new instruction for RX target.
Thanks.
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 09cef3d..a26d6cf 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+2015-03-16 Yoshinori Sato <ysato@users.sourceforge.jp>
+
+ * config/rx-defs.h (rx_cpu_types): Add RXV2.
+ * config/rx-parse.y: Add RXv2 instructions.
+ * config/tc-rx.c (md_parse_option): Add rxv2 option.
+ (md_show_usage): Likewise.
+ * doc/c-rx.texi: Likewise.
+
2015-03-13 Jiong Wang <jiong.wang@arm.com>
* config/tc-aarch64.c (warn_unpredictable_ldst): Don't warn on reg
diff --git a/gas/config/rx-defs.h b/gas/config/rx-defs.h
index 2a15b6c..93deca9 100644
--- a/gas/config/rx-defs.h
+++ b/gas/config/rx-defs.h
@@ -38,7 +38,8 @@ enum rx_cpu_types
RX600,
RX610,
RX200,
- RX100
+ RX100,
+ RXV2
};
extern int rx_pid_register;
diff --git a/gas/config/rx-parse.y b/gas/config/rx-parse.y
index 645ec99..656a258 100644
--- a/gas/config/rx-parse.y
+++ b/gas/config/rx-parse.y
@@ -115,6 +115,7 @@ 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 int need_flag = 0;
static int rx_in_brackets = 0;
@@ -136,11 +137,11 @@ static int sub_op2;
expressionS exp;
}
-%type <regno> REG FLAG CREG BCND BMCND SCCND
+%type <regno> REG FLAG CREG BCND BMCND SCCND ACC
%type <regno> flag bwl bw memex
%type <exp> EXPR disp
-%token REG FLAG CREG
+%token REG FLAG CREG ACC
%token EXPR UNKNOWN_OPCODE IS_OPCODE
@@ -150,19 +151,22 @@ static int sub_op2;
%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 EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU
+%token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOI FTOU
%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 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 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 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 SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
%token TST
+%token UTOF
%token WAIT
%token XCHG XOR
@@ -466,7 +470,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")); }
@@ -474,7 +480,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")); }
@@ -615,8 +623,8 @@ statement :
| 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
+ | STZ { sub_op = 14; sub_op2 = 0; } op_dp20_ri
+ | STNZ { sub_op = 15; sub_op2 = 1; } op_dp20_ri
/* ---------------------------------------------------------------------- */
@@ -624,6 +632,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
/* ---------------------------------------------------------------------- */
@@ -647,16 +656,21 @@ statement :
/* ---------------------------------------------------------------------- */
- | 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
{ id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
| SCCND bwl disp '[' REG ']'
@@ -678,27 +692,41 @@ 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)
@@ -707,6 +735,14 @@ statement :
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)
+ ;
+ else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
+ F (1, 19, 1);
+ else
+ as_bad (_("RACW expects #1 or #2"));}
/* ---------------------------------------------------------------------- */
@@ -739,13 +775,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); }
/* ---------------------------------------------------------------------- */
@@ -757,7 +797,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); }
/* ---------------------------------------------------------------------- */
@@ -797,6 +839,59 @@ statement :
/* ---------------------------------------------------------------------- */
+ | 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"));}
;
/* ====================================================================== */
@@ -856,7 +951,18 @@ op_dp20_rr
{ 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); }
@@ -880,6 +986,16 @@ 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
: { rx_check_float_support (); }
@@ -897,6 +1013,29 @@ float2_op_ni
{ 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"));}
+ ;
+
/* ====================================================================== */
disp : { $$ = zero_expr (); }
@@ -976,6 +1115,7 @@ token_table[] =
{ "isp", CREG, 10 },
{ "fintv", CREG, 11 },
{ "intb", CREG, 12 },
+ { "extb", CREG, 13 },
{ "pbp", CREG, 16 },
{ "pben", CREG, 17 },
@@ -998,6 +1138,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),
@@ -1019,35 +1162,49 @@ token_table[] =
OPC(DIVU),
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(FTOU),
OPC(FSUB),
OPC(FTOI),
OPC(INT),
OPC(ITOF),
OPC(JMP),
OPC(JSR),
+ OPC(MVFACGU),
OPC(MVFACHI),
OPC(MVFACMI),
OPC(MVFACLO),
OPC(MVFC),
+ 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),
@@ -1061,7 +1218,10 @@ token_table[] =
OPC(PUSHA),
OPC(PUSHC),
OPC(PUSHM),
+ OPC(RACL),
OPC(RACW),
+ OPC(RDACL),
+ OPC(RDACW),
OPC(REIT),
OPC(REVL),
OPC(REVW),
@@ -1095,6 +1255,7 @@ token_table[] =
OPC(SUNTIL),
OPC(SWHILE),
OPC(TST),
+ OPC(UTOF),
OPC(WAIT),
OPC(XCHG),
OPC(XOR),
@@ -1643,3 +1804,10 @@ 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"));
+}
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c
index 2dec69f..6eaeef6 100644
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -104,6 +104,20 @@ struct option md_longopts[] =
};
size_t md_longopts_size = sizeof (md_longopts);
+struct cpu_type{
+ char *cpu_name;
+ int type;
+};
+
+struct cpu_type cpu_type_list[] =
+{
+ {"rx100",RX100},
+ {"rx200",RX200},
+ {"rx600",RX600},
+ {"rx610",RX610},
+ {"rxv2",RXV2}
+};
+
int
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
{
@@ -159,20 +173,19 @@ md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
return 1;
case OPTION_CPU:
- if (strcasecmp (arg, "rx100") == 0)
- rx_cpu = RX100;
- else if (strcasecmp (arg, "rx200") == 0)
- rx_cpu = RX200;
- else if (strcasecmp (arg, "rx600") == 0)
- rx_cpu = RX600;
- else if (strcasecmp (arg, "rx610") == 0)
- rx_cpu = RX610;
- else
- {
- as_warn (_("unrecognised RX CPU type %s"), arg);
- break;
- }
- return 1;
+ {
+ unsigned int i;
+ for (i = 0; i < sizeof(cpu_type_list)/sizeof(struct cpu_type); i++)
+ {
+ if (strcasecmp(arg, cpu_type_list[i].cpu_name) == 0)
+ {
+ rx_cpu = cpu_type_list[i].type;
+ return 1;
+ }
+ }
+ as_warn (_("unrecognised RX CPU type %s"), arg);
+ break;
+ }
}
return 0;
}
@@ -191,7 +204,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>\n"));
+ fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2>\n"));
}
static void
diff --git a/gas/doc/c-rx.texi b/gas/doc/c-rx.texi
index 0eddb08..a96dd86 100644
--- a/gas/doc/c-rx.texi
+++ b/gas/doc/c-rx.texi
@@ -108,9 +108,10 @@ alignments. This option is the default.
@cindex @samp{-mcpu=}
@item -mcpu=@var{name}
This option tells the assembler the target CPU type. Currently the
-@code{rx200}, @code{rx600} and @code{rx610} are recognised as valid
-cpu names. Attempting to assemble an instruction not supported by the
-indicated cpu type will result in an error message being generated.
+@code{rx100}, @code{rx200}, @code{rx600}, @code{rx610} and @code{rxv2}
+are recognised as validcpu names. Attempting to assemble an instruction
+not supported by theindicated cpu type will result in an error message
+being generated.
@end table