diff --git a/asm/loong64_assemble.go b/asm/loong64_assemble.go index 5599b2c..d30ffd2 100644 --- a/asm/loong64_assemble.go +++ b/asm/loong64_assemble.go @@ -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))