From aa1c6f56398882fea0969396666004d6ea7ddd57 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Thu, 26 Aug 2021 17:14:12 -0500 Subject: [PATCH] cmd/internal/obj/ppc64: fix mtocrf, cleanup other CR ops Fix "MOVW CRx, Rx" and "MOVFL Rx, constant", The FXM field was not encoded correctly. Generate mtocrf instead of mtcrf when a CRx argument is used. This form is much faster. Simplify several conditional statements which test if the register argument is REG_CR or one of REG_CRx if the tested argument is known to be matched as C_CREG. Likewise, a4 is (the From3 arg) is always TYPE_NONE in the existing optab entries for type_ 69. Change-Id: I3a4749b1cbfdfab6a2616586ae59e932e01dae50 Reviewed-on: https://go-review.googlesource.com/c/go/+/352789 Reviewed-by: Cherry Mui Reviewed-by: Lynn Boger --- src/cmd/asm/internal/asm/testdata/ppc64.s | 13 +++++++ src/cmd/internal/obj/ppc64/asm9.go | 43 +++++++++++------------ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index 28ceb621cb..b9da48acdd 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -751,4 +751,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 MOVD XER, R3 // 7c6102a6 MOVFL CR3, CR1 // 4c8c0000 + MOVW CR0, R1 // 7c380026 + MOVW CR7, R1 // 7c301026 + MOVW CR, R1 // 7c200026 + + MOVW R1, CR // 7c2ff120 + MOVFL R1, CR // 7c2ff120 + MOVW R1, CR2 // 7c320120 + MOVFL R1, CR2 // 7c320120 + MOVFL R1, $255 // 7c2ff120 + MOVFL R1, $1 // 7c301120 + MOVFL R1, $128 // 7c380120 + MOVFL R1, $3 // 7c203120 + RET diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index ff94fa72c7..0901d64792 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -36,6 +36,7 @@ import ( "fmt" "log" "math" + "math/bits" "sort" ) @@ -3353,32 +3354,30 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { 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 { - c.ctxt.Diag("illegal CR field number\n%v", p) + if p.From.Reg == REG_CR || p.To.Reg == REG_CR { + c.ctxt.Diag("CR argument must be a conditional register field (CR0-CR7)\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 { - c.ctxt.Diag("can't use both mask and CR(n)\n%v", p) - } - v = c.regoff(p.GetFrom3()) & 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_MFCR, uint32(p.To.Reg), 0, 0) /* form, whole register */ + if p.From.Reg != REG_CR { + v := uint32(1) << uint(7-(p.From.Reg&7)) /* CR(n) */ + o1 |= 1<<20 | v<<12 /* new form, mfocrf */ + } + + case 69: /* mtcrf CRM,rS, mtocrf CRx,rS */ + var v uint32 + if p.To.Reg == REG_CR { + v = 0xff + } else if p.To.Offset != 0 { // MOVFL gpr, constant + v = uint32(p.To.Offset) + } else { // p.To.Reg == REG_CRx + v = 1 << uint(7-(p.To.Reg&7)) + } + // Use mtocrf form if only one CR field moved. + if bits.OnesCount32(v) == 1 { + v |= 1 << 8 } o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12 -- 2.50.0