test(asm): pin the ADDV16 immediate family the toolchain assembles
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
a3eaa82f87
commit
f661c2fc78
2 files changed
+49
-1
No files matched your search
@@ -872,7 +872,10 @@ func encodeLOONG64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi loo
|
|||||||
|
|
||||||
case l64Firr16:
|
case l64Firr16:
|
||||||
// ADDV16: INSTR $imm, rd or INSTR $imm, rj, rd; the immediate must be
|
// ADDV16: INSTR $imm, rd or INSTR $imm, rj, rd; the immediate must be
|
||||||
// a multiple of 65536 and is shifted right by 16.
|
// a multiple of 65536 and is shifted right by 16. Both registers are
|
||||||
|
// general: the toolchain's class match refuses an F, V or X bank
|
||||||
|
// register here ("illegal combination ADDV16 ... FREG ..."), and the
|
||||||
|
// 5-bit numbering would otherwise encode it silently.
|
||||||
if len(ops) < 2 || !isImmOperand(ops[0]) {
|
if len(ops) < 2 || !isImmOperand(ops[0]) {
|
||||||
return nil, fmt.Errorf("%s expects an immediate operand", mnem)
|
return nil, fmt.Errorf("%s expects an immediate operand", mnem)
|
||||||
}
|
}
|
||||||
@@ -880,6 +883,11 @@ func encodeLOONG64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi loo
|
|||||||
if v&0xFFFF != 0 {
|
if v&0xFFFF != 0 {
|
||||||
return nil, fmt.Errorf("%s: the constant must be a multiple of 65536", mnem)
|
return nil, fmt.Errorf("%s: the constant must be a multiple of 65536", mnem)
|
||||||
}
|
}
|
||||||
|
for _, op := range ops[1:] {
|
||||||
|
if c := loong64RegClass(operandRegName(op)); c != l64ClsGR {
|
||||||
|
return nil, fmt.Errorf("%s: illegal combination: the registers must be general", mnem)
|
||||||
|
}
|
||||||
|
}
|
||||||
rd := l64Reg(ops[len(ops)-1])
|
rd := l64Reg(ops[len(ops)-1])
|
||||||
rj := rd
|
rj := rd
|
||||||
if len(ops) == 3 {
|
if len(ops) == 3 {
|
||||||
|
|||||||
@@ -1105,3 +1105,43 @@ TEXT ·d(SB), NOSPLIT, $0
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestLOONG64_addv16 pins the ADDV16 immediate family, the toolchain's
|
||||||
|
// assembler name for the addu16i.d hardware instruction (loong64enc1.s
|
||||||
|
// spells it ADDV16; the spelling ADDU16I.D is the decoder's name for the
|
||||||
|
// encoding and no assembler input at all). The immediate must be a
|
||||||
|
// multiple of 65536 and rides the instruction field shifted right by 16;
|
||||||
|
// the oracle words are the toolchain's own loong64enc1.s rows, each also
|
||||||
|
// confirmed against GOARCH=loong64 go tool asm.
|
||||||
|
func TestLOONG64_addv16(t *testing.T) {
|
||||||
|
fn := firstTextLOONG64(t, `#include "textflag.h"
|
||||||
|
TEXT ·a16(SB), NOSPLIT, $0
|
||||||
|
ADDV16 $(-32768<<16), R4, R5
|
||||||
|
ADDV16 $(0<<16), R4, R5
|
||||||
|
ADDV16 $(8<<16), R4, R5
|
||||||
|
ADDV16 $(32767<<16), R4, R5
|
||||||
|
ADDV16 $(16<<16), R4
|
||||||
|
RET
|
||||||
|
`)
|
||||||
|
code := assembleLOONG64Helper(t, fn)
|
||||||
|
wantWords(t, code,
|
||||||
|
0x12000085, // addu16i.d r5, r4, -32768
|
||||||
|
0x10000085, // addu16i.d r5, r4, 0
|
||||||
|
0x10002085, // addu16i.d r5, r4, 8
|
||||||
|
0x11FFFC85, // addu16i.d r5, r4, 32767
|
||||||
|
0x10004084, // addu16i.d r4, r4, 16 (destination-only form)
|
||||||
|
0x4C000020,
|
||||||
|
)
|
||||||
|
// The non-multiples the loong64error.s catalogue pins (its rows 3 and
|
||||||
|
// 4): $1 and $65535 both refuse.
|
||||||
|
for _, src := range []string{
|
||||||
|
"ADDV16 $1, R4, R5",
|
||||||
|
"ADDV16 $65535, R4, R5",
|
||||||
|
"ADDV16 $(16<<16), F4",
|
||||||
|
} {
|
||||||
|
fn := firstTextLOONG64(t, "#include \"textflag.h\"\nTEXT ·e(SB), NOSPLIT, $0\n\t"+src+"\n\tRET\n")
|
||||||
|
if _, _, _, _, _, err := assembleLOONG64(fn); err == nil {
|
||||||
|
t.Errorf("%q: expected an error, got none", src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user