kit

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

commit c7fed8abc537edbc37702a44e41072127053dd46
parent 8198e7ccb0d435aa17347041a18771fd3c9f7359
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri, 29 May 2026 15:15:33 -0700

aa64 disasm: decode signed sub-word loads (ldrsb/ldrsh/ldrsw)

Adds the 5 unsigned-imm12 decode rows (opc=10 -> X dst, opc=11 -> W dst) and
makes print_ldst_uimm derive the destination width from opc. These previously
rendered as .inst. Corpus: decode/aa64_ldrs_subword.

Diffstat:
Msrc/arch/aa64/isa.c | 35++++++++++++++++++++++++++++++++---
Atest/asm/decode/aa64_ldrs_subword.expected.txt | 5+++++
Atest/asm/decode/aa64_ldrs_subword.hex | 1+
Atest/asm/decode/aa64_ldrs_subword.targets | 1+
4 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/src/arch/aa64/isa.c b/src/arch/aa64/isa.c @@ -25,6 +25,14 @@ /* Mnemonic Slice literal for a static table row (compile-time length). */ #define MN(s) {{(s)}, sizeof(s) - 1} +/* Load/store unsigned-imm12 opc field values for the V=0 signed sub-word + * loads. opc=00/01 are STR/LDR (AA64_LDST_OPC_STR/LDR in isa.h); the signed + * loads reuse the same size/imm12 layout but sign-extend the loaded value: + * opc=10 (LDRS_X) sign-extends to the 64-bit X destination, + * opc=11 (LDRS_W) sign-extends to the 32-bit W destination. */ +#define AA64_LDST_OPC_LDRS_X 2u +#define AA64_LDST_OPC_LDRS_W 3u + const AA64InsnDesc aa64_insn_table[] = { /* ----- Move-wide immediate (MOVN / MOVZ / MOVK) ----- */ {MN("movn"), 0x12800000u, 0x7F800000u, AA64_FMT_MOVEWIDE, 0, {0, 0}}, @@ -176,7 +184,21 @@ const AA64InsnDesc aa64_insn_table[] = { {MN("subs"), 0x71000000u, 0x7F000000u, AA64_FMT_ADDSUB_IMM, 0, {0, 0}}, /* ----- Load/store, unsigned 12-bit immediate (scaled) ----- - * Mask: family bits 29:27 + 25:24 + size(31:30) + V(26) + opc(23:22). */ + * Mask: family bits 29:27 + 25:24 + size(31:30) + V(26) + opc(23:22). + * + * Signed sub-word loads (LDRSB/LDRSH/LDRSW) share this exact format but + * select opc=10 (sign-extend to X) or opc=11 (sign-extend to W). They + * are listed BEFORE the unsigned STR/LDR rows so first-match-wins picks + * the signed spelling (the masks are disjoint by opc, so the relative + * order is not load-bearing, but keeping them first documents intent). + * size=00 opc=10 LDRSB Xt ; size=00 opc=11 LDRSB Wt + * size=01 opc=10 LDRSH Xt ; size=01 opc=11 LDRSH Wt + * size=10 opc=10 LDRSW Xt (no Wt form: that opc=11 slot is PRFUM). */ + {MN("ldrsb"), 0x39800000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, + {MN("ldrsb"), 0x39C00000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, + {MN("ldrsh"), 0x79800000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, + {MN("ldrsh"), 0x79C00000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, + {MN("ldrsw"), 0xB9800000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, {MN("strb"), 0x39000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, {MN("ldrb"), 0x39400000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, {MN("strh"), 0x79000000u, 0xFFC00000u, AA64_FMT_LDST_UIMM, 0, {0, 0}}, @@ -660,9 +682,16 @@ static u32 ldst_log2_size(const AA64InsnDesc* d, u32 size_field) { static void print_ldst_uimm(StrBuf* sb, u32 w, const AA64InsnDesc* d) { AA64LdStUimm f = aa64_ldst_uimm_unpack(w); u32 sz = ldst_log2_size(d, f.size); - /* Pick reg prefix: V=0 picks W/X by size; V=1 picks B/H/S/D by size. */ + /* Pick reg prefix: V=0 picks W/X; V=1 picks B/H/S/D by size. + * For V=0 the destination width follows opc: the signed sub-word loads + * (opc=10 LDRS_X, opc=11 LDRS_W) name an X or W register independent of + * the access size; the plain STR/LDR (opc<=01) use X only for size=11. */ if (f.V == 0) { - emit_reg(sb, f.Rt, /*sf=*/(int)(sz == 3u), 0); + int sf = (f.opc == AA64_LDST_OPC_LDRS_X) ? 1 + : (f.opc == AA64_LDST_OPC_LDRS_W) + ? 0 + : (int)(sz == 3u); + emit_reg(sb, f.Rt, sf, 0); } else { char p = (sz == 0u) ? 'b' : (sz == 1u) ? 'h' : (sz == 2u) ? 's' : 'd'; emit_vreg(sb, f.Rt, p); diff --git a/test/asm/decode/aa64_ldrs_subword.expected.txt b/test/asm/decode/aa64_ldrs_subword.expected.txt @@ -0,0 +1,5 @@ +0: ldrsb x10, [x11] +4: ldrsb w12, [x13, #3] +8: ldrsh x14, [x15, #8] +c: ldrsw x16, [x17, #4] +10: ldrsh w0, [x1, #2] diff --git a/test/asm/decode/aa64_ldrs_subword.hex b/test/asm/decode/aa64_ldrs_subword.hex @@ -0,0 +1 @@ +6a 01 80 39 ac 0d c0 39 ee 11 80 79 30 06 80 b9 20 04 c0 79 diff --git a/test/asm/decode/aa64_ldrs_subword.targets b/test/asm/decode/aa64_ldrs_subword.targets @@ -0,0 +1 @@ +aa64