kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit a093cd3a04ccea2aff751e618e07ff77befa396c
parent 4f9d8c341c11e0ed72c7621b6517c47a9159d25f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed, 17 Jun 2026 01:01:12 -0700

arm32 as: cmp/mov accept a modified-immediate second operand

The standalone assembler resolved `cmp`/`mov` to their hi-register forms and
parsed a fixed two registers, so `cmp rn, #imm` / `mov rd, #imm` (and the
IT-predicated `moveq rd, #imm`) errored 'bad core register' on the immediate.
Peek the operand shape: cmp emits the 16-bit DPI8 compare (rn<=r7, imm8) or
32-bit cmp.w; mov emits mov.w (no-flags, IT-conditionalizable). This is what the
hand-written coroutine register-switch asm (rt/lib/coro/arm32.c) needs to build
with kit's own assembler — it now does, end to end.

Diffstat:
Msrc/arch/arm32/asm.c | 24++++++++++++++++++++++++
1 file changed, 24 insertions(+), 0 deletions(-)

diff --git a/src/arch/arm32/asm.c b/src/arch/arm32/asm.c @@ -649,6 +649,15 @@ static void assemble_one(AsmDriver* d, const Arm32InsnDesc* desc, u32 cond) { case ARM_FMT_MOVHI16: { u32 rd = parse_reg(d), rm; expect_comma(d); + /* `mov rd, #imm` selects the 32-bit mov.w (preserving mov's no-flags + * semantics; conditionalizable inside an IT block as `moveq`/etc.). */ + if (!peek_is_reg(d)) { + u32 out12; + if (!thumb_expand_imm_encode((u32)parse_imm(d), &out12)) + asm_driver_panic(d, "arm32 asm: mov immediate not encodable"); + emit_t32(d, arm_mov_imm(rd, out12)); + return; + } rm = parse_reg(d); emit_t16(d, arm_mov_hi(rd, rm)); return; @@ -721,6 +730,21 @@ static void assemble_one(AsmDriver* d, const Arm32InsnDesc* desc, u32 cond) { case ARM_FMT_HIREG_16: { u32 rdn = parse_reg(d), rm; expect_comma(d); + /* `cmp` resolves to this hi-register compare first; an immediate second + * operand (`cmp rn, #imm`) selects the modified-immediate compare — the + * 16-bit DPI8 form when rn<=r7 and imm8 fits, else the 32-bit cmp.w. */ + if (!peek_is_reg(d) && slice_eq_cstr(mn, "cmp")) { + i64 imm = parse_imm(d); + if (rdn <= 7u && imm >= 0 && imm <= 255) + emit_t16(d, (u16)(0x2800u | (rdn << 8) | (u32)(imm & 0xffu))); + else { + u32 out12; + if (!thumb_expand_imm_encode((u32)imm, &out12)) + asm_driver_panic(d, "arm32 asm: cmp immediate not encodable"); + emit_t32(d, arm_cmp_imm(rdn, out12)); + } + return; + } rm = parse_reg(d); emit_t16(d, (u16)((desc->match & 0xff00u) | (((rdn >> 3) & 1u) << 7) | ((rm & 0xfu) << 3) | (rdn & 7u)));