Commit 60402856 authored by fanzha02's avatar fanzha02 Committed by Cherry Zhang

cmd/internal/obj/arm64: add support for a series of load/store with register offset instrucitons

The patch adds support for arm64 instructions LDRB, LDRH, LDRSB,
LDRSH, LDRSW, STR, STRB and STRH with register offset.

Test cases are also added.

Change-Id: I8d17fddd2963c0bc366e12b00bac49b93f3f0957
Reviewed-on: https://go-review.googlesource.com/91575Reviewed-by: 's avatarCherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent e0ac5f54
......@@ -107,6 +107,34 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVD (R2)(R6<<3), R4 // 447866f8
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
MOVBU (R3)(R9.UXTW), R8 // 68486938
MOVBU (R5)(R8), R10 // MOVBU (R5)(R8*1), R10 // aa686838
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
MOVHU (R1)(R2<<1), R5 // 25786278
MOVB (R9)(R3.UXTW), R6 // 2649a338
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
MOVH (R5)(R7.SXTX<<1), R18 // b2f8a778
MOVH (R8)(R4<<1), R10 // 0a79a478
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
MOVW (R2)(R5), R12 // MOVW (R2)(R5*1), R12 // 4c68a5b8
MOVD R5, (R2)(R6<<3) // 457826f8
MOVD R9, (R6)(R7.SXTX<<3) // c9f827f8
MOVD ZR, (R6)(R7.SXTX<<3) // dff827f8
MOVW R8, (R2)(R3.UXTW<<2) // 485823b8
MOVW R7, (R3)(R4.SXTW) // 67c824b8
MOVB R4, (R2)(R6.SXTX) // 44e82638
MOVB R8, (R3)(R9.UXTW) // 68482938
MOVB R10, (R5)(R8) // MOVB R10, (R5)(R8*1) // aa682838
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
MOVH R5, (R1)(R2<<1) // 25782278
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
MOVH R8, (R3)(R6.UXTW) // 68482678
MOVB (R29)(R30<<0), R14 // ae7bbe38
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
MOVB R4, (R2)(R6.SXTX) // 44e82638
// LTYPE1 imsr ',' spreg ','
// {
// outcode($1, &$2, $4, &nullgen);
......
......@@ -14,6 +14,8 @@ TEXT errors(SB),$0
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
MOVWU (R5)(R4.UXTW<<3), R10 // ERROR "invalid index shift amount"
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
MOVB (R5)(R4.SXTW<<5), R10 // ERROR "invalid index shift amount"
MOVH R5, (R6)(R2<<3) // ERROR "invalid index shift amount"
VLD1 (R8)(R13), [V2.B16] // ERROR "illegal combination"
VLD1 8(R9), [V2.B16] // ERROR "illegal combination"
VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination"
......
......@@ -448,6 +448,15 @@ var optab = []Optab{
/* load with shifted or extended register offset */
{AMOVD, C_ROFF, C_NONE, C_REG, 98, 4, 0, 0, 0},
{AMOVW, C_ROFF, C_NONE, C_REG, 98, 4, 0, 0, 0},
{AMOVH, C_ROFF, C_NONE, C_REG, 98, 4, 0, 0, 0},
{AMOVB, C_ROFF, C_NONE, C_REG, 98, 4, 0, 0, 0},
{AMOVBU, C_ROFF, C_NONE, C_REG, 98, 4, 0, 0, 0},
/* store with extended register offset */
{AMOVD, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
{AMOVW, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
{AMOVH, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
{AMOVB, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
/* pre/post-indexed/signed-offset load/store register pair
(unscaled, signed 10-bit quad-aligned and long offset) */
......@@ -2367,10 +2376,19 @@ func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
/* checkShiftAmount checks whether the index shift amount is valid */
/* for load with register offset instructions */
func (c *ctxt7) checkShiftAmount(p *obj.Prog, as obj.As) {
amount := (p.From.Index >> 5) & 7
switch as {
case AMOVWU:
func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
var amount int16
amount = (a.Index >> 5) & 7
switch p.As {
case AMOVB, AMOVBU:
if amount != 0 {
c.ctxt.Diag("invalid index shift amount: %v", p)
}
case AMOVH, AMOVHU:
if amount != 1 && amount != 0 {
c.ctxt.Diag("invalid index shift amount: %v", p)
}
case AMOVW, AMOVWU:
if amount != 2 && amount != 0 {
c.ctxt.Diag("invalid index shift amount: %v", p)
}
......@@ -2914,7 +2932,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
c.ctxt.Diag("REGTMP used in large offset store: %v", p)
}
o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
o2 = c.olsxrr(p, int32(c.opstrr(p, p.As)), int(p.From.Reg), r, REGTMP)
o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
case 31: /* movT L(R), R -> ldrT */
// if offset L can be split into hi+lo, and both fit into instructions, do
......@@ -4293,7 +4311,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
if p.From.Offset != 0 {
// extended or shifted offset register.
c.checkShiftAmount(p, p.As)
c.checkShiftAmount(p, &p.From)
o1 = c.opldrr(p, p.As, true)
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
} else {
......@@ -4303,10 +4321,23 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
}
o1 |= uint32(p.From.Reg&31) << 5
rt := int(p.To.Reg)
if p.To.Type == obj.TYPE_NONE {
rt = REGZERO
}
o1 |= uint32(rt & 31)
case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
if p.To.Offset != 0 {
// extended or shifted offset register.
c.checkShiftAmount(p, &p.To)
o1 = c.opstrr(p, p.As, true)
o1 |= uint32(p.To.Offset) /* includes reg, op, etc */
} else {
// (Rn)(Rm), no extension or shift.
o1 = c.opstrr(p, p.As, false)
o1 |= uint32(p.To.Index&31) << 16
}
o1 |= uint32(p.To.Reg&31) << 5
rf := int(p.From.Reg)
o1 |= uint32(rf & 31)
}
out[0] = o1
out[1] = o2
......@@ -5668,20 +5699,25 @@ func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
// for store instruction with register offset.
func (c *ctxt7) opstrr(p *obj.Prog, a obj.As) uint32 {
// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
OptionS := uint32(0x1a)
if extension {
OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
}
switch a {
case AMOVD:
return 0x1a<<10 | 0x1<<21 | 0x1f<<27
return OptionS<<10 | 0x1<<21 | 0x1f<<27
case AMOVW, AMOVWU:
return 0x1a<<10 | 0x1<<21 | 0x17<<27
return OptionS<<10 | 0x1<<21 | 0x17<<27
case AMOVH, AMOVHU:
return 0x1a<<10 | 0x1<<21 | 0x0f<<27
return OptionS<<10 | 0x1<<21 | 0x0f<<27
case AMOVB, AMOVBU:
return 0x1a<<10 | 0x1<<21 | 0x07<<27
return OptionS<<10 | 0x1<<21 | 0x07<<27
case AFMOVS:
return 0x1a<<10 | 0x1<<21 | 0x17<<27 | 1<<26
return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
case AFMOVD:
return 0x1a<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
}
c.ctxt.Diag("bad opstrr %v\n%v", a, p)
return 0
......
......@@ -35,10 +35,17 @@ Go Assembly for ARM64 Reference Manual
LDXPW (<Rn>), (<Rt1>, <Rt2>)
Loads two 32-bit words from memory, and writes them to Rt1 and Rt2.
MOVD|MOVW: Load Register (register offset)
MOVD|MOVW|MOVH|MOVHU|MOVB|MOVBU: Load Register (register offset)
MOVD (Rn)(Rm.UXTW<<3), Rt
MOVD (Rn)(Rm.SXTX), Rt
MOVD (Rn)(Rm<<3), Rt
MOVD (Rn)(Rm), Rt
MOVB|MOVBU (Rn)(Rm.UXTW), Rt
MOVD|MOVW|MOVH|MOVB: Stote Register (register offset)
MOVD Rt, (Rn)(Rm.UXTW<<3)
MOVD Rt, (Rn)(Rm.SXTX)
MOVD Rt, (Rn)(Rm)
PRFM: Prefetch Memory (immediate)
PRFM imm(Rn), <prfop>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment