package core:rexcode/isa/arm32
Overview
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
rexcode · Brendan Punsky (dotbmp@github), original author
Index
Types (35)
- Data_Type
- Data_Types
- Decode_Entry
- Decode_Index
- Encode_Run
- Encoding
- Encoding_Flags
- Error
- Error_Code
- Feature
- Index_Mode
- Instruction
- Instruction_Flags
- Instruction_Info
Label_… (4)
- List_Shape
- Memory
- Mnemonic
- Mode
- NEON_Imm_Form
- Operand
Operand_… (3)
- Print_Options
- Print_Result
- Register
- Relocation
- Relocation_Type
- Shift_Type
- Token
- Token_Kind
Constants (172)
Listed one per row under Constants.
Procedures (2548)
Listed one per row under Procedures.
Procedure Groups (136)
Listed one per row under Procedures.
Types
Data_Type ¶
Data_Type :: enum u8 { NONE, S8, S16, S32, S64, // signed integer U8, U16, U32, U64, // unsigned integer I8, I16, I32, I64, // sign-agnostic integer F16, F32, F64, // floating point P8, P16, // polynomial BF16, // bfloat16 SZ8, SZ16, SZ32, SZ64, // bare element size (`vmov.32`, `vstrb.8`) }
The data type an A32 mnemonic carries as a suffix: vadd.i32, vcvt.s32.f32,
vstrb.8. Unlike A64 -- where the arrangement belongs to each operand
(add v0.4s, v1.4s, v2.4s) -- in A32 it belongs to the INSTRUCTION, which is
why it lives here and on Instruction rather than on Operand.
It is not decoration: NEON reuses one operand shape across every element
width, so vadd.i8 and vadd.f32 are both DPR,DPR,DPR and the type is the
only thing that separates their encodings. Without it the encoder can only
ever reach the first form of each shape.
Data_Types ¶
Data_Types :: [2]Data_Type
Two slots because the convert family names both ends: vcvt.s32.f32.
Everything else leaves dt[1] as .NONE.
Decode_Entry ¶
Decode_Entry :: struct #packed { mnemonic: Mnemonic, // 2 ops: [6]Operand_Type, // 6 enc: [6]Operand_Encoding, // 6 bits: u32, // 4 mask: u32, // 4 feature: Feature, // 1 mode: Mode, // 1 flags: Encoding_Flags, // 1 dt: [2]Data_Type, }
Encode_Run ¶
Companion run index: ENCODE_RUNS[mnemonic] -> contiguous run in ENCODE_FORMS.
Encoding ¶
Encoding :: struct #packed { mnemonic: Mnemonic, // 2 ops: [6]Operand_Type, // 6 enc: [6]Operand_Encoding, // 6 bits: u32, // 4 mask: u32, // 4 feature: Feature, // 1 mode: Mode, // 1 flags: Encoding_Flags, // 1 dt: [2]Data_Type, }
Error_Code ¶
Error_Code :: rexcode_isa.Error_Code
Feature ¶
Feature :: enum u8 { BASE, // ARMv4 base ISA (works on every ARM core including ARM7TDMI / GBA) THUMB, // Thumb-1 (ARMv4T+) V5T, // ARMv5T additions (BLX, CLZ, BKPT) V5TE, // ARMv5TE DSP extensions (SMLAxy / SMULxy / etc.) V5TEJ, // ARMv5TEJ (BXJ; Jazelle support) V6, // ARMv6 SIMD-on-GPR + REV/SXTB/etc. V6K, // ARMv6K (CLREX, multiprocessing hints) V6T2, // ARMv6T2 (Thumb-2, MOVW/MOVT, bitfield) V7, // ARMv7-A/R base (DMB/DSB/ISB, LDREX/STREX full set) V7VE, // ARMv7-A Virtualisation Extensions (HVC, ERET) V8, // ARMv8-A AArch32 (HLT, SEVL, MVN nzcvqg) DIV, // SDIV/UDIV (ARMv7-A optional, ARMv7-R/M mandatory) VFPV2, // VFP version 2 (double-precision FP) VFPV3, // VFP version 3 (D32, VCVTB/T half-prec) VFPV4, // VFP version 4 (VFMA family) HALF_FP, // FP16 storage support NEON, // Advanced SIMD NEON_HALF_FP, // FP16 NEON arithmetic CRYPTO, // ARMv8 crypto (AES + SHA1 + SHA2) CRC32, // ARMv8 CRC32B/H/W + CRC32CB/H/W DOT, // ARMv8.2 dot product (VSDOT/VUDOT) BF16, // ARMv8.6 BFloat16 FCMA, // ARMv8.3 complex number (VCMLA/VCADD) FHM, // ARMv8.2 FP16 multiply-acc-long // ---- M-profile ARMv8-M extensions ---- V8M, // ARMv8-M baseline (Cortex-M23, M33, M55, M85) V8M_SE, // ARMv8-M Security Extensions (TT/TTT/TTA/TTAT) V81M, // ARMv8.1-M mainline (low-overhead loops, MVE) MVE_INT, // M-profile Vector Extension (Helium) integer (Cortex-M55+) MVE_FP, // M-profile Vector Extension floating-point CDE, // Custom Datapath Extension (Cortex-M33+) }
Index_Mode ¶
Index_Mode :: enum u8 { OFFSET = 0, // [Rn, #imm] -- no writeback PRE_INDEX = 1, // [Rn, #imm]! -- writeback after addr calc POST_INDEX = 2, // [Rn], #imm -- writeback, base = Rn pre-update }
Instruction ¶
Instruction :: struct #align (64) { // Six, because the coprocessor forms need six: MCR, MRC and CDP are // written `mcr p15, #0, r0, c0, c0, #0`, and dropping the last two // operands does not merely print short -- an opc2 that is not zero // encodes as zero, which is the wrong instruction. Six operands cannot // fit alongside the rest in 64 bytes (Operand is 11, and Memory cannot // go below 8), so this straddles two cache lines rather than one. ops: [6]Operand `fmt:"v,operand_count"`, // 6 * 11 = 66 mnemonic: Mnemonic, // cond, operand_count, mode, length and the two flag bits share one // 16-bit word -- together they need 13 bits, and spending six bytes on // them was what pushed Instruction over 48. `using` keeps inst.cond, // inst.operand_count, inst.mode, inst.length, inst.sets_flags and // inst.wide reading and writing exactly as they did as plain fields. using _: bit_field u16 { cond: u8 | 4, operand_count: u8 | 3, mode: Mode | 1, length: u8 | 3, sets_flags: bool | 1, wide: bool | 1, writeback: bool | 1, }, // Form-id hint: when non-zero, this is (1 + the index into // ENCODING_TABLE[mnemonic]) of the form the decoder produced. The encoder // uses it as a tie-breaker for the shape-ambiguous entries the data type // does not separate on its own -- register lists, LDM/STM addressing // modes. User-constructed instructions leave it at 0 and take the // first shape match. form_id: u16, // The `.i32` / `.s32.f32` suffix. Zero (.NONE) means "unspecified": the // encoder then takes the first form of the matching shape, which is what // every instruction did before this field existed. Set it and the encoder // picks the encoding for that type. dt: [2]Data_Type, // Spare, and free: the operands leave the tail of the second cache line // unused either way. New fields land here without changing the layout. _: [54]u8, }
Sized and aligned to a cache line -- see the note in arm64/instructions.odin. The payload is 48 bytes; padding out to 64 and aligning is worth ~21% on decode, because decode writes whole Instructions and unaligned stores are expensive enough to outweigh writing more bytes.
Related Procedures With Parameters
Label_Map ¶
Label_Map :: rexcode_isa.Label_Map
Label_Names ¶
Label_Names :: map[rexcode_isa.Label_Offset]string
Label_Offset ¶
Label_Offset :: rexcode_isa.Label_Offset
Memory ¶
Memory :: distinct bit_field u64 { base: Register | 15, index: Register | 15, shift_type: Shift_Type | 4, shift_amt: u8 | 6, mode: Index_Mode | 2, sign: i8 | 3, disp: i32 | 19, }
Packed into one word: this sits in every Operand, so its width is multiplied by four in every Instruction. Field syntax and composite literals are unchanged, so this is invisible to callers.
A memory base or index is always a GPR, whose raw value never exceeds
REG_GPR|15 = 0x100F, so 15 bits hold one losslessly (index uses
Register(0), not a high sentinel, for "absent").
disp gets 19 bits (+/-262,143) against a worst case of 4,095 -- the imm12
of an A32 load -- so there is ~64x headroom.
Related Procedures With Returns
Mnemonic ¶
Mnemonic :: enum u16 { INVALID = 0, // ------------------------------------------------------------------------- // Data processing -- core 16 ops (A32 + T32) // ------------------------------------------------------------------------- AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, // Shift mnemonics (in A32 these are MOV aliases with shift, but in Thumb // they are first-class encodings, so they have their own Mnemonic entries) LSL, LSR, ASR, ROR, RRX, // Thumb-1 specific: ADR is an alias for ADD Rd, PC, #imm (also exists in // A32 as an ADD/SUB imm to PC alias) ADR, NEG, // Thumb-1 only: NEG Rd, Rm = RSB Rd, Rm, #0 // ARMv6T2: 16-bit immediate moves MOVW, // MOV with 16-bit immediate (low half) MOVT, // MOV-Top (high half, preserves low) // ARMv6T2: bit field manipulation BFC, BFI, SBFX, UBFX, // ARMv6: register operand sign/zero extends with optional rotation SXTB, SXTB16, SXTH, UXTB, UXTB16, UXTH, SXTAB, SXTAB16, SXTAH, UXTAB, UXTAB16, UXTAH, // ARMv6: bit reverse / byte swap / count leading zeros CLZ, RBIT, REV, REV16, REVSH, SEL, // select bytes per APSR.GE flags // ARMv6T2/v7: PKHBT/PKHTB (pack halfword) PKHBT, PKHTB, // ARMv6: USAD8 (sum of absolute differences) USAD8, USADA8, // ARMv6: saturating arithmetic SSAT, USAT, SSAT16, USAT16, QADD, QSUB, QDADD, QDSUB, // ARMv6: SIMD on GPRs (8/16-bit lanes packed in 32-bit reg) SADD8, SADD16, SASX, SSAX, SSUB8, SSUB16, UADD8, UADD16, UASX, USAX, USUB8, USUB16, QADD8, QADD16, QASX, QSAX, QSUB8, QSUB16, UQADD8, UQADD16, UQASX, UQSAX, UQSUB8, UQSUB16, SHADD8, SHADD16, SHASX, SHSAX, SHSUB8, SHSUB16, UHADD8, UHADD16, UHASX, UHSAX, UHSUB8, UHSUB16, // ARMv6: dual multiply-accumulate SMUAD, SMUADX, SMUSD, SMUSDX, SMLAD, SMLADX, SMLSD, SMLSDX, SMLALD, SMLALDX, SMLSLD, SMLSLDX, // Most-significant-word multiply SMMUL, SMMULR, SMMLA, SMMLAR, SMMLS, SMMLSR, // Multiply / multiply-accumulate (ARMv4+ core) MUL, MLA, MLS, // ARMv6T2: multiply-subtract UMULL, UMLAL, SMULL, SMLAL, UMAAL, // ARMv6: unsigned long multiply-acc-acc // Halfword multiply (ARMv5TE / ARMv6 DSP): // SMLA{x}{y}, SMLAW{y}, SMUL{x}{y}, SMULW{y}, SMLAL{x}{y} SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMLALBB, SMLALBT, SMLALTB, SMLALTT, // Integer division (ARMv7-A optional, ARMv7-R/M mandatory; v7VE adds A-profile) SDIV, UDIV, // ------------------------------------------------------------------------- // Branches // ------------------------------------------------------------------------- B, // signed 24/26-bit branch BL, // branch + link BX, // branch and exchange (to ARM/Thumb) BLX, // branch+link+exchange (reg or imm) BXJ, // branch and exchange to Jazelle (deprecated) // ARMv6T2+: compare and branch (Thumb-only) CBZ, CBNZ, // ARMv6T2+: table branch (Thumb-only) TBB, TBH, // ------------------------------------------------------------------------- // Status register access / hint instructions // ------------------------------------------------------------------------- MSR, MRS, CPS, // change processor state SETEND, // set endianness (deprecated in v8) NOP, YIELD, WFE, WFI, SEV, SEVL, // ARMv8: sev local DBG, HINT, // generic hint with imm DMB, DSB, ISB, // ARMv7 barriers CLREX, // clear exclusive monitor PLD, PLDW, PLI, // preload // ARMv8 AArch32 additions HLT, // halt instruction (debug) DCPS1, DCPS2, DCPS3, // debug change processor state ERET, // exception return (PL2+) // ARMv8 security/profiling/trace barriers (FEAT_RAS, FEAT_SB, FEAT_SPE, FEAT_TRF) ESB, // error synchronization barrier (HINT #16) PSB_CSYNC, // profile sync barrier (HINT #17) TSB_CSYNC, // trace sync barrier (HINT #18) CSDB, // consumption of speculative data barrier (HINT #20) SB, // synchronization barrier (ARMv8.5, dedicated encoding) // ARMv8.1 PAN (Privileged Access Never) bit toggle SETPAN, // ------------------------------------------------------------------------- // Exception generation // ------------------------------------------------------------------------- SVC, // supervisor call (was SWI) BKPT, // breakpoint HVC, // hypervisor call (ARMv7VE) SMC, // secure monitor call (TrustZone) UDF, // permanently undefined // ------------------------------------------------------------------------- // Load / Store // ------------------------------------------------------------------------- LDR, STR, // word LDRB, STRB, // byte LDRH, STRH, // halfword LDRSB, LDRSH, // signed loads LDRD, STRD, // doubleword (Rt/Rt+1 pair) LDRT, STRT, // user-mode (privileged-mode pretend) LDRBT, STRBT, LDRHT, STRHT, LDRSBT, LDRSHT, // ARMv6+ acquire/release LDA, STL, // word acquire/release LDAB, STLB, // byte LDAH, STLH, // halfword // ARMv6 exclusive load/store LDREX, STREX, LDREXB, STREXB, LDREXH, STREXH, LDREXD, STREXD, LDAEX, STLEX, // ARMv8 acquire/release exclusive LDAEXB, STLEXB, LDAEXH, STLEXH, LDAEXD, STLEXD, // Block move LDM, STM, // IA order (the default spelling) // The other three increment/decrement orders are their own mnemonics -- // that is how an assembler spells them, and it is the only way to reach // their encodings: all four share one operand shape, so nothing else // tells them apart. LDMIB, LDMDA, LDMDB, STMIB, STMDA, STMDB, // Stack convenience aliases PUSH, POP, // Swap (deprecated since ARMv6 but still encoded) SWP, SWPB, // ------------------------------------------------------------------------- // ARMv6 / Return-from-Exception // ------------------------------------------------------------------------- // The addressing mode is part of the name, as it is for LDM and STM. RFEDA, RFEDB, RFEIA, RFEIB, // return from exception SRSDA, SRSDB, SRSIA, SRSIB, // store return state // ------------------------------------------------------------------------- // Coprocessor (legacy CP-space; many subsumed by VFP/NEON) // ------------------------------------------------------------------------- CDP, CDP2, MCR, MCR2, MRC, MRC2, MCRR, MCRR2, MRRC, MRRC2, LDC, LDC2, STC, STC2, // The N bit asks the coprocessor for the long transfer, and the syntax // spells that on the mnemonic. LDCL, LDC2L, STCL, STC2L, // ------------------------------------------------------------------------- // ARMv8 AArch32 CRC32 (FEAT_CRC32) // ------------------------------------------------------------------------- CRC32B, CRC32H, CRC32W, CRC32CB, CRC32CH, CRC32CW, // ------------------------------------------------------------------------- // VFP / Advanced SIMD shared opcodes // ------------------------------------------------------------------------- // -- Scalar FP arithmetic (operates on S<n>, D<n>) ------------------------- VADD, VSUB, VMUL, VDIV, VMLA, VMLS, VNMUL, VNMLA, VNMLS, VFMA, VFMS, VFNMA, VFNMS, // The bfloat16 multiply-accumulates name which half of each pair they // take, bottom or top, on the mnemonic. VFMAB, VFMAT, VABS, VNEG, VSQRT, VCMP, VCMPE, VCVT, // cross-format conversion (encoded via cmode bits) VCVTB, VCVTT, // half-precision conversion (bottom/top lane) VCVTA, VCVTN, VCVTP, VCVTM, // ARMv8: rounding-mode FP-to-int VCVTR, // FP-to-int using FPSCR rounding VMOV, // many forms (reg-reg, reg-imm, GPR-FPR) VMRS, VMSR, // FPSCR/coprocessor access VLDR, VSTR, // The addressing mode is part of the name, as it is for LDM and STM. VLDMIA, VLDMDB, VSTMIA, VSTMDB, VPUSH, VPOP, VSEL, // ARMv8 conditional select VMAXNM, VMINNM, // ARMv8 IEEE 754-2008 min/max VRINTA, VRINTN, VRINTP, VRINTM, // ARMv8 round-to-int by mode VRINTR, VRINTZ, VRINTX, // round to int per current/zero/exact // -- NEON-specific (vector D/Q reg) ----------------------------------------- VADDL, VADDW, VSUBL, VSUBW, VHADD, VHSUB, VRHADD, VQADD, VQSUB, VMULL, VMLAL, VMLSL, VQDMULL, VQDMLAL, VQDMLSL, VQDMULH, VQRDMULH, // ARMv8.1 FEAT_RDM: rounding doubling multiply-accumulate VQRDMLAH, VQRDMLSH, VABA, VABAL, VABD, VABDL, VAND, VBIC, VORR, VORN, VEOR, VBSL, VBIT, VBIF, VMVN, VMOVN, VQMOVN, VQMOVUN, VMOVL, // extend halve-width to full-width VTST, VCEQ, VCGE, VCGT, VCLE, VCLT, VACGE, VACGT, // absolute compare for FP VACLE, VACLT, VMAX, VMIN, VPMAX, VPMIN, VPADD, VPADDL, VPADAL, VRECPE, VRECPS, // reciprocal estimate / step VRSQRTE, VRSQRTS, VSHL, VSHR, VSRA, VRSHL, VRSHR, VRSRA, VSLI, VSRI, VQSHL, VQSHRN, VQSHRUN, VQRSHL, VQRSHRN, VQRSHRUN, VSHRN, VRSHRN, VSHLL, // shift-left long VCLS, VCLZ, VCNT, VREV16, VREV32, VREV64, VEXT, // vector extract VTBL, VTBX, // table lookup VTRN, VUZP, VZIP, VDUP, // duplicate scalar to vector VSWP, // swap // Load/Store structures (NEON) VLD1, VLD2, VLD3, VLD4, VST1, VST2, VST3, VST4, // -- Advanced SIMD / NEON crypto (ARMv8 AArch32 FEAT_AES + FEAT_SHA1/2) --- AESE, AESD, AESMC, AESIMC, SHA1H, SHA1SU0, SHA1SU1, SHA1C, SHA1M, SHA1P, SHA256H, SHA256H2, SHA256SU0, SHA256SU1, // -- VFP rounding (ARMv8 FEAT_FP) ---------------------------------------- VJCVT, // VJCVT: F64-to-S32 with FPSCR.RM rounding // -- Dot Product (FEAT_DotProd) ------------------------------------------ VSDOT, VUDOT, // -- BF16 (FEAT_BF16) ---------------------------------------------------- // BF16<->F32 VDOT, VMMLA, // -- FHM (FEAT_FHM) FP16 matrix mul/acc ---------------------------------- VFMAL, VFMSL, // F16 fused multiply-add long // -- ComplexNum (FEAT_FCMA) ---------------------------------------------- VCMLA, VCADD, // -- I8MM (FEAT_I8MM, ARMv8.6) integer matrix multiply + mixed-sign dot -- VSMMLA, // signed-signed 8x8 matrix mul VUMMLA, // unsigned-unsigned VUSMMLA, // unsigned-signed VSUDOT, // signed-unsigned dot product VUSDOT, // unsigned-signed dot product // -- Lane-indexed NEON multiply / MAC forms (heavily used in DSP/codec) -- // -- MVE saturating unary ----------------------------------------------- VQABS, VQNEG, // -- MVE FP lane manipulation (F16 packing) ----------------------------- VMOVX, // extract high F16 lane from S-reg VINS, // insert F16 into high lane of S-reg // ------------------------------------------------------------------------- // Thumb-only mnemonics (extra ones not shared with A32) // ------------------------------------------------------------------------- IT, // if-then block (Thumb-2) // ------------------------------------------------------------------------- // ARMv8-M Security Extensions (TrustZone-M) // ------------------------------------------------------------------------- TT, // test target TTT, // test target unprivileged TTA, // test target alternate domain TTAT, // test target alternate domain unprivileged SG, // secure gateway (enter secure state) BXNS, // branch and exchange non-secure BLXNS, // branch with link and exchange non-secure // ------------------------------------------------------------------------- // PACBTI for ARMv8.1-M (Cortex-M85) // ------------------------------------------------------------------------- PAC, // PAC R12, LR, SP PACBTI, // PACBTI R12, LR, SP (combined PAC + BTI marker) AUT, // AUT R12, LR, SP AUTG, // AUTG Rd, Rn, Rm (general form) BTI, // M-profile branch target identification // ------------------------------------------------------------------------- // ARMv8.1-M low-overhead loops (Helium prerequisite, but useful even without MVE) // ------------------------------------------------------------------------- WLS, // while loop start WLSTP, // while loop start with tail predication DLS, // do loop start DLSTP, // do loop start with tail predication LE, // loop end LETP, // loop end with tail predication LCTP, // loop clear tail predication // Branch Future (ARMv8.1-M). T32, encoded via REL_BF + BF_BOFF/BF_BLOC/BF_RM // operand encodings and BF_BOFF_T32/BF_BLOC_T32 relocations (see encoder.odin). // bf-point imm4 at hw0[10:7]; branch target J:imm10 at hw1[11]:[10:1]; BFLX/BFX // use a register target Rm at hw0[3:0]; BFCSEL adds a 4-bit condition at // hw0[5:2] (its else-target is the implicit fall-through). Byte-exact vs llvm-mc. BF, // branch future BFX, // branch future indirect (bfx) BFL, // branch future and link BFLX, // branch future link and exchange BFCSEL, // branch future conditional select // ------------------------------------------------------------------------- // Custom Datapath Extension (CDE) // ------------------------------------------------------------------------- CX1, CX1A, // dual-coprocessor + GPR dest (32-bit) CX1D, CX1DA, // 64-bit GPR pair dest CX2, CX2A, CX2D, CX2DA, CX3, CX3A, CX3D, CX3DA, VCX1, VCX1A, // VFP S/D-reg dest VCX2, VCX2A, VCX3, VCX3A, // Predication block (then/else interleaved) VPT, // predicate-then block VPST, // predicate-then-set block (single) VPSEL, // predicate select (per-element) VPNOT, // invert VPR VCTP, // create tail predicate (.8/.16/.32/.64) // Reductions (single-vector accumulate) VADDV, VADDVA, // accumulate sum across vector (signed/unsigned, +acc) VADDLV, VADDLVA, // long version (S64 accumulator) VMAXV, VMAXAV, // max (and absolute) VMINV, VMINAV, VMAXNMV, VMAXNMAV, // FP max-num VMINNMV, VMINNMAV, // Dual MAC reductions (multiply-accumulate then sum) VABAV, // accumulate absolute difference VMLADAV, VMLADAVA, VMLADAVX, VMLADAVAX, VMLALDAV, VMLALDAVA, VMLALDAVX, VMLALDAVAX, VMLSDAV, VMLSDAVA, VMLSDAVX, VMLSDAVAX, VMLSLDAV, VMLSLDAVA, VMLSLDAVX, VMLSLDAVAX, VRMLALDAVH, VRMLALDAVHA, VRMLALDAVHX, VRMLALDAVHAX, VRMLSLDAVH, VRMLSLDAVHA, VRMLSLDAVHX, VRMLSLDAVHAX, VMLAV, VMLAVA, // simple MAC across vector VMLSV, VMLSVA, // Complex arithmetic (Q-register vector form) VCMUL, // complex multiply (separate from VCMLA) VHCADD, // halving complex add // Bit reverse + shifts unique to MVE VBRSR, // bit reverse with shift right VSHLC, // shift left with carry VDDUP, // decrement and duplicate VIDUP, // increment and duplicate VDWDUP, // decrement-wrap and duplicate VIWDUP, // increment-wrap and duplicate // Narrowing with B/T (bottom/top) VMOVNB, VMOVNT, // narrow bottom/top VQMOVNB, VQMOVNT, // saturating narrow B/T VQMOVUNB, VQMOVUNT, // saturating-unsigned narrow B/T // Widening with B/T VSHLLB, VSHLLT, // shift left long bottom/top VMULLB, VMULLT, // multiply long B/T VMLALB, VMLALT, // multiply-accumulate long B/T VMLSLB, VMLSLT, VSHRNB, VSHRNT, // shift right narrow B/T VRSHRNB, VRSHRNT, VQSHRNB, VQSHRNT, VQRSHRNB, VQRSHRNT, VQSHRUNB, VQSHRUNT, VQRSHRUNB, VQRSHRUNT, // Saturating doubling MAC reductions VQDMLADH, VQDMLADHX, VQDMLSDH, VQDMLSDHX, VQRDMLADH, VQRDMLADHX, VQRDMLSDH, VQRDMLSDHX, // MVE load/store (mostly reuses VLDR/VSTR but distinct forms exist): VLDRB, VLDRH, VLDRW, VLDRD, // MVE contiguous load (B/H/W/D) VSTRB, VSTRH, VSTRW, VSTRD, // MVE contiguous store VLD20, VLD21, // 2-vector interleaved (halves) VLD40, VLD41, VLD42, VLD43, // 4-vector interleaved (quarters) VST20, VST21, VST40, VST41, VST42, VST43, // ------------------------------------------------------------------------- // Sentinel // ------------------------------------------------------------------------- _COUNT, }
Related Procedures With Parameters
Mode ¶
Mode :: enum u8 { A32 = 0, // 32-bit ARM T32 = 1, // Thumb (16-bit or 32-bit T2) }
Related Procedures With Parameters
Operand ¶
Operand :: struct #packed { using _: struct #packed #raw_union { // A register operand's shift and lane ride WITH the register instead // of in the tail -- that is what keeps Operand at 10 bytes, and they // only ever apply to a register anyway. `using` means op.reg, // op.shift_type, op.shift_amt and op.lane still read and write // exactly as they did when these were separate fields. using _: bit_field u32 { reg: Register | 16, shift_type: Shift_Type | 4, shift_amt: u8 | 6, lane: u8 | 5, has_lane: bool | 1, }, mem: Memory, immediate: i64, relative: i64, }, kind: Operand_Kind, size: u8, // How the syntax writes this register as a list. `count` 0 means a plain // register. NEON structure loads also come in a spaced form that steps two // registers at a time -- `{d2, d4}` -- and a to-all-lanes form written // `{d2[]}`. A GPR list (`{r4, lr}`) is not a run at all and stays a // bitmask under REG_LIST. list: List_Shape, }
Related Procedures With Returns
Operand_Encoding ¶
Operand_Encoding :: enum u8 { NONE, IMPL, // implicit operand (no bits emitted) // ---- A32 GPR slots ---- RD, // bits 15-12 (data-proc dest) RN_A32, // bits 19-16 RM_A32, // bits 3-0 RS_A32, // bits 11-8 (register-shifted-register shift amount) RT_A32, // bits 15-12 (load/store target = RD slot) RT2_A32, // bits 15-12 + 1 (LDRD/STRD even-odd pair, implicit) RA_A32, // bits 15-12 (MLA, MLS accumulator) RDLO_A32, // bits 15-12 (UMULL/SMULL low result) RDHI_A32, // bits 19-16 (UMULL/SMULL high result) // ---- T32 (Thumb-2 32-bit) slots ---- RD_T32, // bits 11-8 of second halfword (high half of u32) RN_T32, // bits 19-16 of first halfword (low 4 bits of byte at offset 2) RM_T32, // bits 3-0 of second halfword RT_T32, // load/store target RT2_T32, // second load/store register RA_T32, // accumulator (MLA/MLS) // ---- T16 slots ---- RD_T16_LO, // bits 2-0 of halfword (low 3 bits) RM_T16_LO, // bits 5-3 RN_T16_LO, // bits 5-3 (alias) RD_T16_HI, // hi-reg form: rd[3] at bit 7, rd[2:0] at bits 2-0 RM_T16_HI, // rm at bits 6-3 (4-bit hi-reg) // ---- Modified immediate ---- A32_IMM_MOD, // bits 11-0 carry rotate(11:8) + value(7:0) T32_IMM_MOD, // Thumb-2 modified-imm in i:imm3:imm8 (bits 26, 14-12, 7-0) A32_IMM12_ROT, // identical to A32_IMM_MOD; alternate name for clarity // ---- Immediate field placements (A32) ---- A32_IMM12, // bits 11-0 (LDR/STR offset) A32_IMM_SHIFT, // bits 11-7 (data-proc shift_imm) A32_IMM_SHIFT_32, // same field, but a zero means 32 (LSR/ASR) A32_SHIFT_TYPE, // bits 6-5 A32_RS_SHIFT, // bits 11-8 (RSR uses Rs register) A32_IMM24, // bits 23-0 (B/BL/SVC) A32_IMM4, // bits 3-0 in modified-imm rotate or SAT amount A32_IMM4_ROTATE, // bits 11-8 (rotation in some forms) A32_IMM5_LSB, // bits 11-7 (BFC/BFI/UBFX lsb) A32_IMM5_W, // bits 20-16 (BFC/BFI msb -- width = msb - lsb + 1) A32_COND_FIELD, // bits 31-28 A32_REG_LIST, // bits 15-0 (LDM/STM/PUSH/POP bitmask of R0..R15) // ---- VFP / NEON register fields ---- VD_S, // S<reg>: Vd<4:1>=bits 15-12, D=bit 22; combined 5-bit reg VN_S, // S<reg>: Vn<4:1>=bits 19-16, N=bit 7 VM_S, // S<reg>: Vm<4:1>=bits 3-0, M=bit 5 VD_D, // D<reg>: D=bit 22, Vd<3:0>=bits 15-12 VN_D, // D<reg>: N=bit 7, Vn<3:0>=bits 19-16 VM_D, // D<reg>: M=bit 5, Vm<3:0>=bits 3-0 VD_Q, // Q<reg>: D=bit 22, Vd<3:0>=bits 15-12 (must be even) VN_Q, // Q<reg>: N=bit 7, Vn<3:0>=bits 19-16 (must be even) VM_Q, // Q<reg>: M=bit 5, Vm<3:0>=bits 3-0 (must be even) // NEON by-element scalar Dm[lane] (VQDMULH/VQRDMULH-by-scalar): // .16: Dm in D0..D7 at bits 2:0, lane = bit5:bit3 // .32: Dm in D0..D15 at bits 3:0, lane = bit5 NEON_VM_SCALAR16, NEON_VM_SCALAR32, // VMOV (core register to scalar) destination Dd[lane]: Dd at bits 19:16 + // bit 7; the lane bits depend on element size: // .8 lane[2:0] = bit22 : bit21 : bit5 .16 lane[1:0] = bit21 : bit6 // .32 lane[0] = bit21 VMOV_LANE_8, VMOV_LANE_16, VMOV_LANE_32, // MVE complex-op rotation immediate (user passes degrees): // MVE_ROT_HCADD: #90/#270 -> bit 12; MVE_ROT_CMLA: #0/90/180/270 -> bits 24:23 MVE_ROT_HCADD, MVE_ROT_CMLA, // MVE 3-bit Q registers (Q0..Q7): Qn at bits 19:17, Qm at bits 3:1. VN_Q_MVE, VM_Q_MVE, VFP_IMM8, VM_S_PLUS1, // the second S register of a consecutive pair DBG_OPTION, // DBG's option, bits 3:0 -- not the wider hint field MRS_SPEC_REG, // APSR or SPSR, by the R bit VFP_SPEC_REG, // VMRS/VMSR system register, bits 19:16 SETEND_ENDIAN, // LE or BE, by the E bit IMPL_SP, // an SP the syntax names but no field encodes MODE_IMM5, // processor mode, bits 4:0 (SRS) RN_A32_WB, // base register whose writeback rides in bit 21 NEON_LANE_VN_32, // Vn:N with the 32-bit lane index in bit 21 // VFP immediate (VMOV.F32/F64 #imm) NEON_IMM8_ABCDEFGH, // bits 18-16 (abc) + bits 3-0 (defgh) NEON_CMODE, // bits 11-8 (cmode for VMOV/VMVN immediate) NEON_OP_BIT, // bit 5 (op for VMOV immediate variant) // ---- VFP / NEON list ---- VFP_S_LIST, // VLDM/VSTM single-prec list (8-bit count, start in Vd_S) VFP_D_LIST, // VLDM/VSTM double-prec list (8-bit count, start in Vd_D) // VTBL/VTBX read their table from a run of one to four D registers // starting at Vn. Which run length applies is the `len` field, which is // a fixed pattern bit of each form rather than something the operand // encodes -- so the length rides in the encoding, the way the NEON // structure-list lengths already do, and the encoder emits only Vn. NEON_VN_TABLE_1, NEON_VN_TABLE_2, NEON_VN_TABLE_3, NEON_VN_TABLE_4, // NEON "by scalar": the multiplier is one lane of a low D register, and // the register number and the lane number share one four-bit field. How // they share it depends on the element size -- 16-bit takes Vm from bits // 2:0, so D0..D7, and the lane from M:bit3; 32-bit takes Vm from bits // 3:0, so D0..D15, and the lane from M alone. NEON_VM_SCALAR_16, NEON_VM_SCALAR_32, // VDUP from a lane packs the element size and the lane index into one // four-bit field: `xxx1` is a byte lane, `xx10` a halfword, `x100` a // word, and the bits above the marker are the index. NEON_VDUP_LANE_8, NEON_VDUP_LANE_16, NEON_VDUP_LANE_32, // NEON structure load/store lists (VLD1-4 / VST1-4). Unlike VLDM's list, // the register count is part of the form's type field at bits 11:8, so the // encoding writes only Vd; how many registers -- and whether the run steps // by one or by two -- comes from the form. Verified against llvm-mc. NEON_D_LIST_1, // {d2} NEON_D_LIST_2, // {d2, d3} NEON_D_LIST_3, // {d2, d3, d4} NEON_D_LIST_4, // {d2, d3, d4, d5} NEON_D_LIST_2X, // {d2, d4} -- spaced NEON_D_LIST_3X, // {d2, d4, d6} -- spaced NEON_D_LIST_4X, // {d2, d4, d6, d8} -- spaced NEON_D_LIST_ALL, // {d2[]} -- to all lanes // The structure loads that broadcast take a list of two, three or four, // and bit 5 spaces it -- `{d0[], d2[]}` rather than `{d0[], d1[]}`. NEON_D_LIST_ALL_2, NEON_D_LIST_ALL_3, NEON_D_LIST_ALL_4, // VLD1/VST1 single-lane: Vd plus the lane index, whose width and position // follow the element size -- bits 7:5 for .8, 7:6 for .16, bit 7 for .32. // Verified against llvm-mc. // ..._N is how many registers the list holds: VLD2 writes `{d0[1], d1[1]}`. NEON_LANE_D_8, NEON_LANE_D_16, NEON_LANE_D_32, NEON_LANE_D_8_2, NEON_LANE_D_16_2, NEON_LANE_D_32_2, NEON_LANE_D_8_3, NEON_LANE_D_16_3, NEON_LANE_D_32_3, NEON_LANE_D_8_4, NEON_LANE_D_16_4, NEON_LANE_D_32_4, // ---- Memory addressing composites ---- MEM_IMM12_OFFSET, // [Rn, #±imm12] // The halfword and dual load/stores split their 8-bit offset around the // opcode at bits 7:4, so they cannot use the 12-bit forms below. // LDRD/STRD name a register pair, and the second is always the first plus // one, so it occupies no bits of its own. RT2_A32_PAIR, MEM_IMM8_PRE_INDEX, MEM_IMM8_POST_INDEX, MEM_IMM8_OFFSET, MEM_IMM8_SCALED4, // VFP load/store: imm8 in words, U at bit 23 MEM_IMM8_SCALED4_PRE, // same, pre-indexed MEM_IMM8_SCALED4_POST, // same, post-indexed // [Rn, #±imm8] (LDRH/STRH/LDRSB/STRD) MEM_REG_OFFSET, // [Rn, ±Rm{, shift}] MEM_PRE_INDEX, // [Rn, #imm]! / [Rn, ±Rm]! MEM_POST_INDEX, // [Rn], #imm / [Rn], ±Rm MEM_LITERAL, // [PC, #imm] (LDR literal) MEM_DOUBLEREG, // [Rn, Rm] for LDRD/STRD register offset // ---- Coprocessor ---- COPROC_NUM_FIELD, // bits 11-8 in CDP/LDC/STC (cp_num) COPROC_CRD_FIELD, // bits 15-12 -- the destination, which is not CRn COPROC_OPC1_MCR, // bits 23-21 (MCR/MRC opc1, three bits not four) COPROC_OPC1_FIELD, // bits 23-20 (CDP opc1) COPROC_OPC2_FIELD, // bits 7-5 (CDP / MCR / MRC opc2) COPROC_CRN_FIELD, // bits 19-16 COPROC_CRM_FIELD, // bits 3-0 COPROC_OPC_MCRR, // bits 7-4 (MCRR/MRRC 4-bit opcode) // ---- Branch fields ---- BRANCH_24, // A32 imm24 at bits 23-0 (scaled ×4, ±32MB) BRANCH_24_T32, // T32 unconditional: S/J1/J2 + imm10 + imm11 (scaled ×2) BRANCH_20_T32, // T32 conditional: S + cond + imm6 + J1 + J2 + imm11 BRANCH_11_T16, // T16 unconditional (imm11, scaled ×2, ±2KB) BRANCH_8_T16, // T16 conditional (cond + imm8, scaled ×2, ±256B) BRANCH_CBZ, // T16 CBZ/CBNZ (i + imm5 + Rn, scaled ×2) // ARMv8.1-M Branch Future fields (T32): BF_BOFF, // bf-point offset: imm4 at hw0[10:7], (label-PC-4)/2 BF_BLOC, // branch target: J at hw1[11] + imm10 at hw1[10:1] BF_RM, // BFLX/BFX register target at hw0[3:0] BFCSEL_COND, // BFCSEL condition at hw0[5:2] // ---- Misc ---- PSR_FIELD_MASK, // APSR fields_mask at bits 19-16 (MSR) SYSM_FIELD, // SYSm at bits 7-0 (MRS_BANKED) BARRIER_TYPE, // bits 3-0 for DMB/DSB/ISB IT_MASK, // bits 7-0 for IT block (mask + cond) CPS_IFLAGS, // imod + iflags + mode for CPS HINT_FIELD, // hint imm // ---- Saturate ---- VFP_FBITS, // VCVT fixed-point fraction bits: width - (imm4:i) // VSHLL's widest form shifts by exactly the element size, which no field // carries -- the size is a fixed bit of the form, so the amount is too. NEON_SHLL_8, NEON_SHLL_16, NEON_SHLL_32, // Complex-arithmetic rotations, named in degrees. VCADD has two, in bit // 24; VCMLA has four, in bits 21:20. // VCMLA names its rotation twice over: the by-element forms put it in // bits 21:20, the vector forms in 24:23. NEON_ROT_2, NEON_ROT_4, NEON_ROT_4_HI, SAT_IMM5, // bits 20-16: SSAT/SSAT16 saturate-to width, less one SAT_IMM5_T32, // Thumb-2 signed saturate amount, less one SAT_IMM5_U, // bits 20-16: USAT/USAT16 width, which is not biased SAT_IMM5_U_T32, // Thumb-2 unsigned saturate amount // ---- BFC/BFI/SBFX/UBFX ---- // SBFX/UBFX hold the width less one, where BFI/BFC hold the top bit's // position and the width is msb - lsb + 1. BFX_WIDTH, BFI_MSB, // bits 20-16 (msb position) BFI_LSB, // bits 11-7 (lsb position; also shift_imm slot) BFI_LSB_T32, // Thumb-2 BFI lsb (different layout) // ---- NEON shift-immediate (imm6 in bits 21:16, with element-size hint // in bit 22 = L bit for 64-bit shifts) ---- NEON_SHIFT_IMM6, // 6-bit shift amount at bits 21:16 (NEON VSHR/VSRA/...) NEON_SHIFT_IMM3, // 3-bit shift at bits 18:16 (.I8 form, top 3 bits zero) // ---- ARMv8-M / MVE / CDE ---- QD_MVE, // MVE Qd: bit 22 fixed 0, bits 15:13 = Qd[2:0] QN_MVE, // MVE Qn: bit 7, bits 19:17 = Qn[2:0] QM_MVE, // MVE Qm: bit 5, bits 3:1 = Qm[2:0] MVE_SIZE_FIELD, // 2-bit size in bits 21:20 (B/H/W/D) MVE_VPT_MASK_FIELD, // VPT mask in bits 3:0 of second halfword MVE_LOOP_IMM, // low-overhead-loop immediate CDE_COPROC_FIELD, // CDE p<n> coprocessor selector (bits 11:8) CDE_IMM_FIELD, // CDE immediate (variable layout) CDE_ACC_FIELD, // CDE accumulator bit (distinguishes CX1/CX1A) V8M_TT_AT_BITS, // TT/TTA/TTT/TTAT A and T bit field at bits 7:6 }
Operand_Kind ¶
Operand_Kind :: enum u8 { NONE, REGISTER, IMMEDIATE, MEMORY, RELATIVE, REG_LIST, // LDM/STM/PUSH/POP bitmask (low 16 bits = R0..R15) // A modified immediate is a bit pattern an 8-bit field expands into, and // assemblers write it as one: in hex, or as a float when the expansion // produced one. The value is stored expanded either way -- for the float // it is the 32-bit pattern, which is what the encoder needs back. HEX_IMMEDIATE, FLOAT_IMMEDIATE, }
Operand_Type ¶
Operand_Type :: enum u8 { NONE, // ---- Integer registers ---- GPR, // R0..R15 (or SP/LR/PC by alias) GPR_NOPC, // R0..R14 (PC disallowed by spec) GPR_NOSP, // R0..R14 except SP GPR_LOW, // R0..R7 (Thumb-1 low-reg encoding) GPR_SHIFTED, // Rm + shift type + immediate shift amount GPR_RSR, // Rm + shift type + Rs register-shifted-register GPR_LIST, // Register list (LDM/STM/PUSH/POP); bitmask 16 GPRs // ---- Floating point / SIMD ---- SPR, // S0..S31 DPR, // D0..D31 QPR, // Q0..Q15 SPR_LIST, // VLDM/VSTM/VPUSH/VPOP list of S regs DPR_LIST, // VLDM/VSTM list of D regs SPR_ELEM, // S<n> with no extra shape info DPR_ELEM, // D<n>[lane] for scalar-FP-in-SIMD operations QPR_ELEM, // Q<n>[lane] // ---- Immediates ---- IMM, // generic immediate (sized per encoding) IMM_MOD, // A32 modified-immediate (8-bit + 4-bit rotate) IMM_T32_MOD, // Thumb-2 modified-immediate (similar but distinct encoding) IMM16_LO_HI, // MOVW/MOVT 16-bit immediate split into imm4 + imm12 IMM12, // unsigned 12-bit (LDR/STR offset) IMM5, // 5-bit (shift_imm, BFC/BFI lsb) IMM5_W, // 5-bit field width (BFC/BFI/SBFX/UBFX) IMM4, // 4-bit (rotate, ext rotation amount) IMM4_SAT, // SSAT/USAT saturation amount IMM8, // 8-bit (NEON VMOV, ConstantPool index, etc.) IMM3, // 3-bit Thumb register-encoded immediate IMM_HINT, // hint number (DBG, HINT) IMM_BARRIER, // DMB/DSB/ISB barrier type IMM_ENDIAN, // 1-bit BE/LE for SETEND IMM_IFLAGS, // CPS iflags + mode IMM_BANKED, // banked register selector (MSR/MRS banked) IMM_SYSM, // 7-bit SYSm field IMM_COPROC, // coprocessor number 0..15 IMM_COPROC_OP, // coprocessor opcode (CDP / MCR / MRC: opcode1/2 fields) NEON_IMM, // NEON modified-immediate (with cmode + abcdefgh) // ---- PC-relative ---- REL24, // A32 B / BL (signed 24-bit << 2) REL24_T32, // T32 B unconditional (J1/J2 + imm10 + imm11) REL20, // T32 B<cond> (signed 20-bit equivalent) REL11, // T16 B<cond> REL8, // T16 conditional branch (signed 8-bit) REL_LDR_LITERAL, // PC-relative literal load offset REL_BF, // ARMv8.1-M Branch Future label (bf-point / branch target) // ---- Condition code ---- COND, // 4-bit cond field (for IT block / B<cond> / etc.) // ---- Memory ---- MEM, // memory operand; addressing mode in operand payload // ---- Coprocessor ---- COPROC_REG, // CRn / CRm (coprocessor register identifier) COPROC_NUM, // pX (coprocessor number 0..15) // ---- Misc ---- PSR_FIELD, // APSR/CPSR field selector (_nzcvq, _g, _nzcvqg, _s, _x, _c) // ---- ARMv8-M / MVE / CDE operand classes ---- VPR, // VPR predicate register (single; bit-wise predicate state) QPR_MVE, // MVE Q-register (Q0..Q7; 3-bit index; bit 22 = 0 always) QPR_MVE_LIST, // MVE multi-Q list (e.g. VLD2x2 etc.) MVE_VPT_MASK, // VPT block mask (4-bit then/else pattern) MVE_VCTP_SIZE, // 2-bit element-size selector for VCTP (B/H/W/D) MVE_LOOP_TGT, // low-overhead-loop branch target (WLS/LE/DLS imm) CDE_COPROC, // CDE coprocessor number 0..7 CDE_IMM, // CDE immediate (varies per CX1/CX2/CX3 form) CDE_VFP_REG, // CDE VCX1/2/3 destination S/D-reg }
Print_Options ¶
Print_Options :: rexcode_isa.Print_Options
Related Procedures With Parameters
Related Constants
Print_Result ¶
Print_Result :: rexcode_isa.Print_Result
Register ¶
Register :: distinct u16
Related Constants
- APSR
- BE
- CPSR
- D0
- D1
- D10
- D11
- D12
- D13
- D14
- D15
- D16
- D17
- D18
- D19
- D2
- D20
- D21
- D22
- D23
- D24
- D25
- D26
- D27
- D28
- D29
- D3
- D30
- D31
- D4
- D5
- D6
- D7
- D8
- D9
- FP
- FPEXC
- FPSCR
- FPSID
- IP
- LE
- LR
- MVFR0
- MVFR1
- MVFR2
- PC
- Q0
- Q1
- Q10
- Q11
- Q12
- Q13
- Q14
- Q15
- Q2
- Q3
- Q4
- Q5
- Q6
- Q7
- Q8
- Q9
- R0
- R1
- R10
- R11
- R12
- R13
- R14
- R15
- R2
- R3
- R4
- R5
- R6
- R7
- R8
- R9
- S0
- S1
- S10
- S11
- S12
- S13
- S14
- S15
- S16
- S17
- S18
- S19
- S2
- S20
- S21
- S22
- S23
- S24
- S25
- S26
- S27
- S28
- S29
- S3
- S30
- S31
- S4
- S5
- S6
- S7
- S8
- S9
- SB
- SL
- SP
- SPSR
Relocation_Type ¶
Relocation_Type :: enum u8 { NONE = 0, // A32 branches BRANCH_A32_24, // B / BL, 24-bit signed << 2 BLX_A32, // BLX imm, 24-bit signed << 2 + H bit at bit 24 // T32 branches BRANCH_T32_25, // T32 B unconditional (J1/J2 + imm10 + imm11) BRANCH_T32_21, // T32 B<cond> (S + cond + imm6 + J1/J2 + imm11) // T16 branches BRANCH_T16_11, // T16 B unconditional (signed 11-bit << 1) BRANCH_T16_8, // T16 B<cond> (signed 8-bit << 1) BRANCH_T16_CBZ, // T16 CBZ/CBNZ (i + imm5 + Rn) // T32 low-overhead loops (ARMv8.1-M) BRANCH_T32_WLS, // WLS / WLSTP imm11 BRANCH_T32_LE, // LE / LETP imm11 // T32 Branch Future (ARMv8.1-M) BF_BOFF_T32, // bf-point: imm4 at hw0[10:7] = (label - (PC+4))/2 BF_BLOC_T32, // branch target: J at hw1[11] + imm10 at hw1[10:1] // Literal load (ADR / LDR PC-rel) LDR_LITERAL_A32, // signed 12-bit (U bit + imm12) LDR_LITERAL_T32, // signed 12-bit (U bit + imm12) Thumb-2 LDR_LITERAL_T16, // unsigned 8-bit << 2 (Thumb-1 PC-rel) ADR_A32, // ADR encoded as ADD/SUB to PC ADR_T32, ADR_T16, // Thumb-1 ADR (imm8 << 2) // Absolute forms via MOVW + MOVT pair MOVW_ABS, // imm16 low half MOVT_ABS, // imm16 high half }
Shift_Type ¶
Shift_Type :: enum u8 { LSL = 0, LSR = 1, ASR = 2, ROR = 3, RRX = 4, // pseudo: encoded as ROR #0 NONE = 5, // Register-shifted-register markers: the shift count comes from the Rs // register stored in shift_amt (0..15), not from an immediate. Encoder // packs bits 11..8 = Rs, 6..5 = (type - LSL_REG) low 2 bits, bit 4 = 1. LSL_REG = 6, LSR_REG = 7, ASR_REG = 8, ROR_REG = 9, }
Token_Kind ¶
Token_Kind :: rexcode_isa.Token_Kind
Constants
One row per constant, under the prefix it shares with others.
| APSR | :: Register(REG_SREG | 0)---- Status / control registers --------------------------------------------- |
| BE | :: Register(REG_ENDIAN | 1) |
| COND_… 16 | |
|---|---|
| COND_AL | :: u32(0xE) |
| COND_CC | :: u32(0x3) |
| COND_CS | :: u32(0x2) |
| COND_EQ | :: u32(0x0)Condition code constants (cond field values). |
| COND_GE | :: u32(0xA) |
| COND_GT | :: u32(0xC) |
| COND_HI | :: u32(0x8) |
| COND_LE | :: u32(0xD) |
| COND_LS | :: u32(0x9) |
| COND_LT | :: u32(0xB) |
| COND_MI | :: u32(0x4) |
| COND_NE | :: u32(0x1) |
| COND_NV | :: u32(0xF)NV is "always" in encoding (also marks unconditional class) |
| COND_PL | :: u32(0x5) |
| COND_VC | :: u32(0x7) |
| COND_VS | :: u32(0x6) |
| CPSR | :: Register(REG_SREG | 1) |
| D0 | :: Register(REG_DPR | 0)---- VFP/NEON double-precision (D0..D31) ------------------------------------ |
| D1 | :: Register(REG_DPR | 1) |
| D10 | :: Register(REG_DPR | 10) |
| D11 | :: Register(REG_DPR | 11) |
| D12 | :: Register(REG_DPR | 12) |
| D13 | :: Register(REG_DPR | 13) |
| D14 | :: Register(REG_DPR | 14) |
| D15 | :: Register(REG_DPR | 15) |
| D16 | :: Register(REG_DPR | 16) |
| D17 | :: Register(REG_DPR | 17) |
| D18 | :: Register(REG_DPR | 18) |
| D19 | :: Register(REG_DPR | 19) |
| D2 | :: Register(REG_DPR | 2) |
| D20 | :: Register(REG_DPR | 20) |
| D21 | :: Register(REG_DPR | 21) |
| D22 | :: Register(REG_DPR | 22) |
| D23 | :: Register(REG_DPR | 23) |
| D24 | :: Register(REG_DPR | 24) |
| D25 | :: Register(REG_DPR | 25) |
| D26 | :: Register(REG_DPR | 26) |
| D27 | :: Register(REG_DPR | 27) |
| D28 | :: Register(REG_DPR | 28) |
| D29 | :: Register(REG_DPR | 29) |
| D3 | :: Register(REG_DPR | 3) |
| D30 | :: Register(REG_DPR | 30) |
| D31 | :: Register(REG_DPR | 31) |
| D4 | :: Register(REG_DPR | 4) |
| D5 | :: Register(REG_DPR | 5) |
| D6 | :: Register(REG_DPR | 6) |
| D7 | :: Register(REG_DPR | 7) |
| D8 | :: Register(REG_DPR | 8) |
| D9 | :: Register(REG_DPR | 9) |
| DECODE_T32_SUB_BUCKETS | :: 32 |
| DEFAULT_PRINT_OPTIONS | : rexcode_isa.Print_Options : isa.DEFAULT_PRINT_OPTIONS |
| FP | : Register : R11frame pointer |
| FPEXC | :: Register(REG_FPSC | 8) |
| FPSCR | :: Register(REG_FPSC | 1) |
| FPSID | :: Register(REG_FPSC | 0) |
| IP | : Register : R12intra-procedure scratch |
| LABEL_UNDEFINED | : rexcode_isa.Label_Definition : isa.LABEL_UNDEFINED |
| LE | :: Register(REG_ENDIAN | 0)FPSCR / FPSID and friends |
| LR | : Register : R14link register |
| MASK_… 12 | |
| MASK_COND | :: u32(0xF0000000)bits 31-28 |
| MASK_IMM12 | :: u32(0x00000FFF)bits 11-0 |
| MASK_IMM24 | :: u32(0x00FFFFFF)bits 23-0 |
| MASK_OPCODE_HI | :: u32(0x0FE00000)bits 27-25 (selects encoding class) + 24-21 (op) |
| MASK_RD_A32 | :: u32(0x0000F000)bits 15-12 |
| MASK_RLIST | :: u32(0x0000FFFF)bits 15-0 |
| MASK_RM_A32 | :: u32(0x0000000F)bits 3-0 |
| MASK_RN_A32 | :: u32(0x000F0000)bits 19-16 |
| MASK_RS_A32 | :: u32(0x00000F00)bits 11-8 |
| MASK_SHIFT_IMM | :: u32(0x00000F80)bits 11-7 |
| MASK_SHIFT_TYPE | :: u32(0x00000060)bits 6-5 |
| MASK_S_FLAG | :: u32(0x00100000)bit 20 |
| MAX_INST_SIZE | :: 4 |
| MVFR0 | :: Register(REG_FPSC | 7) |
| MVFR1 | :: Register(REG_FPSC | 6) |
| MVFR2 | :: Register(REG_FPSC | 5) |
| PC | : Register : R15program counter |
| PSR_… 8 | |
| PSR_FIELD_ALL | : u8 : PSR_FIELD_F | PSR_FIELD_S | PSR_FIELD_X | PSR_FIELD_C |
| PSR_FIELD_C | :: u8(1 << 0) |
| PSR_FIELD_F | :: u8(1 << 3) |
| PSR_FIELD_G | : u8 : PSR_FIELD_X |
| PSR_FIELD_NZCVQ | : u8 : PSR_FIELD_F_nzcvq = F bit (flags) _g = X bit (GE bits, ARMv6+) _nzcvqg = F | X _all (cpsr_all) …_nzcvq = F bit (flags) _g = X bit (GE bits, ARMv6+) _nzcvqg = F | X _all (cpsr_all) = F | S | X | C |
| PSR_FIELD_NZCVQG | : u8 : PSR_FIELD_F | PSR_FIELD_X |
| PSR_FIELD_S | :: u8(1 << 2) |
| PSR_FIELD_X | :: u8(1 << 1) |
| Q0 | :: Register(REG_QPR | 0)---- NEON quad-word (Q0..Q15) ----------------------------------------------- |
| Q1 | :: Register(REG_QPR | 1) |
| Q10 | :: Register(REG_QPR | 10) |
| Q11 | :: Register(REG_QPR | 11) |
| Q12 | :: Register(REG_QPR | 12) |
| Q13 | :: Register(REG_QPR | 13) |
| Q14 | :: Register(REG_QPR | 14) |
| Q15 | :: Register(REG_QPR | 15) |
| Q2 | :: Register(REG_QPR | 2) |
| Q3 | :: Register(REG_QPR | 3) |
| Q4 | :: Register(REG_QPR | 4) |
| Q5 | :: Register(REG_QPR | 5) |
| Q6 | :: Register(REG_QPR | 6) |
| Q7 | :: Register(REG_QPR | 7) |
| Q8 | :: Register(REG_QPR | 8) |
| Q9 | :: Register(REG_QPR | 9) |
| R0 | :: Register(REG_GPR | 0)---- GPR --------------------------------------------------------------------- |
| R1 | :: Register(REG_GPR | 1) |
| R10 | :: Register(REG_GPR | 10) |
| R11 | :: Register(REG_GPR | 11) |
| R12 | :: Register(REG_GPR | 12) |
| R13 | :: Register(REG_GPR | 13) |
| R14 | :: Register(REG_GPR | 14) |
| R15 | :: Register(REG_GPR | 15) |
| R2 | :: Register(REG_GPR | 2) |
| R3 | :: Register(REG_GPR | 3) |
| R4 | :: Register(REG_GPR | 4) |
| R5 | :: Register(REG_GPR | 5) |
| R6 | :: Register(REG_GPR | 6) |
| R7 | :: Register(REG_GPR | 7) |
| R8 | :: Register(REG_GPR | 8) |
| R9 | :: Register(REG_GPR | 9) |
| REG_… 13 | |
| REG_BANKED | :: u16(0x7000) |
| REG_CLASS_MASK | :: u16(0xF000) |
| REG_COPROC | :: u16(0x8000) |
| REG_COPROC_NUM | :: u16(0xA000)A coprocessor number is written p15, not as a plain number, and it is a different thing from the CRn/CRm registers REG_COPROC names.A coprocessor number is written |
| REG_DPR | :: u16(0x3000) |
| REG_ENDIAN | :: u16(0x9000)SETEND names its argument le or be.SETEND names its argument |
| REG_FPSC | :: u16(0x6000) |
| REG_GPR | :: u16(0x1000) |
| REG_HW_MASK | :: u16(0x0FFF) |
| REG_NONE | :: u16(0x0000) |
| REG_QPR | :: u16(0x4000) |
| REG_SPR | :: u16(0x2000) |
| REG_SREG | :: u16(0x5000) |
| S0 | :: Register(REG_SPR | 0)---- VFP single-precision --------------------------------------------------- |
| S1 | :: Register(REG_SPR | 1) |
| S10 | :: Register(REG_SPR | 10) |
| S11 | :: Register(REG_SPR | 11) |
| S12 | :: Register(REG_SPR | 12) |
| S13 | :: Register(REG_SPR | 13) |
| S14 | :: Register(REG_SPR | 14) |
| S15 | :: Register(REG_SPR | 15) |
| S16 | :: Register(REG_SPR | 16) |
| S17 | :: Register(REG_SPR | 17) |
| S18 | :: Register(REG_SPR | 18) |
| S19 | :: Register(REG_SPR | 19) |
| S2 | :: Register(REG_SPR | 2) |
| S20 | :: Register(REG_SPR | 20) |
| S21 | :: Register(REG_SPR | 21) |
| S22 | :: Register(REG_SPR | 22) |
| S23 | :: Register(REG_SPR | 23) |
| S24 | :: Register(REG_SPR | 24) |
| S25 | :: Register(REG_SPR | 25) |
| S26 | :: Register(REG_SPR | 26) |
| S27 | :: Register(REG_SPR | 27) |
| S28 | :: Register(REG_SPR | 28) |
| S29 | :: Register(REG_SPR | 29) |
| S3 | :: Register(REG_SPR | 3) |
| S30 | :: Register(REG_SPR | 30) |
| S31 | :: Register(REG_SPR | 31) |
| S4 | :: Register(REG_SPR | 4) |
| S5 | :: Register(REG_SPR | 5) |
| S6 | :: Register(REG_SPR | 6) |
| S7 | :: Register(REG_SPR | 7) |
| S8 | :: Register(REG_SPR | 8) |
| S9 | :: Register(REG_SPR | 9) |
| SB | : Register : R9Conventional aliases |
| SHIFT_… 5 | |
| SHIFT_ASR | :: u32(2) |
| SHIFT_LSL | :: u32(0)Shift type field values (A32 bits 6-5). |
| SHIFT_LSR | :: u32(1) |
| SHIFT_ROR | :: u32(3) |
| SHIFT_RRX | :: u32(3)encoded as ROR #0 |
| SL | : Register : R10stack limit |
| SP | : Register : R13stack pointer |
| SPSR | :: Register(REG_SREG | 2) |
Variables
DECODE_BUCKET_LIST ¶
@(rodata) DECODE_BUCKET_LIST: []u16 = …
DECODE_ENTRIES ¶
@(rodata) DECODE_ENTRIES: []Decode_Entry = …
DECODE_FORM_IDX ¶
@(rodata) DECODE_FORM_IDX: []u16 = …
DECODE_INDEX_A32 ¶
@(rodata) DECODE_INDEX_A32: []Decode_Index = …
DECODE_INDEX_T16 ¶
@(rodata) DECODE_INDEX_T16: []Decode_Index = …
DECODE_INDEX_T32 ¶
@(rodata) DECODE_INDEX_T32: []Decode_Index = …
DECODE_INDEX_T32_SUB ¶
@(rodata) DECODE_INDEX_T32_SUB: []Decode_Index = …
ENCODE_FORMS ¶
@(rodata) ENCODE_FORMS: []Encoding = …
ENCODE_RUNS ¶
@(rodata) ENCODE_RUNS: []Encode_Run = …
Procedures
One row per procedure, under the procedure groups they belong to; each is a proc "contextless" unless it says otherwise.
Procedure Groups
Listed with their procedures under Procedures.
Source Files
- decoder.odin
- encoder.odin
- encoding_types.odin
- immediates.odin
- instructions.odin
- mnemonic_builders.odin
- mnemonics.odin
- operands.odin
- printer.odin
- registers.odin
- reloc.odin
- tables.odin
Generation Information
Generated with odin version dev-2026-10 (vendor "odin") Windows_amd64 @ 2026-10-10 00:25:51.511820200 +0000 UTC