aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.s8
-rw-r--r--src/cmd/internal/obj/ppc64/asm9.go79
-rw-r--r--src/runtime/asm_ppc64x.s4
-rw-r--r--src/runtime/sys_linux_ppc64x.s6
4 files changed, 73 insertions, 24 deletions
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