From fa6a1ecd6327ffbedc7dd117e0fba819f6f4faf1 Mon Sep 17 00:00:00 2001 From: Yao Zhang Date: Thu, 10 Sep 2015 11:13:00 -0400 Subject: [PATCH] cmd/internal/obj/mips: added support for GOARCH=mips64{,le} MIPS64 has 32 general purpose 64-bit integer registers (R0-R31), 32 64-bit floating point registers (F0-F31). Instructions are fixed-width, and are 32-bit wide. Instructions are all in standard 1-, 2-, 3-operand forms. MIPS64-specific relocations are added. For this reason, test data of cmd/newlink are regenerated. No other changes are made to portable structures. Branch delay slots are current filled with NOP instructions. The function for instruction scheduling (try to fill the delay slot with a useful instruction) is implemented but disabled for now. Change-Id: Ic364999c7a33245260c1381fc26a2fa8972d38b3 Reviewed-on: https://go-review.googlesource.com/14442 Reviewed-by: Minux Ma --- src/cmd/internal/obj/link.go | 10 + src/cmd/internal/obj/mips/a.out.go | 552 ++-- src/cmd/internal/obj/mips/anames.go | 364 +-- src/cmd/internal/obj/mips/anames0.go | 18 +- src/cmd/internal/obj/mips/asm0.go | 3447 +++++++----------------- src/cmd/internal/obj/mips/list0.go | 44 +- src/cmd/internal/obj/mips/obj0.go | 1229 ++++++--- src/cmd/internal/obj/util.go | 12 +- src/cmd/newlink/testdata/autosection.6 | Bin 937 -> 936 bytes src/cmd/newlink/testdata/autoweak.6 | Bin 386 -> 385 bytes src/cmd/newlink/testdata/dead.6 | Bin 849 -> 848 bytes src/cmd/newlink/testdata/hello.6 | Bin 229 -> 228 bytes src/cmd/newlink/testdata/layout.6 | Bin 396 -> 395 bytes src/cmd/newlink/testdata/pclntab.6 | Bin 3804 -> 3803 bytes 14 files changed, 2167 insertions(+), 3509 deletions(-) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 9780956323..8ebb2f4c62 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -411,12 +411,18 @@ const ( // low 16 bits into that of the second instruction. R_ADDRPOWER R_ADDRARM64 + // R_ADDRMIPS (only used on mips64) resolves to a 32-bit external address, + // by loading the address into a register with two instructions (lui, ori). + R_ADDRMIPS R_SIZE R_CALL R_CALLARM R_CALLARM64 R_CALLIND R_CALLPOWER + // R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address + // of a CALL (JAL) instruction, by encoding the address into the instruction. + R_CALLMIPS R_CONST R_PCREL // R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the @@ -437,6 +443,10 @@ const ( R_USEFIELD R_POWER_TOC R_GOTPCREL + // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address + // of a JMP instruction, by encoding the address into the instruction. + // The stack nosplit check ignores this since it is not a function call. + R_JMPMIPS // Platform dependent relocations. Architectures with fixed width instructions // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be diff --git a/src/cmd/internal/obj/mips/a.out.go b/src/cmd/internal/obj/mips/a.out.go index 3028b6cac8..f271a87609 100644 --- a/src/cmd/internal/obj/mips/a.out.go +++ b/src/cmd/internal/obj/mips/a.out.go @@ -27,14 +27,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package ppc64 +package mips import "cmd/internal/obj" -//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p ppc64 +//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p mips /* - * powerpc 64 + * mips 64 */ const ( NSNAME = 8 @@ -44,7 +44,7 @@ const ( ) const ( - REG_R0 = obj.RBasePPC64 + iota + REG_R0 = obj.RBaseMIPS64 + iota REG_R1 REG_R2 REG_R3 @@ -110,90 +110,128 @@ const ( REG_F30 REG_F31 - REG_CR0 - REG_CR1 - REG_CR2 - REG_CR3 - REG_CR4 - REG_CR5 - REG_CR6 - REG_CR7 + REG_HI + REG_LO - REG_MSR - REG_FPSCR - REG_CR + // co-processor 0 control registers + REG_M0 = obj.RBaseMIPS64 + 1024 + iota + REG_M1 + REG_M2 + REG_M3 + REG_M4 + REG_M5 + REG_M6 + REG_M7 + REG_M8 + REG_M9 + REG_M10 + REG_M11 + REG_M12 + REG_M13 + REG_M14 + REG_M15 + REG_M16 + REG_M17 + REG_M18 + REG_M19 + REG_M20 + REG_M21 + REG_M22 + REG_M23 + REG_M24 + REG_M25 + REG_M26 + REG_M27 + REG_M28 + REG_M29 + REG_M30 + REG_M31 - REG_SPECIAL = REG_CR0 + // FPU control registers + REG_FCR0 = obj.RBaseMIPS64 + 2048 + iota + REG_FCR1 + REG_FCR2 + REG_FCR3 + REG_FCR4 + REG_FCR5 + REG_FCR6 + REG_FCR7 + REG_FCR8 + REG_FCR9 + REG_FCR10 + REG_FCR11 + REG_FCR12 + REG_FCR13 + REG_FCR14 + REG_FCR15 + REG_FCR16 + REG_FCR17 + REG_FCR18 + REG_FCR19 + REG_FCR20 + REG_FCR21 + REG_FCR22 + REG_FCR23 + REG_FCR24 + REG_FCR25 + REG_FCR26 + REG_FCR27 + REG_FCR28 + REG_FCR29 + REG_FCR30 + REG_FCR31 - REG_SPR0 = obj.RBasePPC64 + 1024 // first of 1024 registers - REG_DCR0 = obj.RBasePPC64 + 2048 // first of 1024 registers - - REG_XER = REG_SPR0 + 1 - REG_LR = REG_SPR0 + 8 - REG_CTR = REG_SPR0 + 9 + REG_SPECIAL = REG_M0 REGZERO = REG_R0 /* set to zero */ - REGSP = REG_R1 - REGSB = REG_R2 - REGRET = REG_R3 + REGSP = REG_R29 + REGSB = REG_R30 + REGLINK = REG_R31 + REGRET = REG_R1 REGARG = -1 /* -1 disables passing the first argument in register */ - REGRT1 = REG_R3 /* reserved for runtime, duffzero and duffcopy */ - REGRT2 = REG_R4 /* reserved for runtime, duffcopy */ - REGMIN = REG_R7 /* register variables allocated from here to REGMAX */ - REGCTXT = REG_R11 /* context for closures */ - REGTLS = REG_R13 /* C ABI TLS base pointer */ - REGMAX = REG_R27 - REGEXT = REG_R30 /* external registers allocated from here down */ + REGRT1 = REG_R1 /* reserved for runtime, duffzero and duffcopy */ + REGRT2 = REG_R2 /* reserved for runtime, duffcopy */ + REGCTXT = REG_R22 /* context for closures */ REGG = REG_R30 /* G */ - REGTMP = REG_R31 /* used by the linker */ + REGTMP = REG_R28 /* used by the linker */ FREGRET = REG_F0 - FREGMIN = REG_F17 /* first register variable */ - FREGMAX = REG_F26 /* last register variable for 9g only */ - FREGEXT = REG_F26 /* first external register */ - FREGCVI = REG_F27 /* floating conversion constant */ - FREGZERO = REG_F28 /* both float and double */ - FREGHALF = REG_F29 /* double */ - FREGONE = REG_F30 /* double */ - FREGTWO = REG_F31 /* double */ + FREGZERO = REG_F24 /* both float and double */ + FREGHALF = REG_F26 /* double */ + FREGONE = REG_F28 /* double */ + FREGTWO = REG_F30 /* double */ ) -/* - * GENERAL: - * - * compiler allocates R3 up as temps - * compiler allocates register variables R7-R27 - * compiler allocates external registers R30 down - * - * compiler allocates register variables F17-F26 - * compiler allocates external registers F26 down - */ const ( - BIG = 32768 - 8 + BIG = 32766 ) const ( /* mark flags */ - LABEL = 1 << 0 - LEAF = 1 << 1 - FLOAT = 1 << 2 - BRANCH = 1 << 3 - LOAD = 1 << 4 - FCMP = 1 << 5 - SYNC = 1 << 6 - LIST = 1 << 7 - FOLL = 1 << 8 - NOSCHED = 1 << 9 + FOLL = 1 << 0 + LABEL = 1 << 1 + LEAF = 1 << 2 + SYNC = 1 << 3 + BRANCH = 1 << 4 + LOAD = 1 << 5 + FCMP = 1 << 6 + NOSCHED = 1 << 7 + + NSCHED = 20 ) const ( C_NONE = iota C_REG C_FREG - C_CREG - C_SPR /* special processor register */ + C_FCREG + C_MREG /* special processor register */ + C_HI + C_LO C_ZCON - C_SCON /* 16 bit signed */ - C_UCON /* 32 bit signed, low 16 bits 0 */ + C_SCON /* 16 bit signed */ + C_UCON /* 32 bit signed, low 16 bits 0 */ + C_ADD0CON + C_AND0CON C_ADDCON /* -0x8000 <= v < 0 */ C_ANDCON /* 0 < v <= 0xFFFF */ C_LCON /* other 32 */ @@ -212,12 +250,6 @@ const ( C_ZOREG C_SOREG C_LOREG - C_FPSCR - C_MSR - C_XER - C_LR - C_CTR - C_ANY C_GOK C_ADDR C_TEXTSIZE @@ -226,313 +258,117 @@ const ( ) const ( - AADD = obj.ABasePPC64 + obj.A_ARCHSPECIFIC + iota - AADDCC - AADDV - AADDVCC - AADDC - AADDCCC - AADDCV - AADDCVCC - AADDME - AADDMECC - AADDMEVCC - AADDMEV - AADDE - AADDECC - AADDEVCC - AADDEV - AADDZE - AADDZECC - AADDZEVCC - AADDZEV + AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota + AABSF + AABSW + AADD + AADDD + AADDF + AADDU + AADDW AAND - AANDCC - AANDN - AANDNCC - ABC - ABCL ABEQ - ABGE - ABGT - ABLE - ABLT + ABFPF + ABFPT + ABGEZ + ABGEZAL + ABGTZ + ABLEZ + ABLTZ + ABLTZAL ABNE - ABVC - ABVS - ACMP - ACMPU - ACNTLZW - ACNTLZWCC - ACRAND - ACRANDN - ACREQV - ACRNAND - ACRNOR - ACROR - ACRORN - ACRXOR + ABREAK + ACMPEQD + ACMPEQF + ACMPGED + ACMPGEF + ACMPGTD + ACMPGTF + ADIV + ADIVD + ADIVF + ADIVU ADIVW - ADIVWCC - ADIVWVCC - ADIVWV - ADIVWU - ADIVWUCC - ADIVWUVCC - ADIVWUV - AEQV - AEQVCC - AEXTSB - AEXTSBCC - AEXTSH - AEXTSHCC - AFABS - AFABSCC - AFADD - AFADDCC - AFADDS - AFADDSCC - AFCMPO - AFCMPU - AFCTIW - AFCTIWCC - AFCTIWZ - AFCTIWZCC - AFDIV - AFDIVCC - AFDIVS - AFDIVSCC - AFMADD - AFMADDCC - AFMADDS - AFMADDSCC - AFMOVD - AFMOVDCC - AFMOVDU - AFMOVS - AFMOVSU - AFMSUB - AFMSUBCC - AFMSUBS - AFMSUBSCC - AFMUL - AFMULCC - AFMULS - AFMULSCC - AFNABS - AFNABSCC - AFNEG - AFNEGCC - AFNMADD - AFNMADDCC - AFNMADDS - AFNMADDSCC - AFNMSUB - AFNMSUBCC - AFNMSUBS - AFNMSUBSCC - AFRSP - AFRSPCC - AFSUB - AFSUBCC - AFSUBS - AFSUBSCC - AMOVMW - ALSW - ALWAR - AMOVWBR + AGOK AMOVB AMOVBU - AMOVBZ - AMOVBZU + AMOVD + AMOVDF + AMOVDW + AMOVF + AMOVFD + AMOVFW AMOVH - AMOVHBR AMOVHU - AMOVHZ - AMOVHZU AMOVW - AMOVWU - AMOVFL - AMOVCRFS - AMTFSB0 - AMTFSB0CC - AMTFSB1 - AMTFSB1CC - AMULHW - AMULHWCC - AMULHWU - AMULHWUCC - AMULLW - AMULLWCC - AMULLWVCC - AMULLWV - ANAND - ANANDCC - ANEG - ANEGCC - ANEGVCC - ANEGV + AMOVWD + AMOVWF + AMOVWL + AMOVWR + AMUL + AMULD + AMULF + AMULU + AMULW + ANEGD + ANEGF + ANEGW ANOR - ANORCC AOR - AORCC - AORN - AORNCC AREM - AREMCC - AREMV - AREMVCC AREMU - AREMUCC - AREMUV - AREMUVCC - ARFI - ARLWMI - ARLWMICC - ARLWNM - ARLWNMCC - ASLW - ASLWCC - ASRW - ASRAW - ASRAWCC - ASRWCC - ASTSW - ASTWCCC + ARFE + ASGT + ASGTU + ASLL + ASRA + ASRL ASUB - ASUBCC - ASUBVCC - ASUBC - ASUBCCC - ASUBCV - ASUBCVCC - ASUBME - ASUBMECC - ASUBMEVCC - ASUBMEV - ASUBV - ASUBE - ASUBECC - ASUBEV - ASUBEVCC - ASUBZE - ASUBZECC - ASUBZEVCC - ASUBZEV - ASYNC - AXOR - AXORCC - - ADCBF - ADCBI - ADCBST - ADCBT - ADCBTST - ADCBZ - AECIWX - AECOWX - AEIEIO - AICBI - AISYNC - APTESYNC - ATLBIE - ATLBIEL - ATLBSYNC - ATW - + ASUBD + ASUBF + ASUBU + ASUBW ASYSCALL + ATLBP + ATLBR + ATLBWI + ATLBWR AWORD - - ARFCI - - /* optional on 32-bit */ - AFRES - AFRESCC - AFRSQRTE - AFRSQRTECC - AFSEL - AFSELCC - AFSQRT - AFSQRTCC - AFSQRTS - AFSQRTSCC + AXOR /* 64-bit */ + AMOVV + AMOVVL + AMOVVR + ASLLV + ASRAV + ASRLV + ADIVV + ADIVVU + AREMV + AREMVU + AMULV + AMULVU + AADDV + AADDVU + ASUBV + ASUBVU - ACNTLZD - ACNTLZDCC - ACMPW /* CMP with L=0 */ - ACMPWU - ADIVD - ADIVDCC - ADIVDVCC - ADIVDV - ADIVDU - ADIVDUCC - ADIVDUVCC - ADIVDUV - AEXTSW - AEXTSWCC - /* AFCFIW; AFCFIWCC */ - AFCFID - AFCFIDCC - AFCTID - AFCTIDCC - AFCTIDZ - AFCTIDZCC - ALDAR - AMOVD - AMOVDU - AMOVWZ - AMOVWZU - AMULHD - AMULHDCC - AMULHDU - AMULHDUCC - AMULLD - AMULLDCC - AMULLDVCC - AMULLDV - ARFID - ARLDMI - ARLDMICC - ARLDC - ARLDCCC - ARLDCR - ARLDCRCC - ARLDCL - ARLDCLCC - ASLBIA - ASLBIE - ASLBMFEE - ASLBMFEV - ASLBMTE - ASLD - ASLDCC - ASRD - ASRAD - ASRADCC - ASRDCC - ASTDCCC - ATD - - /* 64-bit pseudo operation */ - ADWORD - AREMD - AREMDCC - AREMDV - AREMDVCC - AREMDU - AREMDUCC - AREMDUV - AREMDUVCC - - /* more 64-bit operations */ - AHRFID + /* 64-bit FP */ + ATRUNCFV + ATRUNCDV + ATRUNCFW + ATRUNCDW + AMOVWU + AMOVFV + AMOVDV + AMOVVF + AMOVVD ALAST // aliases - ABR = obj.AJMP - ABL = obj.ACALL + AJMP = obj.AJMP + AJAL = obj.ACALL + ARET = obj.ARET ) diff --git a/src/cmd/internal/obj/mips/anames.go b/src/cmd/internal/obj/mips/anames.go index 1ae7a52015..a943e503ac 100644 --- a/src/cmd/internal/obj/mips/anames.go +++ b/src/cmd/internal/obj/mips/anames.go @@ -1,300 +1,112 @@ -// Generated by stringer -i a.out.go -o anames.go -p ppc64 +// Generated by stringer -i a.out.go -o anames.go -p mips // Do not edit. -package ppc64 +package mips import "cmd/internal/obj" var Anames = []string{ - obj.A_ARCHSPECIFIC: "ADD", - "ADDCC", - "ADDV", - "ADDVCC", - "ADDC", - "ADDCCC", - "ADDCV", - "ADDCVCC", - "ADDME", - "ADDMECC", - "ADDMEVCC", - "ADDMEV", - "ADDE", - "ADDECC", - "ADDEVCC", - "ADDEV", - "ADDZE", - "ADDZECC", - "ADDZEVCC", - "ADDZEV", + obj.A_ARCHSPECIFIC: "ABSD", + "ABSF", + "ABSW", + "ADD", + "ADDD", + "ADDF", + "ADDU", + "ADDW", "AND", - "ANDCC", - "ANDN", - "ANDNCC", - "BC", - "BCL", "BEQ", - "BGE", - "BGT", - "BLE", - "BLT", + "BFPF", + "BFPT", + "BGEZ", + "BGEZAL", + "BGTZ", + "BLEZ", + "BLTZ", + "BLTZAL", "BNE", - "BVC", - "BVS", - "CMP", - "CMPU", - "CNTLZW", - "CNTLZWCC", - "CRAND", - "CRANDN", - "CREQV", - "CRNAND", - "CRNOR", - "CROR", - "CRORN", - "CRXOR", + "BREAK", + "CMPEQD", + "CMPEQF", + "CMPGED", + "CMPGEF", + "CMPGTD", + "CMPGTF", + "DIV", + "DIVD", + "DIVF", + "DIVU", "DIVW", - "DIVWCC", - "DIVWVCC", - "DIVWV", - "DIVWU", - "DIVWUCC", - "DIVWUVCC", - "DIVWUV", - "EQV", - "EQVCC", - "EXTSB", - "EXTSBCC", - "EXTSH", - "EXTSHCC", - "FABS", - "FABSCC", - "FADD", - "FADDCC", - "FADDS", - "FADDSCC", - "FCMPO", - "FCMPU", - "FCTIW", - "FCTIWCC", - "FCTIWZ", - "FCTIWZCC", - "FDIV", - "FDIVCC", - "FDIVS", - "FDIVSCC", - "FMADD", - "FMADDCC", - "FMADDS", - "FMADDSCC", - "FMOVD", - "FMOVDCC", - "FMOVDU", - "FMOVS", - "FMOVSU", - "FMSUB", - "FMSUBCC", - "FMSUBS", - "FMSUBSCC", - "FMUL", - "FMULCC", - "FMULS", - "FMULSCC", - "FNABS", - "FNABSCC", - "FNEG", - "FNEGCC", - "FNMADD", - "FNMADDCC", - "FNMADDS", - "FNMADDSCC", - "FNMSUB", - "FNMSUBCC", - "FNMSUBS", - "FNMSUBSCC", - "FRSP", - "FRSPCC", - "FSUB", - "FSUBCC", - "FSUBS", - "FSUBSCC", - "MOVMW", - "LSW", - "LWAR", - "MOVWBR", + "GOK", "MOVB", "MOVBU", - "MOVBZ", - "MOVBZU", + "MOVD", + "MOVDF", + "MOVDW", + "MOVF", + "MOVFD", + "MOVFW", "MOVH", - "MOVHBR", "MOVHU", - "MOVHZ", - "MOVHZU", "MOVW", - "MOVWU", - "MOVFL", - "MOVCRFS", - "MTFSB0", - "MTFSB0CC", - "MTFSB1", - "MTFSB1CC", - "MULHW", - "MULHWCC", - "MULHWU", - "MULHWUCC", - "MULLW", - "MULLWCC", - "MULLWVCC", - "MULLWV", - "NAND", - "NANDCC", - "NEG", - "NEGCC", - "NEGVCC", - "NEGV", + "MOVWD", + "MOVWF", + "MOVWL", + "MOVWR", + "MUL", + "MULD", + "MULF", + "MULU", + "MULW", + "NEGD", + "NEGF", + "NEGW", "NOR", - "NORCC", "OR", - "ORCC", - "ORN", - "ORNCC", "REM", - "REMCC", - "REMV", - "REMVCC", "REMU", - "REMUCC", - "REMUV", - "REMUVCC", - "RFI", - "RLWMI", - "RLWMICC", - "RLWNM", - "RLWNMCC", - "SLW", - "SLWCC", - "SRW", - "SRAW", - "SRAWCC", - "SRWCC", - "STSW", - "STWCCC", + "RFE", + "SGT", + "SGTU", + "SLL", + "SRA", + "SRL", "SUB", - "SUBCC", - "SUBVCC", - "SUBC", - "SUBCCC", - "SUBCV", - "SUBCVCC", - "SUBME", - "SUBMECC", - "SUBMEVCC", - "SUBMEV", - "SUBV", - "SUBE", - "SUBECC", - "SUBEV", - "SUBEVCC", - "SUBZE", - "SUBZECC", - "SUBZEVCC", - "SUBZEV", - "SYNC", - "XOR", - "XORCC", - "DCBF", - "DCBI", - "DCBST", - "DCBT", - "DCBTST", - "DCBZ", - "ECIWX", - "ECOWX", - "EIEIO", - "ICBI", - "ISYNC", - "PTESYNC", - "TLBIE", - "TLBIEL", - "TLBSYNC", - "TW", + "SUBD", + "SUBF", + "SUBU", + "SUBW", "SYSCALL", + "TLBP", + "TLBR", + "TLBWI", + "TLBWR", "WORD", - "RFCI", - "FRES", - "FRESCC", - "FRSQRTE", - "FRSQRTECC", - "FSEL", - "FSELCC", - "FSQRT", - "FSQRTCC", - "FSQRTS", - "FSQRTSCC", - "CNTLZD", - "CNTLZDCC", - "CMPW", - "CMPWU", - "DIVD", - "DIVDCC", - "DIVDVCC", - "DIVDV", - "DIVDU", - "DIVDUCC", - "DIVDUVCC", - "DIVDUV", - "EXTSW", - "EXTSWCC", - "FCFID", - "FCFIDCC", - "FCTID", - "FCTIDCC", - "FCTIDZ", - "FCTIDZCC", - "LDAR", - "MOVD", - "MOVDU", - "MOVWZ", - "MOVWZU", - "MULHD", - "MULHDCC", - "MULHDU", - "MULHDUCC", - "MULLD", - "MULLDCC", - "MULLDVCC", - "MULLDV", - "RFID", - "RLDMI", - "RLDMICC", - "RLDC", - "RLDCCC", - "RLDCR", - "RLDCRCC", - "RLDCL", - "RLDCLCC", - "SLBIA", - "SLBIE", - "SLBMFEE", - "SLBMFEV", - "SLBMTE", - "SLD", - "SLDCC", - "SRD", - "SRAD", - "SRADCC", - "SRDCC", - "STDCCC", - "TD", - "DWORD", - "REMD", - "REMDCC", - "REMDV", - "REMDVCC", - "REMDU", - "REMDUCC", - "REMDUV", - "REMDUVCC", - "HRFID", + "XOR", + "MOVV", + "MOVVL", + "MOVVR", + "SLLV", + "SRAV", + "SRLV", + "DIVV", + "DIVVU", + "REMV", + "REMVU", + "MULV", + "MULVU", + "ADDV", + "ADDVU", + "SUBV", + "SUBVU", + "TRUNCFV", + "TRUNCDV", + "TRUNCFW", + "TRUNCDW", + "MOVWU", + "MOVFV", + "MOVDV", + "MOVVF", + "MOVVD", "LAST", } diff --git a/src/cmd/internal/obj/mips/anames0.go b/src/cmd/internal/obj/mips/anames0.go index b48e5162b0..7f342e6895 100644 --- a/src/cmd/internal/obj/mips/anames0.go +++ b/src/cmd/internal/obj/mips/anames0.go @@ -1,14 +1,18 @@ -package ppc64 +package mips -var cnames9 = []string{ +var cnames0 = []string{ "NONE", "REG", "FREG", - "CREG", - "SPR", + "FCREG", + "MREG", + "HI", + "LO", "ZCON", "SCON", "UCON", + "ADD0CON", + "AND0CON", "ADDCON", "ANDCON", "LCON", @@ -27,12 +31,6 @@ var cnames9 = []string{ "ZOREG", "SOREG", "LOREG", - "FPSCR", - "MSR", - "XER", - "LR", - "CTR", - "ANY", "GOK", "ADDR", "TEXTSIZE", diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index c7498ea5f3..f944d3333f 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -27,11 +27,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package ppc64 +package mips import ( "cmd/internal/obj" - "encoding/binary" "fmt" "log" "sort" @@ -52,349 +51,263 @@ type Optab struct { a1 uint8 a2 uint8 a3 uint8 - a4 uint8 type_ int8 size int8 param int16 } var optab = []Optab{ - Optab{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0}, - Optab{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0}, - Optab{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0}, - Optab{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0}, - /* move register */ - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0}, - Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, - Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0}, - Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0}, - Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0}, - Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0}, - Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0}, - Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0}, - Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0}, - Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, - Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0}, - Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0}, - Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0}, - Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0}, - Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0}, - Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */ - Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, - Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0}, - Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0}, - Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0}, - Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0}, - Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0}, - Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0}, - Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, - Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0}, - Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0}, - Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0}, - Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0}, - Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0}, - Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0}, - Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0}, - Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, - Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0}, - Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0}, - Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0}, - Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */ - Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0}, - Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0}, - Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0}, - Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0}, - Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0}, - Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0}, - Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */ - Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0}, - Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */ - Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0}, - Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, - Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, - Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0}, - Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0}, - Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0}, - Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0}, - Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, - Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0}, - Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0}, - Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0}, - Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, - Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0}, - Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0}, - Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0}, - Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0}, - Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0}, - Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, - Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, - Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0}, - Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0}, - Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0}, - Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0}, - Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0}, - Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0}, - Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0}, - Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0}, - Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0}, - - /* store, short offset */ - Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - - /* load, short offset */ - Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO}, - Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO}, - Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB}, - Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB}, - Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB}, - Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB}, - Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB}, - Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP}, - Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP}, - Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP}, - Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP}, - Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP}, - Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO}, - Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO}, - Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO}, - - /* store, long offset */ - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - - /* load, long offset */ - Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB}, - Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB}, - Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB}, - Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB}, - Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB}, - Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP}, - Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP}, - Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP}, - Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP}, - Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP}, - Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO}, - Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO}, - Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO}, - Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO}, - Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO}, - Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0}, - Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0}, - Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0}, - Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0}, - Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0}, - - /* load constant */ - Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, - Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP}, - Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB}, - Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP}, - Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */ - Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP}, - Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB}, - Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP}, - Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */ - Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP}, - Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB}, - Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP}, - Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - - /* load unsigned/long constants (TO DO: check) */ - Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0}, - Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0}, - Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO}, - Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0}, - Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0}, - Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0}, - Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0}, - Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0}, - Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0}, - Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0}, - Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0}, - Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0}, - Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0}, - Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, - Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0}, - Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0}, - Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0}, - Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0}, - Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0}, - Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0}, - Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0}, - Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0}, - Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0}, - Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0}, - Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0}, - Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB}, - Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP}, - Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO}, - Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB}, - Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP}, - Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO}, - Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO}, - Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0}, - Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0}, - Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0}, - Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0}, - Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0}, - Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0}, - Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0}, - Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0}, - Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0}, - Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0}, - Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0}, - Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0}, - Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0}, - Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0}, - Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0}, - Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0}, - Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0}, - Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0}, - Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0}, - Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0}, - Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0}, - Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0}, - Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0}, - Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0}, /* mfmsr */ - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsrd */ - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */ - - /* 64-bit special registers */ - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0}, - Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0}, - Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0}, - - /* 32-bit special registers (gloss over sign-extension or not?) */ - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0}, - Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0}, - Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0}, - Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0}, - Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0}, - Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0}, - Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0}, - Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0}, - Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0}, - Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0}, - Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0}, - Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0}, - Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0}, - Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0}, - Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0}, - Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0}, - Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0}, - Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0}, - Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0}, - Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0}, - Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0}, - Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0}, - Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0}, - Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0}, - Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0}, - Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0}, - Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0}, - Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0}, - Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0}, - Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0}, - Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0}, - Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0}, - Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0}, - Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0}, - Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0}, - Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0}, - Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0}, - Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0}, - Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0}, - Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0}, - Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0}, - Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0}, - Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0}, - Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL - Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL - - Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0}, + {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0}, + {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0}, + + {AMOVW, C_REG, C_NONE, C_REG, 14, 8, 0}, + {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0}, + {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0}, + {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0}, + {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0}, + + {ASUB, C_REG, C_REG, C_REG, 2, 4, 0}, + {AADD, C_REG, C_REG, C_REG, 2, 4, 0}, + {AAND, C_REG, C_REG, C_REG, 2, 4, 0}, + {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0}, + {AADD, C_REG, C_NONE, C_REG, 2, 4, 0}, + {AAND, C_REG, C_NONE, C_REG, 2, 4, 0}, + + {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0}, + {ASLL, C_REG, C_REG, C_REG, 9, 4, 0}, + + {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0}, + {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0}, + {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0}, + {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0}, + {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0}, + {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0}, + + {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, + {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + + {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, + {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, + {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, + + {AMOVW, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, + {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, + {AMOVV, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, + {AMOVB, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, + {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, + {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, + {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, + {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, + {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, + {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, + {AMOVW, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, + {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, + {AMOVV, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, + {AMOVB, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, + {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, + {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0}, + {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0}, + {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0}, + {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0}, + {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0}, + + {AMOVW, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, + {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, + {AMOVV, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, + {AMOVB, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, + {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, + {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, + {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, + {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, + {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, + {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, + {AMOVW, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, + {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, + {AMOVV, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, + {AMOVB, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, + {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, + {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0}, + {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0}, + {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0}, + {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0}, + {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0}, + + {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB}, + {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB}, + {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP}, + {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP}, + {AMOVW, C_LECON, C_NONE, C_REG, 26, 12, REGSB}, + {AMOVV, C_LECON, C_NONE, C_REG, 26, 12, REGSB}, + {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP}, + {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP}, + {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO}, + {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO}, + {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO}, + {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO}, + + {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0}, + {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0}, + {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0}, + {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0}, + + {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0}, + {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0}, + {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0}, + {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0}, + {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0}, + {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0}, + {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0}, + {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0}, + + {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0}, + + {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0}, + {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0}, + {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0}, + {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0}, + + {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0}, + {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0}, + {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0}, + {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0}, + + {AADD, C_UCON, C_REG, C_REG, 25, 8, 0}, + {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0}, + {AAND, C_UCON, C_REG, C_REG, 25, 8, 0}, + {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0}, + + {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0}, + {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0}, + {AADD, C_LCON, C_REG, C_REG, 23, 12, 0}, + {AAND, C_LCON, C_REG, C_REG, 23, 12, 0}, + + {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0}, + {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0}, + + {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0}, + + {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0}, + {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0}, + {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0}, + {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0}, + + {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, + {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, + + {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO}, + {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK}, + + {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, + {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, + {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, + {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, + {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, + {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, + {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, + {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, + {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, + + {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, + {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, + {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, + {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, + {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, + {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, + {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, + {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, + {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, + {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0}, + {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0}, + + {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, + {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, + {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, + {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, + {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, + {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, + {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, + {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, + {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, + + {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, + {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, + {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, + {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, + {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, + {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, + {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, + {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, + {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, + {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0}, + {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0}, + + {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0}, + {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0}, + {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0}, + {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0}, + + {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0}, + {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0}, + {AMOVW, C_UCON, C_NONE, C_FREG, 35, 8, 0}, + {AMOVW, C_LCON, C_NONE, C_FREG, 36, 12, 0}, + + {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0}, + {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0}, + {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0}, + {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0}, + + {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0}, + + {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0}, + {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0}, + {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0}, + {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0}, + + {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */ + {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, + {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, + {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0}, + + {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0}, + {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0}, + {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0}, + {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0}, + {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0}, + {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP + {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP + + {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0}, } type Oprang struct { @@ -406,7 +319,7 @@ var oprange [ALAST & obj.AMask]Oprang var xcmp [C_NCLASS][C_NCLASS]uint8 -func span9(ctxt *obj.Link, cursym *obj.LSym) { +func span0(ctxt *obj.Link, cursym *obj.LSym) { p := cursym.Text if p == nil || p.Link == nil { // handle external functions and ELF section symbols return @@ -414,7 +327,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) { ctxt.Cursym = cursym ctxt.Autosize = int32(p.To.Offset + 8) - if oprange[AANDN&obj.AMask].start == nil { + if oprange[AOR&obj.AMask].start == nil { buildop(ctxt) } @@ -461,25 +374,27 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) { o = oplook(ctxt, p) // very large conditional branches - if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil { + if o.type_ == 6 && p.Pcond != nil { otxt = p.Pcond.Pc - c - if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 { + if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 { q = ctxt.NewProg() q.Link = p.Link p.Link = q - q.As = ABR + q.As = AJMP + q.Lineno = p.Lineno q.To.Type = obj.TYPE_BRANCH q.Pcond = p.Pcond p.Pcond = q q = ctxt.NewProg() q.Link = p.Link p.Link = q - q.As = ABR + q.As = AJMP + q.Lineno = p.Lineno q.To.Type = obj.TYPE_BRANCH q.Pcond = q.Link.Link - //addnop(p->link); - //addnop(p); + addnop(ctxt, p.Link) + addnop(ctxt, p) bflag = 1 } } @@ -509,13 +424,13 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) { bp := cursym.P var i int32 - var out [6]uint32 + var out [4]uint32 for p := cursym.Text.Link; p != nil; p = p.Link { ctxt.Pc = p.Pc ctxt.Curp = p o = oplook(ctxt, p) if int(o.size) > 4*len(out) { - log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p) + log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p) } asmout(ctxt, p, o, out[:]) for i = 0; i < int32(o.size/4); i++ { @@ -545,32 +460,17 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { if REG_F0 <= a.Reg && a.Reg <= REG_F31 { return C_FREG } - if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR { - return C_CREG + if REG_M0 <= a.Reg && a.Reg <= REG_M31 { + return C_MREG } - if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 { - switch a.Reg { - case REG_LR: - return C_LR - - case REG_XER: - return C_XER - - case REG_CTR: - return C_CTR - } - - return C_SPR + if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 { + return C_FCREG } - - if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 { - return C_SPR - } - if a.Reg == REG_FPSCR { - return C_FPSCR + if a.Reg == REG_LO { + return C_LO } - if a.Reg == REG_MSR { - return C_MSR + if a.Reg == REG_HI { + return C_HI } return C_GOK @@ -620,7 +520,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { case obj.TYPE_CONST, obj.TYPE_ADDR: switch a.Name { - case obj.TYPE_NONE: + case obj.NAME_NONE: ctxt.Instoffset = a.Offset if a.Reg != 0 { if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG { @@ -684,7 +584,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) { return C_LCON } - return C_DCON + return C_LCON // C_DCON } if ctxt.Instoffset >= -0x8000 { @@ -696,7 +596,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { if isint32(ctxt.Instoffset) { return C_LCON } - return C_DCON + return C_LCON // C_DCON case obj.TYPE_BRANCH: return C_SBRA @@ -710,6 +610,10 @@ func prasm(p *obj.Prog) { } func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { + if oprange[AOR&obj.AMask].start == nil { + buildop(ctxt) + } + a1 := int(p.Optab) if a1 != 0 { return &optab[a1-1:][0] @@ -721,29 +625,19 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { } a1-- - a3 := C_NONE + 1 - if p.From3 != nil { - a3 = int(p.From3.Class) - if a3 == 0 { - a3 = aclass(ctxt, p.From3) + 1 - p.From3.Class = int8(a3) - } + a3 := int(p.To.Class) + if a3 == 0 { + a3 = aclass(ctxt, &p.To) + 1 + p.To.Class = int8(a3) } a3-- - a4 := int(p.To.Class) - if a4 == 0 { - a4 = aclass(ctxt, &p.To) + 1 - p.To.Class = int8(a4) - } - - a4-- a2 := C_NONE if p.Reg != 0 { a2 = C_REG } - //print("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4); + //print("oplook %P %d %d %d\n", p, a1, a2, a3); r0 := p.As & obj.AMask o := oprange[r0].start @@ -753,21 +647,18 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { e := oprange[r0].stop c1 := xcmp[a1][:] c3 := xcmp[a3][:] - c4 := xcmp[a4][:] for ; -cap(o) < -cap(e); o = o[1:] { if int(o[0].a2) == a2 { if c1[o[0].a1] != 0 { if c3[o[0].a3] != 0 { - if c4[o[0].a4] != 0 { - p.Optab = uint16((-cap(o) + cap(optab)) + 1) - return &o[0] - } + p.Optab = uint16((-cap(o) + cap(optab)) + 1) + return &o[0] } } } } - ctxt.Diag("illegal combination %v %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4)) + ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3)) prasm(p) if o == nil { o = optab @@ -785,18 +676,25 @@ func cmp(a int, b int) bool { return true } + case C_ADD0CON: + if b == C_ADDCON { + return true + } + fallthrough + case C_ADDCON: if b == C_ZCON || b == C_SCON { return true } - case C_ANDCON: - if b == C_ZCON || b == C_SCON { + case C_AND0CON: + if b == C_ANDCON { return true } + fallthrough - case C_SPR: - if b == C_LR || b == C_XER || b == C_CTR { + case C_ANDCON: + if b == C_ZCON || b == C_SCON { return true } @@ -844,9 +742,6 @@ func cmp(a int, b int) bool { if b == C_ZOREG { return true } - - case C_ANY: - return true } return false @@ -881,10 +776,6 @@ func (x ocmp) Less(i, j int) bool { if n != 0 { return n < 0 } - n = int(p1.a4) - int(p2.a4) - if n != 0 { - return n < 0 - } return false } func opset(a, b0 int16) { @@ -919,359 +810,118 @@ func buildop(ctxt *obj.Link) { ctxt.Diag("unknown op in build: %v", obj.Aconv(int(r))) log.Fatalf("bad code") - case ADCBF: /* unary indexed: op (b+a); op (b) */ - opset(ADCBI, r0) - - opset(ADCBST, r0) - opset(ADCBT, r0) - opset(ADCBTST, r0) - opset(ADCBZ, r0) - opset(AICBI, r0) - - case AECOWX: /* indexed store: op s,(b+a); op s,(b) */ - opset(ASTWCCC, r0) - - opset(ASTDCCC, r0) - - case AREM: /* macro */ - opset(AREMCC, r0) - - opset(AREMV, r0) - opset(AREMVCC, r0) - - case AREMU: - opset(AREMU, r0) - opset(AREMUCC, r0) - opset(AREMUV, r0) - opset(AREMUVCC, r0) - - case AREMD: - opset(AREMDCC, r0) - opset(AREMDV, r0) - opset(AREMDVCC, r0) - - case AREMDU: - opset(AREMDU, r0) - opset(AREMDUCC, r0) - opset(AREMDUV, r0) - opset(AREMDUVCC, r0) - - case ADIVW: /* op Rb[,Ra],Rd */ - opset(AMULHW, r0) - - opset(AMULHWCC, r0) - opset(AMULHWU, r0) - opset(AMULHWUCC, r0) - opset(AMULLWCC, r0) - opset(AMULLWVCC, r0) - opset(AMULLWV, r0) - opset(ADIVWCC, r0) - opset(ADIVWV, r0) - opset(ADIVWVCC, r0) - opset(ADIVWU, r0) - opset(ADIVWUCC, r0) - opset(ADIVWUV, r0) - opset(ADIVWUVCC, r0) - opset(AADDCC, r0) - opset(AADDCV, r0) - opset(AADDCVCC, r0) + case AABSF: + opset(AMOVFD, r0) + opset(AMOVDF, r0) + opset(AMOVWF, r0) + opset(AMOVFW, r0) + opset(AMOVWD, r0) + opset(AMOVDW, r0) + opset(ANEGF, r0) + opset(ANEGD, r0) + opset(AABSD, r0) + opset(ATRUNCDW, r0) + opset(ATRUNCFW, r0) + opset(ATRUNCDV, r0) + opset(ATRUNCFV, r0) + opset(AMOVVF, r0) + opset(AMOVFV, r0) + opset(AMOVVD, r0) + opset(AMOVDV, r0) + + case AADD: + opset(ASGT, r0) + opset(ASGTU, r0) + opset(AADDU, r0) opset(AADDV, r0) - opset(AADDVCC, r0) - opset(AADDE, r0) - opset(AADDECC, r0) - opset(AADDEV, r0) - opset(AADDEVCC, r0) - opset(ACRAND, r0) - opset(ACRANDN, r0) - opset(ACREQV, r0) - opset(ACRNAND, r0) - opset(ACRNOR, r0) - opset(ACROR, r0) - opset(ACRORN, r0) - opset(ACRXOR, r0) - opset(AMULHD, r0) - opset(AMULHDCC, r0) - opset(AMULHDU, r0) - opset(AMULHDUCC, r0) - opset(AMULLD, r0) - opset(AMULLDCC, r0) - opset(AMULLDVCC, r0) - opset(AMULLDV, r0) - opset(ADIVD, r0) - opset(ADIVDCC, r0) - opset(ADIVDVCC, r0) - opset(ADIVDV, r0) - opset(ADIVDU, r0) - opset(ADIVDUCC, r0) - opset(ADIVDUVCC, r0) - opset(ADIVDUCC, r0) - - case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */ - opset(AMOVH, r0) - - opset(AMOVHZ, r0) + opset(AADDVU, r0) - case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */ - opset(AMOVHU, r0) - - opset(AMOVHZU, r0) - opset(AMOVWU, r0) - opset(AMOVWZU, r0) - opset(AMOVDU, r0) - opset(AMOVMW, r0) - - case AAND: /* logical op Rb,Rs,Ra; no literal */ - opset(AANDN, r0) - - opset(AANDNCC, r0) - opset(AEQV, r0) - opset(AEQVCC, r0) - opset(ANAND, r0) - opset(ANANDCC, r0) - opset(ANOR, r0) - opset(ANORCC, r0) - opset(AORCC, r0) - opset(AORN, r0) - opset(AORNCC, r0) - opset(AXORCC, r0) - - case AADDME: /* op Ra, Rd */ - opset(AADDMECC, r0) - - opset(AADDMEV, r0) - opset(AADDMEVCC, r0) - opset(AADDZE, r0) - opset(AADDZECC, r0) - opset(AADDZEV, r0) - opset(AADDZEVCC, r0) - opset(ASUBME, r0) - opset(ASUBMECC, r0) - opset(ASUBMEV, r0) - opset(ASUBMEVCC, r0) - opset(ASUBZE, r0) - opset(ASUBZECC, r0) - opset(ASUBZEV, r0) - opset(ASUBZEVCC, r0) - - case AADDC: - opset(AADDCCC, r0) + case AADDF: + opset(ADIVF, r0) + opset(ADIVD, r0) + opset(AMULF, r0) + opset(AMULD, r0) + opset(ASUBF, r0) + opset(ASUBD, r0) + opset(AADDD, r0) + + case AAND: + opset(AOR, r0) + opset(AXOR, r0) case ABEQ: - opset(ABGE, r0) - opset(ABGT, r0) - opset(ABLE, r0) - opset(ABLT, r0) opset(ABNE, r0) - opset(ABVC, r0) - opset(ABVS, r0) - - case ABR: - opset(ABL, r0) - - case ABC: - opset(ABCL, r0) - - case AEXTSB: /* op Rs, Ra */ - opset(AEXTSBCC, r0) - - opset(AEXTSH, r0) - opset(AEXTSHCC, r0) - opset(ACNTLZW, r0) - opset(ACNTLZWCC, r0) - opset(ACNTLZD, r0) - opset(AEXTSW, r0) - opset(AEXTSWCC, r0) - opset(ACNTLZDCC, r0) - - case AFABS: /* fop [s,]d */ - opset(AFABSCC, r0) - - opset(AFNABS, r0) - opset(AFNABSCC, r0) - opset(AFNEG, r0) - opset(AFNEGCC, r0) - opset(AFRSP, r0) - opset(AFRSPCC, r0) - opset(AFCTIW, r0) - opset(AFCTIWCC, r0) - opset(AFCTIWZ, r0) - opset(AFCTIWZCC, r0) - opset(AFCTID, r0) - opset(AFCTIDCC, r0) - opset(AFCTIDZ, r0) - opset(AFCTIDZCC, r0) - opset(AFCFID, r0) - opset(AFCFIDCC, r0) - opset(AFRES, r0) - opset(AFRESCC, r0) - opset(AFRSQRTE, r0) - opset(AFRSQRTECC, r0) - opset(AFSQRT, r0) - opset(AFSQRTCC, r0) - opset(AFSQRTS, r0) - opset(AFSQRTSCC, r0) - - case AFADD: - opset(AFADDS, r0) - opset(AFADDCC, r0) - opset(AFADDSCC, r0) - opset(AFDIV, r0) - opset(AFDIVS, r0) - opset(AFDIVCC, r0) - opset(AFDIVSCC, r0) - opset(AFSUB, r0) - opset(AFSUBS, r0) - opset(AFSUBCC, r0) - opset(AFSUBSCC, r0) - - case AFMADD: - opset(AFMADDCC, r0) - opset(AFMADDS, r0) - opset(AFMADDSCC, r0) - opset(AFMSUB, r0) - opset(AFMSUBCC, r0) - opset(AFMSUBS, r0) - opset(AFMSUBSCC, r0) - opset(AFNMADD, r0) - opset(AFNMADDCC, r0) - opset(AFNMADDS, r0) - opset(AFNMADDSCC, r0) - opset(AFNMSUB, r0) - opset(AFNMSUBCC, r0) - opset(AFNMSUBS, r0) - opset(AFNMSUBSCC, r0) - opset(AFSEL, r0) - opset(AFSELCC, r0) - - case AFMUL: - opset(AFMULS, r0) - opset(AFMULCC, r0) - opset(AFMULSCC, r0) - - case AFCMPO: - opset(AFCMPU, r0) - - case AMTFSB0: - opset(AMTFSB0CC, r0) - opset(AMTFSB1, r0) - opset(AMTFSB1CC, r0) - - case ANEG: /* op [Ra,] Rd */ - opset(ANEGCC, r0) - - opset(ANEGV, r0) - opset(ANEGVCC, r0) - - case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */ - opset(AXOR, r0) - case ASLW: - opset(ASLWCC, r0) - opset(ASRW, r0) - opset(ASRWCC, r0) + case ABLEZ: + opset(ABGEZ, r0) + opset(ABGEZAL, r0) + opset(ABLTZ, r0) + opset(ABLTZAL, r0) + opset(ABGTZ, r0) - case ASLD: - opset(ASLDCC, r0) - opset(ASRD, r0) - opset(ASRDCC, r0) + case AMOVB: + opset(AMOVH, r0) - case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ - opset(ASRAWCC, r0) + case AMOVBU: + opset(AMOVHU, r0) - case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ - opset(ASRADCC, r0) + case AMUL: + opset(AREM, r0) + opset(AREMU, r0) + opset(ADIVU, r0) + opset(AMULU, r0) + opset(ADIV, r0) + opset(ADIVV, r0) + opset(ADIVVU, r0) + opset(AMULV, r0) + opset(AMULVU, r0) + opset(AREMV, r0) + opset(AREMVU, r0) - case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */ - opset(ASUB, r0) + case ASLL: + opset(ASRL, r0) + opset(ASRA, r0) + opset(ASLLV, r0) + opset(ASRAV, r0) + opset(ASRLV, r0) - opset(ASUBCC, r0) + case ASUB: + opset(ASUBU, r0) opset(ASUBV, r0) - opset(ASUBVCC, r0) - opset(ASUBCCC, r0) - opset(ASUBCV, r0) - opset(ASUBCVCC, r0) - opset(ASUBE, r0) - opset(ASUBECC, r0) - opset(ASUBEV, r0) - opset(ASUBEVCC, r0) - - case ASYNC: - opset(AISYNC, r0) - opset(APTESYNC, r0) - opset(ATLBSYNC, r0) - - case ARLWMI: - opset(ARLWMICC, r0) - opset(ARLWNM, r0) - opset(ARLWNMCC, r0) - - case ARLDMI: - opset(ARLDMICC, r0) - - case ARLDC: - opset(ARLDCCC, r0) - - case ARLDCL: - opset(ARLDCR, r0) - opset(ARLDCLCC, r0) - opset(ARLDCRCC, r0) - - case AFMOVD: - opset(AFMOVDCC, r0) - opset(AFMOVDU, r0) - opset(AFMOVS, r0) - opset(AFMOVSU, r0) - - case AECIWX: - opset(ALWAR, r0) - opset(ALDAR, r0) - - case ASYSCALL: /* just the op; flow of control */ - opset(ARFI, r0) - - opset(ARFCI, r0) - opset(ARFID, r0) - opset(AHRFID, r0) - - case AMOVHBR: - opset(AMOVWBR, r0) - - case ASLBMFEE: - opset(ASLBMFEV, r0) - - case ATW: - opset(ATD, r0) - - case ATLBIE: - opset(ASLBIE, r0) - opset(ATLBIEL, r0) - - case AEIEIO: - opset(ASLBIA, r0) - - case ACMP: - opset(ACMPW, r0) - - case ACMPU: - opset(ACMPWU, r0) - - case AADD, - AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ - ALSW, - AMOVW, - /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */ - AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals */ - AMOVD, /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */ - AMOVB, /* macro: move byte with sign extension */ - AMOVBU, /* macro: move byte with sign extension & update */ - AMOVFL, - AMULLW, - /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */ - ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */ - ASTSW, - ASLBMTE, + opset(ASUBVU, r0) + opset(ANOR, r0) + + case ASYSCALL: + opset(ATLBP, r0) + opset(ATLBR, r0) + opset(ATLBWI, r0) + opset(ATLBWR, r0) + + case ACMPEQF: + opset(ACMPGTF, r0) + opset(ACMPGTD, r0) + opset(ACMPGEF, r0) + opset(ACMPGED, r0) + opset(ACMPEQD, r0) + + case ABFPT: + opset(ABFPF, r0) + + case AMOVWL: + opset(AMOVWR, r0) + opset(AMOVVR, r0) + opset(AMOVVL, r0) + + case AMOVW, + AMOVD, + AMOVF, + AMOVV, + ABREAK, + ARFE, + AJAL, + AJMP, + AMOVWU, AWORD, - ADWORD, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -1285,197 +935,60 @@ func buildop(ctxt *obj.Link) { } } -func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 { - return o<<26 | xo<<1 | oe<<10 | rc&1 +func OP(x uint32, y uint32) uint32 { + return x<<3 | y<<0 } -func OPCC(o uint32, xo uint32, rc uint32) uint32 { - return OPVCC(o, xo, 0, rc) +func SP(x uint32, y uint32) uint32 { + return x<<29 | y<<26 } -func OP(o uint32, xo uint32) uint32 { - return OPVCC(o, xo, 0, 0) +func BCOND(x uint32, y uint32) uint32 { + return x<<19 | y<<16 } -/* the order is dest, a/s, b/imm for both arithmetic and logical operations */ -func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 { - return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11 +func MMU(x uint32, y uint32) uint32 { + return SP(2, 0) | 16<<21 | x<<3 | y<<0 } -func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 { - return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF +func FPF(x uint32, y uint32) uint32 { + return SP(2, 1) | 16<<21 | x<<3 | y<<0 } -func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 { - return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11 +func FPD(x uint32, y uint32) uint32 { + return SP(2, 1) | 17<<21 | x<<3 | y<<0 } -func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 { - return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF +func FPW(x uint32, y uint32) uint32 { + return SP(2, 1) | 20<<21 | x<<3 | y<<0 } -func OP_BR(op uint32, li uint32, aa uint32) uint32 { - return op | li&0x03FFFFFC | aa<<1 +func FPV(x uint32, y uint32) uint32 { + return SP(2, 1) | 21<<21 | x<<3 | y<<0 } -func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 { - return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1 +func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { + return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11 } -func OP_BCR(op uint32, bo uint32, bi uint32) uint32 { - return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 +func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 { + return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16 } -func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 { - return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1 +func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 { + return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11 } -const ( - /* each rhs is OPVCC(_, _, _, _) */ - OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0 - OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0 - OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0 - OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0 - OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0 - OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0 - OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0 - OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0 - OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0 - OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0 - OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0 - OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0 - OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0 - OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0 - OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0 - OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0 - OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0 - OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0 - OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0 - OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0 - OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0 - OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0 - OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0 - OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0 - OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0 - OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0 - OP_OR = 31<<26 | 444<<1 | 0<<10 | 0 - OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0 - OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0 - OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0 - OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0 - OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0 - OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0 - OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0 -) - -func oclass(a *obj.Addr) int { - return int(a.Class) - 1 +func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { + return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6 } -// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2. -func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) { - rel := obj.Addrel(ctxt.Cursym) - rel.Off = int32(ctxt.Pc) - rel.Siz = 8 - rel.Sym = s - rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2))) - rel.Type = obj.R_ADDRPOWER +func OP_JMP(op uint32, i uint32) uint32 { + return op | i&0x3FFFFFF } -/* - * 32-bit masks - */ -func getmask(m []byte, v uint32) bool { - m[1] = 0 - m[0] = m[1] - if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */ - if getmask(m, ^v) { - i := int(m[0]) - m[0] = m[1] + 1 - m[1] = byte(i - 1) - return true - } - - return false - } - - for i := 0; i < 32; i++ { - if v&(1<= 32 || v&(1<= 64 || v&(uint64(1)<> 16) - if isuint32(uint64(d)) { - return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v)) - } - return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v)) -} - -func high16adjusted(d int32) uint16 { - if d&0x8000 != 0 { - return uint16((d >> 16) + 1) - } - return uint16(d >> 16) +func oclass(a *obj.Addr) int { + return int(a.Class) - 1 } func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { @@ -1483,934 +996,412 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o2 := uint32(0) o3 := uint32(0) o4 := uint32(0) - o5 := uint32(0) - //print("%v => case %d\n", p, o->type); switch o.type_ { default: - ctxt.Diag("unknown type %d", o.type_) + ctxt.Diag("unknown type %d %v", o.type_) prasm(p) case 0: /* pseudo ops */ break - case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ - if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST { - v := regoff(ctxt, &p.From) - if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 { - //nerrors--; - ctxt.Diag("literal operation on R0\n%v", p) - } - - o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v)) - break - } - - o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)) + case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ + o1 = OP_RRR(oprrr(ctxt, AOR), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg)) - case 2: /* int/cr/fp op Rb,[Ra],Rd */ + case 2: /* add/sub r1,[r2],r3 */ r := int(p.Reg) if r == 0 { r = int(p.To.Reg) } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg)) + o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) - case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */ - d := vregoff(ctxt, &p.From) + case 3: /* mov $soreg, r ==> or/add $i,o,r */ + v := regoff(ctxt, &p.From) - v := int32(d) r := int(p.From.Reg) if r == 0 { r = int(o.param) } - if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) { - ctxt.Diag("literal operation on R0\n%v", p) - } - a := OP_ADDI - if o.a1 == C_UCON { - if d&0xffff != 0 { - log.Fatalf("invalid handling of %v", p) - } - v >>= 16 - if r == REGZERO && isuint32(uint64(d)) { - o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v)) - break - } - - a = OP_ADDIS - } else { - if int64(int16(d)) != d { - log.Fatalf("invalid handling of %v", p) - } + a := AADDVU + if o.a1 == C_ANDCON { + a = AOR } - o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v)) + o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg)) - case 4: /* add/mul $scon,[r1],r2 */ + case 4: /* add $scon,[r1],r2 */ v := regoff(ctxt, &p.From) r := int(p.Reg) if r == 0 { r = int(p.To.Reg) } - if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 { - ctxt.Diag("literal operation on R0\n%v", p) - } - if int32(int16(v)) != v { - log.Fatalf("mishandled instruction %v", p) - } - o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v)) + + o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg)) case 5: /* syscall */ o1 = uint32(oprrr(ctxt, int(p.As))) - case 6: /* logical op Rb,[Rs,]Ra; no literal */ - r := int(p.Reg) - - if r == 0 { - r = int(p.To.Reg) + case 6: /* beq r1,[r2],sbra */ + v := int32(0) + if p.Pcond == nil { + v = int32(-4) >> 2 + } else { + v = int32(p.Pcond.Pc-p.Pc-4) >> 2 + } + if (v<<16)>>16 != v { + ctxt.Diag("short branch too far\n%v", p) } - o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg)) + o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(p.From.Reg), uint32(p.Reg)) + // for ABFPT and ABFPF only: always fill delay slot with 0 + // see comments in func preprocess for details. + o2 = 0 - case 7: /* mov r, soreg ==> stw o(r) */ + case 7: /* mov r, soreg ==> sw o(r) */ r := int(p.To.Reg) - if r == 0 { r = int(o.param) } v := regoff(ctxt, &p.To) - if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 { - if v != 0 { - ctxt.Diag("illegal indexed instruction\n%v", p) - } - o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(r)) - } else { - if int32(int16(v)) != v { - log.Fatalf("mishandled instruction %v", p) - } - o1 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(v)) - } + o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.From.Reg)) - case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */ + case 8: /* mov soreg, r ==> lw o(r) */ r := int(p.From.Reg) - if r == 0 { r = int(o.param) } v := regoff(ctxt, &p.From) - if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 { - if v != 0 { - ctxt.Diag("illegal indexed instruction\n%v", p) - } - o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r)) - } else { - if int32(int16(v)) != v { - log.Fatalf("mishandled instruction %v", p) - } - o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v)) - } + o1 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(v), uint32(r), uint32(p.To.Reg)) - case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */ - r := int(p.From.Reg) + case 9: /* sll r1,[r2],r3 */ + r := int(p.Reg) if r == 0 { - r = int(o.param) + r = int(p.To.Reg) } + o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg)) + + case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */ v := regoff(ctxt, &p.From) - if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 { - if v != 0 { - ctxt.Diag("illegal indexed instruction\n%v", p) - } - o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r)) - } else { - o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v)) + a := AOR + if v < 0 { + a = AADDU } - o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0) - - case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */ + o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP)) r := int(p.Reg) - if r == 0 { r = int(p.To.Reg) } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r)) + o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) - case 11: /* br/bl lbra */ + case 11: /* jmp lbra */ v := int32(0) - - if p.Pcond != nil { - v = int32(p.Pcond.Pc - p.Pc) - if v&03 != 0 { - ctxt.Diag("odd branch target address\n%v", p) - v &^= 03 - } - - if v < -(1<<25) || v >= 1<<24 { - ctxt.Diag("branch too far\n%v", p) - } - } - - o1 = OP_BR(uint32(opirr(ctxt, int(p.As))), uint32(v), 0) - if p.To.Sym != nil { - rel := obj.Addrel(ctxt.Cursym) - rel.Off = int32(ctxt.Pc) - rel.Siz = 4 - rel.Sym = p.To.Sym - v += int32(p.To.Offset) - if v&03 != 0 { - ctxt.Diag("odd branch target address\n%v", p) - v &^= 03 + if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP { + // use PC-relative branch for short branches + // BEQ R0, R0, sbra + if p.Pcond == nil { + v = int32(-4) >> 2 + } else { + v = int32(p.Pcond.Pc-p.Pc-4) >> 2 } - - rel.Add = int64(v) - rel.Type = obj.R_CALLPOWER - } - - case 12: /* movb r,r (extsb); movw r,r (extsw) */ - if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST { - v := regoff(ctxt, &p.From) - if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 { - ctxt.Diag("literal operation on R0\n%v", p) + if (v<<16)>>16 == v { + o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO)) + break } - - o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v)) - break } - - if p.As == AMOVW { - o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0) + if p.Pcond == nil { + v = int32(p.Pc) >> 2 } else { - o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0) - } - - case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */ - if p.As == AMOVBZ { - o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31) - } else if p.As == AMOVH { - o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0) - } else if p.As == AMOVHZ { - o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31) - } else if p.As == AMOVWZ { - o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */ + v = int32(p.Pcond.Pc) >> 2 + } + o1 = OP_JMP(opirr(ctxt, int(p.As)), uint32(v)) + if p.To.Sym == nil { + p.To.Sym = ctxt.Cursym.Text.From.Sym + p.To.Offset = p.Pcond.Pc + } + rel := obj.Addrel(ctxt.Cursym) + rel.Off = int32(ctxt.Pc) + rel.Siz = 4 + rel.Sym = p.To.Sym + rel.Add = p.To.Offset + if p.As == AJAL { + rel.Type = obj.R_CALLMIPS } else { - ctxt.Diag("internal: bad mov[bhw]z\n%v", p) - } - - case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */ - r := int(p.Reg) - - if r == 0 { - r = int(p.To.Reg) - } - d := vregoff(ctxt, p.From3) - var mask [2]uint8 - maskgen64(ctxt, p, mask[:], uint64(d)) - var a int - switch p.As { - case ARLDCL, ARLDCLCC: - a = int(mask[0]) /* MB */ - if mask[1] != 63 { - ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p) - } - - case ARLDCR, ARLDCRCC: - a = int(mask[1]) /* ME */ - if mask[0] != 0 { - ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p) - } - - default: - ctxt.Diag("unexpected op in rldc case\n%v", p) - a = 0 + rel.Type = obj.R_JMPMIPS } - o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg)) - o1 |= (uint32(a) & 31) << 6 - if a&0x20 != 0 { - o1 |= 1 << 5 /* mb[5] is top bit */ + case 12: /* movbs r,r */ + v := 16 + if p.As == AMOVB { + v = 24 } + o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg)) + o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) - case 17, /* bc bo,bi,lbra (same for now) */ - 16: /* bc bo,bi,sbra */ - a := 0 - - if p.From.Type == obj.TYPE_CONST { - a = int(regoff(ctxt, &p.From)) - } - r := int(p.Reg) - if r == 0 { - r = 0 - } - v := int32(0) - if p.Pcond != nil { - v = int32(p.Pcond.Pc - p.Pc) - } - if v&03 != 0 { - ctxt.Diag("odd branch target address\n%v", p) - v &^= 03 - } - - if v < -(1<<16) || v >= 1<<15 { - ctxt.Diag("branch too far\n%v", p) - } - o1 = OP_BC(uint32(opirr(ctxt, int(p.As))), uint32(a), uint32(r), uint32(v), 0) - - case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */ - var v int32 - if p.As == ABC || p.As == ABCL { - v = regoff(ctxt, &p.To) & 31 + case 13: /* movbu r,r */ + if p.As == AMOVBU { + o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg)) } else { - v = 20 /* unconditional */ - } - o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (REG_LR&0x1f)<<16 | ((REG_LR>>5)&0x1f)<<11 - o2 = OPVCC(19, 16, 0, 0) - if p.As == ABL || p.As == ABCL { - o2 |= 1 - } - o2 = OP_BCR(o2, uint32(v), uint32(p.To.Index)) - - case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */ - var v int32 - if p.As == ABC || p.As == ABCL { - v = regoff(ctxt, &p.From) & 31 - } else { - v = 20 /* unconditional */ - } - r := int(p.Reg) - if r == 0 { - r = 0 - } - switch oclass(&p.To) { - case C_CTR: - o1 = OPVCC(19, 528, 0, 0) - - case C_LR: - o1 = OPVCC(19, 16, 0, 0) - - default: - ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p) - v = 0 - } - - if p.As == ABL || p.As == ABCL { - o1 |= 1 + o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg)) } - o1 = OP_BCR(o1, uint32(v), uint32(r)) - case 19: /* mov $lcon,r ==> cau+or */ - d := vregoff(ctxt, &p.From) - - if p.From.Sym == nil { - o1 = loadu32(int(p.To.Reg), d) - o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d))) + case 14: /* movwu r,r */ + o1 = OP_SRR(opirr(ctxt, ASLLV+ALAST), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) + if p.As == AMOVWU { + o2 = OP_SRR(opirr(ctxt, ASRLV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) } else { - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d)))) - o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d)) - addaddrreloc(ctxt, p.From.Sym, &o1, &o2) + o2 = OP_SRR(opirr(ctxt, ASRAV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) } - //if(dlm) reloc(&p->from, p->pc, 0); - - case 20: /* add $ucon,,r */ + case 16: /* sll $c,[r1],r2 */ v := regoff(ctxt, &p.From) - - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - if p.As == AADD && (r0iszero == 0 /*TypeKind(100016)*/ && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) { - ctxt.Diag("literal operation on R0\n%v", p) - } - o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) - - case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */ - if p.To.Reg == REGTMP || p.Reg == REGTMP { - ctxt.Diag("cant synthesize large constant\n%v", p) - } - d := vregoff(ctxt, &p.From) - o1 = loadu32(REGTMP, d) - o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d))) r := int(p.Reg) if r == 0 { r = int(p.To.Reg) } - o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r)) - if p.From.Sym != nil { - ctxt.Diag("%v is not supported", p) - } - - //if(dlm) reloc(&p->from, p->pc, 0); - case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */ - if p.To.Reg == REGTMP || p.Reg == REGTMP { - ctxt.Diag("cant synthesize large constant\n%v", p) - } - d := vregoff(ctxt, &p.From) - o1 = loadu32(REGTMP, d) - o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d))) - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - o3 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r)) - if p.From.Sym != nil { - ctxt.Diag("%v is not supported", p) + /* OP_SRR will use only the low 5 bits of the shift value */ + if v >= 32 && vshift(p.As) { + o1 = OP_SRR(opirr(ctxt, int(p.As)+ALAST), uint32(v-32), uint32(r), uint32(p.To.Reg)) + } else { + o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg)) } - //if(dlm) reloc(&p->from, p->pc, 0); - - /*24*/ - case 25: - /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */ - v := regoff(ctxt, &p.From) - - if v < 0 { - v = 0 - } else if v > 63 { - v = 63 - } + case 18: /* jmp [r1],0(r2) */ r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - var a int - switch p.As { - case ASLD, ASLDCC: - a = int(63 - v) - o1 = OP_RLDICR - - case ASRD, ASRDCC: - a = int(v) - v = 64 - v - o1 = OP_RLDICL - - default: - ctxt.Diag("unexpected op in sldi case\n%v", p) - a = 0 - o1 = 0 - } - - o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F)) - o1 |= (uint32(a) & 31) << 6 - if v&0x20 != 0 { - o1 |= 1 << 1 - } - if a&0x20 != 0 { - o1 |= 1 << 5 /* mb[5] is top bit */ - } - if p.As == ASLDCC || p.As == ASRDCC { - o1 |= 1 /* Rc */ - } - - case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */ - if p.To.Reg == REGTMP { - ctxt.Diag("can't synthesize large constant\n%v", p) - } - v := regoff(ctxt, &p.From) - r := int(p.From.Reg) if r == 0 { r = int(o.param) } - o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v))) - o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v)) - - case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */ - v := regoff(ctxt, p.From3) - - r := int(p.From.Reg) - o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v)) + o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.To.Reg), uint32(r)) + rel := obj.Addrel(ctxt.Cursym) + rel.Off = int32(ctxt.Pc) + rel.Siz = 0 + rel.Type = obj.R_CALLIND - case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */ - if p.To.Reg == REGTMP || p.From.Reg == REGTMP { - ctxt.Diag("can't synthesize large constant\n%v", p) - } - v := regoff(ctxt, p.From3) - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16) - o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v)) - o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP) - if p.From.Sym != nil { - ctxt.Diag("%v is not supported", p) - } - - //if(dlm) reloc(&p->from3, p->pc, 0); - - case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */ + case 19: /* mov $lcon,r ==> lu+or */ v := regoff(ctxt, &p.From) - - d := vregoff(ctxt, p.From3) - var mask [2]uint8 - maskgen64(ctxt, p, mask[:], uint64(d)) - var a int - switch p.As { - case ARLDC, ARLDCCC: - a = int(mask[0]) /* MB */ - if int32(mask[1]) != (63 - v) { - ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p) - } - - case ARLDCL, ARLDCLCC: - a = int(mask[0]) /* MB */ - if mask[1] != 63 { - ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p) - } - - case ARLDCR, ARLDCRCC: - a = int(mask[1]) /* ME */ - if mask[0] != 0 { - ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p) - } - - default: - ctxt.Diag("unexpected op in rldic case\n%v", p) - a = 0 - } - - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F)) - o1 |= (uint32(a) & 31) << 6 - if v&0x20 != 0 { - o1 |= 1 << 1 - } - if a&0x20 != 0 { - o1 |= 1 << 5 /* mb[5] is top bit */ - } - - case 30: /* rldimi $sh,s,$mask,a */ - v := regoff(ctxt, &p.From) - - d := vregoff(ctxt, p.From3) - var mask [2]uint8 - maskgen64(ctxt, p, mask[:], uint64(d)) - if int32(mask[1]) != (63 - v) { - ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p) - } - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F)) - o1 |= (uint32(mask[0]) & 31) << 6 - if v&0x20 != 0 { - o1 |= 1 << 1 - } - if mask[0]&0x20 != 0 { - o1 |= 1 << 5 /* mb[5] is top bit */ - } - - case 31: /* dword */ - d := vregoff(ctxt, &p.From) - - if ctxt.Arch.ByteOrder == binary.BigEndian { - o1 = uint32(d >> 32) - o2 = uint32(d) - } else { - o1 = uint32(d) - o2 = uint32(d >> 32) - } - + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) if p.From.Sym != nil { rel := obj.Addrel(ctxt.Cursym) rel.Off = int32(ctxt.Pc) rel.Siz = 8 rel.Sym = p.From.Sym rel.Add = p.From.Offset - rel.Type = obj.R_ADDR - o2 = 0 - o1 = o2 + rel.Type = obj.R_ADDRMIPS } - case 32: /* fmul frc,fra,frd */ - r := int(p.Reg) - - if r == 0 { - r = int(p.To.Reg) + case 20: /* mov lo/hi,r */ + a := OP(2, 0) /* mfhi */ + if p.From.Reg == REG_LO { + a = OP(2, 2) /* mflo */ } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6 + o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg)) - case 33: /* fabs [frb,]frd; fmr. frb,frd */ - r := int(p.From.Reg) - - if oclass(&p.From) == C_NONE { - r = int(p.To.Reg) + case 21: /* mov r,lo/hi */ + a := OP(2, 1) /* mthi */ + if p.To.Reg == REG_LO { + a = OP(2, 3) /* mtlo */ } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r)) + o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO)) - case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */ - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6 + case 22: /* mul r1,r2 */ + o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO)) - case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */ - v := regoff(ctxt, &p.To) - - r := int(p.To.Reg) + case 23: /* add $lcon,r1,r2 ==> lu+or+add */ + v := regoff(ctxt, &p.From) + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) + r := int(p.Reg) if r == 0 { - r = int(o.param) + r = int(p.To.Reg) } - o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v)) + o3 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) - case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */ + case 24: /* mov $ucon,r ==> lu r */ v := regoff(ctxt, &p.From) + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) - r := int(p.From.Reg) + case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */ + v := regoff(ctxt, &p.From) + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + r := int(p.Reg) if r == 0 { - r = int(o.param) + r = int(p.To.Reg) } - o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v)) + o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) - case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */ + case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */ v := regoff(ctxt, &p.From) - + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) r := int(p.From.Reg) if r == 0 { r = int(o.param) } - o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v)) - o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0) + o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) - case 40: /* word */ - o1 = uint32(regoff(ctxt, &p.From)) - - case 41: /* stswi */ - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11 - - case 42: /* lswi */ - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, p.From3))&0x7F)<<11 - - case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */ - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(p.From.Index), uint32(p.From.Reg)) - - case 44: /* indexed store */ - o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(p.To.Reg)) - - case 45: /* indexed load */ - o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg)) - - case 46: /* plain op */ - o1 = uint32(oprrr(ctxt, int(p.As))) - - case 47: /* op Ra, Rd; also op [Ra,] Rd */ + case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */ + v := regoff(ctxt, &p.From) r := int(p.From.Reg) - if r == 0 { - r = int(p.To.Reg) + r = int(o.param) } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) - - case 48: /* op Rs, Ra */ - r := int(p.From.Reg) - - if r == 0 { - r = int(p.To.Reg) + a := AMOVF + ALAST + if p.As == AMOVD { + a = AMOVD + ALAST } - o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) + switch o.size { + case 16: + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) + o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) + o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(r), uint32(p.To.Reg)) - case 49: /* op Rb; op $n, Rb */ - if p.From.Type != obj.TYPE_REG { /* tlbie $L, rB */ - v := regoff(ctxt, &p.From) & 1 - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21 - } else { - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.From.Reg)) + case 4: + o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg)) } - case 50: /* rem[u] r1[,r2],r3 */ - r := int(p.Reg) - + case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */ + v := regoff(ctxt, &p.To) + r := int(p.To.Reg) if r == 0 { - r = int(p.To.Reg) - } - v := oprrr(ctxt, int(p.As)) - t := v & (1<<10 | 1) /* OE|Rc */ - o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg)) - o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg)) - o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r)) - if p.As == AREMU { - o4 = o3 - - /* Clear top 32 bits */ - o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5 + r = int(o.param) } - - case 51: /* remd[u] r1[,r2],r3 */ - r := int(p.Reg) - - if r == 0 { - r = int(p.To.Reg) + a := AMOVF + if p.As == AMOVD { + a = AMOVD } - v := oprrr(ctxt, int(p.As)) - t := v & (1<<10 | 1) /* OE|Rc */ - o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg)) - o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg)) - o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r)) - - case 52: /* mtfsbNx cr(n) */ - v := regoff(ctxt, &p.From) & 31 - - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(v), 0, 0) - - case 53: /* mffsX ,fr1 */ - o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0) + switch o.size { + case 16: + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) + o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) + o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) - case 54: /* mov msr,r1; mov r1, msr*/ - if oclass(&p.From) == C_REG { - if p.As == AMOVD { - o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0) - } else { - o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0) - } - } else { - o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0) + case 4: + o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg)) } - case 55: /* op Rb, Rd */ - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(p.From.Reg)) - - case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */ - v := regoff(ctxt, &p.From) - - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) - } - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31) - if p.As == ASRAD && (v&0x20 != 0) { - o1 |= 1 << 1 /* mb[5] */ - } + case 30: /* movw r,fr */ + a := SP(2, 1) | (4 << 21) /* mtc1 */ + o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) - case 57: /* slw $sh,[s,]a -> rlwinm ... */ - v := regoff(ctxt, &p.From) + case 31: /* movw fr,r */ + a := SP(2, 1) | (0 << 21) /* mtc1 */ + o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) + case 32: /* fadd fr1,[fr2],fr3 */ r := int(p.Reg) if r == 0 { r = int(p.To.Reg) } + o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) - /* - * Let user (gs) shoot himself in the foot. - * qc has already complained. - * - if(v < 0 || v > 31) - ctxt->diag("illegal shift %ld\n%v", v, p); - */ - if v < 0 { - v = 0 - } else if v > 32 { - v = 32 - } - var mask [2]uint8 - if p.As == ASRW || p.As == ASRWCC { /* shift right */ - mask[0] = uint8(v) - mask[1] = 31 - v = 32 - v - } else { - mask[0] = 0 - mask[1] = uint8(31 - v) - } - - o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1])) - if p.As == ASLWCC || p.As == ASRWCC { - o1 |= 1 /* Rc */ - } + case 33: /* fabs fr1, fr3 */ + o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) - case 58: /* logical $andcon,[s],a */ + case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */ v := regoff(ctxt, &p.From) - - r := int(p.Reg) - if r == 0 { - r = int(p.To.Reg) + a := AADDU + if o.a1 == C_ANDCON { + a = AOR } - o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v)) + o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP)) + o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */ - case 59: /* or/and $ucon,,r */ - v := regoff(ctxt, &p.From) - - r := int(p.Reg) + case 35: /* mov r,lext/auto/oreg ==> sw o(r) */ + v := regoff(ctxt, &p.To) + r := int(p.To.Reg) if r == 0 { - r = int(p.To.Reg) + r = int(o.param) } - o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */ - - case 60: /* tw to,a,b */ - r := int(regoff(ctxt, &p.From) & 31) + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) + o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) + o4 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(p.To.Reg)) - - case 61: /* tw to,a,$simm */ - r := int(regoff(ctxt, &p.From) & 31) - - v := regoff(ctxt, &p.To) - o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(v)) - - case 62: /* rlwmi $sh,s,$mask,a */ + case 36: /* mov lext/auto/oreg,r ==> lw o(r30) */ v := regoff(ctxt, &p.From) - - var mask [2]uint8 - maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3))) - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 - - case 63: /* rlwmi b,s,$mask,a */ - var mask [2]uint8 - maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, p.From3))) - - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 - - case 64: /* mtfsf fr[, $m] {,fpcsr} */ - var v int32 - if p.From3Type() != obj.TYPE_NONE { - v = regoff(ctxt, p.From3) & 255 - } else { - v = 255 - } - o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11 - - case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */ - if p.To.Reg == 0 { - ctxt.Diag("must specify FPSCR(n)\n%v", p) - } - o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12 - - case 66: /* mov spr,r1; mov r1,spr, also dcr */ - var r int - var v int32 - if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 { - r = int(p.From.Reg) - v = int32(p.To.Reg) - if REG_DCR0 <= v && v <= REG_DCR0+1023 { - o1 = OPVCC(31, 451, 0, 0) /* mtdcr */ - } else { - o1 = OPVCC(31, 467, 0, 0) /* mtspr */ - } - } else { - r = int(p.To.Reg) - v = int32(p.From.Reg) - if REG_DCR0 <= v && v <= REG_DCR0+1023 { - o1 = OPVCC(31, 323, 0, 0) /* mfdcr */ - } else { - o1 = OPVCC(31, 339, 0, 0) /* mfspr */ - } - } - - o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11 - - case 67: /* mcrf crfD,crfS */ - if p.From.Type != obj.TYPE_REG || p.From.Reg < REG_CR0 || REG_CR7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg { - ctxt.Diag("illegal CR field number\n%v", p) - } - o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0) - - case 68: /* mfcr rD; mfocrf CRM,rD */ - if p.From.Type == obj.TYPE_REG && REG_CR0 <= p.From.Reg && p.From.Reg <= REG_CR7 { - v := int32(1 << uint(7-(p.To.Reg&7))) /* CR(n) */ - o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */ - } else { - o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */ - } - - case 69: /* mtcrf CRM,rS */ - var v int32 - if p.From3Type() != obj.TYPE_NONE { - if p.To.Reg != 0 { - ctxt.Diag("can't use both mask and CR(n)\n%v", p) - } - v = regoff(ctxt, p.From3) & 0xff - } else { - if p.To.Reg == 0 { - v = 0xff /* CR */ - } else { - v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */ - } - } - - o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12 - - case 70: /* [f]cmp r,r,cr*/ - var r int - if p.Reg == 0 { - r = 0 - } else { - r = (int(p.Reg) & 7) << 2 - } - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg)) - - case 71: /* cmp[l] r,i,cr*/ - var r int - if p.Reg == 0 { - r = 0 - } else { - r = (int(p.Reg) & 7) << 2 + r := int(p.From.Reg) + if r == 0 { + r = int(o.param) } - o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff - - case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */ - o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.From.Reg), 0, uint32(p.To.Reg)) + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) + o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) + o4 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) - case 73: /* mcrfs crfD,crfS */ - if p.From.Type != obj.TYPE_REG || p.From.Reg != REG_FPSCR || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg { - ctxt.Diag("illegal FPSCR/CR field number\n%v", p) + case 37: /* movw r,mr */ + a := SP(2, 0) | (4 << 21) /* mtc0 */ + if p.As == AMOVV { + a = SP(2, 0) | (5 << 21) /* dmtc0 */ } - o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0) + o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) - case 77: /* syscall $scon, syscall Rx */ - if p.From.Type == obj.TYPE_CONST { - if p.From.Offset > BIG || p.From.Offset < -BIG { - ctxt.Diag("illegal syscall, sysnum too large: %v", p) - } - o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset)) - } else if p.From.Type == obj.TYPE_REG { - o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg)) - } else { - ctxt.Diag("illegal syscall: %v", p) - o1 = 0x7fe00008 // trap always + case 38: /* movw mr,r */ + a := SP(2, 0) | (0 << 21) /* mfc0 */ + if p.As == AMOVV { + a = SP(2, 0) | (1 << 21) /* dmfc0 */ } + o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) - o2 = uint32(oprrr(ctxt, int(p.As))) - o3 = AOP_RRR(uint32(oprrr(ctxt, AXOR)), REGZERO, REGZERO, REGZERO) // XOR R0, R0 - - case 78: /* undef */ - o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed - always to be an illegal instruction." */ - - /* relocation operations */ - case 74: - v := regoff(ctxt, &p.To) - - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v)) - addaddrreloc(ctxt, p.To.Sym, &o1, &o2) - - //if(dlm) reloc(&p->to, p->pc, 1); - - case 75: - v := regoff(ctxt, &p.From) - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v)) - addaddrreloc(ctxt, p.From.Sym, &o1, &o2) - - //if(dlm) reloc(&p->from, p->pc, 1); - - case 76: - v := regoff(ctxt, &p.From) - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v))) - o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v)) - addaddrreloc(ctxt, p.From.Sym, &o1, &o2) - o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0) - - //if(dlm) reloc(&p->from, p->pc, 1); + case 40: /* word */ + o1 = uint32(regoff(ctxt, &p.From)) + case 41: /* movw f,fcr */ + o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */ + o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */ + + case 42: /* movw fcr,r */ + o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */ + + case 47: /* movv r,fr */ + a := SP(2, 1) | (5 << 21) /* dmtc1 */ + o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) + + case 48: /* movv fr,r */ + a := SP(2, 1) | (1 << 21) /* dmtc1 */ + o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) + + case 49: /* undef */ + o1 = 8 /* JMP (R0) */ + + /* relocation operations */ + case 50: /* mov r,addr ==> lu + or + sw (REGTMP) */ + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP)) + rel := obj.Addrel(ctxt.Cursym) + rel.Off = int32(ctxt.Pc) + rel.Siz = 8 + rel.Sym = p.To.Sym + rel.Add = p.To.Offset + rel.Type = obj.R_ADDRMIPS + o3 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) + + case 51: /* mov addr,r ==> lu + or + lw (REGTMP) */ + o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP)) + o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP)) + rel := obj.Addrel(ctxt.Cursym) + rel.Off = int32(ctxt.Pc) + rel.Siz = 8 + rel.Sym = p.From.Sym + rel.Add = p.From.Offset + rel.Type = obj.R_ADDRMIPS + o3 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) } out[0] = o1 out[1] = o2 out[2] = o3 out[3] = o4 - out[4] = o5 return } func vregoff(ctxt *obj.Link, a *obj.Addr) int64 { ctxt.Instoffset = 0 - if a != nil { - aclass(ctxt, a) - } + aclass(ctxt, a) return ctxt.Instoffset } @@ -2418,827 +1409,325 @@ func regoff(ctxt *obj.Link, a *obj.Addr) int32 { return int32(vregoff(ctxt, a)) } -func oprrr(ctxt *obj.Link, a int) int32 { +func oprrr(ctxt *obj.Link, a int) uint32 { switch a { case AADD: - return int32(OPVCC(31, 266, 0, 0)) - case AADDCC: - return int32(OPVCC(31, 266, 0, 1)) - case AADDV: - return int32(OPVCC(31, 266, 1, 0)) - case AADDVCC: - return int32(OPVCC(31, 266, 1, 1)) - case AADDC: - return int32(OPVCC(31, 10, 0, 0)) - case AADDCCC: - return int32(OPVCC(31, 10, 0, 1)) - case AADDCV: - return int32(OPVCC(31, 10, 1, 0)) - case AADDCVCC: - return int32(OPVCC(31, 10, 1, 1)) - case AADDE: - return int32(OPVCC(31, 138, 0, 0)) - case AADDECC: - return int32(OPVCC(31, 138, 0, 1)) - case AADDEV: - return int32(OPVCC(31, 138, 1, 0)) - case AADDEVCC: - return int32(OPVCC(31, 138, 1, 1)) - case AADDME: - return int32(OPVCC(31, 234, 0, 0)) - case AADDMECC: - return int32(OPVCC(31, 234, 0, 1)) - case AADDMEV: - return int32(OPVCC(31, 234, 1, 0)) - case AADDMEVCC: - return int32(OPVCC(31, 234, 1, 1)) - case AADDZE: - return int32(OPVCC(31, 202, 0, 0)) - case AADDZECC: - return int32(OPVCC(31, 202, 0, 1)) - case AADDZEV: - return int32(OPVCC(31, 202, 1, 0)) - case AADDZEVCC: - return int32(OPVCC(31, 202, 1, 1)) - + return OP(4, 0) + case AADDU: + return OP(4, 1) + case ASGT: + return OP(5, 2) + case ASGTU: + return OP(5, 3) case AAND: - return int32(OPVCC(31, 28, 0, 0)) - case AANDCC: - return int32(OPVCC(31, 28, 0, 1)) - case AANDN: - return int32(OPVCC(31, 60, 0, 0)) - case AANDNCC: - return int32(OPVCC(31, 60, 0, 1)) - - case ACMP: - return int32(OPVCC(31, 0, 0, 0) | 1<<21) /* L=1 */ - case ACMPU: - return int32(OPVCC(31, 32, 0, 0) | 1<<21) - case ACMPW: - return int32(OPVCC(31, 0, 0, 0)) /* L=0 */ - case ACMPWU: - return int32(OPVCC(31, 32, 0, 0)) - - case ACNTLZW: - return int32(OPVCC(31, 26, 0, 0)) - case ACNTLZWCC: - return int32(OPVCC(31, 26, 0, 1)) - case ACNTLZD: - return int32(OPVCC(31, 58, 0, 0)) - case ACNTLZDCC: - return int32(OPVCC(31, 58, 0, 1)) - - case ACRAND: - return int32(OPVCC(19, 257, 0, 0)) - case ACRANDN: - return int32(OPVCC(19, 129, 0, 0)) - case ACREQV: - return int32(OPVCC(19, 289, 0, 0)) - case ACRNAND: - return int32(OPVCC(19, 225, 0, 0)) - case ACRNOR: - return int32(OPVCC(19, 33, 0, 0)) - case ACROR: - return int32(OPVCC(19, 449, 0, 0)) - case ACRORN: - return int32(OPVCC(19, 417, 0, 0)) - case ACRXOR: - return int32(OPVCC(19, 193, 0, 0)) - - case ADCBF: - return int32(OPVCC(31, 86, 0, 0)) - case ADCBI: - return int32(OPVCC(31, 470, 0, 0)) - case ADCBST: - return int32(OPVCC(31, 54, 0, 0)) - case ADCBT: - return int32(OPVCC(31, 278, 0, 0)) - case ADCBTST: - return int32(OPVCC(31, 246, 0, 0)) - case ADCBZ: - return int32(OPVCC(31, 1014, 0, 0)) - - case AREM, ADIVW: - return int32(OPVCC(31, 491, 0, 0)) - - case AREMCC, ADIVWCC: - return int32(OPVCC(31, 491, 0, 1)) - - case AREMV, ADIVWV: - return int32(OPVCC(31, 491, 1, 0)) - - case AREMVCC, ADIVWVCC: - return int32(OPVCC(31, 491, 1, 1)) - - case AREMU, ADIVWU: - return int32(OPVCC(31, 459, 0, 0)) - - case AREMUCC, ADIVWUCC: - return int32(OPVCC(31, 459, 0, 1)) - - case AREMUV, ADIVWUV: - return int32(OPVCC(31, 459, 1, 0)) - - case AREMUVCC, ADIVWUVCC: - return int32(OPVCC(31, 459, 1, 1)) - - case AREMD, ADIVD: - return int32(OPVCC(31, 489, 0, 0)) - - case AREMDCC, ADIVDCC: - return int32(OPVCC(31, 489, 0, 1)) - - case AREMDV, ADIVDV: - return int32(OPVCC(31, 489, 1, 0)) - - case AREMDVCC, ADIVDVCC: - return int32(OPVCC(31, 489, 1, 1)) - - case AREMDU, ADIVDU: - return int32(OPVCC(31, 457, 0, 0)) - - case AREMDUCC, ADIVDUCC: - return int32(OPVCC(31, 457, 0, 1)) - - case AREMDUV, ADIVDUV: - return int32(OPVCC(31, 457, 1, 0)) - - case AREMDUVCC, ADIVDUVCC: - return int32(OPVCC(31, 457, 1, 1)) - - case AEIEIO: - return int32(OPVCC(31, 854, 0, 0)) - - case AEQV: - return int32(OPVCC(31, 284, 0, 0)) - case AEQVCC: - return int32(OPVCC(31, 284, 0, 1)) - - case AEXTSB: - return int32(OPVCC(31, 954, 0, 0)) - case AEXTSBCC: - return int32(OPVCC(31, 954, 0, 1)) - case AEXTSH: - return int32(OPVCC(31, 922, 0, 0)) - case AEXTSHCC: - return int32(OPVCC(31, 922, 0, 1)) - case AEXTSW: - return int32(OPVCC(31, 986, 0, 0)) - case AEXTSWCC: - return int32(OPVCC(31, 986, 0, 1)) - - case AFABS: - return int32(OPVCC(63, 264, 0, 0)) - case AFABSCC: - return int32(OPVCC(63, 264, 0, 1)) - case AFADD: - return int32(OPVCC(63, 21, 0, 0)) - case AFADDCC: - return int32(OPVCC(63, 21, 0, 1)) - case AFADDS: - return int32(OPVCC(59, 21, 0, 0)) - case AFADDSCC: - return int32(OPVCC(59, 21, 0, 1)) - case AFCMPO: - return int32(OPVCC(63, 32, 0, 0)) - case AFCMPU: - return int32(OPVCC(63, 0, 0, 0)) - case AFCFID: - return int32(OPVCC(63, 846, 0, 0)) - case AFCFIDCC: - return int32(OPVCC(63, 846, 0, 1)) - case AFCTIW: - return int32(OPVCC(63, 14, 0, 0)) - case AFCTIWCC: - return int32(OPVCC(63, 14, 0, 1)) - case AFCTIWZ: - return int32(OPVCC(63, 15, 0, 0)) - case AFCTIWZCC: - return int32(OPVCC(63, 15, 0, 1)) - case AFCTID: - return int32(OPVCC(63, 814, 0, 0)) - case AFCTIDCC: - return int32(OPVCC(63, 814, 0, 1)) - case AFCTIDZ: - return int32(OPVCC(63, 815, 0, 0)) - case AFCTIDZCC: - return int32(OPVCC(63, 815, 0, 1)) - case AFDIV: - return int32(OPVCC(63, 18, 0, 0)) - case AFDIVCC: - return int32(OPVCC(63, 18, 0, 1)) - case AFDIVS: - return int32(OPVCC(59, 18, 0, 0)) - case AFDIVSCC: - return int32(OPVCC(59, 18, 0, 1)) - case AFMADD: - return int32(OPVCC(63, 29, 0, 0)) - case AFMADDCC: - return int32(OPVCC(63, 29, 0, 1)) - case AFMADDS: - return int32(OPVCC(59, 29, 0, 0)) - case AFMADDSCC: - return int32(OPVCC(59, 29, 0, 1)) - - case AFMOVS, AFMOVD: - return int32(OPVCC(63, 72, 0, 0)) /* load */ - case AFMOVDCC: - return int32(OPVCC(63, 72, 0, 1)) - case AFMSUB: - return int32(OPVCC(63, 28, 0, 0)) - case AFMSUBCC: - return int32(OPVCC(63, 28, 0, 1)) - case AFMSUBS: - return int32(OPVCC(59, 28, 0, 0)) - case AFMSUBSCC: - return int32(OPVCC(59, 28, 0, 1)) - case AFMUL: - return int32(OPVCC(63, 25, 0, 0)) - case AFMULCC: - return int32(OPVCC(63, 25, 0, 1)) - case AFMULS: - return int32(OPVCC(59, 25, 0, 0)) - case AFMULSCC: - return int32(OPVCC(59, 25, 0, 1)) - case AFNABS: - return int32(OPVCC(63, 136, 0, 0)) - case AFNABSCC: - return int32(OPVCC(63, 136, 0, 1)) - case AFNEG: - return int32(OPVCC(63, 40, 0, 0)) - case AFNEGCC: - return int32(OPVCC(63, 40, 0, 1)) - case AFNMADD: - return int32(OPVCC(63, 31, 0, 0)) - case AFNMADDCC: - return int32(OPVCC(63, 31, 0, 1)) - case AFNMADDS: - return int32(OPVCC(59, 31, 0, 0)) - case AFNMADDSCC: - return int32(OPVCC(59, 31, 0, 1)) - case AFNMSUB: - return int32(OPVCC(63, 30, 0, 0)) - case AFNMSUBCC: - return int32(OPVCC(63, 30, 0, 1)) - case AFNMSUBS: - return int32(OPVCC(59, 30, 0, 0)) - case AFNMSUBSCC: - return int32(OPVCC(59, 30, 0, 1)) - case AFRES: - return int32(OPVCC(59, 24, 0, 0)) - case AFRESCC: - return int32(OPVCC(59, 24, 0, 1)) - case AFRSP: - return int32(OPVCC(63, 12, 0, 0)) - case AFRSPCC: - return int32(OPVCC(63, 12, 0, 1)) - case AFRSQRTE: - return int32(OPVCC(63, 26, 0, 0)) - case AFRSQRTECC: - return int32(OPVCC(63, 26, 0, 1)) - case AFSEL: - return int32(OPVCC(63, 23, 0, 0)) - case AFSELCC: - return int32(OPVCC(63, 23, 0, 1)) - case AFSQRT: - return int32(OPVCC(63, 22, 0, 0)) - case AFSQRTCC: - return int32(OPVCC(63, 22, 0, 1)) - case AFSQRTS: - return int32(OPVCC(59, 22, 0, 0)) - case AFSQRTSCC: - return int32(OPVCC(59, 22, 0, 1)) - case AFSUB: - return int32(OPVCC(63, 20, 0, 0)) - case AFSUBCC: - return int32(OPVCC(63, 20, 0, 1)) - case AFSUBS: - return int32(OPVCC(59, 20, 0, 0)) - case AFSUBSCC: - return int32(OPVCC(59, 20, 0, 1)) - - case AICBI: - return int32(OPVCC(31, 982, 0, 0)) - case AISYNC: - return int32(OPVCC(19, 150, 0, 0)) - - case AMTFSB0: - return int32(OPVCC(63, 70, 0, 0)) - case AMTFSB0CC: - return int32(OPVCC(63, 70, 0, 1)) - case AMTFSB1: - return int32(OPVCC(63, 38, 0, 0)) - case AMTFSB1CC: - return int32(OPVCC(63, 38, 0, 1)) - - case AMULHW: - return int32(OPVCC(31, 75, 0, 0)) - case AMULHWCC: - return int32(OPVCC(31, 75, 0, 1)) - case AMULHWU: - return int32(OPVCC(31, 11, 0, 0)) - case AMULHWUCC: - return int32(OPVCC(31, 11, 0, 1)) - case AMULLW: - return int32(OPVCC(31, 235, 0, 0)) - case AMULLWCC: - return int32(OPVCC(31, 235, 0, 1)) - case AMULLWV: - return int32(OPVCC(31, 235, 1, 0)) - case AMULLWVCC: - return int32(OPVCC(31, 235, 1, 1)) - - case AMULHD: - return int32(OPVCC(31, 73, 0, 0)) - case AMULHDCC: - return int32(OPVCC(31, 73, 0, 1)) - case AMULHDU: - return int32(OPVCC(31, 9, 0, 0)) - case AMULHDUCC: - return int32(OPVCC(31, 9, 0, 1)) - case AMULLD: - return int32(OPVCC(31, 233, 0, 0)) - case AMULLDCC: - return int32(OPVCC(31, 233, 0, 1)) - case AMULLDV: - return int32(OPVCC(31, 233, 1, 0)) - case AMULLDVCC: - return int32(OPVCC(31, 233, 1, 1)) - - case ANAND: - return int32(OPVCC(31, 476, 0, 0)) - case ANANDCC: - return int32(OPVCC(31, 476, 0, 1)) - case ANEG: - return int32(OPVCC(31, 104, 0, 0)) - case ANEGCC: - return int32(OPVCC(31, 104, 0, 1)) - case ANEGV: - return int32(OPVCC(31, 104, 1, 0)) - case ANEGVCC: - return int32(OPVCC(31, 104, 1, 1)) - case ANOR: - return int32(OPVCC(31, 124, 0, 0)) - case ANORCC: - return int32(OPVCC(31, 124, 0, 1)) + return OP(4, 4) case AOR: - return int32(OPVCC(31, 444, 0, 0)) - case AORCC: - return int32(OPVCC(31, 444, 0, 1)) - case AORN: - return int32(OPVCC(31, 412, 0, 0)) - case AORNCC: - return int32(OPVCC(31, 412, 0, 1)) - - case ARFI: - return int32(OPVCC(19, 50, 0, 0)) - case ARFCI: - return int32(OPVCC(19, 51, 0, 0)) - case ARFID: - return int32(OPVCC(19, 18, 0, 0)) - case AHRFID: - return int32(OPVCC(19, 274, 0, 0)) - - case ARLWMI: - return int32(OPVCC(20, 0, 0, 0)) - case ARLWMICC: - return int32(OPVCC(20, 0, 0, 1)) - case ARLWNM: - return int32(OPVCC(23, 0, 0, 0)) - case ARLWNMCC: - return int32(OPVCC(23, 0, 0, 1)) - - case ARLDCL: - return int32(OPVCC(30, 8, 0, 0)) - case ARLDCR: - return int32(OPVCC(30, 9, 0, 0)) - - case ASYSCALL: - return int32(OPVCC(17, 1, 0, 0)) - - case ASLW: - return int32(OPVCC(31, 24, 0, 0)) - case ASLWCC: - return int32(OPVCC(31, 24, 0, 1)) - case ASLD: - return int32(OPVCC(31, 27, 0, 0)) - case ASLDCC: - return int32(OPVCC(31, 27, 0, 1)) - - case ASRAW: - return int32(OPVCC(31, 792, 0, 0)) - case ASRAWCC: - return int32(OPVCC(31, 792, 0, 1)) - case ASRAD: - return int32(OPVCC(31, 794, 0, 0)) - case ASRADCC: - return int32(OPVCC(31, 794, 0, 1)) - - case ASRW: - return int32(OPVCC(31, 536, 0, 0)) - case ASRWCC: - return int32(OPVCC(31, 536, 0, 1)) - case ASRD: - return int32(OPVCC(31, 539, 0, 0)) - case ASRDCC: - return int32(OPVCC(31, 539, 0, 1)) - + return OP(4, 5) + case AXOR: + return OP(4, 6) case ASUB: - return int32(OPVCC(31, 40, 0, 0)) - case ASUBCC: - return int32(OPVCC(31, 40, 0, 1)) + return OP(4, 2) + case ASUBU: + return OP(4, 3) + case ANOR: + return OP(4, 7) + case ASLL: + return OP(0, 4) + case ASRL: + return OP(0, 6) + case ASRA: + return OP(0, 7) + case ASLLV: + return OP(2, 4) + case ASRLV: + return OP(2, 6) + case ASRAV: + return OP(2, 7) + case AADDV: + return OP(5, 4) + case AADDVU: + return OP(5, 5) case ASUBV: - return int32(OPVCC(31, 40, 1, 0)) - case ASUBVCC: - return int32(OPVCC(31, 40, 1, 1)) - case ASUBC: - return int32(OPVCC(31, 8, 0, 0)) - case ASUBCCC: - return int32(OPVCC(31, 8, 0, 1)) - case ASUBCV: - return int32(OPVCC(31, 8, 1, 0)) - case ASUBCVCC: - return int32(OPVCC(31, 8, 1, 1)) - case ASUBE: - return int32(OPVCC(31, 136, 0, 0)) - case ASUBECC: - return int32(OPVCC(31, 136, 0, 1)) - case ASUBEV: - return int32(OPVCC(31, 136, 1, 0)) - case ASUBEVCC: - return int32(OPVCC(31, 136, 1, 1)) - case ASUBME: - return int32(OPVCC(31, 232, 0, 0)) - case ASUBMECC: - return int32(OPVCC(31, 232, 0, 1)) - case ASUBMEV: - return int32(OPVCC(31, 232, 1, 0)) - case ASUBMEVCC: - return int32(OPVCC(31, 232, 1, 1)) - case ASUBZE: - return int32(OPVCC(31, 200, 0, 0)) - case ASUBZECC: - return int32(OPVCC(31, 200, 0, 1)) - case ASUBZEV: - return int32(OPVCC(31, 200, 1, 0)) - case ASUBZEVCC: - return int32(OPVCC(31, 200, 1, 1)) - - case ASYNC: - return int32(OPVCC(31, 598, 0, 0)) - case APTESYNC: - return int32(OPVCC(31, 598, 0, 0) | 2<<21) - - case ATLBIE: - return int32(OPVCC(31, 306, 0, 0)) - case ATLBIEL: - return int32(OPVCC(31, 274, 0, 0)) - case ATLBSYNC: - return int32(OPVCC(31, 566, 0, 0)) - case ASLBIA: - return int32(OPVCC(31, 498, 0, 0)) - case ASLBIE: - return int32(OPVCC(31, 434, 0, 0)) - case ASLBMFEE: - return int32(OPVCC(31, 915, 0, 0)) - case ASLBMFEV: - return int32(OPVCC(31, 851, 0, 0)) - case ASLBMTE: - return int32(OPVCC(31, 402, 0, 0)) - - case ATW: - return int32(OPVCC(31, 4, 0, 0)) - case ATD: - return int32(OPVCC(31, 68, 0, 0)) - - case AXOR: - return int32(OPVCC(31, 316, 0, 0)) - case AXORCC: - return int32(OPVCC(31, 316, 0, 1)) + return OP(5, 6) + case ASUBVU: + return OP(5, 7) + case AREM, + ADIV: + return OP(3, 2) + case AREMU, + ADIVU: + return OP(3, 3) + case AMUL: + return OP(3, 0) + case AMULU: + return OP(3, 1) + case AREMV, + ADIVV: + return OP(3, 6) + case AREMVU, + ADIVVU: + return OP(3, 7) + case AMULV: + return OP(3, 4) + case AMULVU: + return OP(3, 5) + + case AJMP: + return OP(1, 0) + case AJAL: + return OP(1, 1) + + case ABREAK: + return OP(1, 5) + case ASYSCALL: + return OP(1, 4) + case ATLBP: + return MMU(1, 0) + case ATLBR: + return MMU(0, 1) + case ATLBWI: + return MMU(0, 2) + case ATLBWR: + return MMU(0, 6) + case ARFE: + return MMU(2, 0) + + case ADIVF: + return FPF(0, 3) + case ADIVD: + return FPD(0, 3) + case AMULF: + return FPF(0, 2) + case AMULD: + return FPD(0, 2) + case ASUBF: + return FPF(0, 1) + case ASUBD: + return FPD(0, 1) + case AADDF: + return FPF(0, 0) + case AADDD: + return FPD(0, 0) + case ATRUNCFV: + return FPF(1, 1) + case ATRUNCDV: + return FPD(1, 1) + case ATRUNCFW: + return FPF(1, 5) + case ATRUNCDW: + return FPD(1, 5) + case AMOVFV: + return FPF(4, 5) + case AMOVDV: + return FPD(4, 5) + case AMOVVF: + return FPV(4, 0) + case AMOVVD: + return FPV(4, 1) + case AMOVFW: + return FPF(4, 4) + case AMOVDW: + return FPD(4, 4) + case AMOVWF: + return FPW(4, 0) + case AMOVDF: + return FPD(4, 0) + case AMOVWD: + return FPW(4, 1) + case AMOVFD: + return FPF(4, 1) + case AABSF: + return FPF(0, 5) + case AABSD: + return FPD(0, 5) + case AMOVF: + return FPF(0, 6) + case AMOVD: + return FPD(0, 6) + case ANEGF: + return FPF(0, 7) + case ANEGD: + return FPD(0, 7) + case ACMPEQF: + return FPF(6, 2) + case ACMPEQD: + return FPD(6, 2) + case ACMPGTF: + return FPF(7, 4) + case ACMPGTD: + return FPD(7, 4) + case ACMPGEF: + return FPF(7, 6) + case ACMPGED: + return FPD(7, 6) } - ctxt.Diag("bad r/r opcode %v", obj.Aconv(a)) + if a >= ALAST { + ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST)) + } else { + ctxt.Diag("bad rrr opcode %v", obj.Aconv(a)) + } return 0 } -func opirr(ctxt *obj.Link, a int) int32 { +func opirr(ctxt *obj.Link, a int) uint32 { switch a { case AADD: - return int32(OPVCC(14, 0, 0, 0)) - case AADDC: - return int32(OPVCC(12, 0, 0, 0)) - case AADDCCC: - return int32(OPVCC(13, 0, 0, 0)) - case AADD + ALAST: - return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */ - - case AANDCC: - return int32(OPVCC(28, 0, 0, 0)) - case AANDCC + ALAST: - return int32(OPVCC(29, 0, 0, 0)) /* ANDIS./ANDIU. */ - - case ABR: - return int32(OPVCC(18, 0, 0, 0)) - case ABL: - return int32(OPVCC(18, 0, 0, 0) | 1) - case obj.ADUFFZERO: - return int32(OPVCC(18, 0, 0, 0) | 1) - case obj.ADUFFCOPY: - return int32(OPVCC(18, 0, 0, 0) | 1) - case ABC: - return int32(OPVCC(16, 0, 0, 0)) - case ABCL: - return int32(OPVCC(16, 0, 0, 0) | 1) - - case ABEQ: - return int32(AOP_RRR(16<<26, 12, 2, 0)) - case ABGE: - return int32(AOP_RRR(16<<26, 4, 0, 0)) - case ABGT: - return int32(AOP_RRR(16<<26, 12, 1, 0)) - case ABLE: - return int32(AOP_RRR(16<<26, 4, 1, 0)) - case ABLT: - return int32(AOP_RRR(16<<26, 12, 0, 0)) - case ABNE: - return int32(AOP_RRR(16<<26, 4, 2, 0)) - case ABVC: - return int32(AOP_RRR(16<<26, 4, 3, 0)) - case ABVS: - return int32(AOP_RRR(16<<26, 12, 3, 0)) - - case ACMP: - return int32(OPVCC(11, 0, 0, 0) | 1<<21) /* L=1 */ - case ACMPU: - return int32(OPVCC(10, 0, 0, 0) | 1<<21) - case ACMPW: - return int32(OPVCC(11, 0, 0, 0)) /* L=0 */ - case ACMPWU: - return int32(OPVCC(10, 0, 0, 0)) - case ALSW: - return int32(OPVCC(31, 597, 0, 0)) - - case AMULLW: - return int32(OPVCC(7, 0, 0, 0)) - + return SP(1, 0) + case AADDU: + return SP(1, 1) + case ASGT: + return SP(1, 2) + case ASGTU: + return SP(1, 3) + case AAND: + return SP(1, 4) case AOR: - return int32(OPVCC(24, 0, 0, 0)) - case AOR + ALAST: - return int32(OPVCC(25, 0, 0, 0)) /* ORIS/ORIU */ - - case ARLWMI: - return int32(OPVCC(20, 0, 0, 0)) /* rlwimi */ - case ARLWMICC: - return int32(OPVCC(20, 0, 0, 1)) - case ARLDMI: - return int32(OPVCC(30, 0, 0, 0) | 3<<2) /* rldimi */ - case ARLDMICC: - return int32(OPVCC(30, 0, 0, 1) | 3<<2) - - case ARLWNM: - return int32(OPVCC(21, 0, 0, 0)) /* rlwinm */ - case ARLWNMCC: - return int32(OPVCC(21, 0, 0, 1)) - - case ARLDCL: - return int32(OPVCC(30, 0, 0, 0)) /* rldicl */ - case ARLDCLCC: - return int32(OPVCC(30, 0, 0, 1)) - case ARLDCR: - return int32(OPVCC(30, 1, 0, 0)) /* rldicr */ - case ARLDCRCC: - return int32(OPVCC(30, 1, 0, 1)) - case ARLDC: - return int32(OPVCC(30, 0, 0, 0) | 2<<2) - case ARLDCCC: - return int32(OPVCC(30, 0, 0, 1) | 2<<2) - - case ASRAW: - return int32(OPVCC(31, 824, 0, 0)) - case ASRAWCC: - return int32(OPVCC(31, 824, 0, 1)) - case ASRAD: - return int32(OPVCC(31, (413 << 1), 0, 0)) - case ASRADCC: - return int32(OPVCC(31, (413 << 1), 0, 1)) - - case ASTSW: - return int32(OPVCC(31, 725, 0, 0)) - - case ASUBC: - return int32(OPVCC(8, 0, 0, 0)) - - case ATW: - return int32(OPVCC(3, 0, 0, 0)) - case ATD: - return int32(OPVCC(2, 0, 0, 0)) - + return SP(1, 5) case AXOR: - return int32(OPVCC(26, 0, 0, 0)) /* XORIL */ - case AXOR + ALAST: - return int32(OPVCC(27, 0, 0, 0)) /* XORIU */ - } - - ctxt.Diag("bad opcode i/r %v", obj.Aconv(a)) - return 0 -} - -/* - * load o(a),d - */ -func opload(ctxt *obj.Link, a int) int32 { - switch a { - case AMOVD: - return int32(OPVCC(58, 0, 0, 0)) /* ld */ - case AMOVDU: - return int32(OPVCC(58, 0, 0, 1)) /* ldu */ - case AMOVWZ: - return int32(OPVCC(32, 0, 0, 0)) /* lwz */ - case AMOVWZU: - return int32(OPVCC(33, 0, 0, 0)) /* lwzu */ - case AMOVW: - return int32(OPVCC(58, 0, 0, 0) | 1<<1) /* lwa */ - - /* no AMOVWU */ - case AMOVB, AMOVBZ: - return int32(OPVCC(34, 0, 0, 0)) - /* load */ - - case AMOVBU, AMOVBZU: - return int32(OPVCC(35, 0, 0, 0)) - case AFMOVD: - return int32(OPVCC(50, 0, 0, 0)) - case AFMOVDU: - return int32(OPVCC(51, 0, 0, 0)) - case AFMOVS: - return int32(OPVCC(48, 0, 0, 0)) - case AFMOVSU: - return int32(OPVCC(49, 0, 0, 0)) - case AMOVH: - return int32(OPVCC(42, 0, 0, 0)) - case AMOVHU: - return int32(OPVCC(43, 0, 0, 0)) - case AMOVHZ: - return int32(OPVCC(40, 0, 0, 0)) - case AMOVHZU: - return int32(OPVCC(41, 0, 0, 0)) - case AMOVMW: - return int32(OPVCC(46, 0, 0, 0)) /* lmw */ - } - - ctxt.Diag("bad load opcode %v", obj.Aconv(a)) - return 0 -} - -/* - * indexed load a(b),d - */ -func oploadx(ctxt *obj.Link, a int) int32 { - switch a { - case AMOVWZ: - return int32(OPVCC(31, 23, 0, 0)) /* lwzx */ - case AMOVWZU: - return int32(OPVCC(31, 55, 0, 0)) /* lwzux */ - case AMOVW: - return int32(OPVCC(31, 341, 0, 0)) /* lwax */ - case AMOVWU: - return int32(OPVCC(31, 373, 0, 0)) /* lwaux */ - - case AMOVB, AMOVBZ: - return int32(OPVCC(31, 87, 0, 0)) /* lbzx */ - - case AMOVBU, AMOVBZU: - return int32(OPVCC(31, 119, 0, 0)) /* lbzux */ - case AFMOVD: - return int32(OPVCC(31, 599, 0, 0)) /* lfdx */ - case AFMOVDU: - return int32(OPVCC(31, 631, 0, 0)) /* lfdux */ - case AFMOVS: - return int32(OPVCC(31, 535, 0, 0)) /* lfsx */ - case AFMOVSU: - return int32(OPVCC(31, 567, 0, 0)) /* lfsux */ - case AMOVH: - return int32(OPVCC(31, 343, 0, 0)) /* lhax */ - case AMOVHU: - return int32(OPVCC(31, 375, 0, 0)) /* lhaux */ - case AMOVHBR: - return int32(OPVCC(31, 790, 0, 0)) /* lhbrx */ - case AMOVWBR: - return int32(OPVCC(31, 534, 0, 0)) /* lwbrx */ - case AMOVHZ: - return int32(OPVCC(31, 279, 0, 0)) /* lhzx */ - case AMOVHZU: - return int32(OPVCC(31, 311, 0, 0)) /* lhzux */ - case AECIWX: - return int32(OPVCC(31, 310, 0, 0)) /* eciwx */ - case ALWAR: - return int32(OPVCC(31, 20, 0, 0)) /* lwarx */ - case ALDAR: - return int32(OPVCC(31, 84, 0, 0)) - case ALSW: - return int32(OPVCC(31, 533, 0, 0)) /* lswx */ + return SP(1, 6) + case ALAST: + return SP(1, 7) /* lui */ + case ASLL: + return OP(0, 0) + case ASRL: + return OP(0, 2) + case ASRA: + return OP(0, 3) + case AADDV: + return SP(3, 0) + case AADDVU: + return SP(3, 1) + + case AJMP: + return SP(0, 2) + case AJAL, + obj.ADUFFZERO, + obj.ADUFFCOPY: + return SP(0, 3) + case ABEQ: + return SP(0, 4) + case ABEQ + ALAST: + return SP(2, 4) /* likely */ + case ABNE: + return SP(0, 5) + case ABNE + ALAST: + return SP(2, 5) /* likely */ + case ABGEZ: + return SP(0, 1) | BCOND(0, 1) + case ABGEZ + ALAST: + return SP(0, 1) | BCOND(0, 3) /* likely */ + case ABGEZAL: + return SP(0, 1) | BCOND(2, 1) + case ABGEZAL + ALAST: + return SP(0, 1) | BCOND(2, 3) /* likely */ + case ABGTZ: + return SP(0, 7) + case ABGTZ + ALAST: + return SP(2, 7) /* likely */ + case ABLEZ: + return SP(0, 6) + case ABLEZ + ALAST: + return SP(2, 6) /* likely */ + case ABLTZ: + return SP(0, 1) | BCOND(0, 0) + case ABLTZ + ALAST: + return SP(0, 1) | BCOND(0, 2) /* likely */ + case ABLTZAL: + return SP(0, 1) | BCOND(2, 0) + case ABLTZAL + ALAST: + return SP(0, 1) | BCOND(2, 2) /* likely */ + case ABFPT: + return SP(2, 1) | (257 << 16) + case ABFPT + ALAST: + return SP(2, 1) | (259 << 16) /* likely */ + case ABFPF: + return SP(2, 1) | (256 << 16) + case ABFPF + ALAST: + return SP(2, 1) | (258 << 16) /* likely */ + + case AMOVB, + AMOVBU: + return SP(5, 0) + case AMOVH, + AMOVHU: + return SP(5, 1) + case AMOVW, + AMOVWU: + return SP(5, 3) + case AMOVV: + return SP(7, 7) + case AMOVF: + return SP(7, 1) case AMOVD: - return int32(OPVCC(31, 21, 0, 0)) /* ldx */ - case AMOVDU: - return int32(OPVCC(31, 53, 0, 0)) /* ldux */ + return SP(7, 5) + case AMOVWL: + return SP(5, 2) + case AMOVWR: + return SP(5, 6) + case AMOVVL: + return SP(5, 4) + case AMOVVR: + return SP(5, 5) + + case ABREAK: + return SP(5, 7) + + case AMOVWL + ALAST: + return SP(4, 2) + case AMOVWR + ALAST: + return SP(4, 6) + case AMOVVL + ALAST: + return SP(3, 2) + case AMOVVR + ALAST: + return SP(3, 3) + case AMOVB + ALAST: + return SP(4, 0) + case AMOVBU + ALAST: + return SP(4, 4) + case AMOVH + ALAST: + return SP(4, 1) + case AMOVHU + ALAST: + return SP(4, 5) + case AMOVW + ALAST: + return SP(4, 3) + case AMOVWU + ALAST: + return SP(4, 7) + case AMOVV + ALAST: + return SP(6, 7) + case AMOVF + ALAST: + return SP(6, 1) + case AMOVD + ALAST: + return SP(6, 5) + + case ASLLV: + return OP(7, 0) + case ASRLV: + return OP(7, 2) + case ASRAV: + return OP(7, 3) + case ASLLV + ALAST: + return OP(7, 4) + case ASRLV + ALAST: + return OP(7, 6) + case ASRAV + ALAST: + return OP(7, 7) } - ctxt.Diag("bad loadx opcode %v", obj.Aconv(a)) - return 0 -} - -/* - * store s,o(d) - */ -func opstore(ctxt *obj.Link, a int) int32 { - switch a { - case AMOVB, AMOVBZ: - return int32(OPVCC(38, 0, 0, 0)) /* stb */ - - case AMOVBU, AMOVBZU: - return int32(OPVCC(39, 0, 0, 0)) /* stbu */ - case AFMOVD: - return int32(OPVCC(54, 0, 0, 0)) /* stfd */ - case AFMOVDU: - return int32(OPVCC(55, 0, 0, 0)) /* stfdu */ - case AFMOVS: - return int32(OPVCC(52, 0, 0, 0)) /* stfs */ - case AFMOVSU: - return int32(OPVCC(53, 0, 0, 0)) /* stfsu */ - - case AMOVHZ, AMOVH: - return int32(OPVCC(44, 0, 0, 0)) /* sth */ - - case AMOVHZU, AMOVHU: - return int32(OPVCC(45, 0, 0, 0)) /* sthu */ - case AMOVMW: - return int32(OPVCC(47, 0, 0, 0)) /* stmw */ - case ASTSW: - return int32(OPVCC(31, 725, 0, 0)) /* stswi */ - - case AMOVWZ, AMOVW: - return int32(OPVCC(36, 0, 0, 0)) /* stw */ - - case AMOVWZU, AMOVWU: - return int32(OPVCC(37, 0, 0, 0)) /* stwu */ - case AMOVD: - return int32(OPVCC(62, 0, 0, 0)) /* std */ - case AMOVDU: - return int32(OPVCC(62, 0, 0, 1)) /* stdu */ + if a >= ALAST { + ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST)) + } else { + ctxt.Diag("bad irr opcode %v", obj.Aconv(a)) } - - ctxt.Diag("unknown store opcode %v", obj.Aconv(a)) return 0 } -/* - * indexed store s,a(b) - */ -func opstorex(ctxt *obj.Link, a int) int32 { +func vshift(a int16) bool { switch a { - case AMOVB, AMOVBZ: - return int32(OPVCC(31, 215, 0, 0)) /* stbx */ - - case AMOVBU, AMOVBZU: - return int32(OPVCC(31, 247, 0, 0)) /* stbux */ - case AFMOVD: - return int32(OPVCC(31, 727, 0, 0)) /* stfdx */ - case AFMOVDU: - return int32(OPVCC(31, 759, 0, 0)) /* stfdux */ - case AFMOVS: - return int32(OPVCC(31, 663, 0, 0)) /* stfsx */ - case AFMOVSU: - return int32(OPVCC(31, 695, 0, 0)) /* stfsux */ - - case AMOVHZ, AMOVH: - return int32(OPVCC(31, 407, 0, 0)) /* sthx */ - case AMOVHBR: - return int32(OPVCC(31, 918, 0, 0)) /* sthbrx */ - - case AMOVHZU, AMOVHU: - return int32(OPVCC(31, 439, 0, 0)) /* sthux */ - - case AMOVWZ, AMOVW: - return int32(OPVCC(31, 151, 0, 0)) /* stwx */ - - case AMOVWZU, AMOVWU: - return int32(OPVCC(31, 183, 0, 0)) /* stwux */ - case ASTSW: - return int32(OPVCC(31, 661, 0, 0)) /* stswx */ - case AMOVWBR: - return int32(OPVCC(31, 662, 0, 0)) /* stwbrx */ - case ASTWCCC: - return int32(OPVCC(31, 150, 0, 1)) /* stwcx. */ - case ASTDCCC: - return int32(OPVCC(31, 214, 0, 1)) /* stwdx. */ - case AECOWX: - return int32(OPVCC(31, 438, 0, 0)) /* ecowx */ - case AMOVD: - return int32(OPVCC(31, 149, 0, 0)) /* stdx */ - case AMOVDU: - return int32(OPVCC(31, 181, 0, 0)) /* stdux */ + case ASLLV, + ASRLV, + ASRAV: + return true } - - ctxt.Diag("unknown storex opcode %v", obj.Aconv(a)) - return 0 + return false } diff --git a/src/cmd/internal/obj/mips/list0.go b/src/cmd/internal/obj/mips/list0.go index 4cdcfbcd27..0807a62a8d 100644 --- a/src/cmd/internal/obj/mips/list0.go +++ b/src/cmd/internal/obj/mips/list0.go @@ -27,7 +27,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package ppc64 +package mips import ( "cmd/internal/obj" @@ -35,8 +35,8 @@ import ( ) func init() { - obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, Rconv) - obj.RegisterOpcode(obj.ABasePPC64, Anames) + obj.RegisterRegister(obj.RBaseMIPS64, REG_FCR0+1024, Rconv) + obj.RegisterOpcode(obj.ABaseMIPS64, Anames) } func Rconv(r int) string { @@ -53,44 +53,26 @@ func Rconv(r int) string { if REG_F0 <= r && r <= REG_F31 { return fmt.Sprintf("F%d", r-REG_F0) } - if REG_CR0 <= r && r <= REG_CR7 { - return fmt.Sprintf("CR%d", r-REG_CR0) + if REG_M0 <= r && r <= REG_M31 { + return fmt.Sprintf("M%d", r-REG_M0) } - if r == REG_CR { - return "CR" + if REG_FCR0 <= r && r <= REG_FCR31 { + return fmt.Sprintf("FCR%d", r-REG_FCR0) } - if REG_SPR0 <= r && r <= REG_SPR0+1023 { - switch r { - case REG_XER: - return "XER" - - case REG_LR: - return "LR" - - case REG_CTR: - return "CTR" - } - - return fmt.Sprintf("SPR(%d)", r-REG_SPR0) - } - - if REG_DCR0 <= r && r <= REG_DCR0+1023 { - return fmt.Sprintf("DCR(%d)", r-REG_DCR0) - } - if r == REG_FPSCR { - return "FPSCR" + if r == REG_HI { + return "HI" } - if r == REG_MSR { - return "MSR" + if r == REG_LO { + return "LO" } - return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64) + return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64) } func DRconv(a int) string { s := "C_??" if a >= C_NONE && a <= C_NCLASS { - s = cnames9[a] + s = cnames0[a] } var fp string fp += s diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 1eddc6fc6c..a3ccad2764 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -27,7 +27,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package ppc64 +package mips import ( "cmd/internal/obj" @@ -40,11 +40,11 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { p.From.Class = 0 p.To.Class = 0 - // Rewrite BR/BL to symbol as TYPE_BRANCH. + // Rewrite JMP/JAL to symbol as TYPE_BRANCH. switch p.As { - case ABR, - ABL, - obj.ARET, + case AJMP, + AJAL, + ARET, obj.ADUFFZERO, obj.ADUFFCOPY: if p.To.Sym != nil { @@ -54,7 +54,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { // Rewrite float constants to values stored in memory. switch p.As { - case AFMOVS: + case AMOVF: if p.From.Type == obj.TYPE_FCONST { f32 := float32(p.From.Val.(float64)) i32 := math.Float32bits(f32) @@ -67,7 +67,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { p.From.Offset = 0 } - case AFMOVD: + case AMOVD: if p.From.Type == obj.TYPE_FCONST { i64 := math.Float64bits(p.From.Val.(float64)) literal := fmt.Sprintf("$f64.%016x", i64) @@ -80,7 +80,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { } // Put >32-bit constants in memory and load them - case AMOVD: + case AMOVV: if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset { literal := fmt.Sprintf("$i64.%016x", uint64(p.From.Offset)) s := obj.Linklookup(ctxt, literal, 0) @@ -94,22 +94,28 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { // Rewrite SUB constants into ADD. switch p.As { - case ASUBC: + case ASUB: if p.From.Type == obj.TYPE_CONST { p.From.Offset = -p.From.Offset - p.As = AADDC + p.As = AADD } - case ASUBCCC: + case ASUBU: if p.From.Type == obj.TYPE_CONST { p.From.Offset = -p.From.Offset - p.As = AADDCCC + p.As = AADDU } - case ASUB: + case ASUBV: if p.From.Type == obj.TYPE_CONST { p.From.Offset = -p.From.Offset - p.As = AADD + p.As = AADDV + } + + case ASUBVU: + if p.From.Type == obj.TYPE_CONST { + p.From.Offset = -p.From.Offset + p.As = AADDVU } } } @@ -118,6 +124,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { // TODO(minux): add morestack short-cuts with small fixed frame-size. ctxt.Cursym = cursym + // a switch for enabling/disabling instruction scheduling + nosched := true + if cursym.Text == nil || cursym.Text.Link == nil { return } @@ -152,112 +161,65 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { p.Link.Mark |= LABEL } - case ANOR: + /* too hard, just leave alone */ + case AMOVW, + AMOVV: q = p - if p.To.Type == obj.TYPE_REG { - if p.To.Reg == REGZERO { - p.Mark |= LABEL | SYNC - } + if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL { + p.Mark |= LABEL | SYNC + break + } + if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL { + p.Mark |= LABEL | SYNC } - case ALWAR, - ASTWCCC, - AECIWX, - AECOWX, - AEIEIO, - AICBI, - AISYNC, - ATLBIE, - ATLBIEL, - ASLBIA, - ASLBIE, - ASLBMFEE, - ASLBMFEV, - ASLBMTE, - ADCBF, - ADCBI, - ADCBST, - ADCBT, - ADCBTST, - ADCBZ, - ASYNC, - ATLBSYNC, - APTESYNC, - ATW, + /* too hard, just leave alone */ + case ASYSCALL, AWORD, - ARFI, - ARFCI, - ARFID, - AHRFID: + ATLBWR, + ATLBWI, + ATLBP, + ATLBR: q = p p.Mark |= LABEL | SYNC - continue - case AMOVW, AMOVWZ, AMOVD: + case ANOR: q = p - if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL { - p.Mark |= LABEL | SYNC + if p.To.Type == obj.TYPE_REG { + if p.To.Reg == REGZERO { + p.Mark |= LABEL | SYNC + } } - continue - - case AFABS, - AFABSCC, - AFADD, - AFADDCC, - AFCTIW, - AFCTIWCC, - AFCTIWZ, - AFCTIWZCC, - AFDIV, - AFDIVCC, - AFMADD, - AFMADDCC, - AFMOVD, - AFMOVDU, - /* case AFMOVDS: */ - AFMOVS, - AFMOVSU, - - /* case AFMOVSD: */ - AFMSUB, - AFMSUBCC, - AFMUL, - AFMULCC, - AFNABS, - AFNABSCC, - AFNEG, - AFNEGCC, - AFNMADD, - AFNMADDCC, - AFNMSUB, - AFNMSUBCC, - AFRSP, - AFRSPCC, - AFSUB, - AFSUBCC: - q = p - p.Mark |= FLOAT - continue - - case ABL, - ABCL, + case ABGEZAL, + ABLTZAL, + AJAL, obj.ADUFFZERO, obj.ADUFFCOPY: cursym.Text.Mark &^= LEAF fallthrough - case ABC, + case AJMP, ABEQ, - ABGE, - ABGT, - ABLE, - ABLT, + ABGEZ, + ABGTZ, + ABLEZ, + ABLTZ, ABNE, - ABR, - ABVC, - ABVS: - p.Mark |= BRANCH + ABFPT, ABFPF: + if p.As == ABFPT || p.As == ABFPF { + // We don't treat ABFPT and ABFPF as branches here, + // so that we will always fill nop (0x0) in their + // delay slot during assembly. + // This is to workaround a kernel FPU emulator bug + // where it uses the user stack to simulate the + // instruction in the delay slot if it's not 0x0, + // and somehow that leads to SIGSEGV when the kernel + // jump to the stack. + p.Mark |= SYNC + } else { + p.Mark |= BRANCH + } q = p q1 = p.Pcond if q1 != nil { @@ -269,21 +231,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { if q1.Mark&LEAF == 0 { q1.Mark |= LABEL } - } else { - p.Mark |= LABEL } + //else { + // p.Mark |= LABEL + //} q1 = p.Link if q1 != nil { q1.Mark |= LABEL } continue - case AFCMPO, AFCMPU: - q = p - p.Mark |= FCMP | FLOAT - continue - - case obj.ARET: + case ARET: q = p if p.Link != nil { p.Link.Mark |= LABEL @@ -303,8 +261,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { } autosize := int32(0) - var aoffset int - var mov int var o int var p1 *obj.Prog var p2 *obj.Prog @@ -312,8 +268,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { o = int(p.As) switch o { case obj.ATEXT: - mov = AMOVD - aoffset = 0 autosize = int32(textstksiz + 8) if (p.Mark&LEAF != 0) && autosize <= 8 { autosize = 0 @@ -329,27 +283,23 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { q = p if autosize != 0 { - /* use MOVDU to adjust R1 when saving R31, if autosize is small */ - if cursym.Text.Mark&LEAF == 0 && autosize >= -BIG && autosize <= BIG { - mov = AMOVDU - aoffset = int(-autosize) - } else { - q = obj.Appendp(ctxt, p) - q.As = AADD - q.Lineno = p.Lineno - q.From.Type = obj.TYPE_CONST - q.From.Offset = int64(-autosize) - q.To.Type = obj.TYPE_REG - q.To.Reg = REGSP - q.Spadj = +autosize - } + q = obj.Appendp(ctxt, p) + q.As = AADDV + q.Lineno = p.Lineno + q.From.Type = obj.TYPE_CONST + q.From.Offset = int64(-autosize) + q.To.Type = obj.TYPE_REG + q.To.Reg = REGSP + q.Spadj = +autosize } else if cursym.Text.Mark&LEAF == 0 { - if ctxt.Debugvlog != 0 { - fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name) - ctxt.Bso.Flush() - } + if cursym.Text.From3.Offset&obj.NOSPLIT != 0 { + if ctxt.Debugvlog != 0 { + fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name) + ctxt.Bso.Flush() + } - cursym.Text.Mark |= LEAF + cursym.Text.Mark |= LEAF + } } if cursym.Text.Mark&LEAF != 0 { @@ -358,106 +308,86 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { } q = obj.Appendp(ctxt, q) - q.As = AMOVD - q.Lineno = p.Lineno - q.From.Type = obj.TYPE_REG - q.From.Reg = REG_LR - q.To.Type = obj.TYPE_REG - q.To.Reg = REGTMP - - q = obj.Appendp(ctxt, q) - q.As = int16(mov) + q.As = AMOVV q.Lineno = p.Lineno q.From.Type = obj.TYPE_REG - q.From.Reg = REGTMP + q.From.Reg = REGLINK q.To.Type = obj.TYPE_MEM - q.To.Offset = int64(aoffset) + q.To.Offset = int64(0) q.To.Reg = REGSP - if q.As == AMOVDU { - q.Spadj = int32(-aoffset) - } if cursym.Text.From3.Offset&obj.WRAPPER != 0 { // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame // - // MOVD g_panic(g), R3 - // CMP R0, R3 - // BEQ end - // MOVD panic_argp(R3), R4 - // ADD $(autosize+8), R1, R5 - // CMP R4, R5 - // BNE end - // ADD $8, R1, R6 - // MOVD R6, panic_argp(R3) + // MOVV g_panic(g), R1 + // BEQ R1, end + // MOVV panic_argp(R1), R2 + // ADDV $(autosize+8), R29, R3 + // BNE R2, R3, end + // ADDV $8, R29, R2 + // MOVV R2, panic_argp(R1) // end: // NOP // // The NOP is needed to give the jumps somewhere to land. - // It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes. + // It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes. q = obj.Appendp(ctxt, q) - q.As = AMOVD + q.As = AMOVV q.From.Type = obj.TYPE_MEM q.From.Reg = REGG q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R3 - - q = obj.Appendp(ctxt, q) - q.As = ACMP - q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R0 - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R3 + q.To.Reg = REG_R1 q = obj.Appendp(ctxt, q) q.As = ABEQ + q.From.Type = obj.TYPE_REG + q.From.Reg = REG_R1 q.To.Type = obj.TYPE_BRANCH + q.Mark |= BRANCH p1 = q q = obj.Appendp(ctxt, q) - q.As = AMOVD + q.As = AMOVV q.From.Type = obj.TYPE_MEM - q.From.Reg = REG_R3 + q.From.Reg = REG_R1 q.From.Offset = 0 // Panic.argp q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R4 + q.To.Reg = REG_R2 q = obj.Appendp(ctxt, q) - q.As = AADD + q.As = AADDV q.From.Type = obj.TYPE_CONST q.From.Offset = int64(autosize) + 8 q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R5 - - q = obj.Appendp(ctxt, q) - q.As = ACMP - q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R4 - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R5 + q.To.Reg = REG_R3 q = obj.Appendp(ctxt, q) q.As = ABNE + q.From.Type = obj.TYPE_REG + q.From.Reg = REG_R2 + q.Reg = REG_R3 q.To.Type = obj.TYPE_BRANCH + q.Mark |= BRANCH p2 = q q = obj.Appendp(ctxt, q) - q.As = AADD + q.As = AADDV q.From.Type = obj.TYPE_CONST q.From.Offset = 8 q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R6 + q.To.Reg = REG_R2 q = obj.Appendp(ctxt, q) - q.As = AMOVD + q.As = AMOVV q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R6 + q.From.Reg = REG_R2 q.To.Type = obj.TYPE_MEM - q.To.Reg = REG_R3 + q.To.Reg = REG_R1 q.To.Offset = 0 // Panic.argp q = obj.Appendp(ctxt, q) @@ -467,29 +397,30 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { p2.Pcond = q } - case obj.ARET: + case ARET: if p.From.Type == obj.TYPE_CONST { ctxt.Diag("using BECOME (%v) is not supported!", p) break } if p.To.Sym != nil { // retjmp - p.As = ABR + p.As = AJMP p.To.Type = obj.TYPE_BRANCH break } if cursym.Text.Mark&LEAF != 0 { if autosize == 0 { - p.As = ABR + p.As = AJMP p.From = obj.Addr{} - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_LR + p.To.Type = obj.TYPE_MEM + p.To.Offset = 0 + p.To.Reg = REGLINK p.Mark |= BRANCH break } - p.As = AADD + p.As = AADDV p.From.Type = obj.TYPE_CONST p.From.Offset = int64(autosize) p.To.Type = obj.TYPE_REG @@ -497,10 +428,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { p.Spadj = -autosize q = ctxt.NewProg() - q.As = ABR + q.As = AJMP q.Lineno = p.Lineno - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_LR + q.To.Type = obj.TYPE_MEM + q.To.Offset = 0 + q.To.Reg = REGLINK q.Mark |= BRANCH q.Spadj = +autosize @@ -509,34 +441,22 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { break } - p.As = AMOVD + p.As = AMOVV p.From.Type = obj.TYPE_MEM p.From.Offset = 0 p.From.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REGTMP - - q = ctxt.NewProg() - q.As = AMOVD - q.Lineno = p.Lineno - q.From.Type = obj.TYPE_REG - q.From.Reg = REGTMP - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_LR - - q.Link = p.Link - p.Link = q - p = q + p.To.Reg = REG_R4 if false { // Debug bad returns q = ctxt.NewProg() - q.As = AMOVD + q.As = AMOVV q.Lineno = p.Lineno q.From.Type = obj.TYPE_MEM q.From.Offset = 0 - q.From.Reg = REGTMP + q.From.Reg = REG_R4 q.To.Type = obj.TYPE_REG q.To.Reg = REGTMP @@ -547,7 +467,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { if autosize != 0 { q = ctxt.NewProg() - q.As = AADD + q.As = AADDV q.Lineno = p.Lineno q.From.Type = obj.TYPE_CONST q.From.Offset = int64(autosize) @@ -560,74 +480,84 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { } q1 = ctxt.NewProg() - q1.As = ABR + q1.As = AJMP q1.Lineno = p.Lineno - q1.To.Type = obj.TYPE_REG - q1.To.Reg = REG_LR + q1.To.Type = obj.TYPE_MEM + q1.To.Offset = 0 + q1.To.Reg = REG_R4 q1.Mark |= BRANCH q1.Spadj = +autosize q1.Link = q.Link q.Link = q1 - case AADD: + case AADDV, + AADDVU: if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST { p.Spadj = int32(-p.From.Offset) } } } + + if nosched { + // if we don't do instruction scheduling, simply add + // NOP after each branch instruction. + for p = cursym.Text; p != nil; p = p.Link { + if p.Mark&BRANCH != 0 { + addnop(ctxt, p) + } + } + return + } + + // instruction scheduling + q = nil // p - 1 + q1 = cursym.Text // top of block + o = 0 // count of instructions + for p = cursym.Text; p != nil; p = p1 { + p1 = p.Link + o++ + if p.Mark&NOSCHED != 0 { + if q1 != p { + sched(ctxt, q1, q) + } + for ; p != nil; p = p.Link { + if p.Mark&NOSCHED == 0 { + break + } + q = p + } + p1 = p + q1 = p + o = 0 + continue + } + if p.Mark&(LABEL|SYNC) != 0 { + if q1 != p { + sched(ctxt, q1, q) + } + q1 = p + o = 1 + } + if p.Mark&(BRANCH|SYNC) != 0 { + sched(ctxt, q1, p) + q1 = p1 + o = 0 + } + if o >= NSCHED { + sched(ctxt, q1, p) + q1 = p1 + o = 0 + } + q = p + } } -/* -// instruction scheduling - if(debug['Q'] == 0) - return; - - curtext = nil; - q = nil; // p - 1 - q1 = firstp; // top of block - o = 0; // count of instructions - for(p = firstp; p != nil; p = p1) { - p1 = p->link; - o++; - if(p->mark & NOSCHED){ - if(q1 != p){ - sched(q1, q); - } - for(; p != nil; p = p->link){ - if(!(p->mark & NOSCHED)) - break; - q = p; - } - p1 = p; - q1 = p; - o = 0; - continue; - } - if(p->mark & (LABEL|SYNC)) { - if(q1 != p) - sched(q1, q); - q1 = p; - o = 1; - } - if(p->mark & (BRANCH|SYNC)) { - sched(q1, p); - q1 = p1; - o = 0; - } - if(o >= NSCHED) { - sched(q1, p); - q1 = p1; - o = 0; - } - q = p; - } -*/ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { - // MOVD g_stackguard(g), R3 + // MOVV g_stackguard(g), R1 p = obj.Appendp(ctxt, p) - p.As = AMOVD + p.As = AMOVV p.From.Type = obj.TYPE_MEM p.From.Reg = REGG p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0 @@ -635,38 +565,40 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1 } p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R3 + p.To.Reg = REG_R1 var q *obj.Prog if framesize <= obj.StackSmall { // small stack: SP < stackguard - // CMP stackguard, SP + // AGTU SP, stackguard, R1 p = obj.Appendp(ctxt, p) - p.As = ACMPU + p.As = ASGTU p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 + p.From.Reg = REGSP + p.Reg = REG_R1 p.To.Type = obj.TYPE_REG - p.To.Reg = REGSP + p.To.Reg = REG_R1 } else if framesize <= obj.StackBig { // large stack: SP-framesize < stackguard-StackSmall - // ADD $-framesize, SP, R4 - // CMP stackguard, R4 + // ADDV $-framesize, SP, R2 + // SGTU R2, stackguard, R1 p = obj.Appendp(ctxt, p) - p.As = AADD + p.As = AADDV p.From.Type = obj.TYPE_CONST p.From.Offset = int64(-framesize) p.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R2 p = obj.Appendp(ctxt, p) - p.As = ACMPU + p.As = ASGTU p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 + p.From.Reg = REG_R2 + p.Reg = REG_R1 p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R1 } else { // Such a large stack we need to protect against wraparound. // If SP is close to zero: @@ -676,79 +608,88 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { // // Preemption sets stackguard to StackPreempt, a very large value. // That breaks the math above, so we have to check for that explicitly. - // // stackguard is R3 - // CMP R3, $StackPreempt - // BEQ label-of-call-to-morestack - // ADD $StackGuard, SP, R4 - // SUB R3, R4 - // MOVD $(framesize+(StackGuard-StackSmall)), R31 - // CMPU R31, R4 + // // stackguard is R1 + // MOVV $StackPreempt, R2 + // BEQ R1, R2, label-of-call-to-morestack + // ADDV $StackGuard, SP, R2 + // SUBVU R1, R2 + // MOVV $(framesize+(StackGuard-StackSmall)), R1 + // SGTU R2, R1, R1 p = obj.Appendp(ctxt, p) - p.As = ACMP - p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 - p.To.Type = obj.TYPE_CONST - p.To.Offset = obj.StackPreempt + p.As = AMOVV + p.From.Type = obj.TYPE_CONST + p.From.Offset = obj.StackPreempt + p.To.Type = obj.TYPE_REG + p.To.Reg = REG_R2 p = obj.Appendp(ctxt, p) q = p p.As = ABEQ + p.From.Type = obj.TYPE_REG + p.From.Reg = REG_R1 + p.Reg = REG_R2 p.To.Type = obj.TYPE_BRANCH + p.Mark |= BRANCH p = obj.Appendp(ctxt, p) - p.As = AADD + p.As = AADDV p.From.Type = obj.TYPE_CONST p.From.Offset = obj.StackGuard p.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R2 p = obj.Appendp(ctxt, p) - p.As = ASUB + p.As = ASUBVU p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 + p.From.Reg = REG_R1 p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R2 p = obj.Appendp(ctxt, p) - p.As = AMOVD + p.As = AMOVV p.From.Type = obj.TYPE_CONST p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall p.To.Type = obj.TYPE_REG - p.To.Reg = REGTMP + p.To.Reg = REG_R1 p = obj.Appendp(ctxt, p) - p.As = ACMPU + p.As = ASGTU p.From.Type = obj.TYPE_REG - p.From.Reg = REGTMP + p.From.Reg = REG_R2 + p.Reg = REG_R1 p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R1 } - // q1: BLT done + // q1: BNE R1, done p = obj.Appendp(ctxt, p) q1 := p - p.As = ABLT + p.As = ABNE + p.From.Type = obj.TYPE_REG + p.From.Reg = REG_R1 p.To.Type = obj.TYPE_BRANCH + p.Mark |= BRANCH - // MOVD LR, R5 + // MOVV LINK, R3 p = obj.Appendp(ctxt, p) - p.As = AMOVD + p.As = AMOVV p.From.Type = obj.TYPE_REG - p.From.Reg = REG_LR + p.From.Reg = REGLINK p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R5 + p.To.Reg = REG_R3 if q != nil { q.Pcond = p + p.Mark |= LABEL } - // BL runtime.morestack(SB) + // JAL runtime.morestack(SB) p = obj.Appendp(ctxt, p) - p.As = ABL + p.As = AJAL p.To.Type = obj.TYPE_BRANCH if ctxt.Cursym.Cfunc != 0 { p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0) @@ -757,13 +698,15 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { } else { p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0) } + p.Mark |= BRANCH - // BR start + // JMP start p = obj.Appendp(ctxt, p) - p.As = ABR + p.As = AJMP p.To.Type = obj.TYPE_BRANCH p.Pcond = ctxt.Cursym.Text.Link + p.Mark |= BRANCH // placeholder for q1's jump target p = obj.Appendp(ctxt, p) @@ -774,47 +717,632 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { return p } -func follow(ctxt *obj.Link, s *obj.LSym) { - ctxt.Cursym = s +func addnop(ctxt *obj.Link, p *obj.Prog) { + q := ctxt.NewProg() + // we want to use the canonical NOP (SLL $0,R0,R0) here, + // however, as the assembler will always replace $0 + // as R0, we have to resort to manually encode the SLL + // instruction as WORD $0. + q.As = AWORD + q.Lineno = p.Lineno + q.From.Type = obj.TYPE_CONST + q.From.Name = obj.NAME_NONE + q.From.Offset = 0 + + q.Link = p.Link + p.Link = q +} - firstp := ctxt.NewProg() - lastp := firstp - xfol(ctxt, s.Text, &lastp) - lastp.Link = nil - s.Text = firstp.Link +const ( + E_HILO = 1 << 0 + E_FCR = 1 << 1 + E_MCR = 1 << 2 + E_MEM = 1 << 3 + E_MEMSP = 1 << 4 /* uses offset and size */ + E_MEMSB = 1 << 5 /* uses offset and size */ + ANYMEM = E_MEM | E_MEMSP | E_MEMSB + //DELAY = LOAD|BRANCH|FCMP + DELAY = BRANCH /* only schedule branch */ +) + +type Dep struct { + ireg uint32 + freg uint32 + cc uint32 +} + +type Sch struct { + p obj.Prog + set Dep + used Dep + soffset int32 + size uint8 + nop uint8 + comp bool } -func relinv(a int) int { - switch a { - case ABEQ: - return ABNE - case ABNE: - return ABEQ +func sched(ctxt *obj.Link, p0, pe *obj.Prog) { + var sch [NSCHED]Sch - case ABGE: - return ABLT - case ABLT: - return ABGE + /* + * build side structure + */ + s := sch[:] + for p := p0; ; p = p.Link { + s[0].p = *p + markregused(ctxt, &s[0]) + if p == pe { + break + } + s = s[1:] + } + se := s - case ABGT: - return ABLE - case ABLE: - return ABGT + for i := cap(sch) - cap(se); i >= 0; i-- { + s = sch[i:] + if s[0].p.Mark&DELAY == 0 { + continue + } + if -cap(s) < -cap(se) { + if !conflict(&s[0], &s[1]) { + continue + } + } - case ABVC: - return ABVS - case ABVS: - return ABVC + var t []Sch + var j int + for j = cap(sch) - cap(s) - 1; j >= 0; j-- { + t = sch[j:] + if t[0].comp { + if s[0].p.Mark&BRANCH != 0 { + goto no2 + } + } + if t[0].p.Mark&DELAY != 0 { + if -cap(s) >= -cap(se) || conflict(&t[0], &s[1]) { + goto no2 + } + } + for u := t[1:]; -cap(u) <= -cap(s); u = u[1:] { + if depend(ctxt, &u[0], &t[0]) { + goto no2 + } + } + goto out2 + no2: + } + + if s[0].p.Mark&BRANCH != 0 { + s[0].nop = 1 + } + continue + + out2: + // t[0] is the instruction being moved to fill the delay + stmp := t[0] + copy(t[:i-j], t[1:i-j+1]) + s[0] = stmp + + if t[i-j-1].p.Mark&BRANCH != 0 { + // t[i-j] is being put into a branch delay slot + // combine its Spadj with the branch instruction + t[i-j-1].p.Spadj += t[i-j].p.Spadj + t[i-j].p.Spadj = 0 + } + + i-- + } + + /* + * put it all back + */ + var p *obj.Prog + var q *obj.Prog + for s, p = sch[:], p0; -cap(s) <= -cap(se); s, p = s[1:], q { + q = p.Link + if q != s[0].p.Link { + *p = s[0].p + p.Link = q + } + for s[0].nop != 0 { + s[0].nop-- + addnop(ctxt, p) + } + } +} + +func markregused(ctxt *obj.Link, s *Sch) { + p := &s.p + s.comp = compound(ctxt, p) + s.nop = 0 + if s.comp { + s.set.ireg |= 1 << (REGTMP - REG_R0) + s.used.ireg |= 1 << (REGTMP - REG_R0) + } + + ar := 0 /* dest is really reference */ + ad := 0 /* source/dest is really address */ + ld := 0 /* opcode is load instruction */ + sz := 20 /* size of load/store for overlap computation */ + + /* + * flags based on opcode + */ + switch p.As { + case obj.ATEXT: + ctxt.Autosize = int32(p.To.Offset + 8) + ad = 1 + + case AJAL: + c := p.Reg + if c == 0 { + c = REGLINK + } + s.set.ireg |= 1 << uint(c-REG_R0) + ar = 1 + ad = 1 + + case ABGEZAL, + ABLTZAL: + s.set.ireg |= 1 << (REGLINK - REG_R0) + fallthrough + case ABEQ, + ABGEZ, + ABGTZ, + ABLEZ, + ABLTZ, + ABNE: + ar = 1 + ad = 1 + + case ABFPT, + ABFPF: + ad = 1 + s.used.cc |= E_FCR + + case ACMPEQD, + ACMPEQF, + ACMPGED, + ACMPGEF, + ACMPGTD, + ACMPGTF: + ar = 1 + s.set.cc |= E_FCR + p.Mark |= FCMP + + case AJMP: + ar = 1 + ad = 1 + + case AMOVB, + AMOVBU: + sz = 1 + ld = 1 + + case AMOVH, + AMOVHU: + sz = 2 + ld = 1 + + case AMOVF, + AMOVW, + AMOVWL, + AMOVWR: + sz = 4 + ld = 1 + + case AMOVD, + AMOVV, + AMOVVL, + AMOVVR: + sz = 8 + ld = 1 + + case ADIV, + ADIVU, + AMUL, + AMULU, + AREM, + AREMU, + ADIVV, + ADIVVU, + AMULV, + AMULVU, + AREMV, + AREMVU: + s.set.cc = E_HILO + fallthrough + case AADD, + AADDU, + AADDV, + AADDVU, + AAND, + ANOR, + AOR, + ASGT, + ASGTU, + ASLL, + ASRA, + ASRL, + ASLLV, + ASRAV, + ASRLV, + ASUB, + ASUBU, + ASUBV, + ASUBVU, + AXOR, + + AADDD, + AADDF, + AADDW, + ASUBD, + ASUBF, + ASUBW, + AMULF, + AMULD, + AMULW, + ADIVF, + ADIVD, + ADIVW: + if p.Reg == 0 { + if p.To.Type == obj.TYPE_REG { + p.Reg = p.To.Reg + } + //if(p->reg == NREG) + // print("botch %P\n", p); + } + } + + /* + * flags based on 'to' field + */ + c := int(p.To.Class) + if c == 0 { + c = aclass(ctxt, &p.To) + 1 + p.To.Class = int8(c) + } + c-- + switch c { + default: + fmt.Printf("unknown class %d %v\n", c, p) + + case C_ZCON, + C_SCON, + C_ADD0CON, + C_AND0CON, + C_ADDCON, + C_ANDCON, + C_UCON, + C_LCON, + C_NONE, + C_SBRA, + C_LBRA, + C_ADDR, + C_TEXTSIZE: + break + + case C_HI, + C_LO: + s.set.cc |= E_HILO + + case C_FCREG: + s.set.cc |= E_FCR + + case C_MREG: + s.set.cc |= E_MCR + + case C_ZOREG, + C_SOREG, + C_LOREG: + c = int(p.To.Reg) + s.used.ireg |= 1 << uint(c-REG_R0) + if ad != 0 { + break + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.To) + + m := uint32(ANYMEM) + if c == REGSB { + m = E_MEMSB + } + if c == REGSP { + m = E_MEMSP + } + + if ar != 0 { + s.used.cc |= m + } else { + s.set.cc |= m + } + + case C_SACON, + C_LACON: + s.used.ireg |= 1 << (REGSP - REG_R0) + + case C_SECON, + C_LECON: + s.used.ireg |= 1 << (REGSB - REG_R0) + + case C_REG: + if ar != 0 { + s.used.ireg |= 1 << uint(p.To.Reg-REG_R0) + } else { + s.set.ireg |= 1 << uint(p.To.Reg-REG_R0) + } + + case C_FREG: + if ar != 0 { + s.used.freg |= 1 << uint(p.To.Reg-REG_F0) + } else { + s.set.freg |= 1 << uint(p.To.Reg-REG_F0) + } + if ld != 0 && p.From.Type == obj.TYPE_REG { + p.Mark |= LOAD + } + + case C_SAUTO, + C_LAUTO: + s.used.ireg |= 1 << (REGSP - REG_R0) + if ad != 0 { + break + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.To) + + if ar != 0 { + s.used.cc |= E_MEMSP + } else { + s.set.cc |= E_MEMSP + } + + case C_SEXT, + C_LEXT: + s.used.ireg |= 1 << (REGSB - REG_R0) + if ad != 0 { + break + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.To) + + if ar != 0 { + s.used.cc |= E_MEMSB + } else { + s.set.cc |= E_MEMSB + } + } + + /* + * flags based on 'from' field + */ + c = int(p.From.Class) + if c == 0 { + c = aclass(ctxt, &p.From) + 1 + p.From.Class = int8(c) + } + c-- + switch c { + default: + fmt.Printf("unknown class %d %v\n", c, p) + + case C_ZCON, + C_SCON, + C_ADD0CON, + C_AND0CON, + C_ADDCON, + C_ANDCON, + C_UCON, + C_LCON, + C_NONE, + C_SBRA, + C_LBRA, + C_ADDR, + C_TEXTSIZE: + break + + case C_HI, + C_LO: + s.used.cc |= E_HILO + + case C_FCREG: + s.used.cc |= E_FCR + + case C_MREG: + s.used.cc |= E_MCR + + case C_ZOREG, + C_SOREG, + C_LOREG: + c = int(p.From.Reg) + s.used.ireg |= 1 << uint(c-REG_R0) + if ld != 0 { + p.Mark |= LOAD + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.From) + + m := uint32(ANYMEM) + if c == REGSB { + m = E_MEMSB + } + if c == REGSP { + m = E_MEMSP + } + + s.used.cc |= m + + case C_SACON, + C_LACON: + c = int(p.From.Reg) + if c == 0 { + c = REGSP + } + s.used.ireg |= 1 << uint(c-REG_R0) + + case C_SECON, + C_LECON: + s.used.ireg |= 1 << (REGSB - REG_R0) + + case C_REG: + s.used.ireg |= 1 << uint(p.From.Reg-REG_R0) + + case C_FREG: + s.used.freg |= 1 << uint(p.From.Reg-REG_F0) + if ld != 0 && p.To.Type == obj.TYPE_REG { + p.Mark |= LOAD + } + + case C_SAUTO, + C_LAUTO: + s.used.ireg |= 1 << (REGSP - REG_R0) + if ld != 0 { + p.Mark |= LOAD + } + if ad != 0 { + break + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.From) + + s.used.cc |= E_MEMSP + + case C_SEXT: + case C_LEXT: + s.used.ireg |= 1 << (REGSB - REG_R0) + if ld != 0 { + p.Mark |= LOAD + } + if ad != 0 { + break + } + s.size = uint8(sz) + s.soffset = regoff(ctxt, &p.From) + + s.used.cc |= E_MEMSB + } + + c = int(p.Reg) + if c != 0 { + if REG_F0 <= c && c <= REG_F31 { + s.used.freg |= 1 << uint(c-REG_F0) + } else { + s.used.ireg |= 1 << uint(c-REG_R0) + } + } + s.set.ireg &^= (1 << (REGZERO - REG_R0)) /* R0 cant be set */ +} + +/* + * test to see if 2 instrictions can be + * interchanged without changing semantics + */ +func depend(ctxt *obj.Link, sa, sb *Sch) bool { + if sa.set.ireg&(sb.set.ireg|sb.used.ireg) != 0 { + return true + } + if sb.set.ireg&sa.used.ireg != 0 { + return true + } + + if sa.set.freg&(sb.set.freg|sb.used.freg) != 0 { + return true + } + if sb.set.freg&sa.used.freg != 0 { + return true + } + + /* + * special case. + * loads from same address cannot pass. + * this is for hardware fifo's and the like + */ + if sa.used.cc&sb.used.cc&E_MEM != 0 { + if sa.p.Reg == sb.p.Reg { + if regoff(ctxt, &sa.p.From) == regoff(ctxt, &sb.p.From) { + return true + } + } + } + + x := (sa.set.cc & (sb.set.cc | sb.used.cc)) | (sb.set.cc & sa.used.cc) + if x != 0 { + /* + * allow SB and SP to pass each other. + * allow SB to pass SB iff doffsets are ok + * anything else conflicts + */ + if x != E_MEMSP && x != E_MEMSB { + return true + } + x = sa.set.cc | sb.set.cc | sa.used.cc | sb.used.cc + if x&E_MEM != 0 { + return true + } + if offoverlap(sa, sb) { + return true + } + } + + return false +} + +func offoverlap(sa, sb *Sch) bool { + if sa.soffset < sb.soffset { + if sa.soffset+int32(sa.size) > sb.soffset { + return true + } + return false + } + if sb.soffset+int32(sb.size) > sa.soffset { + return true + } + return false +} + +/* + * test 2 adjacent instructions + * and find out if inserted instructions + * are desired to prevent stalls. + */ +func conflict(sa, sb *Sch) bool { + if sa.set.ireg&sb.used.ireg != 0 { + return true } + if sa.set.freg&sb.used.freg != 0 { + return true + } + if sa.set.cc&sb.used.cc != 0 { + return true + } + return false +} + +func compound(ctxt *obj.Link, p *obj.Prog) bool { + o := oplook(ctxt, p) + if o.size != 4 { + return true + } + if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSB { + return true + } + return false +} + +func follow(ctxt *obj.Link, s *obj.LSym) { + ctxt.Cursym = s - return 0 + firstp := ctxt.NewProg() + lastp := firstp + xfol(ctxt, s.Text, &lastp) + lastp.Link = nil + s.Text = firstp.Link } func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) { var q *obj.Prog var r *obj.Prog var a int - var b int var i int loop: @@ -822,7 +1350,7 @@ loop: return } a = int(p.As) - if a == ABR { + if a == AJMP { q = p.Pcond if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) { p.Mark |= FOLL @@ -853,21 +1381,19 @@ loop: if q == *last || (q.Mark&NOSCHED != 0) { break } - b = 0 /* set */ a = int(q.As) if a == obj.ANOP { i-- continue } - if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID { + if a == AJMP || a == ARET || a == ARFE { goto copy } if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) { continue } - b = relinv(a) - if b == 0 { + if a != ABEQ && a != ABNE { continue } @@ -888,10 +1414,13 @@ loop: (*last).Link = r *last = r - if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID { + if a == AJMP || a == ARET || a == ARFE { return } - r.As = int16(b) + r.As = ABNE + if a == ABNE { + r.As = ABEQ + } r.Pcond = p.Link r.Link = p.Pcond if r.Link.Mark&FOLL == 0 { @@ -904,7 +1433,7 @@ loop: } } - a = ABR + a = AJMP q = ctxt.NewProg() q.As = int16(a) q.Lineno = p.Lineno @@ -917,7 +1446,7 @@ loop: p.Mark |= FOLL (*last).Link = p *last = p - if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID { + if a == AJMP || a == ARET || a == ARFE { if p.Mark&NOSCHED != 0 { p = p.Link goto loop @@ -927,7 +1456,7 @@ loop: } if p.Pcond != nil { - if a != ABL && p.Link != nil { + if a != AJAL && p.Link != nil { xfol(ctxt, p.Link, last) p = p.Pcond if p == nil || (p.Mark&FOLL != 0) { @@ -941,12 +1470,12 @@ loop: goto loop } -var Linkppc64 = obj.LinkArch{ +var Linkmips64 = obj.LinkArch{ ByteOrder: binary.BigEndian, - Name: "ppc64", - Thechar: '9', + Name: "mips64", + Thechar: '0', Preprocess: preprocess, - Assemble: span9, + Assemble: span0, Follow: follow, Progedit: progedit, Minlc: 4, @@ -954,12 +1483,12 @@ var Linkppc64 = obj.LinkArch{ Regsize: 8, } -var Linkppc64le = obj.LinkArch{ +var Linkmips64le = obj.LinkArch{ ByteOrder: binary.LittleEndian, - Name: "ppc64le", - Thechar: '9', + Name: "mips64le", + Thechar: '0', Preprocess: preprocess, - Assemble: span9, + Assemble: span0, Follow: follow, Progedit: progedit, Minlc: 4, diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index e0e873984f..3e29b58dac 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -524,11 +524,12 @@ var regSpace []regSet const ( // Because of masking operations in the encodings, each register // space should start at 0 modulo some power of 2. - RBase386 = 1 * 1024 - RBaseAMD64 = 2 * 1024 - RBaseARM = 3 * 1024 - RBasePPC64 = 4 * 1024 // range [4k, 8k) - RBaseARM64 = 8 * 1024 // range [8k, 12k) + RBase386 = 1 * 1024 + RBaseAMD64 = 2 * 1024 + RBaseARM = 3 * 1024 + RBasePPC64 = 4 * 1024 // range [4k, 8k) + RBaseARM64 = 8 * 1024 // range [8k, 13k) + RBaseMIPS64 = 13 * 1024 // range [13k, 16k) ) // RegisterRegister binds a pretty-printer (Rconv) for register @@ -588,6 +589,7 @@ const ( ABaseAMD64 ABasePPC64 ABaseARM64 + ABaseMIPS64 AMask = 1<<12 - 1 // AND with this to use the opcode as an array index. ) diff --git a/src/cmd/newlink/testdata/autosection.6 b/src/cmd/newlink/testdata/autosection.6 index 90c842792c6186def36e0c3029f75ee91f874f11..702cab6d5a89bde069c1d8fdae50eb60bf63213e 100644 GIT binary patch delta 67 zcmZ3dXK@-VgWy delta 68 zcmZ3%zLI@{oJz7`TC#ybqJmpdrh;Q>x`L6Rf}yFEskxPjp@NZtp{atlq0vM~eL*n> X2EN47lKhgyBnAcs5e~79jq1z*U+EBL diff --git a/src/cmd/newlink/testdata/autoweak.6 b/src/cmd/newlink/testdata/autoweak.6 index c95dd20214f42d3dbc8c2a394ab5e2fc7049724c..5c68cdb61e057fe81e6a62d83abcc409c6ee43fd 100644 GIT binary patch delta 66 zcmZo-Ze*Syr)*%5nrdWWq7YJ=st}x7pkSe3WN2k*Xk}oiU}Ruus-SCNGSNw2P>O+p VFR`>Fza%ks9yJ WfiJPNB)=pviGhJZghOm$BO?Gg2@lr* diff --git a/src/cmd/newlink/testdata/dead.6 b/src/cmd/newlink/testdata/dead.6 index a3ec719808aa235435539a6103b9fc5dab90239e..6f14aa27cf98b95a1804c6d10c70c3ef71d39196 100644 GIT binary patch delta 136 zcmcb}c7bhzoU(yIYO0Zii9$$eszPvTfr5pCk)f5Lp_PH5f{}rtse-P7$wVg;1t|sw zu9U=*L_;P91_2HpAg?5~qQsDafkBP~BsX~#qtwI=*^E+?WfC~F|KC>09e5ussI20 delta 130 zcmcb>c9Cs@oJz7`TC#ybqJmpdrh;Q>x`L6Rf}yFEskxPjp@NZtp{atlq0vM~6In3^ z2CkIEl0-u$1_l8RE+DTYwW7q3fq_AeLu}%t4o0!b(v0!yKxHB+sfj7^V6{M5uv&-^ Ml7`I-8P_uc0MGIrp#T5? diff --git a/src/cmd/newlink/testdata/hello.6 b/src/cmd/newlink/testdata/hello.6 index 6731f525d08f5fd3fd3d302ccef0eb7efc730aa2..825a2a66ffa77c61e778e82c648b496c436ecf3d 100644 GIT binary patch delta 50 zcmaFL_=ItSoU(yIYO0Zii9$$eszPvTfr5pCk)f5Lp_PH5f{}rtse-P7$wVh-MyZKy F@c?Gr4NU+5 delta 51 zcmaFD_>^&ioJz7`TC#ybqJmpdrh;Q>x`L6Rf}yFEskxPjp@NZtp{atlq0vM~XGXD! Gt?>YU#SOmz diff --git a/src/cmd/newlink/testdata/layout.6 b/src/cmd/newlink/testdata/layout.6 index fcfbe1b3ded4daae150d6b3f5cab79720e57144e..7e2a22b163ef10e40ce9e97b5828bc6ff3df9341 100644 GIT binary patch delta 107 zcmeBS?q;4Kr)*%5nrdWWq7YJ=st}x7pkSe3WN2k*Xk}oiU}Ruus-SCNGSSIXM2dky sq$ocnu_Q6RxH6Xk$m5WjIA2r=C@z2`YQO;$;7cklhN`jys=Brf0E0Ige*gdg delta 125 zcmeBX?qQxFr;==#mTX{s9x`L6Rf}yFEskxPjp@NZtp{atlq0vUi_q^I% i3=CXprFqE)3=9lB959|CkS7M`83B1J9AcBB`5FLz`V}Am -- 2.48.1