kit

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

commit 8fc2220a22d992bfc53306be9c34ffa9ef6c5601
parent 6ddf35a70674161ac4cccecf126763cc566e8c50
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri, 29 May 2026 14:24:30 -0700

aa64 asm: encode byte/half and signed sub-word loads/stores

p_ldr_str hardwired the access size to the register width (word/dword), so the
assembler had no ldrb/strb/ldrh/strh/ldrsb/ldrsh/ldrsw. Generalize it to
p_ldst_core(is_load, fixed_size, sign_ext): byte/half use a fixed size; signed
loads pick opc 10/11 (sign-extend to 64-/32-bit) by destination width.
Byte-identical to clang; adds aa64_ldst_subword corpus case.

Diffstat:
Msrc/arch/aa64/asm.c | 34+++++++++++++++++++++++++++++++---
Atest/asm/encode/aa64_ldst_subword.expected.hex | 1+
Atest/asm/encode/aa64_ldst_subword.s | 14++++++++++++++
Atest/asm/encode/aa64_ldst_subword.targets | 2++
4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/arch/aa64/asm.c b/src/arch/aa64/asm.c @@ -935,13 +935,21 @@ static AA64Mem parse_mem(AsmDriver* d) { /* ldr/str Rt, [Xn, #imm] — chooses scaled or unscaled form based on * alignment of imm. */ -static void p_ldr_str(AsmDriver* d, int is_load) { +/* Core load/store. `fixed_size` is the access log2-size (0=byte..3=dword) for + * ldrb/ldrh/ldrsw etc., or -1 to derive it from the register width (ldr/str). + * `sign_ext` selects the signed-load opc (10 = sign-extend to 64-bit, 11 = to + * 32-bit), keyed on the destination register width. */ +static void p_ldst_core(AsmDriver* d, int is_load, int fixed_size, + int sign_ext) { AA64Reg rt = parse_reg(d); reject_sp_reg(d, rt, "ldr/str"); expect_comma(d, "ldr/str"); AA64Mem m = parse_mem(d); - u32 size = rt.is64 ? 3u : 2u; - u32 opc = is_load ? AA64_LDST_OPC_LDR : AA64_LDST_OPC_STR; + u32 size = (fixed_size >= 0) ? (u32)fixed_size : (rt.is64 ? 3u : 2u); + u32 opc = !is_load ? AA64_LDST_OPC_STR + : !sign_ext ? AA64_LDST_OPC_LDR + : rt.is64 ? 2u /* LDRS*, 64-bit dst */ + : 3u; /* LDRS*, 32-bit dst */ if (!m.pre_index) { /* Try scaled unsigned-imm12 first. */ u32 scale = 1u << size; @@ -974,6 +982,19 @@ static void p_ldr_str(AsmDriver* d, int is_load) { asm_driver_panic(d, "asm: ldr/str: pre-indexed form not yet supported"); } +/* ldr/str: access width follows the register (Wt=word, Xt=dword). */ +static void p_ldr_str(AsmDriver* d, int is_load) { + p_ldst_core(d, is_load, /*fixed_size=*/-1, /*sign_ext=*/0); +} +/* Byte/half + signed sub-word loads/stores (fixed access width). */ +static void p_ldrb(AsmDriver* d) { p_ldst_core(d, 1, 0, 0); } +static void p_strb(AsmDriver* d) { p_ldst_core(d, 0, 0, 0); } +static void p_ldrh(AsmDriver* d) { p_ldst_core(d, 1, 1, 0); } +static void p_strh(AsmDriver* d) { p_ldst_core(d, 0, 1, 0); } +static void p_ldrsb(AsmDriver* d) { p_ldst_core(d, 1, 0, 1); } +static void p_ldrsh(AsmDriver* d) { p_ldst_core(d, 1, 1, 1); } +static void p_ldrsw(AsmDriver* d) { p_ldst_core(d, 1, 2, 1); } + /* ldur/stur — unscaled signed-imm9. */ static void p_ldur_stur(AsmDriver* d, int is_load) { AA64Reg rt = parse_reg(d); @@ -1399,6 +1420,13 @@ static const AA64Mn kTable[] = { {"hlt", p_hlt_, 0}, {"ldr", p_ldr_, 0}, {"str", p_str_, 0}, + {"ldrb", p_ldrb, 0}, + {"strb", p_strb, 0}, + {"ldrh", p_ldrh, 0}, + {"strh", p_strh, 0}, + {"ldrsb", p_ldrsb, 0}, + {"ldrsh", p_ldrsh, 0}, + {"ldrsw", p_ldrsw, 0}, {"ldur", p_ldur_, 0}, {"stur", p_stur_, 0}, {"ldp", p_ldp_, 0}, diff --git a/test/asm/encode/aa64_ldst_subword.expected.hex b/test/asm/encode/aa64_ldst_subword.expected.hex @@ -0,0 +1 @@ +2000403962104039a4040039e6044079280d00796a018039ac0dc039ee118079300680b9200840b9620840f9c0035fd6 diff --git a/test/asm/encode/aa64_ldst_subword.s b/test/asm/encode/aa64_ldst_subword.s @@ -0,0 +1,14 @@ +.text +t: + ldrb w0, [x1] + ldrb w2, [x3, #4] + strb w4, [x5, #1] + ldrh w6, [x7, #2] + strh w8, [x9, #6] + ldrsb x10, [x11] + ldrsb w12, [x13, #3] + ldrsh x14, [x15, #8] + ldrsw x16, [x17, #4] + ldr w0, [x1, #8] + ldr x2, [x3, #16] + ret diff --git a/test/asm/encode/aa64_ldst_subword.targets b/test/asm/encode/aa64_ldst_subword.targets @@ -0,0 +1 @@ +aa64 +\ No newline at end of file