NEGV R1, R2 // 0001102f
RET
+// MSA VMOVI
+ VMOVB $511, W0 // 7b0ff807
+ VMOVH $24, W23 // 7b20c5c7
+ VMOVW $-24, W15 // 7b5f43c7
+ VMOVD $-511, W31 // 7b700fc7
+
+ VMOVB (R0), W8 // 78000220
+ VMOVB 511(R3), W0 // 79ff1820
+ VMOVB -512(R12), W21 // 7a006560
+ VMOVH (R24), W12 // 7800c321
+ VMOVH 110(R19), W8 // 78379a21
+ VMOVH -70(R12), W3 // 7bdd60e1
+ VMOVW (R3), W31 // 78001fe2
+ VMOVW 64(R20), W16 // 7810a422
+ VMOVW -104(R17), W24 // 7be68e22
+ VMOVD (R3), W2 // 780018a3
+ VMOVD 128(R23), W19 // 7810bce3
+ VMOVD -256(R31), W0 // 7be0f823
+
+ VMOVB W8, (R0) // 78000224
+ VMOVB W0, 511(R3) // 79ff1824
+ VMOVB W21, -512(R12) // 7a006564
+ VMOVH W12, (R24) // 7800c325
+ VMOVH W8, 110(R19) // 78379a25
+ VMOVH W3, -70(R12) // 7bdd60e5
+ VMOVW W31, (R3) // 78001fe6
+ VMOVW W16, 64(R20) // 7810a426
+ VMOVW W24, -104(R17) // 7be68e26
+ VMOVD W2, (R3) // 780018a7
+ VMOVD W19, 128(R23) // 7810bce7
+ VMOVD W0, -256(R31) // 7be0f827
+ RET
+
// END
//
// LEND comma // asm doesn't support the trailing comma.
{ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
{ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
+ {AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
+ {AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
+ {AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
+ {AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
+
{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
return C_FCREG
}
+ if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
+ return C_WREG
+ }
if a.Reg == REG_LO {
return C_LO
}
case AMOVVL:
opset(AMOVVR, r0)
+ case AVMOVB:
+ opset(AVMOVH, r0)
+ opset(AVMOVW, r0)
+ opset(AVMOVD, r0)
+
case AMOVW,
AMOVD,
AMOVF,
return op | i&0x3FFFFFF
}
+func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
+ return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
+}
+
+func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
+ return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
+}
+
func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 := uint32(0)
o2 := uint32(0)
rel.Sym = p.From.Sym
rel.Add = p.From.Offset
rel.Type = objabi.R_ADDRMIPSTLS
+
+ case 56: /* vmov{b,h,w,d} $scon, wr */
+
+ v := c.regoff(&p.From)
+ o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
+
+ case 57: /* vld $soreg, wr */
+ v := c.lsoffset(p.As, c.regoff(&p.From))
+ o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
+
+ case 58: /* vst wr, $soreg */
+ v := c.lsoffset(p.As, c.regoff(&p.To))
+ o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
}
out[0] = o1
}
return false
}
+
+// MSA Two-bit Data Format Field Encoding
+func (c *ctxt0) twobitdf(a obj.As) uint32 {
+ switch a {
+ case AVMOVB:
+ return 0
+ case AVMOVH:
+ return 1
+ case AVMOVW:
+ return 2
+ case AVMOVD:
+ return 3
+ default:
+ c.ctxt.Diag("unsupported data format %v", a)
+ }
+ return 0
+}
+
+// MSA Load/Store offset have to be multiple of size of data format
+func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
+ var mod int32
+ switch a {
+ case AVMOVB:
+ mod = 1
+ case AVMOVH:
+ mod = 2
+ case AVMOVW:
+ mod = 4
+ case AVMOVD:
+ mod = 8
+ default:
+ c.ctxt.Diag("unsupported instruction:%v", a)
+ }
+
+ if o%mod != 0 {
+ c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
+ }
+
+ return o / mod
+}