sys32 - concentration all (except #NM) exception handlers in ecx_c for optimization purpose

debug  - moved handler to sys32::exc_c
fpu    - moved except_16/19 to sys32::exc_c
memory - changing interface for page_fault_handler
v86    - changing interface for handler v86_exc_c
kernel - small optimization

git-svn-id: svn://kolibrios.org@1056 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Galkov 2009-04-04 19:58:42 +00:00
parent 3be0aa5c21
commit 82da211b9b
7 changed files with 799 additions and 887 deletions

View File

@ -415,59 +415,28 @@ debugger_notify:
.ret: .ret:
ret ret
debug_exc: debug_ex:
test byte [esp+8+2], 2
jnz v86_debug_exc
; int 1 = #DB
save_ring3_context
cld
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov eax, dr6
push eax
xor eax, eax
mov dr6, eax
; test if debugging
cli
mov eax, [current_slot]
mov eax, [eax+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
add esp, 0x20+4
mov [error_interrupt], 1
call show_error_parameters
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 4
jmp change_task
.debug:
; we are debugged process, notify debugger and suspend ourself ; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID ; eax=debugger PID
pop edx mov edx, dr6 ; debug_message data=DR6_image
xor ebx, ebx
mov dr6, ebx
mov ebx, dr7 mov ebx, dr7
mov cl, not 1 mov cl, not 8
.l1: .l1: shl bl,2
test bl, 1 jc @f
jnz @f
and dl, cl and dl, cl
@@: @@: sar cl,1
shr ebx, 2 jc .l1
add cl, cl mov ecx,3 ; debug_message code=debug_exception
inc ecx .notify:
cmp cl, not 10h push edx ; debug_message data
jnz .l1 mov ebx, [TASK_BASE]
push edx ; DR6 image push [ebx+TASKDATA.pid] ; PID
mov ecx, [TASK_BASE] push ecx ; debug_message code
push dword [ecx+TASKDATA.pid] ; PID mov ecx,12 ; debug_message size
push 12 call debugger_notify ;; only ONE using, inline ???
pop ecx add esp,12
push 3 ; 3 = debug exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [TASK_BASE] mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 1 ; suspended mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task call change_task

View File

@ -142,7 +142,7 @@ fpu_restore:
ret ret
align 4 align 4
e7: ;#NM exception handler except_7: ;#NM exception handler
save_ring3_context save_ring3_context
clts clts
mov ax, app_data ; mov ax, app_data ;
@ -188,8 +188,8 @@ reg_eflags equ ebp+12
reg_esp equ ebp+16 reg_esp equ ebp+16
reg_ss equ ebp+20 reg_ss equ ebp+20
align 4 align 4 ;not used now
except_16: ;fpu native exceptions handler proc except_16 ;fpu native exceptions handler
test byte [esp+8+2], 2 test byte [esp+8+2], 2
jnz v86_except_16 jnz v86_except_16
push ebp push ebp
@ -233,9 +233,10 @@ except_16: ;fpu native exceptions handler
mov bl, 16 mov bl, 16
jmp exc_c jmp exc_c
endp
align 4 align 4 ;not used now
except_19: ;sse exceptions handler proc except_19 ;sse exceptions handler
test byte [esp+8+2], 2 test byte [esp+8+2], 2
jnz v86_except_19 jnz v86_except_19
push ebp push ebp
@ -278,6 +279,7 @@ except_19: ;sse exceptions handler
mov bl, 19 mov bl, 19
jmp exc_c jmp exc_c
endp
restore reg_eip restore reg_eip
restore reg_cs restore reg_cs

View File

@ -544,23 +544,14 @@ get_pg_addr:
align 4 align 4
; Now it is called from sys32::exc_c (see stack frame there)
proc page_fault_handler proc page_fault_handler
test byte [esp+12+2], 2
jnz v86_page_fault
.err_code equ ebp+32
.err_addr equ ebp-4 .err_addr equ ebp-4
pushad
mov ebp, esp mov ebp, esp
mov eax, cr2 mov ebx, cr2
push eax push ebx ; that is locals: .err_addr = cr2
mov ax, app_data
mov ds, ax
mov es, ax
inc [pg_data.pages_faults] inc [pg_data.pages_faults]
; push eax ; push eax
@ -571,10 +562,9 @@ proc page_fault_handler
; pop edx ; pop edx
; pop eax ; pop eax
mov ebx, [.err_addr] mov eax, [pf_err_code]
mov eax, [.err_code]
cmp ebx, OS_BASE cmp ebx, OS_BASE ;ebx == .err_addr
jb .user_space ;страница в памяти приложения ; jb .user_space ;страница в памяти приложения ;
cmp ebx, page_tabs cmp ebx, page_tabs
@ -583,7 +573,7 @@ proc page_fault_handler
cmp ebx, kernel_tabs cmp ebx, kernel_tabs
jb .alloc;.app_tabs ;таблицы страниц приложения ; jb .alloc;.app_tabs ;таблицы страниц приложения ;
;просто создадим одну ;просто создадим одну
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå
cmp ebx, LFB_BASE cmp ebx, LFB_BASE
jb .core_tabs ;таблицы страниц ядра jb .core_tabs ;таблицы страниц ядра
;Ошибка ;Ошибка
@ -591,8 +581,13 @@ proc page_fault_handler
;область LFB ;область LFB
;Ошибка ;Ошибка
jmp .fail jmp .fail
end if
.core_tabs:
.fail: ;simply return to caller
mov esp, ebp
mov bl, 14 ;#PF
ret
align 4
.user_space: .user_space:
test eax, PG_MAP test eax, PG_MAP
jnz .err_access ;Страница присутствует jnz .err_access ;Страница присутствует
@ -615,33 +610,32 @@ align 4
test eax, eax test eax, eax
jz .fail jz .fail
stdcall map_page,[ebp-4],eax,dword PG_UW stdcall map_page,[.err_addr],eax,dword PG_UW
mov edi, [ebp-4] mov edi, [.err_addr]
and edi, 0xFFFFF000 and edi, 0xFFFFF000
mov ecx, 1024 mov ecx, 1024
xor eax, eax xor eax, eax
cld ;cld ;caller is duty for this
rep stosd rep stosd
.exit: .exit: ;iret with repeat fault instruction
mov esp, ebp add esp,8 ; clear in stack: locals(.err_addr) + ret_to_caller
popad restore_ring3_context
add esp, 4
iretd iretd
.err_access: .err_access = .fail
;никогда не происходит ;никогда не происходит
jmp .fail ;jmp .fail
.kernel_space: .kernel_space:
test eax, PG_MAP test eax, PG_MAP
jz .fail ;страница не присутствует jz .fail ;страница не присутствует
test eax, 4 ;U/S test eax,12 ;U/S (+below)
jnz .fail ;приложение обратилось к памяти jnz .fail ;приложение обратилось к памяти
;ядра ;ядра
test eax, 8 ;test eax, 8
jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò ;jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò
;в таблицах страниц. добавлено в P4/Xeon ;в таблицах страниц. добавлено в P4/Xeon
;попытка записи в защищённую страницу ядра ;попытка записи в защищённую страницу ядра
@ -660,7 +654,7 @@ align 4
jz .fail jz .fail
push eax push eax
stdcall map_page,[ebp-4],eax,dword PG_SW stdcall map_page,[.err_addr],eax,dword PG_SW
pop eax pop eax
mov edi, [.err_addr] mov edi, [.err_addr]
and edi, -4096 and edi, -4096
@ -674,26 +668,9 @@ align 4
add esi, [default_io_map] add esi, [default_io_map]
mov ecx, 4096/4 mov ecx, 4096/4
cld ;cld ;caller is duty for this
rep movsd rep movsd
jmp .exit jmp .exit
;íå îáðàáàòûâàåì. Îøèáêà
.core_tabs:
.fail:
mov esp, ebp
popad
add esp, 4
; iretd
save_ring3_context ;debugger support
mov bl, 14
jmp exc_c
iretd
endp endp
align 4 align 4
@ -1346,6 +1323,3 @@ proc create_ring_buffer stdcall, size:dword, flags:dword
.fail: .fail:
ret ret
endp endp

View File

@ -14,212 +14,206 @@
$Revision$ $Revision$
align 4 align 4 ;3A08
idtreg:
dw 8*0x41-1
dd idts+8
build_interrupt_table: build_interrupt_table:
mov edi, idts
mov edi, idts+8
mov esi, sys_int mov esi, sys_int
mov ecx, 0x40 mov ecx, 0x40
@@: mov eax, (10001110b shl 24) + os_code
lodsd @@: movsw ;low word of code-entry
mov [edi], ax ; lower part of offset stosd ;interrupt gate type : os_code selector
mov [edi+2], word os_code ; segment selector movsw ;high word of code-entry
mov ax, word 10001110b shl 8 ; type: interrupt gate
mov [edi+4], eax
add edi, 8
loop @b loop @b
movsd ;copy low dword of trap gate for int 0x40
;mov edi,8*0x40+idts+8 movsd ;copy high dword of trap gate for int 0x40
mov dword [edi], (i40 and 0xFFFF) or (os_code shl 16) lidt [esi]
mov dword [edi+4], (11101111b shl 8) or (i40 and 0xFFFF0000)
; type: trap gate
ret ret
iglobal iglobal
align 4
msg_sel_ker db "kernel", 0
msg_sel_app db "application", 0
sys_int: sys_int:
dd e0,debug_exc,e2,e3 ;exception handlers addresses (for interrupt gate construction)
dd e4,e5,e6,e7 dd e0,e1,e2,e3,e4,e5,e6,except_7
dd e8,e9,e10,e11 dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15
dd e12,e13,page_fault_handler,e15 dd e16, e17,e18, e19
times 12 dd unknown_interrupt ;int_20..int_31
dd except_16, e17,e18, except_19
times 12 dd unknown_interrupt
;interrupt handlers addresses (for interrupt gate construction)
dd irq0, irq_serv.irq_1, irq_serv.irq_2 dd irq0, irq_serv.irq_1, irq_serv.irq_2
if USE_COM_IRQ if USE_COM_IRQ
dd irq_serv.irq_3, irq_serv.irq_4 dd irq_serv.irq_3, irq_serv.irq_4
else else
dd p_irq3, p_irq4 dd p_irq3, p_irq4 ;??? íåñòûêîâêà
end if end if
dd irq_serv.irq_5, p_irq6, irq_serv.irq_7 dd irq_serv.irq_5, p_irq6, irq_serv.irq_7
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10
dd irq_serv.irq_11, irq_serv.irq_12, irqD,p_irq14,p_irq15 dd irq_serv.irq_11, irq_serv.irq_12, irqD,p_irq14,p_irq15
times 16 dd unknown_interrupt ;int_0x30..int_0x3F
times 16 dd unknown_interrupt ;int_0x40 gate trap (for directly copied)
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16
idtreg: ; data for LIDT instruction (must be immediately below sys_int data)
dw 2*($-sys_int-4)-1
dd idts ;0x8000B100
dw 0 ;ïðîñòî âûðàâíèâàíèå
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b
dd msg_exc_c,msg_exc_d,msg_exc_e
msg_exc_8 db "Double fault", 0
msg_exc_u db "Undefined Exception", 0
msg_exc_a db "Invalid TSS", 0
msg_exc_b db "Segment not present", 0
msg_exc_c db "Stack fault", 0
msg_exc_d db "General protection fault", 0
msg_exc_e db "Page fault", 0
msg_sel_ker db "kernel", 0
msg_sel_app db "application", 0
dd i40
endg endg
macro save_ring3_context macro save_ring3_context {
{
pushad pushad
} }
macro restore_ring3_context macro restore_ring3_context {
{
popad popad
} }
macro exc_wo_code [num] {
; simply return control to interrupted process
unknown_interrupt:
iret
macro exc_wo_code [num]
{
forward
e#num : e#num :
save_ring3_context save_ring3_context
mov bl, num mov bl, num
jmp exc_c jmp exc_c
} } exc_wo_code 0,1,2,3,4,5,6,15,16,19
macro exc_w_code [num] macro exc_w_code [num] {
{
forward
e#num : e#num :
add esp, 4 add esp, 4
save_ring3_context save_ring3_context
mov bl, num mov bl, num
jmp exc_c jmp exc_c
} } exc_w_code 8,9,10,11,12,13,17,18
exc_wo_code 0, 2, 3, 4, 5, 6, 9, 15, 18
exc_w_code 8, 10, 11, 12, 13, 14, 17
exc_c: uglobal
mov ax, app_data ;èñêëþ÷åíèå pf_err_code dd ?
mov ds, ax ;çàãðóçèì ïðàâèëüíûå çíà÷åíè endg
mov es, ax ;â ðåãèñòðû
page_fault_exc:
pop [pf_err_code] ;äåéñòâèòåëüíî äî ñëåäóþùåãî #PF
save_ring3_context
mov bl,14
exc_c: ;èñêëþ÷åíèå
; Ôðýéì ñòåêà ïðè èñêëþ÷åíèè/ïðåðûâàíèè èç 3-ãî êîëüöà + pushad (ò.å., èìåííî çäåñü)
reg_ss equ esp+0x30
reg_esp3 equ esp+0x2C
reg_eflags equ esp+0x28
reg_cs3 equ esp+0x24
reg_eip equ esp+0x20
; ýòî ôðýéì îò pushad
reg_eax equ esp+0x1C
reg_ecx equ esp+0x18
reg_edx equ esp+0x14
reg_ebx equ esp+0x10
reg_esp0 equ esp+0x0C
reg_ebp equ esp+0x08
reg_esi equ esp+0x04
reg_edi equ esp+0x00
Mov ds,ax,app_data ; çàãðóçèì ïðàâèëüíûå çíà÷åíèÿ
mov es,ax ; â ñåãìåíòíûå ðåãèñòðû
cld ; è ïðèâîäèì DF ê ñòàíäàðòó
; redirect to V86 manager? (EFLAGS & 0x20000) != 0? ; redirect to V86 manager? (EFLAGS & 0x20000) != 0?
test byte [esp+20h+8+2], 2 test byte[reg_eflags+2],2
jnz v86_exc_c jnz v86_exc_c
cmp bl,14 ; #PF
; test if debugging jne .l0
cli call page_fault_handler
mov eax, [current_slot] .l0: mov esi, [current_slot]
mov eax, [eax+APPDATA.debugger_slot] mov eax,[esi+APPDATA.fpu_handler]
cmp bl,16 ; #MF
je .l1
cmp bl,19 ; #XF
jne .l2
mov eax,[esi+APPDATA.sse_handler]
.l1: test eax, eax
jnz IRetToUserHook
.l2: cli
mov eax, [esi+APPDATA.debugger_slot]
test eax, eax test eax, eax
jnz .debug jnz .debug
sti sti
; not debuggee => say error and terminate ; not debuggee => say error and terminate
movzx eax, bl call show_error_parameters ;; only ONE using, inline ???
mov [error_interrupt], eax ;mov edx, [TASK_BASE]
call show_error_parameters mov [edx + TASKDATA.state], byte 4 ; terminate
add esp, 0x20 jmp change_task ; stack - here it does not matter at all
mov edx, [TASK_BASE]
mov [edx + TASKDATA.state], byte 4
jmp change_task
.debug: .debug:
; we are debugged process, notify debugger and suspend ourself ; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID ; eax=debugger PID
cld cmp bl,1 ; #DB
movzx ecx, bl je debug_ex
push ecx movzx edx, bl ; debug_message data=Number_Of_Exception
mov ecx, [TASK_BASE] mov ecx,1 ; debug_message code=other_exception
push dword [ecx+TASKDATA.pid] ; PID of current process jmp debug_ex.notify ; notify debugger and suspend ourself
push 12
pop ecx
push 1 ; 1=exception
call debugger_notify
pop ecx
pop ecx
pop ecx
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task
restore_ring3_context
iretd
iglobal IRetToUserHook:
hexletters db '0123456789ABCDEF' xchg eax, [reg_eip]
error_interrupt dd -1 sub dword[reg_esp3], 4
endg mov edi, [reg_esp3]
stosd
restore_ring3_context
unknown_interrupt:
iretd
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
show_error_parameters: show_error_parameters:
mov eax,[CURRENT_TASK] mov edx,[TASK_BASE] ;not scratched below
shl eax, 5 DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid]
DEBUGF 1, "K : Process - forced terminate PID: %x\n", [CURRENT_TASK + TASKDATA.pid + eax] cmp bl, 0x08
mov eax, [error_interrupt] jb .l0
cmp al, 0x08 cmp bl, 0x0e
jne @f jbe .l1
DEBUGF 1, "K : Double fault\n" .l0: mov bl, 0x09
jmp defined_error .l1: movzx eax,bl
@@: mov eax,[msg_fault_sel+eax*4 - 0x08*4]
cmp al, 0x0a DEBUGF 1, "K : %s\n", eax
jne @f mov eax, [reg_cs3+4]
DEBUGF 1, "K : Invalid TSS\n"
jmp defined_error
@@:
cmp al, 0x0b
jne @f
DEBUGF 1, "K : Segment not present\n"
jmp defined_error
@@:
cmp al, 0x0c
jne @f
DEBUGF 1, "K : Stack fault\n"
jmp defined_error
@@:
cmp al, 0x0d
jne @f
DEBUGF 1, "K : General protection fault\n"
jmp defined_error
@@:
cmp al, 0x0e
jne @f
DEBUGF 1, "K : Page fault\n"
jmp defined_error
@@:
DEBUGF 1, "K : Undefined Exception\n"
defined_error:
DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [esp + 0x20], [esp - 12 + 0x20], [esp - 4 + 0x20]
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [esp - 8 + 0x20], [esp - 24 + 0x20], [esp - 28 + 0x20]
DEBUGF 1, "K : EBP : %x EIP : %x ", [esp - 20 + 0x20], [esp + 4 + 0x20]
mov eax, [esp + 8 + 0x20]
mov edi, msg_sel_app mov edi, msg_sel_app
mov ebx, [esp + 16 + 0x20] mov ebx, [reg_esp3+4]
cmp eax, app_code cmp eax, app_code
je @f je @f
mov edi, msg_sel_ker mov edi, msg_sel_ker
mov ebx, [esp - 16 + 0x20] mov ebx, [reg_esp0+4]
@@: @@: DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4]
DEBUGF 1, "ESP : %x\nK : Flags : %x CS : %x (%s)\n", ebx, [esp + 12 + 0x20], eax, edi DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4]
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi
ret ret
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
restore reg_ss
restore reg_esp3
restore reg_eflags
restore reg_cs
restore reg_eip
restore reg_eax
restore reg_ecx
restore reg_edx
restore reg_ebx
restore reg_esp0
restore reg_ebp
restore reg_esi
restore reg_edi
; irq1 -> hid/keyboard.inc ; irq1 -> hid/keyboard.inc
macro irqh [num] macro irqh [num] {
{
forward
p_irq#num : p_irq#num :
mov edi, num mov edi, num
jmp irqhandler jmp irqhandler
} }
irqh 2,3,4,5,7,8,9,10,11
p_irq6: p_irq6:
@ -277,26 +271,18 @@ ready_for_next_irq_1:
ret ret
irqD: irqD:
save_ring3_context push eax
mov ax, app_data ;os_data
mov ds, ax
mov es, ax
mov dx,0xf0
mov al,0 mov al,0
out dx,al out 0xf0,al
mov dx,0xa0
mov al,0x20 mov al,0x20
out dx,al out 0xa0,al
mov dx,0x20 out 0x20,al
out dx,al pop eax
restore_ring3_context
iret iret
irqh 2,3,4,5,7,8,9,10,11
irqhandler: irqhandler:
mov esi,edi ; 1 mov esi,edi ; 1

View File

@ -351,27 +351,6 @@ endg
; a protected-mode interrupt handler (typically the general-protection ; a protected-mode interrupt handler (typically the general-protection
; exception handler, which in turn calls the virtual 8086-mode monitor). ; exception handler, which in turn calls the virtual 8086-mode monitor).
v86_debug_exc:
pushad
xor eax, eax
mov dr6, eax
mov bl, 1
jmp v86_exc_c
v86_page_fault:
add esp, 4
pushad
mov bl, 14
jmp v86_exc_c
v86_except_16:
pushad
mov bl, 16
jmp v86_exc_c
v86_except_19:
pushad
mov bl, 19
iglobal iglobal
v86_exc_str1 db 'V86 : unexpected exception ',0 v86_exc_str1 db 'V86 : unexpected exception ',0
v86_exc_str2 db ' at ',0 v86_exc_str2 db ' at ',0
@ -387,11 +366,12 @@ v86_irqerr db 'V86 : IRQ already hooked',13,10,0
endg endg
v86_exc_c: v86_exc_c:
mov ax, app_data
mov ds, ax
mov es, ax
; Did we all that we have wanted to do? ; Did we all that we have wanted to do?
mov eax, [esp+v86_regs.size+10h+18h] cmp bl,1
jne @f
xor eax, eax
mov dr6, eax
@@: mov eax, [esp+v86_regs.size+10h+18h]
cmp word [esp+v86_regs.eip], ax cmp word [esp+v86_regs.eip], ax
jnz @f jnz @f
shr eax, 16 shr eax, 16

View File

@ -454,8 +454,8 @@ high_code:
; LOAD IDT ; LOAD IDT
call build_interrupt_table call build_interrupt_table ;lidt is executed
lidt [idtreg] ;lidt [idtreg]
call init_kernel_heap call init_kernel_heap
stdcall kernel_alloc, RING0_STACK_SIZE+512 stdcall kernel_alloc, RING0_STACK_SIZE+512
@ -1296,6 +1296,7 @@ display_number_force:
xor edx,edx xor edx,edx
call division_64_bits call division_64_bits
div ebx div ebx
hexletters = __fdo_hexdigits
add edx,hexletters add edx,hexletters
mov dl,[edx] mov dl,[edx]
mov [edi],dl mov [edi],dl

View File

@ -70,9 +70,9 @@
; ;
; A400 -> B0FF free ; A400 -> B0FF free
; B100 -> B2FF IDT ; B100 -> B307 IDT for int_0x00..int_0x40
; B300 -> BFFF free ; B308 -> BFFF free
; C000 -> C3FF window stack C000 no of windows - all in words ; C000 -> C3FF window stack C000 no of windows - all in words
; C402 -> C7FF window position in stack ; C402 -> C7FF window position in stack