diff --git a/gold/nanomips-insn-property.h b/gold/nanomips-insn-property.h index ff7b9135ff26..2d31081de196 100644 --- a/gold/nanomips-insn-property.h +++ b/gold/nanomips-insn-property.h @@ -75,7 +75,9 @@ enum Transform_type // Transform to 16-bit save/restore.jrc instruction. TT_SAVERESTORE16, // Transform to 16-bit bxxzc instruction. - TT_PCREL16_ZERO + TT_PCREL16_ZERO, + // Transform to avoid hw1100880 issue + TT_IMM48_FIX, }; // The Nanomips_insn_template class is to store information about a diff --git a/gold/nanomips-insn.def b/gold/nanomips-insn.def index 3a40af0d5cdc..f0d457f45cca 100644 --- a/gold/nanomips-insn.def +++ b/gold/nanomips-insn.def @@ -68,7 +68,7 @@ // addiugp[48] $reg, %gprel32(sym) #define ADDIUGP48(reloc, tregmap) NIT48("addiugp[48]", 0x6002, reloc, INS_REG(5, 5, tregmap)) // lapc[48] $reg, sym -#define LAPC48 NIT48("lapc[48]", 0x6003, PC_I32, INS_REG(5, 5, TREG)) +#define LAPC48(tregmap) NIT48("lapc[48]", 0x6003, PC_I32, INS_REG(5, 5, tregmap)) // li[48] $reg, sym #define LI48 NIT48("li[48]", 0x6000, I32, INS_REG(5, 5, TREG)) // lwpc[48] $reg, %reloc(sym) @@ -80,7 +80,9 @@ // addiu[gp.w] $reg, $gp, %gprel(sym) #define ADDIUGPW32 NIT32("addiu[gp.w]", 0x40000000, GPREL19_S2, INS_REG(21, 5, TREG), NULL) // addu $reg, $reg, $gp -#define ADDU32(tregmap, sregmap) NIT32("addu", 0x23800150, NONE, INS_REG(16, 5, tregmap), INS_REG(11, 5, sregmap)) +#define ADDUGP32(tregmap, sregmap) NIT32("addu", 0x23800150, NONE, INS_REG(16, 5, tregmap), INS_REG(11, 5, sregmap)) +// addu $reg, $reg +#define ADDU32(tregmap, sregmap) NIT32("addu", 0x20000150, NONE, INS_REG(11, 10, tregmap), INS_REG(21, 5, sregmap)) // aluipc $reg, %reloc(sym) #define ALUIPC32(reloc, tregmap) NIT32("aluipc", 0xe0000002, reloc, INS_REG(21, 5, tregmap), NULL) // balc sym @@ -222,6 +224,19 @@ NTT(GPREL32_WORD, RELS(R(GPREL_I32)), INSNS(ADDI // lapc[48] $reg, sym NIP48("lapc[48]", 0x6003, EXT_REG(5, 5)) NTT(PCREL32, RELS(R(PC_I32)), INSNS(LAPC32(TREG))) +NTT(IMM48_FIX, RELS(R(PC_I32)), INSNS(ALUIPC32(PC_HI20, TREG), ORI32(LO12, TREG, TREG))) + +// li[48] $reg, sym +NIP48("li[48]", 0x6000, EXT_REG(5, 5)) +NTT(IMM48_FIX, RELS(R(I32)), INSNS(LAPC48(TREG))) + +// addiu[48] $reg, sym +NIP48("addiu[48]", 0x6001, EXT_REG(5, 5)) +NTT(IMM48_FIX, RELS(R(I32)), INSNS(LAPC48(SREG), ADDU32(TREG, SREG))) + +// lapc[48] $reg, sym +NIP48("swpc[48]", 0x600f, EXT_REG(5, 5)) +NTT(IMM48_FIX, RELS(R(PC_I32)), INSNS(ALUIPC32(PC_HI20, SREG), SW32(LO12))) // Transformations for 32-bit instructions. @@ -232,7 +247,7 @@ NTT(ABS_NMF, RELS(R(PC25_S1)), INSNS(LI48 NTT(ABS16_LONG, RELS(R(PC25_S1)), INSNS(LUI32(HI20, SREG), ORI32(LO12, SREG, SREG), JALRC16(SREG))) NTT(ABS32_LONG, RELS(R(PC25_S1)), INSNS(LUI32(HI20, SREG), ORI32(LO12, SREG, SREG), JALRC32)) NTT(PCREL16, RELS(R(PC25_S1)), INSNS(BALC16)) -NTT(PCREL_NMF, RELS(R(PC25_S1)), INSNS(LAPC48, JALRC16(SREG))) +NTT(PCREL_NMF, RELS(R(PC25_S1)), INSNS(LAPC48(TREG), JALRC16(SREG))) NTT(PCREL16_LONG, RELS(R(PC25_S1)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, SREG, SREG), JALRC16(SREG))) NTT(PCREL32_LONG, RELS(R(PC25_S1)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, SREG, SREG), JALRC32)) @@ -242,7 +257,7 @@ NTT(ABS_NMF, RELS(R(PC25_S1)), INSNS(LI48 NTT(ABS16_LONG, RELS(R(PC25_S1)), INSNS(LUI32(HI20, SREG), ORI32(LO12, SREG, SREG), JRC16)) NTT(ABS32_LONG, RELS(R(PC25_S1)), INSNS(LUI32(HI20, SREG), ORI32(LO12, SREG, SREG), JRC32)) NTT(PCREL16, RELS(R(PC25_S1)), INSNS(BC16)) -NTT(PCREL_NMF, RELS(R(PC25_S1)), INSNS(LAPC48, JRC16)) +NTT(PCREL_NMF, RELS(R(PC25_S1)), INSNS(LAPC48(TREG), JRC16)) NTT(PCREL16_LONG, RELS(R(PC25_S1)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, SREG, SREG), JRC16)) NTT(PCREL32_LONG, RELS(R(PC25_S1)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, SREG, SREG), JRC32)) @@ -251,7 +266,7 @@ NIP32("lapc", 0x04000000, EXT_REG(21, 5), NULL, NTT(DISCARD, RELS(R(PC21_S1)), INSNS()) NTT(ABS_NMF, RELS(R(PC21_S1)), INSNS(LI48)) NTT(ABS32_LONG, RELS(R(PC21_S1)), INSNS(LUI32(HI20, TREG), ORI32(LO12, TREG, TREG))) -NTT(PCREL_NMF, RELS(R(PC21_S1)), INSNS(LAPC48)) +NTT(PCREL_NMF, RELS(R(PC21_S1)), INSNS(LAPC48(TREG))) NTT(PCREL32_LONG, RELS(R(PC21_S1)), INSNS(ALUIPC32(PC_HI20, TREG), ORI32(LO12, TREG, TREG))) // move.balc $reg, $reg, sym @@ -325,16 +340,16 @@ NTT(PCREL_NMF, RELS(R(GPREL19_S2)), INSNS(LWPC NTT(PCREL32_LONG, RELS(R(GPREL19_S2)), INSNS(ALUIPC32(PC_HI20, SREG), LW32(LO12))) NTT(GPREL16, RELS(R(GPREL19_S2)), INSNS(LWGP16)) NTT(GPREL32_NMF, RELS(R(GPREL19_S2)), INSNS(ADDIUGP48(GPREL_I32, SREG), LW32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LW32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LW32(GPREL_LO12))) NTT(ABS_NMF, RELS(R(GOT_DISP)), INSNS(LI48)) NTT(ABS32_LONG, RELS(R(GOT_DISP)), INSNS(LUI32(HI20, TREG), ORI32(LO12, TREG, TREG))) NTT(PCREL32, RELS(R(GOT_DISP)), INSNS(LAPC32(SREG))) -NTT(PCREL_NMF, RELS(R(GOT_DISP)), INSNS(LAPC48)) +NTT(PCREL_NMF, RELS(R(GOT_DISP)), INSNS(LAPC48(TREG))) NTT(PCREL32_LONG, RELS(R(GOT_DISP)), INSNS(ALUIPC32(PC_HI20, TREG), ORI32(LO12, TREG, TREG))) NTT(GPREL32, RELS(R(GOT_DISP)), INSNS(ADDIUGPB32)) NTT(GPREL32_WORD, RELS(R(GOT_DISP)), INSNS(ADDIUGPW32)) NTT(GPREL_NMF, RELS(R(GOT_DISP)), INSNS(ADDIUGP48(GPREL_I32, TREG))) -NTT(GPREL_LONG, RELS(R(GOT_DISP)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDU32(SREG, TREG))) +NTT(GPREL_LONG, RELS(R(GOT_DISP)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDUGP32(SREG, TREG))) NTT(GOTPCREL_NMF, RELS(R(TLS_GOTTPREL)), INSNS(LWPC48(TLS_GOTTPREL_PC_I32))) NTT(DISCARD, RELS(R(GOT_CALL), R(GOT_PAGE)), INSNS()) NTT(GOTPCREL_NMF, RELS(R(GOT_DISP), R(GOT_CALL), R(GOT_PAGE)), INSNS(LWPC48(GOTPC_I32))) @@ -347,14 +362,14 @@ NTT(PCREL_NMF, RELS(R(GPREL19_S2)), INSNS(SWPC NTT(PCREL32_LONG, RELS(R(GPREL19_S2)), INSNS(ALUIPC32(PC_HI20, SREG), SW32(LO12))) NTT(GPREL16, RELS(R(GPREL19_S2)), INSNS(SWGP16)) NTT(GPREL32_NMF, RELS(R(GPREL19_S2)), INSNS(ADDIUGP48(GPREL_I32, SREG), SW32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SW32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SW32(GPREL_LO12))) // addiu[gp.w] $reg, $gp, %reloc(sym) NIP32("addiu[gp.w]", 0x40000000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(HI20, SREG), ORI32(LO12, TREG, SREG))) NTT(PCREL32_LONG, RELS(R(GPREL19_S2)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, TREG, SREG))) NTT(GPREL_NMF, RELS(R(GPREL19_S2)), INSNS(ADDIUGP48(GPREL_I32, TREG))) -NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDU32(SREG, TREG))) +NTT(GPREL_LONG, RELS(R(GPREL19_S2)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDUGP32(SREG, TREG))) NTT(GPREL_NMF, RELS(R(TLS_GD)), INSNS(ADDIUGP48(TLS_GD_I32, TREG))) NTT(GPREL_NMF, RELS(R(TLS_LD)), INSNS(ADDIUGP48(TLS_LD_I32, TREG))) @@ -364,49 +379,49 @@ NTT(ABS32_LONG, RELS(R(GPREL18)), INSNS(LUI3 NTT(PCREL32_LONG, RELS(R(GPREL18)), INSNS(ALUIPC32(PC_HI20, SREG), ORI32(LO12, TREG, SREG))) NTT(GPREL32_WORD, RELS(R(GPREL18)), INSNS(ADDIUGPW32)) NTT(GPREL_NMF, RELS(R(GPREL18)), INSNS(ADDIUGP48(GPREL_I32, TREG))) -NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDU32(SREG, TREG))) +NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ORI32(GPREL_LO12, SREG, SREG), ADDUGP32(SREG, TREG))) // lb $reg, %gprel(sym)($gp) NIP32("lb[gp]", 0x44000000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL18)), INSNS(LUI32(HI20, SREG), LB32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL18)), INSNS(ALUIPC32(PC_HI20, SREG), LB32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL18)), INSNS(ADDIUGP48(GPREL_I32, SREG), LB32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LB32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LB32(GPREL_LO12))) // lbu $reg, %gprel(sym)($gp) NIP32("lbu[gp]", 0x44080000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL18)), INSNS(LUI32(HI20, SREG), LBU32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL18)), INSNS(ALUIPC32(PC_HI20, SREG), LBU32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL18)), INSNS(ADDIUGP48(GPREL_I32, SREG), LBU32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LBU32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LBU32(GPREL_LO12))) // sb $reg, %gprel(sym)($gp) NIP32("sb[gp]", 0x44040000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL18)), INSNS(LUI32(HI20, SREG), SB32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL18)), INSNS(ALUIPC32(PC_HI20, SREG), SB32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL18)), INSNS(ADDIUGP48(GPREL_I32, SREG), SB32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SB32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL18)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SB32(GPREL_LO12))) // lh $reg, %gprel(sym)($gp) NIP32("lh[gp]", 0x44100000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(HI20, SREG), LH32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL17_S1)), INSNS(ALUIPC32(PC_HI20, SREG), LH32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL17_S1)), INSNS(ADDIUGP48(GPREL_I32, SREG), LH32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LH32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LH32(GPREL_LO12))) // lhu $reg, %gprel(sym)($gp) NIP32("lhu[gp]", 0x44100001, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(HI20, SREG), LHU32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL17_S1)), INSNS(ALUIPC32(PC_HI20, SREG), LHU32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL17_S1)), INSNS(ADDIUGP48(GPREL_I32, SREG), LHU32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LHU32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LHU32(GPREL_LO12))) // sh $reg, %gprel(sym)($gp) NIP32("sh[gp]", 0x44140000, EXT_REG(21, 5), NULL, NULL, NULL) NTT(ABS32_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(HI20, SREG), SH32(LO12))) NTT(PCREL32_LONG, RELS(R(GPREL17_S1)), INSNS(ALUIPC32(PC_HI20, SREG), SH32(LO12))) NTT(GPREL32_NMF, RELS(R(GPREL17_S1)), INSNS(ADDIUGP48(GPREL_I32, SREG), SH32(NONE))) -NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SH32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GPREL17_S1)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SH32(GPREL_LO12))) // lb $reg, %got_ofst(sym)($reg) NIP32("lb", 0x84000000, EXT_REG(21, 5), valid_reg, EXT_REG(16, 5), valid_reg) @@ -417,7 +432,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(LBGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LB16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LB32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LB32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LB32(GPREL_LO12))) // lbu $reg, %got_ofst(sym)($reg) NIP32("lbu", 0x84002000, EXT_REG(21, 5), valid_reg, EXT_REG(16, 5), valid_reg) @@ -428,7 +443,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(LBUGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LBU16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LBU32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LBU32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LBU32(GPREL_LO12))) // lh $reg, %got_ofst(sym)($reg) NIP32("lh", 0x84004000, EXT_REG(21, 5), valid_reg, EXT_REG(16, 5), valid_reg) @@ -439,7 +454,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(LHGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LH16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LH32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LH32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LH32(GPREL_LO12))) // lhu $reg, %got_ofst(sym)($reg) NIP32("lhu", 0x84006000, EXT_REG(21, 5), valid_reg, EXT_REG(16, 5), valid_reg) @@ -450,7 +465,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(LHUGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LHU16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LHU32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LHU32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LHU32(GPREL_LO12))) // lw $reg, %reloc(sym)($reg) NIP32("lw", 0x84008000, EXT_REG(21, 5), valid_reg, EXT_REG(16, 5), valid_reg) @@ -464,7 +479,7 @@ NTT(GPREL16, RELS(R(GOT_OFST)), INSNS(LWGP NTT(GPREL32_WORD, RELS(R(GOT_OFST)), INSNS(LWGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LW16(NONE))) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), LW32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), LW32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), LW32(GPREL_LO12))) // restore u, dst1, [dst2, ...] where gp = 1 NIP32("restore[gp]", 0x80003006, EXT_REG(16, 4), NULL, ext_sres_fields, NULL) @@ -489,7 +504,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(SBGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SB16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SB32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SB32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SB32(GPREL_LO12))) // sh $reg, %got_ofst(sym)($reg) NIP32("sh", 0x84005000, EXT_REG(21, 5), valid_st_src_reg, EXT_REG(16, 5), valid_reg) @@ -500,7 +515,7 @@ NTT(PCREL32_LONG, RELS(R(GOT_OFST)), INSNS(ALUI NTT(GPREL32, RELS(R(GOT_OFST)), INSNS(SHGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SH16)) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SH32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SH32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SH32(GPREL_LO12))) // sw $reg, %reloc(sym)($reg) NIP32("sw", 0x84009000, EXT_REG(21, 5), valid_st_src_reg, EXT_REG(16, 5), valid_reg) @@ -514,7 +529,7 @@ NTT(GPREL16, RELS(R(GOT_OFST)), INSNS(SWGP NTT(GPREL32_WORD, RELS(R(GOT_OFST)), INSNS(SWGP32)) NTT(GPREL_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SW16(NONE))) NTT(GPREL32_NMF, RELS(R(GOT_OFST)), INSNS(ADDIUGP48(GPREL_I32, SREG), SW32(NONE))) -NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDU32(SREG, SREG), SW32(GPREL_LO12))) +NTT(GPREL_LONG, RELS(R(GOT_OFST)), INSNS(LUI32(GPREL_HI20, SREG), ADDUGP32(SREG, SREG), SW32(GPREL_LO12))) // jalrc $ra, $reg NIP32("jalrc", 0x4be00000, NULL, NULL, EXT_REG(16, 5), NULL) @@ -568,5 +583,5 @@ NTT(ABS_NMF, RELS(R(JALR16)), INSNS(LI48 NTT(ABS16_LONG, RELS(R(JALR16)), INSNS(LUI32(HI20, TREG), ORI32(LO12, TREG, TREG), JALRC16(TREG))) NTT(PCREL16, RELS(R(JALR16)), INSNS(BALC16)) NTT(PCREL32, RELS(R(JALR16)), INSNS(BALC32)) -NTT(PCREL_NMF, RELS(R(JALR16)), INSNS(LAPC48, JALRC16(TREG))) +NTT(PCREL_NMF, RELS(R(JALR16)), INSNS(LAPC48(TREG), JALRC16(TREG))) NTT(PCREL16_LONG, RELS(R(JALR16)), INSNS(ALUIPC32(PC_HI20, TREG), ORI32(LO12, TREG, TREG), JALRC16(TREG))) diff --git a/gold/nanomips-reloc.def b/gold/nanomips-reloc.def index e7b68b9dc1a4..43494d87e102 100644 --- a/gold/nanomips-reloc.def +++ b/gold/nanomips-reloc.def @@ -56,7 +56,7 @@ NRD(HI20, STATIC, 32, 20, 0, NRD(LO12, STATIC, 32, 12, 0xfc00f000, Symbol::ABSOLUTE_REF) NRD(GPREL_I32, STATIC, 48, 32, 0xfc1f, Symbol::RELATIVE_REF) NRD(PC_I32, STATIC, 48, 32, 0xfc1f, Symbol::RELATIVE_REF) -NRD(I32, STATIC, 48, 32, 0, Symbol::ABSOLUTE_REF) +NRD(I32, STATIC, 48, 32, 0xfc1f, Symbol::ABSOLUTE_REF) NRD(GOT_DISP, STATIC, 32, 21, 0xfc000003, Symbol::RELATIVE_REF) NRD(GOTPC_I32, STATIC, 48, 32, 0, Symbol::RELATIVE_REF) NRD(GOTPC_HI20, STATIC, 32, 20, 0, Symbol::RELATIVE_REF) diff --git a/gold/nanomips.cc b/gold/nanomips.cc index b4bf69ea9194..3ce9bf88329f 100644 --- a/gold/nanomips.cc +++ b/gold/nanomips.cc @@ -2495,6 +2495,15 @@ class Nanomips_relocate_functions } public: + static inline bool + value_needs_hw1100880_fix(Address value) + { + if (!parameters->options().fix_nmips_hw1100880()) + return false; + + return (((value & 0x50016400) == 0x50012400) && + (((value >> 24) & 0x7) == 0x1 || ((value >> 24) & 0x2) == 0x2)); + } // R_NANOMIPS_GOT_DISP, R_NANOMIPS_GOT_PAGE, R_NANOMIPS_GOT_CALL, // R_NANOMIPS_TLS_GD, , R_NANOMIPS_TLS_LD, R_NANOMIPS_TLS_GOTTPREL static inline Status @@ -2646,8 +2655,17 @@ class Nanomips_relocate_functions // R_NANOMIPS_TLS_GOTTPREL_PC_I32, R_NANOMIPS_TLS_TPREL_I32, // R_NANOMIPS_TLS_DTPREL_I32 static inline Status - rel48(unsigned char* view, Address value, bool should_check_overflow) + rel48(unsigned char* view, Address value, bool should_check_overflow, + const Nanomips_reloc_property* reloc_property) { + if (value_needs_hw1100880_fix(value) && + (reloc_property->name() == "li[48]" || + reloc_property->name() == "addiu[48]" || + reloc_property->name() == "addiugp[48]" || + reloc_property->name() == "lapc[48]" || + reloc_property->name() == "swpc[48]")) + return Status::STATUS_UNALIGNED; + Nanomips_insn_swap<48, big_endian>::writeval(view, value); return (should_check_overflow ? check_overflow<32>(value, CHECK_SIGNED) : STATUS_OKAY); @@ -4558,11 +4576,17 @@ Nanomips_transformations::transform( switch (r_type) { case elfcpp::R_NANOMIPS_GPREL_I32: - case elfcpp::R_NANOMIPS_PC_I32: r_offset -= 2; treg = insn_property->treg(insn); sreg = 0; break; + case elfcpp::R_NANOMIPS_PC_I32: + case elfcpp::R_NANOMIPS_I32: + r_offset -= 2; + treg = insn_property->treg(insn); + treg = treg << 5 | treg; + sreg = parameters->options().expand_reg(); + break; case elfcpp::R_NANOMIPS_PC25_S1: treg = parameters->options().expand_reg(); sreg = parameters->options().expand_reg(); @@ -5248,6 +5272,8 @@ Nanomips_expand_insn::find_insn( case elfcpp::R_NANOMIPS_TLS_GD: case elfcpp::R_NANOMIPS_TLS_LD: case elfcpp::R_NANOMIPS_TLS_GOTTPREL: + case elfcpp::R_NANOMIPS_PC_I32: + case elfcpp::R_NANOMIPS_I32: return nanomips_insn_property_table->get_insn_property(insn, mask, r_type); default: @@ -5344,6 +5370,11 @@ Nanomips_expand_insn::expand_type( case elfcpp::R_NANOMIPS_LO4_S2: // Transform [ls]w[16] into [ls]w. return TT_ABS32; + case elfcpp::R_NANOMIPS_PC_I32: + case elfcpp::R_NANOMIPS_I32: + return (insn_property->has_transform(TT_IMM48_FIX, r_type) + ? TT_IMM48_FIX + : TT_NONE); default: gold_unreachable(); } @@ -5420,6 +5451,7 @@ Nanomips_expand_insn::type( Address address, Address gp) { + typedef Nanomips_relocate_functions Reloc_funcs; const Address invalid_address = static_cast
(0) - 1; const Nanomips_relobj* relobj = Nanomips_relobj::as_nanomips_relobj(relinfo->object); @@ -5427,6 +5459,7 @@ Nanomips_expand_insn::type( typename elfcpp::Elf_types::Elf_Swxword r_addend = reloc.get_r_addend(); + switch (r_type) { case elfcpp::R_NANOMIPS_PC25_S1: @@ -5531,6 +5564,20 @@ Nanomips_expand_insn::type( case elfcpp::R_NANOMIPS_TLS_LD: case elfcpp::R_NANOMIPS_TLS_GOTTPREL: return this->expand_code_and_data_models(target, relobj, gsym, reloc, gp); + case elfcpp::R_NANOMIPS_PC_I32: + { + Valtype value = psymval->value(relobj, r_addend) - address - 6; + if (!Reloc_funcs::value_needs_hw1100880_fix(value)) + return TT_NONE; + break; + } + case elfcpp::R_NANOMIPS_I32: + { + Valtype value = psymval->value(relobj, r_addend); + if (!Reloc_funcs::value_needs_hw1100880_fix(value)) + return TT_NONE; + break; + } default: gold_unreachable(); } @@ -6944,7 +6991,7 @@ Target_nanomips::resolve_pcrel_relocatable( switch (r_type) { case elfcpp::R_NANOMIPS_PC_I32: - reloc_status = Reloc_funcs::rel48(view, value, true); + reloc_status = Reloc_funcs::rel48(view, value, true, reloc_property); break; case elfcpp::R_NANOMIPS_PC25_S1: reloc_status = Reloc_funcs::relpc25_s1(view, value, true); @@ -8357,7 +8404,7 @@ Target_nanomips::Relocate::relocate( case elfcpp::R_NANOMIPS_TLS_GOTTPREL_PC_I32: case elfcpp::R_NANOMIPS_TLS_TPREL_I32: case elfcpp::R_NANOMIPS_TLS_DTPREL_I32: - reloc_status = Reloc_funcs::rel48(view, value, check_overflow); + reloc_status = Reloc_funcs::rel48(view, value, check_overflow, reloc_property); break; case elfcpp::R_NANOMIPS_32: { diff --git a/gold/options.h b/gold/options.h index 5249b5d152cf..b25b5f42f028 100644 --- a/gold/options.h +++ b/gold/options.h @@ -880,6 +880,10 @@ class General_options N_("(nanoMIPS only) Do not finalize relocations in " "relocatable output")); + DEFINE_bool(fix_nmips_hw1100880, options::TWO_DASHES, '\0', false, + N_("(nanoMIPS only) Rewrite instructions to avoid hw1100880 issue"), + N_("(nanoMIPS only) Do not rewrite instructions to avoid hw1100880 issue")); + DEFINE_string(filter, options::TWO_DASHES, 'F', NULL, N_("Filter for shared object symbol table"), N_("SHLIB")); diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index e41da0f33561..902a70ee734a 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -4875,6 +4875,24 @@ nanomips_emit_relocs.o: nanomips_emit_relocs.s MOSTLYCLEANFILES += nanomips_emit_relocs +# Test that the -fix-nmips-hw1100880 performs transformations + +check_SCRIPTS += nanomips_fix_hw1100880.sh +check_DATA += nanomips_fix_hw1100880.stdout + +nanomips_fix_hw1100880.stdout: nanomips_fix_hw1100880 + $(TEST_OBJDUMP) -d -M show-arch-insn $< > $@ + +nanomips_fix_hw1100880: nanomips_fix_hw1100880.o ../ld-new + ../ld-new nanomips_fix_hw1100880.o --fix-nmips-hw1100880 --no-relax \ + --section-start .text=0x1000000 --section-start .foo=0x51012400 \ + --section-start .bar=0x52012500 --section-start .frob=0x2000000 -o $@ + +nanomips_fix_hw1100880.o: nanomips_fix_hw1100880.s + $(TEST_AS) -EL -march=32r6 -m32 -o $@ $< + +MOSTLYCLEANFILES += nanomips_fix_hw1100880 + endif DEFAULT_TARGET_NANOMIPS endif NATIVE_OR_CROSS_LINKER diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 7744ada1dc16..365cf314c4a8 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -1112,6 +1112,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ # Test that the --emit-relocs works with --gc-sections. # Not nanoMIPS specific, but we only run these tests on host. + +# Test that the -fix-nmips-hw1100880 performs transformations @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_106 = nanomips_pcrel_out_of_range.sh \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_gprel_out_of_range.sh \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_sort_by_ref.sh \ @@ -1124,7 +1126,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap.sh \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax.sh \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax.sh \ -@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.sh +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.sh \ +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw1100880.sh @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_107 = nanomips_b_out_of_range_pcrel.stdout \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_insn32_pcrel.stdout \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_nmf_pcrel.stdout \ @@ -1182,7 +1185,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap.stdout \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax.stdout \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax.stdout \ -@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.stdout +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.stdout \ +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw1100880.stdout @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_108 = nanomips_b_out_of_range_pcrel \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_insn32_pcrel \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_nmf_pcrel \ @@ -1234,7 +1238,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax \ @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax \ -@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs \ +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw1100880 @DEFAULT_TARGET_X86_64_TRUE@am__append_109 = *.dwo *.dwp @DEFAULT_TARGET_X86_64_TRUE@am__append_110 = dwp_test_1.sh \ @DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.sh @@ -5668,6 +5673,8 @@ nanomips_bxxzc32_relax.sh.log: nanomips_bxxzc32_relax.sh @p='nanomips_bxxzc32_relax.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) nanomips_emit_relocs.sh.log: nanomips_emit_relocs.sh @p='nanomips_emit_relocs.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +nanomips_fix_hw1100880.sh.log: nanomips_fix_hw1100880.sh + @p='nanomips_fix_hw1100880.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) dwp_test_1.sh.log: dwp_test_1.sh @p='dwp_test_1.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) dwp_test_2.sh.log: dwp_test_2.sh @@ -9028,6 +9035,17 @@ uninstall-am: @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_emit_relocs.o: nanomips_emit_relocs.s @DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6 -m32 -o $@ $< +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_fix_hw1100880.stdout: nanomips_fix_hw1100880 +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d -M show-arch-insn $< > $@ + +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_fix_hw1100880: nanomips_fix_hw1100880.o ../ld-new +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new nanomips_fix_hw1100880.o --fix-nmips-hw1100880 --no-relax \ +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ --section-start .text=0x1000000 --section-start .foo=0x51012400 \ +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ --section-start .bar=0x52012500 --section-start .frob=0x2000000 -o $@ + +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_fix_hw1100880.o: nanomips_fix_hw1100880.s +@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6 -m32 -o $@ $< + # Tests for the dwp tool. # We don't want to rely yet on GCC support for -gsplit-dwarf, # so we use (for now) test cases in x86 assembly language, diff --git a/gold/testsuite/nanomips_fix_hw1100880.s b/gold/testsuite/nanomips_fix_hw1100880.s new file mode 100644 index 000000000000..82615c1a6a42 --- /dev/null +++ b/gold/testsuite/nanomips_fix_hw1100880.s @@ -0,0 +1,48 @@ + .linkrelax + .section .text,"ax",@progbits + .align 4 + .globl __start + .ent __start +__start: + # li[48] -> lapc[48]. + li $a0, foo + # li[48] -> aluipc + ori. + li $a1, bar + li $a2, frob + # addiu[48] -> lapc[48] + addu + addiu $a3, foo + # addiu[48] -> aluipc + ori + addu + addiu $a4, bar + addiu $a5, frob + # lapc[48] -> aluipc + ori. + lapc.b $t0, foo + lapc.b $t1, bar + swpc $t2, foo + swpc $t3, bar + .end __start + .size __start, .-__start + + .section .foo,"ax",@progbits + .align 4 + .globl foo + .ent foo +foo: + jrc $ra + .end foo + .size foo, .-foo + .section .bar,"ax",@progbits + .align 4 + .globl bar + .ent bar +bar: + jrc $ra + .end bar + .size bar, .-bar + .section .frob,"ax",@progbits + .align 4 + .globl frob + .ent frob +frob: + jrc $ra + .end frob + .size frob, .-frob diff --git a/gold/testsuite/nanomips_fix_hw1100880.sh b/gold/testsuite/nanomips_fix_hw1100880.sh new file mode 100755 index 000000000000..6d99bf16e75c --- /dev/null +++ b/gold/testsuite/nanomips_fix_hw1100880.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# nanomips_function_call.sh -- test nanoMIPS function call transformations. + +# Copyright (C) 2018 Free Software Foundation, Inc. +# Written by Vladimir Radosavljevic . + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +check() +{ + file=$1 + pattern=$2 + + found=`grep "$pattern" $file` + if test -z "$found"; then + echo "pattern \"$pattern\" not found in file $file." + exit 1 + fi +} + +# Test li[48] transformation into lapc[48]. +check nanomips_fix_hw1100880.stdout " 1000000: 6083 23fa lapc\[48\] a0.*" + +# Test li[48] transformation into aluipc, ori. +check nanomips_fix_hw1100880.stdout " 1000006: e0a1 2a22 aluipc a1,.*" +check nanomips_fix_hw1100880.stdout " 100000a: 80a5 0500 ori a1,a1,.*" + +# Test li[48] not being transformed +check nanomips_fix_hw1100880.stdout " 100000e: 60c0 0000 li\[48\] a2,.*" + +# Test addiu[48] transformation into lapc[48], addu. +check nanomips_fix_hw1100880.stdout " 1000014: 6023 23e6 lapc\[48\] at,.*" +check nanomips_fix_hw1100880.stdout " 100001a: 2027 3950 addu\[32\] a3,a3,at" + +# Test addiu[48] transformation into aluipc, ori, addu. +check nanomips_fix_hw1100880.stdout " 100001e: e021 2a22 aluipc at,.*" +check nanomips_fix_hw1100880.stdout " 1000022: 8021 0500 ori at,at,.*" +check nanomips_fix_hw1100880.stdout " 1000026: 2028 4150 addu\[32\] a4,a4,at" + +# Test addiu[48] not being transformed +check nanomips_fix_hw1100880.stdout " 100002a: 6121 0000 addiu\[48\] a5,a5,.*" + +# Test lapc[48] not being transformed +check nanomips_fix_hw1100880.stdout " 1000030: 6183 23ca lapc\[48\] t0,.*" + +# Test lapc[48] transformation into aluipc, ori. +check nanomips_fix_hw1100880.stdout " 1000036: e1a1 2a22 aluipc t1,.*" +check nanomips_fix_hw1100880.stdout " 100003a: 81ad 0500 ori t1,t1,.*" + +# Test swpc[48] not being transformed +check nanomips_fix_hw1100880.stdout " 100003e: 61cf 23bc swpc\[48\] t2,.*" + +# Test swpc[48] transformation into aluipc, sw. +check nanomips_fix_hw1100880.stdout " 1000044: e021 2a22 aluipc at,.*" +check nanomips_fix_hw1100880.stdout " 1000048: 85e1 9500 sw\[u12\] t3,.*(at)" + +exit 0