fix(asm): compress movq immediates to the go-tool-asm imm32 forms

Assisted-by: GLM 5.3
This commit is contained in:
2026-08-24 20:23:39 +02:00
parent b08005753e
commit eade875b53
2 changed files with 35 additions and 4 deletions
+23 -2
View File
@@ -91,7 +91,28 @@ func (e *enc) encodeMov(ops []Operand, size int) error {
case Imm:
if dstIsReg {
// MOV r, imm: 0xB0+reg (8-bit) / 0xB8+reg (16/32/64, imm64 for Q).
v := int64(src)
// The Go assembler compresses 64-bit moves whose immediate fits
// a signed int32, choosing per sign:
// v >= 0: B8+rd imm32 without REX.W (zero-extended by the
// hardware, REX.B still emitted for R8-R15);
// v < 0: REX.W C7 /0 imm32 (sign-extended — the plain B8+rd
// form would zero-extend and corrupt the value).
// Out-of-range immediates keep the B8+rd imm64 form.
if size == 8 && v >= 0 && v <= (1<<31)-1 {
i := newInstr(4, []byte{0xB8 + byte(dstReg.idx&7)})
i.rexB = dstReg.idx >= 8
i.imm = le32(v)
return e.emit(i)
}
if size == 8 && v < 0 && v >= -(1<<31) {
i := newInstr(8, []byte{0xC7})
if err := setRMDigit(i, 0, dstReg, 8); err != nil {
return err
}
i.imm = le32(v)
return e.emit(i)
}
opBase := byte(0xB8)
if size == 1 {
opBase = 0xB0
@@ -101,7 +122,7 @@ func (e *enc) encodeMov(ops []Operand, size int) error {
if dstReg.needsREX(size) {
i.rexForced = true
}
i.imm = immediate(int64(src), size, true)
i.imm = immediate(v, size, true)
return e.emit(i)
}
// MOV r/m, imm: 0xC6 (8-bit) / 0xC7 /0.