jitasm
A Python x86-64 JIT assembler.
I've tested on Windows and Linux. I have no macOS computer for testing, but theoretically it should also work on Intel macOS.
pip install jitasm
Example
The following example creates an int64_t max(int64_t a, int64_t b) function equivalent to:
int64_t max(int64_t a, int64_t b) {
if (a >= b) return a;
return b;
}
On Linux, the generated instructions are:
max:
mov rax, rdi
cmp rdi, rsi
jge .done
mov rax, rsi
.done:
ret
And we provide a pseudo-instruction branch.cc to do CMP and Jcc:
max:
mov rax, rdi
bge rdi, rsi, .done
mov rax, rsi
.done:
ret
And we implement it in Python using jitasm:
from jitasm.x86_64 import *
from jitasm.utils import ccall
e = Emitter()
(e.label("max"),
e.mov(RAX, RDI),
e.bge(RDI, RSI, ".done"),
e.mov(RAX, RSI),
e.label(".done"),
e.ret())
e.finalize()
max_fn_ptr = e.symbol("max")
assert ccall(max_fn_ptr, 3, 7) == 7
assert ccall(max_fn_ptr, 42, -1) == 42
finalize() allocates executable memory and resolves labels. symbol() returns
the address of a public label, and ctypes.CFUNCTYPE converts that address into
a callable Python object. Call unmap() when the generated code is no longer
needed. Functions created from symbol() must not be called after unmapping.
The emitter can be finalized again to create a fresh mapping.
See test_qsort.py for a larger example on Linux.
Windows
Windows is using a different ABI, registers for function arguments are RCX, RDX, R8, R9:
from jitasm.x86_64 import *
from jitasm.utils import ccall
e = Emitter()
e.label('add_two')
e.mov(RAX, RCX)
e.add(RAX, RDX)
e.ret()
e.finalize()
assert ccall(e.symbol('add_two'), 20, 22) == 42
Save Registers on Stack Using with
with e.save_regs(rax, rbx, rcx, rdx):
do_something()
will generate code like this:
push rax
push rbx
push rcx
push rdx
do_something
pop rdx
pop rcx
pop rbx
pop rax
Assembly Spec
`m8/m16/m32/m64/m128/m256/m*`: `[r64]`
| `[r64 + r64 * scale +/- simm32]` (scale = 1/2/4/8)
| `[r64 * scale +/- simm32]` (scale = 1/2/4/8)
| `[r64 +/- simm32]`
| `[rip + rel32]`
`rel32`: label
`cond`: EQ | NE | LT | GT | LE | GE | LTU | GTU | GEU | LEU | P | NP | O | NO | S | NS
Implemented Instructions
Only an essential subset of the x86-64 instruction set with several pseudo-instructions is implemented.
Data directives
DB:db int8...DW:dw int16...DD:dd int32.../dd float32.../dd (target_label, base_label)...DQ:dq int64.../dq float64...ASCII:ascii strASCIZ:asciz strALIGN:align bytes// DATA section zero-padding
Data movement and addressing
MOV:mov r64, r64MOV:mov r64, imm64// zero usesXOR r64, r64MOV:mov r64, m64MOV:mov m64, r64MOV:mov m32, r64// low bitsMOV:mov m16, r64// low bitsMOV:mov m8, r64// low bitsMOVZX:movzx r64, r8MOVZX:movzx r64, r16MOVZX:movzx r64, r32MOVZX:movzx r64, m8MOVZX:movzx r64, m16MOVZX:movzx r64, m32MOVSX:movsx r64, r8MOVSX:movsx r64, r16MOVSX:movsx r64, r32MOVSX:movsx r64, m8MOVSX:movsx r64, m16MOVSX:movsx r64, m32LEA:lea r64, m*
Integer arithmetic and bitwise operations
ADD:add r64, r64/add r64, simm32SUB:sub r64, r64/sub r64, simm32BITAND:bitand r64, r64/bitand r64, simm32BITOR:bitor r64, r64/bitor r64, simm32XOR:xor r64, r64/xor r64, simm32BITNOT:bitnot r64//XOR r64, -1NEG:neg r64IMUL:imul r64, r64/imul r64, simm32IDIV:idiv r64, r64// quotient, remainderDIV:div r64, r64// quotient, remainderSHL:shl r64, r64/shl r64, uimm8SAR:sar r64, r64/sar r64, uimm8SHR:shr r64, r64/shr r64, uimm8ROR:ror r64, r64/ror r64, uimm8ROL:rol r64, r64/rol r64, uimm8
Scalar floating point
MOVSS, MOVSD, and scalar arithmetic select AVX when available and otherwise use SSE.
MOVSS:movss xmm, xmmMOVSS:movss xmm, m32MOVSS:movss m32, xmmMOVSD:movsd xmm, xmmMOVSD:movsd xmm, m64MOVSD:movsd m64, xmmADDSS:addss xmm, xmmSUBSS:subss xmm, xmmMULSS:mulss xmm, xmmDIVSS:divss xmm, xmmADDSD:addsd xmm, xmmSUBSD:subsd xmm, xmmMULSD:mulsd xmm, xmmDIVSD:divsd xmm, xmmCVTSI2SS:cvtsi2ss xmm, r64CVTTSS2SI:cvttss2si r64, xmmCVTSI2SD:cvtsi2sd xmm, r64CVTTSD2SI:cvttsd2si r64, xmmROUNDS:rounds xmm, xmm// single precision, round to nearest, ties to evenCEILS:ceils xmm, xmmFLOORS:floors xmm, xmmTRUNCS:truncs xmm, xmmROUNDD:roundd xmm, xmm// double precision, round to nearest, ties to evenCEILD:ceild xmm, xmmFLOORD:floord xmm, xmmTRUNCD:truncd xmm, xmm
Comparisons and branches
Floating-point comparisons select AVX when available and otherwise use SSE.
CMP:cmp r64, r64/cmp r64, simm32UCOMISS:ucomiss xmm, xmmUCOMISD:ucomisd xmm, xmmJCC:jcc cond, rel32Jcchelpers (each takesrel32):- Equality:
je/jeq/jz,jne/jnz - Unsigned:
ja/jnbe/jgtu,jae/jnb/jnc/jgeu,jb/jnae/jc/jltu,jbe/jna/jleu - Signed:
jg/jnle/jgt,jge/jnl,jl/jnge/jlt,jle/jng - Flags:
jo/jno(overflow),js/jns(sign),jp/jpe/jnp/jpo(parity)
- Equality:
SETCC:setcc cond, r8CMOVcc:cmoveq/cmovne/cmovgt/cmovge/cmovlt/cmovle r64, r64CMOVcc:cmovgtu/cmovgeu/cmovltu/cmovleu/cmovp r64, r64BRANCH:branch cond, r64, r64, rel32BRANCH:branch cond, r64, simm32, rel32BRANCHS:branchs cond, xmm, xmm, rel32//beqs/bnes/bgts/bges/blts/blesBRANCHD:branchd cond, xmm, xmm, rel32//beqd/bned/bgtd/bged/bltd/bledCSET:cset cond, r64, r64, r8CSET:cset cond, r64, simm32, r8CSETS:csets cond, xmm, xmm, r8//seteqs/setnes/setgts/setges/setlts/setlesCSETD:csetd cond, xmm, xmm, r8//seteqd/setned/setgtd/setged/setltd/setled
Stack, calls, and control flow
PUSH:push r64POP:pop r64BEGIN:begin//PUSH RBP+MOV RBP, RSPEND:end//MOV RSP, RBP+POP RBP+RETCALL:call rel32CALL:call r64JMP:jmp rel32JMP:jmp r64RET:ret
System
CPUID:cpuid// query processor identification and features
AVX
VMOVAPS:vmovaps xmm, xmm/vmovaps ymm, ymmVMOVAPS:vmovaps xmm, m128/vmovaps m128, xmmVMOVAPS:vmovaps ymm, m256/vmovaps m256, ymmVMOVUPS:vmovups xmm, xmm/vmovups ymm, ymmVMOVUPS:vmovups xmm, m128/vmovups m128, xmmVMOVUPS:vmovups ymm, m256/vmovups m256, ymmVADDPS:vaddps xmm, xmm, xmm/vaddps ymm, ymm, ymmVSUBPS:vsubps xmm, xmm, xmm/vsubps ymm, ymm, ymmVMULPS:vmulps xmm, xmm, xmm/vmulps ymm, ymm, ymmVDIVPS:vdivps xmm, xmm, xmm/vdivps ymm, ymm, ymmVADDSUBPS:vaddsubps xmm, xmm, xmm/vaddsubps ymm, ymm, ymmVSQRTPS:vsqrtps xmm, xmm/vsqrtps ymm, ymmVMAXPS:vmaxps xmm, xmm, xmm/vmaxps ymm, ymm, ymmVMINPS:vminps xmm, xmm, xmm/vminps ymm, ymm, ymmVANDPS:vandps xmm, xmm, xmm/vandps ymm, ymm, ymmVANDNPS:vandnps xmm, xmm, xmm/vandnps ymm, ymm, ymmVORPS:vorps xmm, xmm, xmm/vorps ymm, ymm, ymmVXORPS:vxorps xmm, xmm, xmm/vxorps ymm, ymm, ymmVHADDPS:vhaddps xmm, xmm, xmm/vhaddps ymm, ymm, ymmVHSUBPS:vhsubps xmm, xmm, xmm/vhsubps ymm, ymm, ymmVDPPS:vdpps xmm, xmm, xmm, input_mask, output_maskVDPPS:vdpps ymm, ymm, ymm, input_mask, output_maskVRCPPS:vrcpps xmm, xmm/vrcpps ymm, ymmVRSQRTPS:vrsqrtps xmm, xmm/vrsqrtps ymm, ymmVROUNDPS:vroundps xmm, xmm/vroundps ymm, ymm// round to nearest, ties to evenVFLOORPS:vfloorps xmm, xmm/vfloorps ymm, ymmVCEILPS:vceilps xmm, xmm/vceilps ymm, ymmVTRUNCPS:vtruncps xmm, xmm/vtruncps ymm, ymmVCMPPS:vcmpps xmm, xmm, xmm, predicate/vcmpps ymm, ymm, ymm, predicateVCMPPShelpers:veqps/vltps/vleps/vunordps/vneps/vnltps/vnleps/vordps/vgtps/vgepsVBLENDPS:vblendps xmm, xmm, xmm, mask/vblendps ymm, ymm, ymm, maskVSHUFPS:vshufps xmm, xmm, xmm, imm/vshufps ymm, ymm, ymm, immVPERMILPS:vpermilps xmm, xmm, imm/vpermilps ymm, ymm, immVPERMILPS:vpermilps xmm, xmm, xmm/vpermilps ymm, ymm, ymmVPERM2F128:vperm2f128 ymm, ymm, ymm, sel, zmask// sel: two lanes (0-3); zmask: 1 zeroes a laneVUNPCKLPS:vunpcklps xmm, xmm, xmm/vunpcklps ymm, ymm, ymmVUNPCKHPS:vunpckhps xmm, xmm, xmm/vunpckhps ymm, ymm, ymmVINSERTPS:vinsertps xmm, xmm, xmm, count_dst, count_src, zero_maskVMASKMOVPS:vmaskmovps xmm, xmm, m128/vmaskmovps m128, xmm, xmm// mask is the middle operandVMASKMOVPS:vmaskmovps ymm, ymm, m256/vmaskmovps m256, ymm, ymmVMOVMSKPS:vmovmskps r32, xmm/vmovmskps r32, ymmVMOVSHDUP:vmovshdup xmm, xmm/vmovshdup ymm, ymmVMOVSLDUP:vmovsldup xmm, xmm/vmovsldup ymm, ymmVEXTRACTPS:vextractps r32, xmm, imm// imm: element index 0-3VEXTRACTF128:vextractf128 xmm, ymm, imm// imm: lane 0-1VINSERTF128:vinsertf128 ymm, ymm, xmm, imm// imm: lane 0-1VBROADCASTSS:vbroadcastss xmm, m32/vbroadcastss ymm, m32VBROADCASTSS:vbroadcastss xmm, xmm/vbroadcastss ymm, xmm// AVX2VPTEST:vptest xmm, xmm/vptest ymm, ymm// set ZF and CF from packed bitwise testsVZEROUPPER:vzeroupper// clear bits 128–255 of all YMM registers
Release files for jitasm 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jitasm-0.3.0.tar.gz | 54.9 kB | Details |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jitasm-0.3.0-cp314-cp314-win_amd64.whl | CPython 3.14 | CPython 3.14 | Windows x86-64 | Details |
| jitasm-0.3.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 | Details |
Total release size: 141.7 kB
Release files / jitasm-0.3.0.tar.gz
| Download URL | jitasm-0.3.0.tar.gz |
|---|---|
| Size | 54.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bde3f85e6433c280aa2797fc7d271069cb3d26fd5941c31742af132355e238f6
|
|
BLAKE2b-256 checksum How to use checksums |
3d5b38ec40ff3aabc1ad41c0208209296b2737e8aab7b890fe66ea3d36fdc05f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / jitasm-0.3.0-cp314-cp314-win_amd64.whl
| Download URL | jitasm-0.3.0-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 41.7 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
789bf1ec92503e5c2791d3b9f612a6726c8f7660b0d7bf892a9dcadf62d3c293
|
|
BLAKE2b-256 checksum How to use checksums |
648b1cbbb220d04fd0fcc53402d9231e04f1a72e413f3327b8bfb6054f4f990b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.0
|
Release files / jitasm-0.3.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | jitasm-0.3.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 45.1 kB |
| Tags | CPython 3.14 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
d75b2916a61bd45fc38649fc3b3382cadfc877f7f645665558db72d8f954ec06
|
|
BLAKE2b-256 checksum How to use checksums |
faed97b0ee57d42661f50af6ea13e0df4700b268d1fef8abaa18c73e7c27e3e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|