FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
FMOVD F4, (R2)(R6<<3) // 447826fc
+ CMPW $40960, R0 // 1f284071
+ CMPW $27745, R2 // 3b8c8d525f001b6b
+ CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
+ CMPW $0xffff0, R1 // CMPW $1048560, R1 // fb3f1c323f001b6b
+ ADD $0x3fffffffc000, R5 // ADD $70368744161280, R5 // fb7f72b2a5001b8b
// LTYPE1 imsr ',' spreg ','
// {
// outcode($1, &$2, $4, &nullgen);
ANDS $0x22220000, R3, R4 // ANDS $572653568, R3, R4 // 5b44a4d264001bea
BICS $0x22220000, R3, R4 // BICS $572653568, R3, R4 // 5b44a4d264003bea
+ EOR $0xe03fffffffffffff, R20, R22 // EOR $-2287828610704211969, R20, R22 // 96e243d2
+ TSTW $0x600000006, R1 // TSTW $25769803782, R1 // 3f041f72
+ ANDS $0xffff, R2 // ANDS $65535, R2 // 423c40f2
+ AND $0x7fffffff, R3 // AND $2147483647, R3 // 63784092
+ ANDS $0x0ffffffff80000000, R2 // ANDS $-2147483648, R2 // 428061f2
+ AND $0xfffff, R2 // AND $1048575, R2 // 424c4092
+ ANDW $0xf00fffff, R1 // ANDW $4027580415, R1 // 215c0412
+ ANDSW $0xff00ffff, R1 // ANDSW $4278255615, R1 // 215c0872
+ TSTW $0xff00ff, R1 // TSTW $16711935, R1 // 3f9c0072
+
AND $8, R0, RSP // 1f007d92
ORR $8, R0, RSP // 1f007db2
EOR $8, R0, RSP // 1f007dd2
ORN $8, R0, RSP // 1ff87cb2
EON $8, R0, RSP // 1ff87cd2
+ MOVD $0x3fffffffc000, R0 // MOVD $70368744161280, R0 // e07f72b2
+ MOVW $0xaaaa0000, R1 // MOVW $2863267840, R1 // 4155b552
+ MOVW $0xaaaaffff, R1 // MOVW $2863333375, R1 // a1aaaa12
+ MOVW $0xaaaa, R1 // MOVW $43690, R1 // 41559552
+ MOVW $0xffffaaaa, R1 // MOVW $4294945450, R1 // a1aa8a12
+ MOVW $0xffff0000, R1 // MOVW $4294901760, R1 // e1ffbf52
+ MOVD $0xffff00000000000, R1 // MOVD $1152903912420802560, R1 // e13f54b2
+ MOVD $0x11110000, R1 // MOVD $286326784, R1 // 2122a2d2
+ MOVD $0, R1 // 010080d2
+ MOVD $-1, R1 // 01008092
+ MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
+ MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92
+
//
// CLS
//
CMP R22.SXTX, RSP // ffe336eb
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
- CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a4d2ff633b6b
+ CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b
// TST
TST $15, R2 // 5f0c40f2
return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
}
+func MOVCONST(d int64, s int, rt int) uint32 {
+ return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
+}
+
const (
LFROM = 1 << 0
LTO = 1 << 1
/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
{AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
{AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
-
- // TODO: these don't work properly.
- // { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0},
- // { AMOVD, C_ADDCON, C_NONE, C_REG, 2, 4, 0 , 0},
{AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
{AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
+ {AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
+ {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
{AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
{AMOVD, C_AACON, C_NONE, C_NONE, C_REG, 4, 4, REGFROM, 0, 0},
{AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
{AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
{AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
- {AMOVW, C_VCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
{AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0},
- {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
{AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, 0, 0},
{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
return false
}
+func isANDWop(op obj.As) bool {
+ switch op {
+ case AANDW, AORRW, AEORW, AANDSW, ATSTW,
+ ABICW, AEONW, AORNW, ABICSW:
+ return true
+ }
+ return false
+}
+
+func isADDWop(op obj.As) bool {
+ switch op {
+ case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
+ return true
+ }
+ return false
+}
+
func isRegShiftOrExt(a *obj.Addr) bool {
return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0
}
return C_GOK
}
+// con32class reclassifies the constant of 32-bit instruction. Becuase the constant type is 32-bit,
+// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
+func (c *ctxt7) con32class(a *obj.Addr) int {
+ v := uint32(a.Offset)
+ if v == 0 {
+ return C_ZCON
+ }
+ if isaddcon(int64(v)) {
+ if v <= 0xFFF {
+ if isbitcon(uint64(v)) {
+ return C_ABCON0
+ }
+ return C_ADDCON0
+ }
+ if isbitcon(uint64(v)) {
+ return C_ABCON
+ }
+ return C_ADDCON
+ }
+
+ t := movcon(int64(v))
+ if t >= 0 {
+ if isbitcon(uint64(v)) {
+ return C_MBCON
+ }
+ return C_MOVCON
+ }
+
+ t = movcon(int64(^v))
+ if t >= 0 {
+ if isbitcon(uint64(v)) {
+ return C_MBCON
+ }
+ return C_MOVCON
+ }
+
+ if isbitcon(uint64(v)) {
+ return C_BITCON
+ }
+
+ if 0 <= v && v <= 0xffffff {
+ return C_ADDCON2
+ }
+ return C_LCON
+}
+
func (c *ctxt7) aclass(a *obj.Addr) int {
switch a.Type {
case obj.TYPE_NONE:
if isbitcon(uint64(v)) {
return C_ABCON
}
+ if movcon(v) >= 0 {
+ return C_AMCON
+ }
+ if movcon(^v) >= 0 {
+ return C_AMCON
+ }
return C_ADDCON
}
}
a1 = a0 + 1
p.From.Class = int8(a1)
+ // more specific classification of 32-bit integers
+ if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
+ if p.As == AMOVW || isADDWop(p.As) {
+ ra0 := c.con32class(&p.From)
+ // do not break C_ADDCON2 when S bit is set
+ if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
+ ra0 = C_LCON
+ }
+ a1 = ra0 + 1
+ p.From.Class = int8(a1)
+ }
+ if isANDWop(p.As) {
+ switch p.As {
+ case AANDW, AORRW, AEORW, AANDSW, ATSTW:
+ // For 32-bit logical instruction with constant,
+ // rewrite the high 32-bit to be a copy of the low
+ // 32-bit, so that the BITCON test can be shared
+ // for both 32-bit and 64-bit.
+ if a0 == C_BITCON {
+ break
+ }
+ fallthrough
+ default:
+ a1 = c.con32class(&p.From) + 1
+ p.From.Class = int8(a1)
+ }
+ }
+ }
}
a1--
}
case C_ADDCON:
- if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON {
+ if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
return true
}
}
case C_MOVCON:
- if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 {
+ if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
return true
}
}
case C_LCON:
- if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 {
+ if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
return true
}
if r == 0 {
r = rt
}
- o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From)) & 0x000fff, r, rt)
- o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From)) & 0xfff000, rt, rt)
+ o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
+ o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
case 50: /* sys/sysl */
o1 = c.opirr(p, p.As)
if p.Reg == REGTMP {
c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
}
- o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
+ if isADDWop(p.As) || isANDWop(p.As) {
+ o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
+ } else {
+ o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
+ }
rt := int(p.To.Reg)
if p.To.Type == obj.TYPE_NONE {
return o1
}
- r := 32
- if as == AMOVD {
- r = 64
+ if as == AMOVW {
+ d := uint32(a.Offset)
+ s := movcon(int64(d))
+ if s < 0 || 16*s >= 32 {
+ d = ^d
+ s = movcon(int64(d))
+ if s < 0 || 16*s >= 32 {
+ c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
+ }
+ o1 = c.opirr(p, AMOVNW)
+ } else {
+ o1 = c.opirr(p, AMOVZW)
+ }
+ o1 |= MOVCONST(int64(d), s, rt)
}
- d := a.Offset
- s := movcon(d)
- if s < 0 || s >= r {
- d = ^d
- s = movcon(d)
- if s < 0 || s >= r {
- c.ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p)
- }
- if as == AMOVD {
+ if as == AMOVD {
+ d := a.Offset
+ s := movcon(d)
+ if s < 0 || 16*s >= 64 {
+ d = ^d
+ s = movcon(d)
+ if s < 0 || 16*s >= 64 {
+ c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
+ }
o1 = c.opirr(p, AMOVN)
} else {
- o1 = c.opirr(p, AMOVNW)
- }
- } else {
- if as == AMOVD {
o1 = c.opirr(p, AMOVZ)
- } else {
- o1 = c.opirr(p, AMOVZW)
}
+ o1 |= MOVCONST(d, s, rt)
}
- o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
+
return o1
}