MOVH $-512, R3 // a739fe00
MOVB $-1, R4 // a749ffff
- MOVD $-2147483648, n-8(SP) // c0b180000000e3b0f0100024
- MOVW $-131072, n-8(SP) // c0b1fffe0000e3b0f0100050
- MOVH $-512, n-8(SP) // e544f010fe00
+ MOVD $32767, n-8(SP) // e548f0107fff
+ MOVD $-1, -524288(R1) // e3a010008071e548a000ffff
+ MOVW $32767, n-8(SP) // e54cf0107fff
+ MOVW $-32768, 4096(R2) // e3a020000171e54ca0008000
+ MOVH $512, n-8(SP) // e544f0100200
+ MOVH $-512, 524288(R3) // c0a10008000041aa3000e544a000fe00
MOVB $-1, n-8(SP) // 92fff010
+ MOVB $255, 4096(R4) // ebff40000152
+ MOVB $-128, -524288(R5) // eb8050008052
+ MOVB $1, -524289(R6) // c0a1fff7ffff41aa60009201a000
ADD R1, R2 // b9e81022
ADD R1, R2, R3 // b9e81032
}
func zeroAuto(pp *gc.Progs, n *gc.Node) {
- // Note: this code must not clobber any registers.
- p := pp.Prog(s390x.ACLEAR)
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = n.Type.Size()
- p.To.Type = obj.TYPE_MEM
- p.To.Name = obj.NAME_AUTO
- p.To.Reg = s390x.REGSP
- p.To.Offset = n.Xoffset
- p.To.Sym = n.Sym.Linksym()
+ // Note: this code must not clobber any registers or the
+ // condition code.
+ sym := n.Sym.Linksym()
+ size := n.Type.Size()
+ for i := int64(0); i < size; i += int64(gc.Widthptr) {
+ p := pp.Prog(s390x.AMOVD)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = 0
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_AUTO
+ p.To.Reg = s390x.REGSP
+ p.To.Offset = n.Xoffset + i
+ p.To.Sym = sym
+ }
}
func ginsnop(pp *gc.Progs) {
(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(off1+off2) -> (FMOVDstore [off1+off2] {sym} ptr val mem)
// Fold constants into stores.
-(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && validValAndOff(c,off) && int64(int16(c)) == c && ptr.Op != OpSB ->
+(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB ->
(MOVDstoreconst [makeValAndOff(c,off)] {sym} ptr mem)
-(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB ->
+(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB ->
(MOVWstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem)
-(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && ptr.Op != OpSB ->
+(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && isU12Bit(off) && ptr.Op != OpSB ->
(MOVHstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem)
-(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && ptr.Op != OpSB ->
+(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && is20Bit(off) && ptr.Op != OpSB ->
(MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem)
// Fold address offsets into constant stores.
-(MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
+(MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
(MOVDstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
-(MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
+(MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
(MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
-(MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
+(MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
(MOVHstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
-(MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
+(MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem) && is20Bit(ValAndOff(sc).Off()+off) ->
(MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
// We need to fold MOVDaddr into the MOVx ops so that the live variable analysis knows
(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
(FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
-(MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
+// Cannot store constant to SB directly (no 'move relative long immediate' instructions).
+(MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
(MOVDstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
-(MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
+(MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
(MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
-(MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
+(MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
(MOVHstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
-(MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
+(MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
(MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
// generating indexed loads and stores
-> (XORWload <t> [off] {sym} x ptr mem)
// Combine constant stores into larger (unaligned) stores.
-// It doesn't work to global data (based on SB),
-// because STGRL doesn't support unaligned address
+// Avoid SB because constant stores to relative offsets are
+// emulated by the assembler and also can't handle unaligned offsets.
(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
&& p.Op != OpSB
&& x.Uses == 1
&& x.Uses == 1
&& ValAndOff(a).Off() + 2 == ValAndOff(c).Off()
&& clobber(x)
- -> (MOVWstoreconst [makeValAndOff(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16, ValAndOff(a).Off())] {s} p mem)
+ -> (MOVWstore [ValAndOff(a).Off()] {s} p (MOVDconst [int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))]) mem)
(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
&& p.Op != OpSB
&& x.Uses == 1
// For storeconst ops, the AuxInt field encodes both
// the value to store and an address offset of the store.
// Cast AuxInt to a ValAndOff to extract Val and Off fields.
- {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
- {name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
- {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
- {name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
+ {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
+ {name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
+ {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
+ {name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
{name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"},
name: "MOVBstoreconst",
auxType: auxSymValAndOff,
argLen: 2,
- clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymWrite,
asm: s390x.AMOVB,
name: "MOVHstoreconst",
auxType: auxSymValAndOff,
argLen: 2,
- clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymWrite,
asm: s390x.AMOVH,
name: "MOVWstoreconst",
auxType: auxSymValAndOff,
argLen: 2,
- clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymWrite,
asm: s390x.AMOVW,
name: "MOVDstoreconst",
auxType: auxSymValAndOff,
argLen: 2,
- clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymWrite,
asm: s390x.AMOVD,
return n == int64(int16(n))
}
+// isU12Bit reports whether n can be represented as an unsigned 12 bit integer.
+func isU12Bit(n int64) bool {
+ return 0 <= n && n < (1<<12)
+}
+
// isU16Bit reports whether n can be represented as an unsigned 16 bit integer.
func isU16Bit(n int64) bool {
return n == int64(uint16(n))
return true
}
// match: (MOVBstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: validOff(off) && ptr.Op != OpSB
+ // cond: is20Bit(off) && ptr.Op != OpSB
// result: (MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem)
for {
off := v.AuxInt
}
c := v_1.AuxInt
mem := v.Args[2]
- if !(validOff(off) && ptr.Op != OpSB) {
+ if !(is20Bit(off) && ptr.Op != OpSB) {
break
}
v.reset(OpS390XMOVBstoreconst)
}
func rewriteValueS390X_OpS390XMOVBstoreconst_0(v *Value) bool {
// match: (MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem)
- // cond: ValAndOff(sc).canAdd(off)
+ // cond: is20Bit(ValAndOff(sc).Off()+off)
// result: (MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
for {
sc := v.AuxInt
off := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(ValAndOff(sc).canAdd(off)) {
+ if !(is20Bit(ValAndOff(sc).Off() + off)) {
break
}
v.reset(OpS390XMOVBstoreconst)
return true
}
// match: (MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
- // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
// result: (MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
for {
sc := v.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
break
}
v.reset(OpS390XMOVBstoreconst)
return true
}
// match: (MOVDstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: validValAndOff(c,off) && int64(int16(c)) == c && ptr.Op != OpSB
+ // cond: is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB
// result: (MOVDstoreconst [makeValAndOff(c,off)] {sym} ptr mem)
for {
off := v.AuxInt
}
c := v_1.AuxInt
mem := v.Args[2]
- if !(validValAndOff(c, off) && int64(int16(c)) == c && ptr.Op != OpSB) {
+ if !(is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB) {
break
}
v.reset(OpS390XMOVDstoreconst)
}
func rewriteValueS390X_OpS390XMOVDstoreconst_0(v *Value) bool {
// match: (MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem)
- // cond: ValAndOff(sc).canAdd(off)
+ // cond: isU12Bit(ValAndOff(sc).Off()+off)
// result: (MOVDstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
for {
sc := v.AuxInt
off := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(ValAndOff(sc).canAdd(off)) {
+ if !(isU12Bit(ValAndOff(sc).Off() + off)) {
break
}
v.reset(OpS390XMOVDstoreconst)
return true
}
// match: (MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
- // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
// result: (MOVDstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
for {
sc := v.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
break
}
v.reset(OpS390XMOVDstoreconst)
return true
}
// match: (MOVHstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: validOff(off) && ptr.Op != OpSB
+ // cond: isU12Bit(off) && ptr.Op != OpSB
// result: (MOVHstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem)
for {
off := v.AuxInt
}
c := v_1.AuxInt
mem := v.Args[2]
- if !(validOff(off) && ptr.Op != OpSB) {
+ if !(isU12Bit(off) && ptr.Op != OpSB) {
break
}
v.reset(OpS390XMOVHstoreconst)
return false
}
func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ types := &b.Func.Config.Types
+ _ = types
// match: (MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem)
- // cond: ValAndOff(sc).canAdd(off)
+ // cond: isU12Bit(ValAndOff(sc).Off()+off)
// result: (MOVHstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
for {
sc := v.AuxInt
off := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(ValAndOff(sc).canAdd(off)) {
+ if !(isU12Bit(ValAndOff(sc).Off() + off)) {
break
}
v.reset(OpS390XMOVHstoreconst)
return true
}
// match: (MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
- // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
// result: (MOVHstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
for {
sc := v.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
break
}
v.reset(OpS390XMOVHstoreconst)
}
// match: (MOVHstoreconst [c] {s} p x:(MOVHstoreconst [a] {s} p mem))
// cond: p.Op != OpSB && x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x)
- // result: (MOVWstoreconst [makeValAndOff(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16, ValAndOff(a).Off())] {s} p mem)
+ // result: (MOVWstore [ValAndOff(a).Off()] {s} p (MOVDconst [int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))]) mem)
for {
c := v.AuxInt
s := v.Aux
if !(p.Op != OpSB && x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) {
break
}
- v.reset(OpS390XMOVWstoreconst)
- v.AuxInt = makeValAndOff(ValAndOff(c).Val()&0xffff|ValAndOff(a).Val()<<16, ValAndOff(a).Off())
+ v.reset(OpS390XMOVWstore)
+ v.AuxInt = ValAndOff(a).Off()
v.Aux = s
v.AddArg(p)
+ v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, types.UInt64)
+ v0.AuxInt = int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))
+ v.AddArg(v0)
v.AddArg(mem)
return true
}
return true
}
// match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB
+ // cond: is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB
// result: (MOVWstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem)
for {
off := v.AuxInt
}
c := v_1.AuxInt
mem := v.Args[2]
- if !(validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB) {
+ if !(is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB) {
break
}
v.reset(OpS390XMOVWstoreconst)
types := &b.Func.Config.Types
_ = types
// match: (MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem)
- // cond: ValAndOff(sc).canAdd(off)
+ // cond: isU12Bit(ValAndOff(sc).Off()+off)
// result: (MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
for {
sc := v.AuxInt
off := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(ValAndOff(sc).canAdd(off)) {
+ if !(isU12Bit(ValAndOff(sc).Off() + off)) {
break
}
v.reset(OpS390XMOVWstoreconst)
return true
}
// match: (MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
- // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
+ // cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
// result: (MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
for {
sc := v.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
- if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
+ if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
break
}
v.reset(OpS390XMOVWstoreconst)
Optab{AMOVBZ, C_DCON, C_NONE, C_NONE, C_REG, 3, 0},
// store constant
- Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
- Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
- Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
- Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
- Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
- Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
- Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
- Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
- Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
- Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
- Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
- Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
- Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
- Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
- Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVD, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVW, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVWZ, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
+ Optab{AMOVD, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVW, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVWZ, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
+ Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
// store
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, REGSP},
v := c.regoff(&p.From)
d := c.regoff(&p.To)
r := p.To.Reg
- x := p.To.Index
+ if p.To.Index != 0 {
+ c.ctxt.Diag("cannot use index register")
+ }
if r == 0 {
r = o.param
}
- if int32(int16(v)) == v && x == 0 {
- if d < 0 || d >= DISP12 {
- if r == REGTMP || r == REGTMP2 {
- zRIL(_a, op_AGFI, uint32(r), uint32(d), asm)
+ var opcode uint32
+ switch p.As {
+ case AMOVD:
+ opcode = op_MVGHI
+ case AMOVW, AMOVWZ:
+ opcode = op_MVHI
+ case AMOVH, AMOVHZ:
+ opcode = op_MVHHI
+ case AMOVB, AMOVBZ:
+ opcode = op_MVI
+ }
+ if d < 0 || d >= DISP12 {
+ if r == REGTMP {
+ c.ctxt.Diag("displacement must be in range [0, 4096) to use %v", r)
+ }
+ if d >= -DISP20/2 && d < DISP20/2 {
+ if opcode == op_MVI {
+ opcode = op_MVIY
} else {
- zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
- zRRE(op_AGR, REGTMP, uint32(r), asm)
+ zRXY(op_LAY, uint32(REGTMP), 0, uint32(r), uint32(d), asm)
r = REGTMP
+ d = 0
}
- d = 0
- }
- var opcode uint32
- switch p.As {
- case AMOVD:
- opcode = op_MVGHI
- case AMOVW, AMOVWZ:
- opcode = op_MVHI
- case AMOVH, AMOVHZ:
- opcode = op_MVHHI
- case AMOVB, AMOVBZ:
- opcode = op_MVI
- }
- if opcode == op_MVI {
- zSI(opcode, uint32(v), uint32(r), uint32(d), asm)
} else {
- zSIL(opcode, uint32(r), uint32(d), uint32(v), asm)
- }
- } else {
- zRIL(_a, op_LGFI, REGTMP2, uint32(v), asm)
- if d < -DISP20/2 || d >= DISP20/2 {
- if r == REGTMP {
- zRIL(_a, op_AGFI, REGTMP, uint32(d), asm)
- } else {
- zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
- if x != 0 {
- zRRE(op_AGR, REGTMP, uint32(x), asm)
- }
- x = REGTMP
- }
+ zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
+ zRX(op_LA, REGTMP, REGTMP, uint32(r), 0, asm)
+ r = REGTMP
d = 0
}
- zRXY(c.zopstore(p.As), REGTMP2, uint32(x), uint32(r), uint32(d), asm)
- }
-
- case 73: // mov $constant addr (including relocation)
- v := c.regoff(&p.From)
- d := c.regoff(&p.To)
- a := uint32(0)
- if d&1 != 0 {
- d -= 1
- a = 1
}
- zRIL(_b, op_LARL, REGTMP, uint32(d), asm)
- c.addrilreloc(p.To.Sym, int64(d))
- if int32(int16(v)) == v {
- var opcode uint32
- switch p.As {
- case AMOVD:
- opcode = op_MVGHI
- case AMOVW, AMOVWZ:
- opcode = op_MVHI
- case AMOVH, AMOVHZ:
- opcode = op_MVHHI
- case AMOVB, AMOVBZ:
- opcode = op_MVI
- }
- if opcode == op_MVI {
- zSI(opcode, uint32(v), REGTMP, a, asm)
- } else {
- zSIL(opcode, REGTMP, a, uint32(v), asm)
- }
- } else {
- zRIL(_a, op_LGFI, REGTMP2, uint32(v), asm)
- zRXY(c.zopstore(p.As), REGTMP2, 0, REGTMP, a, asm)
+ switch opcode {
+ case op_MVI:
+ zSI(opcode, uint32(v), uint32(r), uint32(d), asm)
+ case op_MVIY:
+ zSIY(opcode, uint32(v), uint32(r), uint32(d), asm)
+ default:
+ zSIL(opcode, uint32(r), uint32(d), uint32(v), asm)
}
case 74: // mov reg addr (including relocation)