fix(asm): compress movq immediates to the go-tool-asm imm32 forms
Assisted-by: GLM 5.3
This commit is contained in:
+23
-2
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user