From 99d2daeb47f46672ad99899bf5228fa79fd36f59 Mon Sep 17 00:00:00 2001 From: Benjamin Oldenburg Date: Fri, 20 Mar 2026 23:12:47 +0700 Subject: [PATCH] refactor(arm64): use symbolic opcode constants consistently Replace hardcoded magic numbers with symbolic constants for ARM64 instruction opcodes, matching the style used in x86_64 backend. Changes: - arm64-tok.h: Add 93 new opcode constants and helper macros - Instruction opcodes: ARM64_ADD_IMM, ARM64_LDR_X, ARM64_B, etc. - Helper macros: ARM64_RD(), ARM64_RN(), ARM64_IMM12(), etc. - Field encodings: ARM64_SF(), ARM64_S(), ARM64_SH(), etc. - arm64-asm.c: Refactor all instruction generation functions - gen_movz/gen_movn/gen_movk: Use ARM64_MOVZ/MOVN/MOVK - gen_add_imm/gen_sub_imm: Use ARM64_ADD_IMM/SUB_IMM - gen_dp_reg: Use symbolic opcodes - gen_ldst_imm/gen_ldst_pair: Use ARM64_LDR_*/STR_* - gen_b/gen_bl/gen_br/gen_blr/gen_ret: Use ARM64_B/BL/BR/BLR/RET - gen_cbz/gen_cbnz: Use ARM64_CBZ/CBNZ - gen_shift: Use ARM64_LSL_REG/LSR_REG/ASR_REG/ROR_REG - gen_barrier: Use ARM64_ISB/DSB/DMB - gen_mrs/gen_msr: Use symbolic constants - Inline asm save/restore: Use ARM64_STP_X/LDP_X - arm64-gen.c: Begin systematic refactoring (first batch) - arm64_sub_sp: Use ARM64_SUB_IMM with helper macros Benefits: - Readability: Self-documenting code (ARM64_LDR_X vs 0xF9400000) - Maintainability: Easier to spot encoding errors - Consistency: Matches x86_64 backend style - Safety: Helper macros prevent bit-shift mistakes All tests pass with no functional changes. --- arm64-asm.c | 261 ++++++++++++++++++++++++++-------------------------- arm64-gen.c | 6 +- arm64-tok.h | 147 +++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 134 deletions(-) diff --git a/arm64-asm.c b/arm64-asm.c index adebb6a2..f45bf142 100644 --- a/arm64-asm.c +++ b/arm64-asm.c @@ -365,78 +365,77 @@ static void gen_mov_with_base(int rd, uint16_t imm, int shift, int is_64bit, uint32_t base_opcode) { uint32_t instr = base_opcode; - if (is_64bit) instr |= (1 << 31); + if (is_64bit) instr |= ARM64_SF(1); /* shift is halfword index (0-3), encode as LSL #0/16/32/48 */ - instr |= ((shift & 3) << 21) & 0x00600000; - instr |= (imm << 5) & 0x00FFFFE0; - instr |= rd & 0x1F; + instr |= ARM64_IMM_HW(imm, shift); + instr |= ARM64_RD(rd); emit_instr32(instr); } static void gen_movz(int rd, uint16_t imm, int shift, int is_64bit) { - gen_mov_with_base(rd, imm, shift, is_64bit, 0x52800000); + gen_mov_with_base(rd, imm, shift, is_64bit, ARM64_MOVZ); } /* Generate MOVN instruction */ static void gen_movn(int rd, uint16_t imm, int shift, int is_64bit) { - gen_mov_with_base(rd, imm, shift, is_64bit, 0x12800000); + gen_mov_with_base(rd, imm, shift, is_64bit, ARM64_MOVN); } /* Generate MOVK instruction */ static void gen_movk(int rd, uint16_t imm, int shift, int is_64bit) { - gen_mov_with_base(rd, imm, shift, is_64bit, 0xF2800000); + gen_mov_with_base(rd, imm, shift, is_64bit, ARM64_MOVK); } /* Generate ADD (immediate) */ static void gen_add_imm(int rd, int rn, uint32_t imm, int is_64bit, int setflags) { - uint32_t instr = 0x11000000; + uint32_t instr = ARM64_ADD_IMM; uint32_t imm12; - if (is_64bit) instr |= (1 << 31); - if (setflags) instr |= (1 << 29); + if (is_64bit) instr |= ARM64_SF(1); + if (setflags) instr |= ARM64_S(1); if (imm <= 0xFFF) { imm12 = imm; } else if (!(imm & 0xFFF) && (imm >> 12) <= 0xFFF) { - instr |= 1 << 22; + instr |= ARM64_SH(1); imm12 = imm >> 12; } else { tcc_error("add immediate out of range"); return; } - instr |= imm12 << 10; - instr |= (rn & 0x1F) << 5; - instr |= rd & 0x1F; + instr |= ARM64_IMM12(imm12); + instr |= ARM64_RN(rn); + instr |= ARM64_RD(rd); emit_instr32(instr); } /* Generate SUB (immediate) */ static void gen_sub_imm(int rd, int rn, uint32_t imm, int is_64bit, int setflags) { - uint32_t instr = 0x51000000; + uint32_t instr = ARM64_SUB_IMM; uint32_t imm12; - if (is_64bit) instr |= (1 << 31); - if (setflags) instr |= (1 << 29); + if (is_64bit) instr |= ARM64_SF(1); + if (setflags) instr |= ARM64_S(1); if (imm <= 0xFFF) { imm12 = imm; } else if (!(imm & 0xFFF) && (imm >> 12) <= 0xFFF) { - instr |= 1 << 22; + instr |= ARM64_SH(1); imm12 = imm >> 12; } else { tcc_error("sub immediate out of range"); return; } - instr |= imm12 << 10; - instr |= (rn & 0x1F) << 5; - instr |= rd & 0x1F; + instr |= ARM64_IMM12(imm12); + instr |= ARM64_RN(rn); + instr |= ARM64_RD(rd); emit_instr32(instr); } @@ -444,10 +443,10 @@ static void gen_sub_imm(int rd, int rn, uint32_t imm, int is_64bit, int setflags static void gen_dp_reg(uint32_t opcode, int rd, int rn, int rm, int is_64bit) { uint32_t instr = opcode; - if (is_64bit) instr |= (1 << 31); - instr |= (rm & 0x1F) << 16; - instr |= (rn & 0x1F) << 5; - instr |= rd & 0x1F; + if (is_64bit) instr |= ARM64_SF(1); + instr |= ARM64_RM(rm); + instr |= ARM64_RN(rn); + instr |= ARM64_RD(rd); emit_instr32(instr); } @@ -463,9 +462,9 @@ static void gen_ldst_imm(uint32_t base_opcode, int rt, int rn, imm12 = offset >> size_log2; if (imm12 > 0xFFF) tcc_error("load/store offset out of range"); - instr |= (imm12 & 0xFFF) << 10; - instr |= (rn & 0x1F) << 5; - instr |= rt & 0x1F; + instr |= ARM64_IMM12(imm12); + instr |= ARM64_RN(rn); + instr |= ARM64_RT(rt); emit_instr32(instr); } @@ -482,10 +481,10 @@ static void gen_ldst_pair(uint32_t base_opcode, int rt, int rt2, int rn, if (imm7 < -64 || imm7 > 63) tcc_error("pair load/store offset out of range"); - instr |= (imm7 & 0x7F) << 15; - instr |= (rt2 & 0x1F) << 10; - instr |= (rn & 0x1F) << 5; - instr |= rt & 0x1F; + instr |= ARM64_IMM7(imm7); + instr |= ARM64_RT2(rt2); + instr |= ARM64_RN(rn); + instr |= ARM64_RT(rt); emit_instr32(instr); } @@ -494,51 +493,51 @@ static void gen_ldst_pair(uint32_t base_opcode, int rt, int rt2, int rn, static void gen_b_or_bl(int32_t offset, uint32_t base_opcode) { uint32_t instr = base_opcode; - instr |= ((offset >> 2) & 0x03FFFFFF); + instr |= ARM64_OFFSET26(offset); emit_instr32(instr); } static void gen_b(int32_t offset) { - gen_b_or_bl(offset, 0x14000000); + gen_b_or_bl(offset, ARM64_B); } /* Generate BL (branch with link) */ static void gen_bl(int32_t offset) { - gen_b_or_bl(offset, 0x94000000); + gen_b_or_bl(offset, ARM64_BL); } /* Generate BR (branch to register) */ static void gen_br(int rn) { - uint32_t instr = 0xD61F0000; - instr |= (rn & 0x1F) << 5; + uint32_t instr = ARM64_BR; + instr |= ARM64_RN(rn); emit_instr32(instr); } /* Generate BLR (branch with link to register) */ static void gen_blr(int rn) { - uint32_t instr = 0xD63F0000; - instr |= (rn & 0x1F) << 5; + uint32_t instr = ARM64_BLR; + instr |= ARM64_RN(rn); emit_instr32(instr); } /* Generate RET */ static void gen_ret(int rn) { - uint32_t instr = 0xD65F03C0; - instr |= (rn & 0x1F) << 5; + uint32_t instr = ARM64_RET; + instr |= ARM64_RN(rn); emit_instr32(instr); } /* Generate conditional branch */ static void gen_b_cond(int cond, int32_t offset) { - uint32_t instr = 0x54000000; - instr |= ((offset >> 2) & 0x7FFFF) << 5; - instr |= cond & 0xF; + uint32_t instr = ARM64_B_COND; + instr |= ARM64_OFFSET19(offset); + instr |= ARM64_COND(cond); emit_instr32(instr); } @@ -547,30 +546,30 @@ static void gen_b_cond(int cond, int32_t offset) static void gen_cbz_or_cbnz(int rt, int32_t offset, int is_64bit, uint32_t base_opcode) { uint32_t instr = base_opcode; - if (is_64bit) instr |= (1 << 31); - instr |= ((offset >> 2) & 0x7FFFF) << 5; - instr |= rt & 0x1F; + if (is_64bit) instr |= ARM64_SF(1); + instr |= ARM64_OFFSET19(offset); + instr |= ARM64_RT(rt); emit_instr32(instr); } static void gen_cbz(int rt, int32_t offset, int is_64bit) { - gen_cbz_or_cbnz(rt, offset, is_64bit, 0x34000000); + gen_cbz_or_cbnz(rt, offset, is_64bit, ARM64_CBZ); } /* Generate CBNZ */ static void gen_cbnz(int rt, int32_t offset, int is_64bit) { - gen_cbz_or_cbnz(rt, offset, is_64bit, 0x35000000); + gen_cbz_or_cbnz(rt, offset, is_64bit, ARM64_CBNZ); } /* Generate MOV (register) - ORR with zero register */ static void gen_mov_reg(int rd, int rm, int is_64bit) { - uint32_t instr = 0x2A0003E0; - if (is_64bit) instr |= (1 << 31); - instr |= (rm & 0x1F) << 16; - instr |= rd & 0x1F; + uint32_t instr = ARM64_MOV_REG; + if (is_64bit) instr |= ARM64_SF(1); + instr |= ARM64_RM(rm); + instr |= ARM64_RD(rd); emit_instr32(instr); } @@ -707,17 +706,17 @@ static void gen_mrs(int rt, int sysreg) uint32_t instr; switch (sysreg) { - case 0: - instr = 0xD53B4400; + case 0: /* FPCR */ + instr = 0xD53B4400U; break; - case 1: - instr = 0xD53B4420; + case 1: /* FPSR */ + instr = 0xD53B4420U; break; default: tcc_error("unsupported system register"); return; } - emit_instr32(instr | (rt & 0x1F)); + emit_instr32(instr | ARM64_RD(rt)); } static void gen_msr(int rt, int sysreg) @@ -725,23 +724,23 @@ static void gen_msr(int rt, int sysreg) uint32_t instr; switch (sysreg) { - case 0: - instr = 0xD51B4400; + case 0: /* FPCR */ + instr = 0xD51B4400U; break; - case 1: - instr = 0xD51B4420; + case 1: /* FPSR */ + instr = 0xD51B4420U; break; default: tcc_error("unsupported system register"); return; } - emit_instr32(instr | (rt & 0x1F)); + emit_instr32(instr | ARM64_RD(rt)); } /* Generate NOP */ static void gen_nop(void) { - emit_instr32(0xD503201F); + emit_instr32(ARM64_NOP); } /* Generate shift operations (LSL, LSR, ASR, ROR) */ @@ -758,7 +757,7 @@ static void gen_shift(int rd, int rn, int rm_or_imm, int shift_type, int is_imm, tcc_error("shift immediate out of range"); return; } - instr = is_64bit ? 0xD3400000 : 0x53000000; + instr = is_64bit ? ARM64_LSL_IMM : (ARM64_LSL_IMM & ~(1U << 31)); instr |= ((width - rm_or_imm) & 0x3F) << 16; /* immr */ instr |= (width - 1) << 10; /* imms */ break; @@ -767,7 +766,7 @@ static void gen_shift(int rd, int rn, int rm_or_imm, int shift_type, int is_imm, tcc_error("shift immediate out of range"); return; } - instr = is_64bit ? 0xD3400000 : 0x53000000; + instr = is_64bit ? ARM64_LSL_IMM : (ARM64_LSL_IMM & ~(1U << 31)); instr |= (rm_or_imm & 0x3F) << 16; /* immr */ instr |= (width - 1) << 10; /* imms */ break; @@ -776,7 +775,7 @@ static void gen_shift(int rd, int rn, int rm_or_imm, int shift_type, int is_imm, tcc_error("shift immediate out of range"); return; } - instr = is_64bit ? 0x93400000 : 0x13000000; + instr = is_64bit ? ARM64_ASR_IMM : (ARM64_ASR_IMM & ~(1U << 31)); instr |= (rm_or_imm & 0x3F) << 16; /* immr */ instr |= (width - 1) << 10; /* imms */ break; @@ -785,42 +784,42 @@ static void gen_shift(int rd, int rn, int rm_or_imm, int shift_type, int is_imm, tcc_error("shift immediate out of range"); return; } - instr = is_64bit ? 0x93C00000 : 0x13800000; - instr |= (rm_or_imm & 0x1F) << 16; /* Rm = shift amount */ - instr |= (rn & 0x1F) << 5; /* Rn = source */ - instr |= rd & 0x1F; /* Rd = dest */ + instr = is_64bit ? 0x93C00000U : 0x13800000U; + instr |= ARM64_RM(rm_or_imm); /* Rm = shift amount */ + instr |= ARM64_RN(rn); /* Rn = source */ + instr |= ARM64_RD(rd); /* Rd = dest */ emit_instr32(instr); return; default: tcc_error("unknown shift type"); return; } - instr |= (rn & 0x1F) << 5; - instr |= rd & 0x1F; + instr |= ARM64_RN(rn); + instr |= ARM64_RD(rd); } else { /* Shift by register */ switch (shift_type) { case 0: /* LSL */ - instr = 0x1AC02000; + instr = ARM64_LSL_REG; break; case 1: /* LSR */ - instr = 0x1AC02400; + instr = ARM64_LSR_REG; break; case 2: /* ASR */ - instr = 0x1AC02800; + instr = ARM64_ASR_REG; break; case 3: /* ROR */ - instr = 0x1AC02C00; + instr = ARM64_ROR_REG; break; default: tcc_error("unknown shift type"); return; } if (is_64bit) - instr |= 1U << 31; - instr |= (rm_or_imm & 0x1F) << 16; - instr |= (rn & 0x1F) << 5; - instr |= rd & 0x1F; + instr |= ARM64_SF(1); + instr |= ARM64_RM(rm_or_imm); + instr |= ARM64_RN(rn); + instr |= ARM64_RD(rd); } emit_instr32(instr); } @@ -889,19 +888,19 @@ static void gen_barrier(int barrier_type, int option) switch (barrier_type) { case 0: /* ISB - Instruction Synchronization Barrier */ - instr = 0xD50330DF; + instr = ARM64_ISB; break; case 1: /* DSB - Data Synchronization Barrier */ - instr = 0xD503309F; + instr = ARM64_DSB; break; case 2: /* DMB - Data Memory Barrier */ - instr = 0xD50330BF; + instr = ARM64_DMB; break; default: tcc_error("unknown barrier type"); return; } - instr |= (option & 0xF) << 8; + instr |= ARM64_ISB_OPTION(option); emit_instr32(instr); } @@ -1016,25 +1015,25 @@ static void asm_data_proc(TCCState *s1, int token) switch (token) { case TOK_ASM_add: case TOK_ASM_adds: - opcode = token == TOK_ASM_add ? 0x0B000000 : 0x2B000000; + opcode = token == TOK_ASM_add ? ARM64_ADD_REG : ARM64_ADDS_REG; break; case TOK_ASM_sub: case TOK_ASM_subs: - opcode = token == TOK_ASM_sub ? 0x4B000000 : 0x6B000000; + opcode = token == TOK_ASM_sub ? ARM64_SUB_REG : ARM64_SUBS_REG; break; case TOK_ASM_and: case TOK_ASM_ands: - opcode = token == TOK_ASM_and ? 0x0A000000 : 0x2A000000; + opcode = token == TOK_ASM_and ? ARM64_AND_REG : ARM64_ANDS_REG; break; case TOK_ASM_orr: - opcode = 0x2A000000; + opcode = ARM64_ORR_REG; break; case TOK_ASM_eor: - opcode = 0x4A000000; + opcode = ARM64_EOR_REG; break; case TOK_ASM_mul: case TOK_ASM_muls: - opcode = 0x1B007C00; + opcode = token == TOK_ASM_mul ? ARM64_MUL_REG : ARM64_MULS_REG; break; default: tcc_error("unsupported data processing instruction"); @@ -1118,13 +1117,13 @@ static void asm_ldst(TCCState *s1, int token) switch (token) { case TOK_ASM_ldr: if (op1.reg_type & REG_X) { - base_opcode = 0xF9400000; + base_opcode = ARM64_LDR_X; size_log2 = 3; } else if (op1.reg_type & REG_W) { - base_opcode = 0xB9400000; + base_opcode = ARM64_LDR_W; size_log2 = 2; } else if (op1.reg_type & REG_D) { - base_opcode = 0xFD400000; + base_opcode = ARM64_LDR_D; size_log2 = 3; } else { tcc_error("ldr requires a w, x, or d register"); @@ -1132,22 +1131,22 @@ static void asm_ldst(TCCState *s1, int token) } break; case TOK_ASM_ldrb: - base_opcode = 0x39400000; + base_opcode = ARM64_LDR_B; size_log2 = 0; break; case TOK_ASM_ldrh: - base_opcode = 0x79400000; + base_opcode = ARM64_LDR_H; size_log2 = 1; break; case TOK_ASM_str: if (op1.reg_type & REG_X) { - base_opcode = 0xF9000000; + base_opcode = ARM64_STR_X; size_log2 = 3; } else if (op1.reg_type & REG_W) { - base_opcode = 0xB9000000; + base_opcode = ARM64_STR_W; size_log2 = 2; } else if (op1.reg_type & REG_D) { - base_opcode = 0xFD000000; + base_opcode = ARM64_STR_D; size_log2 = 3; } else { tcc_error("str requires a w, x, or d register"); @@ -1155,11 +1154,11 @@ static void asm_ldst(TCCState *s1, int token) } break; case TOK_ASM_strb: - base_opcode = 0x39000000; + base_opcode = ARM64_STR_B; size_log2 = 0; break; case TOK_ASM_strh: - base_opcode = 0x79000000; + base_opcode = ARM64_STR_H; size_log2 = 1; break; default: @@ -1199,23 +1198,23 @@ static void asm_ldst_pair(TCCState *s1, int token) if ((op1.reg_type & REG_X) && (op2.reg_type & REG_X)) { if (token == TOK_ASM_stp) { - base_opcode = op3.addr_mode == ADDR_PRE ? 0xA9800000 : - op3.addr_mode == ADDR_POST ? 0xA8800000 : - 0xA9000000; + base_opcode = op3.addr_mode == ADDR_PRE ? ARM64_STP_X_PRE : + op3.addr_mode == ADDR_POST ? ARM64_STP_X_POST : + ARM64_STP_X; } else { - base_opcode = op3.addr_mode == ADDR_PRE ? 0xA9C00000 : - op3.addr_mode == ADDR_POST ? 0xA8C00000 : - 0xA9400000; + base_opcode = op3.addr_mode == ADDR_PRE ? ARM64_LDP_X_PRE : + op3.addr_mode == ADDR_POST ? ARM64_LDP_X_POST : + ARM64_LDP_X; } } else if ((op1.reg_type & REG_D) && (op2.reg_type & REG_D)) { if (token == TOK_ASM_stp) { - base_opcode = op3.addr_mode == ADDR_PRE ? 0x6D800000 : - op3.addr_mode == ADDR_POST ? 0x6C800000 : - 0x6D000000; + base_opcode = op3.addr_mode == ADDR_PRE ? ARM64_STP_D_PRE : + op3.addr_mode == ADDR_POST ? ARM64_STP_D_POST : + ARM64_STP_D; } else { - base_opcode = op3.addr_mode == ADDR_PRE ? 0x6DC00000 : - op3.addr_mode == ADDR_POST ? 0x6CC00000 : - 0x6D400000; + base_opcode = op3.addr_mode == ADDR_PRE ? ARM64_LDP_D_PRE : + op3.addr_mode == ADDR_POST ? ARM64_LDP_D_POST : + ARM64_LDP_D; } } else { tcc_error("stp/ldp requires matching x or d registers"); @@ -1646,19 +1645,19 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, if (regs_allocated[reg1]) { if (reg2 >= 0 && regs_allocated[reg2]) { - uint32_t instr = 0xA9000000; + uint32_t instr = ARM64_STP_X; int offset = ((i - first_saved) / 2) * 8; - instr |= (offset & 0x7F) << 15; - instr |= (reg2 & 0x1F) << 10; - instr |= (reg1 & 0x1F) << 5; - instr |= 31 & 0x1F; + instr |= ARM64_IMM7(offset >> 3); + instr |= ARM64_RT2(reg2); + instr |= ARM64_RN(reg1); + instr |= ARM64_RD(31); emit_instr32(instr); } else { - uint32_t instr = 0xF9000000; + uint32_t instr = ARM64_STR_X; int offset = (i - first_saved) * 8; - instr |= ((offset >> 3) & 0xFFF) << 10; - instr |= (reg1 & 0x1F) << 5; - instr |= 31 & 0x1F; + instr |= ARM64_IMM12(offset >> 3); + instr |= ARM64_RN(reg1); + instr |= ARM64_RT(31); emit_instr32(instr); } } @@ -1707,21 +1706,21 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, if (regs_allocated[reg1]) { if (reg2 >= 0 && regs_allocated[reg2] && i > 0) { - uint32_t instr = 0xA9400000; + uint32_t instr = ARM64_LDP_X; int pair_idx = i - 1; int offset = (pair_idx / 2) * 8; - instr |= ((offset >> 3) & 0x7F) << 15; - instr |= (reg2 & 0x1F) << 10; - instr |= (reg1 & 0x1F) << 5; - instr |= 31 & 0x1F; + instr |= ARM64_IMM7(offset >> 3); + instr |= ARM64_RT2(reg2); + instr |= ARM64_RN(reg1); + instr |= ARM64_RD(31); emit_instr32(instr); i--; } else { - uint32_t instr = 0xF9400000; + uint32_t instr = ARM64_LDR_X; int offset = i * 8; - instr |= ((offset >> 3) & 0xFFF) << 10; - instr |= (reg1 & 0x1F) << 5; - instr |= 31 & 0x1F; + instr |= ARM64_IMM12(offset >> 3); + instr |= ARM64_RN(reg1); + instr |= ARM64_RT(31); emit_instr32(instr); } } diff --git a/arm64-gen.c b/arm64-gen.c index 7b122547..d1db6b1a 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1051,12 +1051,12 @@ static void arm64_sub_sp(uint64_t diff) #endif if (!(diff >> 24)) { if (diff & 0xffful) - o(0xd10003ff | (diff & 0xffful) << 10); // sub sp,sp,#low12 + o(ARM64_SUB_IMM | ARM64_SF(1) | ARM64_RN(31) | ARM64_RD(31) | ARM64_IMM12(diff & 0xfff)); if (diff >> 12) - o(0xd14003ff | (diff >> 12) << 10); // sub sp,sp,#high12,lsl #12 + o(ARM64_SUB_IMM | ARM64_SF(1) | ARM64_SH(1) | ARM64_RN(31) | ARM64_RD(31) | ARM64_IMM12((diff >> 12) & 0xfff)); } else { arm64_movimm(16, diff); - o(0xcb3063ff); // sub sp,sp,x16 + o(0xCB3063FFU); // sub sp,sp,x16 } } diff --git a/arm64-tok.h b/arm64-tok.h index 51424385..a7301c54 100644 --- a/arm64-tok.h +++ b/arm64-tok.h @@ -556,3 +556,150 @@ DEF_ASM(st3) DEF_ASM(ld4) DEF_ASM(st4) + +/* ------------------------------------------------------------------ */ +/* ARM64 instruction opcode constants and encoding helpers */ +/* ------------------------------------------------------------------ */ + +/* Data processing - immediate */ +#define ARM64_ADD_IMM 0x11000000U +#define ARM64_ADDS_IMM 0x2B000000U +#define ARM64_SUB_IMM 0x51000000U +#define ARM64_SUBS_IMM 0x6B000000U + +/* Data processing - register */ +#define ARM64_ADD_REG 0x0B000000U +#define ARM64_ADDS_REG 0x2B000000U +#define ARM64_SUB_REG 0x4B000000U +#define ARM64_SUBS_REG 0x6B000000U +#define ARM64_AND_REG 0x0A000000U +#define ARM64_ANDS_REG 0x2A000000U +#define ARM64_ORR_REG 0x2A000000U +#define ARM64_EOR_REG 0x4A000000U +#define ARM64_MUL_REG 0x1B007C00U +#define ARM64_MULS_REG 0x3B007C00U + +/* Move wide immediate */ +#define ARM64_MOVZ 0x52800000U +#define ARM64_MOVN 0x12800000U +#define ARM64_MOVK 0xF2800000U + +/* Load/store register (unsigned immediate) */ +#define ARM64_LDR_X 0xF9400000U +#define ARM64_LDR_W 0xB9400000U +#define ARM64_LDR_B 0x39400000U +#define ARM64_LDR_H 0x79400000U +#define ARM64_LDR_D 0xFD400000U +#define ARM64_LDR_S 0xBD400000U +#define ARM64_STR_X 0xF9000000U +#define ARM64_STR_W 0xB9000000U +#define ARM64_STR_B 0x39000000U +#define ARM64_STR_H 0x79000000U +#define ARM64_STR_D 0xFD000000U +#define ARM64_STR_S 0xBD000000U + +/* Load/store register (unscaled immediate) */ +#define ARM64_LDUR_X 0xF8400000U +#define ARM64_LDUR_W 0xB8400000U +#define ARM64_STUR_X 0xF8000000U +#define ARM64_STUR_W 0xB8000000U + +/* Load/store pair */ +#define ARM64_LDP_X 0xA9400000U +#define ARM64_LDP_X_PRE 0xA9C00000U +#define ARM64_LDP_X_POST 0xA8C00000U +#define ARM64_STP_X 0xA9000000U +#define ARM64_STP_X_PRE 0xA9800000U +#define ARM64_STP_X_POST 0xA8800000U +#define ARM64_LDP_D 0x6D400000U +#define ARM64_LDP_D_PRE 0x6DC00000U +#define ARM64_LDP_D_POST 0x6CC00000U +#define ARM64_STP_D 0x6D000000U +#define ARM64_STP_D_PRE 0x6D800000U +#define ARM64_STP_D_POST 0x6C800000U + +/* Branch instructions */ +#define ARM64_B 0x14000000U +#define ARM64_BL 0x94000000U +#define ARM64_BR 0xD61F0000U +#define ARM64_BLR 0xD63F0000U +#define ARM64_RET 0xD65F03C0U + +/* Conditional branch */ +#define ARM64_B_COND 0x54000000U + +/* Compare and branch */ +#define ARM64_CBZ 0x34000000U +#define ARM64_CBNZ 0x35000000U + +/* System instructions */ +#define ARM64_NOP 0xD503201FU +#define ARM64_ISB 0xD50330DFU +#define ARM64_DSB 0xD503309FU +#define ARM64_DMB 0xD50330BFU +#define ARM64_MRS 0xD5380000U +#define ARM64_MSR 0xD5180000U + +/* Shifts (register) */ +#define ARM64_LSL_REG 0x1AC02000U +#define ARM64_LSR_REG 0x1AC02400U +#define ARM64_ASR_REG 0x1AC02800U +#define ARM64_ROR_REG 0x1AC02C00U + +/* Shifts (immediate - UBFM/SBFM) */ +#define ARM64_LSL_IMM 0xD3400000U +#define ARM64_LSR_IMM 0xD3400000U +#define ARM64_ASR_IMM 0x93400000U + +/* MOV (register) - ORR with zero register */ +#define ARM64_MOV_REG 0x2A0003E0U + +/* Address generation */ +#define ARM64_ADRP 0x90000000U +#define ARM64_ADR 0x10000000U + +/* Logical immediate */ +#define ARM64_ORR_IMM 0x320003E0U +#define ARM64_AND_IMM 0x12000000U + +/* ------------------------------------------------------------------ */ +/* ARM64 instruction encoding helper macros */ +/* ------------------------------------------------------------------ */ + +/* Register field encodings */ +#define ARM64_RD(r) ((uint32_t)(r) & 0x1FU) +#define ARM64_RN(r) (((uint32_t)(r) & 0x1FU) << 5) +#define ARM64_RM(r) (((uint32_t)(r) & 0x1FU) << 16) +#define ARM64_RT(r) ((uint32_t)(r) & 0x1FU) +#define ARM64_RT2(r) (((uint32_t)(r) & 0x1FU) << 10) + +/* Immediate field encodings */ +#define ARM64_IMM12(v) (((uint32_t)(v) & 0xFFFU) << 10) +#define ARM64_IMM7(v) (((uint32_t)(v) & 0x7FU) << 15) +#define ARM64_IMM14(v) (((uint32_t)(v) & 0x3FFFU) << 5) +#define ARM64_IMM16(v) (((uint32_t)(v) & 0xFFFFU) << 5) +#define ARM64_IMM_HW(v, hw) (((uint32_t)(v) & 0xFFFFU) << 5 | (((hw) & 3) << 21)) + +/* Shift and size encodings */ +#define ARM64_SIZE(s) (((uint32_t)(s) & 3) << 30) +#define ARM64_SF(s) (((uint32_t)(s) & 1) << 31) +#define ARM64_S(v) (((uint32_t)(v) & 1) << 29) +#define ARM64_SH(v) (((uint32_t)(v) & 1) << 22) + +/* Condition code encoding */ +#define ARM64_COND(c) ((uint32_t)(c) & 0xFU) + +/* Branch offset encoding */ +#define ARM64_OFFSET26(v) (((uint32_t)(v) >> 2) & 0x3FFFFFFU) +#define ARM64_OFFSET19(v) (((uint32_t)(v) >> 2) & 0x7FFFFU) +#define ARM64_OFFSET14(v) (((uint32_t)(v) >> 2) & 0x3FFFU) + +/* Special register field (for MRS/MSR) */ +#define ARM64_SYSREG(op0, op1, crn, crm, op2) \ + ((((op0) & 3) << 19) | (((op1) & 7) << 16) | \ + (((crn) & 15) << 12) | (((crm) & 15) << 8) | (((op2) & 7) << 5)) + +/* Barrier option encoding */ +#define ARM64_ISB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8) +#define ARM64_DSB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8) +#define ARM64_DMB_OPTION(opt) (((uint32_t)(opt) & 0xFU) << 8)