Subversion Repositories Kolibri OS

Rev

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

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