Skip to main content

Asm

Struct Asm 

Source
pub struct Asm { /* private fields */ }
Expand description

The x86-64 byte emitter with late-bound labels.

Implementations§

Source§

impl Asm

Source

pub fn new() -> Self

An empty assembler.

Source

pub fn pos(&self) -> usize

The current byte length (a position label).

Source

pub fn new_label(&mut self) -> LabelId

Reserve a new (unbound) label.

Source

pub fn bind(&mut self, l: LabelId)

Fix label l at the current position.

Source

pub fn mov_ri(&mut self, dst: Reg, imm: i64)

mov dst, imm64 (REX.W + B8+rd io). Always 10 bytes; simple and exact.

Source

pub fn mov_rr(&mut self, dst: Reg, src: Reg)

mov dst, src (REX.W 89 /r, src in reg field).

Source

pub fn mov_rm(&mut self, dst: Reg, base: Reg, disp: i32)

mov dst, [base + disp] (REX.W 8B /r).

Source

pub fn mov_mr(&mut self, base: Reg, disp: i32, src: Reg)

mov [base + disp], src (REX.W 89 /r).

Source

pub fn add_rr(&mut self, dst: Reg, src: Reg)

add dst, src (REX.W 01 /r).

Source

pub fn sub_rr(&mut self, dst: Reg, src: Reg)

sub dst, src (REX.W 29 /r).

Source

pub fn imul_rr(&mut self, dst: Reg, src: Reg)

imul dst, src (REX.W 0F AF /r — dst is the reg field).

Source

pub fn sub_ri(&mut self, dst: Reg, imm: i32)

sub dst, imm32 (REX.W 81 /5 id) — sign-extended 32-bit immediate.

Source

pub fn add_ri(&mut self, dst: Reg, imm: i32)

add dst, imm32 (REX.W 81 /0 id) — sign-extended 32-bit immediate.

Source

pub fn cmp_ri(&mut self, dst: Reg, imm: i32)

cmp dst, imm32 (REX.W 81 /7 id) — dst - imm, sets flags.

Source

pub fn call_r(&mut self, target: Reg)

call reg (FF /2) — an indirect near call through a register.

Source

pub fn shl_ri(&mut self, dst: Reg, imm: u8)

shl dst, imm8 (REX.W C1 /4 ib) — shift left by a constant count.

Source

pub fn and_rr(&mut self, dst: Reg, src: Reg)

and dst, src (REX.W 21 /r).

Source

pub fn or_rr(&mut self, dst: Reg, src: Reg)

or dst, src (REX.W 09 /r).

Source

pub fn xor_rr(&mut self, dst: Reg, src: Reg)

xor dst, src (REX.W 31 /r).

Source

pub fn not_r(&mut self, dst: Reg)

not dst (REX.W F7 /2).

Source

pub fn neg_r(&mut self, dst: Reg)

neg dst (REX.W F7 /3).

Source

pub fn shl_cl(&mut self, dst: Reg)

shl dst, cl (REX.W D3 /4).

Source

pub fn sar_cl(&mut self, dst: Reg)

sar dst, cl (REX.W D3 /7) — arithmetic shift right.

Source

pub fn cmp_rr(&mut self, a: Reg, b: Reg)

cmp a, b (REX.W 39 /r — a - b, sets flags).

Source

pub fn cqo(&mut self)

cqo (REX.W 99): sign-extend rax into rdx:rax (for idiv).

Source

pub fn idiv_r(&mut self, src: Reg)

idiv src (REX.W F7 /7): rdx:rax / src → quotient rax, remainder rdx.

Source

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.

Source

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.

Source

pub fn test_rr(&mut self, a: Reg, b: Reg)

test a, a (REX.W 85 /r) — sets ZF when a == 0.

Source

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.

Source

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.

Source

pub fn movsd_rr(&mut self, dst: Xmm, src: Xmm)

movsd dst, src (F2 0F 10 /r) — XMM→XMM scalar-double copy.

Source

pub fn addsd_rr(&mut self, dst: Xmm, src: Xmm)

addsd dst, src (F2 0F 58 /r) — dst += src.

Source

pub fn subsd_rr(&mut self, dst: Xmm, src: Xmm)

subsd dst, src (F2 0F 5C /r) — dst -= src.

Source

pub fn mulsd_rr(&mut self, dst: Xmm, src: Xmm)

mulsd dst, src (F2 0F 59 /r) — dst *= src.

Source

pub fn divsd_rr(&mut self, dst: Xmm, src: Xmm)

divsd dst, src (F2 0F 5E /r) — dst /= src.

Source

pub fn sqrtsd_rr(&mut self, dst: Xmm, src: Xmm)

sqrtsd dst, src (F2 0F 51 /r) — dst = sqrt(src).

Source

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.

Source

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.

Source

pub fn movupd_rr(&mut self, dst: Xmm, src: Xmm)

movupd dst, src (66 0F 10 /r) — XMM→XMM 128-bit copy (both lanes).

Source

pub fn addpd_rr(&mut self, dst: Xmm, src: Xmm)

addpd dst, src (66 0F 58 /r) — dst[lane] += src[lane] for both lanes.

Source

pub fn subpd_rr(&mut self, dst: Xmm, src: Xmm)

subpd dst, src (66 0F 5C /r) — dst[lane] -= src[lane] for both lanes.

Source

pub fn mulpd_rr(&mut self, dst: Xmm, src: Xmm)

mulpd dst, src (66 0F 59 /r) — dst[lane] *= src[lane] for both lanes.

Source

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).

Source

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.

Source

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.

Source

pub fn andnpd_rr(&mut self, dst: Xmm, src: Xmm)

andnpd dst, src (66 0F 55 /r) — dst = (NOT dst) AND src (128-bit).

Source

pub fn orpd_rr(&mut self, dst: Xmm, src: Xmm)

orpd dst, src (66 0F 56 /r) — bitwise OR of both 128-bit lanes.

Source

pub fn xorpd_rr(&mut self, dst: Xmm, src: Xmm)

xorpd dst, src (66 0F 57 /r) — bitwise XOR of both 128-bit lanes.

Source

pub fn divpd_rr(&mut self, dst: Xmm, src: Xmm)

divpd dst, src (66 0F 5E /r) — dst[lane] /= src[lane] for both lanes.

Source

pub fn sqrtpd_rr(&mut self, dst: Xmm, src: Xmm)

sqrtpd dst, src (66 0F 51 /r) — dst[lane] = sqrt(src[lane]) both lanes.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn jmp(&mut self, label: LabelId)

jmp label (E9 cd, rel32 patched in resolve).

Source

pub fn jcc(&mut self, cond: Cond, label: LabelId)

jcc label (0F 80+cc cd, rel32 patched in resolve).

Source

pub fn push(&mut self, r: Reg)

push reg (50+rd, with REX.B for r8..r15).

Source

pub fn pop(&mut self, r: Reg)

pop reg (58+rd, with REX.B for r8..r15).

Source

pub fn ret(&mut self)

ret (C3).

Source

pub fn resolve(self) -> Vec<u8>

Resolve all label fixups against bound positions and return the final machine code. Panics if a referenced label was never bound (a backend bug — every label this module creates is bound before resolve).

Trait Implementations§

Source§

impl Default for Asm

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Asm

§

impl RefUnwindSafe for Asm

§

impl Send for Asm

§

impl Sync for Asm

§

impl Unpin for Asm

§

impl UnsafeUnpin for Asm

§

impl UnwindSafe for Asm

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.