feat: add unicorn emulation

This commit is contained in:
Fey Naomi Schrewe 2025-10-22 12:25:05 +02:00
parent 0da0a54b74
commit aa0f28cc5e
4 changed files with 267 additions and 8 deletions

4
.gitignore vendored
View File

@ -41,3 +41,7 @@ luac.out
*.hex *.hex
/luarocks
/lua
/lua_modules
/.luarocks

View File

@ -4,7 +4,9 @@
: branch : branch
: branch-link} : branch-link}
(require :host.assembler.opcodes)) (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 [name] {:label name})
(fn label? [value] (fn label? [value]
@ -28,13 +30,8 @@
((. form 1) (table.unpack (slice form 2))))))) ((. form 1) (table.unpack (slice form 2)))))))
state)) state))
(fn link [{: labels : instructions : reverse-labels}] ; (fn link [{: labels : instructions : reverse-labels}]
()) ; ())
(macro x [...]
`[,(unpack (icollect [_ form (ipairs ...)] '[,(. form 1)]))])
(macrodebug (x (move (r 9) (r 8))))
(assemble (assemble
[[move (r 8) (r 2)] [[move (r 8) (r 2)]
@ -42,3 +39,7 @@
[move (r 9) (r 3)] [move (r 9) (r 3)]
[branch (label :label-1)]] [branch (label :label-1)]]
0x8000) 0x8000)
(let [assembly (assemble [[move (r 8) 127]])
byte-string (table.concat (map (. assembly :instructions) word->byte) "")]
(emulate byte-string))

245
host/util/emulator.fnl Normal file
View File

@ -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 #<function: 0xb400007bd0e480d0>
; :context_restore #<function: 0xb400007bd0e48a50>
; :context_save #<function: 0xb400007bd0e48250>
; :ctl_exits_disable #<function: 0xb400007bd0e485d0>
; :ctl_exits_enable #<function: 0xb400007bd0e49210>
; :ctl_flush_tlb #<function: 0xb400007bd0e496d0>
; :ctl_get_arch #<function: 0xb400007bd0e49950>
; :ctl_get_cpu_model #<function: 0xb400007bd0e48e50>
; :ctl_get_exits #<function: 0xb400007bd0e49410>
; :ctl_get_exits_cnt #<function: 0xb400007bd0e497d0>
; :ctl_get_mode #<function: 0xb400007bd0e49490>
; :ctl_get_page_size #<function: 0xb400007bd0e49810>
; :ctl_get_timeout #<function: 0xb400007bd0e49390>
; :ctl_remove_cache #<function: 0xb400007bd0e48f10>
; :ctl_request_cache #<function: 0xb400007bd0e49990>
; :ctl_set_cpu_model #<function: 0xb400007bd0e49650>
; :ctl_set_exits #<function: 0xb400007bd0e48d90>
; :ctl_set_page_size #<function: 0xb400007bd0e49290>
; :emu_start #<function: 0xb400007bd0e48490>
; :emu_stop #<function: 0xb400007bd0e48890>
; :errno #<function: 0xb400007bd0e486d0>
; :hook_add #<function: 0xb400007bd0e48690>
; :hook_del #<function: 0xb400007bd0e48150>
; :mem_map #<function: 0xb400007bd0e48710>
; :mem_protect #<function: 0xb400007bd0e48a10>
; :mem_read #<function: 0xb400007bd0e48650>
; :mem_regions #<function: 0xb400007bd0e48b10>
; :mem_unmap #<function: 0xb400007bd0e483d0>
; :mem_write #<function: 0xb400007bd0e48350>
; :query #<function: 0xb400007bd0e48950>
; :reg_read #<function: 0xb400007bd0e48390>
; :reg_read_as #<function: 0xb400007bd0e48450>
; :reg_read_batch #<function: 0xb400007bd0e48590>
; :reg_read_batch_as #<function: 0xb400007bd0e482d0>
; :reg_write #<function: 0xb400007bd0e48850>
; :reg_write_as #<function: 0xb400007bd0e48610>
; :reg_write_batch #<function: 0xb400007bd0e48550>}
;
(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}

9
target/examples.fnl Normal file
View File

@ -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)))