diff --git a/arm64-asm.c b/arm64-asm.c index f45bf142..67f3f379 100644 --- a/arm64-asm.c +++ b/arm64-asm.c @@ -707,10 +707,10 @@ static void gen_mrs(int rt, int sysreg) switch (sysreg) { case 0: /* FPCR */ - instr = 0xD53B4400U; + instr = ARM64_MRS_FPCR; break; case 1: /* FPSR */ - instr = 0xD53B4420U; + instr = ARM64_MRS_FPSR; break; default: tcc_error("unsupported system register"); @@ -725,10 +725,10 @@ static void gen_msr(int rt, int sysreg) switch (sysreg) { case 0: /* FPCR */ - instr = 0xD51B4400U; + instr = ARM64_MSR_FPCR; break; case 1: /* FPSR */ - instr = 0xD51B4420U; + instr = ARM64_MSR_FPSR; break; default: tcc_error("unsupported system register"); @@ -784,7 +784,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 ? 0x93C00000U : 0x13800000U; + instr = is_64bit ? ARM64_EXTR64 : ARM64_EXTR; instr |= ARM64_RM(rm_or_imm); /* Rm = shift amount */ instr |= ARM64_RN(rn); /* Rn = source */ instr |= ARM64_RD(rd); /* Rd = dest */ diff --git a/arm64-gen.c b/arm64-gen.c index 681b50f2..e5f17f62 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -483,30 +483,32 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend) #ifdef TCC_TARGET_PE /* PE links symbol addresses directly; there is no ELF-style GOT here. */ greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, 0); - o(0x90000000 | r); // adrp xr, #sym + o(ARM64_ADRP | r); // adrp xr, #sym greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, 0); - o(0x91000000 | r | (r << 5)); // add xr, xr, #sym + o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r); // add xr, xr, #sym #else greloca(cur_text_section, sym, ind, R_AARCH64_ADR_GOT_PAGE, 0); - o(0x90000000 | r); // adrp xr, #sym + o(ARM64_ADRP | r); // adrp xr, #sym greloca(cur_text_section, sym, ind, R_AARCH64_LD64_GOT_LO12_NC, 0); - o(0xf9400000 | r | (r << 5)); // ld xr,[xr, #sym] + o(ARM64_LDR_X | ARM64_RN(r) | r); // ld xr,[xr, #sym] #endif if (addend) { // add xr, xr, #addend if (addend & 0xffful) - o(0x91000000 | r | r << 5 | (addend & 0xfff) << 10); + o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r | + (addend & 0xfff) << 10); if (addend > 0xffful) { // add xr, xr, #addend, lsl #12 if (addend & 0xfff000ul) - o(0x91400000 | r | r << 5 | ((addend >> 12) & 0xfff) << 10); + o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) | + ARM64_RN(r) | r | ((addend >> 12) & 0xfff) << 10); if (addend > 0xfffffful) { /* very unlikely */ int t = r ? 0 : 1; - o(0xf81f0fe0 | t); /* str xt, [sp, #-16]! */ + o(ARM64_STR_X_PRE | 0x001F0FE0U | t); /* str xt, [sp, #-16]! */ arm64_movimm(t, addend & ~0xfffffful); // use xt for addent - o(0x8B000000 | (t << 16) | (r << 5) | r); /* add xr, xr, xt */ - o(0xf84107e0 | t); /* ldr xt, [sp], #16 */ + o(ARM64_ADD_REG | ARM64_SF(1) | ARM64_RM(t) | ARM64_RN(r) | r); /* add xr, xr, xt */ + o(ARM64_LDR_X_POST | 0x000107E0U | t); /* ldr xt, [sp], #16 */ } } } @@ -586,12 +588,12 @@ ST_FUNC void load(int r, SValue *sv) if (svr < VT_CONST) { if (IS_FREG(r) && IS_FREG(svr)) if (svtt == VT_LDOUBLE) - o(0x4ea01c00 | fltr(r) | fltr(svr) << 5); + o(ARM64_MOV_V16B | fltr(r) | fltr(svr) << 5); // mov v(r).16b,v(svr).16b else - o(0x1e604000 | fltr(r) | fltr(svr) << 5); // fmov d(r),d(svr) + o(ARM64_FMOV_SCALAR | fltr(r) | fltr(svr) << 5); // fmov d(r),d(svr) else if (!IS_FREG(r) && !IS_FREG(svr)) - o(0xaa0003e0 | intr(r) | intr(svr) << 16); // mov x(r),x(svr) + o(ARM64_MOV_REG | ARM64_SF(1) | intr(r) | intr(svr) << 16); // mov x(r),x(svr) else assert(0); return; @@ -610,7 +612,7 @@ ST_FUNC void load(int r, SValue *sv) if (svr == VT_JMP || svr == VT_JMPI) { int t = (svr == VT_JMPI); arm64_movimm(intr(r), t); - o(0x14000002); // b .+8 + o(ARM64_B | 2); // b .+8 gsym(svcul); arm64_movimm(intr(r), t ^ 1); return; @@ -697,13 +699,13 @@ static void arm64_gen_bl_or_b(int b) if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { greloca(cur_text_section, vtop->sym, ind, b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0); - o(0x14000000 | (uint32_t)!b << 31); // b/bl . + o(b ? ARM64_B : ARM64_BL); // b/bl . } else { #ifdef CONFIG_TCC_BCHECK vtop->r &= ~VT_MUSTBOUND; #endif - o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr + o((b ? ARM64_BR : ARM64_BLR) | intr(gv(RC_R30)) << 5); // br/blr } } @@ -714,7 +716,7 @@ static void gen_bounds_call(int v) Sym *sym = external_helper_sym(v); greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0); - o(0x94000000); // bl + o(ARM64_BL); // bl } static void gen_bounds_prolog(void) @@ -723,10 +725,10 @@ static void gen_bounds_prolog(void) func_bound_offset = lbounds_section->data_offset; func_bound_ind = ind; func_bound_add_epilog = 0; - o(0xd503201f); /* nop -> mov x0, lbound section pointer */ - o(0xd503201f); - o(0xd503201f); - o(0xd503201f); /* nop -> call __bound_local_new */ + o(ARM64_NOP); /* nop -> mov x0, lbound section pointer */ + o(ARM64_NOP); + o(ARM64_NOP); + o(ARM64_NOP); /* nop -> call __bound_local_new */ } static void gen_bounds_epilog(void) @@ -1043,7 +1045,7 @@ static void arm64_sub_sp(uint64_t diff) arm64_movimm(15, diff >> 4); greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0); - o(0x94000000); // bl __chkstk + o(ARM64_BL); // bl __chkstk o(0xcb2f73ff); // sub sp,sp,x15,lsl #4 return; } @@ -1165,9 +1167,9 @@ ST_FUNC void gfunc_call(int nb_args) if ((variadic || old_style) && i > var_nb_arg && is_float(vtop->type.t)) { gv(RC_FLOAT); if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) - o(0x9e660000 | intr(a[i] / 2) | fltr(vtop->r) << 5); // fmov xN,dM + o(ARM64_FMOV_XD | intr(a[i] / 2) | fltr(vtop->r) << 5); // fmov xN,dM else - o(0x1e260000 | intr(a[i] / 2) | fltr(vtop->r) << 5); // fmov wN,sM + o(ARM64_FMOV_WS | intr(a[i] / 2) | fltr(vtop->r) << 5); // fmov wN,sM } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { int align, size = type_size(&vtop->type, &align); @@ -1394,7 +1396,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) arm64_func_sub_sp_offset = ind; /* In gfunc_epilog these will be replaced with stack setup code. */ for (i = 0; i < ARM64_FUNC_STACK_SETUP_SLOTS; ++i) - o(0xd503201f); // nop + o(ARM64_NOP); // nop loc = 0; #ifdef CONFIG_TCC_BCHECK if (tcc_state->do_bounds_check) @@ -1481,7 +1483,7 @@ ST_FUNC void gen_va_arg(CType *t) vtop[0].r = r1 | VT_LVAL; r1 = intr(r1); - o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // ap + o(ARM64_LDR_X | ARM64_RN(r0) | r1); // ldr x(r1),[x(r0)] // ap if (slot) { if (slot == 16) { o(0x910363be); // add x30,x29,#216 @@ -1498,7 +1500,7 @@ ST_FUNC void gen_va_arg(CType *t) } if (indirect) - o(0xf9400000 | r1 | r1 << 5); // ldr x(r1),[x(r1)] + o(ARM64_LDR_X | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)] return; #endif @@ -1525,7 +1527,7 @@ ST_FUNC void gen_va_arg(CType *t) o(0x310003c0 | r1 | n << 10); // adds w(r1),w30,#(n) o(0x540000ad); // b.le .+20 #endif - o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack + o(ARM64_LDR_X | ARM64_RN(r0) | r1); // ldr x(r1),[x(r0)] // __stack if (align == 16) { o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15 o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16 @@ -1533,13 +1535,13 @@ ST_FUNC void gen_va_arg(CType *t) o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n) o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack #if !defined(TCC_TARGET_MACHO) - o(0x14000004); // b .+16 + o(ARM64_B | 4); // b .+16 o(0xb9001800 | r1 | r0 << 5); // str w(r1),[x(r0),#24] // __gr_offs o(0xf9400400 | r1 | r0 << 5); // ldr x(r1),[x(r0),#8] // __gr_top o(0x8b3ec000 | r1 | r1 << 5); // add x(r1),x(r1),w30,sxtw #endif if (size > 16) - o(0xf9400000 | r1 | r1 << 5); // ldr x(r1),[x(r1)] + o(ARM64_LDR_X | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)] } else { uint32_t ssz = (size + 7) & -(uint32_t)8; @@ -1550,7 +1552,7 @@ ST_FUNC void gen_va_arg(CType *t) o(0x310003c0 | r1 | rsz << 10); // adds w(r1),w30,#(rsz) b1 = ind; o(0x5400000d); // b.le lab1 #endif - o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack + o(ARM64_LDR_X | ARM64_RN(r0) | r1); // ldr x(r1),[x(r0)] // __stack if (fsize == 16) { o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15 o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16 @@ -1558,7 +1560,7 @@ ST_FUNC void gen_va_arg(CType *t) o(0x9100001e | r1 << 5 | ssz << 10); // add x30,x(r1),#(ssz) o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack #if !defined(TCC_TARGET_MACHO) - b2 = ind; o(0x14000000); // b lab2 + b2 = ind; o(ARM64_B); // b lab2 // lab1: write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3); o(0xb9001c00 | r1 | r0 << 5); // str w(r1),[x(r0),#28] // __vr_offs @@ -1580,7 +1582,7 @@ ST_FUNC void gen_va_arg(CType *t) (uint32_t)(hfa != 3) << 21); // st(hfa) {v28.(s|d),...}[0],[x(r1)] } // lab2: - write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2); + write32le(cur_text_section->data + b2, ARM64_B | ((ind - b2) >> 2)); #endif } } @@ -1655,7 +1657,7 @@ ST_FUNC void gfunc_epilog(void) ind = arm64_func_sub_sp_offset; arm64_sub_sp(diff); for (i = ind; i < patch_end; i += 4) - write32le(cur_text_section->data + i, 0xd503201f); // nop + write32le(cur_text_section->data + i, ARM64_NOP); // nop ind = saved_ind; } o(0x910003bf); // mov sp,x29 @@ -1675,7 +1677,7 @@ ST_FUNC void gen_fill_nops(int bytes) if ((bytes & 3)) tcc_error("alignment of code section not multiple of 4"); while (bytes > 0) { - o(0xd503201f); // nop + o(ARM64_NOP); // nop bytes -= 4; } } @@ -1694,7 +1696,7 @@ ST_FUNC int gjmp(int t) ST_FUNC void gjmp_addr(int a) { assert(a - ind + 0x8000000 < 0x10000000); - o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff)); + o(ARM64_B | (((a - ind) >> 2) & 0x3ffffff)); } ST_FUNC int gjmp_append(int n, int t) @@ -2257,7 +2259,7 @@ ST_FUNC void gen_increment_tcov (SValue *sv) vtop->r = r1 = get_reg(RC_INT); r2 = get_reg(RC_INT); arm64_sym(r1, sv->sym, 0); - o(0xf9400000 | (intr(r1)<<5) | intr(r2)); // ldr r2, [r1] + o(ARM64_LDR_X | ARM64_RN(intr(r1)) | intr(r2)); // ldr r2, [r1] o(0x91000400 | (intr(r2)<<5) | intr(r2)); // add r2, r2, #1 o(0xf9000000 | (intr(r1)<<5) | intr(r2)); // str r2, [r1] vpop(); @@ -2294,21 +2296,21 @@ ST_FUNC void gen_clear_cache(void) o(0x1ac02000 | isz | p << 5 | isz << 16); // lsl w(isz),w(p),w(isz) o(0x51000400 | p | dsz << 5); // sub w(p),w(dsz),#1 o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p) - b1 = ind; o(0x14000000); // b + b1 = ind; o(ARM64_B); // b lab1 = ind; o(0xd50b7b20 | p); // dc cvau,x(p) o(0x8b000000 | p | p << 5 | dsz << 16); // add x(p),x(p),x(dsz) - write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2); + write32le(cur_text_section->data + b1, ARM64_B | ((ind - b1) >> 2)); o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end) o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1 o(0xd5033b9f); // dsb ish o(0x51000400 | p | isz << 5); // sub w(p),w(isz),#1 o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p) - b1 = ind; o(0x14000000); // b + b1 = ind; o(ARM64_B); // b lab1 = ind; o(0xd50b7520 | p); // ic ivau,x(p) o(0x8b000000 | p | p << 5 | isz << 16); // add x(p),x(p),x(isz) - write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2); + write32le(cur_text_section->data + b1, ARM64_B | ((ind - b1) >> 2)); o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end) o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1 o(0xd5033b9f); // dsb ish diff --git a/arm64-link.c b/arm64-link.c index dc57611e..0b807c4b 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -131,17 +131,18 @@ ST_FUNC void relocate_plt(TCCState *s1) uint64_t off = (got >> 12) - (plt >> 12); if ((off + ((uint32_t)1 << 20)) >> 21) tcc_error_noabort("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); - write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]! - write32le(p + 4, (0x90000010 | // adrp x16,... + write32le(p, ARM64_STP_X_PRE | ARM64_RT(16) | ARM64_RT2(30) | + ARM64_RN(31) | ARM64_IMM7(-2)); // stp x16,x30,[sp,#-16]! + write32le(p + 4, (ARM64_ADRP | ARM64_RD(16) | // adrp x16,... (off & 0x1ffffc) << 3 | (off & 3) << 29)); - write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...] + write32le(p + 8, (ARM64_LDR_X | ARM64_RT(17) | ARM64_RN(16) | // ldr x17,[x16,#...] (got & 0xff8) << 7)); - write32le(p + 12, (0x91000210 | // add x16,x16,#... + write32le(p + 12, (ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RD(16) | ARM64_RN(16) | // add x16,x16,#... (got & 0xfff) << 10)); - write32le(p + 16, 0xd61f0220); // br x17 - write32le(p + 20, 0xd503201f); // nop - write32le(p + 24, 0xd503201f); // nop - write32le(p + 28, 0xd503201f); // nop + write32le(p + 16, ARM64_BR | ARM64_RN(17)); // br x17 + write32le(p + 20, ARM64_NOP); // nop + write32le(p + 24, ARM64_NOP); // nop + write32le(p + 28, ARM64_NOP); // nop p += 32; got = s1->got->sh_addr; while (p < p_end) { @@ -150,13 +151,13 @@ ST_FUNC void relocate_plt(TCCState *s1) uint64_t off = (addr >> 12) - (pc >> 12); if ((off + ((uint32_t)1 << 20)) >> 21) tcc_error_noabort("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc); - write32le(p, (0x90000010 | // adrp x16,... + write32le(p, (ARM64_ADRP | ARM64_RD(16) | // adrp x16,... (off & 0x1ffffc) << 3 | (off & 3) << 29)); - write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...] + write32le(p + 4, (ARM64_LDR_X | ARM64_RT(17) | ARM64_RN(16) | // ldr x17,[x16,#...] (addr & 0xff8) << 7)); - write32le(p + 8, (0x91000210 | // add x16,x16,#... + write32le(p + 8, (ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RD(16) | ARM64_RN(16) | // add x16,x16,#... (addr & 0xfff) << 10)); - write32le(p + 12, 0xd61f0220); // br x17 + write32le(p + 12, ARM64_BR | ARM64_RN(17)); // br x17 p += 16; } } @@ -321,7 +322,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK) { - write32le(ptr, 0xd503201f); /* nop */ + write32le(ptr, ARM64_NOP); /* nop */ return; } #endif diff --git a/arm64-tok.h b/arm64-tok.h index 8b925740..210f6b26 100644 --- a/arm64-tok.h +++ b/arm64-tok.h @@ -692,6 +692,10 @@ #define ARM64_DMB 0xD50330BFU #define ARM64_MRS 0xD5380000U #define ARM64_MSR 0xD5180000U +#define ARM64_MRS_FPCR 0xD53B4400U +#define ARM64_MRS_FPSR 0xD53B4420U +#define ARM64_MSR_FPCR 0xD51B4400U +#define ARM64_MSR_FPSR 0xD51B4420U /* Shifts (register) */ #define ARM64_LSL_REG 0x1AC02000U @@ -809,7 +813,8 @@ #define ARM64_FCMP 0x1E202008U /* FCMP with zero */ #define ARM64_SDIV 0x1AC00C00U /* SDIV (32-bit) */ -/* EXTR (Extract) - 64-bit variant */ +/* EXTR (Extract) */ +#define ARM64_EXTR 0x13800000U /* EXTR Wd, Wn, Wm, #imm (32-bit) */ #define ARM64_EXTR64 0x93C00000U /* EXTR Xd, Xn, Xm, #imm (64-bit) */ /* ARM64_MUL removed - use ARM64_MUL_REG with gen_dp_reg() */