|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Invalid-instruction dispatcher + trap-path seams (see emu_seams.h). More...
#include <capstone/capstone.h>#include <stdio.h>#include "emu_engine.h"#include "emu_exc.h"#include "emu_host_io_internal.h"#include "emu_seams.h"Go to the source code of this file.
Enumerations | |
| enum | cs_op_field_t : uint32_t { k_cs_op_shift = 12U , k_cs_op_mask = 0x3U } |
| Thumb halfword-two field decode for the conditional-select family. More... | |
| enum | cond_select_t : uint32_t { k_cs_hw1_mask = 0xFFF0U , k_cs_hw1_match = 0xEA50U , k_cs_hw2_b15 = 0x8000U , k_cs_hw2_b14 = 0x4000U , k_cs_op_csel = 0U , k_cs_op_csinc = 1U , k_cs_op_csinv = 2U , k_cs_op_csneg = 3U , k_cs_insn_len = 4U , k_cs_reg_sp = 13U , k_cs_reg_pc = 15U } |
| enum | apsr_bit_t : uint32_t { k_apsr_n = 31U , k_apsr_z = 30U , k_apsr_c = 29U , k_apsr_v = 28U } |
| enum | arm_cond_t : uint32_t { k_cond_eq = 0x0U , k_cond_ne = 0x1U , k_cond_cs = 0x2U , k_cond_cc = 0x3U , k_cond_mi = 0x4U , k_cond_pl = 0x5U , k_cond_vs = 0x6U , k_cond_vc = 0x7U , k_cond_hi = 0x8U , k_cond_ls = 0x9U , k_cond_ge = 0xAU , k_cond_lt = 0xBU , k_cond_gt = 0xCU , k_cond_le = 0xDU , k_cond_al = 0xEU } |
| ARM/Thumb 4-bit condition-code field encodings (cond[3:0]). More... | |
| enum | : uint32_t { k_lob_dls_hw1 = 0xF040U , k_lob_dls_h1m = 0xFFF0U , k_lob_dls_hw2 = 0xE001U , k_lob_le_hw1 = 0xF00FU , k_lob_le_hw2 = 0xC000U , k_lob_le_h2m = 0xF000U , k_lob_le_imm10 = 0x03FFU , k_lob_le_lsb = 11U , k_lob_rn_mask = 0xFU , k_lob_insn_len = 4U } |
Functions | |
| static RA8_INTERNAL bool | internal_cond_holds (uint32_t cond, uint32_t xpsr) |
| Evaluate an ARM condition code against the APSR flags. | |
| static RA8_INTERNAL bool | internal_cs_reserved_reg (uint32_t reg) |
Report whether reg is reserved as a conditional-select operand. | |
| static RA8_INTERNAL bool | internal_emulate_cond_select (uc_engine *uc, uint32_t pc, const uint8_t *code) |
| Emulate one Armv8.1-M conditional-select instruction if present at PC. | |
| static RA8_INTERNAL bool | internal_emulate_barrier (uc_engine *uc, uint32_t pc, const uint8_t *code) |
| Emulate an Armv8-M memory barrier (DSB/DMB/ISB) as a NOP if present. | |
| static RA8_INTERNAL bool | internal_emulate_sec_scrub (uc_engine *uc, uint32_t pc, const uint8_t code[4]) |
| Emulate the Armv8-M security register-scrub ops as NOPs. | |
| static RA8_INTERNAL bool | internal_emulate_lob (uc_engine *uc, uint32_t pc, const uint8_t code[4]) |
| Emulate a DLS/LE Low-Overhead-Branch instruction; true iff handled. | |
| static RA8_INTERNAL bool | internal_dispatch_armv81_seam (uc_engine *uc, uint32_t pc, const uint8_t code[4]) |
| Emulate one Armv8.1-M instruction Unicorn's M33 core does not provide. | |
| static RA8_INTERNAL bool | internal_dispatch_insn_seam (uc_engine *uc, uint32_t pc, const uint8_t code[4]) |
| Try each Armv8.1-M / security seam in turn; true (and stop) if handled. | |
| static RA8_INTERNAL void | internal_report_unhandled_insn (uint32_t pc, const uint8_t code[4]) |
| Report + capstone-disassemble an instruction no seam could decode. | |
| bool | on_invalid_insn (uc_engine *uc, void *user) |
| Disassemble + report an instruction the core could not decode. | |
| void | emu_insn_seams_install (uc_engine *uc) |
| Implementation of emu_insn_seams_install() – arm the dispatcher. | |
| uint64_t | emu_lob_emulated_count (void) |
| Implementation of emu_lob_emulated_count() – plain counter read. | |
Variables | |
| static uint64_t | s_lob_emulated = 0U |
| Count of LOB instructions emulated this run (run-end telemetry). | |
Invalid-instruction dispatcher + trap-path seams (see emu_seams.h).
The UC_HOOK_INSN_INVALID dispatcher and the seams that ride it: the armed div-0 UDF service, the Armv8-M security register scrubs (CLRM / VSCCLRM), the Armv8.1-M conditional-select family (CSEL/CSINC/CSINV/CSNEG), the DSB/DMB/ISB barriers old Unicorn builds trap, the MVE run consumer, and the low-overhead-branch (DLS/LE) hardware loops. Every handled seam edits PC and stops the engine so the chunked run loop relaunches on valid code (editing PC and continuing in-place corrupts Unicorn's block/Thumb state). Moved verbatim out of the ra8_emulator main translation unit.
Definition in file emu_insn_seams.c.
| anonymous enum : uint32_t |
Definition at line 340 of file emu_insn_seams.c.
| enum apsr_bit_t : uint32_t |
| Enumerator | |
|---|---|
| k_apsr_n | Negative. |
| k_apsr_z | Zero. |
| k_apsr_c | Carry. |
| k_apsr_v | Overflow. |
Definition at line 57 of file emu_insn_seams.c.
| enum arm_cond_t : uint32_t |
ARM/Thumb 4-bit condition-code field encodings (cond[3:0]).
Definition at line 68 of file emu_insn_seams.c.
| enum cond_select_t : uint32_t |
Definition at line 42 of file emu_insn_seams.c.
| enum cs_op_field_t : uint32_t |
Thumb halfword-two field decode for the conditional-select family.
| Enumerator | |
|---|---|
| k_cs_op_shift | CSEL-family op = hw2[13:12]. |
| k_cs_op_mask | 2-bit op field. |
Definition at line 29 of file emu_insn_seams.c.
| void emu_insn_seams_install | ( | uc_engine * | uc | ) |
Implementation of emu_insn_seams_install() – arm the dispatcher.
Arm the invalid-instruction dispatcher on the engine.
Definition at line 586 of file emu_insn_seams.c.
References on_invalid_insn().
Referenced by internal_main_install_core_seams().
| uint64_t emu_lob_emulated_count | ( | void | ) |
Implementation of emu_lob_emulated_count() – plain counter read.
Count of LOB (DLS/LE) instructions emulated this run (telemetry).
Definition at line 593 of file emu_insn_seams.c.
References s_lob_emulated.
Referenced by internal_run_print_stop_summary().
|
static |
Evaluate an ARM condition code against the APSR flags.
| [in] | cond | 4-bit ARM condition code (0..15). |
| [in] | xpsr | Current xPSR (APSR flags live in the top nibble). |
Evaluate an arm condition code against the apsr flags; this step is contained within the emu insn seams model and uses bounded caller or module-owned storage.
| true | The cond holds condition holds or completed successfully; false otherwise. |
Definition at line 99 of file emu_insn_seams.c.
References k_apsr_c, k_apsr_n, k_apsr_v, k_apsr_z, k_cond_cc, k_cond_cs, k_cond_eq, k_cond_ge, k_cond_gt, k_cond_hi, k_cond_le, k_cond_ls, k_cond_lt, k_cond_mi, k_cond_ne, k_cond_pl, k_cond_vc, k_cond_vs, k_lo4_mask, and RA8_INTERNAL.
Referenced by internal_emulate_cond_select().
|
static |
Report whether reg is reserved as a conditional-select operand.
SP and PC make CSEL/CSINC/CSINV/CSNEG UNPREDICTABLE, so no compiler emits them and their presence means the decode window landed on a different instruction entirely.
| [in] | reg | Register index [0, 15]. |
reg is SP or PC. | true | reg is SP (13) or PC (15). |
| false | reg is a general-purpose operand register. |
reg was masked to four bits by the caller. Definition at line 157 of file emu_insn_seams.c.
References k_cs_reg_pc, k_cs_reg_sp, and RA8_INTERNAL.
Referenced by internal_emulate_cond_select().
|
static |
Emulate one Armv8.1-M instruction Unicorn's M33 core does not provide.
The RA8D2 firmware is built for Cortex-M85 (Armv8.1-M) but the nearest core Unicorn offers is M33 (Armv8-M), so the conditional selects, the barriers, Helium, the register-form long shifts and the hardware loops all arrive as undefined instructions. Each handler writes its result and advances PC; the caller stops the engine so the chunked run loop relaunches from the new PC. Split out of internal_dispatch_insn_seam, which keeps the two seams that are about ra8_emulator's own machinery (a patched divide, a security scrub) rather than a missing instruction.
| [in,out] | uc | Unicorn engine. |
| [in] | pc | Address of the trapping instruction. |
| [in] | code | The 4 instruction bytes at pc. |
| true | PC has advanced; the caller must stop and relaunch. |
| false | No handler recognised code. |
code holds the bytes the core failed to decode at pc. uc is stopped inside the invalid-instruction hook. Definition at line 442 of file emu_insn_seams.c.
References emulate_long_shift_reg(), emulate_mve(), internal_emulate_barrier(), internal_emulate_cond_select(), and internal_emulate_lob().
Referenced by internal_dispatch_insn_seam().
|
static |
Try each Armv8.1-M / security seam in turn; true (and stop) if handled.
Try each armv8.1-m / security seam in turn; true (and stop) if handled; this step is contained within the emu insn seams model and uses bounded caller or module-owned storage.
| [in,out] | uc | Unicorn engine whose emulated state is read or updated. |
| [in] | pc | Guest program-counter value associated with the operation. |
| [in] | code | Instruction, status, or command code decoded by the operation. |
| true | The dispatch insn seam condition holds or completed successfully; false otherwise. |
Definition at line 499 of file emu_insn_seams.c.
References emulate_div0_patched(), internal_dispatch_armv81_seam(), and internal_emulate_sec_scrub().
Referenced by on_invalid_insn().
|
static |
Emulate an Armv8-M memory barrier (DSB/DMB/ISB) as a NOP if present.
Some Unicorn builds – e.g. 2.0.1, as packaged on the Linux CI runner – do not decode the self-synchronising barrier instructions DSB / DMB / ISB and trap them as invalid, where a newer build executes them. They have no architectural effect in this single-threaded, in-order emulator (there is no real memory ordering or pipeline to enforce), so recognising the encoding and advancing PC past the 4-byte instruction is a faithful NOP. This keeps the firmware's boot-path barriers (e.g. after a clock / SDRAM register write) from faulting regardless of the host Unicorn version. Anything else is left untouched.
| [in,out] | uc | Unicorn engine. |
| [in] | pc | Address of the trapped instruction. |
| [in] | code | The 4 instruction bytes already read at pc. |
| true | The emulate barrier condition holds or completed successfully; false otherwise. |
< First half-word of DSB/DMB/ISB.
< Fixed high byte of the second h-word.
< 0x8F: the barrier group.
< Barrier subtype field, bits [7:4].
< DSB.
< DMB.
< ISB.
< Thumb-2 barrier instruction length.
Definition at line 265 of file emu_insn_seams.c.
References RA8_INTERNAL.
Referenced by internal_dispatch_armv81_seam().
|
static |
Emulate one Armv8.1-M conditional-select instruction if present at PC.
Decodes the CSEL/CSINC/CSINV/CSNEG encoding (see cond_select_t), evaluates the condition against the APSR, computes Rd, writes it back, and advances PC past the 4-byte instruction. This lets Unicorn's M33 core execute the M85 firmware's branchless index math instead of trapping on an opcode it does not implement. Anything that is not this family is left untouched.
| [in,out] | uc | Unicorn engine. |
| [in] | pc | Address of the trapped instruction. |
| [in] | code | The 4 instruction bytes already read at pc. |
| true | The emulate cond select condition holds or completed successfully; false otherwise. |
Definition at line 183 of file emu_insn_seams.c.
References internal_cond_holds(), internal_cs_reserved_reg(), k_arm_reg_id, k_cs_hw1_mask, k_cs_hw1_match, k_cs_hw2_b14, k_cs_hw2_b15, k_cs_insn_len, k_cs_op_csel, k_cs_op_csinc, k_cs_op_csinv, k_cs_op_csneg, k_cs_op_mask, k_cs_op_shift, and k_lo4_mask.
Referenced by internal_dispatch_armv81_seam().
|
static |
Emulate a DLS/LE Low-Overhead-Branch instruction; true iff handled.
Emulate a dls/le low-overhead-branch instruction; true iff handled; this step is contained within the emu insn seams model and uses bounded caller or module-owned storage.
| [in,out] | uc | Unicorn engine whose emulated state is read or updated. |
| [in] | pc | Guest program-counter value associated with the operation. |
| [in] | code | Instruction, status, or command code decoded by the operation. |
| true | The emulate lob condition holds or completed successfully; false otherwise. |
Definition at line 368 of file emu_insn_seams.c.
References k_arm_reg_id, k_byte_bits, k_lob_dls_h1m, k_lob_dls_hw1, k_lob_dls_hw2, k_lob_insn_len, k_lob_le_h2m, k_lob_le_hw1, k_lob_le_hw2, k_lob_le_imm10, k_lob_le_lsb, k_lob_rn_mask, RA8_INTERNAL, and s_lob_emulated.
Referenced by internal_dispatch_armv81_seam().
|
static |
Emulate the Armv8-M security register-scrub ops as NOPs.
CLRM {regs} and VSCCLRM {s..,VPR} zero caller-saved core / FP registers on a Non-Secure-Callable return so Secure data cannot leak to the Non-Secure caller. ra8_emulator is a single flat domain with one register/FP bank, so the scrub has no observable effect on a correct caller (the cleared registers are already caller-saved/clobbered) – model them as NOPs so the cmse veneer epilogue runs. Unicorn's M33 rejects both as invalid.
| [in,out] | uc | Unicorn engine. |
| [in] | pc | Address of the instruction. |
| [in] | code | Four instruction bytes at pc. |
code was a scrub op (PC advanced past it); false otherwise. code holds the 4 bytes at pc. uc is running. | true | The emulate sec scrub condition holds or completed successfully; false otherwise. |
Definition at line 316 of file emu_insn_seams.c.
References k_byte_bits, k_clrm_hw0, k_thumb2_insn_bytes, k_vscclrm_hw0_d, and k_vscclrm_hw0_s.
Referenced by internal_dispatch_insn_seam().
|
static |
Report + capstone-disassemble an instruction no seam could decode.
Report + capstone-disassemble an instruction no seam could decode; this step is contained within the emu insn seams model and uses bounded caller or module-owned storage.
| [in] | pc | Guest program-counter value associated with the operation. |
| [in] | code | Instruction, status, or command code decoded by the operation. |
Definition at line 534 of file emu_insn_seams.c.
References k_cs_insn_len, priv_emu_io_errf(), and RA8_INTERNAL.
Referenced by on_invalid_insn().
| bool on_invalid_insn | ( | uc_engine * | uc, |
| void * | user ) |
Disassemble + report an instruction the core could not decode.
UC_HOOK_INSN_INVALID dispatcher: service or report a trapped opcode.
Definition at line 560 of file emu_insn_seams.c.
References emu_mem_read(), emu_mve_nocp_spurious(), internal_dispatch_insn_seam(), and internal_report_unhandled_insn().
Referenced by emu_insn_seams_install().
|
static |
Count of LOB instructions emulated this run (run-end telemetry).
Definition at line 353 of file emu_insn_seams.c.
Referenced by emu_lob_emulated_count(), and internal_emulate_lob().