fix(asm): validate the loong64 ll/sc offset span like the toolchain

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-06 23:59:27 +02:00
1 parent 6cc6165c2b
commit 1040739fbb
3 files changed
+138 -1

No files matched your search

+32
View File
@@ -257,6 +257,38 @@ func l64WordsLE(ws ...uint32) []byte {
return out
}
// l64firr14Words returns the words the 2RI14 families (LL/LLW/LLV, SC/SCW/
// SCV, MOVWP/MOVVP) encode to for a 4-aligned byte offset. The toolchain
// classifies the memory operand by span, with the class constants' -2 slop
// included verbatim: a signed 16-bit offset (C_SOREG_16) rides in si14 alone;
// 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.
func l64firr14Words(op uint32, off, rj, rd int) []byte {
switch {
case off >= -32766 && off < 32766:
return l64wordLE(l64irr14(op, off>>2, rj, rd))
case off >= -2147483650 && off < 2147483646:
return l64WordsLE(
l64irr16(l64InstrTable["ADDV16"].op, off>>16, 0, 30),
l64rrr(l64DualTable["ADDV"].rrr, rj, 30, 30),
l64irr14(op, off>>2, 30, rd),
)
default:
return l64WordsLE(
l64ir(l64InstrTable["LU12IW"].op, off>>12, 30),
l64irr(l64DualTable["OR"].imm, off&0xFFF, 30, 30),
l64ir(l64InstrTable["LU32ID"].op, off>>32, 30),
l64irr(l64InstrTable["LU52ID"].op, off>>52, 30, 30),
l64rrr(l64DualTable["ADDV"].rrr, 30, rj, rj),
l64irr14(op, 0, rj, rd),
)
}
}
// ---- instruction formats ----
type l64Format uint8