1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; UrForth level
1: self
-hosting
32-bit Forth compiler
3 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 code: (URFORTH-STARTUP-CODEBLOCK)
17 inc ecx
;; skip final
0 argument
23 ;; move data stack up a little
(so underflows won
't destroy cli args and such)
26 ;; probe both stacks, to ensure that we can use "sub esp" without problems
27 ld eax,esp ;; so we will be able to restore ESP
28 mov ecx,DSTACK_SIZE+RSTACK_SIZE+2048 ;; and two extra pages, because why not
31 sub esp,4096+4 ;; compensate previous push
32 sub ecx,1024 ;; 4096/4
33 jr nc,.stack_probe_loop
37 ;; fuck. so-called "modern" distros are all broken, and we cannot use BRK to extend our image
39 ;; allocate memory for dictionary
40 ;; binary size should be equal to DP
41 ld eax,[pfa "(init-mem-size)"]
46 ld [pfa "dp-last-addr"],ebx
48 ld eax,[elfhead_codesize_addr+4] ;; virtual size
50 sub ebx,[elfhead_codesize_addr] ;; disk size
54 lea eax,[eax+urforth_code_base_addr-1]
55 ld [pfa "dp-last-addr"],eax
56 ;; set it here, why not
57 ld eax,[elfhead_codesize_addr] ;; disk size
58 add eax,urforth_code_base_addr
59 ld [pfa "dp-protected"],eax
62 ;; fix "next" codepoint (just in case)
64 ;; put 0xff 0xe0 there (jmp eax)
66 ld dword [urforth_next],eax
69 $if URFORTH_TLS_TYPE = URFORTH_TLS_TYPE_FS
70 ;; allocate one page for uservars
72 xor ebx,ebx ;; address
73 ld ecx,URFORTH_MAX_USERAREA_SIZE
75 ld esi,0x22 ;; anon, private
83 ;; copy default values
84 ld esi,ua_default_values
86 ld ecx,URFORTH_MAX_USERAREA_CELLS
89 ld [eax+ua_ofs_baseaddr],eax
90 ;; allocate thread data area
91 ;; entry 6 is usually reserved for stack
92 ;; entries 7 and 8 seems to be free
94 ld dword [esp],-1 ;; get free TLS entry
95 ld dword [esp+4],eax ;; base address
96 ld dword [esp+8],1 ;; limit, in pages
97 ld dword [esp+12],0b1_0_1_0_00_1
103 ;; load TS with the created selector
105 ld [pfa "(user-tls-entry-index)"],eax
112 ;; allocate memory for debugger/segfault stack
115 ;; EAX: start address
119 ld [urfsegfault_stack_bottom],ebx
121 call urforth_setup_segfault_handler
135 ld edx,[pfa "dp-last-addr"]
200 ;; setup return stack
202 sub ERP,RSTACK_SIZE*4
204 ;; save initial stack ponters
205 ld ts:[ua_ofs_sp0],esp
206 ld ts:[ua_ofs_rp0],ERP
208 ;; and setup initial stack size (it is different from default thread stack sizes)
209 ld ts:[ua_ofs_spsize],DSTACK_SIZE
210 ld ts:[ua_ofs_rpsize],RSTACK_SIZE
212 ;; patch "main thread" flag
213 ld dword ts:[ua_ofs_is_main_thread],1
215 ;; and start execution
216 jp cfa "(COLD-FIRSTTIME)"
218 ;; allocate memory via BRK
222 ;; EAX: start address (first byte)
223 ;; EBX: end address (*after* the last byte)
224 ;; other registers and flags are dead (except ESP)
226 ;; save size (overallocate a little, for safety)
230 ;; get current BRK address
235 ;; [esp]: start address
236 ;; [esp+4]: alloc size
243 ld ebx,eax ;; EBX=end address
245 ld eax,[esp] ;; start address
246 add eax,[esp+4] ;; alloc size
251 ;; calc end address, to be precise
253 ;; remove overallocated safety margin from end address
259 .pverstr: db "/proc/version",0
261 .fatal_oom_msg: db "FATAL: out of memory!",10
262 .fatal_oom_msg_len equ $-.fatal_oom_msg
265 ;; print error and exit
268 mov ecx,.fatal_oom_msg
269 mov edx,.fatal_oom_msg_len