From ba0bab7b4fda1498f2ace58b9d38f0fb8c748f53 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 26 Oct 2019 22:48:15 -0400 Subject: [PATCH] cmd/internal/obj/mips: fix encoding of FCR registers The asm encoder generally assumes that the lowest 5 bits of the REG_XX constants match the machine instruction encoding, i.e. the lowest 5 bits is the register number. This was not true for FCR registers and M registers. Make it so. MOV Rx, FCRy was encoded as two machine instructions. The first is unnecessary. Remove. Change-Id: Ib988e6b109ba8f564337cdd31019c1a6f1881f5b Reviewed-on: https://go-review.googlesource.com/c/go/+/203717 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/cmd/asm/internal/asm/testdata/mips64.s | 13 ++++---- src/cmd/internal/obj/mips/a.out.go | 35 +++++++++++++++++----- src/cmd/internal/obj/mips/asm0.go | 7 ++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/mips64.s b/src/cmd/asm/internal/asm/testdata/mips64.s index 2d1bc18cec..e80f4d83d1 100644 --- a/src/cmd/asm/internal/asm/testdata/mips64.s +++ b/src/cmd/asm/internal/asm/testdata/mips64.s @@ -130,27 +130,27 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0 // { // outcode(int($1), &$2, 0, &$4); // } - MOVW FCR0, R1 + MOVW FCR31, R1 // 4441f800 // LMOVW freg ',' fpscr // { // outcode(int($1), &$2, 0, &$4); // } - MOVW R1, FCR0 + MOVW R1, FCR31 // 44c1f800 // LMOVW rreg ',' mreg // { // outcode(int($1), &$2, 0, &$4); // } - MOVW R1, M1 - MOVV R1, M1 + MOVW R1, M1 // 40810800 + MOVV R1, M1 // 40a10800 // LMOVW mreg ',' rreg // { // outcode(int($1), &$2, 0, &$4); // } - MOVW M1, R1 - MOVV M1, R1 + MOVW M1, R1 // 40010800 + MOVV M1, R1 // 40210800 // @@ -406,6 +406,7 @@ label4: NEGW R1, R2 // 00011023 NEGV R1, R2 // 0001102f + RET // END // diff --git a/src/cmd/internal/obj/mips/a.out.go b/src/cmd/internal/obj/mips/a.out.go index 026e8db76a..b0205ec11a 100644 --- a/src/cmd/internal/obj/mips/a.out.go +++ b/src/cmd/internal/obj/mips/a.out.go @@ -46,7 +46,7 @@ const ( ) const ( - REG_R0 = obj.RBaseMIPS + iota + REG_R0 = obj.RBaseMIPS + iota // must be a multiple of 32 REG_R1 REG_R2 REG_R3 @@ -79,7 +79,7 @@ const ( REG_R30 REG_R31 - REG_F0 + REG_F0 // must be a multiple of 32 REG_F1 REG_F2 REG_F3 @@ -112,11 +112,8 @@ const ( REG_F30 REG_F31 - REG_HI - REG_LO - // co-processor 0 control registers - REG_M0 + REG_M0 // must be a multiple of 32 REG_M1 REG_M2 REG_M3 @@ -150,7 +147,7 @@ const ( REG_M31 // FPU control registers - REG_FCR0 + REG_FCR0 // must be a multiple of 32 REG_FCR1 REG_FCR2 REG_FCR3 @@ -183,7 +180,10 @@ const ( REG_FCR30 REG_FCR31 - REG_LAST = REG_FCR31 // the last defined register + REG_HI + REG_LO + + REG_LAST = REG_LO // the last defined register REG_SPECIAL = REG_M0 @@ -412,3 +412,22 @@ const ( AJAL = obj.ACALL ARET = obj.ARET ) + +func init() { + // The asm encoder generally assumes that the lowest 5 bits of the + // REG_XX constants match the machine instruction encoding, i.e. + // the lowest 5 bits is the register number. + // Check this here. + if REG_R0%32 != 0 { + panic("REG_R0 is not a multiple of 32") + } + if REG_F0%32 != 0 { + panic("REG_F0 is not a multiple of 32") + } + if REG_M0%32 != 0 { + panic("REG_M0 is not a multiple of 32") + } + if REG_FCR0%32 != 0 { + panic("REG_FCR0 is not a multiple of 32") + } +} diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 77aa24a4f6..76a3eec6bf 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -362,8 +362,8 @@ var optab = []Optab{ {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0}, - {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0, 0}, - {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0, sys.MIPS64}, + {AMOVW, C_REG, C_NONE, C_FCREG, 41, 4, 0, 0}, + {AMOVV, C_REG, C_NONE, C_FCREG, 41, 4, 0, sys.MIPS64}, {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0}, {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, sys.MIPS64}, @@ -1476,8 +1476,7 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 = uint32(c.regoff(&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 */ + o1 = 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 */