Subversion Repositories Kolibri OS

Rev

Rev 8052 | Rev 8869 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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