Skip to content

Commit 68fea52

Browse files
mengzhuocherrymui
authored andcommitted
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing new sets of register W0-W31 (C_WREG) and 12 new instructions: * VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate) * VMOV{B,H,W,D} SOREG, WREG (Vector load) * VMOV{B,H,W,D} WREG, SOREG (Vector store) Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d Reviewed-on: https://go-review.googlesource.com/c/go/+/215723 Run-TryBot: Meng Zhuo <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 588ee79 commit 68fea52

File tree

8 files changed

+171
-0
lines changed

8 files changed

+171
-0
lines changed

src/cmd/asm/internal/arch/arch.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ func archMips64(linkArch *obj.LinkArch) *Arch {
484484
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
485485
register[obj.Rconv(i)] = int16(i)
486486
}
487+
for i := mips.REG_W0; i <= mips.REG_W31; i++ {
488+
register[obj.Rconv(i)] = int16(i)
489+
}
487490
register["HI"] = mips.REG_HI
488491
register["LO"] = mips.REG_LO
489492
// Pseudo-registers.
@@ -501,6 +504,7 @@ func archMips64(linkArch *obj.LinkArch) *Arch {
501504
"FCR": true,
502505
"M": true,
503506
"R": true,
507+
"W": true,
504508
}
505509

506510
instructions := make(map[string]obj.As)

src/cmd/asm/internal/arch/mips.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ func mipsRegisterNumber(name string, n int16) (int16, bool) {
6363
if 0 <= n && n <= 31 {
6464
return mips.REG_R0 + n, true
6565
}
66+
case "W":
67+
if 0 <= n && n <= 31 {
68+
return mips.REG_W0 + n, true
69+
}
6670
}
6771
return 0, false
6872
}

src/cmd/asm/internal/asm/testdata/mips64.s

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,39 @@ label4:
583583
NEGV R1, R2 // 0001102f
584584
RET
585585

586+
// MSA VMOVI
587+
VMOVB $511, W0 // 7b0ff807
588+
VMOVH $24, W23 // 7b20c5c7
589+
VMOVW $-24, W15 // 7b5f43c7
590+
VMOVD $-511, W31 // 7b700fc7
591+
592+
VMOVB (R0), W8 // 78000220
593+
VMOVB 511(R3), W0 // 79ff1820
594+
VMOVB -512(R12), W21 // 7a006560
595+
VMOVH (R24), W12 // 7800c321
596+
VMOVH 110(R19), W8 // 78379a21
597+
VMOVH -70(R12), W3 // 7bdd60e1
598+
VMOVW (R3), W31 // 78001fe2
599+
VMOVW 64(R20), W16 // 7810a422
600+
VMOVW -104(R17), W24 // 7be68e22
601+
VMOVD (R3), W2 // 780018a3
602+
VMOVD 128(R23), W19 // 7810bce3
603+
VMOVD -256(R31), W0 // 7be0f823
604+
605+
VMOVB W8, (R0) // 78000224
606+
VMOVB W0, 511(R3) // 79ff1824
607+
VMOVB W21, -512(R12) // 7a006564
608+
VMOVH W12, (R24) // 7800c325
609+
VMOVH W8, 110(R19) // 78379a25
610+
VMOVH W3, -70(R12) // 7bdd60e5
611+
VMOVW W31, (R3) // 78001fe6
612+
VMOVW W16, 64(R20) // 7810a426
613+
VMOVW W24, -104(R17) // 7be68e26
614+
VMOVD W2, (R3) // 780018a7
615+
VMOVD W19, 128(R23) // 7810bce7
616+
VMOVD W0, -256(R31) // 7be0f827
617+
RET
618+
586619
// END
587620
//
588621
// LEND comma // asm doesn't support the trailing comma.

src/cmd/internal/obj/mips/a.out.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const (
4343
NSYM = 50
4444
NREG = 32 /* number of general registers */
4545
NFREG = 32 /* number of floating point registers */
46+
NWREG = 32 /* number of MSA registers */
4647
)
4748

4849
const (
@@ -180,6 +181,41 @@ const (
180181
REG_FCR30
181182
REG_FCR31
182183

184+
// MSA registers
185+
// The lower bits of W registers are alias to F registers
186+
REG_W0 // must be a multiple of 32
187+
REG_W1
188+
REG_W2
189+
REG_W3
190+
REG_W4
191+
REG_W5
192+
REG_W6
193+
REG_W7
194+
REG_W8
195+
REG_W9
196+
REG_W10
197+
REG_W11
198+
REG_W12
199+
REG_W13
200+
REG_W14
201+
REG_W15
202+
REG_W16
203+
REG_W17
204+
REG_W18
205+
REG_W19
206+
REG_W20
207+
REG_W21
208+
REG_W22
209+
REG_W23
210+
REG_W24
211+
REG_W25
212+
REG_W26
213+
REG_W27
214+
REG_W28
215+
REG_W29
216+
REG_W30
217+
REG_W31
218+
183219
REG_HI
184220
REG_LO
185221

@@ -217,6 +253,8 @@ func init() {
217253
f(REG_F0, REG_F31, 32) // For 32-bit MIPS, compiler only uses even numbered registers -- see cmd/compile/internal/ssa/gen/MIPSOps.go
218254
MIPSDWARFRegisters[REG_HI] = 64
219255
MIPSDWARFRegisters[REG_LO] = 65
256+
// The lower bits of W registers are alias to F registers
257+
f(REG_W0, REG_W31, 32)
220258
}
221259

222260
const (
@@ -243,6 +281,7 @@ const (
243281
C_FREG
244282
C_FCREG
245283
C_MREG /* special processor register */
284+
C_WREG /* MSA registers */
246285
C_HI
247286
C_LO
248287
C_ZCON
@@ -405,6 +444,12 @@ const (
405444
AMOVVF
406445
AMOVVD
407446

447+
/* MSA */
448+
AVMOVB
449+
AVMOVH
450+
AVMOVW
451+
AVMOVD
452+
408453
ALAST
409454

410455
// aliases
@@ -430,4 +475,7 @@ func init() {
430475
if REG_FCR0%32 != 0 {
431476
panic("REG_FCR0 is not a multiple of 32")
432477
}
478+
if REG_W0%32 != 0 {
479+
panic("REG_W0 is not a multiple of 32")
480+
}
433481
}

src/cmd/internal/obj/mips/anames.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/internal/obj/mips/anames0.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var cnames0 = []string{
1010
"FREG",
1111
"FCREG",
1212
"MREG",
13+
"WREG",
1314
"HI",
1415
"LO",
1516
"ZCON",

src/cmd/internal/obj/mips/asm0.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ var optab = []Optab{
377377
{ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
378378
{ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
379379

380+
{AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
381+
{AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
382+
{AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
383+
{AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
384+
380385
{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
381386
{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
382387
{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
@@ -556,6 +561,9 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
556561
if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
557562
return C_FCREG
558563
}
564+
if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
565+
return C_WREG
566+
}
559567
if a.Reg == REG_LO {
560568
return C_LO
561569
}
@@ -1029,6 +1037,11 @@ func buildop(ctxt *obj.Link) {
10291037
case AMOVVL:
10301038
opset(AMOVVR, r0)
10311039

1040+
case AVMOVB:
1041+
opset(AVMOVH, r0)
1042+
opset(AVMOVW, r0)
1043+
opset(AVMOVD, r0)
1044+
10321045
case AMOVW,
10331046
AMOVD,
10341047
AMOVF,
@@ -1121,6 +1134,14 @@ func OP_JMP(op uint32, i uint32) uint32 {
11211134
return op | i&0x3FFFFFF
11221135
}
11231136

1137+
func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
1138+
return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
1139+
}
1140+
1141+
func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
1142+
return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
1143+
}
1144+
11241145
func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
11251146
o1 := uint32(0)
11261147
o2 := uint32(0)
@@ -1629,6 +1650,19 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
16291650
rel.Sym = p.From.Sym
16301651
rel.Add = p.From.Offset
16311652
rel.Type = objabi.R_ADDRMIPSTLS
1653+
1654+
case 56: /* vmov{b,h,w,d} $scon, wr */
1655+
1656+
v := c.regoff(&p.From)
1657+
o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
1658+
1659+
case 57: /* vld $soreg, wr */
1660+
v := c.lsoffset(p.As, c.regoff(&p.From))
1661+
o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
1662+
1663+
case 58: /* vst wr, $soreg */
1664+
v := c.lsoffset(p.As, c.regoff(&p.To))
1665+
o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
16321666
}
16331667

16341668
out[0] = o1
@@ -2009,3 +2043,43 @@ func vshift(a obj.As) bool {
20092043
}
20102044
return false
20112045
}
2046+
2047+
// MSA Two-bit Data Format Field Encoding
2048+
func (c *ctxt0) twobitdf(a obj.As) uint32 {
2049+
switch a {
2050+
case AVMOVB:
2051+
return 0
2052+
case AVMOVH:
2053+
return 1
2054+
case AVMOVW:
2055+
return 2
2056+
case AVMOVD:
2057+
return 3
2058+
default:
2059+
c.ctxt.Diag("unsupported data format %v", a)
2060+
}
2061+
return 0
2062+
}
2063+
2064+
// MSA Load/Store offset have to be multiple of size of data format
2065+
func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
2066+
var mod int32
2067+
switch a {
2068+
case AVMOVB:
2069+
mod = 1
2070+
case AVMOVH:
2071+
mod = 2
2072+
case AVMOVW:
2073+
mod = 4
2074+
case AVMOVD:
2075+
mod = 8
2076+
default:
2077+
c.ctxt.Diag("unsupported instruction:%v", a)
2078+
}
2079+
2080+
if o%mod != 0 {
2081+
c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
2082+
}
2083+
2084+
return o / mod
2085+
}

src/cmd/internal/obj/mips/list0.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ func rconv(r int) string {
5959
if REG_FCR0 <= r && r <= REG_FCR31 {
6060
return fmt.Sprintf("FCR%d", r-REG_FCR0)
6161
}
62+
if REG_W0 <= r && r <= REG_W31 {
63+
return fmt.Sprintf("W%d", r-REG_W0)
64+
}
6265
if r == REG_HI {
6366
return "HI"
6467
}

0 commit comments

Comments
 (0)