fix(asm): match the toolchain's loong64 logical immediate expansion
Assisted-by: GLM 5.3
This commit is contained in:
1 parent
7f955f8bd1
commit
41aa8edfd2
1 file changed
+12
-4
+12
-4
@@ -1183,8 +1183,8 @@ func encodeLOONG64Branch21(instr *ast.Instr, mnem string, op uint32, ops []*ast.
|
||||
//
|
||||
// ADD/SGT family: −2048..0x7ff → addi/slti directly (4 bytes)
|
||||
// 0x800..0xfff → ori r30, r0, v; op rd, rj, r30 (8)
|
||||
// AND/OR/XOR: 0..0x7ff → andi/ori/xori directly (4)
|
||||
// −2048..−1 → addi.d r30, r0, v; op rd, rj, r30 (8)
|
||||
// AND/OR/XOR: 0..0xfff → andi/ori/xori directly (4)
|
||||
// −2048..−1 → addi.w r30, r0, v; op rd, rj, r30 (8)
|
||||
// 32-bit: lu12i.w r30, v>>12 [; ori r30, r30, v]; op (8/12)
|
||||
// 64-bit: lu12i.w + ori + lu32i.d + lu52i.d + op (20)
|
||||
func encodeLOONG64ImmArith(mnem string, de l64DualEnc, ops []*ast.Operand) ([]byte, error) {
|
||||
@@ -1222,12 +1222,18 @@ func encodeLOONG64ImmArith(mnem string, de l64DualEnc, ops []*ast.Operand) ([]by
|
||||
if v == 0 {
|
||||
return l64wordLE(l64rrr(de.rrr, 0, rj, rd)), nil
|
||||
}
|
||||
if v >= 0 && v <= 0x7ff {
|
||||
if v >= 0 && v <= 0xfff {
|
||||
// andi/ori/xori take the full unsigned 12-bit range, the
|
||||
// toolchain's C_UU12CON class.
|
||||
return l64wordLE(l64irr(de.imm, int(v), rj, rd)), nil
|
||||
}
|
||||
if v >= -2048 && v < 0 {
|
||||
// The toolchain's case 10 loads the negative constant with
|
||||
// addi.w (opirr(AADD)), whose 32-bit result zero-extends into
|
||||
// the register; addi.d here would sign-extend instead and the
|
||||
// 64-bit AND/OR/XOR would keep bits the toolchain clears.
|
||||
return l64WordsLE(
|
||||
l64irr(0x00b<<22, int(v), 0, 30), // addi.d r30, r0, v
|
||||
l64irr(0x00a<<22, int(v), 0, 30), // addi.w r30, r0, v
|
||||
l64rrr(de.rrr, 30, rj, rd),
|
||||
), nil
|
||||
}
|
||||
@@ -1285,6 +1291,8 @@ func l64FmaOperands(ops []*ast.Operand) (fa, fk, fj, fd int, err error) {
|
||||
|
||||
// l64MemOperands extracts (rd, rj, off, load) from a load/store instruction:
|
||||
// INSTR mem, rd is a load, INSTR rd, mem a store.
|
||||
// l64MemOperands splits the two-operand load/store forms: the register and
|
||||
// the memory side, the memory's base and byte offset, and the direction.
|
||||
func l64MemOperands(ops []*ast.Operand, fi loong64FrameInfo) (rd, rj int, off int32, load bool, err error) {
|
||||
if len(ops) != 2 {
|
||||
return 0, 0, 0, false, fmt.Errorf("expected 2 operands, got %d", len(ops))
|
||||
|
||||
Reference in new issue
Block a user