hs = 2, lo = 3,
}
+local map_bti = {
+ c = 0x40, j = 0x80, jc = 0xc0,
+}
+
------------------------------------------------------------------------------
local parse_reg_type
return shl(bit.bxor(c, inv), 12)
end
+local function parse_map(expr, map)
+ local x = map[expr]
+ if not x then werror("bad operand") end
+ return x
+end
+
local function parse_load(params, nparams, n, op)
if params[n+2] then werror("too many operands") end
local scale = shr(op, 30)
tbz_3 = "36000000DTBw|36000000DTBx",
tbnz_3 = "37000000DTBw|37000000DTBx",
+ -- Branch Target Identification.
+ bti_1 = "d503241ft",
+
-- ARM64e: Pointer authentication codes (PAC).
blraaz_1 = "d63f081fNx",
+ blrabz_1 = "d63f0c1fNx",
braa_2 = "d71f0800NDx",
+ brab_2 = "d71f0c00NDx",
braaz_1 = "d61f081fNx",
+ brabz_1 = "d61f0c1fNx",
+ paciasp_0 = "d503233f",
pacibsp_0 = "d503237f",
+ autiasp_0 = "d50323bf",
+ autibsp_0 = "d50323ff",
+ retaa_0 = "d65f0bff",
retab_0 = "d65f0fff",
-- Miscellaneous instructions.
op = op + parse_cond(q, 0); n = n + 1
elseif p == "c" then
op = op + parse_cond(q, 1); n = n + 1
+ elseif p == "t" then
+ op = op + parse_map(q, map_bti); n = n + 1
else
assert(false)
|.macro ret_auth; ret; .endmacro
|.endif
|
+|// ARM64 branch target identification (BTI).
+|.if BRANCH_TRACK
+|.macro bti_jump; bti j; .endmacro
+|.macro bti_call; bti c; .endmacro
+|.macro bti_tailcall; bti jc; .endmacro
+|.else
+|.macro bti_jump; .endmacro
+|.macro bti_call; .endmacro
+|.macro bti_tailcall; .endmacro
+|.endif
+|
|//-----------------------------------------------------------------------
|
|// Stack layout while in interpreter. Must match with lj_frame.h.
|
|->vm_unwind_c: // Unwind C stack, return from vm_pcall.
| // (void *cframe, int errcode)
+ | bti_tailcall
| add fp, CARG1, # SAVE_FP_LR_
| mov sp, CARG1
| mov CRET1, CARG2
| ldr L, SAVE_L
| ldr GL, L->glref
|->vm_unwind_c_eh: // Landing pad for external unwinder.
+ | bti_tailcall
| mv_vmstate TMP0w, C
| st_vmstate TMP0w
| b ->vm_leave_unw
|
|->vm_unwind_ff: // Unwind C stack, return from ff pcall.
| // (void *cframe)
+ | bti_tailcall
| add fp, CARG1, # SAVE_FP_LR_
| mov sp, CARG1
| ldr L, SAVE_L
| init_constants
| ldr GL, L->glref // Setup pointer to global state.
|->vm_unwind_ff_eh: // Landing pad for external unwinder.
+ | bti_tailcall
| mov RC, #16 // 2 results: false + error message.
| ldr BASE, L->base
| mov_false TMP0
|.endif
|
|->cont_cat: // RA = resultptr, CARG4 = meta base
+ | bti_jump
| ldr INSw, [PC, #-4]
| sub CARG2, CARG4, #32
| ldr TMP0, [RA]
| sub RB, RB, #0x20000
| csel PC, PC, RB, lo
|->cont_nop:
+ | bti_jump
| ins_next
|
|->cont_ra: // RA = resultptr
+ | bti_jump
| ldr INSw, [PC, #-4]
| ldr TMP0, [RA]
| decode_RA TMP1, INS
| b ->cont_nop
|
|->cont_condt: // RA = resultptr
+ | bti_jump
| ldr TMP0, [RA]
| mov_true TMP1
| cmp TMP1, TMP0 // Branch if result is true.
| b <4
|
|->cont_condf: // RA = resultptr
+ | bti_jump
| ldr TMP0, [RA]
| mov_false TMP1
| cmp TMP0, TMP1 // Branch if result is false.
|
|.macro .ffunc, name
|->ff_ .. name:
+ | bti_jump
|.endmacro
|
|.macro .ffunc_1, name
|->ff_ .. name:
+ | bti_jump
| ldr CARG1, [BASE]
| cmp NARGS8:RC, #8
| blo ->fff_fallback
|
|.macro .ffunc_2, name
|->ff_ .. name:
+ | bti_jump
| ldp CARG1, CARG2, [BASE]
| cmp NARGS8:RC, #16
| blo ->fff_fallback
|
|->vm_record: // Dispatch target for recording phase.
|.if JIT
+ | bti_jump
| ldrb CARG1w, GL->hookmask
| tst CARG1, #HOOK_VMEVENT // No recording while in vmevent.
| bne >5
|.endif
|
|->vm_rethook: // Dispatch target for return hooks.
+ | bti_jump
| ldrb TMP2w, GL->hookmask
| tbz TMP2w, #HOOK_ACTIVE_SHIFT, >1 // Hook already active?
|5: // Re-dispatch to static ins.
| br_auth TMP0
|
|->vm_inshook: // Dispatch target for instr/line hooks.
+ | bti_jump
| ldrb TMP2w, GL->hookmask
| ldr TMP3w, GL->hookcount
| tbnz TMP2w, #HOOK_ACTIVE_SHIFT, <5 // Hook already active?
| br_auth TMP0
|
|->cont_hook: // Continue from hook yield.
+ | bti_jump
| ldr CARG1, [CARG4, #-40]
| add PC, PC, #4
| str CARG1w, SAVE_MULTRES // Restore MULTRES for *M ins.
|.endif
|
|->vm_callhook: // Dispatch target for call hooks.
+ | bti_jump
| mov CARG2, PC
|.if JIT
| b >1
|->cont_stitch: // Trace stitching.
|.if JIT
| // RA = resultptr, CARG4 = meta base
+ | bti_jump
| ldr RBw, SAVE_MULTRES
| ldr INSw, [PC, #-4]
| ldr TRACE:CARG3, [CARG4, #-40] // Save previous trace.
|
|->vm_profhook: // Dispatch target for profiler hook.
#if LJ_HASPROFILE
+ | bti_jump
| mov CARG1, L
| str BASE, L->base
| mov CARG2, PC
|
|->vm_exit_handler:
|.if JIT
+ | bti_call
| sub sp, sp, #(64*8)
| savex_, 0, 1
| savex_, 2, 3
|.endif
|
|->vm_exit_interp:
+ | bti_jump
| // CARG1 = MULTRES or negated error code, BASE, PC and GL set.
|.if JIT
| ldr L, SAVE_L
|
| // int lj_vm_modi(int dividend, int divisor);
|->vm_modi:
+ | bti_call
| eor CARG4w, CARG1w, CARG2w
| cmp CARG4w, #0
| eor CARG3w, CARG1w, CARG1w, asr #31
|// Next idx returned in CRET2w.
|->vm_next:
|.if JIT
+ | bti_call
| ldr NEXT_LIM, NEXT_TAB->asize
| ldr NEXT_TMP1, NEXT_TAB->array
|1: // Traverse array part.
|=>defop:
switch (op) {
+#if !LJ_HASJIT
+ case BC_FORL:
+ case BC_JFORI:
+ case BC_JFORL:
+ case BC_ITERL:
+ case BC_JITERL:
+ case BC_LOOP:
+ case BC_JLOOP:
+ case BC_FUNCF:
+ case BC_JFUNCF:
+ case BC_JFUNCV:
+#endif
+ case BC_FUNCV: /* NYI: compiled vararg functions. */
+ break; /* Avoid redundant bti instructions. */
+ default:
+ | bti_jump
+ break;
+ }
+
+ switch (op) {
/* -- Comparison ops ---------------------------------------------------- */
"\t.align 3\n"
".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
#endif
+#endif
+#if LJ_TARGET_LINUX && LJ_ABI_BRANCH_TRACK
+ fprintf(ctx->fp,
+ "\t.section .note.gnu.property,\"a\"\n"
+ "\t.align 3\n"
+ "\t.long 4\n"
+ "\t.long 16\n"
+ "\t.long 5\n"
+ "\t.long 0x00554e47\n"
+ "\t.long 0xc0000000\n"
+ "\t.long 4\n"
+ "\t.long 1\n"
+ "\t.long 0\n");
#endif
break;
#if !LJ_NO_UNWIND