aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/asm
diff options
context:
space:
mode:
authorPaul E. Murphy <murp@ibm.com>2021-10-21 15:25:14 -0500
committerPaul Murphy <murp@ibm.com>2022-05-06 17:56:02 +0000
commit4a5711c3cf944b3ff51af261166ef34b2ed22b8a (patch)
tree37737fd61ccf588e0b164cd3a985e065983279a8 /src/cmd/asm
parent091e913414794d9176861b1ffcdbcfdc2d742af3 (diff)
downloadgo-4a5711c3cf944b3ff51af261166ef34b2ed22b8a.tar.xz
cmd/compile,cmd/asm: fix ppc64 usage of BI argument of BC opcode
Avoid coercing the CR bit into a GPR register type argument, and move the existing usage to CRx_y register types. And, update the compiler usage to this. This transformation is done internally, so it should not alter existing assembly code. Likewise, add assembly tests for all optab entries of BC/BR. This found some cases which were not possible to realize with handwritten asm, or assemble to something very unexpected if generated by the compiler. The following optab entries are removed, and the cases simplified or removed: {as: ABR, a3: C_SCON, a6: C_LR, type_: 18, size: 4} This existed only to pass the BH hint to JMP (LR) from compiler generated code. It cannot be matched with asm. Instead, add and support 4-operand form "BC{,L} $BO, $BI, $BH, (LR)". {as: ABR, a1: C_REG, a6: C_CTR, type_: 18, size: 4} Could be used like "BR R1, (CTR)", but always compiles to bctr irrespective of arg 1. Any usage should be rewritten as "JMP (CTR)", or rewritten if this was not the intended behavior. {as: ABR, a6: C_ZOREG, type_: 15, size: 8}: {as: ABC, a6: C_ZOREG, type_: 15, size: 8}, Not reachable: 0(reg) is coerced to reg in assembler frontend. {as: ABC, a2: C_REG, a6: C_LR, type_: 18, size: 4} {as: ABC, a2: C_REG, a6: C_CTR, type_: 18, size: 4} Only usable from the compiler. However, the compiler does not generate this form today. Without a BO operand (usually in a1), it is not clear what this should assemble to. Change-Id: I1b5151f884a5877e4a610e6fd41261e8e64c5454 Reviewed-on: https://go-review.googlesource.com/c/go/+/357775 Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> Run-TryBot: Paul Murphy <murp@ibm.com> Reviewed-by: Than McIntosh <thanm@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/asm')
-rw-r--r--src/cmd/asm/internal/asm/asm.go49
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.s61
2 files changed, 87 insertions, 23 deletions
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index d0cb6328f1..3afbec8b92 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -14,6 +14,7 @@ import (
"cmd/asm/internal/flags"
"cmd/asm/internal/lex"
"cmd/internal/obj"
+ "cmd/internal/obj/ppc64"
"cmd/internal/obj/x86"
"cmd/internal/objabi"
"cmd/internal/sys"
@@ -410,19 +411,45 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
case 3:
if p.arch.Family == sys.PPC64 {
// Special 3-operand jumps.
- // First two must be constants; a[1] is a register number.
+ // a[1] is a register number expressed as a constant or register value
target = &a[2]
- prog.From = obj.Addr{
- Type: obj.TYPE_CONST,
- Offset: p.getConstant(prog, op, &a[0]),
+ prog.From = a[0]
+ if a[0].Type != obj.TYPE_CONST {
+ // Legacy code may use a plain constant, accept it, and coerce
+ // into a constant. E.g:
+ // BC 4,...
+ // into
+ // BC $4,...
+ prog.From = obj.Addr{
+ Type: obj.TYPE_CONST,
+ Offset: p.getConstant(prog, op, &a[0]),
+ }
+
}
- reg := int16(p.getConstant(prog, op, &a[1]))
- reg, ok := p.arch.RegisterNumber("R", reg)
- if !ok {
- p.errorf("bad register number %d", reg)
- return
+
+ // Likewise, fixup usage like:
+ // BC x,LT,...
+ // BC x,foo+2,...
+ // BC x,4
+ // BC x,$5
+ // into
+ // BC x,CR0LT,...
+ // BC x,CR0EQ,...
+ // BC x,CR1LT,...
+ // BC x,CR1GT,...
+ // The first and second case demonstrate a symbol name which is
+ // effectively discarded. In these cases, the offset determines
+ // the CR bit.
+ prog.Reg = a[1].Reg
+ if a[1].Type != obj.TYPE_REG {
+ // The CR bit is represented as a constant 0-31. Convert it to a Reg.
+ c := p.getConstant(prog, op, &a[1])
+ reg, success := ppc64.ConstantToCRbit(c)
+ if !success {
+ p.errorf("invalid CR bit register number %d", c)
+ }
+ prog.Reg = reg
}
- prog.Reg = reg
break
}
if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 || p.arch.Family == sys.RISCV64 {
@@ -461,7 +488,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
p.errorf("wrong number of arguments to %s instruction", op)
return
case 4:
- if p.arch.Family == sys.S390X {
+ if p.arch.Family == sys.S390X || p.arch.Family == sys.PPC64 {
// 4-operand compare-and-branch.
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
index 8663963c64..03d0a9f38d 100644
--- a/src/cmd/asm/internal/asm/testdata/ppc64.s
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -24,7 +24,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVW $-32767, R5 // 38a08001
MOVW $-32768, R6 // 38c08000
MOVW $1234567, R5 // 6405001260a5d687
- MOVD 8(R3), R4 // e8830008
+ MOVD 8(R3), R4 // e8830008
MOVD (R3)(R4), R5 // 7ca4182a
MOVW 4(R3), R4 // e8830006
MOVW (R3)(R4), R5 // 7ca41aaa
@@ -41,7 +41,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVDBR (R3)(R4), R5 // 7ca41c28
MOVWBR (R3)(R4), R5 // 7ca41c2c
MOVHBR (R3)(R4), R5 // 7ca41e2c
- MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc20
+ MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc40
MOVD $foo(SB), R5 // 3ca0000038a50000
MOVDU 8(R3), R4 // e8830009
@@ -79,14 +79,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVBU R4, 1(R3) // 9c830001
MOVBU R5, (R3)(R4) // 7ca419ee
- MOVB $0, R4 // 38800000
- MOVBZ $0, R4 // 38800000
- MOVH $0, R4 // 38800000
- MOVHZ $0, R4 // 38800000
- MOVW $0, R4 // 38800000
- MOVWZ $0, R4 // 38800000
- MOVD $0, R4 // 38800000
- MOVD $0, R0 // 38000000
+ MOVB $0, R4 // 38800000
+ MOVBZ $0, R4 // 38800000
+ MOVH $0, R4 // 38800000
+ MOVHZ $0, R4 // 38800000
+ MOVW $0, R4 // 38800000
+ MOVWZ $0, R4 // 38800000
+ MOVD $0, R4 // 38800000
+ MOVD $0, R0 // 38000000
ADD $1, R3 // 38630001
ADD $1, R3, R4 // 38830001
@@ -772,9 +772,46 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVFL R1, $3 // 7c203120
// Verify supported bdnz/bdz encodings.
- BC 16,0,0(PC) // BC $16,R0,0(PC) // 42000000
+ BC 16,0,0(PC) // BC $16, CR0LT, 0(PC) // 42000000
BDNZ 0(PC) // 42000000
BDZ 0(PC) // 42400000
- BC 18,0,0(PC) // BC $18,R0,0(PC) // 42400000
+ BC 18,0,0(PC) // BC $18, CR0LT, 0(PC) // 42400000
+
+ // Verify the supported forms of bcclr[l]
+ BC $20,CR0LT,$1,LR // 4e800820
+ BC $20,CR0LT,$0,LR // 4e800020
+ BC $20,CR0LT,LR // 4e800020
+ BC $20,CR0GT,LR // 4e810020
+ BC 20,CR0LT,LR // BC $20,CR0LT,LR // 4e800020
+ BC 20,undefined_symbol,LR // BC $20,CR0LT,LR // 4e800020
+ BC 20,undefined_symbol+1,LR // BC $20,CR0GT,LR // 4e810020
+ JMP LR // 4e800020
+ BR LR // JMP LR // 4e800020
+ BCL $20,CR0LT,$1,LR // 4e800821
+ BCL $20,CR0LT,$0,LR // 4e800021
+ BCL $20,CR0LT,LR // 4e800021
+ BCL $20,CR0GT,LR // 4e810021
+ BCL 20,CR0LT,LR // BCL $20,CR0LT,LR // 4e800021
+ BCL 20,undefined_symbol,LR // BCL $20,CR0LT,LR // 4e800021
+ BCL 20,undefined_symbol+1,LR // BCL $20,CR0GT,LR // 4e810021
+
+ // Verify the supported forms of bcctr[l]
+ BC $20,CR0LT,CTR // 4e800420
+ BC $20,CR0GT,CTR // 4e810420
+ BC 20,CR0LT,CTR // BC $20,CR0LT,CTR // 4e800420
+ BC 20,undefined_symbol,CTR // BC $20,CR0LT,CTR // 4e800420
+ BC 20,undefined_symbol+1,CTR // BC $20,CR0GT,CTR // 4e810420
+ JMP CTR // 4e800420
+ BR CTR // JMP CTR // 4e800420
+ BCL $20,CR0LT,CTR // 4e800421
+ BCL $20,CR0GT,CTR // 4e810421
+ BCL 20,CR0LT,CTR // BCL $20,CR0LT,CTR // 4e800421
+ BCL 20,undefined_symbol,CTR // BCL $20,CR0LT,CTR // 4e800421
+ BCL 20,undefined_symbol+1,CTR // BCL $20,CR0GT,CTR // 4e810421
+
+ // Verify bc encoding (without pic enabled)
+ BC $16,CR0LT,0(PC) // 42000000
+ BCL $16,CR0LT,0(PC) // 42000001
+ BC $18,CR0LT,0(PC) // 42400000
RET