diff options
Diffstat (limited to 'toolchain/binutils/patches')
-rw-r--r-- | toolchain/binutils/patches/2.20.1/902-rlx.patch | 1985 |
1 files changed, 1985 insertions, 0 deletions
diff --git a/toolchain/binutils/patches/2.20.1/902-rlx.patch b/toolchain/binutils/patches/2.20.1/902-rlx.patch new file mode 100644 index 000000000..53cb9a65e --- /dev/null +++ b/toolchain/binutils/patches/2.20.1/902-rlx.patch @@ -0,0 +1,1985 @@ +Index: binutils/opcodes/mips-opc.c +=================================================================== +--- binutils.orig/opcodes/mips-opc.c ++++ binutils/opcodes/mips-opc.c +@@ -163,6 +163,18 @@ + #define D33 INSN_DSPR2 + #define D64 INSN_DSP64 + ++#define RLX0 INSN_4180 ++#define RLX1 INSN_5280 ++#define RLX2 INSN_4181|INSN_5181 ++#define RLX3 INSN_4281|INSN_5281 ++ ++#define RLXA (RLX0|RLX1|RLX2|RLX3) ++#define RLXB (RLX1|RLX2|RLX3) ++ ++#define RAD1 INSN_5181|INSN_5280|INSN_5281 ++#define RAD2 INSN_5281 ++ ++ + /* MIPS MT ASE support. */ + #define MT32 INSN_MT + +@@ -188,7 +200,7 @@ const struct mips_opcode mips_builtin_op + {"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4_32|G3 }, + {"prefx", "h,t(b)", 0x4c00000f, 0xfc0007ff, RD_b|RD_t|FP_S, 0, I4_33 }, + {"nop", "", 0x00000000, 0xffffffff, 0, INSN2_ALIAS, I1 }, /* sll */ +-{"ssnop", "", 0x00000040, 0xffffffff, 0, INSN2_ALIAS, I32|N55 }, /* sll */ ++{"ssnop", "", 0x00000040, 0xffffffff, 0, INSN2_ALIAS, I32|N55|RLX3 }, /* sll */ + {"ehb", "", 0x000000c0, 0xffffffff, 0, INSN2_ALIAS, I33 }, /* sll */ + {"li", "t,j", 0x24000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* addiu */ + {"li", "t,i", 0x34000000, 0xffe00000, WR_t, INSN2_ALIAS, I1 }, /* ori */ +@@ -509,14 +521,16 @@ const struct mips_opcode mips_builtin_op + {"flushd", "", 0xbc020000, 0xffffffff, 0, 0, L1 }, + {"flushid", "", 0xbc030000, 0xffffffff, 0, 0, L1 }, + {"wb", "o(b)", 0xbc040000, 0xfc1f0000, SM|RD_b, 0, L1 }, +-{"cache", "k,o(b)", 0xbc000000, 0xfc000000, RD_b, 0, I3_32|T3}, ++{"cache", "k,o(b)", 0xbc000000, 0xfc000000, RD_b, 0, I3_32|T3|RLXB}, + {"cache", "k,A(b)", 0, (int) M_CACHE_AB, INSN_MACRO, 0, I3_32|T3}, + {"ceil.l.d", "D,S", 0x4620000a, 0xffff003f, WR_D|RD_S|FP_D, 0, I3_33 }, + {"ceil.l.s", "D,S", 0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3_33 }, + {"ceil.w.d", "D,S", 0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 }, + {"ceil.w.s", "D,S", 0x4600000e, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 }, + {"cfc0", "t,G", 0x40400000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 }, ++{"cfc0", "t,G,#H", 0x40400000, 0xffe007c0, LCD|WR_t|RD_C0, 0, RLX3 }, + {"cfc1", "t,G", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, ++{"cfc1", "t,G,#H", 0x44400000, 0xffe007c0, LCD|WR_t|RD_C1|FP_S, 0, RLX3 }, + {"cfc1", "t,S", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 }, + /* cfc2 is at the bottom of the table. */ + /* cfc3 is at the bottom of the table. */ +@@ -529,7 +543,9 @@ const struct mips_opcode mips_builtin_op + {"clo", "U,s", 0x70000021, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, + {"clz", "U,s", 0x70000020, 0xfc0007ff, WR_d|WR_t|RD_s, 0, I32|N55 }, + {"ctc0", "t,G", 0x40c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, ++{"ctc0", "t,G,#H", 0x40c00000, 0xffe007c0, COD|RD_t|WR_CC, 0, RLX3 }, + {"ctc1", "t,G", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, ++{"ctc1", "t,G,#H", 0x44c00000, 0xffe007c0, COD|RD_t|WR_CC|FP_S, 0, RLX3 }, + {"ctc1", "t,S", 0x44c00000, 0xffe007ff, COD|RD_t|WR_CC|FP_S, 0, I1 }, + /* ctc2 is at the bottom of the table. */ + /* ctc3 is at the bottom of the table. */ +@@ -567,7 +583,7 @@ const struct mips_opcode mips_builtin_op + /* dctr and dctw are used on the r5000. */ + {"dctr", "o(b)", 0xbc050000, 0xfc1f0000, RD_b, 0, I3 }, + {"dctw", "o(b)", 0xbc090000, 0xfc1f0000, RD_b, 0, I3 }, +-{"deret", "", 0x4200001f, 0xffffffff, 0, 0, I32|G2 }, ++{"deret", "", 0x4200001f, 0xffffffff, 0, 0, I32|G2|RLXA }, + {"dext", "t,r,I,+I", 0, (int) M_DEXT, INSN_MACRO, 0, I65 }, + {"dext", "t,r,+A,+C", 0x7c000003, 0xfc00003f, WR_t|RD_s, 0, I65 }, + {"dextm", "t,r,+A,+G", 0x7c000001, 0xfc00003f, WR_t|RD_s, 0, I65 }, +@@ -777,8 +793,8 @@ const struct mips_opcode mips_builtin_op + {"li.d", "T,L", 0, (int) M_LI_DD, INSN_MACRO, INSN2_M_FP_D, I1 }, + {"li.s", "t,f", 0, (int) M_LI_S, INSN_MACRO, INSN2_M_FP_S, I1 }, + {"li.s", "T,l", 0, (int) M_LI_SS, INSN_MACRO, INSN2_M_FP_S, I1 }, +-{"ll", "t,o(b)", 0xc0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2 }, +-{"ll", "t,A(b)", 0, (int) M_LL_AB, INSN_MACRO, 0, I2 }, ++{"ll", "t,o(b)", 0xc0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I2|RLX2|RLX3 }, ++{"ll", "t,A(b)", 0, (int) M_LL_AB, INSN_MACRO, 0, I2|RLX2|RLX3 }, + {"lld", "t,o(b)", 0xd0000000, 0xfc000000, LDD|RD_b|WR_t, 0, I3 }, + {"lld", "t,A(b)", 0, (int) M_LLD_AB, INSN_MACRO, 0, I3 }, + {"lui", "t,u", 0x3c000000, 0xffe00000, WR_t, 0, I1 }, +@@ -822,8 +838,8 @@ const struct mips_opcode mips_builtin_op + {"maccu", "d,s,t", 0x00000068, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, + {"maccu", "d,s,t", 0x00000159, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N5 }, + {"maccus", "d,s,t", 0x00000468, 0xfc0007ff, RD_s|RD_t|WR_HILO|WR_d, 0, N412 }, +-{"mad", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, +-{"madu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3 }, ++{"mad", "s,t", 0x70000000, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3|RLXA }, ++{"madu", "s,t", 0x70000001, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, P3|RLXA }, + {"madd.d", "D,R,S,T", 0x4c000021, 0xfc00003f, RD_R|RD_S|RD_T|WR_D|FP_D, 0, I4_33 }, + {"madd.d", "D,S,T", 0x46200018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, + {"madd.d", "D,S,T", 0x72200018, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, +@@ -871,10 +887,12 @@ const struct mips_opcode mips_builtin_op + {"mftlo", "d,*", 0x41000021, 0xfff307ff, TRAP|WR_d|RD_a, 0, MT32 }, + {"mftr", "d,t,!,H,$", 0x41000000, 0xffe007c8, TRAP|WR_d, 0, MT32 }, + {"mfc0", "t,G", 0x40000000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1|IOCT }, ++{"mfc0", "t,G,#H", 0x40000000, 0xffe007c0, LCD|WR_t|RD_C0, 0, RLX3 }, + {"mfc0", "t,+D", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32|IOCT}, + {"mfc0", "t,G,H", 0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I32|IOCT}, + {"mfc1", "t,S", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, + {"mfc1", "t,G", 0x44000000, 0xffe007ff, LCD|WR_t|RD_S|FP_S, 0, I1 }, ++{"mfc1", "t,G,#H", 0x44000000, 0xffe007c0, LCD|WR_t|RD_S|FP_S, 0, RLX3 }, + {"mfhc1", "t,S", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, + {"mfhc1", "t,G", 0x44600000, 0xffe007ff, LCD|WR_t|RD_S|FP_D, 0, I33 }, + /* mfc2 is at the bottom of the table. */ +@@ -902,7 +920,7 @@ const struct mips_opcode mips_builtin_op + {"movf.l", "X,Y,N", 0x46a00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, + {"movf.s", "D,S,N", 0x46000011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4_32 }, + {"movf.ps", "D,S,N", 0x46c00011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5_33 }, +-{"movn", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F }, ++{"movn", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F|RLXB }, + {"movnz", "d,v,t", 0x0000000b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL2E|IL2F }, + {"ffc", "d,v", 0x0000000b, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, + {"movn.d", "D,S,t", 0x46200013, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4_32 }, +@@ -916,7 +934,7 @@ const struct mips_opcode mips_builtin_op + {"movt.l", "X,Y,N", 0x46a10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, MX|SB1 }, + {"movt.s", "D,S,N", 0x46010011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_S, 0, I4_32 }, + {"movt.ps", "D,S,N", 0x46c10011, 0xffe3003f, WR_D|RD_S|RD_CC|FP_D, 0, I5_33 }, +-{"movz", "d,v,t", 0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F }, ++{"movz", "d,v,t", 0x0000000a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I4_32|IL2E|IL2F|RLXB }, + {"ffs", "d,v", 0x0000000a, 0xfc1f07ff, WR_d|RD_s, 0, L1 }, + {"movz.d", "D,S,t", 0x46200012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, I4_32 }, + {"movz.l", "D,S,t", 0x46a00012, 0xffe0003f, WR_D|RD_S|RD_t|FP_D, 0, MX|SB1 }, +@@ -944,17 +962,19 @@ const struct mips_opcode mips_builtin_op + {"msub.ps", "D,S,T", 0x45600019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2E }, + {"msub.ps", "D,S,T", 0x71600019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, IL2F }, + {"msub", "s,t", 0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +-{"msub", "s,t", 0x70000004, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, ++{"msub", "s,t", 0x70000004, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55|RLXA }, + {"msub", "7,s,t", 0x70000004, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, + {"msubu", "s,t", 0x0000001f, 0xfc00ffff, RD_s|RD_t|WR_HILO, 0, L1 }, +-{"msubu", "s,t", 0x70000005, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55 }, ++{"msubu", "s,t", 0x70000005, 0xfc00ffff, RD_s|RD_t|MOD_HILO, 0, I32|N55|RLXA }, + {"msubu", "7,s,t", 0x70000005, 0xfc00e7ff, MOD_a|RD_s|RD_t, 0, D33 }, + {"mtpc", "t,P", 0x4080c801, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, + {"mtps", "t,P", 0x4080c800, 0xffe0ffc1, COD|RD_t|WR_C0, 0, M1|N5 }, + {"mtc0", "t,G", 0x40800000, 0xffe007ff, COD|RD_t|WR_C0|WR_CC, 0, I1|IOCT }, ++{"mtc0", "t,G,#H", 0x40800000, 0xffe007c0, COD|RD_t|WR_C0|WR_CC, 0, RLX3 }, + {"mtc0", "t,+D", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32|IOCT}, + {"mtc0", "t,G,H", 0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I32|IOCT}, + {"mtc1", "t,S", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, ++{"mtc1", "t,G,#H", 0x44800000, 0xffe007c0, COD|RD_t|WR_S|FP_S, 0, RLX3 }, + {"mtc1", "t,G", 0x44800000, 0xffe007ff, COD|RD_t|WR_S|FP_S, 0, I1 }, + {"mthc1", "t,S", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, + {"mthc1", "t,G", 0x44e00000, 0xffe007ff, COD|RD_t|WR_S|FP_D, 0, I33 }, +@@ -1172,8 +1192,8 @@ const struct mips_opcode mips_builtin_op + {"rzu.qh", "X,Q", 0x78200020, 0xfc20f83f, WR_D|RD_T|FP_D, RD_MACC, MX }, + {"sb", "t,o(b)", 0xa0000000, 0xfc000000, SM|RD_t|RD_b, 0, I1 }, + {"sb", "t,A(b)", 0, (int) M_SB_AB, INSN_MACRO, 0, I1 }, +-{"sc", "t,o(b)", 0xe0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I2 }, +-{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, 0, I2 }, ++{"sc", "t,o(b)", 0xe0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I2|RLX2|RLX3 }, ++{"sc", "t,A(b)", 0, (int) M_SC_AB, INSN_MACRO, 0, I2|RLX2|RLX3 }, + {"scd", "t,o(b)", 0xf0000000, 0xfc000000, SM|RD_t|WR_t|RD_b, 0, I3 }, + {"scd", "t,A(b)", 0, (int) M_SCD_AB, INSN_MACRO, 0, I3 }, + {"sd", "t,o(b)", 0xfc000000, 0xfc000000, SM|RD_t|RD_b, 0, I3 }, +@@ -1182,8 +1202,8 @@ const struct mips_opcode mips_builtin_op + {"sdbbp", "", 0x0000000e, 0xffffffff, TRAP, 0, G2 }, + {"sdbbp", "c", 0x0000000e, 0xfc00ffff, TRAP, 0, G2 }, + {"sdbbp", "c,q", 0x0000000e, 0xfc00003f, TRAP, 0, G2 }, +-{"sdbbp", "", 0x7000003f, 0xffffffff, TRAP, 0, I32 }, +-{"sdbbp", "B", 0x7000003f, 0xfc00003f, TRAP, 0, I32 }, ++{"sdbbp", "", 0x7000003f, 0xffffffff, TRAP, 0, I32|RLXA }, ++{"sdbbp", "B", 0x7000003f, 0xfc00003f, TRAP, 0, I32|RLXA }, + {"sdc1", "T,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, + {"sdc1", "E,o(b)", 0xf4000000, 0xfc000000, SM|RD_T|RD_b|FP_D, 0, I2 }, + {"sdc1", "T,A(b)", 0, (int) M_SDC1_AB, INSN_MACRO, INSN2_M_FP_D, I2 }, +@@ -1338,7 +1358,8 @@ const struct mips_opcode mips_builtin_op + {"syncs", "", 0x0000018f, 0xffffffff, INSN_SYNC, 0, IOCT }, + {"syncw", "", 0x0000010f, 0xffffffff, INSN_SYNC, 0, IOCT }, + {"syncws", "", 0x0000014f, 0xffffffff, INSN_SYNC, 0, IOCT }, +-{"sync", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2|G1 }, ++{"sync", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2|G1|RLX3 }, ++{"sync", "#I", 0x0000000f, 0xfffff83f, INSN_SYNC, 0, RLX3 }, + {"sync", "1", 0x0000000f, 0xfffff83f, INSN_SYNC, 0, I32 }, + {"sync.p", "", 0x0000040f, 0xffffffff, INSN_SYNC, 0, I2 }, + {"sync.l", "", 0x0000000f, 0xffffffff, INSN_SYNC, 0, I2 }, +@@ -1433,26 +1454,32 @@ const struct mips_opcode mips_builtin_op + {"udi0", "s,t,+2", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi0", "s,+3", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi0", "+4", 0x70000010, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi0", "d,v,t", 0x00000038, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi1", "s,t,d,+1",0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi1", "s,t,+2", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi1", "s,+3", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi1", "+4", 0x70000011, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi1", "d,v,t", 0x0000003a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi2", "s,t,d,+1",0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi2", "s,t,+2", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi2", "s,+3", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi2", "+4", 0x70000012, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi2", "d,v,t", 0x0000003b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi3", "s,t,d,+1",0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi3", "s,t,+2", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi3", "s,+3", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi3", "+4", 0x70000013, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi3", "d,v,t", 0x0000003c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi4", "s,t,d,+1",0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi4", "s,t,+2", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi4", "s,+3", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi4", "+4", 0x70000014, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi4", "d,v,t", 0x0000003e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi5", "s,t,d,+1",0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi5", "s,t,+2", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi5", "s,+3", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi5", "+4", 0x70000015, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, ++{"udi5", "d,v,t", 0x0000003f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, RLXB }, + {"udi6", "s,t,d,+1",0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi6", "s,t,+2", 0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, + {"udi6", "s,+3", 0x70000016, 0xfc00003f, WR_d|RD_s|RD_t, 0, I33 }, +@@ -1505,7 +1532,9 @@ const struct mips_opcode mips_builtin_op + {"bc2tl", "p", 0x49030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, + {"bc2tl", "N,p", 0x49030000, 0xffe30000, CBL|RD_CC, 0, I32 }, + {"cfc2", "t,G", 0x48400000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, ++{"cfc2", "t,G,#H", 0x48400000, 0xffe007c0, LCD|WR_t|RD_C2, 0, RLX3 }, + {"ctc2", "t,G", 0x48c00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, ++{"ctc2", "t,G,#H", 0x48c00000, 0xffe007c0, COD|RD_t|WR_CC, 0, RLX3 }, + {"dmfc2", "t,i", 0x48200000, 0xffe00000, LCD|WR_t|RD_C2, 0, IOCT }, + {"dmfc2", "t,G", 0x48200000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I3 }, + {"dmfc2", "t,G,H", 0x48200000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I64 }, +@@ -1513,11 +1542,13 @@ const struct mips_opcode mips_builtin_op + {"dmtc2", "t,G", 0x48a00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I3 }, + {"dmtc2", "t,G,H", 0x48a00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I64 }, + {"mfc2", "t,G", 0x48000000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I1 }, ++{"mfc2", "t,G,#H", 0x48000000, 0xffe007c0, LCD|WR_t|RD_C2, 0, RLX3 }, + {"mfc2", "t,G,H", 0x48000000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I32 }, + {"mfhc2", "t,G", 0x48600000, 0xffe007ff, LCD|WR_t|RD_C2, 0, I33 }, + {"mfhc2", "t,G,H", 0x48600000, 0xffe007f8, LCD|WR_t|RD_C2, 0, I33 }, + {"mfhc2", "t,i", 0x48600000, 0xffe00000, LCD|WR_t|RD_C2, 0, I33 }, + {"mtc2", "t,G", 0x48800000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I1 }, ++{"mtc2", "t,G,#H", 0x48800000, 0xffe007c0, COD|RD_t|WR_C2|WR_CC, 0, RLX3 }, + {"mtc2", "t,G,H", 0x48800000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I32 }, + {"mthc2", "t,G", 0x48e00000, 0xffe007ff, COD|RD_t|WR_C2|WR_CC, 0, I33 }, + {"mthc2", "t,G,H", 0x48e00000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC, 0, I33 }, +@@ -1530,12 +1561,16 @@ const struct mips_opcode mips_builtin_op + {"bc3t", "p", 0x4d010000, 0xffff0000, CBD|RD_CC, 0, I1 }, + {"bc3tl", "p", 0x4d030000, 0xffff0000, CBL|RD_CC, 0, I2|T3 }, + {"cfc3", "t,G", 0x4c400000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, ++{"cfc3", "t,G,#H", 0x4c400000, 0xffe007c0, LCD|WR_t|RD_C3, 0, RLX3 }, + {"ctc3", "t,G", 0x4cc00000, 0xffe007ff, COD|RD_t|WR_CC, 0, I1 }, ++{"ctc3", "t,G,#H", 0x4cc00000, 0xffe007c0, COD|RD_t|WR_CC, 0, RLX3 }, + {"dmfc3", "t,G", 0x4c200000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I3 }, + {"dmtc3", "t,G", 0x4ca00000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I3 }, + {"mfc3", "t,G", 0x4c000000, 0xffe007ff, LCD|WR_t|RD_C3, 0, I1 }, ++{"mfc3", "t,G,#H", 0x4c000000, 0xffe007c0, LCD|WR_t|RD_C3, 0, RLX3 }, + {"mfc3", "t,G,H", 0x4c000000, 0xffe007f8, LCD|WR_t|RD_C3, 0, I32 }, + {"mtc3", "t,G", 0x4c800000, 0xffe007ff, COD|RD_t|WR_C3|WR_CC, 0, I1 }, ++{"mtc3", "t,G,#H", 0x4c800000, 0xffe007c0, COD|RD_t|WR_C3|WR_CC, 0, RLX3 }, + {"mtc3", "t,G,H", 0x4c800000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC, 0, I32 }, + + /* Conflicts with the 4650's "mul" instruction. Nobody's using the +@@ -1561,6 +1596,7 @@ const struct mips_opcode mips_builtin_op + {"addu_s.qb", "d,s,t", 0x7c000110, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, + {"addwc", "d,s,t", 0x7c000450, 0xfc0007ff, WR_d|RD_s|RD_t, 0, D32 }, + {"bitrev", "d,t", 0x7c0006d2, 0xffe007ff, WR_d|RD_t, 0, D32 }, ++{"bitrev", "d,t,s", 0x7c00000c, 0xFC0007FF, RD_s|RD_t|WR_d, 0, RAD1 }, + {"bposge32", "p", 0x041c0000, 0xffff0000, CBD, 0, D32 }, + {"bposge64", "p", 0x041d0000, 0xffff0000, CBD, 0, D64 }, + {"cmp.eq.ph", "s,t", 0x7c000211, 0xfc00ffff, RD_s|RD_t, 0, D32 }, +@@ -1984,7 +2020,176 @@ const struct mips_opcode mips_builtin_op + {"cop0", "C", 0, (int) M_COP0, INSN_MACRO, 0, I1 }, + {"cop1", "C", 0, (int) M_COP1, INSN_MACRO, INSN2_M_FP_S, I1 }, + {"cop2", "C", 0, (int) M_COP2, INSN_MACRO, 0, I1 }, +-{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, 0, I1 } ++{"cop3", "C", 0, (int) M_COP3, INSN_MACRO, 0, I1 }, ++ ++/* dbb: modified for supporting radiax instructions */ ++/* 2006-01-19 tonywu: cleanup radiax instructions definition */ ++/* 2008-07-12 tonywu: add taroko support */ ++/* 2008-08-31 tonywu: add rad type */ ++/* d1: m0(3), m1(7), m2(11), m3(15) */ ++/* d2: m0l, m0h, m0 ~ m3l, m3h, m3 */ ++/* d3: m0l, m0h, ~ m3l, m3h */ ++/* d4: LXC0 */ ++{"mta2", "s,#d2", 0x7C00005D, 0xFC1F07ff, RD_s, 0, RAD1}, ++{"mta2.g", "s,#d2", 0x7C00015D, 0xFC1F07ff, RD_s, 0, RAD1}, ++{"mfa", "d,#t3", 0x7C00001C, 0xFFE007FF, WR_d, 0, RAD1}, ++{"mfa", "d,#t3,##", 0x7C00001C, 0xFFE0007F, WR_d, 0, RAD1}, ++{"mfa2", "d,#t1", 0x7C00005C, 0xFFE007FF, WR_d, 0, RAD1}, ++{"mfa2", "d,#t1,##", 0x7C00005C, 0xFFE0007F, WR_d, 0, RAD1}, ++{"diva", "#d1,s,t", 0x7C00001A, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"divau", "#d1,s,t", 0x7C00021A, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"multa", "#d1,s,t", 0x7C000112, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"multau", "#d1,s,t", 0x7C000312, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imulta", "#d1,s,t", 0x7C000102, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"imultau", "#d1,s,t", 0x7C000302, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmulta", "#d1,s,t", 0x7C000502, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"multa2", "#d2,s,t", 0x7C000152, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imulta2", "#d2,s,t", 0x7C000142, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmulta2", "#d2,s,t", 0x7C000542, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"mulna2", "#d2,s,t", 0x7C000153, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imulna2", "#d2,s,t", 0x7C000143, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmulna2", "#d2,s,t", 0x7C000543, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"cmulta", "#d1,s,t", 0x7C00001B, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"icmulta", "#d1,s,t", 0x7C00011B, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qcmulta", "#d1,s,t", 0x7C00051B, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"madda", "#d1,s,t", 0x7C000012, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"maddau", "#d1,s,t", 0x7C000212, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imadda", "#d1,s,t", 0x7C000002, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"imaddau", "#d1,s,t", 0x7C000202, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmadda", "#d1,s,t", 0x7C000402, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"madda2", "#d2,s,t", 0x7C000052, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imadda2", "#d2,s,t", 0x7C000042, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmadda2", "#d2,s,t", 0x7C000442, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"madda2.s", "#d2,s,t", 0x7C0000D2, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imadda2.s32", "#d2,s,t", 0x7C0000C2, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmadda2.s32", "#d2,s,t", 0x7C0004C2, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"imadda2.s40", "#d2,s,t", 0x7C0001C2, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmadda2.s40", "#d2,s,t", 0x7C0005C2, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"msuba", "#d1,s,t", 0x7C000013, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"msubau", "#d1,s,t", 0x7C000213, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imsuba", "#d1,s,t", 0x7C000003, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"imsubau", "#d1,s,t", 0x7C000203, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmsuba", "#d1,s,t", 0x7C000403, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"msuba2", "#d2,s,t", 0x7C000053, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imsuba2", "#d2,s,t", 0x7C000043, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmsuba2", "#d2,s,t", 0x7C000443, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"msuba2.s", "#d2,s,t", 0x7C0000D3, 0xFC0007FF, RD_t | RD_s, 0, RAD1}, ++{"imsuba2.s32", "#d2,s,t", 0x7C0000C3, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmsuba2.s32", "#d2,s,t", 0x7C0004C3, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"imsuba2.s40", "#d2,s,t", 0x7C0001C3, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"qmsuba2.s40", "#d2,s,t", 0x7C0005C3, 0xFC0007FF, RD_t | RD_s, 0, RAD2}, ++{"addma", "#d3,#s3,#t3", 0x7C00001E, 0xFC0007FF, 0, 0, RAD1}, ++{"addma.s", "#d3,#s3,#t3", 0x7C00009E, 0xFC0007FF, 0, 0, RAD1}, ++{"addma.s32", "#d3,#s3,#t3", 0x7C00041E, 0xFC0007FF, 0, 0, RAD2}, ++{"addma.s40", "#d3,#s3,#t3", 0x7C00049E, 0xFC0007FF, 0, 0, RAD2}, ++{"subma", "#d3,#s3,#t3", 0x7C00001F, 0xFC0007FF, 0, 0, RAD1}, ++{"subma.s", "#d3,#s3,#t3", 0x7C00009F, 0xFC0007FF, 0, 0, RAD1}, ++{"subma.s32", "#d3,#s3,#t3", 0x7C00041F, 0xFC0007FF, 0, 0, RAD2}, ++{"subma.s40", "#d3,#s3,#t3", 0x7C00049F, 0xFC0007FF, 0, 0, RAD2}, ++{"rnda2", "#t2", 0x7C000056, 0xFFE0FFFF, 0, 0, RAD1}, ++{"rnda2", "#t2,##", 0x7C000056, 0xFFE0F87F, 0, 0, RAD1}, ++{"lt", "#`,#@(b)", 0x7C000036, 0xFC00003F, LDD | RD_b | WR_t, 0, RAD1}, ++{"st", "#`,#@(b)", 0x7C00003E, 0xFC00003F, SM | RD_t | RD_b, 0, RAD1}, ++{"ltp", "#`,(b)#~", 0x7C0000f2, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"ltp.c0", "#`,(b)#~", 0x7C000032, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"ltp.c1", "#`,(b)#~", 0x7C000072, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"ltp.c2", "#`,(b)#~", 0x7C0000b2, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lwp", "t,(b)#~", 0x7C0000f3, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lwp.c0", "t,(b)#~", 0x7C000033, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lwp.c1", "t,(b)#~", 0x7C000073, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lwp.c2", "t,(b)#~", 0x7C0000b3, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhp", "t,(b)#~", 0x7C0000f1, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhp.c0", "t,(b)#~", 0x7C000031, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhp.c1", "t,(b)#~", 0x7C000071, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhp.c2", "t,(b)#~", 0x7C0000b1, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhpu", "t,(b)#~", 0x7C0000f5, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhpu.c0", "t,(b)#~", 0x7C000035, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhpu.c1", "t,(b)#~", 0x7C000075, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lhpu.c2", "t,(b)#~", 0x7C0000b5, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbp", "t,(b)#~", 0x7C0000f0, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbp.c0", "t,(b)#~", 0x7C000030, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbp.c1", "t,(b)#~", 0x7C000070, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbp.c2", "t,(b)#~", 0x7C0000b0, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbpu", "t,(b)#~", 0x7C0000f4, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbpu.c0", "t,(b)#~", 0x7C000034, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbpu.c1", "t,(b)#~", 0x7C000074, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"lbpu.c2", "t,(b)#~", 0x7C0000b4, 0xFC0000FF, LDD | WR_t | RD_b, 0, RAD1}, ++{"stp", "#`,(b)#~", 0x7C0000fa, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"stp.c0", "#`,(b)#~", 0x7C00003a, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"stp.c1", "#`,(b)#~", 0x7C00007a, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"stp.c2", "#`,(b)#~", 0x7C0000ba, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"swp", "t,(b)#~", 0x7C0000fb, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"swp.c0", "t,(b)#~", 0x7C00003b, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"swp.c1", "t,(b)#~", 0x7C00007b, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"swp.c2", "t,(b)#~", 0x7C0000bb, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"shp", "t,(b)#~", 0x7C0000f9, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"shp.c0", "t,(b)#~", 0x7C000039, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"shp.c1", "t,(b)#~", 0x7C000079, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"shp.c2", "t,(b)#~", 0x7C0000b9, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"sbp", "t,(b)#~", 0x7C0000f8, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"sbp.c0", "t,(b)#~", 0x7C000038, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"sbp.c1", "t,(b)#~", 0x7C000078, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"sbp.c2", "t,(b)#~", 0x7C0000b8, 0xFC0000FF, WR_t | RD_b, 0, RAD1}, ++{"mtru", "t,#u", 0x7C000025, 0xFFE007FF, RD_t, 0, RAD1}, ++{"mfru", "t,#u", 0x7C000024, 0xFFE007FF, RD_t, 0, RAD1}, ++{"mtrk", "t,#k", 0x7C0000A5, 0xFFE007FF, RD_t, 0, RAD1}, ++{"mfrk", "t,#k", 0x7C0000A4, 0xFFE007FF, RD_t, 0, RAD1}, ++{"sllv2", "d,t,s", 0x7C000044, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"srlv2", "d,t,s", 0x7C000046, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"srav2", "d,t,s", 0x7C000047, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"addr", "d,s,t", 0x7C000021, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"addr.s", "d,s,t", 0x7C0000A1, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"addr2", "d,s,t", 0x7C000061, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"addr2.s", "d,s,t", 0x7C0000E1, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"subr", "d,s,t", 0x7C000023, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"subr.s", "d,s,t", 0x7C0000A3, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"subr2", "d,s,t", 0x7C000063, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"subr2.s", "d,s,t", 0x7C0000E3, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"sltr2", "d,s,t", 0x7C00006A, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"min", "d,s,t", 0x7C000028, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"min2", "d,s,t", 0x7C000068, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"max", "d,s,t", 0x7C000029, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"max2", "d,s,t", 0x7C000069, 0xFC0007FF, RD_t | RD_s | WR_d, 0, RAD1}, ++{"absr", "d,t", 0x7C00000F, 0xFFE007FF, RD_t | WR_d, 0, RAD1}, ++{"absr.s", "d,t", 0x7C00008F, 0xFFE007FF, RD_t | WR_d, 0, RAD1}, ++{"absr2", "d,t", 0x7C00004F, 0xFFE007FF, RD_t | WR_d, 0, RAD1}, ++{"absr2.s", "d,t", 0x7C0000CF, 0xFFE007FF, RD_t | WR_d, 0, RAD1}, ++{"mux2.hh", "d,s,t", 0x7C00064D, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"mux2.hl", "d,s,t", 0x7C00044D, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"mux2.lh", "d,s,t", 0x7C00024D, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"mux2.ll", "d,s,t", 0x7C00004D, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cls", "d,t", 0x7C00000E, 0xFFE007FF, RD_t | WR_d, 0, RAD1}, ++{"cmveqz", "d,s,t", 0x7C000001, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cmveqz.h", "d,s,t", 0x7C000081, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cmveqz.l", "d,s,t", 0x7C000101, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cmvnez", "d,s,t", 0x7C000041, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cmvnez.h", "d,s,t", 0x7C0000c1, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++{"cmvnez.l", "d,s,t", 0x7C000141, 0xFC0007FF, RD_s | RD_t | WR_d, 0, RAD1}, ++ ++ ++/* Coprocessor 0 operations */ ++{"mflxc0", "t,#d4", 0x40600000, 0xFFE007FF, LCD | WR_t | RD_C0, 0, RLXB}, ++{"mflxc0", "t,#d4,#H", 0x40600000, 0xFFE007C0, LCD | WR_t | RD_C0, 0, RLX3}, ++{"mtlxc0", "t,#d4", 0x40E00000, 0xFFE007FF, COD | RD_t | WR_C0 | WR_CC, 0, RLXB}, ++{"mtlxc0", "t,#d4,#H", 0x40E00000, 0xFFE007C0, COD | RD_t | WR_C0 | WR_CC, 0, RLX3}, ++/*MAC-DIV*/ ++{"sleep", "", 0x42000038, 0xffffffff, 0, 0, RLXA}, ++{"sleep", "#I", 0x42000038, 0xfffff83f, 0, 0, RLX3}, ++{"madh", "s,t", 0xF0000000, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"madl", "s,t", 0xF0000002, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"mazh", "s,t", 0xF0000004, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"mazl", "s,t", 0xF0000006, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"msbh", "s,t", 0xF0000010, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"msbl", "s,t", 0xF0000012, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"mszh", "s,t", 0xF0000014, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"mszl", "s,t", 0xF0000016, 0xFC00FFFF, RD_s | RD_t, 0, RLXA}, ++{"ltw", "#`,#-(b)", 0x7800003C, 0xFC00003F, LDD | RD_b | WR_t, 0, INSN_4181 | INSN_4281}, ++/* Lexra opcode extensions. Register mode */ ++/* Lexra opcode extensions. Immediate mode */ ++{"udi0i", "t,r,j", 0x60000000, 0xfc000000, WR_t | RD_s, 0, RLXB}, ++{"udi1i", "t,r,j", 0x64000000, 0xfc000000, WR_t | RD_s, 0, RLXB}, ++{"udi2i", "t,r,j", 0x68000000, 0xfc000000, WR_t | RD_s, 0, RLXB}, ++{"udi3i", "t,r,j", 0x6c000000, 0xfc000000, WR_t | RD_s, 0, RLXB}, + }; + + #define MIPS_NUM_OPCODES \ +Index: binutils/bfd/bfd-in2.h +=================================================================== +--- binutils.orig/bfd/bfd-in2.h ++++ binutils/bfd/bfd-in2.h +@@ -1828,11 +1828,17 @@ enum bfd_architecture + #define bfd_mach_mips4100 4100 + #define bfd_mach_mips4111 4111 + #define bfd_mach_mips4120 4120 ++#define bfd_mach_mips4180 4180 ++#define bfd_mach_mips4181 4181 ++#define bfd_mach_mips4281 4281 + #define bfd_mach_mips4300 4300 + #define bfd_mach_mips4400 4400 + #define bfd_mach_mips4600 4600 + #define bfd_mach_mips4650 4650 + #define bfd_mach_mips5000 5000 ++#define bfd_mach_mips5181 5181 ++#define bfd_mach_mips5280 5280 ++#define bfd_mach_mips5281 5281 + #define bfd_mach_mips5400 5400 + #define bfd_mach_mips5500 5500 + #define bfd_mach_mips6000 6000 +@@ -2189,7 +2195,8 @@ typedef enum bfd_reloc_status + generated only when linking i960 coff files with i960 b.out + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ +- bfd_reloc_dangerous ++ bfd_reloc_dangerous, ++ bfd_reloc_notmultipleof8_ltw + } + bfd_reloc_status_type; + +@@ -4680,6 +4687,7 @@ value in a word. The relocation is rela + /* This is used to tell the dynamic linker to copy the value out of + the dynamic object into the runtime process image. */ + BFD_RELOC_MICROBLAZE_COPY, ++ BFD_RELOC_OFF6A, + BFD_RELOC_UNUSED }; + typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; + reloc_howto_type *bfd_reloc_type_lookup +Index: binutils/bfd/cpu-mips.c +=================================================================== +--- binutils.orig/bfd/cpu-mips.c ++++ binutils/bfd/cpu-mips.c +@@ -67,11 +67,17 @@ enum + I_mips4100, + I_mips4111, + I_mips4120, ++ I_mips4180, ++ I_mips4181, ++ I_mips4281, + I_mips4300, + I_mips4400, + I_mips4600, + I_mips4650, + I_mips5000, ++ I_mips5181, ++ I_mips5280, ++ I_mips5281, + I_mips5400, + I_mips5500, + I_mips6000, +@@ -106,11 +112,17 @@ static const bfd_arch_info_type arch_inf + N (64, 64, bfd_mach_mips4100, "mips:4100", FALSE, NN(I_mips4100)), + N (64, 64, bfd_mach_mips4111, "mips:4111", FALSE, NN(I_mips4111)), + N (64, 64, bfd_mach_mips4120, "mips:4120", FALSE, NN(I_mips4120)), ++ N (32, 32, bfd_mach_mips4180, "mips:4180", FALSE, NN(I_mips4180)), ++ N (32, 32, bfd_mach_mips4181, "mips:4181", FALSE, NN(I_mips4181)), ++ N (32, 32, bfd_mach_mips4281, "mips:4281", FALSE, NN(I_mips4281)), + N (64, 64, bfd_mach_mips4300, "mips:4300", FALSE, NN(I_mips4300)), + N (64, 64, bfd_mach_mips4400, "mips:4400", FALSE, NN(I_mips4400)), + N (64, 64, bfd_mach_mips4600, "mips:4600", FALSE, NN(I_mips4600)), + N (64, 64, bfd_mach_mips4650, "mips:4650", FALSE, NN(I_mips4650)), + N (64, 64, bfd_mach_mips5000, "mips:5000", FALSE, NN(I_mips5000)), ++ N (32, 32, bfd_mach_mips5181, "mips:5181", FALSE, NN(I_mips5181)), ++ N (32, 32, bfd_mach_mips5280, "mips:5280", FALSE, NN(I_mips5280)), ++ N (32, 32, bfd_mach_mips5281, "mips:5281", FALSE, NN(I_mips5281)), + N (64, 64, bfd_mach_mips5400, "mips:5400", FALSE, NN(I_mips5400)), + N (64, 64, bfd_mach_mips5500, "mips:5500", FALSE, NN(I_mips5500)), + N (32, 32, bfd_mach_mips6000, "mips:6000", FALSE, NN(I_mips6000)), +Index: binutils/opcodes/mips-dis.c +=================================================================== +--- binutils.orig/opcodes/mips-dis.c ++++ binutils/opcodes/mips-dis.c +@@ -32,6 +32,28 @@ + symbol table is available when this code runs out in an embedded + system as when it is used for disassembler support in a monitor. */ + ++int is_rlx_insn = 0; ++int des_reg_type = 0; ++/* the des reg is: ++ * 0 gr, ++ * 1 accumulator, ++ * 2 Radiax User register, ++ * 3 Selects Lexra Coprocessor0 register ++ */ ++int src_reg_type = 0; ++/* the src reg is: ++ * 0 gr, ++ * 1 accumulator, ++ * 2 Radiax User register ++ */ ++int targ_reg_type = 0; ++/* the target reg is: ++ * 0 gr, ++ * 1 accumulator, ++ * 2 Radiax User register ++ */ ++ ++ + #if !defined(EMBEDDED_ENV) + #define SYMTAB_AVAILABLE 1 + #include "elf-bfd.h" +@@ -84,6 +106,16 @@ static const char * const mips_gpr_names + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" + }; + ++static const char *const mips_accumulator_names_alias[16] = { ++ "reserve", "m0l", "m0h", "m0", "reserve", "m1l", "m1h", "m1", ++ "reserve", "m2l", "m2h", "m2", "reserve", "m3l", "m3h", "m3" ++}; ++ ++static const char *const mips_radreg_names_alias[14] = { ++ "cbs0", "cbs1", "cbs2", "reserved", "cbe0", "cbe1", "cbe2", "reserved", ++ "lps0", "lpe0", "lpc0", "reserved", "mmd", "reserved" ++}; ++ + static const char * const mips_fpr_names_numeric[32] = + { + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", +@@ -433,6 +465,12 @@ const struct mips_arch_choice mips_arch_ + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, + { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, ++ { "4180", 1, bfd_mach_mips4180, CPU_LX4180, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, ++ { "4181", 1, bfd_mach_mips4181, CPU_RLX4181, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, ++ { "4281", 1, bfd_mach_mips4281, CPU_RLX4281, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, + { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, + { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, +@@ -443,6 +481,12 @@ const struct mips_arch_choice mips_arch_ + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, + { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, ++ { "5181", 1, bfd_mach_mips5181, CPU_RLX5181, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, ++ { "5281", 1, bfd_mach_mips5281, CPU_RLX5281, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, ++ { "5280", 1, bfd_mach_mips5280, CPU_LX5280, ISA_MIPS1, ++ mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric}, + { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, + mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric }, + { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, +@@ -815,6 +859,7 @@ print_insn_args (const char *d, + { + int op, delta; + unsigned int lsb, msb, msbd; ++ int tmp_regno; + + lsb = 0; + +@@ -1074,13 +1119,22 @@ print_insn_args (const char *d, + case 'b': + case 'r': + case 'v': +- (*info->fprintf_func) (info->stream, "%s", ++ if (src_reg_type == 1) ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_accumulator_names_alias[(l >> OP_SH_RS) & OP_MASK_RS]); ++ else ++ (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]); ++ + break; + + case 't': + case 'w': +- (*info->fprintf_func) (info->stream, "%s", ++ if (targ_reg_type == 1) ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_accumulator_names_alias[(l >> OP_SH_RT) & OP_MASK_RT]); ++ else ++ (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); + break; + +@@ -1131,8 +1185,50 @@ print_insn_args (const char *d, + break; + + case 'd': +- (*info->fprintf_func) (info->stream, "%s", ++ switch(des_reg_type) { ++ case 1: ++ tmp_regno = (l >> OP_SH_RD) & OP_MASK_RD; ++ if (tmp_regno >= 16 || tmp_regno < 0) ++ (*info->fprintf_func) (info->stream, "INVALID"); ++ else ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_accumulator_names_alias ++ [tmp_regno]); ++ break; ++ case 2: ++ tmp_regno = (l >> OP_SH_RD) & OP_MASK_RD; ++ if (tmp_regno <= 7) ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_radreg_names_alias[tmp_regno]); ++ else if ((16 <= tmp_regno) && (tmp_regno <= 19)) ++ { ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_radreg_names_alias[tmp_regno - ++ 8]); ++ } ++ else if (tmp_regno == 24) ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_radreg_names_alias[12]); ++ else ++ (*info->fprintf_func) (info->stream, "%s", ++ mips_radreg_names_alias[13]); ++ break; ++ case 3: ++ tmp_regno = (l >> OP_SH_RD) & OP_MASK_RD; ++ if (tmp_regno == 0) ++ (*info->fprintf_func) (info->stream, "estatus"); ++ else if (tmp_regno == 1) ++ (*info->fprintf_func) (info->stream, "ecause"); ++ else if (tmp_regno == 2) ++ (*info->fprintf_func) (info->stream, "intvec"); ++ else ++ (*info->fprintf_func) (info->stream, "reserved"); ++ break; ++ default: ++ (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]); ++ break; ++ } + break; + + case 'U': +@@ -1329,6 +1425,40 @@ print_insn_args (const char *d, + (l >> OP_SH_FT) & OP_MASK_FT); + break; + ++ case '#': ++ (*info->fprintf_func) (info->stream, "%i", ++ (l >> OP_SH_IMMIDATE74) & ++ OP_MASK_IMMIDATE74); ++ break; ++ ++ /* 8 bits immediate ,used in lbp,stp,etc(OP_*_IMMIDATE88) */ ++ case '~': ++ delta = (l >> OP_SH_IMMIDATE88) & OP_MASK_IMMIDATE88; ++ if (delta & 0x80) ++ delta |= ~0xff; ++ ++ (*info->fprintf_func) (info->stream, "%i", delta); ++ break; ++ ++ /* even register,used in lt,st,ltp,stp (OP_*_EVENREG) */ ++ case '`': ++ delta = (l >> OP_SH_EVENREG) & OP_MASK_EVENREG; ++ if ((delta % 2) != 0) ++ delta--; /* for "lt" insn */ ++ (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[delta]); ++ break; ++ ++ /* 10 bits offset,used in ltw(OP_*_OFFSET6A) */ ++ case '-': ++ delta = (l >> OP_SH_OFFSET6A) & OP_MASK_OFFSET6A; ++ if (delta & 0x200) ++ delta |= ~0x3ff; ++ /* 2006-02-08 tonywu: fix ltw objdump displacement */ ++ delta <<= 3; ++ (*info->fprintf_func) (info->stream, "%d", delta); ++ ++ break; ++ + default: + /* xgettext:c-format */ + (*info->fprintf_func) (info->stream, +@@ -1426,6 +1556,80 @@ print_insn_mips (bfd_vma memaddr, + (*info->fprintf_func) (info->stream, "%s", op->name); + + d = op->args; ++ ++ des_reg_type = 0; ++ src_reg_type = 0; ++ targ_reg_type = 0; ++ ++ if ((op->membership & INSN_4181) || ++ (op->membership & INSN_4281) || ++ (op->membership & INSN_5181) || ++ (op->membership & INSN_5281) || ++ (op->membership & INSN_5280)) ++ { ++ is_rlx_insn = 1; ++ if (strncmp (op->name, "mta2", 4) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if ((strncmp (op->name, "mflxc0", 6) == 0) ++ || (strncmp (op->name, "mtlxc0", 6) == 0)) ++ { ++ des_reg_type = 3; ++ } ++ else if (strncmp (op->name, "mfa", 3) == 0) ++ { ++ targ_reg_type = 1; ++ } ++ else if (strncmp (op->name, "diva", 4) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "multa", 5) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "mulna2", 6) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "cmulta", 6) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "madda", 5) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "msuba", 5) == 0) ++ { ++ des_reg_type = 1; ++ } ++ else if (strncmp (op->name, "addma", 5) == 0) ++ { ++ des_reg_type = 1; ++ src_reg_type = 1; ++ targ_reg_type = 1; ++ } ++ else if (strncmp (op->name, "subma", 5) == 0) ++ { ++ des_reg_type = 1; ++ src_reg_type = 1; ++ targ_reg_type = 1; ++ } ++ else if (strncmp (op->name, "rnda2", 5) == 0) ++ { ++ targ_reg_type = 1; ++ } ++ else if (strncmp (op->name, "mtru", 4) == 0) ++ { ++ des_reg_type = 2; ++ } ++ else if (strncmp (op->name, "mfru", 4) == 0) ++ { ++ des_reg_type = 2; ++ } ++ } + if (d != NULL && *d != '\0') + { + (*info->fprintf_func) (info->stream, "\t"); +Index: binutils/opcodes/mips16-opc.c +=================================================================== +--- binutils.orig/opcodes/mips16-opc.c ++++ binutils/opcodes/mips16-opc.c +@@ -65,6 +65,11 @@ + #define I64 INSN_ISA64 + #define T3 INSN_3900 + ++#define RLX1 INSN_4180 | INSN_4181 | INSN_4281 | INSN_5181 | INSN_5280 | INSN_5281 ++#define RLX2 INSN_4181 | INSN_4281 | INSN_5181 | INSN_5280 | INSN_5281 ++#define RLX3 INSN_4181 | INSN_4281 | INSN_5181 | INSN_5281 ++#define RLX4 INSN_5181 | INSN_5280 | INSN_5281 ++ + const struct mips_opcode mips16_opcodes[] = + { + /* name, args, match, mask, pinfo, pinfo2, membership */ +@@ -109,6 +114,7 @@ const struct mips_opcode mips16_opcodes[ + {"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 }, + {"bnez", "x,p", 0x2800, 0xf800, BR|RD_x, 0, I1 }, + {"break", "6", 0xe805, 0xf81f, TRAP, 0, I1 }, ++{"break", "", 0xe805, 0xffff, TRAP, 0, RLX1}, + {"bteqz", "p", 0x6000, 0xff00, BR|RD_T, 0, I1 }, + {"btnez", "p", 0x6100, 0xff00, BR|RD_T, 0, I1 }, + {"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 }, +@@ -184,10 +190,18 @@ const struct mips_opcode mips16_opcodes[ + {"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, 0, I1 }, + {"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, 0, I1 }, + {"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, 0, I3 }, ++{"madh", "x,y", 0xf800, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"madl", "x,y", 0xf802, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"mazh", "x,y", 0xf804, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"mazl", "x,y", 0xf806, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, + {"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, 0, I1 }, + {"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, 0, I1 }, + {"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, 0, I1 }, + {"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, 0, I1 }, ++{"msbh", "x,y", 0xf810, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"msbl", "x,y", 0xf812, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"mszh", "x,y", 0xf814, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, ++{"mszl", "x,y", 0xf816, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, RLX1}, + {"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, 0, I1 }, + {"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, + {"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 }, +Index: binutils/include/opcode/mips.h +=================================================================== +--- binutils.orig/include/opcode/mips.h ++++ binutils/include/opcode/mips.h +@@ -58,6 +58,22 @@ Software Foundation, 51 Franklin Street + + The general coprocessor instructions use COPZ. */ + ++#define OP_MASK_IMMIDATE74 0xf /* used in MFA,MFA2,RNDA2 */ ++#define OP_SH_IMMIDATE74 7 /* used in MFA,MFA2,RNDA2 */ ++#define OP_MASK_IMMIDATE6b 0x7ff /* used in lt,st */ ++#define OP_SH_IMMIDATE6b 6 /* used in lt,st */ ++#define OP_MASK_IMMIDATE88 0xff /* used in lbp,stp,etc */ ++#define OP_SH_IMMIDATE88 8 /* used in lbp,stp,etc */ ++#define OP_MASK_EVENREG 0x1f /* used in lt,st,ltp,stp */ ++#define OP_SH_EVENREG 16 /* used in lt,st,ltp,stp */ ++#define OP_MASK_OFFSET6A 0x3ff /* used in ltw */ ++#define OP_SH_OFFSET6A 6 /* used in ltw */ ++ ++#define OP_MASK_RLX_SEL 0x3f ++#define OP_SH_RLX_SEL 0 ++#define OP_MASK_RLX_STYPE 0x3f ++#define OP_SH_RLX_STYPE 6 ++ + #define OP_MASK_OP 0x3f + #define OP_SH_OP 26 + #define OP_MASK_RS 0x1f +@@ -274,6 +290,13 @@ struct mips_opcode + "j" 16 bit signed immediate (OP_*_DELTA) + "k" 5 bit cache opcode in target register position (OP_*_CACHE) + Also used for immediate operands in vr5400 vector insns. ++*********************** dbb modified for supporting radiax instructions ************************** ++ "@" 11 bits immediate used in lt,st (OP_*_IMMIDATE6b),in fact it is 14 bits,mutiple of 8; ++ "#" 4 bits immediate from 0 to 8,used in MFA,MFA2,RNDA2 (OP_*_IMMIDATE74) ++ "~" 8 bits immediate ,used in lbp,stp,etc(OP_*_IMMIDATE88) ++ "`" even register,used in lt,st,ltp,stp (OP_*_EVENREG) ++ "-" 10 bits offset,used in ltw(OP_*_OFFSET6A) ++*********************** dbb modified for supporting radiax instructions ************************** + "o" 16 bit signed offset (OP_*_DELTA) + "p" 16 bit PC relative branch target address (OP_*_DELTA) + "q" 10 bit extra breakpoint code (OP_*_CODE2) +@@ -571,15 +594,18 @@ static const unsigned int mips_isa_table + #define INSN_10000 0x00100000 + /* Broadcom SB-1 instruction. */ + #define INSN_SB1 0x00200000 ++ + /* NEC VR4111/VR4181 instruction. */ + #define INSN_4111 0x00400000 + /* NEC VR4120 instruction. */ + #define INSN_4120 0x00800000 ++ ++ ++#if 0 //JMM - break all these badly sorry! + /* NEC VR5400 instruction. */ + #define INSN_5400 0x01000000 + /* NEC VR5500 instruction. */ + #define INSN_5500 0x02000000 +- + /* MDMX ASE */ + #define INSN_MDMX 0x04000000 + /* MT ASE */ +@@ -592,6 +618,35 @@ static const unsigned int mips_isa_table + #define INSN_LOONGSON_2E 0x40000000 + /* ST Microelectronics Loongson 2F. */ + #define INSN_LOONGSON_2F 0x80000000 ++#else ++ ++#define INSN_4180 0x01000000 ++#define INSN_4181 0x02000000 ++#define INSN_4281 0x04000000 ++#define INSN_5181 0x08000000 ++#define INSN_5280 0x10000000 ++#define INSN_5281 0x20000000 ++ ++#define INSN_DONT_CARE 0x80000000 ++/* NEC VR5400 instruction. */ ++#define INSN_5400 INSN_DONT_CARE ++/* NEC VR5500 instruction. */ ++#define INSN_5500 INSN_DONT_CARE ++/* MDMX ASE */ ++#define INSN_MDMX INSN_DONT_CARE ++/* MT ASE */ ++#define INSN_MT INSN_DONT_CARE ++/* SmartMIPS ASE */ ++#define INSN_SMARTMIPS INSN_DONT_CARE ++/* DSP R2 ASE */ ++#define INSN_DSPR2 INSN_DONT_CARE ++/* ST Microelectronics Loongson 2E. */ ++#define INSN_LOONGSON_2E INSN_DONT_CARE ++/* ST Microelectronics Loongson 2F. */ ++#define INSN_LOONGSON_2F INSN_DONT_CARE ++#endif ++ ++ + /* RMI Xlr instruction */ + #define INSN_XLR 0x00000020 + +@@ -621,11 +676,17 @@ static const unsigned int mips_isa_table + #define CPU_VR4100 4100 + #define CPU_R4111 4111 + #define CPU_VR4120 4120 ++#define CPU_LX4180 4180 /* LX4180 */ ++#define CPU_RLX4181 4181 /* RLX4181 */ ++#define CPU_RLX4281 4281 /* RLX4281 */ + #define CPU_R4300 4300 + #define CPU_R4400 4400 + #define CPU_R4600 4600 + #define CPU_R4650 4650 + #define CPU_R5000 5000 ++#define CPU_RLX5181 5181 /* RLX5181 */ ++#define CPU_RLX5281 5281 /* RLX5281 */ ++#define CPU_LX5280 5280 /* LX5280 */ + #define CPU_VR5400 5400 + #define CPU_VR5500 5500 + #define CPU_R6000 6000 +@@ -681,6 +742,12 @@ static const unsigned int mips_isa_table + || (cpu == CPU_OCTEON \ + && ((insn)->membership & INSN_OCTEON) != 0) \ + || (cpu == CPU_XLR && ((insn)->membership & INSN_XLR) != 0) \ ++ || (cpu == CPU_LX4180 && ((insn)->membership & INSN_4180) != 0) \ ++ || (cpu == CPU_RLX4181 && ((insn)->membership & INSN_4181) != 0) \ ++ || (cpu == CPU_RLX4281 && ((insn)->membership & INSN_4281) != 0) \ ++ || (cpu == CPU_RLX5181 && ((insn)->membership & INSN_5181) != 0) \ ++ || (cpu == CPU_LX5280 && ((insn)->membership & INSN_5280) != 0) \ ++ || (cpu == CPU_RLX5281 && ((insn)->membership & INSN_5281) != 0) \ + || 0) /* Please keep this term for easier source merging. */ + + /* This is a list of macro expanded instructions. +Index: binutils/gas/config/tc-mips.c +=================================================================== +--- binutils.orig/gas/config/tc-mips.c ++++ binutils/gas/config/tc-mips.c +@@ -99,6 +99,32 @@ static char *mips_regmask_frag; + #define FP 30 + #define RA 31 + ++#define M0L 1 ++#define M0H 2 ++#define M0 3 ++#define M1L 5 ++#define M1H 6 ++#define M1 7 ++#define M2L 9 ++#define M2H 10 ++#define M2 11 ++#define M3L 13 ++#define M3H 14 ++#define M3 15 ++#define ESTATUS 0 ++#define ECAUSE 1 ++#define INTVEC 2 ++#define CBS0 0 ++#define CBS1 1 ++#define CBS2 2 ++#define CBE0 4 ++#define CBE1 5 ++#define CBE2 6 ++#define LPS0 16 ++#define LPE0 17 ++#define LPC0 18 ++#define MMD 24 ++ + #define ILLEGAL_REG (32) + + #define AT mips_opts.at +@@ -272,6 +298,8 @@ static struct mips_set_options mips_opts + /* sym32 */ FALSE, /* soft_float */ FALSE, /* single_float */ FALSE + }; + ++static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0, 0 }; ++ + /* These variables are filled in with the masks of registers used. + The object format code reads them and puts them in the appropriate + place. */ +@@ -497,7 +525,10 @@ static int mips_32bitmode = 0; + level I. */ + #define gpr_interlocks \ + (mips_opts.isa != ISA_MIPS1 \ +- || mips_opts.arch == CPU_R3900) ++ || mips_opts.arch == CPU_R3900 \ ++ || mips_opts.arch == CPU_RLX4281 \ ++ || mips_opts.arch == CPU_LX5280 \ ++ || mips_opts.arch == CPU_RLX5281 ) + + /* Whether the processor uses hardware interlocks to avoid delays + required by coprocessor instructions, and thus does not require +@@ -1102,6 +1133,11 @@ static void s_mips_loc (int); + static bfd_boolean pic_need_relax (symbolS *, asection *); + static int relaxed_branch_length (fragS *, asection *, int); + static int validate_mips_insn (const struct mips_opcode *); ++static inline int rlx_nops_for_new_insn (const struct mips_cl_insn *, const struct mips_cl_insn *); ++static inline int rlx_is_insn_lt (const struct mips_cl_insn *, const struct mips_cl_insn *); ++static inline int rlx_is_insn_st (const struct mips_cl_insn *, const struct mips_cl_insn *); ++static inline int rlx_is_insn_swappable (const struct mips_cl_insn *, const struct mips_cl_insn *); ++ + + /* Table and functions used to map between CPU/ISA names, and + ISA levels, and CPU numbers. */ +@@ -1683,6 +1719,34 @@ struct regname { + #define MIPS16_SPECIAL_REGISTER_NAMES \ + {"$pc", RTYPE_PC | 0} + ++#define RLX_REGISTER_ALIAS_NAMES \ ++ {"$m0l", RTYPE_GP | 1}, \ ++ {"$m0h", RTYPE_GP | 2}, \ ++ {"$m0", RTYPE_GP | 3}, \ ++ {"$m1l", RTYPE_GP | 5}, \ ++ {"$m1h", RTYPE_GP | 6}, \ ++ {"$m1", RTYPE_GP | 7}, \ ++ {"$m2l", RTYPE_GP | 9}, \ ++ {"$m2h", RTYPE_GP | 10}, \ ++ {"$m2", RTYPE_GP | 11}, \ ++ {"$m3l", RTYPE_GP | 13}, \ ++ {"$m3l", RTYPE_GP | 14}, \ ++ {"$m3", RTYPE_GP | 15}, \ ++ {"$estatus", RTYPE_GP | 0}, \ ++ {"$ecause", RTYPE_GP | 1}, \ ++ {"$intvec", RTYPE_GP | 2}, \ ++ {"$mmd", RTYPE_GP | 24}, \ ++ {"$cbs0", RTYPE_GP | 0}, \ ++ {"$cbs1", RTYPE_GP | 1}, \ ++ {"$cbs2", RTYPE_GP | 2}, \ ++ {"$cbe0", RTYPE_GP | 4}, \ ++ {"$cbe1", RTYPE_GP | 5}, \ ++ {"$cbe2", RTYPE_GP | 6}, \ ++ {"$lps0", RTYPE_GP | 16}, \ ++ {"$lpe0", RTYPE_GP | 17}, \ ++ {"$lpc0", RTYPE_GP | 18} ++ ++ + #define MDMX_VECTOR_REGISTER_NAMES \ + /* {"$v0", RTYPE_VEC | 0}, clash with REG 2 above */ \ + /* {"$v1", RTYPE_VEC | 1}, clash with REG 3 above */ \ +@@ -1736,6 +1800,7 @@ static const struct regname reg_names[] + SYMBOLIC_REGISTER_NAMES, + + MIPS16_SPECIAL_REGISTER_NAMES, ++ RLX_REGISTER_ALIAS_NAMES, + MDMX_VECTOR_REGISTER_NAMES, + MIPS_DSP_ACCUMULATOR_NAMES, + {0, 0} +@@ -2556,6 +2621,13 @@ insns_between (const struct mips_cl_insn + || (!cop_interlocks && (pinfo1 & INSN_LOAD_COPROC_DELAY))) + { + know (pinfo1 & INSN_WRITE_GPR_T); ++ ++ /* 2006-01-06 tonywu: insn2 == NULL => mips_optimize = 0 */ ++ /* 2006-10-16 tonywu: fix lt nop bug */ ++ if (rlx_is_insn_lt (insn1, insn2) || rlx_is_insn_st (insn1, insn2)) ++ return 1; ++ /* 2006-10-16 tonywu: fix lt nop bug */ ++ + if (INSN2_USES_REG (EXTRACT_OPERAND (RT, *insn1), MIPS_GR_REG)) + return 1; + } +@@ -2613,7 +2685,7 @@ insns_between (const struct mips_cl_insn + + #undef INSN2_USES_REG + +- return 0; ++ return rlx_nops_for_new_insn (insn1, insn2); + } + + /* Return the number of nops that would be needed to work around the +@@ -2687,6 +2759,36 @@ nops_for_insn (const struct mips_cl_insn + return nops; + } + ++/* 2006-01-09 tonywu: fix branch delay slot filling bug */ ++static inline int ++rlx_is_insn_swappable (const struct mips_cl_insn *history, ++ const struct mips_cl_insn *insn) ++{ ++ ++ unsigned long pinfo1, pinfo2; ++ ++ pinfo1 = history[0].insn_mo->pinfo; ++ pinfo2 = history[1].insn_mo->pinfo; ++ ++ if (pinfo1 & INSN_LOAD_MEMORY_DELAY || pinfo1 & INSN_WRITE_GPR_T) ++ { ++ if (insn_uses_reg (insn, EXTRACT_OPERAND (RT, history[0]), MIPS_GR_REG)) ++ { ++ return 1; ++ } ++ } ++ ++ if (pinfo2 & INSN_LOAD_MEMORY_DELAY || pinfo1 & INSN_WRITE_GPR_T) ++ { ++ if (insn_uses_reg (insn, EXTRACT_OPERAND (RT, history[1]), MIPS_GR_REG)) ++ { ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++ + /* The variable arguments provide NUM_INSNS extra instructions that + might be added to HISTORY. Return the largest number of nops that + would be needed after the extended sequence. */ +@@ -3193,13 +3295,16 @@ append_insn (struct mips_cl_insn *ip, ex + /* We do not swap with a trap instruction, since it + complicates trap handlers to have the trap + instruction be in a delay slot. */ ++ || rlx_is_insn_swappable (history, ip) > 0 + || (prev_pinfo & INSN_TRAP) + /* If the branch reads a register that the previous + instruction sets, we can not swap. */ + || (! mips_opts.mips16 + && (prev_pinfo & INSN_WRITE_GPR_T) + && insn_uses_reg (ip, EXTRACT_OPERAND (RT, history[0]), +- MIPS_GR_REG)) ++ MIPS_GR_REG) ++ /* 2006-01-06 tonywu: add for lt/ltw */ ++ && (rlx_is_insn_lt (history, ip))) + || (! mips_opts.mips16 + && (prev_pinfo & INSN_WRITE_GPR_D) + && insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]), +@@ -8555,6 +8660,32 @@ validate_mips_insn (const struct mips_op + case '1': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break; + case '2': USE_BITS (OP_MASK_BP, OP_SH_BP); break; + case '3': USE_BITS (OP_MASK_SA3, OP_SH_SA3); break; ++ /* 2006-01-04 tonywu: merged from 2.14 to 2.16 */ ++ case '#': ++ switch (c = *p++) ++ { ++ /* dbb: new instructions support */ ++ case '`': USE_BITS (OP_MASK_EVENREG, OP_SH_EVENREG); break; ++ case '~': USE_BITS (OP_MASK_IMMIDATE88, OP_SH_IMMIDATE88); break; ++ case '#': USE_BITS (OP_MASK_IMMIDATE74, OP_SH_IMMIDATE74); break; ++ case '@': USE_BITS (OP_MASK_IMMIDATE6b, OP_SH_IMMIDATE6b); break; ++ case '-': USE_BITS (OP_MASK_OFFSET6A, OP_SH_OFFSET6A); break; ++ /* dbb: new instructions support */ ++ /* 2008-07-08 tonywu: add for taroko processor */ ++ case 'H': USE_BITS (OP_MASK_RLX_SEL, OP_SH_RLX_SEL); break; ++ case 'I': USE_BITS (OP_MASK_RLX_STYPE, OP_SH_RLX_STYPE); break; ++ case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); p++; break; ++ case 's': USE_BITS (OP_MASK_RS, OP_SH_RS); p++; break; ++ case 't': USE_BITS (OP_MASK_RT, OP_SH_RT); p++; break; ++ case 'u': USE_BITS (OP_MASK_RD, OP_SH_RD); break; ++ case 'k': USE_BITS (OP_MASK_RD, OP_SH_RD); break; ++ /* 2008-07-08 tonywu: add for taroko processor */ ++ default: ++ as_bad (_("internal: bad rlx opcode (unknown extension operand type `#%c'): %s %s"), ++ c, opc->name, opc->args); ++ return 0; ++ } ++ break; + case '4': USE_BITS (OP_MASK_SA4, OP_SH_SA4); break; + case '5': USE_BITS (OP_MASK_IMM8, OP_SH_IMM8); break; + case '6': USE_BITS (OP_MASK_RS, OP_SH_RS); break; +@@ -8576,6 +8707,7 @@ validate_mips_insn (const struct mips_op + return 0; + } + #undef USE_BITS ++ if (strcmp (opc->name, "sleep") != 0) + if (used_bits != 0xffffffff) + { + as_bad (_("internal: bad mips opcode (bits 0x%lx undefined): %s %s"), +@@ -8652,6 +8784,7 @@ mips_ip (char *str, struct mips_cl_insn + char *s; + const char *args; + char c = 0; ++ char t = 0; + struct mips_opcode *insn; + char *argsStart; + unsigned int regno; +@@ -8661,6 +8794,7 @@ mips_ip (char *str, struct mips_cl_insn + char *s_reset; + char save_c = 0; + offsetT min_range, max_range; ++ int multipletype; + int argnum; + unsigned int rtype; + +@@ -9446,6 +9580,339 @@ do_msbd: + else + break; + ++ case '#': ++ switch (*++args) ++ { ++ case 'd': ++ case 's': ++ case 't': ++ s_reset = s; ++ regno = 32; ++ if (s[0] == '$') ++ { ++ reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); ++ } ++ ++ /* 2006-11-28 tonywu: add radiax alias name */ ++ c = *args; ++ t = *++args; ++ ++ /* Now that we have assembled one operand, we use the args string ++ * to figure out where it goes in the instruction. */ ++ switch (t) ++ { ++ case '1': /* m0(3), m1(7), m2(11), m3(15) */ ++ if (regno <= 0 || regno > 15 || (regno & 3) != 3) ++ as_bad (_ ++ ("RADIAX: illegal register (%d) in %s type d%c"), ++ regno, str, t); ++ break; ++ ++ case '2': /* m0l, m0h, m0 ~ m3l, m3h, m3 */ ++ if (regno <= 0 || regno > 15 || (regno & 3) == 0) ++ as_bad (_ ++ ("RADIAX: illegal register (%d) in %s type d%c"), ++ regno, str, t); ++ break; ++ ++ case '3': /* m0l, m0h, ~ m3l, m3h */ ++ if (regno <= 0 || regno > 15 ++ || (regno & 3) == 0 || (regno & 3) == 3) ++ as_bad (_ ++ ("RADIAX: illegal register (%d) in %s type d%c"), ++ regno, str, t); ++ break; ++ ++ case '4': /* LXC0 registers */ ++ if (regno > 31) ++ as_bad (_ ++ ("RLX: illegal register (%d) in %s type d%c"), ++ regno, str, t); ++ break; ++ ++ default: ++ as_bad (_("RLX: illegal register type d%c in %s"), t, ++ str); ++ break; ++ } ++ ++ switch (c) ++ { ++ case 'd': ++ INSERT_OPERAND (RD, *ip, regno); ++ break; ++ case 's': ++ INSERT_OPERAND (RS, *ip, regno); ++ break; ++ case 't': ++ INSERT_OPERAND (RT, *ip, regno); ++ break; ++ } ++ ++ lastregno = regno; ++ continue; ++ ++ case 'u': ++ case 'k': ++ s_reset = s; ++ regno = 32; ++ if (s[0] == '$') ++ { ++ reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); ++ } ++ /* 2006-11-28 tonywu: add radiax alias name */ ++ c = *args; ++ ++ /* Now that we have assembled one operand, we use the args string ++ * to figure out where it goes in the instruction. */ ++ if (regno == 32) ++ as_bad (_("RLX: illegal register (%d) in %s"), regno, ++ str); ++ ++ switch (c) ++ { ++ case 'u': ++ INSERT_OPERAND (RD, *ip, regno); ++ break; ++ case 'k': ++ INSERT_OPERAND (RD, *ip, regno); ++ break; ++ } ++ ++ lastregno = regno; ++ continue; ++ ++ case '-': ++ /* 10bits offset used in ltw (OP_*_OFFSET6A), ++ * in fact it is 13 bits,multiple of 8; */ ++ if (*s == '(' && strchr (s + 1, '(') == 0) ++ { ++ imm_expr.X_op = O_constant; ++ imm_expr.X_add_number = 0; ++ continue; ++ } ++ ++ my_getExpression (&imm_expr, s); ++ check_absolute_expr (ip, &imm_expr); ++ if (imm_expr.X_op == O_constant) ++ { ++ if ((imm_expr.X_add_number % 8) != 0) ++ as_bad (_("(%d) is not multiple of 8"), ++ (int) imm_expr.X_add_number); ++ if (((imm_expr.X_add_number + 4096) & ~0x1FFF) != 0) ++ as_bad (_("(%d) is too large to fit in 13 bits"), ++ (int) imm_expr.X_add_number); ++ ip->insn_opcode |= ++ (((imm_expr.X_add_number >> 3) & OP_MASK_OFFSET6A) << ++ OP_SH_OFFSET6A); ++ imm_expr.X_op = O_absent; ++ } ++ else ++ { ++ *imm_reloc = BFD_RELOC_OFF6A; ++ } ++ s = expr_end; ++ continue; ++ /* 11 bits immediate used in lt,st (OP_*_IMMIDATE6b), ++ * in fact it is 14 bits, multiple of 8; */ ++ case '@': ++ if (*s == '(' && strchr (s + 1, '(') == 0) ++ { ++ imm_expr.X_op = O_constant; ++ imm_expr.X_add_number = 0; ++ continue; ++ } ++ my_getExpression (&imm_expr, s); ++ check_absolute_expr (ip, &imm_expr); ++ if (imm_expr.X_add_number % 8 != 0) ++ as_bad (_("(%d) is not multiple of 8"), ++ (int) imm_expr.X_add_number); ++ if (((imm_expr.X_add_number + 8192) & ~0x3FFF) != 0) ++ as_bad (_("(%d) is too large to fit in 14 bits"), ++ (int) imm_expr.X_add_number); ++ ip->insn_opcode |= ++ (((imm_expr.X_add_number >> 3) & OP_MASK_IMMIDATE6b) << ++ OP_SH_IMMIDATE6b); ++ imm_expr.X_op = O_absent; ++ s = expr_end; ++ continue; ++ ++ /* 4 bits immediate from 0 to 8,used in MFA,MFA2,RNDA2 (OP_*_IMMIDATE74) */ ++ case '#': ++ my_getExpression (&imm_expr, s); ++ check_absolute_expr (ip, &imm_expr); ++ if (imm_expr.X_add_number > 8 || imm_expr.X_add_number < 0) ++ as_bad (_("(%d) is out of range 0-8"), ++ (int) imm_expr.X_add_number); ++ ip->insn_opcode |= ++ ((imm_expr.X_add_number & OP_MASK_IMMIDATE74) << ++ OP_SH_IMMIDATE74); ++ imm_expr.X_op = O_absent; ++ s = expr_end; ++ continue; ++ /* 8 bits immediate ,used in lbp,stp,etc(OP_*_IMMIDATE88) */ ++ case '~': ++ my_getExpression (&imm_expr, s); ++ check_absolute_expr (ip, &imm_expr); ++ if ((strncmp (str, "lbp", 3) == 0) ++ || (strncmp (str, "sbp", 3) == 0)) ++ multipletype = 0; ++ else if ((strncmp (str, "lhp", 3) == 0) ++ || (strncmp (str, "shp", 3) == 0)) ++ multipletype = 2; ++ else if ((strncmp (str, "lwp", 3) == 0) ++ || (strncmp (str, "swp", 3) == 0)) ++ multipletype = 4; ++ else ++ multipletype = 8; ++ ++ switch (multipletype) ++ { ++ case 0: ++ if (((imm_expr.X_add_number + 128) & ~0xff) != 0) ++ as_bad (_("(%d) is too large to fit in 8 bits"), ++ (int) imm_expr.X_add_number); ++ break; ++ ++ case 2: ++ if ((imm_expr.X_add_number % 2) != 0) ++ as_bad (_("(%d) is not multiple of 2"), ++ (int) imm_expr.X_add_number); ++ if (((imm_expr.X_add_number + 256) & ~0x1FF) != 0) ++ as_bad (_("(%d) is too large to fit in 8 bits"), ++ (int) imm_expr.X_add_number); ++ imm_expr.X_add_number = imm_expr.X_add_number >> 1; ++ break; ++ ++ case 4: ++ if ((imm_expr.X_add_number % 4) != 0) ++ as_bad (_("(%d) is not multiple of 4"), ++ (int) imm_expr.X_add_number); ++ ++ if (((imm_expr.X_add_number + 512) & ~0x3FF) != 0) ++ as_bad (_("(%d) is too large to fit in 8 bits"), ++ (int) imm_expr.X_add_number); ++ imm_expr.X_add_number = imm_expr.X_add_number >> 2; ++ break; ++ ++ case 8: ++ if ((imm_expr.X_add_number % 8) != 0) ++ as_bad (_("(%d) is not multiple of 8"), ++ (int) imm_expr.X_add_number); ++ ++ if (((imm_expr.X_add_number + 1024) & ~0x7FF) != 0) ++ as_bad (_("(%d) is too large to fit in 8 bits"), ++ (int) imm_expr.X_add_number); ++ ++ imm_expr.X_add_number = imm_expr.X_add_number >> 3; ++ break; ++ } ++ ip->insn_opcode |= ++ ((imm_expr. ++ X_add_number & OP_MASK_IMMIDATE88) << OP_SH_IMMIDATE88); ++ imm_expr.X_op = O_absent; ++ s = expr_end; ++ continue; ++ ++ /* even register,used in lt,st,ltp,stp (OP_*_EVENREG) */ ++ case '`': ++ if (s[0] == '$') ++ { ++ regno = 0; ++ if (ISDIGIT (s[1])) ++ { ++ ++s; ++ do ++ { ++ regno *= 10; ++ regno += *s - '0'; ++ ++s; ++ } ++ while (ISDIGIT (*s)); ++ ++ } ++ else if ((s[1] == 'f') && (s[2] == 'p')) ++ { ++ regno = 30; ++ s += 3; ++ } ++ else if ((s[1] == 'a') && (s[2] == 't')) ++ { ++ regno = 1; ++ s += 3; ++ } ++ else ++ { ++ insn_error = "register needed!"; ++ return; ++ } ++ } ++ else ++ { ++ insn_error = "register needed!"; ++ return; ++ } ++ ++ if (regno > 31) ++ as_bad (_("invalid register number (%d)"), regno); ++ ++ if (regno % 2 != 0) ++ as_bad (_("not an even register number(%d) "), regno); ++ ++ ip->insn_opcode |= ++ (regno & OP_MASK_EVENREG) << OP_SH_EVENREG; ++ continue; ++ ++ case 'H': ++ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ++ s += 2; ++ if (ISDIGIT (*s)) ++ { ++ c = 0; ++ do ++ { ++ c *= 10; ++ c += *s - '0'; ++ ++s; ++ } ++ while (ISDIGIT (*s)); ++ } ++ else ++ c = 64; /* Invalid sel or stype value. */ ++ ++ if (c > 63) ++ as_bad (_("invalid coprocessor sel value (0-63)")); ++ ++ ip->insn_opcode |= (c & OP_MASK_RLX_SEL) << OP_SH_RLX_SEL; ++ continue; ++ ++ case 'I': ++ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ++ s += 2; ++ ++ if (ISDIGIT (*s)) ++ { ++ c = 0; ++ do ++ { ++ c *= 10; ++ c += *s - '0'; ++ ++s; ++ } ++ while (ISDIGIT (*s)); ++ } ++ else ++ c = 64; /* Invalid sel value. */ ++ ++ if (c > 63) ++ as_bad (_("invalid coprocessor stype value (0-63)")); ++ ++ ip->insn_opcode |= ++ (c & OP_MASK_RLX_STYPE) << OP_SH_RLX_STYPE; ++ continue; ++ } ++ break; ++ + case 'b': /* base register */ + case 'd': /* destination register */ + case 's': /* source register */ +@@ -9467,8 +9934,32 @@ do_msbd: + ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); + if (regno == AT && mips_opts.at) + { +- if (mips_opts.at == ATREG) +- as_warn (_("used $at without \".set noat\"")); ++ if (mips_opts.at == ATREG) { ++ if ((strncmp (ip->insn_mo->name, "mta2", 4) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "mfa", 3) != 0 ++ || *args != 't') ++ && (strncmp (ip->insn_mo->name, "diva", 4) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "mtru", 4) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "mfru", 4) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "multa", 5) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "mulna2", 6) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "cmulta", 6) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "madda", 5) != 0 ++ || *args != 'd') ++ && (strncmp (ip->insn_mo->name, "msuba", 5) != 0 ++ || *args != 'd') ++ && strncmp (ip->insn_mo->name, "addma", 5) != 0 ++ && strncmp (ip->insn_mo->name, "subma", 5) != 0 ++ && strncmp (ip->insn_mo->name, "rnda2", 5) != 0) ++ as_warn (_("used $at without \".set noat\"")); ++ } + else + as_warn (_("used $%u with \".set at=$%u\""), + regno, mips_opts.at); +@@ -9511,11 +10002,53 @@ do_msbd: + { + case 'r': + case 's': ++ if (strncmp (ip->insn_mo->name, "addma", 5) == 0 ++ || strncmp (ip->insn_mo->name, "subma", 5) == 0) ++ { ++ if ((regno & 3) == 0 || (regno & 3) == 3) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ } + case 'v': + case 'b': + INSERT_OPERAND (RS, *ip, regno); + break; + case 'd': ++ if (strncmp (ip->insn_mo->name, "addma", 5) == 0 ++ || strncmp (ip->insn_mo->name, "subma", 5) == 0) ++ { ++ if (((regno & 3) == 0) || ((regno & 3) == 3)) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ } ++ ++ if (strncmp (ip->insn_mo->name, "diva", 4) == 0 ++ || (strlen (ip->insn_mo->name) == 5 ++ && strncmp (ip->insn_mo->name, "multa", 5) == 0) ++ || strncmp (ip->insn_mo->name, "multau", 6) == 0 ++ || strncmp (ip->insn_mo->name, "cmulta", 6) == 0 ++ || (strlen (ip->insn_mo->name) == 5 ++ && strncmp (ip->insn_mo->name, "madda", 5) == 0) ++ || strncmp (ip->insn_mo->name, "maddau", 6) == 0 ++ || (strlen (ip->insn_mo->name) == 5 ++ && strncmp (ip->insn_mo->name, "msuba", 5) == 0) ++ || strncmp (ip->insn_mo->name, "msubau", 6) == 0) ++ { ++ if ((regno & 3) != 3) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ } ++ ++ if (strncmp (ip->insn_mo->name, "multa2", 6) == 0 ++ || strncmp (ip->insn_mo->name, "mulna2", 6) == 0 ++ || strncmp (ip->insn_mo->name, "rnadda2", 6) == 0 ++ || strncmp (ip->insn_mo->name, "msuba2", 6) == 0 ++ || strncmp (ip->insn_mo->name, "mta2", 4) == 0) ++ { ++ if ((regno & 3) == 0) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ } + case 'G': + case 'K': + case 'g': +@@ -9527,6 +10060,25 @@ do_msbd: + break; + case 'w': + case 't': ++ if (strncmp (ip->insn_mo->name, "addma", 5) == 0 || ++ strncmp (ip->insn_mo->name, "subma", 5) == 0 || ++ strncmp (ip->insn_mo->name, "mfa", ++ strlen (ip->insn_mo->name)) == 0) ++ { ++ if (((regno & 3) == 0) || ((regno & 3) == 3)) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ } ++ ++ if (strncmp (ip->insn_mo->name, "mfa2", 4) == 0) ++ if ((regno & 3) != 3) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); ++ ++ if (strncmp (ip->insn_mo->name, "rnda2", 5) == 0) ++ if ((regno & 3) == 0) ++ as_bad (_("Illegal reg number (%d) in %s"), regno, ++ str); + case 'E': + INSERT_OPERAND (RT, *ip, regno); + break; +@@ -11855,6 +12407,9 @@ mips_after_parse_args (void) + if (mips_arch_string != 0) + arch_info = mips_parse_cpu ("-march", mips_arch_string); + ++ if (mips_tune_string != 0) ++ mips_set_architecture (mips_parse_cpu ("-mtune", mips_tune_string)); ++ + if (file_mips_isa != ISA_UNKNOWN) + { + /* Handle -mipsN. At this point, file_mips_isa contains the +@@ -12422,6 +12977,40 @@ md_apply_fix (fixS *fixP, valueT *valP, + fixP->fx_done = 0; + break; + ++ case BFD_RELOC_OFF6A: ++ if (fixP->fx_done) ++ { ++ valueT tmp_value; ++ valueT org_value; ++ ++ buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where); ++ tmp_value = ++ *(valueT *) (fixP->fx_frag->fr_literal + fixP->fx_where); ++ org_value = *valP; ++ ++ if (target_big_endian) ++ { ++ tmp_value = ++ (((tmp_value & 0xff) << 24) | ++ ((tmp_value & 0xff00) << 8) | ++ (((tmp_value & 0xff0000) >> 8)) | ++ (((tmp_value & 0xff000000) >> 24))); ++ } ++ ++ if ((org_value % 8) != 0) ++ as_bad (_("(%d) is not multiple of 8"), (int) org_value); ++ ++ if ((org_value & ~0x1FFF) != 0) ++ as_bad (_("(%d) is too large to stay in 13 bits"), ++ (int) org_value); ++ ++ tmp_value |= ++ (((org_value >> 3) & OP_MASK_OFFSET6A) << OP_SH_OFFSET6A); ++ md_number_to_chars ((char *) buf, tmp_value, 4); ++ } ++ break; ++ ++ + default: + internalError (); + } +@@ -15190,6 +15779,12 @@ static const struct mips_cpu_info mips_c + { "r3000", 0, ISA_MIPS1, CPU_R3000 }, + { "r2000", 0, ISA_MIPS1, CPU_R3000 }, + { "r3900", 0, ISA_MIPS1, CPU_R3900 }, ++ {"lx4180", 0, ISA_MIPS1, CPU_LX4180}, ++ {"rlx4181", 0, ISA_MIPS1, CPU_RLX4181}, ++ {"rlx4281", 0, ISA_MIPS1, CPU_RLX4281}, ++ {"rlx5181", 0, ISA_MIPS1, CPU_RLX5181}, ++ {"lx5280", 0, ISA_MIPS1, CPU_LX5280}, ++ {"rlx5281", 0, ISA_MIPS1, CPU_RLX5281}, + + /* MIPS II */ + { "r6000", 0, ISA_MIPS2, CPU_R6000 }, +@@ -15353,14 +15948,28 @@ mips_matching_cpu_name_p (const char *ca + + /* If not, try comparing based on numerical designation alone. + See if GIVEN is an unadorned number, or 'r' followed by a number. */ +- if (TOLOWER (*given) == 'r') ++ ++ /* 2006-01-19 tonywu: add to parse LX/RLX CPUs */ ++ if (TOLOWER (given[0]) == 'l' && TOLOWER (given[1]) == 'x') ++ given += 2; ++ else if (TOLOWER (given[0]) == 'r' && ++ TOLOWER (given[1]) == 'l' && TOLOWER (given[2]) == 'x') ++ given += 3; ++ else if (TOLOWER (*given) == 'r') + given++; ++ + if (!ISDIGIT (*given)) + return FALSE; + + /* Skip over some well-known prefixes in the canonical name, + hoping to find a number there too. */ +- if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r') ++ /* 2006-01-19 tonywu: add to parse LX/RLX CPUs */ ++ if (TOLOWER (canonical[0]) == 'l' && TOLOWER (canonical[1]) == 'x') ++ canonical += 2; ++ else if (TOLOWER (canonical[0]) == 'r' && ++ TOLOWER (canonical[1]) == 'l' && TOLOWER (canonical[2]) == 'x') ++ canonical += 3; ++ else if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r') + canonical += 2; + else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm') + canonical += 2; +@@ -15624,3 +16233,83 @@ tc_mips_regname_to_dw2regnum (char *regn + + return regnum; + } ++ ++static inline int ++rlx_is_insn_lt (const struct mips_cl_insn *insn1, ++ const struct mips_cl_insn *insn2) ++{ ++ int is_lt = 0; ++ ++ if (insn1 == NULL || insn2 == NULL) ++ return 0; ++ ++ if (strncmp (insn1->insn_mo->name, "lt", 2) == 0) ++ is_lt = 1; ++ else if (strncmp (insn1->insn_mo->name, "ltw", 3) == 0) ++ is_lt = 1; ++ ++ if (is_lt == 0) ++ return 0; ++ ++ int regno1 = EXTRACT_OPERAND (RT, *insn1); ++ int regno2 = regno1 + 1; ++ ++ if (insn_uses_reg (insn2, regno1, MIPS_GR_REG) || ++ insn_uses_reg (insn2, regno2, MIPS_GR_REG)) ++ return 1; ++ ++ return 0; ++} ++ ++static inline int ++rlx_is_insn_st (const struct mips_cl_insn *insn1, ++ const struct mips_cl_insn *insn2) ++{ ++ int is_st = 0; ++ ++ if (insn1 == NULL || insn2 == NULL) ++ return 0; ++ ++ if (strncmp (insn2->insn_mo->name, "st", 2) == 0) ++ is_st = 1; ++ ++ if (is_st == 0) ++ return 0; ++ ++ int regno1 = EXTRACT_OPERAND (RT, *insn1); ++ int regno2 = 0; ++ ++ if (regno1 % 2 == 0) ++ regno2 = regno1 + 1; ++ else ++ regno2 = regno1 - 1; ++ ++ if (insn_uses_reg (insn2, regno1, MIPS_GR_REG) || ++ insn_uses_reg (insn2, regno2, MIPS_GR_REG)) ++ return 1; ++ ++ return 0; ++} ++ ++/* 2006-01-05 tonywu: merged from 2.14 */ ++static inline int ++rlx_nops_for_new_insn (const struct mips_cl_insn *pre, ++ const struct mips_cl_insn *now) ++{ ++ if ((pre == NULL) || (now == NULL)) ++ return 0; ++ ++ if ((pre->insn_mo->match == 0 && pre->insn_mo->mask == 0xffffffff) || ++ (now->insn_mo->match == 0 && now->insn_mo->mask == 0xffffffff)) ++ return 0; ++ ++ if (pre->insn_mo == &dummy_opcode || now->insn_mo == &dummy_opcode) ++ return 0; ++ ++ if (strcmp (pre->insn_mo->name, "madda") == 0 && ++ strcmp (now->insn_mo->name, "mfa") == 0 && ++ EXTRACT_OPERAND (RD, *pre) == EXTRACT_OPERAND (RT, *now)) ++ return 2; ++ ++ return 0; ++} +Index: binutils/bfd/elf32-mips.c +=================================================================== +--- binutils.orig/bfd/elf32-mips.c ++++ binutils/bfd/elf32-mips.c +@@ -717,6 +717,20 @@ static reloc_howto_type elf_mips_howto_t + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ ++ /* relocation added by dbb */ ++ HOWTO (R_RELOC_OFF6A, /* type */ ++ 3, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 10, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 6, /* bitpos */ ++ complain_overflow_dont, /* complain_on_overflow */ ++ NULL, /* special_function */ ++ "R_RELOC_OFF6A", /* name */ ++ TRUE, /* partial_inplace */ ++ 0x0000FFC0, /* src_mask */ ++ 0x0000FFC0, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This +@@ -1274,7 +1288,8 @@ static const struct elf_reloc_map mips_r + { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 }, + { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 }, + { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 }, +- { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 } ++ { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }, ++ { BFD_RELOC_OFF6A, R_RELOC_OFF6A} + }; + + static const struct elf_reloc_map mips16_reloc_map[] = +Index: binutils/bfd/elfxx-mips.c +=================================================================== +--- binutils.orig/bfd/elfxx-mips.c ++++ binutils/bfd/elfxx-mips.c +@@ -5361,6 +5361,12 @@ mips_elf_calculate_relocation (bfd *abfd + } + break; + ++ case R_RELOC_OFF6A: ++ value = (symbol + ((addend >> 6) << 3)); ++ if ((value % 8) != 0) ++ return bfd_reloc_notmultipleof8_ltw; ++ value = ((value >> 3) << 6) & howto->dst_mask; ++ break; + case R_MIPS_LITERAL: + /* Because we don't merge literal sections, we can handle this + just like R_MIPS_GPREL16. In the long run, we should merge +@@ -9156,6 +9162,12 @@ _bfd_mips_elf_relocate_section (bfd *out + } + break; + ++ case bfd_reloc_notmultipleof8_ltw: ++ msg = _("offset in ltw instruction is not multiple of 8"); ++ info->callbacks->warning ++ (info, msg, name, input_bfd, input_section, rel->r_offset); ++ return FALSE; ++ + case bfd_reloc_ok: + break; + +Index: binutils/bfd/libbfd.h +=================================================================== +--- binutils.orig/bfd/libbfd.h ++++ binutils/bfd/libbfd.h +@@ -2126,6 +2126,7 @@ static const char *const bfd_reloc_code_ + "BFD_RELOC_MICROBLAZE_64_GOTOFF", + "BFD_RELOC_MICROBLAZE_32_GOTOFF", + "BFD_RELOC_MICROBLAZE_COPY", ++ "BFD_RELOC_OFF6A", + "@@overflow: BFD_RELOC_UNUSED@@", + }; + #endif +Index: binutils/bfd/reloc.c +=================================================================== +--- binutils.orig/bfd/reloc.c ++++ binutils/bfd/reloc.c +@@ -52,6 +52,7 @@ SECTION + #include "bfd.h" + #include "bfdlink.h" + #include "libbfd.h" ++#include "elf/mips.h" + /* + DOCDD + INODE +@@ -1215,6 +1216,15 @@ space consuming. For each target: + } + */ + ++ ++ switch (howto->type) ++ { ++ case R_RELOC_OFF6A: ++ if ((relocation % 8) != 0) ++ return bfd_reloc_notmultipleof8_ltw; ++ break; ++ } ++ + relocation >>= (bfd_vma) howto->rightshift; + + /* Shift everything up to where it's going to be used. */ +Index: binutils/gas/write.c +=================================================================== +--- binutils.orig/gas/write.c ++++ binutils/gas/write.c +@@ -1133,6 +1133,9 @@ install_reloc (asection *sec, arelent *r + case bfd_reloc_outofrange: + as_bad_where (file, line, _("relocation out of range")); + break; ++ case bfd_reloc_notmultipleof8_ltw: ++ as_bad_where (file, line, _("offset in ltw instruction is not multiple of 8")); ++ break; + default: + as_fatal (_("%s:%u: bad return from bfd_install_relocation: %x"), + file, line, s); +Index: binutils/include/elf/mips.h +=================================================================== +--- binutils.orig/include/elf/mips.h ++++ binutils/include/elf/mips.h +@@ -88,7 +88,8 @@ START_RELOC_NUMBERS (elf_mips_reloc_type + RELOC_NUMBER (R_MIPS_TLS_TPREL_HI16, 49) + RELOC_NUMBER (R_MIPS_TLS_TPREL_LO16, 50) + RELOC_NUMBER (R_MIPS_GLOB_DAT, 51) +- FAKE_RELOC (R_MIPS_max, 52) ++ RELOC_NUMBER (R_RELOC_OFF6A, 52) ++ FAKE_RELOC (R_MIPS_max, 53) + /* These relocs are used for the mips16. */ + FAKE_RELOC (R_MIPS16_min, 100) + RELOC_NUMBER (R_MIPS16_26, 100) |