Subversion Repositories Kolibri OS

Rev

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

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