pub struct Asm { /* private fields */ }Expand description
The x86-64 byte emitter with late-bound labels.
Implementations§
Source§impl Asm
impl Asm
Sourcepub fn mov_ri(&mut self, dst: Reg, imm: i64)
pub fn mov_ri(&mut self, dst: Reg, imm: i64)
mov dst, imm64 (REX.W + B8+rd io). Always 10 bytes; simple and exact.
Sourcepub fn imul_rr(&mut self, dst: Reg, src: Reg)
pub fn imul_rr(&mut self, dst: Reg, src: Reg)
imul dst, src (REX.W 0F AF /r — dst is the reg field).
Sourcepub fn sub_ri(&mut self, dst: Reg, imm: i32)
pub fn sub_ri(&mut self, dst: Reg, imm: i32)
sub dst, imm32 (REX.W 81 /5 id) — sign-extended 32-bit immediate.
Sourcepub fn add_ri(&mut self, dst: Reg, imm: i32)
pub fn add_ri(&mut self, dst: Reg, imm: i32)
add dst, imm32 (REX.W 81 /0 id) — sign-extended 32-bit immediate.
Sourcepub fn cmp_ri(&mut self, dst: Reg, imm: i32)
pub fn cmp_ri(&mut self, dst: Reg, imm: i32)
cmp dst, imm32 (REX.W 81 /7 id) — dst - imm, sets flags.
Sourcepub fn call_r(&mut self, target: Reg)
pub fn call_r(&mut self, target: Reg)
call reg (FF /2) — an indirect near call through a register.
Sourcepub fn shl_ri(&mut self, dst: Reg, imm: u8)
pub fn shl_ri(&mut self, dst: Reg, imm: u8)
shl dst, imm8 (REX.W C1 /4 ib) — shift left by a constant count.
Sourcepub fn idiv_r(&mut self, src: Reg)
pub fn idiv_r(&mut self, src: Reg)
idiv src (REX.W F7 /7): rdx:rax / src → quotient rax, remainder rdx.
Sourcepub fn mul_r(&mut self, src: Reg)
pub fn mul_r(&mut self, src: Reg)
mul src (REX.W F7 /4): UNSIGNED rdx:rax = rax * src — the high 64 bits
of the 128-bit product land in rdx, the low in rax. The magic-reciprocal
high-multiply primitive.
Sourcepub fn shr_ri(&mut self, dst: Reg, imm: u8)
pub fn shr_ri(&mut self, dst: Reg, imm: u8)
shr dst, imm (REX.W C1 /5 ib) — LOGICAL (zero-filling) shift right by a
constant. Distinct from sar (/7, arithmetic/sign-filling): the
unsigned magic reciprocal shifts unsigned high-product bits, so it must
zero-fill.
Sourcepub fn movsd_rm(&mut self, dst: Xmm, base: Reg, disp: i32)
pub fn movsd_rm(&mut self, dst: Xmm, base: Reg, disp: i32)
movsd xmm, [base+disp] (F2 0F 10 /r) — load an f64 from the frame.
Sourcepub fn movsd_mr(&mut self, base: Reg, disp: i32, src: Xmm)
pub fn movsd_mr(&mut self, base: Reg, disp: i32, src: Xmm)
movsd [base+disp], xmm (F2 0F 11 /r) — store an f64 to the frame.
Sourcepub fn movsd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn movsd_rr(&mut self, dst: Xmm, src: Xmm)
movsd dst, src (F2 0F 10 /r) — XMM→XMM scalar-double copy.
Sourcepub fn sqrtsd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn sqrtsd_rr(&mut self, dst: Xmm, src: Xmm)
sqrtsd dst, src (F2 0F 51 /r) — dst = sqrt(src).
Sourcepub fn movupd_rm(&mut self, dst: Xmm, base: Reg, disp: i32)
pub fn movupd_rm(&mut self, dst: Xmm, base: Reg, disp: i32)
movupd xmm, [base+disp] (66 0F 10 /r) — load an UNALIGNED 128-bit pair.
Unaligned (not movapd) because frame/array slots carry no 16-byte
alignment guarantee; the unaligned form is penalty-free on modern cores
when the access happens to be aligned.
Sourcepub fn movupd_mr(&mut self, base: Reg, disp: i32, src: Xmm)
pub fn movupd_mr(&mut self, base: Reg, disp: i32, src: Xmm)
movupd [base+disp], xmm (66 0F 11 /r) — store an unaligned 128-bit pair.
Sourcepub fn movupd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn movupd_rr(&mut self, dst: Xmm, src: Xmm)
movupd dst, src (66 0F 10 /r) — XMM→XMM 128-bit copy (both lanes).
Sourcepub fn addpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn addpd_rr(&mut self, dst: Xmm, src: Xmm)
addpd dst, src (66 0F 58 /r) — dst[lane] += src[lane] for both lanes.
Sourcepub fn subpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn subpd_rr(&mut self, dst: Xmm, src: Xmm)
subpd dst, src (66 0F 5C /r) — dst[lane] -= src[lane] for both lanes.
Sourcepub fn mulpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn mulpd_rr(&mut self, dst: Xmm, src: Xmm)
mulpd dst, src (66 0F 59 /r) — dst[lane] *= src[lane] for both lanes.
Sourcepub fn cmppd_rr(&mut self, dst: Xmm, src: Xmm, pred: u8)
pub fn cmppd_rr(&mut self, dst: Xmm, src: Xmm, pred: u8)
cmppd dst, src, pred (66 0F C2 /r ib) — per-lane compare; each lane is
set to all-ones (true) or all-zero (false). pred: 0=EQ 1=LT 2=LE 3=UNORD
4=NEQ 5=NLT 6=NLE 7=ORD. The mandelbrot escape test uses LE (2).
Sourcepub fn movmskpd(&mut self, dst: Reg, src: Xmm)
pub fn movmskpd(&mut self, dst: Reg, src: Xmm)
movmskpd r32/64, xmm (66 0F 50 /r) — extract the two lane SIGN bits into
a GP register (bit0=lane0, bit1=lane1). After a cmppd, a true lane’s sign
bit is 1, so this yields the active-lane bitmask the loop-exit test reads.
The GP dst is the reg field, the XMM src the rm field.
Sourcepub fn andpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn andpd_rr(&mut self, dst: Xmm, src: Xmm)
andpd dst, src (66 0F 54 /r) — bitwise AND of both 128-bit lanes. The
branchless counter masks a packed 1.0 by the escape mask.
Sourcepub fn andnpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn andnpd_rr(&mut self, dst: Xmm, src: Xmm)
andnpd dst, src (66 0F 55 /r) — dst = (NOT dst) AND src (128-bit).
Sourcepub fn orpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn orpd_rr(&mut self, dst: Xmm, src: Xmm)
orpd dst, src (66 0F 56 /r) — bitwise OR of both 128-bit lanes.
Sourcepub fn xorpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn xorpd_rr(&mut self, dst: Xmm, src: Xmm)
xorpd dst, src (66 0F 57 /r) — bitwise XOR of both 128-bit lanes.
Sourcepub fn divpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn divpd_rr(&mut self, dst: Xmm, src: Xmm)
divpd dst, src (66 0F 5E /r) — dst[lane] /= src[lane] for both lanes.
Sourcepub fn sqrtpd_rr(&mut self, dst: Xmm, src: Xmm)
pub fn sqrtpd_rr(&mut self, dst: Xmm, src: Xmm)
sqrtpd dst, src (66 0F 51 /r) — dst[lane] = sqrt(src[lane]) both lanes.
Sourcepub fn ucomisd_rr(&mut self, a: Xmm, b: Xmm)
pub fn ucomisd_rr(&mut self, a: Xmm, b: Xmm)
ucomisd a, b (66 0F 2E /r) — unordered f64 compare setting CF/ZF/PF.
NaN (unordered) sets ZF=CF=PF=1, so the seta/setae/jbe family used by the
backend folds the unordered case to FALSE, matching the kernel’s IEEE
relations (NaN compares false).
Sourcepub fn cvtsi2sd(&mut self, dst: Xmm, src: Reg)
pub fn cvtsi2sd(&mut self, dst: Xmm, src: Reg)
cvtsi2sd xmm, r64 (F2 REX.W 0F 2A /r) — signed i64 → f64 (the kernel’s
IntToFloat). The GP source is the rm field, the XMM dst the reg field.
Sourcepub fn movq_xr(&mut self, dst: Xmm, src: Reg)
pub fn movq_xr(&mut self, dst: Xmm, src: Reg)
movq xmm, r64 (66 REX.W 0F 6E /r) — bit-copy a GP register into an XMM
(no conversion). The GP src is the rm field, the XMM dst the reg field.
Sourcepub fn movq_rx(&mut self, dst: Reg, src: Xmm)
pub fn movq_rx(&mut self, dst: Reg, src: Xmm)
movq r64, xmm (66 REX.W 0F 7E /r) — bit-copy an XMM into a GP register.
The XMM src is the reg field, the GP dst the rm field.
Sourcepub fn movzx_rm8(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn movzx_rm8(&mut self, dst: Reg, base: Reg, disp: i32)
movzx dst, byte [base + disp] (REX.W 0F B6 /r) — load ONE byte from
memory and zero-extend it into the 64-bit dst. The byte-array
(Seq of Bool) element load: frame[D] = buf[i-1] as i64 over 1-byte
elements, where the loaded u8 widens to a non-negative i64 (0..=255) —
bit-identical to the logos_stencil_arrldb *ptr as i64.
Sourcepub fn mov_mr8(&mut self, base: Reg, disp: i32, src: Reg)
pub fn mov_mr8(&mut self, base: Reg, disp: i32, src: Reg)
mov byte [base + disp], src8 (88 /r) — store the LOW byte of src to
memory. The byte-array element store; the value is pre-normalized to 0/1
by the caller (matching logos_stencil_arrstb’s (v != 0) as u8), so
only the low byte is written. A REX prefix is emitted whenever any high
register bit is set OR src is one of spl/bpl/sil/dil (rsp..rdi,
encodings 4..7) — those low-byte registers are addressable ONLY with a
REX prefix present (without REX the encoding means ah/ch/dh/bh).
Sourcepub fn movsxd_rm(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn movsxd_rm(&mut self, dst: Reg, base: Reg, disp: i32)
movsxd dst, dword [base + disp] (REX.W 63 /r) — load FOUR bytes from
memory and SIGN-extend them into the 64-bit dst. The half-width
(IntsI32) array element load: frame[D] = buf[i-1] as i64 over 4-byte
i32 elements — bit-identical to logos_stencil_arrld_i32’s
*(i32*)ptr as i64.
Sourcepub fn mov_mr32(&mut self, base: Reg, disp: i32, src: Reg)
pub fn mov_mr32(&mut self, base: Reg, disp: i32, src: Reg)
mov dword [base + disp], src32 (89 /r, NO REX.W) — store the LOW 4 bytes
of src to memory. The half-width (IntsI32) element store: the value is
truncated to i32 (lossless under the narrowing proof) — bit-identical to
logos_stencil_arrst_i32’s *(i32*)ptr = v as i32. A REX prefix (without
the W bit) is emitted only for the high-register extension bits.
Sourcepub fn setcc8(&mut self, cond: Cond, dst: Reg)
pub fn setcc8(&mut self, cond: Cond, dst: Reg)
setcc dst8 — set the LOW byte of dst to 0/1 from the flags (no
zero-extension of the upper bits). A REX prefix (even empty) makes
spl/bpl/sil/dil and r8b..r15b addressable; emit REX with B = dst.hi().
Used to normalize a byte-array store value to 0/1 in the same register
whose low byte is then stored by Asm::mov_mr8.
Sourcepub fn setcc_movzx(&mut self, cond: Cond, dst: Reg)
pub fn setcc_movzx(&mut self, cond: Cond, dst: Reg)
setcc dst8 then movzx dst, dst8 — materialize a 0/1 from flags.
dst must be a register whose low byte is addressable under REX
(all of rax..r15 are with a REX prefix).