diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index b62eda8b14..90bee3d9b6 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -627,8 +627,6 @@ func addpad(pc, a int64, ctxt *obj.Link) int { } case 16: switch pc % 16 { - // When currently aligned to 4, avoid 3 NOPs and set to - // 8 byte alignment which should still help. case 4, 12: return 4 case 8: @@ -758,15 +756,20 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 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) } - origsize := o.size - c.asmout(p, o, out[:]) - if origsize == 0 && o.size > 0 { - for i = 0; i < int32(o.size/4); i++ { - c.ctxt.Arch.ByteOrder.PutUint32(bp, out[0]) - bp = bp[4:] + // asmout is not set up to add large amounts of padding + if o.type_ == 0 && p.As == obj.APCALIGN { + pad := LOP_RRR(OP_OR, REGZERO, REGZERO, REGZERO) + aln := c.vregoff(&p.From) + v := addpad(p.Pc, aln, c.ctxt) + if v > 0 { + // Same padding instruction for all + for i = 0; i < int32(v/4); i++ { + c.ctxt.Arch.ByteOrder.PutUint32(bp, pad) + bp = bp[4:] + } } - o.size = origsize } else { + c.asmout(p, o, out[:]) for i = 0; i < int32(o.size/4); i++ { c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) bp = bp[4:] @@ -2387,19 +2390,6 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { prasm(p) case 0: /* pseudo ops */ - if p.As == obj.APCALIGN { - aln := c.vregoff(&p.From) - v := addpad(p.Pc, aln, c.ctxt) - if v > 0 { - for i := 0; i < 6; i++ { - out[i] = uint32(0) - } - o.size = int8(v) - out[0] = LOP_RRR(OP_OR, REGZERO, REGZERO, REGZERO) - return - } - o.size = 0 - } break case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go new file mode 100644 index 0000000000..fff478e552 --- /dev/null +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -0,0 +1,81 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ppc64 + +import ( + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +var invalidPCAlignSrc = ` +TEXT test(SB),0,$0-0 +ADD $2, R3 +PCALIGN $32 +RET +` +var validPCAlignSrc = ` +TEXT test(SB),0,$0-0 +ADD $2, R3 +PCALIGN $16 +MOVD $8, R4 +ADD $8, R4 +PCALIGN $16 +ADD $8, R4 +PCALIGN $8 +ADD $4, R6 +PCALIGN $16 +ADD R2, R3, R4 +RET +` + +// TestPCalign generates two asm files containing the +// PCALIGN directive, to verify correct values are and +// accepted, and incorrect values are flagged in error. +func TestPCalign(t *testing.T) { + testenv.MustHaveGoBuild(t) + + dir, err := ioutil.TempDir("", "testpcalign") + if err != nil { + t.Fatalf("could not create directory: %v", err) + } + defer os.RemoveAll(dir) + + // generate a test with valid uses of PCALIGN + + tmpfile := filepath.Join(dir, "x.s") + err = ioutil.WriteFile(tmpfile, []byte(validPCAlignSrc), 0644) + if err != nil { + t.Fatalf("can't write output: %v\n", err) + } + + // build generated file without errors and assemble it + cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), "-S", tmpfile) + cmd.Env = append(os.Environ(), "GOARCH=ppc64le", "GOOS=linux") + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("Build failed: %v, output: %s", err, out) + } + + // generate a test with invalid use of PCALIGN + + tmpfile = filepath.Join(dir, "xi.s") + err = ioutil.WriteFile(tmpfile, []byte(invalidPCAlignSrc), 0644) + if err != nil { + t.Fatalf("can't write output: %v\n", err) + } + + // build test with errors and check for messages + cmd = exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "xi.o"), "-S", tmpfile) + cmd.Env = append(os.Environ(), "GOARCH=ppc64le", "GOOS=linux") + out, err = cmd.CombinedOutput() + if !strings.Contains(string(out), "Unexpected alignment") { + t.Errorf("Invalid alignment not detected for PCALIGN\n") + } +}