fix(asm): encode the loong64 64-bit-span 2RI14 offsets like the toolchain
Assisted-by: GLM 5.3
This commit is contained in:
1 parent
41aa8edfd2
commit
b9dfb48d79
2 files changed
+30
-7
No files matched your search
+28
-4
@@ -825,6 +825,22 @@ func encodeLOONG64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi loo
|
||||
if off&3 != 0 {
|
||||
return nil, fmt.Errorf("%s: offset must be a multiple of 4", mnem)
|
||||
}
|
||||
// The 64-bit span reproduces the toolchain's case 73/74 size-24
|
||||
// expansion word for word, its missing load negation included: a
|
||||
// MOVWP/MOVVP load emits the store opcode, because case 74 spells
|
||||
// opirr(p.As) where the narrower spans spell opirr(-p.As), and the
|
||||
// LL family has no unnegated opirr entry at all, so the toolchain
|
||||
// refuses those loads with "bad irr opcode".
|
||||
if off < -2147483650 || off >= 2147483646 {
|
||||
if load {
|
||||
switch mnem {
|
||||
case "MOVWP", "MOVVP":
|
||||
op += 1 << 24
|
||||
default:
|
||||
return nil, fmt.Errorf("bad irr opcode %s", mnem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return l64firr14Words(op, int(off), rj, rd), nil
|
||||
|
||||
case l64Fir20:
|
||||
@@ -1292,21 +1308,29 @@ 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) {
|
||||
// the memory side, the memory's base and full-width byte offset (64-bit
|
||||
// offsets reach the 2RI14 families' six-word span), and the direction.
|
||||
func l64MemOperands(ops []*ast.Operand, fi loong64FrameInfo) (rd, rj int, off int64, load bool, err error) {
|
||||
if len(ops) != 2 {
|
||||
return 0, 0, 0, false, fmt.Errorf("expected 2 operands, got %d", len(ops))
|
||||
}
|
||||
var mem *ast.Operand
|
||||
if isMemOperand(ops[0]) {
|
||||
rd = l64Reg(ops[1])
|
||||
rj, off = l64MemWithFrame(ops[0], fi)
|
||||
mem = ops[0]
|
||||
load = true
|
||||
} else if isMemOperand(ops[1]) {
|
||||
rd = l64Reg(ops[0])
|
||||
rj, off = l64MemWithFrame(ops[1], fi)
|
||||
mem = ops[1]
|
||||
} else {
|
||||
return 0, 0, 0, false, fmt.Errorf("expected a memory operand")
|
||||
}
|
||||
if mem.Addr.Sym != nil && mem.Addr.Sym.Pseudo != "" {
|
||||
pj, poff := loong64ResolvePseudo(mem.Addr.Sym, fi)
|
||||
rj, off = pj, int64(poff)
|
||||
} else {
|
||||
rj, off = loong64RegNum(mem.Addr.Base), mem.Addr.Offset
|
||||
}
|
||||
if rd < 0 || rj < 0 {
|
||||
return 0, 0, 0, false, fmt.Errorf("invalid operand")
|
||||
}
|
||||
|
||||
@@ -264,9 +264,8 @@ func l64WordsLE(ws ...uint32) []byte {
|
||||
// a 32-bit one (C_LOREG_32) splits between addu16i.d (bits 31:16, materialised
|
||||
// in R30, the assembler temp) and si14 (bits 15:2); anything wider
|
||||
// (C_LOREG_64) builds the whole constant in R30 through lu12i.w + ori +
|
||||
// lu32i.d + lu52i.d and folds the base into it. The loong64 backend resolves
|
||||
// memory offsets as int32, so the third span answers nothing the encoder can
|
||||
// ask today: it stands so the mapping stays complete if that domain widens.
|
||||
// lu32i.d + lu52i.d and folds the base into it. The caller adjusts the
|
||||
// opcode for the 64-bit span's load-direction quirks before arriving here.
|
||||
func l64firr14Words(op uint32, off, rj, rd int) []byte {
|
||||
switch {
|
||||
case off >= -32766 && off < 32766:
|
||||
|
||||
Reference in new issue
Block a user