1 ;;; Copyright (C) 2018 Keziah Wesley
3 ;;; You can redistribute and/or modify this file under the terms of the
4 ;;; GNU Affero General Public License as published by the Free Software
5 ;;; Foundation, either version 3 of the License, or (at your option) any
8 ;;; This file is distributed in the hope that it will be useful, but
9 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 ;;; Affero General Public License for more details.
13 ;;; You should have received a copy of the GNU Affero General Public
14 ;;; License along with this file. If not, see
15 ;;; <http://www.gnu.org/licenses/>.
26 db ((ops.%1 - ops)>>3), %2, %3, %4
29 db ((ops.%1 - ops)>>3), %2
37 ;;; tracing: abort if not primtype match (XXX: actual tests usu. more complex...)
41 ;;; tracing: abort if not fulltype match
45 %macro tr_guard_bounds 0
48 ;;; profiling: count jumps if offset negative.
52 ;;; log if tracing. record if profiling and offset negative.
56 ;;; tracing: log road not taken.
57 %macro tr_br_fallthrough 2
68 %define TT_MSUBR (PT_RECORD | 0100h) ; aka RVECTOR
69 %define TT_CODE (PT_UBLOCK | 0100h)
70 %define TT_DOPE_UB (PT_DOPE | (PT_UBLOCK << 8))
73 ; lea r14, [.leaf_ret]
100 errStr db 'An error has occurred.',0xA
103 byeStr db 0xA,'Goodbye!',0xA
109 ;<destrucxn 1 start..end>
111 ;reqs: ;<destrucr? 1 opts local1>
112 ;<destrucr? 1 opts local2>
113 ;<error NEED-MORE-ARGS>
114 ;opt1: ;<destrucr? 1 opt2 local3>
116 ;opt2: ;<destrucr? 1 chk local4>
118 ;chk: ;<empr? 1 body>
119 ;<error TOO-MANY-ARGS>
122 ;reqs: ;<destrucxn local1..local2>
123 ;opt1: ;<destrucr? 1 opt2 local3>
125 ;opt2: ;<destrucr? 1 chk local4>
127 ;chk: ;<empr? 1 body>
128 ;<error TOO-MANY-ARGS>
131 ;; <MAPF ,STRING <FUNCTION (x) ...>>
134 ;; implicit locals (0-1):
137 ;; reserved locals (2-2):
157 .len equ ($-unparse_code) >> 2
159 doj TT_DOPE_UB, 0, .len
161 doj TT_CODE, unparse_code.len, unparse_code
162 doj TT_MSUBR, unparse_rv.len, unparse_rv
163 .len equ ($-unparse_rv) >> 3
166 ;; implicit locals (0-1):
169 ;; reserved locals (2-3):
187 .len equ ($-fact_code) >> 2
189 doj TT_DOPE_UB, 0, .len
191 doj TT_CODE, fact_code.len, fact_code
192 doj TT_MSUBR, fact_rv.len, fact_rv
193 .len equ ($-fact_rv) >> 3
196 ;; implicit locals (0-1):
199 ;; reserved locals (2-2):
216 .len equ ($-toplevel_code) >> 2
218 doj TT_DOPE_UB, 0, .len
220 doj TT_CODE, toplevel_code.len, toplevel_code
221 doj TT_MSUBR, fact_rv.len, fact_rv
222 doj TT_MSUBR, unparse_rv.len, unparse_rv
223 .len equ ($-toplevel_rv) >> 3
224 oj_toplevel doj TT_MSUBR, toplevel_rv.len, toplevel_rv
230 ;; ebp: bp [nonnegative idxes are locals, neg are cur FRAME's fields]
231 ;; esp: sp [top of stack. starts at end of locals. grows UP.]
232 ;; edi: next free heap pos [grows up.]
233 ;; on entry into an op:
238 ;; inline this for "release mode", but it's a useful breakpoint
251 ;; Setup memory layout:
252 mov edx, 1|2 ; int prot = PROT_READ | PROT_WRITE
253 mov r10d, 2|32|64 ; int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT
254 mov r8d, -1 ; int fd = -1
255 xor edi, edi ; void *addr = NULL
256 xor r9d, r9d ; off_t offset = 0
257 ;; initial stack (1MB)
258 mov esi, 100000h ; size_t length
263 ;; (large-alloc space)...
265 ;; minor heap (default: 8MB)
266 mov esi, 800000h ; size_t length
271 ;; Load some builtins into the heap
273 ;; Setup a PROCESS for the GC...
276 ;; point locals to a static MSUBR object for the toplevel MSUBR
278 ;; set eax,ebx as if we'd just read <APPLY 0 0 0>
281 xor esi, esi ; toplevel must not return
284 op_princ: ; PRINC [B]:STRING
285 mov rax, [rbp + 8*rbx]
295 mov edx, eax ; size_t
297 shr rax, 32 ; const void *
299 mov eax, 1 ; write(2)
300 mov edi, eax ; int fd = stdout
311 op_halt: ; HALT [B]:FIX
312 mov edx, byeLen ; size_t count
313 mov esi, byeStr ; const void *buf
314 mov eax, 1 ; write(2)
315 lea edi, [rax+rax] ; int fd = stderr
318 mov rax, [rbp + 8*rbx]
322 mov edi, eax ; int status
323 mov eax, 60 ; exit(2)
326 op_applyb: ; <APPLY nargs:byte local:msubr =>
327 ; ignore [=] for now. we'll re-decode this insn in op_return
329 mov rax, [rbp + 8*rax]
350 ;; save a FRAME of state to return to:
357 ;mov [rbp-16], e-- ; padding
358 mov [rbp-12], ebx ; start of args on stack
359 mov [rbp-8], esi ; return-to ip
360 mov [rbp-4], r8d ; prev FRAME/locals boundary
364 lea rbx, [rbx+rcx+PT_RECORD]
365 mov [rbp], rdx ; 0: MSUBR (RVECTOR)
366 mov [rbp+8], rbx ; 1: ARGS TUPLE
375 op_return: ; <RETURN any:local>
388 op_nthrb: ; <NTH index:byte record:local =>
391 mov rax, [rbp + 8*rcx]
393 ;; TODO: fallback to pmorphic
409 op_restyl: ; <RESTYL index:local bytes:local =>
412 mov rax, [rbp + 8*rcx]
414 ;; TODO: fallback to pmorphic
417 mov rbx, [rbp + 8*rbx]
418 sub rbx, PT_FIX ; (dec rbx) if PT_FIX==1
432 op_putyl: ; <PUTYL local:index value:local local:bytes>
435 mov rcx, [rbp + 8*rbx]
443 mov rax, [rbp + 8*rax]
445 ;; TODO: fallback to pmorphic
449 mov rdx, [rbp + 8*rdx]
459 mov [rax + rcx - 1], dl
463 op_constb: ; <CONSTB byte = hitype:byte>
478 op_subb: ; <SUBB rhs:byte in:fix =>
493 op_addb: ; <ADDB ubyte local:fix =>
508 op_andb: ; <ANDB byte local:fix =>
521 op_lshb: ; <LSHB byte local:fix =>
536 op_newyl: ; <NEWYB len:local initial:byte =>
550 or eax, ecx ; " aaaa"
553 or rax, rcx ; "aaaaaaaa"
565 blitheap_op: ; rax=init ecx=len (dword [rdx]: rewritten if base != edi)
576 op_mull: ; <MULL b:fix c:fix =>
598 op_grtrb: ; <GRTRB? rhs:byte tgt in:fix>
611 op_jump: ; <JUMP . ##>
616 op_error: ; ERROR local:atom local:any local:any
621 mov edx, errLen ; size_t count
622 mov esi, errStr ; const void *buf
623 mov eax, 1 ; write(2)
624 lea edi, [rax+rax] ; int fd = stderr
630 mov edi, -1 ; int status
631 mov eax, 60 ; exit(2)