Rev 5356 | Rev 6333 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5356 | Rev 5363 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2007-2012. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2007-2015. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 | 7 | ||
8 | $Revision: 5356 $ |
8 | $Revision: 5363 $ |
9 | 9 | ||
10 | ; Virtual-8086 mode manager |
10 | ; Virtual-8086 mode manager |
11 | ; diamond, 2007, 2008 |
11 | ; diamond, 2007, 2008 |
12 | 12 | ||
13 | DEBUG_SHOW_IO = 0 |
13 | DEBUG_SHOW_IO = 0 |
14 | 14 | ||
15 | struct V86_machine |
15 | struct V86_machine |
16 | ; page directory |
16 | ; page directory |
17 | process dd ? |
17 | process dd ? |
18 | ; mutex to protect all data from writing by multiple threads at one time |
18 | ; mutex to protect all data from writing by multiple threads at one time |
19 | mutex dd ? |
19 | mutex dd ? |
20 | ; i/o permission map |
20 | ; i/o permission map |
21 | iopm dd ? |
21 | iopm dd ? |
22 | ends |
22 | ends |
23 | 23 | ||
24 | ; Create V86 machine |
24 | ; Create V86 machine |
25 | ; in: nothing |
25 | ; in: nothing |
26 | ; out: eax = handle (pointer to struc V86_machine) |
26 | ; out: eax = handle (pointer to struc V86_machine) |
27 | ; eax = NULL => failure |
27 | ; eax = NULL => failure |
28 | ; destroys: ebx, ecx, edx (due to malloc) |
28 | ; destroys: ebx, ecx, edx (due to malloc) |
29 | v86_create: |
29 | v86_create: |
30 | ; allocate V86_machine structure |
30 | ; allocate V86_machine structure |
31 | mov eax, sizeof.V86_machine |
31 | mov eax, sizeof.V86_machine |
32 | call malloc |
32 | call malloc |
33 | test eax, eax |
33 | test eax, eax |
34 | jz .fail |
34 | jz .fail |
35 | ; initialize mutex |
35 | ; initialize mutex |
36 | and dword [eax+V86_machine.mutex], 0 |
36 | and dword [eax+V86_machine.mutex], 0 |
37 | ; allocate tables |
37 | ; allocate tables |
38 | mov ebx, eax |
38 | mov ebx, eax |
39 | 39 | ||
40 | stdcall create_process, 4096, eax, 4096 ;FIXME |
40 | stdcall create_process, 4096, eax, 4096 ;FIXME |
41 | test eax, eax |
41 | test eax, eax |
42 | jz .fail2 |
42 | jz .fail2 |
43 | 43 | ||
44 | mov [eax+PROC.mem_used], 4096 |
44 | mov [eax+PROC.mem_used], 4096 |
45 | mov [ebx+V86_machine.process], eax |
45 | mov [ebx+V86_machine.process], eax |
46 | 46 | ||
47 | push 2000h |
47 | push 2000h |
48 | call kernel_alloc |
48 | call kernel_alloc |
49 | test eax, eax |
49 | test eax, eax |
50 | jz .fail2 |
50 | jz .fail2 |
51 | 51 | ||
52 | mov [ebx+V86_machine.iopm], eax |
52 | mov [ebx+V86_machine.iopm], eax |
53 | 53 | ||
54 | 54 | ||
55 | ; initialize tables |
55 | ; initialize tables |
56 | push edi |
56 | push edi |
57 | mov edi, eax |
57 | mov edi, eax |
58 | mov eax, -1 |
58 | mov eax, -1 |
59 | mov ecx, 2000h/4 |
59 | mov ecx, 2000h/4 |
60 | rep stosd |
60 | rep stosd |
61 | 61 | ||
62 | mov eax, [ebx+V86_machine.process] |
62 | mov eax, [ebx+V86_machine.process] |
63 | mov eax, [eax+PROC.pdt_0_phys] |
63 | mov eax, [eax+PROC.pdt_0_phys] |
64 | 64 | ||
65 | pushfd |
65 | pushfd |
66 | cli |
66 | cli |
67 | mov cr3, eax |
67 | mov cr3, eax |
68 | 68 | ||
69 | 69 | ||
70 | ; now V86 specific: initialize known addresses in first Mb |
70 | ; now V86 specific: initialize known addresses in first Mb |
71 | 71 | ||
72 | ; first page - BIOS data (shared between all machines!) |
72 | ; first page - BIOS data (shared between all machines!) |
73 | ; physical address = 0 |
73 | ; physical address = 0 |
74 | ; linear address = OS_BASE |
74 | ; linear address = OS_BASE |
75 | ; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!) |
75 | ; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!) |
76 | ; physical address = 0x9C000 |
76 | ; physical address = 0x9C000 |
77 | ; linear address = 0x8009C000 |
77 | ; linear address = 0x8009C000 |
78 | ; (I have seen one computer with EBDA segment = 0x9D80, |
78 | ; (I have seen one computer with EBDA segment = 0x9D80, |
79 | ; all other computers use less memory) |
79 | ; all other computers use less memory) |
80 | 80 | ||
81 | mov eax, PG_UWR |
81 | mov eax, PG_UWR |
82 | mov [page_tabs], eax |
82 | mov [page_tabs], eax |
83 | invlpg [eax] |
83 | invlpg [eax] |
84 | 84 | ||
85 | mov byte [0x500], 0xCD |
85 | mov byte [0x500], 0xCD |
86 | mov byte [0x501], 0x13 |
86 | mov byte [0x501], 0x13 |
87 | mov byte [0x502], 0xF4 |
87 | mov byte [0x502], 0xF4 |
88 | mov byte [0x503], 0xCD |
88 | mov byte [0x503], 0xCD |
89 | mov byte [0x504], 0x10 |
89 | mov byte [0x504], 0x10 |
90 | mov byte [0x505], 0xF4 |
90 | mov byte [0x505], 0xF4 |
91 | 91 | ||
92 | mov eax, 0x99000+PG_UWR |
92 | mov eax, 0x99000+PG_UWR |
93 | mov edi, page_tabs+0x99*4 |
93 | mov edi, page_tabs+0x99*4 |
94 | mov edx, 0x1000 |
94 | mov edx, 0x1000 |
95 | mov ecx, 7 |
95 | mov ecx, 7 |
96 | @@: |
96 | @@: |
97 | stosd |
97 | stosd |
98 | add eax, edx |
98 | add eax, edx |
99 | loop @b |
99 | loop @b |
100 | 100 | ||
101 | ; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!) |
101 | ; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!) |
102 | ; physical address = 0xC0000 |
102 | ; physical address = 0xC0000 |
103 | 103 | ||
104 | mov eax, 0xC0000+PG_UWR |
104 | mov eax, 0xC0000+PG_UWR |
105 | mov edi, page_tabs+0xC0*4 |
105 | mov edi, page_tabs+0xC0*4 |
106 | mov ecx, 64 |
106 | mov ecx, 64 |
107 | @@: |
107 | @@: |
108 | stosd |
108 | stosd |
109 | add eax, edx |
109 | add eax, edx |
110 | loop @b |
110 | loop @b |
111 | 111 | ||
112 | mov eax, sys_proc |
112 | mov eax, sys_proc |
113 | push ebx |
113 | push ebx |
114 | call set_cr3 |
114 | call set_cr3 |
115 | pop ebx |
115 | pop ebx |
116 | popfd |
116 | popfd |
117 | 117 | ||
118 | pop edi |
118 | pop edi |
119 | 119 | ||
120 | mov eax, ebx |
120 | mov eax, ebx |
121 | ret |
121 | ret |
122 | .fail2: |
122 | .fail2: |
123 | mov eax, ebx |
123 | mov eax, ebx |
124 | call free |
124 | call free |
125 | .fail: |
125 | .fail: |
126 | xor eax, eax |
126 | xor eax, eax |
127 | ret |
127 | ret |
128 | 128 | ||
129 | ;not used |
129 | ;not used |
130 | ; Destroy V86 machine |
130 | ; Destroy V86 machine |
131 | ; in: eax = handle |
131 | ; in: eax = handle |
132 | ; out: nothing |
132 | ; out: nothing |
133 | ; destroys: eax, ebx, ecx, edx (due to free) |
133 | ; destroys: eax, ebx, ecx, edx (due to free) |
134 | ;v86_destroy: |
134 | ;v86_destroy: |
135 | ; push eax |
135 | ; push eax |
136 | ; stdcall kernel_free, [eax+V86_machine.pagedir] |
136 | ; stdcall kernel_free, [eax+V86_machine.pagedir] |
137 | ; pop eax |
137 | ; pop eax |
138 | ; jmp free |
138 | ; jmp free |
139 | 139 | ||
140 | ; Translate V86-address to linear address |
140 | ; Translate V86-address to linear address |
141 | ; in: eax=V86 address |
141 | ; in: eax=V86 address |
142 | ; esi=handle |
142 | ; esi=handle |
143 | ; out: eax=linear address |
143 | ; out: eax=linear address |
144 | ; destroys: nothing |
144 | ; destroys: nothing |
145 | v86_get_lin_addr: |
145 | v86_get_lin_addr: |
146 | push ecx edx |
146 | push ecx edx |
147 | mov ecx, eax |
147 | mov ecx, eax |
148 | shr ecx, 12 |
148 | shr ecx, 12 |
149 | mov edx, [page_tabs+ecx*4] |
149 | mov edx, [page_tabs+ecx*4] |
150 | and eax, 0xFFF |
150 | and eax, 0xFFF |
151 | and edx, 0xFFFFF000 |
151 | and edx, 0xFFFFF000 |
152 | or eax, edx |
152 | or eax, edx |
153 | pop edx ecx |
153 | pop edx ecx |
154 | ret |
154 | ret |
155 | 155 | ||
156 | ;not used |
156 | ;not used |
157 | ; Sets linear address for V86-page |
157 | ; Sets linear address for V86-page |
158 | ; in: eax=linear address (must be page-aligned) |
158 | ; in: eax=linear address (must be page-aligned) |
159 | ; ecx=V86 page (NOT address!) |
159 | ; ecx=V86 page (NOT address!) |
160 | ; esi=handle |
160 | ; esi=handle |
161 | ; out: nothing |
161 | ; out: nothing |
162 | ; destroys: nothing |
162 | ; destroys: nothing |
163 | ;v86_set_page: |
163 | ;v86_set_page: |
164 | ; push eax ebx |
164 | ; push eax ebx |
165 | ; mov ebx, [esi+V86_machine.pagedir] |
165 | ; mov ebx, [esi+V86_machine.pagedir] |
166 | ; mov [ebx+ecx*4+0x1800], eax |
166 | ; mov [ebx+ecx*4+0x1800], eax |
167 | ; call get_pg_addr |
167 | ; call get_pg_addr |
168 | ; or al, 111b |
168 | ; or al, 111b |
169 | ; mov [ebx+ecx*4+0x1000], eax |
169 | ; mov [ebx+ecx*4+0x1000], eax |
170 | ; pop ebx eax |
170 | ; pop ebx eax |
171 | ; ret |
171 | ; ret |
172 | 172 | ||
173 | ; Allocate memory in V86 machine |
173 | ; Allocate memory in V86 machine |
174 | ; in: eax=size (in bytes) |
174 | ; in: eax=size (in bytes) |
175 | ; esi=handle |
175 | ; esi=handle |
176 | ; out: eax=V86 address, para-aligned (0x10 multiple) |
176 | ; out: eax=V86 address, para-aligned (0x10 multiple) |
177 | ; destroys: nothing |
177 | ; destroys: nothing |
178 | ; недописана!!! |
178 | ; недописана!!! |
179 | ;v86_alloc: |
179 | ;v86_alloc: |
180 | ; push ebx ecx edx edi |
180 | ; push ebx ecx edx edi |
181 | ; lea ebx, [esi+V86_machine.mutex] |
181 | ; lea ebx, [esi+V86_machine.mutex] |
182 | ; call wait_mutex |
182 | ; call wait_mutex |
183 | ; add eax, 0x1F |
183 | ; add eax, 0x1F |
184 | ; shr eax, 4 |
184 | ; shr eax, 4 |
185 | ; mov ebx, 0x1000 ; start with address 0x1000 (second page) |
185 | ; mov ebx, 0x1000 ; start with address 0x1000 (second page) |
186 | ; mov edi, [esi+V86_machine.tables] |
186 | ; mov edi, [esi+V86_machine.tables] |
187 | ;.l: |
187 | ;.l: |
188 | ; mov ecx, ebx |
188 | ; mov ecx, ebx |
189 | ; shr ecx, 12 |
189 | ; shr ecx, 12 |
190 | ; mov edx, [edi+0x1000+ecx*4] ; get linear address |
190 | ; mov edx, [edi+0x1000+ecx*4] ; get linear address |
191 | ; test edx, edx ; page allocated? |
191 | ; test edx, edx ; page allocated? |
192 | ; jz .unalloc |
192 | ; jz .unalloc |
193 | ; mov ecx, ebx |
193 | ; mov ecx, ebx |
194 | ; and ecx, 0xFFF |
194 | ; and ecx, 0xFFF |
195 | ; add edx, ecx |
195 | ; add edx, ecx |
196 | ; cmp dword [edx], 0 ; free block? |
196 | ; cmp dword [edx], 0 ; free block? |
197 | ; jnz .n |
197 | ; jnz .n |
198 | ; cmp dword [edx+4], |
198 | ; cmp dword [edx+4], |
199 | ; and [esi+V86_machine.mutex], 0 |
199 | ; and [esi+V86_machine.mutex], 0 |
200 | ; pop edi edx ecx ebx |
200 | ; pop edi edx ecx ebx |
201 | ; ret |
201 | ; ret |
202 | 202 | ||
203 | uglobal |
203 | uglobal |
204 | sys_v86_machine dd ? |
204 | sys_v86_machine dd ? |
205 | endg |
205 | endg |
206 | 206 | ||
207 | ; Called from kernel.asm at first stages of loading |
207 | ; Called from kernel.asm at first stages of loading |
208 | ; Initialize system V86 machine (used to simulate BIOS int 13h) |
208 | ; Initialize system V86 machine (used to simulate BIOS int 13h) |
209 | init_sys_v86: |
209 | init_sys_v86: |
210 | call v86_create |
210 | call v86_create |
211 | mov [sys_v86_machine], eax |
211 | mov [sys_v86_machine], eax |
212 | test eax, eax |
212 | test eax, eax |
213 | jz .ret |
213 | jz .ret |
214 | mov esi, eax |
214 | mov esi, eax |
215 | if ~DEBUG_SHOW_IO |
215 | if ~DEBUG_SHOW_IO |
216 | ; allow access to all ports |
216 | ; allow access to all ports |
217 | mov ecx, [esi+V86_machine.iopm] |
217 | mov ecx, [esi+V86_machine.iopm] |
218 | xor eax, eax |
218 | xor eax, eax |
219 | mov edi, ecx |
219 | mov edi, ecx |
220 | mov ecx, 10000h/8/4 |
220 | mov ecx, 10000h/8/4 |
221 | rep stosd |
221 | rep stosd |
222 | end if |
222 | end if |
223 | .ret: |
223 | .ret: |
224 | ret |
224 | ret |
225 | 225 | ||
226 | struct v86_regs |
226 | struct v86_regs |
227 | ; don't change the order, it is important |
227 | ; don't change the order, it is important |
228 | edi dd ? |
228 | edi dd ? |
229 | esi dd ? |
229 | esi dd ? |
230 | ebp dd ? |
230 | ebp dd ? |
231 | dd ? ; ignored |
231 | dd ? ; ignored |
232 | ebx dd ? |
232 | ebx dd ? |
233 | edx dd ? |
233 | edx dd ? |
234 | ecx dd ? |
234 | ecx dd ? |
235 | eax dd ? |
235 | eax dd ? |
236 | eip dd ? |
236 | eip dd ? |
237 | cs dd ? |
237 | cs dd ? |
238 | eflags dd ? ; VM flag must be set! |
238 | eflags dd ? ; VM flag must be set! |
239 | esp dd ? |
239 | esp dd ? |
240 | ss dd ? |
240 | ss dd ? |
241 | es dd ? |
241 | es dd ? |
242 | ds dd ? |
242 | ds dd ? |
243 | fs dd ? |
243 | fs dd ? |
244 | gs dd ? |
244 | gs dd ? |
245 | ends |
245 | ends |
246 | 246 | ||
247 | ; Run V86 machine |
247 | ; Run V86 machine |
248 | ; in: ebx -> registers for V86 (two structures: in and out) |
248 | ; in: ebx -> registers for V86 (two structures: in and out) |
249 | ; esi = handle |
249 | ; esi = handle |
250 | ; ecx = expected end address (CS:IP) |
250 | ; ecx = expected end address (CS:IP) |
251 | ; edx = IRQ to hook or -1 if not required |
251 | ; edx = IRQ to hook or -1 if not required |
252 | ; out: structure pointed to by ebx is filled with new values |
252 | ; out: structure pointed to by ebx is filled with new values |
253 | ; eax = 1 - exception has occured, cl contains code |
253 | ; eax = 1 - exception has occured, cl contains code |
254 | ; eax = 2 - access to disabled i/o port, ecx contains port address |
254 | ; eax = 2 - access to disabled i/o port, ecx contains port address |
255 | ; eax = 3 - IRQ is already hooked by another VM |
255 | ; eax = 3 - IRQ is already hooked by another VM |
256 | ; destroys: nothing |
256 | ; destroys: nothing |
257 | v86_start: |
257 | v86_start: |
258 | 258 | ||
259 | pushad |
259 | pushad |
260 | 260 | ||
261 | cli |
261 | cli |
262 | 262 | ||
263 | mov ecx, [current_slot] |
263 | mov ecx, [current_slot] |
264 | 264 | ||
265 | push dword [ecx+APPDATA.io_map] |
265 | push dword [ecx+APPDATA.io_map] |
266 | push dword [ecx+APPDATA.io_map+4] |
266 | push dword [ecx+APPDATA.io_map+4] |
267 | push [ecx+APPDATA.process] |
267 | push [ecx+APPDATA.process] |
268 | push [ecx+APPDATA.saved_esp0] |
268 | push [ecx+APPDATA.saved_esp0] |
269 | mov [ecx+APPDATA.saved_esp0], esp |
269 | mov [ecx+APPDATA.saved_esp0], esp |
270 | mov [tss._esp0], esp |
270 | mov [tss._esp0], esp |
271 | 271 | ||
272 | mov eax, [esi+V86_machine.iopm] |
272 | mov eax, [esi+V86_machine.iopm] |
273 | call get_pg_addr |
273 | call get_pg_addr |
274 | inc eax |
274 | inc eax |
275 | mov dword [ecx+APPDATA.io_map], eax |
275 | mov dword [ecx+APPDATA.io_map], eax |
276 | mov dword [page_tabs + (tss._io_map_0 shr 10)], eax |
276 | mov dword [page_tabs + (tss._io_map_0 shr 10)], eax |
277 | 277 | ||
278 | mov eax, [esi+V86_machine.iopm] |
278 | mov eax, [esi+V86_machine.iopm] |
279 | add eax, 0x1000 |
279 | add eax, 0x1000 |
280 | call get_pg_addr |
280 | call get_pg_addr |
281 | inc eax |
281 | inc eax |
282 | mov dword [ecx+APPDATA.io_map+4], eax |
282 | mov dword [ecx+APPDATA.io_map+4], eax |
283 | mov dword [page_tabs + (tss._io_map_1 shr 10)], eax |
283 | mov dword [page_tabs + (tss._io_map_1 shr 10)], eax |
284 | 284 | ||
285 | mov eax, [esi+V86_machine.process] |
285 | mov eax, [esi+V86_machine.process] |
286 | mov [ecx+APPDATA.process], eax |
286 | mov [ecx+APPDATA.process], eax |
287 | mov [current_process], eax |
287 | mov [current_process], eax |
288 | mov eax, [eax+PROC.pdt_0_phys] |
288 | mov eax, [eax+PROC.pdt_0_phys] |
289 | mov cr3, eax |
289 | mov cr3, eax |
290 | 290 | ||
291 | ; We do not enable interrupts, because V86 IRQ redirector assumes that |
291 | ; We do not enable interrupts, because V86 IRQ redirector assumes that |
292 | ; machine is running |
292 | ; machine is running |
293 | ; They will be enabled by IRET. |
293 | ; They will be enabled by IRET. |
294 | ; sti |
294 | ; sti |
295 | 295 | ||
296 | mov eax, esi |
296 | mov eax, esi |
297 | sub esp, sizeof.v86_regs |
297 | sub esp, sizeof.v86_regs |
298 | mov esi, ebx |
298 | mov esi, ebx |
299 | mov edi, esp |
299 | mov edi, esp |
300 | mov ecx, sizeof.v86_regs/4 |
300 | mov ecx, sizeof.v86_regs/4 |
301 | rep movsd |
301 | rep movsd |
302 | 302 | ||
303 | cmp edx, -1 |
303 | cmp edx, -1 |
304 | jz .noirqhook |
304 | jz .noirqhook |
305 | uglobal |
305 | uglobal |
306 | v86_irqhooks rd IRQ_RESERVED * 2 |
306 | v86_irqhooks rd IRQ_RESERVED * 2 |
307 | endg |
307 | endg |
308 | cmp [v86_irqhooks+edx*8], 0 |
308 | cmp [v86_irqhooks+edx*8], 0 |
309 | jz @f |
309 | jz @f |
310 | cmp [v86_irqhooks+edx*8], eax |
310 | cmp [v86_irqhooks+edx*8], eax |
311 | jz @f |
311 | jz @f |
312 | mov esi, v86_irqerr |
312 | mov esi, v86_irqerr |
313 | call sys_msg_board_str |
313 | call sys_msg_board_str |
314 | inc [v86_irqhooks+edx*8+4] |
314 | inc [v86_irqhooks+edx*8+4] |
315 | mov eax, 3 |
315 | mov eax, 3 |
316 | jmp v86_exc_c.exit |
316 | jmp v86_exc_c.exit |
317 | @@: |
317 | @@: |
318 | mov [v86_irqhooks+edx*8], eax |
318 | mov [v86_irqhooks+edx*8], eax |
319 | inc [v86_irqhooks+edx*8+4] |
319 | inc [v86_irqhooks+edx*8+4] |
320 | .noirqhook: |
320 | .noirqhook: |
321 | 321 | ||
322 | popad |
322 | popad |
323 | iretd |
323 | iretd |
324 | 324 | ||
325 | ; It is only possible to leave virtual-8086 mode by faulting to |
325 | ; It is only possible to leave virtual-8086 mode by faulting to |
326 | ; a protected-mode interrupt handler (typically the general-protection |
326 | ; a protected-mode interrupt handler (typically the general-protection |
327 | ; exception handler, which in turn calls the virtual 8086-mode monitor). |
327 | ; exception handler, which in turn calls the virtual 8086-mode monitor). |
328 | 328 | ||
329 | iglobal |
329 | iglobal |
330 | v86_exc_str1 db 'V86 : unexpected exception ',0 |
330 | v86_exc_str1 db 'V86 : unexpected exception ',0 |
331 | v86_exc_str2 db ' at ',0 |
331 | v86_exc_str2 db ' at ',0 |
332 | v86_exc_str3 db ':',0 |
332 | v86_exc_str3 db ':',0 |
333 | v86_exc_str4 db 13,10,'V86 : faulted code:',0 |
333 | v86_exc_str4 db 13,10,'V86 : faulted code:',0 |
334 | v86_exc_str5 db ' (unavailable)',0 |
334 | v86_exc_str5 db ' (unavailable)',0 |
335 | v86_newline db 13,10,0 |
335 | v86_newline db 13,10,0 |
336 | v86_io_str1 db 'V86 : access to disabled i/o port ',0 |
336 | v86_io_str1 db 'V86 : access to disabled i/o port ',0 |
337 | v86_io_byte db ' (byte)',13,10,0 |
337 | v86_io_byte db ' (byte)',13,10,0 |
338 | v86_io_word db ' (word)',13,10,0 |
338 | v86_io_word db ' (word)',13,10,0 |
339 | v86_io_dword db ' (dword)',13,10,0 |
339 | v86_io_dword db ' (dword)',13,10,0 |
340 | v86_irqerr db 'V86 : IRQ already hooked',13,10,0 |
340 | v86_irqerr db 'V86 : IRQ already hooked',13,10,0 |
341 | endg |
341 | endg |
342 | 342 | ||
343 | v86_exc_c: |
343 | v86_exc_c: |
344 | ; Did we all that we have wanted to do? |
344 | ; Did we all that we have wanted to do? |
345 | cmp bl, 1 |
345 | cmp bl, 1 |
346 | jne @f |
346 | jne @f |
347 | xor eax, eax |
347 | xor eax, eax |
348 | mov dr6, eax |
348 | mov dr6, eax |
349 | @@: |
349 | @@: |
350 | mov eax, [esp+sizeof.v86_regs+10h+18h] |
350 | mov eax, [esp+sizeof.v86_regs+10h+18h] |
351 | cmp word [esp+v86_regs.eip], ax |
351 | cmp word [esp+v86_regs.eip], ax |
352 | jnz @f |
352 | jnz @f |
353 | shr eax, 16 |
353 | shr eax, 16 |
354 | cmp word [esp+v86_regs.cs], ax |
354 | cmp word [esp+v86_regs.cs], ax |
355 | jz .done |
355 | jz .done |
356 | @@: |
356 | @@: |
357 | ; Various system events, which must be handled, result in #GP |
357 | ; Various system events, which must be handled, result in #GP |
358 | cmp bl, 13 |
358 | cmp bl, 13 |
359 | jnz .nogp |
359 | jnz .nogp |
360 | ; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
360 | ; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
361 | cmp word [esp+v86_regs.eip+2], 0 |
361 | cmp word [esp+v86_regs.eip+2], 0 |
362 | jnz .nogp |
362 | jnz .nogp |
363 | ; Otherwise we can safely access byte at CS:IP |
363 | ; Otherwise we can safely access byte at CS:IP |
364 | ; (because it is #GP, not #PF handler) |
364 | ; (because it is #GP, not #PF handler) |
365 | ; Если бы мы могли схлопотать исключение только из-за чтения байтов кода, |
365 | ; Если бы мы могли схлопотать исключение только из-за чтения байтов кода, |
366 | ; мы бы его уже схлопотали и это было бы не #GP |
366 | ; мы бы его уже схлопотали и это было бы не #GP |
367 | movzx esi, word [esp+v86_regs.cs] |
367 | movzx esi, word [esp+v86_regs.cs] |
368 | shl esi, 4 |
368 | shl esi, 4 |
369 | add esi, [esp+v86_regs.eip] |
369 | add esi, [esp+v86_regs.eip] |
370 | lodsb |
370 | lodsb |
371 | cmp al, 0xCD ; int xx command = CD xx |
371 | cmp al, 0xCD ; int xx command = CD xx |
372 | jz .handle_int |
372 | jz .handle_int |
373 | cmp al, 0xCF |
373 | cmp al, 0xCF |
374 | jz .handle_iret |
374 | jz .handle_iret |
375 | cmp al, 0xF3 |
375 | cmp al, 0xF3 |
376 | jz .handle_rep |
376 | jz .handle_rep |
377 | cmp al, 0xEC |
377 | cmp al, 0xEC |
378 | jz .handle_in |
378 | jz .handle_in |
379 | cmp al, 0xED |
379 | cmp al, 0xED |
380 | jz .handle_in_word |
380 | jz .handle_in_word |
381 | cmp al, 0xEE |
381 | cmp al, 0xEE |
382 | jz .handle_out |
382 | jz .handle_out |
383 | cmp al, 0xEF |
383 | cmp al, 0xEF |
384 | jz .handle_out_word |
384 | jz .handle_out_word |
385 | cmp al, 0xE4 |
385 | cmp al, 0xE4 |
386 | jz .handle_in_imm |
386 | jz .handle_in_imm |
387 | cmp al, 0xE6 |
387 | cmp al, 0xE6 |
388 | jz .handle_out_imm |
388 | jz .handle_out_imm |
389 | cmp al, 0x9C |
389 | cmp al, 0x9C |
390 | jz .handle_pushf |
390 | jz .handle_pushf |
391 | cmp al, 0x9D |
391 | cmp al, 0x9D |
392 | jz .handle_popf |
392 | jz .handle_popf |
393 | cmp al, 0xFA |
393 | cmp al, 0xFA |
394 | jz .handle_cli |
394 | jz .handle_cli |
395 | cmp al, 0xFB |
395 | cmp al, 0xFB |
396 | jz .handle_sti |
396 | jz .handle_sti |
397 | cmp al, 0x66 |
397 | cmp al, 0x66 |
398 | jz .handle_66 |
398 | jz .handle_66 |
399 | jmp .nogp |
399 | jmp .nogp |
400 | .handle_int: |
400 | .handle_int: |
401 | cmp word [esp+v86_regs.eip], 0xFFFF |
401 | cmp word [esp+v86_regs.eip], 0xFFFF |
402 | jae .nogp |
402 | jae .nogp |
403 | xor eax, eax |
403 | xor eax, eax |
404 | lodsb |
404 | lodsb |
405 | ; call sys_msg_board_byte |
405 | ; call sys_msg_board_byte |
406 | ; simulate INT command |
406 | ; simulate INT command |
407 | ; N.B. It is possible that some checks need to be corrected, |
407 | ; N.B. It is possible that some checks need to be corrected, |
408 | ; but at least in case of normal execution the code works. |
408 | ; but at least in case of normal execution the code works. |
409 | .simulate_int: |
409 | .simulate_int: |
410 | cmp word [esp+v86_regs.esp], 6 |
410 | cmp word [esp+v86_regs.esp], 6 |
411 | jae @f |
411 | jae @f |
412 | mov bl, 12 ; #SS exception |
412 | mov bl, 12 ; #SS exception |
413 | jmp .nogp |
413 | jmp .nogp |
414 | @@: |
414 | @@: |
415 | movzx edx, word [esp+v86_regs.ss] |
415 | movzx edx, word [esp+v86_regs.ss] |
416 | shl edx, 4 |
416 | shl edx, 4 |
417 | push eax |
417 | push eax |
418 | movzx eax, word [esp+4+v86_regs.esp] |
418 | movzx eax, word [esp+4+v86_regs.esp] |
419 | sub eax, 6 |
419 | sub eax, 6 |
420 | add edx, eax |
420 | add edx, eax |
421 | mov eax, edx |
421 | mov eax, edx |
422 | mov esi, [esp+4+sizeof.v86_regs+10h+4] |
422 | mov esi, [esp+4+sizeof.v86_regs+10h+4] |
423 | call v86_get_lin_addr |
423 | call v86_get_lin_addr |
424 | cmp eax, 0x1000 |
424 | cmp eax, 0x1000 |
425 | jae @f |
425 | jae @f |
426 | mov bl, 14 ; #PF exception |
426 | mov bl, 14 ; #PF exception |
427 | jmp .nogp |
427 | jmp .nogp |
428 | @@: |
428 | @@: |
429 | lea eax, [edx+5] |
429 | lea eax, [edx+5] |
430 | call v86_get_lin_addr |
430 | call v86_get_lin_addr |
431 | cmp eax, 0x1000 |
431 | cmp eax, 0x1000 |
432 | jae @f |
432 | jae @f |
433 | mov bl, 14 ; #PF exception |
433 | mov bl, 14 ; #PF exception |
434 | jmp .nogp |
434 | jmp .nogp |
435 | @@: |
435 | @@: |
436 | sub word [esp+4+v86_regs.esp], 6 |
436 | sub word [esp+4+v86_regs.esp], 6 |
437 | mov eax, [esp+4+v86_regs.eip] |
437 | mov eax, [esp+4+v86_regs.eip] |
438 | cmp byte [esp+1], 0 |
438 | cmp byte [esp+1], 0 |
439 | jnz @f |
439 | jnz @f |
440 | inc eax |
440 | inc eax |
441 | inc eax |
441 | inc eax |
442 | @@: |
442 | @@: |
443 | mov word [edx], ax |
443 | mov word [edx], ax |
444 | mov eax, [esp+4+v86_regs.cs] |
444 | mov eax, [esp+4+v86_regs.cs] |
445 | mov word [edx+2], ax |
445 | mov word [edx+2], ax |
446 | mov eax, [esp+4+v86_regs.eflags] |
446 | mov eax, [esp+4+v86_regs.eflags] |
447 | mov word [edx+4], ax |
447 | mov word [edx+4], ax |
448 | pop eax |
448 | pop eax |
449 | mov ah, 0 |
449 | mov ah, 0 |
450 | mov cx, [eax*4] |
450 | mov cx, [eax*4] |
451 | mov word [esp+v86_regs.eip], cx |
451 | mov word [esp+v86_regs.eip], cx |
452 | mov cx, [eax*4+2] |
452 | mov cx, [eax*4+2] |
453 | mov word [esp+v86_regs.cs], cx |
453 | mov word [esp+v86_regs.cs], cx |
454 | ; note that interrupts will be disabled globally at IRET |
454 | ; note that interrupts will be disabled globally at IRET |
455 | and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
455 | and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
456 | ; continue V86 execution |
456 | ; continue V86 execution |
457 | popad |
457 | popad |
458 | iretd |
458 | iretd |
459 | .handle_iret: |
459 | .handle_iret: |
460 | cmp word [esp+v86_regs.esp], 0x10000 - 6 |
460 | cmp word [esp+v86_regs.esp], 0x10000 - 6 |
461 | jbe @f |
461 | jbe @f |
462 | mov bl, 12 |
462 | mov bl, 12 |
463 | jmp .nogp |
463 | jmp .nogp |
464 | @@: |
464 | @@: |
465 | movzx edx, word [esp+v86_regs.ss] |
465 | movzx edx, word [esp+v86_regs.ss] |
466 | shl edx, 4 |
466 | shl edx, 4 |
467 | movzx eax, word [esp+v86_regs.esp] |
467 | movzx eax, word [esp+v86_regs.esp] |
468 | add edx, eax |
468 | add edx, eax |
469 | mov eax, edx |
469 | mov eax, edx |
470 | mov esi, [esp+sizeof.v86_regs+10h+4] |
470 | mov esi, [esp+sizeof.v86_regs+10h+4] |
471 | call v86_get_lin_addr |
471 | call v86_get_lin_addr |
472 | cmp eax, 0x1000 |
472 | cmp eax, 0x1000 |
473 | jae @f |
473 | jae @f |
474 | mov bl, 14 |
474 | mov bl, 14 |
475 | jmp .nogp |
475 | jmp .nogp |
476 | @@: |
476 | @@: |
477 | lea eax, [edx+5] |
477 | lea eax, [edx+5] |
478 | call v86_get_lin_addr |
478 | call v86_get_lin_addr |
479 | cmp eax, 0x1000 |
479 | cmp eax, 0x1000 |
480 | jae @f |
480 | jae @f |
481 | mov bl, 14 |
481 | mov bl, 14 |
482 | jmp .nogp |
482 | jmp .nogp |
483 | @@: |
483 | @@: |
484 | mov ax, [edx] |
484 | mov ax, [edx] |
485 | mov word [esp+v86_regs.eip], ax |
485 | mov word [esp+v86_regs.eip], ax |
486 | mov ax, [edx+2] |
486 | mov ax, [edx+2] |
487 | mov word [esp+v86_regs.cs], ax |
487 | mov word [esp+v86_regs.cs], ax |
488 | mov ax, [edx+4] |
488 | mov ax, [edx+4] |
489 | mov word [esp+v86_regs.eflags], ax |
489 | mov word [esp+v86_regs.eflags], ax |
490 | add word [esp+v86_regs.esp], 6 |
490 | add word [esp+v86_regs.esp], 6 |
491 | popad |
491 | popad |
492 | iretd |
492 | iretd |
493 | .handle_pushf: |
493 | .handle_pushf: |
494 | cmp word [esp+v86_regs.esp], 1 |
494 | cmp word [esp+v86_regs.esp], 1 |
495 | jnz @f |
495 | jnz @f |
496 | mov bl, 12 |
496 | mov bl, 12 |
497 | jmp .nogp |
497 | jmp .nogp |
498 | @@: |
498 | @@: |
499 | movzx edx, word [esp+v86_regs.ss] |
499 | movzx edx, word [esp+v86_regs.ss] |
500 | shl edx, 4 |
500 | shl edx, 4 |
501 | mov eax, [esp+v86_regs.esp] |
501 | mov eax, [esp+v86_regs.esp] |
502 | sub eax, 2 |
502 | sub eax, 2 |
503 | movzx eax, ax |
503 | movzx eax, ax |
504 | add edx, eax |
504 | add edx, eax |
505 | mov eax, edx |
505 | mov eax, edx |
506 | mov esi, [esp+sizeof.v86_regs+10h+4] |
506 | mov esi, [esp+sizeof.v86_regs+10h+4] |
507 | call v86_get_lin_addr |
507 | call v86_get_lin_addr |
508 | cmp eax, 0x1000 |
508 | cmp eax, 0x1000 |
509 | jae @f |
509 | jae @f |
510 | mov bl, 14 ; #PF exception |
510 | mov bl, 14 ; #PF exception |
511 | jmp .nogp |
511 | jmp .nogp |
512 | @@: |
512 | @@: |
513 | lea eax, [edx+1] |
513 | lea eax, [edx+1] |
514 | call v86_get_lin_addr |
514 | call v86_get_lin_addr |
515 | cmp eax, 0x1000 |
515 | cmp eax, 0x1000 |
516 | jae @f |
516 | jae @f |
517 | mov bl, 14 |
517 | mov bl, 14 |
518 | jmp .nogp |
518 | jmp .nogp |
519 | @@: |
519 | @@: |
520 | sub word [esp+v86_regs.esp], 2 |
520 | sub word [esp+v86_regs.esp], 2 |
521 | mov eax, [esp+v86_regs.eflags] |
521 | mov eax, [esp+v86_regs.eflags] |
522 | mov [edx], ax |
522 | mov [edx], ax |
523 | inc word [esp+v86_regs.eip] |
523 | inc word [esp+v86_regs.eip] |
524 | popad |
524 | popad |
525 | iretd |
525 | iretd |
526 | .handle_pushfd: |
526 | .handle_pushfd: |
527 | cmp word [esp+v86_regs.esp], 4 |
527 | cmp word [esp+v86_regs.esp], 4 |
528 | jae @f |
528 | jae @f |
529 | mov bl, 12 ; #SS exception |
529 | mov bl, 12 ; #SS exception |
530 | jmp .nogp |
530 | jmp .nogp |
531 | @@: |
531 | @@: |
532 | movzx edx, word [esp+v86_regs.ss] |
532 | movzx edx, word [esp+v86_regs.ss] |
533 | shl edx, 4 |
533 | shl edx, 4 |
534 | movzx eax, word [esp+v86_regs.esp] |
534 | movzx eax, word [esp+v86_regs.esp] |
535 | sub eax, 4 |
535 | sub eax, 4 |
536 | add edx, eax |
536 | add edx, eax |
537 | mov eax, edx |
537 | mov eax, edx |
538 | mov esi, [esp+sizeof.v86_regs+10h+4] |
538 | mov esi, [esp+sizeof.v86_regs+10h+4] |
539 | call v86_get_lin_addr |
539 | call v86_get_lin_addr |
540 | cmp eax, 0x1000 |
540 | cmp eax, 0x1000 |
541 | jae @f |
541 | jae @f |
542 | mov bl, 14 ; #PF exception |
542 | mov bl, 14 ; #PF exception |
543 | jmp .nogp |
543 | jmp .nogp |
544 | @@: |
544 | @@: |
545 | lea eax, [edx+3] |
545 | lea eax, [edx+3] |
546 | call v86_get_lin_addr |
546 | call v86_get_lin_addr |
547 | cmp eax, 0x1000 |
547 | cmp eax, 0x1000 |
548 | jae @f |
548 | jae @f |
549 | mov bl, 14 ; #PF exception |
549 | mov bl, 14 ; #PF exception |
550 | jmp .nogp |
550 | jmp .nogp |
551 | @@: |
551 | @@: |
552 | sub word [esp+v86_regs.esp], 4 |
552 | sub word [esp+v86_regs.esp], 4 |
553 | movzx eax, word [esp+v86_regs.eflags] |
553 | movzx eax, word [esp+v86_regs.eflags] |
554 | mov [edx], eax |
554 | mov [edx], eax |
555 | add word [esp+v86_regs.eip], 2 |
555 | add word [esp+v86_regs.eip], 2 |
556 | popad |
556 | popad |
557 | iretd |
557 | iretd |
558 | .handle_popf: |
558 | .handle_popf: |
559 | cmp word [esp+v86_regs.esp], 0xFFFF |
559 | cmp word [esp+v86_regs.esp], 0xFFFF |
560 | jnz @f |
560 | jnz @f |
561 | mov bl, 12 |
561 | mov bl, 12 |
562 | jmp .nogp |
562 | jmp .nogp |
563 | @@: |
563 | @@: |
564 | movzx edx, word [esp+v86_regs.ss] |
564 | movzx edx, word [esp+v86_regs.ss] |
565 | shl edx, 4 |
565 | shl edx, 4 |
566 | movzx eax, word [esp+v86_regs.esp] |
566 | movzx eax, word [esp+v86_regs.esp] |
567 | add edx, eax |
567 | add edx, eax |
568 | mov eax, edx |
568 | mov eax, edx |
569 | mov esi, [esp+sizeof.v86_regs+10h+4] |
569 | mov esi, [esp+sizeof.v86_regs+10h+4] |
570 | call v86_get_lin_addr |
570 | call v86_get_lin_addr |
571 | cmp eax, 0x1000 |
571 | cmp eax, 0x1000 |
572 | jae @f |
572 | jae @f |
573 | mov bl, 14 ; #PF exception |
573 | mov bl, 14 ; #PF exception |
574 | jmp .nogp |
574 | jmp .nogp |
575 | @@: |
575 | @@: |
576 | lea eax, [edx+1] |
576 | lea eax, [edx+1] |
577 | call v86_get_lin_addr |
577 | call v86_get_lin_addr |
578 | cmp eax, 0x1000 |
578 | cmp eax, 0x1000 |
579 | jae @f |
579 | jae @f |
580 | mov bl, 14 |
580 | mov bl, 14 |
581 | jmp .nogp |
581 | jmp .nogp |
582 | @@: |
582 | @@: |
583 | mov ax, [edx] |
583 | mov ax, [edx] |
584 | mov word [esp+v86_regs.eflags], ax |
584 | mov word [esp+v86_regs.eflags], ax |
585 | add word [esp+v86_regs.esp], 2 |
585 | add word [esp+v86_regs.esp], 2 |
586 | inc word [esp+v86_regs.eip] |
586 | inc word [esp+v86_regs.eip] |
587 | popad |
587 | popad |
588 | iretd |
588 | iretd |
589 | .handle_popfd: |
589 | .handle_popfd: |
590 | cmp word [esp+v86_regs.esp], 0x10000 - 4 |
590 | cmp word [esp+v86_regs.esp], 0x10000 - 4 |
591 | jbe @f |
591 | jbe @f |
592 | mov bl, 12 |
592 | mov bl, 12 |
593 | jmp .nogp |
593 | jmp .nogp |
594 | @@: |
594 | @@: |
595 | movzx edx, word [esp+v86_regs.ss] |
595 | movzx edx, word [esp+v86_regs.ss] |
596 | shl edx, 4 |
596 | shl edx, 4 |
597 | movzx eax, word [esp+v86_regs.esp] |
597 | movzx eax, word [esp+v86_regs.esp] |
598 | add edx, eax |
598 | add edx, eax |
599 | mov eax, edx |
599 | mov eax, edx |
600 | mov esi, [esp+sizeof.v86_regs+10h+4] |
600 | mov esi, [esp+sizeof.v86_regs+10h+4] |
601 | call v86_get_lin_addr |
601 | call v86_get_lin_addr |
602 | cmp eax, 0x1000 |
602 | cmp eax, 0x1000 |
603 | jae @f |
603 | jae @f |
604 | mov bl, 14 |
604 | mov bl, 14 |
605 | jmp .nogp |
605 | jmp .nogp |
606 | @@: |
606 | @@: |
607 | lea eax, [edx+3] |
607 | lea eax, [edx+3] |
608 | call v86_get_lin_addr |
608 | call v86_get_lin_addr |
609 | cmp eax, 0x1000 |
609 | cmp eax, 0x1000 |
610 | jae @f |
610 | jae @f |
611 | mov bl, 14 |
611 | mov bl, 14 |
612 | jmp .nogp |
612 | jmp .nogp |
613 | @@: |
613 | @@: |
614 | mov eax, [edx] |
614 | mov eax, [edx] |
615 | mov word [esp+v86_regs.eflags], ax |
615 | mov word [esp+v86_regs.eflags], ax |
616 | add word [esp+v86_regs.esp], 4 |
616 | add word [esp+v86_regs.esp], 4 |
617 | add word [esp+v86_regs.eip], 2 |
617 | add word [esp+v86_regs.eip], 2 |
618 | popad |
618 | popad |
619 | iretd |
619 | iretd |
620 | .handle_cli: |
620 | .handle_cli: |
621 | and byte [esp+v86_regs.eflags+1], not 2 |
621 | and byte [esp+v86_regs.eflags+1], not 2 |
622 | inc word [esp+v86_regs.eip] |
622 | inc word [esp+v86_regs.eip] |
623 | popad |
623 | popad |
624 | iretd |
624 | iretd |
625 | .handle_sti: |
625 | .handle_sti: |
626 | or byte [esp+v86_regs.eflags+1], 2 |
626 | or byte [esp+v86_regs.eflags+1], 2 |
627 | inc word [esp+v86_regs.eip] |
627 | inc word [esp+v86_regs.eip] |
628 | popad |
628 | popad |
629 | iretd |
629 | iretd |
630 | .handle_rep: |
630 | .handle_rep: |
631 | cmp word [esp+v86_regs.eip], 0xFFFF |
631 | cmp word [esp+v86_regs.eip], 0xFFFF |
632 | jae .nogp |
632 | jae .nogp |
633 | lodsb |
633 | lodsb |
634 | cmp al, 6Eh |
634 | cmp al, 6Eh |
635 | jz .handle_rep_outsb |
635 | jz .handle_rep_outsb |
636 | jmp .nogp |
636 | jmp .nogp |
637 | .handle_rep_outsb: |
637 | .handle_rep_outsb: |
638 | .handle_in: |
638 | .handle_in: |
639 | .handle_out: |
639 | .handle_out: |
640 | .invalid_io_byte: |
640 | .invalid_io_byte: |
641 | movzx ebx, word [esp+v86_regs.edx] |
641 | movzx ebx, word [esp+v86_regs.edx] |
642 | mov ecx, 1 |
642 | mov ecx, 1 |
643 | jmp .invalid_io |
643 | jmp .invalid_io |
644 | .handle_in_imm: |
644 | .handle_in_imm: |
645 | .handle_out_imm: |
645 | .handle_out_imm: |
646 | cmp word [esp+v86_regs.eip], 0xFFFF |
646 | cmp word [esp+v86_regs.eip], 0xFFFF |
647 | jae .nogp |
647 | jae .nogp |
648 | lodsb |
648 | lodsb |
649 | movzx ebx, al |
649 | movzx ebx, al |
650 | mov ecx, 1 |
650 | mov ecx, 1 |
651 | jmp .invalid_io |
651 | jmp .invalid_io |
652 | .handle_66: |
652 | .handle_66: |
653 | cmp word [esp+v86_regs.eip], 0xFFFF |
653 | cmp word [esp+v86_regs.eip], 0xFFFF |
654 | jae .nogp |
654 | jae .nogp |
655 | lodsb |
655 | lodsb |
656 | cmp al, 0x9C |
656 | cmp al, 0x9C |
657 | jz .handle_pushfd |
657 | jz .handle_pushfd |
658 | cmp al, 0x9D |
658 | cmp al, 0x9D |
659 | jz .handle_popfd |
659 | jz .handle_popfd |
660 | cmp al, 0xEF |
660 | cmp al, 0xEF |
661 | jz .handle_out_dword |
661 | jz .handle_out_dword |
662 | cmp al, 0xED |
662 | cmp al, 0xED |
663 | jz .handle_in_dword |
663 | jz .handle_in_dword |
664 | jmp .nogp |
664 | jmp .nogp |
665 | .handle_in_word: |
665 | .handle_in_word: |
666 | .handle_out_word: |
666 | .handle_out_word: |
667 | movzx ebx, word [esp+v86_regs.edx] |
667 | movzx ebx, word [esp+v86_regs.edx] |
668 | mov ecx, 2 |
668 | mov ecx, 2 |
669 | jmp .invalid_io |
669 | jmp .invalid_io |
670 | .handle_in_dword: |
670 | .handle_in_dword: |
671 | .handle_out_dword: |
671 | .handle_out_dword: |
672 | .invalid_io_dword: |
672 | .invalid_io_dword: |
673 | movzx ebx, word [esp+v86_regs.edx] |
673 | movzx ebx, word [esp+v86_regs.edx] |
674 | mov ecx, 4 |
674 | mov ecx, 4 |
675 | .invalid_io: |
675 | .invalid_io: |
676 | mov esi, v86_io_str1 |
676 | mov esi, v86_io_str1 |
677 | call sys_msg_board_str |
677 | call sys_msg_board_str |
678 | mov eax, ebx |
678 | mov eax, ebx |
679 | call sys_msg_board_dword |
679 | call sys_msg_board_dword |
680 | mov esi, v86_io_byte |
680 | mov esi, v86_io_byte |
681 | cmp ecx, 1 |
681 | cmp ecx, 1 |
682 | jz @f |
682 | jz @f |
683 | mov esi, v86_io_word |
683 | mov esi, v86_io_word |
684 | cmp ecx, 2 |
684 | cmp ecx, 2 |
685 | jz @f |
685 | jz @f |
686 | mov esi, v86_io_dword |
686 | mov esi, v86_io_dword |
687 | @@: |
687 | @@: |
688 | call sys_msg_board_str |
688 | call sys_msg_board_str |
689 | if DEBUG_SHOW_IO |
689 | if DEBUG_SHOW_IO |
690 | mov edx, ebx |
690 | mov edx, ebx |
691 | mov ebx, 200 |
691 | mov ebx, 200 |
692 | call delay_hs |
692 | call delay_hs |
693 | mov esi, [esp+v86_regs.size+10h+4] |
693 | mov esi, [esp+v86_regs.size+10h+4] |
694 | mov eax, [esi+V86_machine.iopm] |
694 | mov eax, [esi+V86_machine.iopm] |
695 | @@: |
695 | @@: |
696 | btr [eax], edx |
696 | btr [eax], edx |
697 | inc edx |
697 | inc edx |
698 | loop @b |
698 | loop @b |
699 | popad |
699 | popad |
700 | iretd |
700 | iretd |
701 | else |
701 | else |
702 | mov eax, 2 |
702 | mov eax, 2 |
703 | jmp .exit |
703 | jmp .exit |
704 | end if |
704 | end if |
705 | .nogp: |
705 | .nogp: |
706 | 706 | ||
707 | mov esi, v86_exc_str1 |
707 | mov esi, v86_exc_str1 |
708 | call sys_msg_board_str |
708 | call sys_msg_board_str |
709 | mov al, bl |
709 | mov al, bl |
710 | call sys_msg_board_byte |
710 | call sys_msg_board_byte |
711 | mov esi, v86_exc_str2 |
711 | mov esi, v86_exc_str2 |
712 | call sys_msg_board_str |
712 | call sys_msg_board_str |
713 | mov ax, [esp+32+4] |
713 | mov ax, [esp+32+4] |
714 | call sys_msg_board_word |
714 | call sys_msg_board_word |
715 | mov esi, v86_exc_str3 |
715 | mov esi, v86_exc_str3 |
716 | call sys_msg_board_str |
716 | call sys_msg_board_str |
717 | mov ax, [esp+32] |
717 | mov ax, [esp+32] |
718 | call sys_msg_board_word |
718 | call sys_msg_board_word |
719 | mov esi, v86_exc_str4 |
719 | mov esi, v86_exc_str4 |
720 | call sys_msg_board_str |
720 | call sys_msg_board_str |
721 | mov ecx, 8 |
721 | mov ecx, 8 |
722 | movzx edx, word [esp+32+4] |
722 | movzx edx, word [esp+32+4] |
723 | shl edx, 4 |
723 | shl edx, 4 |
724 | add edx, [esp+32] |
724 | add edx, [esp+32] |
725 | @@: |
725 | @@: |
726 | mov esi, [esp+sizeof.v86_regs+10h+4] |
726 | mov esi, [esp+sizeof.v86_regs+10h+4] |
727 | mov eax, edx |
727 | mov eax, edx |
728 | call v86_get_lin_addr |
728 | call v86_get_lin_addr |
729 | cmp eax, 0x1000 |
729 | cmp eax, 0x1000 |
730 | jb .nopage |
730 | jb .nopage |
731 | mov esi, v86_exc_str3-2 |
731 | mov esi, v86_exc_str3-2 |
732 | call sys_msg_board_str |
732 | call sys_msg_board_str |
733 | mov al, [edx] |
733 | mov al, [edx] |
734 | call sys_msg_board_byte |
734 | call sys_msg_board_byte |
735 | inc edx |
735 | inc edx |
736 | loop @b |
736 | loop @b |
737 | jmp @f |
737 | jmp @f |
738 | .nopage: |
738 | .nopage: |
739 | mov esi, v86_exc_str5 |
739 | mov esi, v86_exc_str5 |
740 | call sys_msg_board_str |
740 | call sys_msg_board_str |
741 | @@: |
741 | @@: |
742 | mov esi, v86_newline |
742 | mov esi, v86_newline |
743 | call sys_msg_board_str |
743 | call sys_msg_board_str |
744 | mov eax, 1 |
744 | mov eax, 1 |
745 | jmp .exit |
745 | jmp .exit |
746 | 746 | ||
747 | .done: |
747 | .done: |
748 | xor eax, eax |
748 | xor eax, eax |
749 | 749 | ||
750 | .exit: |
750 | .exit: |
751 | mov [esp+sizeof.v86_regs+10h+1Ch], eax |
751 | mov [esp+sizeof.v86_regs+10h+1Ch], eax |
752 | mov [esp+sizeof.v86_regs+10h+18h], ebx |
752 | mov [esp+sizeof.v86_regs+10h+18h], ebx |
753 | 753 | ||
754 | mov edx, [esp+sizeof.v86_regs+10h+14h] |
754 | mov edx, [esp+sizeof.v86_regs+10h+14h] |
755 | cmp edx, -1 |
755 | cmp edx, -1 |
756 | jz @f |
756 | jz @f |
757 | dec [v86_irqhooks+edx*8+4] |
757 | dec [v86_irqhooks+edx*8+4] |
758 | jnz @f |
758 | jnz @f |
759 | and [v86_irqhooks+edx*8], 0 |
759 | and [v86_irqhooks+edx*8], 0 |
760 | @@: |
760 | @@: |
761 | 761 | ||
762 | mov esi, esp |
762 | mov esi, esp |
763 | mov edi, [esi+sizeof.v86_regs+10h+10h] |
763 | mov edi, [esi+sizeof.v86_regs+10h+10h] |
764 | add edi, sizeof.v86_regs |
764 | add edi, sizeof.v86_regs |
765 | mov ecx, sizeof.v86_regs/4 |
765 | mov ecx, sizeof.v86_regs/4 |
766 | rep movsd |
766 | rep movsd |
767 | mov esp, esi |
767 | mov esp, esi |
768 | 768 | ||
769 | cli |
769 | cli |
770 | mov ecx, [current_slot] |
770 | mov ecx, [current_slot] |
771 | pop eax |
771 | pop eax |
772 | 772 | ||
773 | mov [ecx+APPDATA.saved_esp0], eax |
773 | mov [ecx+APPDATA.saved_esp0], eax |
774 | mov [tss._esp0], eax |
774 | mov [tss._esp0], eax |
775 | pop eax |
775 | pop eax |
776 | mov [ecx+APPDATA.process], eax |
776 | mov [ecx+APPDATA.process], eax |
777 | mov [current_process], eax |
777 | mov [current_process], eax |
778 | pop ebx |
778 | pop ebx |
779 | mov dword [ecx+APPDATA.io_map+4], ebx |
779 | mov dword [ecx+APPDATA.io_map+4], ebx |
780 | mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx |
780 | mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx |
781 | pop ebx |
781 | pop ebx |
782 | mov dword [ecx+APPDATA.io_map], ebx |
782 | mov dword [ecx+APPDATA.io_map], ebx |
783 | mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx |
783 | mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx |
784 | mov eax, [eax+PROC.pdt_0_phys] |
784 | mov eax, [eax+PROC.pdt_0_phys] |
785 | mov cr3, eax |
785 | mov cr3, eax |
786 | sti |
786 | sti |
787 | 787 | ||
788 | popad |
788 | popad |
789 | ret |
789 | ret |
790 | 790 | ||
791 | ;my05: |
791 | ;my05: |
792 | ; mov dx, 30C2h |
792 | ; mov dx, 30C2h |
793 | ; mov cx, 4 |
793 | ; mov cx, 4 |
794 | ;.0: |
794 | ;.0: |
795 | ; in al, dx |
795 | ; in al, dx |
796 | ; cmp al, 0FFh |
796 | ; cmp al, 0FFh |
797 | ; jz @f |
797 | ; jz @f |
798 | ; test al, 4 |
798 | ; test al, 4 |
799 | ; jnz .1 |
799 | ; jnz .1 |
800 | ;@@: |
800 | ;@@: |
801 | ; add dx, 8 |
801 | ; add dx, 8 |
802 | ; in al, dx |
802 | ; in al, dx |
803 | ; cmp al, 0FFh |
803 | ; cmp al, 0FFh |
804 | ; jz @f |
804 | ; jz @f |
805 | ; test al, 4 |
805 | ; test al, 4 |
806 | ; jnz .1 |
806 | ; jnz .1 |
807 | ;@@: |
807 | ;@@: |
808 | ; loop .0 |
808 | ; loop .0 |
809 | ; ret |
809 | ; ret |
810 | ;.1: |
810 | ;.1: |
811 | ; or al, 84h |
811 | ; or al, 84h |
812 | ; out dx, al |
812 | ; out dx, al |
813 | ;.2: |
813 | ;.2: |
814 | ; mov dx, 30F7h |
814 | ; mov dx, 30F7h |
815 | ; in al, dx |
815 | ; in al, dx |
816 | ; mov byte [BOOT_VAR + 48Eh], 0FFh |
816 | ; mov byte [BOOT_VAR + 48Eh], 0FFh |
817 | ; ret |
817 | ; ret |
818 | 818 | ||
819 | align 4 |
819 | align 4 |
820 | v86_irq: |
820 | v86_irq: |
821 | ; push irq/pushad/jmp v86_irq |
821 | ; push irq/pushad/jmp v86_irq |
822 | ; ebp = irq |
822 | ; ebp = irq |
823 | lea esi, [esp+1Ch] |
823 | lea esi, [esp+1Ch] |
824 | lea edi, [esi+4] |
824 | lea edi, [esi+4] |
825 | mov ecx, 8 |
825 | mov ecx, 8 |
826 | std |
826 | std |
827 | rep movsd |
827 | rep movsd |
828 | cld |
828 | cld |
829 | mov edi, ebp |
829 | mov edi, ebp |
830 | pop eax |
830 | pop eax |
831 | v86_irq2: |
831 | v86_irq2: |
832 | mov esi, [v86_irqhooks+edi*8] ; get VM handle |
832 | mov esi, [v86_irqhooks+edi*8] ; get VM handle |
833 | mov eax, [esi+V86_machine.process] |
833 | mov eax, [esi+V86_machine.process] |
834 | mov ecx, [CURRENT_TASK] |
834 | mov ecx, [CURRENT_TASK] |
835 | shl ecx, 8 |
835 | shl ecx, 8 |
836 | cmp [SLOT_BASE+ecx+APPDATA.process], eax |
836 | cmp [SLOT_BASE+ecx+APPDATA.process], eax |
837 | jnz .notcurrent |
837 | jnz .notcurrent |
838 | lea eax, [edi+8] |
838 | lea eax, [edi+8] |
839 | cmp al, 10h |
839 | cmp al, 10h |
840 | mov ah, 1 |
840 | mov ah, 1 |
841 | jb @f |
841 | jb @f |
842 | add al, 60h |
842 | add al, 60h |
843 | @@: |
843 | @@: |
844 | jmp v86_exc_c.simulate_int |
844 | jmp v86_exc_c.simulate_int |
845 | .notcurrent: |
845 | .notcurrent: |
846 | mov ebx, SLOT_BASE + 0x100 |
846 | mov ebx, SLOT_BASE + 0x100 |
847 | mov ecx, [TASK_COUNT] |
847 | mov ecx, [TASK_COUNT] |
848 | .scan: |
848 | .scan: |
849 | cmp [ebx+APPDATA.process], eax |
849 | cmp [ebx+APPDATA.process], eax |
850 | jnz .cont |
850 | jnz .cont |
851 | push ecx |
851 | push ecx |
852 | mov ecx, [ebx+APPDATA.saved_esp0] |
852 | mov ecx, [ebx+APPDATA.saved_esp0] |
853 | cmp word [ecx-sizeof.v86_regs+v86_regs.esp], 6 |
853 | cmp word [ecx-sizeof.v86_regs+v86_regs.esp], 6 |
854 | jb .cont2 |
854 | jb .cont2 |
855 | movzx edx, word [ecx-sizeof.v86_regs+v86_regs.ss] |
855 | movzx edx, word [ecx-sizeof.v86_regs+v86_regs.ss] |
856 | shl edx, 4 |
856 | shl edx, 4 |
857 | push eax |
857 | push eax |
858 | movzx eax, word [ecx-sizeof.v86_regs+v86_regs.esp] |
858 | movzx eax, word [ecx-sizeof.v86_regs+v86_regs.esp] |
859 | sub eax, 6 |
859 | sub eax, 6 |
860 | add edx, eax |
860 | add edx, eax |
861 | mov eax, edx |
861 | mov eax, edx |
862 | call v86_get_lin_addr |
862 | call v86_get_lin_addr |
863 | cmp eax, 0x1000 |
863 | cmp eax, 0x1000 |
864 | jb .cont3 |
864 | jb .cont3 |
865 | lea eax, [edx+5] |
865 | lea eax, [edx+5] |
866 | call v86_get_lin_addr |
866 | call v86_get_lin_addr |
867 | cmp eax, 0x1000 |
867 | cmp eax, 0x1000 |
868 | jb .cont3 |
868 | jb .cont3 |
869 | pop eax |
869 | pop eax |
870 | pop ecx |
870 | pop ecx |
871 | jmp .found |
871 | jmp .found |
872 | .cont3: |
872 | .cont3: |
873 | pop eax |
873 | pop eax |
874 | .cont2: |
874 | .cont2: |
875 | pop ecx |
875 | pop ecx |
876 | .cont: |
876 | .cont: |
877 | add ebx, 0x100 |
877 | add ebx, 0x100 |
878 | loop .scan |
878 | loop .scan |
879 | mov ecx, edi |
879 | mov ecx, edi |
880 | call irq_eoi |
880 | call irq_eoi |
881 | popad |
881 | popad |
882 | iretd |
882 | iretd |
883 | .found: |
883 | .found: |
884 | mov eax, [eax+PROC.pdt_0_phys] |
884 | mov eax, [eax+PROC.pdt_0_phys] |
885 | mov cr3, eax |
885 | mov cr3, eax |
886 | mov esi, [ebx+APPDATA.saved_esp0] |
886 | mov esi, [ebx+APPDATA.saved_esp0] |
887 | sub word [esi-sizeof.v86_regs+v86_regs.esp], 6 |
887 | sub word [esi-sizeof.v86_regs+v86_regs.esp], 6 |
888 | mov ecx, [esi-sizeof.v86_regs+v86_regs.eip] |
888 | mov ecx, [esi-sizeof.v86_regs+v86_regs.eip] |
889 | mov word [edx], cx |
889 | mov word [edx], cx |
890 | mov ecx, [esi-sizeof.v86_regs+v86_regs.cs] |
890 | mov ecx, [esi-sizeof.v86_regs+v86_regs.cs] |
891 | mov word [edx+2], cx |
891 | mov word [edx+2], cx |
892 | mov ecx, [esi-sizeof.v86_regs+v86_regs.eflags] |
892 | mov ecx, [esi-sizeof.v86_regs+v86_regs.eflags] |
893 | mov word [edx+4], cx |
893 | mov word [edx+4], cx |
894 | lea eax, [edi+8] |
894 | lea eax, [edi+8] |
895 | cmp al, 10h |
895 | cmp al, 10h |
896 | jb @f |
896 | jb @f |
897 | add al, 60h |
897 | add al, 60h |
898 | @@: |
898 | @@: |
899 | mov cx, [eax*4] |
899 | mov cx, [eax*4] |
900 | mov word [esi-sizeof.v86_regs+v86_regs.eip], cx |
900 | mov word [esi-sizeof.v86_regs+v86_regs.eip], cx |
901 | mov cx, [eax*4+2] |
901 | mov cx, [eax*4+2] |
902 | mov word [esi-sizeof.v86_regs+v86_regs.cs], cx |
902 | mov word [esi-sizeof.v86_regs+v86_regs.cs], cx |
903 | and byte [esi-sizeof.v86_regs+v86_regs.eflags+1], not 3 |
903 | and byte [esi-sizeof.v86_regs+v86_regs.eflags+1], not 3 |
904 | call update_counters |
904 | call update_counters |
905 | lea edi, [ebx + 0x100000000 - SLOT_BASE] |
905 | lea edi, [ebx + 0x100000000 - SLOT_BASE] |
906 | shr edi, 3 |
906 | shr edi, 3 |
907 | add edi, CURRENT_TASK |
907 | add edi, CURRENT_TASK |
908 | call find_next_task.found |
908 | call find_next_task.found |
909 | call do_change_task |
909 | call do_change_task |
910 | popad |
910 | popad |
911 | iretd |
911 | iretd |