From e1f8fe8dff31136ec2c3f3ba83fbeee9f2ef4c3b Mon Sep 17 00:00:00 2001 From: Carlos Eduardo Seo Date: Wed, 10 Jan 2018 15:29:50 -0200 Subject: [PATCH] cmd/internal/obj/ppc64: implement full operand support for l*arx instructions The current implementation of l*arx instructions does not accept non-zero offsets in RA nor the EH field. This change adds full functionality to those instructions. Updates #23845 Change-Id: If113f70d11de5f35f8389520b049390dbc40e863 Reviewed-on: https://go-review.googlesource.com/99635 Run-TryBot: Lynn Boger TryBot-Result: Gobot Gobot Reviewed-by: Lynn Boger --- src/cmd/asm/internal/asm/testdata/ppc64.s | 20 +++++++++++ src/cmd/asm/internal/asm/testdata/ppc64enc.s | 14 ++++++++ src/cmd/internal/obj/ppc64/a.out.go | 1 + src/cmd/internal/obj/ppc64/anames.go | 1 + src/cmd/internal/obj/ppc64/asm9.go | 36 +++++++++++++++++--- 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index e34671231f..c6150573fc 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -1199,6 +1199,26 @@ label1: CALL foo(SB) RET foo(SB) +// load-and-reserve +// L*AR (RB)(RA*1),EH,RT produces +// l*arx RT,RA,RB,EH +// +// Extended forms also accepted. Assumes RA=0, EH=0: +// L*AR (RB),RT +// L*AR (RB),EH,RT + LBAR (R4)(R3*1), $1, R5 + LBAR (R4), $0, R5 + LBAR (R3), R5 + LHAR (R4)(R3*1), $1, R5 + LHAR (R4), $0, R5 + LHAR (R3), R5 + LWAR (R4)(R3*1), $1, R5 + LWAR (R4), $0, R5 + LWAR (R3), R5 + LDAR (R4)(R3*1), $1, R5 + LDAR (R4), $0, R5 + LDAR (R3), R5 + // END // // LEND comma // asm doesn't support the trailing comma. diff --git a/src/cmd/asm/internal/asm/testdata/ppc64enc.s b/src/cmd/asm/internal/asm/testdata/ppc64enc.s index f39c0728eb..7ab1a578f8 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64enc.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64enc.s @@ -84,4 +84,18 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 XOR $1234567, R5 // 641f001263ffd6877fe52a78 XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78 + // load-and-reserve + LBAR (R4)(R3*1),$1,R5 // 7ca32069 + LBAR (R4),$0,R5 // 7ca02068 + LBAR (R3),R5 // 7ca01868 + LHAR (R4)(R3*1),$1,R5 // 7ca320e9 + LHAR (R4),$0,R5 // 7ca020e8 + LHAR (R3),R5 // 7ca018e8 + LWAR (R4)(R3*1),$1,R5 // 7ca32029 + LWAR (R4),$0,R5 // 7ca02028 + LWAR (R3),R5 // 7ca01828 + LDAR (R4)(R3*1),$1,R5 // 7ca320a9 + LDAR (R4),$0,R5 // 7ca020a8 + LDAR (R3),R5 // 7ca018a8 + RET diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 16a959d62a..55e544209d 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -519,6 +519,7 @@ const ( AISEL AMOVMW ALBAR + ALHAR ALSW ALWAR ALWSYNC diff --git a/src/cmd/internal/obj/ppc64/anames.go b/src/cmd/internal/obj/ppc64/anames.go index 28bbd4248f..bfbb544d09 100644 --- a/src/cmd/internal/obj/ppc64/anames.go +++ b/src/cmd/internal/obj/ppc64/anames.go @@ -126,6 +126,7 @@ var Anames = []string{ "ISEL", "MOVMW", "LBAR", + "LHAR", "LSW", "LWAR", "LWSYNC", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 11c43ec2e5..92365e9178 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -581,6 +581,8 @@ var optab = []Optab{ {AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0}, {AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0}, {AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0}, + {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0}, + {ALDAR, C_ZOREG, C_NONE, C_ANDCON, C_REG, 45, 4, 0}, {AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0}, {ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0}, {ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0}, @@ -1791,10 +1793,10 @@ func buildop(ctxt *obj.Link) { opset(AFMOVS, r0) opset(AFMOVSU, r0) - case AECIWX: + case ALDAR: opset(ALBAR, r0) + opset(ALHAR, r0) opset(ALWAR, r0) - opset(ALDAR, r0) case ASYSCALL: /* just the op; flow of control */ opset(ARFI, r0) @@ -1861,6 +1863,7 @@ func buildop(ctxt *obj.Link) { AVMSUMUDM, AADDEX, ACMPEQB, + AECIWX, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -1993,6 +1996,11 @@ func AOP_Z23I(op uint32, d uint32, a uint32, b uint32, c uint32) uint32 { return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11 | (c&3)<<7 } +/* X-form, 3-register operands + EH field */ +func AOP_RRRI(op uint32, d uint32, a uint32, b uint32, c uint32) uint32 { + return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11 | (c & 1) +} + func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 { return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11 } @@ -2994,8 +3002,24 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(p.To.Reg)) case 45: /* indexed load */ - o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg)) - + switch p.As { + /* The assembler accepts a 4-operand l*arx instruction. The fourth operand is an Exclusive Access Hint (EH) */ + /* The EH field can be used as a lock acquire/release hint as follows: */ + /* 0 = Atomic Update (fetch-and-operate or similar algorithm) */ + /* 1 = Exclusive Access (lock acquire and release) */ + case ALBAR, ALHAR, ALWAR, ALDAR: + if p.From3Type() != obj.TYPE_NONE { + eh := int(c.regoff(p.GetFrom3())) + if eh > 1 { + c.ctxt.Diag("illegal EH field\n%v", p) + } + o1 = AOP_RRRI(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg), uint32(eh)) + } else { + o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg)) + } + default: + o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg)) + } case 46: /* plain op */ o1 = c.oprrr(p.As) @@ -4765,10 +4789,12 @@ func (c *ctxt9) oploadx(a obj.As) uint32 { return OPVCC(31, 310, 0, 0) /* eciwx */ case ALBAR: return OPVCC(31, 52, 0, 0) /* lbarx */ + case ALHAR: + return OPVCC(31, 116, 0, 0) /* lharx */ case ALWAR: return OPVCC(31, 20, 0, 0) /* lwarx */ case ALDAR: - return OPVCC(31, 84, 0, 0) + return OPVCC(31, 84, 0, 0) /* ldarx */ case ALSW: return OPVCC(31, 533, 0, 0) /* lswx */ case AMOVD: