refactor(arch): extract the displacement tail and SIB builders
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
27ef71859b
commit
47d561b229
1 file changed
+36
-43
+36
-43
@@ -183,34 +183,48 @@ func (in ExtInstr) amd64Memory(op ExtOperand, pos int) (base int, disp int64, er
|
||||
return op.Reg, op.Imm, nil
|
||||
}
|
||||
|
||||
// amd64DispTail lays the displacement bytes and their ModR/M mod field: no
|
||||
// bytes at displacement zero, a disp8 when the value fits a signed byte and
|
||||
// a disp32 otherwise. The force flag makes a zero displacement encode
|
||||
// anyway, the mod-01 shape the RBP and R13 bases demand, whose bare r/m 101
|
||||
// would otherwise address RIP-relative.
|
||||
func amd64DispTail(disp int64, force bool) (mod byte, tail []byte) {
|
||||
if !force && disp == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if disp >= -128 && disp <= 127 {
|
||||
return 1, []byte{byte(disp)}
|
||||
}
|
||||
return 2, []byte{byte(disp), byte(disp >> 8), byte(disp >> 16), byte(disp >> 24)}
|
||||
}
|
||||
|
||||
// amd64Sib builds the SIB byte the scaled forms carry: the scale field over
|
||||
// the index and the base, whose number rides the r/m field.
|
||||
func amd64Sib(base, index, scale int) byte {
|
||||
sib := byte(base & 7)
|
||||
sib |= byte(index&7) << 3
|
||||
switch scale {
|
||||
case 2:
|
||||
sib |= 1 << 6
|
||||
case 4:
|
||||
sib |= 2 << 6
|
||||
case 8:
|
||||
sib |= 3 << 6
|
||||
}
|
||||
return sib
|
||||
}
|
||||
|
||||
// amd64EncodeMemory returns the register-form template with a base-relative
|
||||
// memory operand filled in: dest and vvvv keep their register meanings, the
|
||||
// ModR/M r/m field carries the base, and the high base bit rides EVEX.B as
|
||||
// amd64Encode lays it. The ModR/M mod bits and the trailing SIB and
|
||||
// displacement bytes follow the canonical choices the GNU assembler makes
|
||||
// for the plain, unscaled SDM displacements: no displacement bytes at
|
||||
// displacement zero, a disp8 when the value fits a signed byte and a disp32
|
||||
// otherwise, the SIB byte 0x24 when the base is RSP or R12, whose r/m
|
||||
// encoding 100 demands it, and a forced displacement on RBP and R13, whose
|
||||
// mod-00 r/m encoding 101 means RIP-relative. The operand must have passed
|
||||
// amd64Memory first.
|
||||
// for the plain, unscaled SDM displacements, and the operand must have
|
||||
// passed amd64Memory first.
|
||||
func amd64EncodeMemory(b []byte, dest, vvvv, base int, disp int64) []byte {
|
||||
out := amd64Encode(b, dest, vvvv, base)
|
||||
rm := base & 7
|
||||
var tail []byte
|
||||
mod := byte(0)
|
||||
switch {
|
||||
case rm == 5 || disp != 0:
|
||||
// RBP and R13 cannot drop the displacement: mod 00 with r/m 101
|
||||
// addresses RIP-relative, not through the base.
|
||||
if disp >= -128 && disp <= 127 {
|
||||
mod = 1
|
||||
tail = []byte{byte(disp)}
|
||||
} else {
|
||||
mod = 2
|
||||
tail = []byte{byte(disp), byte(disp >> 8), byte(disp >> 16), byte(disp >> 24)}
|
||||
}
|
||||
}
|
||||
mod, tail := amd64DispTail(disp, rm == 5)
|
||||
if rm == 4 {
|
||||
// RSP and R12 need the SIB byte: no index, base 100.
|
||||
tail = append([]byte{0x24}, tail...)
|
||||
@@ -247,29 +261,8 @@ func amd64EncodeScaledMemory(b []byte, dest, vvvv, base, index, scale int, disp
|
||||
out[1] &^= 0x40
|
||||
}
|
||||
rm := base & 7
|
||||
var tail []byte
|
||||
mod := byte(0)
|
||||
switch {
|
||||
case rm == 5 || disp != 0:
|
||||
if disp >= -128 && disp <= 127 {
|
||||
mod = 1
|
||||
tail = []byte{byte(disp)}
|
||||
} else {
|
||||
mod = 2
|
||||
tail = []byte{byte(disp), byte(disp >> 8), byte(disp >> 16), byte(disp >> 24)}
|
||||
}
|
||||
}
|
||||
sib := byte(rm)
|
||||
sib |= byte(index&7) << 3
|
||||
switch scale {
|
||||
case 2:
|
||||
sib |= 1 << 6
|
||||
case 4:
|
||||
sib |= 2 << 6
|
||||
case 8:
|
||||
sib |= 3 << 6
|
||||
}
|
||||
tail = append([]byte{sib}, tail...)
|
||||
mod, tail := amd64DispTail(disp, rm == 5)
|
||||
tail = append([]byte{amd64Sib(rm, index, scale)}, tail...)
|
||||
out[5] = out[5]&0x38 | mod<<6 | 4
|
||||
return append(out, tail...)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user