From aa0f28cc5ed1b1cb8939a6666b5e2ad8c96dfbec Mon Sep 17 00:00:00 2001 From: Fey Naomi Schrewe Date: Wed, 22 Oct 2025 12:25:05 +0200 Subject: [PATCH] feat: add unicorn emulation --- .gitignore | 4 + host/assembler.fnl | 17 +-- host/util/emulator.fnl | 245 +++++++++++++++++++++++++++++++++++++++++ target/examples.fnl | 9 ++ 4 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 host/util/emulator.fnl create mode 100644 target/examples.fnl diff --git a/.gitignore b/.gitignore index 0667445..da57932 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ luac.out *.hex +/luarocks +/lua +/lua_modules +/.luarocks diff --git a/host/assembler.fnl b/host/assembler.fnl index 6cc2dde..661d9a0 100644 --- a/host/assembler.fnl +++ b/host/assembler.fnl @@ -4,7 +4,9 @@ : branch : branch-link} (require :host.assembler.opcodes)) -(local {: any : slice : push} (require :deps.lume)) +(local {: any : slice : push : map} (require :deps.lume)) +(local {: word->byte} (require :host.util)) +(local {: emulate} (require :host.util.emulator)) (fn label [name] {:label name}) (fn label? [value] @@ -28,13 +30,8 @@ ((. form 1) (table.unpack (slice form 2))))))) state)) -(fn link [{: labels : instructions : reverse-labels}] - ()) - -(macro x [...] - `[,(unpack (icollect [_ form (ipairs ...)] '[,(. form 1)]))]) - -(macrodebug (x (move (r 9) (r 8)))) +; (fn link [{: labels : instructions : reverse-labels}] +; ()) (assemble [[move (r 8) (r 2)] @@ -42,3 +39,7 @@ [move (r 9) (r 3)] [branch (label :label-1)]] 0x8000) + +(let [assembly (assemble [[move (r 8) 127]]) + byte-string (table.concat (map (. assembly :instructions) word->byte) "")] + (emulate byte-string)) diff --git a/host/util/emulator.fnl b/host/util/emulator.fnl new file mode 100644 index 0000000..7f05f1c --- /dev/null +++ b/host/util/emulator.fnl @@ -0,0 +1,245 @@ +(local unicorn (require :unicorn)) +(local {:UC_ARCH_ARM arch_arm} (require :unicorn.unicorn_const)) +(local {:UC_ARM_REG_R0 r0-offset} (require :unicorn.arm_const)) + +(require :unicorn.arm_const) +; {:UC_ARM_REG_APSR 1 +; :UC_ARM_REG_APSR_G 128 +; :UC_ARM_REG_APSR_NZCV 2 +; :UC_ARM_REG_APSR_NZCVQ 127 +; :UC_ARM_REG_APSR_NZCVQG 129 +; :UC_ARM_REG_BASEPRI 124 +; :UC_ARM_REG_BASEPRI_MAX 125 +; :UC_ARM_REG_C13_C0_2 112 +; :UC_ARM_REG_C13_C0_3 113 +; :UC_ARM_REG_C1_C0_2 111 +; :UC_ARM_REG_CONTROL 117 +; :UC_ARM_REG_CPSR 3 +; :UC_ARM_REG_CP_REG 139 +; :UC_ARM_REG_D0 14 +; :UC_ARM_REG_D1 15 +; :UC_ARM_REG_D10 24 +; :UC_ARM_REG_D11 25 +; :UC_ARM_REG_D12 26 +; :UC_ARM_REG_D13 27 +; :UC_ARM_REG_D14 28 +; :UC_ARM_REG_D15 29 +; :UC_ARM_REG_D16 30 +; :UC_ARM_REG_D17 31 +; :UC_ARM_REG_D18 32 +; :UC_ARM_REG_D19 33 +; :UC_ARM_REG_D2 16 +; :UC_ARM_REG_D20 34 +; :UC_ARM_REG_D21 35 +; :UC_ARM_REG_D22 36 +; :UC_ARM_REG_D23 37 +; :UC_ARM_REG_D24 38 +; :UC_ARM_REG_D25 39 +; :UC_ARM_REG_D26 40 +; :UC_ARM_REG_D27 41 +; :UC_ARM_REG_D28 42 +; :UC_ARM_REG_D29 43 +; :UC_ARM_REG_D3 17 +; :UC_ARM_REG_D30 44 +; :UC_ARM_REG_D31 45 +; :UC_ARM_REG_D4 18 +; :UC_ARM_REG_D5 19 +; :UC_ARM_REG_D6 20 +; :UC_ARM_REG_D7 21 +; :UC_ARM_REG_D8 22 +; :UC_ARM_REG_D9 23 +; :UC_ARM_REG_EAPSR 119 +; :UC_ARM_REG_EAPSR_G 134 +; :UC_ARM_REG_EAPSR_NZCVQ 133 +; :UC_ARM_REG_EAPSR_NZCVQG 135 +; :UC_ARM_REG_ENDING 141 +; :UC_ARM_REG_EPSR 121 +; :UC_ARM_REG_ESR 140 +; :UC_ARM_REG_FAULTMASK 126 +; :UC_ARM_REG_FP 77 +; :UC_ARM_REG_FPEXC 4 +; :UC_ARM_REG_FPINST 5 +; :UC_ARM_REG_FPINST2 46 +; :UC_ARM_REG_FPSCR 6 +; :UC_ARM_REG_FPSCR_NZCV 7 +; :UC_ARM_REG_FPSID 8 +; :UC_ARM_REG_IAPSR 118 +; :UC_ARM_REG_IAPSR_G 131 +; :UC_ARM_REG_IAPSR_NZCVQ 130 +; :UC_ARM_REG_IAPSR_NZCVQG 132 +; :UC_ARM_REG_IEPSR 122 +; :UC_ARM_REG_INVALID 0 +; :UC_ARM_REG_IP 78 +; :UC_ARM_REG_IPSR 114 +; :UC_ARM_REG_ITSTATE 9 +; :UC_ARM_REG_LR 10 +; :UC_ARM_REG_MSP 115 +; :UC_ARM_REG_MVFR0 47 +; :UC_ARM_REG_MVFR1 48 +; :UC_ARM_REG_MVFR2 49 +; :UC_ARM_REG_PC 11 +; :UC_ARM_REG_PRIMASK 123 +; :UC_ARM_REG_PSP 116 +; :UC_ARM_REG_Q0 50 +; :UC_ARM_REG_Q1 51 +; :UC_ARM_REG_Q10 60 +; :UC_ARM_REG_Q11 61 +; :UC_ARM_REG_Q12 62 +; :UC_ARM_REG_Q13 63 +; :UC_ARM_REG_Q14 64 +; :UC_ARM_REG_Q15 65 +; :UC_ARM_REG_Q2 52 +; :UC_ARM_REG_Q3 53 +; :UC_ARM_REG_Q4 54 +; :UC_ARM_REG_Q5 55 +; :UC_ARM_REG_Q6 56 +; :UC_ARM_REG_Q7 57 +; :UC_ARM_REG_Q8 58 +; :UC_ARM_REG_Q9 59 +; :UC_ARM_REG_R0 66 +; :UC_ARM_REG_R1 67 +; :UC_ARM_REG_R10 76 +; :UC_ARM_REG_R11 77 +; :UC_ARM_REG_R12 78 +; :UC_ARM_REG_R13 12 +; :UC_ARM_REG_R14 10 +; :UC_ARM_REG_R15 11 +; :UC_ARM_REG_R2 68 +; :UC_ARM_REG_R3 69 +; :UC_ARM_REG_R4 70 +; :UC_ARM_REG_R5 71 +; :UC_ARM_REG_R6 72 +; :UC_ARM_REG_R7 73 +; :UC_ARM_REG_R8 74 +; :UC_ARM_REG_R9 75 +; :UC_ARM_REG_S0 79 +; :UC_ARM_REG_S1 80 +; :UC_ARM_REG_S10 89 +; :UC_ARM_REG_S11 90 +; :UC_ARM_REG_S12 91 +; :UC_ARM_REG_S13 92 +; :UC_ARM_REG_S14 93 +; :UC_ARM_REG_S15 94 +; :UC_ARM_REG_S16 95 +; :UC_ARM_REG_S17 96 +; :UC_ARM_REG_S18 97 +; :UC_ARM_REG_S19 98 +; :UC_ARM_REG_S2 81 +; :UC_ARM_REG_S20 99 +; :UC_ARM_REG_S21 100 +; :UC_ARM_REG_S22 101 +; :UC_ARM_REG_S23 102 +; :UC_ARM_REG_S24 103 +; :UC_ARM_REG_S25 104 +; :UC_ARM_REG_S26 105 +; :UC_ARM_REG_S27 106 +; :UC_ARM_REG_S28 107 +; :UC_ARM_REG_S29 108 +; :UC_ARM_REG_S3 82 +; :UC_ARM_REG_S30 109 +; :UC_ARM_REG_S31 110 +; :UC_ARM_REG_S4 83 +; :UC_ARM_REG_S5 84 +; :UC_ARM_REG_S6 85 +; :UC_ARM_REG_S7 86 +; :UC_ARM_REG_S8 87 +; :UC_ARM_REG_S9 88 +; :UC_ARM_REG_SB 75 +; :UC_ARM_REG_SL 76 +; :UC_ARM_REG_SP 12 +; :UC_ARM_REG_SPSR 13 +; :UC_ARM_REG_XPSR 120 +; :UC_ARM_REG_XPSR_G 137 +; :UC_ARM_REG_XPSR_NZCVQ 136 +; :UC_ARM_REG_XPSR_NZCVQG 138 +; :UC_CPU_ARM_1026 2 +; :UC_CPU_ARM_1136 4 +; :UC_CPU_ARM_1136_R2 3 +; :UC_CPU_ARM_1176 5 +; :UC_CPU_ARM_11MPCORE 6 +; :UC_CPU_ARM_926 0 +; :UC_CPU_ARM_946 1 +; :UC_CPU_ARM_CORTEX_A15 17 +; :UC_CPU_ARM_CORTEX_A7 14 +; :UC_CPU_ARM_CORTEX_A8 15 +; :UC_CPU_ARM_CORTEX_A9 16 +; :UC_CPU_ARM_CORTEX_M0 7 +; :UC_CPU_ARM_CORTEX_M3 8 +; :UC_CPU_ARM_CORTEX_M33 11 +; :UC_CPU_ARM_CORTEX_M4 9 +; :UC_CPU_ARM_CORTEX_M7 10 +; :UC_CPU_ARM_CORTEX_R5 12 +; :UC_CPU_ARM_CORTEX_R5F 13 +; :UC_CPU_ARM_ENDING 34 +; :UC_CPU_ARM_MAX 33 +; :UC_CPU_ARM_PXA250 21 +; :UC_CPU_ARM_PXA255 22 +; :UC_CPU_ARM_PXA260 23 +; :UC_CPU_ARM_PXA261 24 +; :UC_CPU_ARM_PXA262 25 +; :UC_CPU_ARM_PXA270 26 +; :UC_CPU_ARM_PXA270A0 27 +; :UC_CPU_ARM_PXA270A1 28 +; :UC_CPU_ARM_PXA270B0 29 +; :UC_CPU_ARM_PXA270B1 30 +; :UC_CPU_ARM_PXA270C0 31 +; :UC_CPU_ARM_PXA270C5 32 +; :UC_CPU_ARM_SA1100 19 +; :UC_CPU_ARM_SA1110 20 +; :UC_CPU_ARM_TI925T 18} +; + +; {:close # +; :context_restore # +; :context_save # +; :ctl_exits_disable # +; :ctl_exits_enable # +; :ctl_flush_tlb # +; :ctl_get_arch # +; :ctl_get_cpu_model # +; :ctl_get_exits # +; :ctl_get_exits_cnt # +; :ctl_get_mode # +; :ctl_get_page_size # +; :ctl_get_timeout # +; :ctl_remove_cache # +; :ctl_request_cache # +; :ctl_set_cpu_model # +; :ctl_set_exits # +; :ctl_set_page_size # +; :emu_start # +; :emu_stop # +; :errno # +; :hook_add # +; :hook_del # +; :mem_map # +; :mem_protect # +; :mem_read # +; :mem_regions # +; :mem_unmap # +; :mem_write # +; :query # +; :reg_read # +; :reg_read_as # +; :reg_read_batch # +; :reg_read_batch_as # +; :reg_write # +; :reg_write_as # +; :reg_write_batch #} +; + +(fn get-emulator [] (unicorn.open arch_arm)) + +(fn register [emulator n]) +(fn print-registers [emulator] + (for [i 1 16] (print (string.format "r%-2d := 0x%08x" i (emulator:reg_read (+ r0-offset i)))))) + +(fn emulate [code] + "Run a bytestring on an emulated arm processor" + (with-open [emulator (get-emulator)] + (emulator:mem_map 0 (^ 2 20)) + (emulator:mem_write 0 code) + (emulator:emu_start 0 100) + (print-registers emulator))) + +{: emulate} diff --git a/target/examples.fnl b/target/examples.fnl new file mode 100644 index 0000000..2431b2f --- /dev/null +++ b/target/examples.fnl @@ -0,0 +1,9 @@ +; type in native dialect +(deftype string {length integer + buf (ptr byte)}) + +(Lambda open-file + {read boolean + file-descriptor integer} + (let [flags (lshift read 3)] + (syscall! 93 file-descriptor flags)))