diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index 14b0de1271..e266593050 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -24,7 +24,7 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0 // { // outcode(int($1), &$2, 0, &$4); // } - MOVW foo<>+3(SB), R2 + MOVW foo<>+4(SB), R2 MOVW 16(R1), R2 // LMOVW regaddr ',' rreg @@ -61,7 +61,7 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0 // { // outcode(int($1), &$2, 0, &$4); // } - FMOVD foo<>+3(SB), F2 + FMOVD foo<>+4(SB), F2 FMOVD 16(R1), F2 // LFMOV regaddr ',' freg @@ -86,7 +86,7 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0 // { // outcode(int($1), &$2, 0, &$4); // } - FMOVD F2, foo<>+3(SB) + FMOVD F2, foo<>+4(SB) FMOVD F2, 16(R1) // LFMOV freg ',' regaddr @@ -132,7 +132,7 @@ TEXT foo(SB),DUPOK|NOSPLIT,$0 // { // outcode(int($1), &$2, 0, &$4); // } - FMOVD F1, foo<>+3(SB) + FMOVD F1, foo<>+4(SB) FMOVD F1, 16(R2) // LMOVW freg ',' regaddr diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 2169416b61..65c1a2b2cb 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -1985,29 +1985,48 @@ const ( DS_FORM ) -// opform returns the form (D_FORM or DS_FORM) of an instruction. Used to decide on -// which relocation to use with a load or store and only supports the needed -// instructions. +// This function determines when a non-indexed load or store is D or +// DS form for use in finding the size of the offset field in the instruction. +// The size is needed when setting the offset value in the instruction +// and when generating relocation for that field. +// DS form instructions include: ld, ldu, lwa, std, stdu. All other +// loads and stores with an offset field are D form. This function should +// only be called with the same opcodes as are handled by opstore and opload. func (c *ctxt9) opform(insn uint32) int { switch insn { default: c.ctxt.Diag("bad insn in loadform: %x", insn) case OPVCC(58, 0, 0, 0), // ld + OPVCC(58, 0, 0, 1), // ldu OPVCC(58, 0, 0, 0) | 1<<1, // lwa - OPVCC(62, 0, 0, 0): // std + OPVCC(62, 0, 0, 0), // std + OPVCC(62, 0, 0, 1): //stdu return DS_FORM case OP_ADDI, // add OPVCC(32, 0, 0, 0), // lwz - OPVCC(42, 0, 0, 0), // lha - OPVCC(40, 0, 0, 0), // lhz + OPVCC(33, 0, 0, 0), // lwzu OPVCC(34, 0, 0, 0), // lbz - OPVCC(50, 0, 0, 0), // lfd + OPVCC(35, 0, 0, 0), // lbzu + OPVCC(40, 0, 0, 0), // lhz + OPVCC(41, 0, 0, 0), // lhzu + OPVCC(42, 0, 0, 0), // lha + OPVCC(43, 0, 0, 0), // lhau + OPVCC(46, 0, 0, 0), // lmw OPVCC(48, 0, 0, 0), // lfs + OPVCC(49, 0, 0, 0), // lfsu + OPVCC(50, 0, 0, 0), // lfd + OPVCC(51, 0, 0, 0), // lfdu OPVCC(36, 0, 0, 0), // stw - OPVCC(44, 0, 0, 0), // sth + OPVCC(37, 0, 0, 0), // stwu OPVCC(38, 0, 0, 0), // stb + OPVCC(39, 0, 0, 0), // stbu + OPVCC(44, 0, 0, 0), // sth + OPVCC(45, 0, 0, 0), // sthu + OPVCC(47, 0, 0, 0), // stmw + OPVCC(52, 0, 0, 0), // stfs + OPVCC(53, 0, 0, 0), // stfsu OPVCC(54, 0, 0, 0), // stfd - OPVCC(52, 0, 0, 0): // stfs + OPVCC(55, 0, 0, 0): // stfdu return D_FORM } return 0 @@ -2268,7 +2287,12 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { if int32(int16(v)) != v { log.Fatalf("mishandled instruction %v", p) } - o1 = AOP_IRR(c.opstore(p.As), uint32(p.From.Reg), uint32(r), uint32(v)) + // Offsets in DS form stores must be a multiple of 4 + inst := c.opstore(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } + o1 = AOP_IRR(inst, uint32(p.From.Reg), uint32(r), uint32(v)) } case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */ @@ -2294,7 +2318,12 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { if int32(int16(v)) != v { log.Fatalf("mishandled instruction %v", p) } - o1 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), uint32(r), uint32(v)) + // Offsets in DS form loads must be a multiple of 4 + inst := c.opload(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } + o1 = AOP_IRR(inst, uint32(p.To.Reg), uint32(r), uint32(v)) } case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */ @@ -2789,8 +2818,13 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } + // Offsets in DS form stores must be a multiple of 4 + inst := c.opstore(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v))) - o2 = AOP_IRR(c.opstore(p.As), uint32(p.From.Reg), REGTMP, uint32(v)) + o2 = AOP_IRR(inst, uint32(p.From.Reg), REGTMP, uint32(v)) case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */ v := c.regoff(&p.From) @@ -3120,19 +3154,34 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { /* relocation operations */ case 74: v := c.vregoff(&p.To) - o1, o2 = c.symbolAccess(p.To.Sym, v, p.From.Reg, c.opstore(p.As)) + // Offsets in DS form stores must be a multiple of 4 + inst := c.opstore(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } + o1, o2 = c.symbolAccess(p.To.Sym, v, p.From.Reg, inst) //if(dlm) reloc(&p->to, p->pc, 1); case 75: v := c.vregoff(&p.From) - o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, c.opload(p.As)) + // Offsets in DS form loads must be a multiple of 4 + inst := c.opload(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } + o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, inst) //if(dlm) reloc(&p->from, p->pc, 1); case 76: v := c.vregoff(&p.From) - o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, c.opload(p.As)) + // Offsets in DS form loads must be a multiple of 4 + inst := c.opload(p.As) + if c.opform(inst) == DS_FORM && v&0x3 != 0 { + log.Fatalf("invalid offset for DS form load/store %v", p) + } + o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, inst) o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0) //if(dlm) reloc(&p->from, p->pc, 1); diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index caa000bb56..616861ea7d 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -85,14 +85,14 @@ nocgo: // start this M BL runtime·mstart(SB) - MOVD R0, 1(R0) + MOVD R0, 0(R0) RET DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) GLOBL runtime·mainPC(SB),RODATA,$8 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 - MOVD R0, 2(R0) // TODO: TD + MOVD R0, 0(R0) // TODO: TD RET TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index b43bda1ef2..ef7dab21b7 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -189,7 +189,7 @@ TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 MOVW size+24(FP), R6 SYSCALL $SYS_rt_sigprocmask BVC 2(PC) - MOVD R0, 0xf1(R0) // crash + MOVD R0, 0xf0(R0) // crash RET TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36 @@ -273,7 +273,7 @@ TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0 MOVD n+8(FP), R4 SYSCALL $SYS_munmap BVC 2(PC) - MOVD R0, 0xf3(R0) + MOVD R0, 0xf0(R0) RET TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0 @@ -366,7 +366,7 @@ TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0 MOVD old+8(FP), R4 SYSCALL $SYS_sigaltstack BVC 2(PC) - MOVD R0, 0xf1(R0) // crash + MOVD R0, 0xf0(R0) // crash RET TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0