1
0
mirror of https://github.com/golang/go synced 2024-11-17 01:54:53 -07:00

cmd/asm: refactor some encoding functions for load/store with immediate offset on arm64

Some of the current functions for encoding load/store with
immediate offset instructions, like opstr12(), opstr9(),
opldr12(), opldr9() and opldrpp(), etc., they have the same
code, so this patch refactors them and merges them into two
functions opstr() and opldr().

Change-Id: I60367f8b720b77c7ebe6d66905a950dcf7701836
Reviewed-on: https://go-review.googlesource.com/c/go/+/263479
Run-TryBot: fannie zhang <Fannie.Zhang@arm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: fannie zhang <Fannie.Zhang@arm.com>
This commit is contained in:
fanzha02 2020-10-16 18:35:30 +08:00 committed by fannie zhang
parent d8044a6744
commit 308ec220a2

View File

@ -205,12 +205,8 @@ func SYSHINT(x uint32) uint32 {
return SYSOP(0, 0, 3, 2, 0, x, 0x1F) return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
} }
func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 { func LDSTR(sz uint32, v uint32, opc uint32) uint32 {
return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22 return sz<<30 | 7<<27 | v<<26 | opc<<22
}
func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
} }
func LD2STR(o uint32) uint32 { func LD2STR(o uint32) uint32 {
@ -3392,10 +3388,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = int(o.param) r = int(o.param)
} }
if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg)) o1 = c.olsr9s(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
} else { } else {
v = int32(c.offsetshift(p, int64(v), int(o.a4))) v = int32(c.offsetshift(p, int64(v), int(o.a4)))
o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg)) o1 = c.olsr12u(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
} }
case 21: /* movT O(R),R -> ldrT */ case 21: /* movT O(R),R -> ldrT */
@ -3407,11 +3403,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = int(o.param) r = int(o.param)
} }
if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg)) o1 = c.olsr9s(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
} else { } else {
v = int32(c.offsetshift(p, int64(v), int(o.a1))) v = int32(c.offsetshift(p, int64(v), int(o.a1)))
//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg)) o1 = c.olsr12u(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
} }
case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
@ -3424,7 +3420,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
if v < -256 || v > 255 { if v < -256 || v > 255 {
c.ctxt.Diag("offset out of range [-255,254]: %v", p) c.ctxt.Diag("offset out of range [-255,254]: %v", p)
} }
o1 = c.opldrpp(p, p.As) o1 = c.opldr(p, p.As)
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 10 o1 |= 1 << 10
} else { } else {
@ -3442,7 +3438,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
if v < -256 || v > 255 { if v < -256 || v > 255 {
c.ctxt.Diag("offset out of range [-255,254]: %v", p) c.ctxt.Diag("offset out of range [-255,254]: %v", p)
} }
o1 = LD2STR(c.opldrpp(p, p.As)) o1 = c.opstr(p, p.As)
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 10 o1 |= 1 << 10
} else { } else {
@ -3594,7 +3590,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
} }
o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) o2 = c.olsr12u(p, int32(c.opstr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
break break
storeusepool: storeusepool:
@ -3638,7 +3634,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
} }
o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP) o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
break break
loadusepool: loadusepool:
@ -4127,7 +4123,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
rel.Sym = p.To.Sym rel.Sym = p.To.Sym
rel.Add = p.To.Offset rel.Add = p.To.Offset
rel.Type = objabi.R_ADDRARM64 rel.Type = objabi.R_ADDRARM64
o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg)) o3 = c.olsr12u(p, int32(c.opstr(p, p.As)), 0, REGTMP, int(p.From.Reg))
case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
@ -4138,7 +4134,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = p.From.Offset rel.Add = p.From.Offset
rel.Type = objabi.R_ADDRARM64 rel.Type = objabi.R_ADDRARM64
o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg)) o3 = c.olsr12u(p, int32(c.opldr(p, p.As)), 0, REGTMP, int(p.To.Reg))
case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
v := int32(c.regoff(&p.From)) v := int32(c.regoff(&p.From))
@ -4191,7 +4187,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
rel := obj.Addrel(c.cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(c.pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
@ -4204,7 +4200,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
rel := obj.Addrel(c.cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(c.pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
@ -4765,7 +4761,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
} }
} }
o1 = c.opldrpp(p, p.As) o1 = c.opirr(p, p.As)
o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31)) o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */ case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
@ -6106,8 +6102,12 @@ func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
case AVUSHLL2, AVUXTL2: case AVUSHLL2, AVUXTL2:
return 3<<29 | 15<<24 | 0x29<<10 return 3<<29 | 15<<24 | 0x29<<10
case AVXAR: case AVXAR:
return 0xCE<<24 | 1<<23 return 0xCE<<24 | 1<<23
case APRFM:
return 0xf9<<24 | 2<<22
} }
c.ctxt.Diag("%v: bad irr %v", p, a) c.ctxt.Diag("%v: bad irr %v", p, a)
@ -6502,7 +6502,7 @@ func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
} }
/* /*
* load/store register (unsigned immediate) C3.3.13 * load/store register (scaled 12-bit unsigned immediate) C3.3.13
* these produce 64-bit values (when there's an option) * these produce 64-bit values (when there's an option)
*/ */
func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 { func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
@ -6512,49 +6512,12 @@ func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
o |= (v & 0xFFF) << 10 o |= (v & 0xFFF) << 10
o |= int32(b&31) << 5 o |= int32(b&31) << 5
o |= int32(r & 31) o |= int32(r & 31)
o |= 1 << 24
return uint32(o) return uint32(o)
} }
func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
switch a {
case AMOVD:
return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
case AMOVW:
return LDSTR12U(2, 0, 2)
case AMOVWU:
return LDSTR12U(2, 0, 1)
case AMOVH:
return LDSTR12U(1, 0, 2)
case AMOVHU:
return LDSTR12U(1, 0, 1)
case AMOVB:
return LDSTR12U(0, 0, 2)
case AMOVBU:
return LDSTR12U(0, 0, 1)
case AFMOVS:
return LDSTR12U(2, 1, 1)
case AFMOVD:
return LDSTR12U(3, 1, 1)
}
c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
return 0
}
func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
return LD2STR(c.opldr12(p, a))
}
/* /*
* load/store register (unscaled immediate) C3.3.12 * load/store register (unscaled 9-bit signed immediate) C3.3.12
*/ */
func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 { func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
if v < -256 || v > 255 { if v < -256 || v > 255 {
@ -6566,76 +6529,48 @@ func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
return uint32(o) return uint32(o)
} }
func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 { // store(immediate)
switch a { // scaled 12-bit unsigned immediate offset.
case AMOVD: // unscaled 9-bit signed immediate offset.
return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ // pre/post-indexed store.
// and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
case AMOVW: func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 {
return LDSTR9S(2, 0, 2) return LD2STR(c.opldr(p, a))
case AMOVWU:
return LDSTR9S(2, 0, 1)
case AMOVH:
return LDSTR9S(1, 0, 2)
case AMOVHU:
return LDSTR9S(1, 0, 1)
case AMOVB:
return LDSTR9S(0, 0, 2)
case AMOVBU:
return LDSTR9S(0, 0, 1)
case AFMOVS:
return LDSTR9S(2, 1, 1)
case AFMOVD:
return LDSTR9S(3, 1, 1)
}
c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
return 0
} }
func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 { // load(immediate)
return LD2STR(c.opldr9(p, a)) // scaled 12-bit unsigned immediate offset.
} // unscaled 9-bit signed immediate offset.
// pre/post-indexed load.
func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 { // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AMOVD: case AMOVD:
return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
case AMOVW: case AMOVW:
return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 return LDSTR(2, 0, 2)
case AMOVWU: case AMOVWU:
return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 return LDSTR(2, 0, 1)
case AMOVH: case AMOVH:
return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 return LDSTR(1, 0, 2)
case AMOVHU: case AMOVHU:
return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 return LDSTR(1, 0, 1)
case AMOVB: case AMOVB:
return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22 return LDSTR(0, 0, 2)
case AMOVBU: case AMOVBU:
return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 return LDSTR(0, 0, 1)
case AFMOVS: case AFMOVS:
return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 return LDSTR(2, 1, 1)
case AFMOVD: case AFMOVD:
return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22 return LDSTR(3, 1, 1)
case APRFM:
return 0xf9<<24 | 2<<22
} }
c.ctxt.Diag("bad opldr %v\n%v", a, p) c.ctxt.Diag("bad opldr %v\n%v", a, p)