feat(asm): encode the amd64 and loong64 tails of the corpus testdata
Assisted-by: GLM 5.3
This commit is contained in:
@@ -831,3 +831,230 @@ TEXT ·atoms(SB), NOSPLIT, $0
|
||||
0x4C000020,
|
||||
)
|
||||
}
|
||||
|
||||
// TestLOONG64_llacqScrel pins the acquire/release LL/SC pair. The oracle
|
||||
// words come from GOARCH=loong64 go tool objdump and the toolchain's own
|
||||
// loong64enc1.s golden bytes.
|
||||
func TestLOONG64_llacqScrel(t *testing.T) {
|
||||
fn := firstTextLOONG64(t, `#include "textflag.h"
|
||||
TEXT ·llsc(SB), NOSPLIT, $0
|
||||
LLACQW (R5), R4
|
||||
LLACQV (R5), R4
|
||||
SCRELW R4, (R6)
|
||||
SCRELV R4, (R6)
|
||||
RET
|
||||
`)
|
||||
code := assembleLOONG64Helper(t, fn)
|
||||
wantWords(t, code,
|
||||
0x385780A4, // ll.acq.w r4, r5
|
||||
0x385788A4, // ll.acq.d r4, r5
|
||||
0x385784C4, // sc.rel.w r4, r6
|
||||
0x38578CC4, // sc.rel.d r4, r6
|
||||
0x4C000020,
|
||||
)
|
||||
// The toolchain accepts the zero-offset memory form alone.
|
||||
for i, src := range []string{
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
LLACQW 4(R5), R4
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
SCRELV R4, 8(R6)
|
||||
RET
|
||||
`,
|
||||
} {
|
||||
fn := firstTextLOONG64(t, src)
|
||||
if _, _, _, _, _, err := assembleLOONG64(fn); err == nil {
|
||||
t.Errorf("case %d: expected an error, got none", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestLOONG64_vmovqSuffixed pins the element-broadcast and element-move
|
||||
// VMOVQ/XVMOVQ forms, with the oracle words lifted verbatim from the
|
||||
// toolchain's loong64enc1.s.
|
||||
func TestLOONG64_vmovqSuffixed(t *testing.T) {
|
||||
fn := firstTextLOONG64(t, `#include "textflag.h"
|
||||
TEXT ·vmovq(SB), NOSPLIT, $0
|
||||
VMOVQ V1.B[3], V9.B16
|
||||
VMOVQ V2.H[2], V8.H8
|
||||
VMOVQ V3.W[1], V7.W4
|
||||
VMOVQ V4.V[0], V6.V2
|
||||
XVMOVQ X0, X31.B32
|
||||
XVMOVQ X1, X30.H16
|
||||
XVMOVQ X2, X29.W8
|
||||
XVMOVQ X3, X28.V4
|
||||
XVMOVQ X3, X27.Q2
|
||||
XVMOVQ X0, X31.W[7]
|
||||
XVMOVQ X1, X29.W[0]
|
||||
XVMOVQ X3, X28.V[3]
|
||||
XVMOVQ X4, X27.V[0]
|
||||
XVMOVQ X31.W[7], X0
|
||||
XVMOVQ X29.W[0], X1
|
||||
XVMOVQ X28.V[3], X8
|
||||
XVMOVQ X27.V[0], X9
|
||||
RET
|
||||
`)
|
||||
code := assembleLOONG64Helper(t, fn)
|
||||
wantWords(t, code,
|
||||
0x72F78C29, // vreplvei.b v9, v1, 3
|
||||
0x72F7C848, // vreplvei.h v8, v2, 2
|
||||
0x72F7E467, // vreplvei.w v7, v3, 1
|
||||
0x72F7F086, // vreplvei.d v6, v4, 0
|
||||
0x7707001F, // xvreplve0.b x31, x0
|
||||
0x7707803E, // xvreplve0.h x30, x1
|
||||
0x7707C05D, // xvreplve0.w x29, x2
|
||||
0x7707E07C, // xvreplve0.d x28, x3
|
||||
0x7707F07B, // xvreplve0.q x27, x3
|
||||
0x76FFDC1F, // xvinsve0.w x31, x0, 7
|
||||
0x76FFC03D, // xvinsve0.w x29, x1, 0
|
||||
0x76FFEC7C, // xvinsve0.d x28, x3, 3
|
||||
0x76FFE09B, // xvinsve0.d x27, x4, 0
|
||||
0x7703DFE0, // xvpickve.w x0, x31, 7
|
||||
0x7703C3A1, // xvpickve.w x1, x29, 0
|
||||
0x7703EF88, // xvpickve.d x8, x28, 3
|
||||
0x7703E369, // xvpickve.d x9, x27, 0
|
||||
0x4C000020,
|
||||
)
|
||||
// The rejected shapes: a width mismatch between the element and the
|
||||
// arrangement, an element index past the lane count, a wrong-bank
|
||||
// vreplvei and an arrangement the LASX bank does not spell.
|
||||
for i, src := range []string{
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
VMOVQ V1.H[3], V9.B16
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
VMOVQ V1.B[16], V9.B16
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
XVMOVQ X1.B[3], X9.B32
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
XVMOVQ X0, X31.B16
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
XVMOVQ X0, X31.W[8]
|
||||
RET
|
||||
`,
|
||||
} {
|
||||
fn := firstTextLOONG64(t, src)
|
||||
if _, _, _, _, _, err := assembleLOONG64(fn); err == nil {
|
||||
t.Errorf("case %d: expected an error, got none", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestLOONG64_parityFixes pins the operand forms whose encodings were found
|
||||
// diverging from the toolchain by the loong64enc1.s differential: the
|
||||
// $off(reg) address immediate (addi.d), the SCQ operand order, the scaled
|
||||
// vldrepl offsets (with their field masks), the XVSEQB/XVSEQV immediate
|
||||
// opcodes and the zero-register base the toolchain gives FP-relative
|
||||
// VMOVQ/XVMOVQ memory operands. Golden words from loong64enc1.s.
|
||||
func TestLOONG64_parityFixes(t *testing.T) {
|
||||
fn := firstTextLOONG64(t, `#include "textflag.h"
|
||||
TEXT ·parity(SB), NOSPLIT, $0-32
|
||||
MOVW $4(R4), R5
|
||||
MOVV $4(R4), R5
|
||||
MOVW $65536(R4), R5
|
||||
MOVW $-4096(R4), R5
|
||||
SCQ R4, R5, (R6)
|
||||
VMOVQ 2(R4), V1.H8
|
||||
VMOVQ -6(R4), V1.H8
|
||||
VMOVQ -12(R4), V2.W4
|
||||
VMOVQ -16(R4), V3.V2
|
||||
XVMOVQ -10(R4), X1.H16
|
||||
XVSEQB $0, X2, X4
|
||||
XVSEQH $3, X2, X4
|
||||
XVSEQW $12, X2, X4
|
||||
XVSEQV $15, X2, X4
|
||||
XVSEQV $-15, X2, X4
|
||||
VMOVQ V2, y+16(FP)
|
||||
VMOVQ y+16(FP), V2
|
||||
VMOVQ V2, x+2030(FP)
|
||||
XVMOVQ X6, y+16(FP)
|
||||
RET
|
||||
`)
|
||||
code := assembleLOONG64Helper(t, fn)
|
||||
wantWords(t, code,
|
||||
0x02C01085, // addi.d $4, r4, r5
|
||||
0x02C01085, // addi.d $4, r4, r5 (MOVW keeps the 64-bit addi.d)
|
||||
0x1400021E, // lu12i.w $16, r30
|
||||
0x038003DE, // ori $0, r30, r30
|
||||
0x0010F885, // add.d r5, r4, r30
|
||||
0x15FFFFFE, // lu12i.w $-1, r30
|
||||
0x038003DE, // ori $0, r30, r30
|
||||
0x0010F885, // add.d r5, r4, r30
|
||||
0x385714C4, // sc.q r4, r5, (r6): middle<<10 | base<<5 | first
|
||||
0x30400481, // vldrepl.h v1, 2(r4)
|
||||
0x305FF481, // vldrepl.h v1, -6(r4)
|
||||
0x302FF482, // vldrepl.w v2, -12(r4)
|
||||
0x3017F883, // vldrepl.d v3, -16(r4)
|
||||
0x325FEC81, // xvldrepl.h x1, -10(r4)
|
||||
0x76800044, // xvseqi.b x4, x2, 0
|
||||
0x76808C44, // xvseqi.h x4, x2, 3
|
||||
0x76813044, // xvseqi.w x4, x2, 12
|
||||
0x7681BC44, // xvseqi.d x4, x2, 15
|
||||
0x7681C444, // xvseqi.d x4, x2, -15
|
||||
0x2C406002, // vst v2, 24(r0): FP-relative keeps the zero base
|
||||
0x2C006002, // vld v2, 24(r0)
|
||||
0x2C5FD802, // vst v2, 2038(r0)
|
||||
0x2CC06006, // xvst x6, 24(r0)
|
||||
0x4C000020,
|
||||
)
|
||||
// Misaligned vldrepl offsets are rejected, as the toolchain does.
|
||||
for i, src := range []string{
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
VMOVQ 3(R4), V1.H8
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
MOVW $4(R4), F1
|
||||
RET
|
||||
`,
|
||||
} {
|
||||
fn := firstTextLOONG64(t, src)
|
||||
if _, _, _, _, _, err := assembleLOONG64(fn); err == nil {
|
||||
t.Errorf("case %d: expected an error, got none", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestLOONG64_bytePseudo pins the BYTE literal-data pseudo-op, which the
|
||||
// loong64 toolchain does not spell but the arm64 and riscv64 encoders of
|
||||
// this package already accept for byte-exact data layout (a superset
|
||||
// spelling, shippable via the goobj path).
|
||||
func TestLOONG64_bytePseudo(t *testing.T) {
|
||||
fn := firstTextLOONG64(t, `#include "textflag.h"
|
||||
TEXT ·bytes(SB), NOSPLIT, $0
|
||||
BYTE $2
|
||||
BYTE $1; BYTE $0
|
||||
BYTE $255
|
||||
RET
|
||||
`)
|
||||
code := assembleLOONG64Helper(t, fn)
|
||||
// Four literal bytes, then RET (jirl r0, r1, 0); the trailing bytes pad
|
||||
// the final word the way any sub-word tail does.
|
||||
want := []byte{2, 1, 0, 0xFF, 0x20, 0x00, 0x00, 0x4C}
|
||||
if !bytes.Equal(code[:len(want)], want) {
|
||||
t.Errorf("bytes = % x, want % x", code, want)
|
||||
}
|
||||
for _, src := range []string{
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
BYTE $256
|
||||
RET
|
||||
`,
|
||||
`TEXT ·e(SB), NOSPLIT, $0
|
||||
BYTE $-1
|
||||
RET
|
||||
`,
|
||||
} {
|
||||
fn := firstTextLOONG64(t, src)
|
||||
if _, _, _, _, _, err := assembleLOONG64(fn); err == nil {
|
||||
t.Errorf("%q: expected an error, got none", src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user