aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorArchana R <aravind5@in.ibm.com>2022-05-11 10:48:48 -0500
committerLynn Boger <laboger@linux.vnet.ibm.com>2022-08-30 12:42:54 +0000
commit67d85ad00f9d9be0cc2bb1bb96d01c3d40dcb376 (patch)
treebdf38d3afd2557a4f6f0695578a2a624a518c497 /src/cmd/internal/obj
parent4381c61c58315dbdb8004bf56e54a5d2aa5d0498 (diff)
downloadgo-67d85ad00f9d9be0cc2bb1bb96d01c3d40dcb376.tar.xz
cmd/asm: add new classification for index memory operands on PPC64
When a base+displacement kind of operand is given in an index-mode instruction, the assembler does not flag it as an invalid instruction causing the user to get an incorrect encoding of that instruction leading to incorrect execution of the program. Enable assembler to recognize valid and invalid operands used in index mode instructions by classifying SOREG type into two further types XOREG (used uniquely in index addressing mode instructions) and SOREG for instructions working on base+displacement operands. Also cleaned up usage of obj.Addr.Scale on PPC64. Change-Id: Ib4d84343ae57477c6c074f44c4c2749496e11b91 Reviewed-on: https://go-review.googlesource.com/c/go/+/405542 Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Archana Ravindar <aravind5@in.ibm.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/ppc64/a.out.go3
-rw-r--r--src/cmd/internal/obj/ppc64/anames9.go1
-rw-r--r--src/cmd/internal/obj/ppc64/asm9.go147
-rw-r--r--src/cmd/internal/obj/ppc64/asm_test.go1
4 files changed, 93 insertions, 59 deletions
diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go
index 30eba4339a..6b6e498fd2 100644
--- a/src/cmd/internal/obj/ppc64/a.out.go
+++ b/src/cmd/internal/obj/ppc64/a.out.go
@@ -419,9 +419,10 @@ const (
C_SBRA /* A short offset argument to a branching instruction */
C_LBRA /* A long offset argument to a branching instruction */
C_LBRAPIC /* Like C_LBRA, but requires an extra NOP for potential TOC restore by the linker. */
- C_ZOREG /* An reg+reg memory arg, or a $0+reg memory op */
+ C_ZOREG /* An $0+reg memory op */
C_SOREG /* An $n+reg memory arg where n is a 16 bit signed offset */
C_LOREG /* An $n+reg memory arg where n is a 32 bit signed offset */
+ C_XOREG /* An reg+reg memory arg */
C_FPSCR /* The fpscr register */
C_XER /* The xer, holds the carry bit */
C_LR /* The link register */
diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go
index 05bfd944d1..c6cc923b80 100644
--- a/src/cmd/internal/obj/ppc64/anames9.go
+++ b/src/cmd/internal/obj/ppc64/anames9.go
@@ -39,6 +39,7 @@ var cnames9 = []string{
"ZOREG",
"SOREG",
"LOREG",
+ "XOREG",
"FPSCR",
"XER",
"LR",
diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go
index 94ad7a173b..ecd108e117 100644
--- a/src/cmd/internal/obj/ppc64/asm9.go
+++ b/src/cmd/internal/obj/ppc64/asm9.go
@@ -197,28 +197,36 @@ var optab = []Optab{
{as: AFMUL, a1: C_FREG, a2: C_FREG, a6: C_FREG, type_: 32, size: 4},
{as: AMOVBU, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
+ {as: AMOVBU, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBU, a1: C_SOREG, a6: C_REG, type_: 8, size: 8},
+ {as: AMOVBU, a1: C_XOREG, a6: C_REG, type_: 109, size: 8},
{as: AMOVBZU, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
+ {as: AMOVBZU, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBZU, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
+ {as: AMOVBZU, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
- {as: AMOVHBR, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
- {as: AMOVHBR, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
+ {as: AMOVHBR, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
+ {as: AMOVHBR, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: AMOVB, a1: C_ADDR, a6: C_REG, type_: 75, size: 12},
{as: AMOVB, a1: C_LOREG, a6: C_REG, type_: 36, size: 12},
{as: AMOVB, a1: C_SOREG, a6: C_REG, type_: 8, size: 8},
+ {as: AMOVB, a1: C_XOREG, a6: C_REG, type_: 109, size: 8},
{as: AMOVB, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVB, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVB, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
+ {as: AMOVB, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVB, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AMOVBZ, a1: C_ADDR, a6: C_REG, type_: 75, size: 8},
{as: AMOVBZ, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
{as: AMOVBZ, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
+ {as: AMOVBZ, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVBZ, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
+ {as: AMOVBZ, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AMOVD, a1: C_ADDCON, a6: C_REG, type_: 3, size: 4},
@@ -229,6 +237,7 @@ var optab = []Optab{
{as: AMOVD, a1: C_LACON, a6: C_REG, type_: 26, size: 8},
{as: AMOVD, a1: C_ADDR, a6: C_REG, type_: 75, size: 8},
{as: AMOVD, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
+ {as: AMOVD, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVD, a1: C_SOREG, a6: C_SPR, type_: 107, size: 8},
{as: AMOVD, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
{as: AMOVD, a1: C_TLS_LE, a6: C_REG, type_: 79, size: 8},
@@ -236,6 +245,7 @@ var optab = []Optab{
{as: AMOVD, a1: C_SPR, a6: C_REG, type_: 66, size: 4},
{as: AMOVD, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVD, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
+ {as: AMOVD, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVD, a1: C_SPR, a6: C_SOREG, type_: 106, size: 8},
{as: AMOVD, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
{as: AMOVD, a1: C_REG, a6: C_SPR, type_: 66, size: 4},
@@ -251,28 +261,33 @@ var optab = []Optab{
{as: AMOVW, a1: C_CREG, a6: C_REG, type_: 68, size: 4},
{as: AMOVW, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
{as: AMOVW, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
+ {as: AMOVW, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVW, a1: C_SPR, a6: C_REG, type_: 66, size: 4},
{as: AMOVW, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVW, a1: C_REG, a6: C_CREG, type_: 69, size: 4},
{as: AMOVW, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVW, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
+ {as: AMOVW, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVW, a1: C_REG, a6: C_SPR, type_: 66, size: 4},
{as: AMOVW, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AFMOVD, a1: C_ADDCON, a6: C_FREG, type_: 24, size: 8},
{as: AFMOVD, a1: C_SOREG, a6: C_FREG, type_: 8, size: 4},
+ {as: AFMOVD, a1: C_XOREG, a6: C_FREG, type_: 109, size: 4},
{as: AFMOVD, a1: C_LOREG, a6: C_FREG, type_: 36, size: 8},
{as: AFMOVD, a1: C_ZCON, a6: C_FREG, type_: 24, size: 4},
{as: AFMOVD, a1: C_ADDR, a6: C_FREG, type_: 75, size: 8},
{as: AFMOVD, a1: C_FREG, a6: C_FREG, type_: 33, size: 4},
{as: AFMOVD, a1: C_FREG, a6: C_SOREG, type_: 7, size: 4},
+ {as: AFMOVD, a1: C_FREG, a6: C_XOREG, type_: 108, size: 4},
{as: AFMOVD, a1: C_FREG, a6: C_LOREG, type_: 35, size: 8},
{as: AFMOVD, a1: C_FREG, a6: C_ADDR, type_: 74, size: 8},
- {as: AFMOVSX, a1: C_ZOREG, a6: C_FREG, type_: 45, size: 4},
- {as: AFMOVSX, a1: C_FREG, a6: C_ZOREG, type_: 44, size: 4},
+ {as: AFMOVSX, a1: C_XOREG, a6: C_FREG, type_: 45, size: 4},
+ {as: AFMOVSX, a1: C_FREG, a6: C_XOREG, type_: 44, size: 4},
{as: AFMOVSZ, a1: C_ZOREG, a6: C_FREG, type_: 45, size: 4},
+ {as: AFMOVSZ, a1: C_XOREG, a6: C_FREG, type_: 45, size: 4},
{as: AMOVFL, a1: C_CREG, a6: C_CREG, type_: 67, size: 4},
{as: AMOVFL, a1: C_FPSCR, a6: C_CREG, type_: 73, size: 4},
@@ -325,7 +340,7 @@ var optab = []Optab{
{as: AFTSQRT, a1: C_FREG, a6: C_SCON, type_: 93, size: 4}, /* floating test for sw square root, x-form */
{as: ACOPY, a1: C_REG, a6: C_REG, type_: 92, size: 4}, /* copy/paste facility, x-form */
{as: ADARN, a1: C_SCON, a6: C_REG, type_: 92, size: 4}, /* deliver random number, x-form */
- {as: ALDMX, a1: C_SOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */
+ {as: ALDMX, a1: C_XOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */
{as: AMADDHD, a1: C_REG, a2: C_REG, a3: C_REG, a6: C_REG, type_: 83, size: 4}, /* multiply-add high/low doubleword, va-form */
{as: AADDEX, a1: C_REG, a2: C_REG, a3: C_SCON, a6: C_REG, type_: 94, size: 4}, /* add extended using alternate carry, z23-form */
{as: ACRAND, a1: C_CRBIT, a2: C_CRBIT, a6: C_CRBIT, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */
@@ -333,10 +348,10 @@ var optab = []Optab{
/* Vector instructions */
/* Vector load */
- {as: ALV, a1: C_SOREG, a6: C_VREG, type_: 45, size: 4}, /* vector load, x-form */
+ {as: ALV, a1: C_XOREG, a6: C_VREG, type_: 45, size: 4}, /* vector load, x-form */
/* Vector store */
- {as: ASTV, a1: C_VREG, a6: C_SOREG, type_: 44, size: 4}, /* vector store, x-form */
+ {as: ASTV, a1: C_VREG, a6: C_XOREG, type_: 44, size: 4}, /* vector store, x-form */
/* Vector logical */
{as: AVAND, a1: C_VREG, a2: C_VREG, a6: C_VREG, type_: 82, size: 4}, /* vector and, vx-form */
@@ -405,26 +420,26 @@ var optab = []Optab{
{as: AVSHASIGMA, a1: C_ANDCON, a2: C_VREG, a3: C_ANDCON, a6: C_VREG, type_: 82, size: 4}, /* vector SHA sigma, vx-form */
/* VSX vector load */
- {as: ALXVD2X, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx vector load, xx1-form */
+ {as: ALXVD2X, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx vector load, xx1-form */
{as: ALXV, a1: C_SOREG, a6: C_VSREG, type_: 96, size: 4}, /* vsx vector load, dq-form */
{as: ALXVL, a1: C_REG, a2: C_REG, a6: C_VSREG, type_: 98, size: 4}, /* vsx vector load length */
/* VSX vector store */
- {as: ASTXVD2X, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx vector store, xx1-form */
+ {as: ASTXVD2X, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx vector store, xx1-form */
{as: ASTXV, a1: C_VSREG, a6: C_SOREG, type_: 97, size: 4}, /* vsx vector store, dq-form */
{as: ASTXVL, a1: C_VSREG, a2: C_REG, a6: C_REG, type_: 99, size: 4}, /* vsx vector store with length x-form */
/* VSX scalar load */
- {as: ALXSDX, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar load, xx1-form */
+ {as: ALXSDX, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar load, xx1-form */
/* VSX scalar store */
- {as: ASTXSDX, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx scalar store, xx1-form */
+ {as: ASTXSDX, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx scalar store, xx1-form */
/* VSX scalar as integer load */
- {as: ALXSIWAX, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar as integer load, xx1-form */
+ {as: ALXSIWAX, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar as integer load, xx1-form */
/* VSX scalar store as integer */
- {as: ASTXSIWX, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx scalar as integer store, xx1-form */
+ {as: ASTXSIWX, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx scalar as integer store, xx1-form */
/* VSX move from VSR */
{as: AMFVSRD, a1: C_VSREG, a6: C_REG, type_: 88, size: 4},
@@ -488,24 +503,25 @@ var optab = []Optab{
{as: AFCMPO, a1: C_FREG, a2: C_CREG, a6: C_FREG, type_: 70, size: 4},
{as: ATW, a1: C_LCON, a2: C_REG, a6: C_REG, type_: 60, size: 4},
{as: ATW, a1: C_LCON, a2: C_REG, a6: C_ADDCON, type_: 61, size: 4},
- {as: ADCBF, a1: C_ZOREG, type_: 43, size: 4},
{as: ADCBF, a1: C_SOREG, type_: 43, size: 4},
- {as: ADCBF, a1: C_ZOREG, a2: C_REG, a6: C_SCON, type_: 43, size: 4},
+ {as: ADCBF, a1: C_XOREG, type_: 43, size: 4},
+ {as: ADCBF, a1: C_XOREG, a2: C_REG, a6: C_SCON, type_: 43, size: 4},
{as: ADCBF, a1: C_SOREG, a6: C_SCON, type_: 43, size: 4},
- {as: AECOWX, a1: C_REG, a2: C_REG, a6: C_ZOREG, type_: 44, size: 4},
- {as: AECIWX, a1: C_ZOREG, a2: C_REG, a6: C_REG, type_: 45, size: 4},
- {as: AECOWX, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
- {as: AECIWX, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
- {as: ALDAR, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
- {as: ALDAR, a1: C_ZOREG, a3: C_ANDCON, a6: C_REG, type_: 45, size: 4},
+ {as: ADCBF, a1: C_XOREG, a6: C_SCON, type_: 43, size: 4},
+ {as: AECOWX, a1: C_REG, a2: C_REG, a6: C_XOREG, type_: 44, size: 4},
+ {as: AECIWX, a1: C_XOREG, a2: C_REG, a6: C_REG, type_: 45, size: 4},
+ {as: AECOWX, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
+ {as: AECIWX, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
+ {as: ALDAR, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
+ {as: ALDAR, a1: C_XOREG, a3: C_ANDCON, a6: C_REG, type_: 45, size: 4},
{as: AEIEIO, type_: 46, size: 4},
{as: ATLBIE, a1: C_REG, type_: 49, size: 4},
{as: ATLBIE, a1: C_SCON, a6: C_REG, type_: 49, size: 4},
{as: ASLBMFEE, a1: C_REG, a6: C_REG, type_: 55, size: 4},
{as: ASLBMTE, a1: C_REG, a6: C_REG, type_: 55, size: 4},
- {as: ASTSW, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
+ {as: ASTSW, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
{as: ASTSW, a1: C_REG, a3: C_LCON, a6: C_ZOREG, type_: 41, size: 4},
- {as: ALSW, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
+ {as: ALSW, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: ALSW, a1: C_ZOREG, a3: C_LCON, a6: C_REG, type_: 42, size: 4},
{as: APNOP, type_: 105, size: 8, ispfx: true},
@@ -583,7 +599,7 @@ func (c *ctxt9) getimpliedreg(a *obj.Addr, p *obj.Prog) int {
switch class {
case C_SACON, C_LACON:
return REGSP
- case C_LOREG, C_SOREG, C_ZOREG:
+ case C_LOREG, C_SOREG, C_ZOREG, C_XOREG:
switch a.Name {
case obj.NAME_EXTERN, obj.NAME_STATIC:
return REGSB
@@ -881,6 +897,13 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
return c.aclassreg(a.Reg)
case obj.TYPE_MEM:
+ if a.Index != 0 {
+ if a.Name != obj.NAME_NONE || a.Offset != 0 {
+ c.ctxt.Logf("Unexpected Instruction operand index %d offset %d class %d \n", a.Index, a.Offset, a.Class)
+
+ }
+ return C_XOREG
+ }
switch a.Name {
case obj.NAME_GOTREF, obj.NAME_TOCREF:
return C_ADDR
@@ -903,6 +926,7 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
case obj.NAME_AUTO:
c.instoffset = int64(c.autosize) + a.Offset
+
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SOREG
}
@@ -917,13 +941,13 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
case obj.NAME_NONE:
c.instoffset = a.Offset
- if c.instoffset == 0 {
+ if a.Offset == 0 && a.Index == 0 {
return C_ZOREG
- }
- if c.instoffset >= -BIG && c.instoffset < BIG {
+ } else if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SOREG
+ } else {
+ return C_LOREG
}
- return C_LOREG
}
return C_GOK
@@ -1160,6 +1184,9 @@ func cmp(a int, b int) bool {
case C_LOREG:
return cmp(C_SOREG, b)
+ case C_XOREG:
+ return cmp(C_REG, b) || cmp(C_ZOREG, b)
+
// An even/odd register input always matches the regular register types.
case C_REG:
return cmp(C_REGP, b) || (b == C_ZCON && r0iszero != 0)
@@ -2562,22 +2589,15 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = c.getimpliedreg(&p.To, p)
}
v := c.regoff(&p.To)
- if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 {
- if v != 0 {
- c.ctxt.Diag("illegal indexed instruction\n%v", p)
- }
- o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
- } else {
- if int32(int16(v)) != v {
- log.Fatalf("mishandled instruction %v", p)
- }
- // 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))
+ if int32(int16(v)) != v {
+ log.Fatalf("mishandled instruction %v", p)
}
+ // 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), lbz o(r) + extsb r,r */
r := int(p.From.Reg)
@@ -2586,22 +2606,15 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = c.getimpliedreg(&p.From, p)
}
v := c.regoff(&p.From)
- if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
- if v != 0 {
- c.ctxt.Diag("illegal indexed instruction\n%v", p)
- }
- o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
- } else {
- if int32(int16(v)) != v {
- log.Fatalf("mishandled instruction %v", p)
- }
- // 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))
+ if int32(int16(v)) != v {
+ log.Fatalf("mishandled instruction %v", p)
+ }
+ // 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))
// Sign extend MOVB operations. This is ignored for other cases (o.size == 4).
o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
@@ -3141,9 +3154,16 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = uint32(c.regoff(&p.From))
case 41: /* stswi */
+ if p.To.Type == obj.TYPE_MEM && p.To.Index == 0 && p.To.Offset != 0 {
+ c.ctxt.Diag("Invalid addressing mode used in index type instruction: %v", p.As)
+ }
+
o1 = AOP_RRR(c.opirr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 42: /* lswi */
+ if p.From.Type == obj.TYPE_MEM && p.From.Index == 0 && p.From.Offset != 0 {
+ c.ctxt.Diag("Invalid addressing mode used in index type instruction: %v", p.As)
+ }
o1 = AOP_RRR(c.opirr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 43: /* data cache instructions: op (Ra+[Rb]), [th|l] */
@@ -3772,6 +3792,17 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if so&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
+
+ case 108: /* mov r, xoreg ==> stwx rx,ry */
+ r := int(p.To.Reg)
+ o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
+
+ case 109: /* mov xoreg, r ==> lbzx/lhzx/lwzx rx,ry, lbzx rx,ry + extsb r,r */
+ r := int(p.From.Reg)
+
+ o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
+ // Sign extend MOVB operations. This is ignored for other cases (o.size == 4).
+ o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
}
out[0] = o1
diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go
index c16d4a6e73..15dde3a952 100644
--- a/src/cmd/internal/obj/ppc64/asm_test.go
+++ b/src/cmd/internal/obj/ppc64/asm_test.go
@@ -482,6 +482,7 @@ func TestAddrClassifier(t *testing.T) {
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: BIG}, C_LOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: -BIG - 33}, C_LOREG}, // 33 is FixedFrameSize-1
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE}, C_ZOREG},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Index: REG_R4}, C_XOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: 1}, C_SOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: BIG}, C_LOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: -BIG - 33}, C_LOREG},