)
const (
- C_NONE = iota
- C_REG
- C_FREG
- C_VREG
- C_VSREG
- C_CREG
- C_SPR /* special processor register */
- C_ZCON
- C_SCON /* 16 bit signed */
- C_UCON /* 32 bit signed, low 16 bits 0 */
- C_ADDCON /* -0x8000 <= v < 0 */
- C_ANDCON /* 0 < v <= 0xFFFF */
- C_LCON /* other 32 */
- C_DCON /* other 64 (could subdivide further) */
- C_SACON /* $n(REG) where n <= int16 */
- C_LACON /* $n(REG) where int16 < n <= int32 */
- C_DACON /* $n(REG) where int32 < n */
- C_SBRA
- C_LBRA
- C_LBRAPIC
- C_ZOREG // conjecture: either (1) register + zeroed offset, or (2) "R0" implies zero or C_REG
- C_SOREG // D/DS form memory operation
- C_LOREG // 32 bit addis + D/DS-form memory operation
- C_FPSCR
- C_XER
- C_LR
- C_CTR
- C_ANY
- C_GOK
- C_ADDR
- C_TLS_LE
- C_TLS_IE
- C_TEXTSIZE
+ C_NONE = iota
+ C_REGP /* An even numbered gpr which can be used a gpr pair argument */
+ C_REG /* Any gpr register */
+ C_FREGP /* An even numbered fpr which can be used a fpr pair argument */
+ C_FREG /* Any fpr register */
+ C_VREG /* Any vector register */
+ C_VSREGP /* An even numbered vsx register which can be used as a vsx register pair argument */
+ C_VSREG /* Any vector-scalar register */
+ C_CREG /* The condition registor (CR) or a condition register field (CRx) */
+ C_SPR /* special processor register */
+ C_ZCON /* The constant zero */
+ C_U1CON /* 1 bit unsigned constant */
+ C_U2CON /* 2 bit unsigned constant */
+ C_U3CON /* 3 bit unsigned constant */
+ C_U4CON /* 4 bit unsigned constant */
+ C_U5CON /* 5 bit unsigned constant */
+ C_U8CON /* 8 bit unsigned constant */
+ C_U15CON /* 15 bit unsigned constant */
+ C_S16CON /* 16 bit signed constant */
+ C_U16CON /* 16 bit unsigned constant */
+ C_32S16CON /* Any 32 bit constant of the form 0x....0000, signed or unsigned */
+ C_32CON /* Any constant which fits into 32 bits. Can be signed or unsigned */
+ C_S34CON /* 34 bit signed constant */
+ C_64CON /* Any constant which fits into 64 bits. Can be signed or unsigned */
+ C_SACON /* $n(REG) where n <= int16 */
+ C_LACON /* $n(REG) where n <= int32 */
+ C_DACON /* $n(REG) where n <= int64 */
+ 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_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_FPSCR /* The fpscr register */
+ C_XER /* The xer, holds the carry bit */
+ C_LR /* The link register */
+ C_CTR /* The count register */
+ C_ANY /* Any argument */
+ C_GOK /* A non-matched argument */
+ C_ADDR /* A symbolic memory location */
+ C_TLS_LE /* A thread local, local-exec, type memory arg */
+ C_TLS_IE /* A thread local, initial-exec, type memory arg */
+ C_TEXTSIZE /* An argument with Type obj.TYPE_TEXTSIZE */
C_NCLASS /* must be the last */
+
+ /* Aliased names which should be cleaned up, or integrated. */
+ C_SCON = C_U15CON
+ C_UCON = C_32S16CON
+ C_ADDCON = C_S16CON
+ C_ANDCON = C_U16CON
+ C_LCON = C_32CON
+
+ /* Aliased names which may be generated by ppc64map for the optab. */
+ C_S3216CON = C_32S16CON // TODO: these should be treated differently (e.g xoris vs addis)
+ C_U3216CON = C_32S16CON
+ C_S32CON = C_32CON
+ C_U32CON = C_32CON
)
const (
var cnames9 = []string{
"NONE",
+ "REGP",
"REG",
+ "FREGP",
"FREG",
"VREG",
+ "VSREGP",
"VSREG",
"CREG",
"SPR",
"ZCON",
- "SCON",
- "UCON",
- "ADDCON",
- "ANDCON",
- "LCON",
- "DCON",
+ "U1CON",
+ "U2CON",
+ "U3CON",
+ "U4CON",
+ "U5CON",
+ "U8CON",
+ "U15CON",
+ "S16CON",
+ "U16CON",
+ "32S16CON",
+ "32CON",
+ "S34CON",
+ "64CON",
"SACON",
"LACON",
"DACON",
{as: ABC, a6: C_ZOREG, type_: 15, size: 8},
{as: ASYNC, type_: 46, size: 4},
{as: AWORD, a1: C_LCON, type_: 40, size: 4},
- {as: ADWORD, a1: C_LCON, type_: 31, size: 8},
- {as: ADWORD, a1: C_DCON, type_: 31, size: 8},
+ {as: ADWORD, a1: C_64CON, type_: 31, size: 8},
{as: ADWORD, a1: C_LACON, type_: 31, size: 8},
{as: AADDME, a1: C_REG, a6: C_REG, type_: 47, size: 4},
{as: AEXTSB, a1: C_REG, a6: C_REG, type_: 48, size: 4},
{as: ALDMX, a1: C_SOREG, 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_CREG, a6: C_CREG, type_: 2, size: 4}, /* logical ops for condition registers xl-form */
+ {as: ACRAND, a1: C_CREG, a2: C_CREG, a6: C_CREG, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */
/* Vector instructions */
{as: AXVCVSXDDP, a1: C_VSREG, a6: C_VSREG, type_: 89, size: 4}, /* vsx vector integer-fp conversion, xx2-form */
{as: ACMP, a1: C_REG, a6: C_REG, type_: 70, size: 4},
- {as: ACMP, a1: C_REG, a2: C_REG, a6: C_REG, type_: 70, size: 4},
+ {as: ACMP, a1: C_REG, a2: C_CREG, a6: C_REG, type_: 70, size: 4},
{as: ACMP, a1: C_REG, a6: C_ADDCON, type_: 71, size: 4},
- {as: ACMP, a1: C_REG, a2: C_REG, a6: C_ADDCON, type_: 71, size: 4},
+ {as: ACMP, a1: C_REG, a2: C_CREG, a6: C_ADDCON, type_: 71, size: 4},
{as: ACMPU, a1: C_REG, a6: C_REG, type_: 70, size: 4},
- {as: ACMPU, a1: C_REG, a2: C_REG, a6: C_REG, type_: 70, size: 4},
+ {as: ACMPU, a1: C_REG, a2: C_CREG, a6: C_REG, type_: 70, size: 4},
{as: ACMPU, a1: C_REG, a6: C_ANDCON, type_: 71, size: 4},
- {as: ACMPU, a1: C_REG, a2: C_REG, a6: C_ANDCON, type_: 71, size: 4},
+ {as: ACMPU, a1: C_REG, a2: C_CREG, a6: C_ANDCON, type_: 71, size: 4},
{as: AFCMPO, a1: C_FREG, a6: C_FREG, type_: 70, size: 4},
- {as: AFCMPO, a1: C_FREG, a2: C_REG, a6: C_FREG, type_: 70, size: 4},
+ {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},
// or "MOVD R5, foo+10(SP) or pseudo-register is used. The other common case is when
// generating constants in register like "MOVD $constant, Rx".
func (c *ctxt9) getimpliedreg(a *obj.Addr, p *obj.Prog) int {
- switch oclass(a) {
- case C_ADDCON, C_ANDCON, C_UCON, C_LCON, C_SCON, C_ZCON:
+ class := oclass(a)
+ if class >= C_ZCON && class <= C_64CON {
return REGZERO
+ }
+ switch class {
case C_SACON, C_LACON:
return REGSP
case C_LOREG, C_SOREG, C_ZOREG:
return uint64(uint32(v)) == v
}
+func (c *ctxt9) aclassreg(reg int16) int {
+ if REG_R0 <= reg && reg <= REG_R31 {
+ return C_REGP + int(reg&1)
+ }
+ if REG_F0 <= reg && reg <= REG_F31 {
+ return C_FREGP + int(reg&1)
+ }
+ if REG_V0 <= reg && reg <= REG_V31 {
+ return C_VREG
+ }
+ if REG_VS0 <= reg && reg <= REG_VS63 {
+ return C_VSREGP + int(reg&1)
+ }
+ if REG_CR0 <= reg && reg <= REG_CR7 || reg == REG_CR {
+ return C_CREG
+ }
+ if REG_SPR0 <= reg && reg <= REG_SPR0+1023 {
+ switch reg {
+ case REG_LR:
+ return C_LR
+
+ case REG_XER:
+ return C_XER
+
+ case REG_CTR:
+ return C_CTR
+ }
+
+ return C_SPR
+ }
+ if reg == REG_FPSCR {
+ return C_FPSCR
+ }
+ return C_GOK
+}
+
func (c *ctxt9) aclass(a *obj.Addr) int {
switch a.Type {
case obj.TYPE_NONE:
return C_NONE
case obj.TYPE_REG:
- if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
- return C_REG
- }
- if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
- return C_FREG
- }
- if REG_V0 <= a.Reg && a.Reg <= REG_V31 {
- return C_VREG
- }
- if REG_VS0 <= a.Reg && a.Reg <= REG_VS63 {
- return C_VSREG
- }
- if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR {
- return C_CREG
- }
- if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 {
- switch a.Reg {
- case REG_LR:
- return C_LR
-
- case REG_XER:
- return C_XER
-
- case REG_CTR:
- return C_CTR
- }
-
- return C_SPR
- }
- if a.Reg == REG_FPSCR {
- return C_FPSCR
- }
- return C_GOK
+ return c.aclassreg(a.Reg)
case obj.TYPE_MEM:
switch a.Name {
case obj.NAME_NONE:
c.instoffset = a.Offset
if a.Reg != 0 {
- if -BIG <= c.instoffset && c.instoffset <= BIG {
+ if -BIG <= c.instoffset && c.instoffset < BIG {
return C_SACON
}
if isint32(c.instoffset) {
}
if c.instoffset >= 0 {
- if c.instoffset == 0 {
- return C_ZCON
- }
- if c.instoffset <= 0x7fff {
- return C_SCON
- }
- if c.instoffset <= 0xffff {
- return C_ANDCON
- }
- if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
- return C_UCON
+ sbits := bits.Len64(uint64(c.instoffset))
+ switch {
+ case sbits <= 5:
+ return C_ZCON + sbits
+ case sbits <= 8:
+ return C_U8CON
+ case sbits <= 15:
+ return C_U15CON
+ case sbits <= 16:
+ return C_U16CON
+ case sbits <= 31:
+ // Special case, a positive int32 value which is a multiple of 2^16
+ if c.instoffset&0xFFFF == 0 {
+ return C_U3216CON
+ }
+ return C_U32CON
+ case sbits <= 32:
+ return C_U32CON
+ case sbits <= 33:
+ return C_S34CON
+ default:
+ return C_64CON
}
- if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
- return C_LCON
+ } else {
+ sbits := bits.Len64(uint64(^c.instoffset))
+ switch {
+ case sbits <= 15:
+ return C_S16CON
+ case sbits <= 31:
+ // Special case, a negative int32 value which is a multiple of 2^16
+ if c.instoffset&0xFFFF == 0 {
+ return C_S3216CON
+ }
+ return C_S32CON
+ case sbits <= 33:
+ return C_S34CON
+ default:
+ return C_64CON
}
- return C_DCON
}
- if c.instoffset >= -0x8000 {
- return C_ADDCON
- }
- if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
- return C_UCON
- }
- if isint32(c.instoffset) {
- return C_LCON
- }
- return C_DCON
-
case obj.TYPE_BRANCH:
if a.Sym != nil && c.ctxt.Flag_dynlink {
return C_LBRAPIC
a2 := C_NONE
if p.Reg != 0 {
- if REG_R0 <= p.Reg && p.Reg <= REG_R31 {
- a2 = C_REG
- } else if REG_V0 <= p.Reg && p.Reg <= REG_V31 {
- a2 = C_VREG
- } else if REG_VS0 <= p.Reg && p.Reg <= REG_VS63 {
- a2 = C_VSREG
- } else if REG_F0 <= p.Reg && p.Reg <= REG_F31 {
- a2 = C_FREG
- }
+ a2 = c.aclassreg(p.Reg)
}
// c.ctxt.Logf("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4, a5, a6)
return &ops[0]
}
+// Compare two operand types (ex C_REG, or C_SCON)
+// and return true if b is compatible with a.
+//
+// Argument comparison isn't reflexitive, so care must be taken.
+// a is the argument type as found in optab, b is the argument as
+// fitted by aclass.
func cmp(a int, b int) bool {
if a == b {
return true
}
switch a {
- case C_LCON:
- if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
- return true
- }
-
- case C_ADDCON:
- if b == C_ZCON || b == C_SCON {
- return true
- }
-
- case C_ANDCON:
- if b == C_ZCON || b == C_SCON {
- return true
- }
case C_SPR:
if b == C_LR || b == C_XER || b == C_CTR {
return true
}
- case C_UCON:
- if b == C_ZCON {
- return true
- }
-
- case C_SCON:
- if b == C_ZCON {
- return true
- }
+ case C_U1CON:
+ return cmp(C_ZCON, b)
+ case C_U2CON:
+ return cmp(C_U1CON, b)
+ case C_U3CON:
+ return cmp(C_U2CON, b)
+ case C_U4CON:
+ return cmp(C_U3CON, b)
+ case C_U5CON:
+ return cmp(C_U4CON, b)
+ case C_U8CON:
+ return cmp(C_U5CON, b)
+ case C_U15CON:
+ return cmp(C_U8CON, b)
+ case C_U16CON:
+ return cmp(C_U15CON, b)
+
+ case C_S16CON:
+ return cmp(C_U15CON, b)
+ case C_32CON:
+ return cmp(C_S16CON, b) || cmp(C_U16CON, b) || cmp(C_32S16CON, b)
+ case C_S34CON:
+ return cmp(C_32CON, b)
+ case C_64CON:
+ return cmp(C_S34CON, b)
+
+ case C_32S16CON:
+ return cmp(C_ZCON, b)
case C_LACON:
- if b == C_SACON {
- return true
- }
+ return cmp(C_SACON, b)
case C_LBRA:
- if b == C_SBRA {
- return true
- }
+ return cmp(C_SBRA, b)
case C_SOREG:
- if b == C_ZOREG {
- return true
- }
+ return cmp(C_ZOREG, b)
case C_LOREG:
- if b == C_SOREG || b == C_ZOREG {
- return true
- }
+ return cmp(C_SOREG, b)
+ // An even/odd register input always matches the regular register types.
case C_REG:
- if b == C_ZCON {
- return r0iszero != 0 /*TypeKind(100016)*/
- }
-
+ return cmp(C_REGP, b) || (b == C_ZCON && r0iszero != 0)
+ case C_FREG:
+ return cmp(C_FREGP, b)
case C_VSREG:
/* Allow any VR argument as a VSR operand. */
- if b == C_VREG {
- return true
- }
+ return cmp(C_VSREGP, b) || cmp(C_VREG, b)
case C_ANY:
return true
import (
"bytes"
+ "cmd/internal/obj"
+ "cmd/internal/objabi"
"fmt"
"internal/testenv"
"io/ioutil"
+ "math"
"os"
"os/exec"
"path/filepath"
tstFunc(t.rstart, t.rend, t.msk, t.rout)
}
}
+
+// Verify interesting obj.Addr arguments are classified correctly.
+func TestAddrClassifier(t *testing.T) {
+ type cmplx struct {
+ pic int
+ pic_dyn int
+ dyn int
+ nonpic int
+ }
+ tsts := [...]struct {
+ arg obj.Addr
+ output interface{}
+ }{
+ // Supported register type args
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_R1}, C_REG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_R2}, C_REGP},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_F1}, C_FREG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_F2}, C_FREGP},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_V2}, C_VREG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_VS1}, C_VSREG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_VS2}, C_VSREGP},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR}, C_CREG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR1}, C_CREG},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0}, C_SPR},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 1}, C_XER},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 8}, C_LR},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 9}, C_CTR},
+ {obj.Addr{Type: obj.TYPE_REG, Reg: REG_FPSCR}, C_FPSCR},
+
+ // Memory type arguments.
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_GOTREF}, C_ADDR},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_TOCREF}, C_ADDR},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.STLSBSS}}, cmplx{C_TLS_IE, C_TLS_IE, C_TLS_LE, C_TLS_LE}},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.SDATA}}, C_ADDR},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO}, C_SOREG},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO, Offset: BIG}, C_LOREG},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO, Offset: -BIG - 1}, C_LOREG},
+ {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM}, C_SOREG},
+ {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, 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},
+
+ // Misc (golang initializes -0.0 to 0.0, hence the obfuscation below)
+ {obj.Addr{Type: obj.TYPE_TEXTSIZE}, C_TEXTSIZE},
+ {obj.Addr{Type: obj.TYPE_FCONST, Val: 0.0}, C_ZCON},
+ {obj.Addr{Type: obj.TYPE_FCONST, Val: math.Float64frombits(0x8000000000000000)}, C_S16CON},
+
+ // Address type arguments
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: 1}, C_SACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: BIG}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: -BIG - 1}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: 1 << 32}, C_DACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.SDATA}}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_STATIC, Sym: &obj.LSym{Type: objabi.SDATA}}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: 1}, C_SACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: BIG}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: -BIG - 1}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: 1}, C_SACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: BIG}, C_LACON},
+ {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: -BIG - 33}, C_LACON}, // 33 is FixedFrameSize-1
+
+ // Constant type arguments
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 0}, C_ZCON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1}, C_U1CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 2}, C_U2CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 4}, C_U3CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 8}, C_U4CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 16}, C_U5CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 32}, C_U8CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 14}, C_U15CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 15}, C_U16CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 16}, C_U3216CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 + 1<<16}, C_U32CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 32}, C_S34CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 33}, C_64CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -1}, C_S16CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10000}, C_S3216CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10001}, C_S32CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 33)}, C_S34CON},
+ {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 34)}, C_64CON},
+
+ // Branch like arguments
+ {obj.Addr{Type: obj.TYPE_BRANCH, Sym: &obj.LSym{Type: objabi.SDATA}}, cmplx{C_SBRA, C_LBRAPIC, C_LBRAPIC, C_SBRA}},
+ {obj.Addr{Type: obj.TYPE_BRANCH}, C_SBRA},
+ }
+
+ pic_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_shared: true, Arch: &Linkppc64}, autosize: 0}
+ pic_dyn_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_shared: true, Flag_dynlink: true, Arch: &Linkppc64}, autosize: 0}
+ dyn_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_dynlink: true, Arch: &Linkppc64}, autosize: 0}
+ nonpic_ctxt9 := ctxt9{ctxt: &obj.Link{Arch: &Linkppc64}, autosize: 0}
+ ctxts := [...]*ctxt9{&pic_ctxt9, &pic_dyn_ctxt9, &dyn_ctxt9, &nonpic_ctxt9}
+ name := [...]string{"pic", "pic_dyn", "dyn", "nonpic"}
+ for _, tst := range tsts {
+ var expect []int
+ switch tst.output.(type) {
+ case cmplx:
+ v := tst.output.(cmplx)
+ expect = []int{v.pic, v.pic_dyn, v.dyn, v.nonpic}
+ case int:
+ expect = []int{tst.output.(int), tst.output.(int), tst.output.(int), tst.output.(int)}
+ }
+ for i, _ := range ctxts {
+ if output := ctxts[i].aclass(&tst.arg); output != expect[i] {
+ t.Errorf("%s.aclass(%v) = %v, expected %v\n", name[i], tst.arg, DRconv(output), DRconv(expect[i]))
+ }
+ }
+ }
+}