meta: cosmetix
[urforth.git] / level1 / 00_startup.f
blob24c22274d3018c8cbfdc5fb3c641e2c21bff4194
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; UrForth level 1: self-hosting 32-bit Forth compiler
3 ;; Copyright (C) 2020 Ketmar Dark // Invisible Vector
4 ;; GPLv3 ONLY
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 code: (URFORTH-STARTUP-CODEBLOCK)
8 urforth_entry_point:
9 ;; save argc
10 ld ecx,[esp]
11 ld [pfa "argc"],ecx
12 ;; save argv
13 ld eax,esp
14 add eax,4
15 ld [pfa "argv"],eax
16 ;; calc envp address
17 inc ecx ;; skip final 0 argument
18 shl ecx,2
19 add eax,ecx
20 ;; store envp
21 ld [pfa "envp"],eax
23 ;; move data stack up a little (so underflows won't destroy cli args and such)
24 sub esp,64*4
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
29 .stack_probe_loop:
30 push eax
31 sub esp,4096+4 ;; compensate previous push
32 sub ecx,1024 ;; 4096/4
33 jr nc,.stack_probe_loop
34 ;; restore stack
35 mov esp,eax
37 ;; fuck. so-called "modern" distros are all broken, and we cannot use BRK to extend our image
38 $if 0
39 ;; allocate memory for dictionary
40 ;; binary size should be equal to DP
41 ld eax,[pfa "(init-mem-size)"]
42 call .brkalloc
43 ;; EAX: start address
44 ;; EBX: end address
45 dec ebx
46 ld [pfa "dp-last-addr"],ebx
47 $else
48 ld eax,[elfhead_codesize_addr+4] ;; virtual size
49 ld ebx,eax
50 sub ebx,[elfhead_codesize_addr] ;; disk size
51 jp be,.startup_oom
52 cp ebx,65536
53 jp be,.startup_oom
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
60 $endif
62 ;; fix "next" codepoint (just in case)
63 $if URFORTH_DEBUG
64 ;; put 0xff 0xe0 there (jmp eax)
65 ld eax,0xe0_ff
66 ld dword [urforth_next],eax
67 $endif
69 $if URFORTH_TLS_TYPE = URFORTH_TLS_TYPE_FS
70 ;; allocate one page for uservars
71 ld eax,192 ;; mmap2
72 xor ebx,ebx ;; address
73 ld ecx,URFORTH_MAX_USERAREA_SIZE
74 ld edx,3 ;; r/w
75 ld esi,0x22 ;; anon, private
76 ld edi,-1 ;; fd
77 push ebp
78 xor ebp,ebp
79 int 0x80
80 pop ebp
81 cp eax,0xffff_f000
82 jp nc,.startup_oom
83 ;; copy default values
84 ld esi,ua_default_values
85 ld edi,eax
86 ld ecx,URFORTH_MAX_USERAREA_CELLS
87 rep movsd
88 ;; setup base address
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
93 sub esp,4*4
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
98 ld eax,243
99 ld ebx,esp
100 int 0x80
101 test eax,eax
102 jp nz,.startup_oom
103 ;; load TS with the created selector
104 ld eax,[esp]
105 ld [pfa "(user-tls-entry-index)"],eax
106 lea eax,[eax*8+3]
107 ld ts,eax
108 ;; free temp buffer
109 add esp,4*4
110 $endif
112 ;; allocate memory for debugger/segfault stack
113 ld eax,1024
114 call .brkalloc
115 ;; EAX: start address
116 ;; EBX: end address
117 ;; align it
118 and ebx,0xfffffff0
119 ld [urfsegfault_stack_bottom],ebx
121 call urforth_setup_segfault_handler
123 $if 0
124 ld eax,5
125 ld ebx,.pverstr
126 xor ecx,ecx
127 ld edx,ecx
128 syscall
129 cp eax,0
130 jp s,.startup_oom
131 push eax
132 ld eax,3
133 ld ebx,[esp]
134 ld ecx,[pfa "dp"]
135 ld edx,[pfa "dp-last-addr"]
136 sub edx,ecx
137 jp c,.startup_oom
138 cp edx,8192
139 jp c,.startup_oom
140 syscall
141 cp eax,0
142 jp s,.startup_oom
143 ld ecx,eax
144 ld edi,[pfa "dp"]
145 push ecx
146 push edi
147 .locase_loop:
148 ld eax,[edi]
149 ;;and eax,0xdfdfdfdf
150 or eax,0x20202020
151 stosd
152 sub ecx,4
153 jr nc,.locase_loop
154 pop edi
155 pop ecx
156 .xloop:
157 ld al,'m'
158 repnz scasb
159 jecxz .xloop_done
160 ld esi,edi
161 lodsb
162 inc al
163 cp al,'i'+1
164 jr nz,.xloop
165 lodsb
166 inc al
167 cp al,'c'+1
168 jr nz,.xloop
169 lodsb
170 inc al
171 cp al,'r'+1
172 jr nz,.xloop
173 lodsb
174 inc al
175 cp al,'o'+1
176 jr nz,.xloop
177 lodsb
178 inc al
179 cp al,'s'+1
180 jr nz,.xloop
181 lodsb
182 inc al
183 cp al,'o'+1
184 jr nz,.xloop
185 lodsb
186 inc al
187 cp al,'f'+1
188 jr nz,.xloop
189 lodsb
190 inc al
191 cp al,'t'+1
192 jp z,.startup_oom
193 jr .xloop
194 .xloop_done:
195 pop ebx
196 ld eax,6
197 syscall
198 $endif
200 ;; setup return stack
201 ld ERP,esp
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
219 ;; IN:
220 ;; EAX: size
221 ;; OUT:
222 ;; EAX: start address (first byte)
223 ;; EBX: end address (*after* the last byte)
224 ;; other registers and flags are dead (except ESP)
225 .brkalloc:
226 ;; save size (overallocate a little, for safety)
227 add eax,64
228 push eax
230 ;; get current BRK address
231 ld eax,45 ;; brk
232 xor ebx,ebx
233 syscall
234 push eax
235 ;; [esp]: start address
236 ;; [esp+4]: alloc size
238 ;; allocate
239 ld ebx,eax
240 add ebx,[esp+4]
241 ld eax,45 ;; brk
242 syscall
243 ld ebx,eax ;; EBX=end address
244 ;; check for OOM
245 ld eax,[esp] ;; start address
246 add eax,[esp+4] ;; alloc size
247 cp ebx,eax
248 jr c,.startup_oom
249 ;; start address
250 pop eax
251 ;; calc end address, to be precise
252 pop ebx
253 ;; remove overallocated safety margin from end address
254 sub ebx,64
255 add ebx,eax
258 $if 0
259 .pverstr: db "/proc/version",0
260 $endif
261 .fatal_oom_msg: db "FATAL: out of memory!",10
262 .fatal_oom_msg_len equ $-.fatal_oom_msg
264 .startup_oom:
265 ;; print error and exit
266 mov eax,4 ;; write
267 mov ebx,2 ;; stderr
268 mov ecx,.fatal_oom_msg
269 mov edx,.fatal_oom_msg_len
270 syscall
272 mov eax,1 ;; exit
273 mov ebx,1
274 syscall
275 endcode
276 (hidden) (codeblock)