kit

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

commit 4f9d8c341c11e0ed72c7621b6517c47a9159d25f
parent beb0ad1e2b1f44d0c85a4de95c4481e7feb7e552
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed, 17 Jun 2026 00:54:38 -0700

arm32: leave __ARM_FP undefined on soft-float; add UDF

Two prerequisites for the kit-self-built runtime (§3):
- __ARM_FP was predefined to 0, so the coroutine register-save asm's
  `#ifdef __ARM_FP` selected the VFP (d8..d15 vstr/vldr) path on a soft-float
  build. clang/gcc leave __ARM_FP UNDEFINED when there is no hardware FP; match
  that so the integer path is taken.
- UDF #imm8 (T1) — the coro trampoline traps a returned entry fn with `udf #0`.
  Add the encoder + descriptor row (BKPT-shaped imm8) + assembler case.

Diffstat:
Msrc/arch/arm32/arch.c | 5++++-
Msrc/arch/arm32/asm.c | 2+-
Msrc/arch/arm32/isa.c | 3+++
Msrc/arch/arm32/isa.h | 3+++
4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/arch/arm32/arch.c b/src/arch/arm32/arch.c @@ -129,7 +129,10 @@ static const KitPredefinedMacro arm32_predefined_macros[] = { {KIT_SLICE_LIT("__ARM_EABI__"), KIT_SLICE_LIT("1")}, {KIT_SLICE_LIT("__ARM_PCS"), KIT_SLICE_LIT("1")}, {KIT_SLICE_LIT("__SOFTFP__"), KIT_SLICE_LIT("1")}, - {KIT_SLICE_LIT("__ARM_FP"), KIT_SLICE_LIT("0")}, + /* __ARM_FP is a bitmask of hardware FP precisions; on soft-float it is left + * UNDEFINED (not 0), matching clang/gcc — `#ifdef __ARM_FP` then correctly + * selects the integer code path (e.g. the coroutine register-save asm skips + * the d8..d15 VFP saves). A hard-float variant will define it. */ {KIT_SLICE_LIT("__ARM_FEATURE_CLZ"), KIT_SLICE_LIT("1")}, {KIT_SLICE_LIT("__ARM_FEATURE_IDIV"), KIT_SLICE_LIT("1")}, {KIT_SLICE_LIT("__ARM_FEATURE_UNALIGNED"), KIT_SLICE_LIT("1")}, diff --git a/src/arch/arm32/asm.c b/src/arch/arm32/asm.c @@ -660,7 +660,7 @@ static void assemble_one(AsmDriver* d, const Arm32InsnDesc* desc, u32 cond) { } case ARM_FMT_BKPT: { u32 imm8 = (u32)parse_imm(d) & 0xffu; - emit_t16(d, arm_bkpt(imm8)); + emit_t16(d, slice_eq_cstr(mn, "udf") ? arm_udf(imm8) : arm_bkpt(imm8)); return; } case ARM_FMT_EXT16: { diff --git a/src/arch/arm32/isa.c b/src/arch/arm32/isa.c @@ -250,6 +250,9 @@ const Arm32InsnDesc arm32_insn_table[] = { * mask==0 hint; pin mask nonzero is implicit by ordering after the hints. */ {MN("it"), 0x0000bf00u, 0x0000ff00u, ARM_FMT_IT, ARM_FMT_W16, {0}}, {MN("bkpt"), 0x0000be00u, 0x0000ff00u, ARM_FMT_BKPT, ARM_FMT_W16, {0}}, + /* UDF #imm8 (T1, 0xDExx): same imm8 shape as BKPT, decoded after the 0xB0xx + * hint/branch block so it does not shadow a tighter match. */ + {MN("udf"), 0x0000de00u, 0x0000ff00u, ARM_FMT_BKPT, ARM_FMT_W16, {0}}, /* CBZ/CBNZ: 0xB1xx (op=0)/0xB9xx (op=1); mask the i/imm5/rn fields. */ {MN("cbz"), 0x0000b100u, 0x0000fd00u, ARM_FMT_CBZ, ARM_FMT_W16, {0}}, {MN("cbnz"), 0x0000b900u, 0x0000fd00u, ARM_FMT_CBZ, ARM_FMT_W16, {0}}, diff --git a/src/arch/arm32/isa.h b/src/arch/arm32/isa.h @@ -281,6 +281,9 @@ static inline u32 arm_bl(void) { return arm_t32(0xf7ffu, 0xfffeu); } /* B static inline u16 arm_bx(u32 rm) { return (u16)(0x4700u | (rm << 3)); } static inline u16 arm_blx_reg(u32 rm) { return (u16)(0x4780u | (rm << 3)); } static inline u16 arm_bkpt(u32 imm8) { return (u16)(0xbe00u | (imm8 & 0xffu)); } +/* UDF #imm8 (T1, permanently undefined) — the coroutine trampoline's trap on a + * returned entry fn. Same 16-bit imm8 shape as BKPT, different opcode. */ +static inline u16 arm_udf(u32 imm8) { return (u16)(0xde00u | (imm8 & 0xffu)); } static inline u16 arm_nop16(void) { return (u16)0xbf00u; } /* NOP.W (32-bit) — pads a multi-slot prologue placeholder region. */ static inline u32 arm_nop32(void) { return arm_t32(0xf3afu, 0x8000u); }