complete SSE support. user-level SSE & FPU exceptions handling

git-svn-id: svn://kolibrios.org@168 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2006-10-07 09:47:03 +00:00
parent 6f8abcc3e7
commit 233c3e6435
13 changed files with 5687 additions and 25 deletions

View File

@ -86,6 +86,19 @@ CAPS_SVM equ 73 ;secure virual machine
CAPS_ALTMOVCR8 equ 74 ;
CR0_PE equ 0x00000001 ;protected mode
CR0_MP equ 0x00000002 ;monitor fpu
CR0_EM equ 0x00000004 ;fpu emulation
CR0_TS equ 0x00000008 ;task switch
CR0_ET equ 0x00000010 ;extension type hardcoded to 1
CR0_NE equ 0x00000020 ;numeric error
CR0_WP equ 0x00010000 ;write protect
CR0_AM equ 0x00040000 ;alignment check
CR0_NW equ 0x20000000 ;not write-through
CR0_CD equ 0x40000000 ;cache disable
CR0_PG equ 0x80000000 ;paging
CR4_VME equ 0x0001
CR4_PVI equ 0x0002
CR4_TSD equ 0x0004
@ -98,7 +111,22 @@ CR4_PCE equ 0x0100
CR4_OSFXSR equ 0x0200
CR4_OSXMMEXPT equ 0x0400
SSE_IE equ 0x0001
SSE_DE equ 0x0002
SSE_ZE equ 0x0004
SSE_OE equ 0x0008
SSE_UE equ 0x0010
SSE_PE equ 0x0020
SSE_DAZ equ 0x0040
SSE_IM equ 0x0080
SSE_DM equ 0x0100
SSE_ZM equ 0x0200
SSE_OM equ 0x0400
SSE_UM equ 0x0800
SSE_PM equ 0x1000
SSE_FZ equ 0x8000
SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM)
OS_BASE equ 0; 0x80400000

View File

@ -5,13 +5,13 @@ reg_cs equ ebp+8
reg_eflags equ ebp+12
reg_esp equ ebp+16
reg_ss equ ebp+20
fpu_ctrl equ ebp-28
;fpu_ctrl equ ebp-28
align 4
except_16:
push ebp
mov ebp, esp
sub esp, 28
; sub esp, 28
push eax
push ebx
@ -41,11 +41,53 @@ except_16:
iretd
.default:
pop edx
pop ecx
pop ebx
pop eax
leave
fnstenv [fpu_ctrl]
fnclex
or word [fpu_ctrl], 0111111b
fldenv [fpu_ctrl]
save_ring3_context ;debugger support
mov bl, 16
jmp exc_c
; fnstenv [fpu_ctrl]
; fnclex
; or word [fpu_ctrl], 0111111b
; fldenv [fpu_ctrl]
; pop edx
; pop ecx
; pop ebx
; pop eax
; leave
; iretd
align 16
except_19:
push ebp
mov ebp, esp
push eax
push ebx
push ecx
push edx
mov ebx, [ss:CURRENT_TASK]
shl ebx, 8
mov eax, [ss:ebx+PROC_BASE+APPDATA.sse_handler]
test eax, eax
jz .default
mov ecx, [reg_eip]
mov edx, [reg_esp]
sub edx, 4
mov [ss:edx+new_app_base], ecx
mov [reg_esp], edx
mov dword [reg_eip], eax
pop edx
pop ecx
@ -55,10 +97,21 @@ except_16:
leave
iretd
.default:
pop edx
pop ecx
pop ebx
pop eax
leave
save_ring3_context ;debugger support
mov bl, 19
jmp exc_c
restore reg_eip
restore reg_cs
restore reg_eflags
restore reg_esp
restore reg_ss
restore fpu_ctrl
;restore fpu_ctrl

View File

@ -4,9 +4,9 @@ tmp_page_tab equ 0x01000000
align 4
proc mem_test
mov eax, cr0
or eax, 0x60000000 ;disable caching
or eax, (CR0_CD+CR0_NW);disable caching
mov cr0, eax
wbinvd ;invalidate cache
wbinvd ;invalidate cache
xor edi, edi
mov ebx, 'TEST'
@ -17,7 +17,7 @@ proc mem_test
xchg ebx, dword [edi]
je @b
and eax, 0x21
and eax, not (CR0_CD+CR0_NW)
mov cr0, eax
mov eax, edi
ret
@ -40,7 +40,10 @@ proc init_memEx
jnc @F
or eax, PG_GLOBAL
or ebx, CR4_PGE
@@:
mov cr4, ebx
mov dword [sys_pgdir], eax
add eax, 0x00400000
mov dword [sys_pgdir+4], eax
@ -52,8 +55,6 @@ proc init_memEx
mov dword [sys_pgdir+0x600], sys_master_tab+PG_SW
mov dword [sys_master_tab+0x600], sys_master_tab+PG_SW
mov cr4, ebx
mov ecx, [pg_data.kernel_tables]
sub ecx, 4
mov eax, tmp_page_tab+PG_SW
@ -1102,6 +1103,15 @@ new_services:
stdcall srv_handlerEx, ebx
mov [esp+36], eax
ret
@@:
cmp eax, 18
ja @f
mov ecx, [CURRENT_TASK]
shl ecx, 8
mov eax, [ecx+PROC_BASE+APPDATA.sse_handler]
mov [ecx+PROC_BASE+APPDATA.sse_handler], ebx
mov [esp+36], eax
ret
@@:
.fail:

View File

@ -172,8 +172,8 @@ iglobal
dd e8,e9,e10,e11
dd e12,e13,page_fault_handler,e15
dd except_16, e17
times 14 dd unknown_interrupt
dd except_16, e17,e18, except_19
times 12 dd unknown_interrupt
dd irq0 , irq_serv.irq_1, p_irq2 ,irq_serv.irq_3
dd p_irq4 ,irq_serv.irq_5,p_irq6,irq_serv.irq_7
@ -219,7 +219,7 @@ macro exc_w_code [num]
jmp exc_c
}
exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15 ; 18, 19
exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15, 18
exc_w_code 8, 10, 11, 12, 13, 14, 17
exc_c:

View File

@ -0,0 +1,223 @@
align 4
proc detect_codec
locals
codec_id dd ?
endl
stdcall codec_read, dword 0x7C
shl eax, 16
mov [codec_id], eax
stdcall codec_read, dword 0x7E
or eax, [codec_id]
mov [codec.chip_id], eax
and eax, 0xFFFFFF00
mov edi, codecs
@@:
mov ebx, [edi]
test ebx, ebx
jz .unknown
cmp eax, ebx
jne .next
mov eax, [edi+4]
mov [codec.ac_vendor_ids], eax
stdcall detect_chip, [edi+8]
ret
.next:
add edi, 12
jmp @B
.unknown:
mov [codec.ac_vendor_ids], ac_unknown
mov [codec.chip_ids], chip_unknown
ret
endp
align 4
proc detect_chip stdcall, chip_tab:dword
mov eax, [codec.chip_id]
and eax, 0xFF
mov edi, [chip_tab]
@@:
mov ebx, [edi]
test ebx, ebx
jz .unknown
cmp eax,ebx
jne .next
mov eax, [edi+4]
mov [codec.chip_ids], eax
ret
.next:
add edi, 8
jmp @b
.unknown:
mov [codec.chip_ids], chip_unknown
ret
endp
align 4
proc setup_codec
xor eax, eax
stdcall codec_write, dword CODEC_AUX_VOL
mov eax, 0x1010
stdcall codec_write, dword CODEC_MASTER_VOL_REG
mov ax, 0x08
stdcall codec_write, dword 0x0C
mov ax, 0x0808
stdcall codec_write, dword CODEC_PCM_OUT_REG
mov ax, 0x0808
stdcall codec_write, dword 0x10
mov ax, 0x0808
stdcall codec_write, dword 0x12
mov ax, 0x0808
stdcall codec_write, dword 0x16
stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1)
or eax, BIT0 ; set VRA (BIT0)
stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG
stdcall set_sample_rate, dword 48000
.init_error:
xor eax, eax ; exit with error
ret
endp
align 4
proc set_master_vol stdcall, vol:dword
mov ebx, 63
mov ecx, 20644
mov eax, [vol]
cmp eax, 90
jna @f
mov eax, 90
@@:
mul ecx
shr eax, 15
sub ebx, eax
mov ah, bl
mov al, bl
stdcall codec_write, dword CODEC_MASTER_VOL_REG
ret
endp
align 4
proc get_master_vol stdcall, pvol:dword
stdcall codec_read, dword CODEC_MASTER_VOL_REG
and eax, 0x3F
mov ebx, 63
mov ecx, 20644
xchg eax, ebx
sub eax, ebx
shl eax, 15
xor edx, edx
div ecx
mov ebx, [pvol]
mov [ebx], eax
ret
endp
align 4
proc set_sample_rate stdcall, rate:dword
mov eax, [rate]
stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG
ret
endp
align 16
ac_unknown db 'unknown manufacturer',13,10,0
ac_Realtek db 'Realtek Semiconductor',13,10,0
ac_Analog db 'Analog Devices',13,10,0
ac_CMedia db 'C-Media Electronics',13,10,0
chip_unknown db 'unknown chip', 13,10,0
CHIP_ANALOG equ 0x41445300
CHIP_REALTEK equ 0x414C4700
CHIP_CMEDIA equ 0x434D4900
align 16
codecs dd CHIP_ANALOG, ac_Analog, chips_Analog
dd CHIP_CMEDIA, ac_CMedia, chips_CMedia
dd CHIP_REALTEK,ac_Realtek, chips_Realtek
dd 0
align 16
chips_Analog dd 0x03, chip_AD1819
dd 0x40, chip_AD1881
dd 0x48, chip_AD1881A
dd 0x60, chip_AD1884
dd 0x61, chip_AD1886
dd 0x62, chip_AD1887
dd 0x63, chip_AD1886A
dd 0x70, chip_AD1980
dd 0x75, chip_AD1985
dd 0
chips_Realtek dd 0x20, chip_ALC650
dd 0x21, chip_ALC650D
dd 0x22, chip_ALC650E
dd 0x23, chip_ALC650F
dd 0x60, chip_ALC655
dd 0x80, chip_ALC658
dd 0x81, chip_ALC658D
dd 0x90, chip_ALC850
dd 0
chips_CMedia dd 0x41, chip_CM9738
dd 0x61, chip_CM9739
dd 0x69, chip_CM9780
dd 0x78, chip_CM9761
dd 0x82, chip_CM9761
dd 0x83, chip_CM9761
dd 0
align 16
;Analog Devices
chip_AD1819 db 'AD1819 ',0dh,0ah,00h
chip_AD1881 db 'AD1881 ',0dh,0ah,00h
chip_AD1881A db 'AD1881A',0dh,0ah,00h
chip_AD1884 db 'AD1885 ',0dh,0ah,00h
chip_AD1885 db 'AD1885 ',0dh,0ah,00h
chip_AD1886 db 'AD1886 ',0dh,0ah,00h
chip_AD1886A db 'AD1886A',0dh,0ah,00h
chip_AD1887 db 'AD1887 ',0dh,0ah,00h
chip_AD1980 db 'AD1980 ',0dh,0ah,00h
chip_AD1985 db 'AD1985 ',0dh,0ah,00h
;Realtek
chip_ALC650 db 'ALC650 ',0dh,0ah,00h
chip_ALC650D db 'ALC650D',0dh,0ah,00h
chip_ALC650E db 'ALC650E',0dh,0ah,00h
chip_ALC650F db 'ALC650F',0dh,0ah,00h
chip_ALC655 db 'ALC655 ',0dh,0ah,00h
chip_ALC658 db 'ALC658 ',0dh,0ah,00h
chip_ALC658D db 'ALC658D',0dh,0ah,00h
chip_ALC850 db 'ALC850 ',0dh,0ah,00h
;CMedia
chip_CM9738 db 'CMI9738', 0dh,0ah,0
chip_CM9739 db 'CMI9739', 0dh,0ah,0
chip_CM9780 db 'CMI9780', 0dh,0ah,0
chip_CM9761 db 'CMI9761', 0dh,0ah,0

View File

@ -0,0 +1,795 @@
;
; This file is part of the Infinity sound library.
; (C) copyright Serge 2006
; email: infinity_sound@mail.ru
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
format MS COFF
include 'proc32.inc'
include 'main.inc'
DEBUG equ 1
EVENT_NOTIFY equ 0x00000200
OS_BASE equ 0; 0x80400000
new_app_base equ 0x60400000; 0x01000000
PROC_BASE equ OS_BASE+0x0080000
public service_proc
public START
public IMPORTS
SND_CREATE_BUFF equ 2
SND_PLAY equ 3
SND_STOP equ 4
SND_SETBUFF equ 5
SND_DESTROY_BUFF equ 6
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
virtual at 0
IOCTL IOCTL
end virtual
section '.flat' align 16
START:
stdcall [GetService], szSound
test eax, eax
jz .fail
mov [hSound], eax
stdcall [KernelAlloc], 16*512
test eax, eax
jz .out_of_mem
mov [mix_buff], eax
mov edi, stream_list
mov ecx, 17
xor eax, eax
cld
rep stosd
mov edi, stream
mov ecx, 4*STREAM_SIZE
rep stosd
stdcall set_handler, [hSound], new_mix
stdcall [RegService], szInfinity, service_proc
mov [stream_count],0
ret
.fail:
if DEBUG
mov esi, msgFail
call [SysMsgBoardStr]
end if
xor eax, eax
ret
.out_of_mem:
if DEBUG
mov esi, msgMem
call [SysMsgBoardStr]
end if
xor eax, eax
ret
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
align 4
proc service_proc stdcall, ioctl:dword
mov edi, [ioctl]
mov eax, [edi+io_code]
cmp eax, SND_CREATE_BUFF
jne @F
mov ebx, [edi+input]
stdcall CreateBuffer,[ebx]
ret
@@:
cmp eax, SND_PLAY
jne @F
mov ebx, [edi+input]
stdcall play_buffer, [ebx]
ret
@@:
cmp eax, SND_STOP
jne @F
; if DEBUG
; mov esi, msgStop
; call [SysMsgBoardStr]
; end if
mov ebx, [edi+input]
stdcall stop_buffer, [ebx]
ret
@@:
cmp eax, SND_SETBUFF
jne @F
mov ebx, [edi+input]
mov eax, [ebx+4]
add eax, new_app_base
stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12]
ret
@@:
cmp eax, SND_DESTROY_BUFF
jne @F
mov ebx, [edi+input]
stdcall DestroyBuffer, [ebx]
ret
@@:
xor eax, eax
ret
endp
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
TASK_COUNT equ 0x0003004
CURRENT_TASK equ 0x0003000
align 8
proc CreateBuffer stdcall, format:dword
locals
str dd ?
endl
call alloc_stream
and eax, eax
jz .fail
mov [str], eax
mov edi, eax
mov edx, [stream_count]
mov [stream_list+edx*4], eax
inc [stream_count]
mov [edi+STREAM.magic], 'WAVE'
mov [edi+STREAM.size], STREAM_SIZE
stdcall [KernelAlloc], 180*1024
mov edi, [str]
mov [edi+STREAM.base], eax
mov [edi+STREAM.curr_seg], eax
mov [edi+STREAM.notify_off1], eax
add eax, 0x8000
mov [edi+STREAM.notify_off2], eax
add eax, 0x7FFF
mov [edi+STREAM.limit], eax
inc eax
mov [edi+STREAM.work_buff], eax
mov [edi+STREAM.work_read], eax
mov [edi+STREAM.work_write], eax
mov [edi+STREAM.work_count], 0
add eax, 0x10000
mov [edi+STREAM.work_top], eax
add eax, 1024*32
mov [edi+STREAM.r_buff], eax
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov eax, [0x3000+ebx+4]
mov [edi+STREAM.notify_task], eax
mov eax, [format]
mov [edi+STREAM.format], eax
mov [edi+STREAM.flags], SND_STOP
xor ebx, ebx
cmp eax, 19
jb @f
mov ebx, 0x80808080
@@:
mov [edi+STREAM.r_silence], ebx
shl eax, 4
mov ebx, [resampler_params+eax]
mov ecx, [resampler_params+eax+4]
mov edx, [resampler_params+eax+8]
mov [edi+STREAM.r_size],ebx
mov [edi+STREAM.r_end], ecx
mov [edi+STREAM.r_dt], edx
mov ebx, [resampler_params+eax+12]
mov [edi+STREAM.resample], ebx
mov edi, [edi+STREAM.base]
mov ecx, 180*1024/4
xor eax, eax
rep stosd
mov eax, [str]
ret
.fail:
xor eax, eax
ret
endp
align 4
pid_to_slot:
push ebx
push ecx
mov ebx,[TASK_COUNT]
shl ebx,5
mov ecx,2*32
.loop:
cmp byte [CURRENT_TASK+ecx+0xa],9
jz .endloop ;skip empty slots
cmp [CURRENT_TASK+ecx+0x4],eax ;check PID
jz .pid_found
.endloop:
add ecx,32
cmp ecx,ebx
jle .loop
pop ecx
pop ebx
xor eax,eax
ret
.pid_found:
shr ecx,5
mov eax,ecx
pop ecx
pop ebx
ret
align 4
proc DestroyBuffer stdcall, str:dword
mov esi, [str]
cmp [esi+STREAM.magic], 'WAVE'
jne .fail
cmp [esi+STREAM.size], STREAM_SIZE
jne .fail
stdcall [KernelFree], [esi+STREAM.base]
mov eax, [str]
call free_stream
mov edi, [str]
mov ecx, STREAM_SIZE/4
xor eax, eax
cld
rep stosd
mov eax, [str]
mov esi, stream_list
mov ecx, 16
@@:
cmp [esi], eax
je .remove
add esi, 4
dec ecx
jnz @B
xor eax, eax
inc eax
ret
.remove:
mov edi, esi
add esi, 4
cld
rep movsd
dec [stream_count]
xor eax, eax
inc eax
ret
.fail:
xor eax, eax
ret
endp
align 4
proc play_buffer stdcall, str:dword
mov ebx, [str]
cmp [ebx+STREAM.magic], 'WAVE'
jne .fail
cmp [ebx+STREAM.size], STREAM_SIZE
jne .fail
mov [ebx+STREAM.flags], SND_PLAY
mov eax,[ebx+STREAM.work_buff]
mov [ebx+STREAM.work_read], eax
mov [ebx+STREAM.work_write], eax
mov [ebx+STREAM.work_count], 0
mov eax, [ebx+STREAM.base]
mov [ebx+STREAM.curr_seg], eax
mov esi, [ebx+STREAM.curr_seg]
mov edi, [ebx+STREAM.work_write]
mov edx, [ebx+STREAM.r_buff]
mov ecx, 32
mov eax, [ebx+STREAM.r_silence]
@@:
mov [edx], eax
add edx, 4
dec ecx
jnz @B
mov edx, [ebx+STREAM.r_buff]
stdcall [ebx+STREAM.resample], edi, esi, edx,\
[ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end]
mov ebx, [str]
add [ebx+STREAM.work_count], eax;
add [ebx+STREAM.work_write], eax;
mov eax, [ebx+STREAM.r_size]
add [ebx+STREAM.curr_seg], eax
; if DEBUG
; mov esi, msgPlay
; call [SysMsgBoardStr]
; end if
stdcall dev_play, [hSound]
xor eax, eax
inc eax
ret
.fail:
xor eax, eax
ret
endp
align 4
proc stop_buffer stdcall, str:dword
mov edi, [str]
cmp [edi+STREAM.magic], 'WAVE'
jne .fail
cmp [edi+STREAM.size], STREAM_SIZE
jne .fail
mov [edi+STREAM.flags], SND_STOP
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
xor eax, eax
inc eax
ret
.fail:
xor eax, eax
ret
endp
align 4
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
mov edx, [str]
test edx, edx
jz .fail
cmp [edx+STREAM.magic], 'WAVE'
jne .fail
cmp [edx+STREAM.size], STREAM_SIZE
jne .fail
mov esi,[src]
test esi, esi
jz .fail
cmp esi, new_app_base
jb .fail
mov ecx, [size]
test ecx, ecx
jz .fail
mov eax, [edx+STREAM.base]
add eax, [offs]
cmp eax, [edx+STREAM.base]
jb .fail
mov edi, eax
add eax, ecx
sub eax, 1
cmp eax, [edx+STREAM.limit]
ja .fail
shr ecx, 2
cld
rep movsd
xor eax, eax
inc eax
ret
.fail:
xor eax, eax
ret
endp
align 4
proc alloc_stream
mov esi, stream_map
pushf
cli
bsf eax, [esi]
jnz .find
popf
xor eax, eax
ret
.find: btr [esi], eax
popf
mov ebx, STREAM_SIZE
mul ebx
add eax, stream
ret
endp
align 4
proc free_stream
sub eax, stream
mov ebx, STREAM_SIZE
xor edx, edx
div ebx
and edx, edx
jnz .err
bts [stream_map], eax
ret
.err:
xor eax, eax
ret
endp
align 4
proc check_stream
xor edx, edx
mov ecx, [play_count]
.l1:
mov esi, [play_list+edx]
mov eax, [esi+STR.curr_seg]
cmp eax, [esi+STR.limit]
jb .next
.m1: mov eax,[esi+STR.base]
mov [esi+STR.curr_seg], eax
.next:
add edx, 4
loop .l1
ret
endp
align 4
proc prepare_playlist
.restart:
xor ebx, ebx
xor edx, edx
mov [play_count], 0
mov ecx, [stream_count]
jcxz .exit
.l1:
mov esi, [stream_list+ebx]
test esi, esi
jz .next
cmp [esi+STREAM.magic], 'WAVE'
jne .next
cmp [esi+STREAM.size], STREAM_SIZE
jne .next
mov eax,[esi+STREAM.notify_task]
cmp eax, -1
je .fail
call pid_to_slot
test eax, eax
jz .fail
cmp [esi+STREAM.flags], SND_PLAY;
jne .next
cmp [esi+STREAM.work_count], 16384
jb .next
mov [play_list+edx], esi
inc [play_count]
add edx, 4
.next:
add ebx, 4
loop .l1
.exit:
ret
.fail:
stdcall DestroyBuffer, esi
jmp .restart
endp
align 4
proc prepare_updatelist
xor ebx, ebx
xor edx, edx
mov [play_count], 0
mov ecx, [stream_count]
jcxz .exit
.l1:
mov eax, [stream_list+ebx]
test eax, eax
jz .next
cmp [eax+STREAM.flags], SND_PLAY
jne .next
mov [play_list+edx], eax
inc [play_count]
add edx, 4
.next:
add ebx, 4
loop .l1
.exit:
ret
endp
align 4
proc set_handler stdcall, hsrv:dword, handler_proc:dword
locals
handler dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
mov eax, [hsrv]
lea ecx, [handler_proc]
xor ebx, ebx
mov [handler], eax
mov [io_code], DEV_CALLBACK
mov [input], ecx
mov [inp_size], 4
mov [output], ebx
mov [out_size], 0
lea eax, [handler]
stdcall [ServiceHandler], eax
ret
endp
align 4
proc dev_play stdcall, hsrv:dword
locals
handle dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
mov eax, [hsrv]
xor ebx, ebx
mov [handle], eax
mov [io_code], DEV_PLAY
mov [input], ebx
mov [inp_size], ebx
mov [output], ebx
mov [out_size], ebx
lea eax, [handle]
stdcall [ServiceHandler], eax
ret
endp
include 'mixer.asm'
align 16
play_list dd 16 dup(0)
stream_list dd 17 dup(0)
align 16
resampler_params:
;r_size r_end r_dt resampler_func
dd 0,0,0,0 ; 0 PCM_ALL
dd 16384, 0, 0, copy_stream ; 1 PCM_2_16_48
dd 16384, 0, 0, m16_stereo ; 2 PCM_1_16_48
dd 16384, 0x08000000, 30109, resample_2 ; 3 PCM_2_16_44
dd 8192, 0x08000000, 30109, resample_1 ; 4 PCM_1_16_44
dd 16384, 0x08000000, 21846, resample_2 ; 5 PCM_2_16_32
dd 8192, 0x08000000, 21846, resample_1 ; 6 PCM_1_16_32
dd 16384, 0x08000000, 16384, resample_2 ; 7 PCM_2_16_24
dd 8192, 0x08000000, 16384, resample_1 ; 8 PCM_1_16_24
dd 8192, 0x04000000, 15052, resample_2 ; 9 PCM_2_16_22
dd 4096, 0x04000000, 15052, resample_1 ;10 PCM_1_16_22
dd 8192, 0x04000000, 10923, resample_2 ;11 PCM_2_16_16
dd 4096, 0x04000000, 10923, resample_1 ;12 PCM_1_16_16
dd 8192, 0x04000000, 8192, resample_2 ;13 PCM_2_16_12
dd 4096, 0x04000000, 8192, resample_1 ;14 PCM_1_16_12
dd 4096, 0x02000000, 7527, resample_2 ;15 PCM_2_16_11
dd 2048, 0x02000000, 7527, resample_1 ;16 PCM_1_16_11
dd 4096, 0x02000000, 5462, resample_2 ;17 PCM_2_16_8
dd 2048, 0x02000000, 5462, resample_1 ;18 PCM_1_16_8
dd 16384, 0, 0, s8_stereo ;19 PCM_2_8_48
dd 8192, 0, 0, m8_stereo ;20 PCM_1_8_48
dd 8192, 0x08000000, 30109, resample_28 ;21 PCM_2_8_44
dd 4096, 0x08000000, 30109, resample_18 ;22 PCM_1_8_44
dd 8192, 0x08000000, 21846, resample_28 ;23 PCM_2_8_32
dd 4096, 0x08000000, 21846, resample_18 ;24 PCM_1_8_32
dd 8192, 0x08000000, 16384, resample_28 ;25 PCM_2_8_24
dd 4096, 0x08000000, 16384, resample_18 ;26 PCM_1_8_24
dd 4096, 0x04000000, 15052, resample_28 ;27 PCM_2_8_22
dd 2048, 0x04000000, 15052, resample_18 ;28 PCM_1_8_22
dd 4096, 0x04000000, 10923, resample_28 ;29 PCM_2_8_16
dd 2048, 0x04000000, 10923, resample_18 ;30 PCM_1_8_16
dd 4096, 0x04000000, 8192, resample_28 ;31 PCM_2_8_12
dd 2048, 0x04000000, 8192, resample_18 ;32 PCM_1_8_12
dd 2048, 0x02000000, 7527, resample_28 ;33 PCM_2_8_11
dd 1024, 0x02000000, 7527, resample_18 ;34 PCM_1_8_11
dd 2048, 0x02000000, 5462, resample_28 ;35 PCM_2_8_8
dd 1024, 0x02000000, 5462, resample_18 ;36 PCM_1_8_8
play_count dd 0
stream_count dd 0
align 8
hSound dd 0
m7 dw 0x8000,0x8000,0x8000,0x8000
mm80 dq 0x8080808080808080
mm_mask dq 0xFF00FF00FF00FF00
mix_input dd 16 dup(0)
align 16
;fpu_state db 512 dup(0)
align 16
stream db STREAM_SIZE*16 dup(0)
stream_map dd 0xFFFF ; 16
mix_buff dd 0
mix_buff_map dd 0
align 16
IMPORTS:
AttachIntHandler dd szAttachIntHandler
SysMsgBoardStr dd szSysMsgBoardStr
PciApi dd szPciApi
PciRead32 dd szPciRead32
PciRead8 dd szPciRead8
AllocKernelSpace dd szAllocKernelSpace
MapPage dd szMapPage
KernelAlloc dd szKernelAlloc
KernelFree dd szKernelFree
GetPgAddr dd szGetPgAddr
RegService dd szRegService
GetCurrentTask dd szGetCurrentTask
GetService dd szGetService
ServiceHandler dd szServiceHandler
FpuSave dd szFpuSave
FpuRestore dd szFpuRestore
dd 0
szKernel db 'KERNEL', 0
szAttachIntHandler db 'AttachIntHandler',0
szSysMsgBoardStr db 'SysMsgBoardStr', 0
szPciApi db 'PciApi', 0
szPciRead32 db 'PciRead32', 0
szPciRead8 db 'PciRead8', 0
szAllocKernelSpace db 'AllocKernelSpace',0
szMapPage db 'MapPage',0
szRegService db 'RegService',0
szKernelAlloc db 'KernelAlloc',0
szGetPgAddr db 'GetPgAddr',0
szGetCurrentTask db 'GetCurrentTask ',0
szGetService db 'GetService',0
szServiceHandler db 'ServiceHandler',0
szKernelFree db 'KernelFree',0
szFpuSave db 'FpuSave',0
szFpuRestore db 'FpuRestore',0
szInfinity db 'INFINITY',0
szSound db 'SOUND',0
if DEBUG
msgFail db 'Sound service not found',13,10,0
msgPlay db 'Play buffer',13,10,0
msgStop db 'Stop',13,10,0
msgUser db 'User callback',13,10,0
msgMem db 'Not enough memory',13,10,0
end if

View File

@ -0,0 +1,133 @@
;
; This file is part of the Infinity sound AC97 driver.
; (C) copyright Serge 2006
; email: infinity_sound@mail.ru
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
PCM_2_16_48 equ 1
PCM_1_16_48 equ 2
PCM_2_16_44 equ 3
PCM_1_16_44 equ 4
PCM_2_16_32 equ 5
PCM_1_16_32 equ 6
PCM_2_16_24 equ 7
PCM_1_16_24 equ 8
PCM_2_16_22 equ 9
PCM_1_16_22 equ 10
PCM_2_16_16 equ 11
PCM_1_16_16 equ 12
PCM_2_16_12 equ 13
PCM_1_16_12 equ 14
PCM_2_16_11 equ 15
PCM_1_16_11 equ 16
PCM_2_8_48 equ 17
PCM_1_8_48 equ 18
PCM_2_8_44 equ 19
PCM_1_8_44 equ 20
PCM_2_8_32 equ 21
PCM_1_8_32 equ 22
PCM_2_8_24 equ 23
PCM_1_8_24 equ 24
PCM_2_8_22 equ 25
PCM_1_8_22 equ 26
PCM_2_8_16 equ 27
PCM_1_8_16 equ 28
PCM_2_8_12 equ 29
PCM_1_8_12 equ 30
PCM_2_8_11 equ 31
PCM_1_8_11 equ 32
SND_PLAY equ 1
SND_STOP equ 2
; struc SND_DEV
;{ .magic dd 0
; .size dd 0
; .count dd 0
; dd 0
; .snd_buff dd 16 dup (0)
;}
;virtual at 0
; SND_DEV SND_DEV
;end virtual
;SND_DEV_SIZE equ 80
struc STREAM
{ .magic dd 0
.size dd 0
.device dd 0
.format dd 0
.flags dd 0
.work_buff dd 0
.work_read dd 0
.work_write dd 0
.work_count dd 0
.work_top dd 0
.r_buff dd 0
.r_size dd 0
.r_end dd 0
.r_dt dd 0
.r_silence dd 0
.base dd 0
.curr_seg dd 0
.limit dd 0
.buff_size dd 0
.notify_off1 dd 0
.notify_off2 dd 0
.notify_task dd 0
.resample dd 0
}
STREAM_SIZE equ 23*4
virtual at 0
STREAM STREAM
end virtual
struc WAVE_HEADER
{ .riff_id dd ?
.riff_size dd ?
.riff_format dd ?
.fmt_id dd ?
.fmt_size dd ?
.format_tag dw ?
.channels dw ?
.freq dd ?
.bytes_sec dd ?
.block_align dw ?
.bits_sample dw ?
.data_id dd ?
.data_size dd ?
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,268 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }

1177
kernel/trunk/drivers/sis.asm Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -120,7 +120,7 @@ app_data equ 3+app_data_l-gdts
; CR0 Flags - Protected mode and Paging
mov ecx, 0x00000021
mov ecx, CR0_PE
; Enabling 32 bit protected mode
@ -399,9 +399,9 @@ include 'detect/disks.inc'
mov eax, sys_pgdir ;+PG_NOCACHE
mov cr3, eax
mov eax,cr0
or eax,0x80000000
mov cr0,eax
mov eax,cr0
or eax,CR0_PG
mov cr0,eax
call init_kernel_heap
call init_LFB
@ -447,25 +447,48 @@ include 'detect/disks.inc'
mov ecx, 16
rep movsb
clts
fninit
bt [cpu_caps], CAPS_FXSR
jnc .no_FXSR
stdcall kernel_alloc, 512*256
mov [fpu_data], eax
mov ebx, cr4
or ebx, CR4_OSFXSR
mov ecx, cr0
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT
mov cr4, ebx
jmp .clts
and ecx, not (CR0_MP+CR0_EM)
or ecx, CR0_NE
mov cr0, ecx
mov dword [esp-4], SSE_INIT
ldmxcsr [esp-4]
xorps xmm0, xmm0
xorps xmm1, xmm1
xorps xmm2, xmm2
xorps xmm3, xmm3
xorps xmm4, xmm4
xorps xmm5, xmm5
xorps xmm6, xmm6
xorps xmm7, xmm7
jmp .set_cr
.no_FXSR:
stdcall kernel_alloc, 112*256
mov [fpu_data], eax
mov ebx, cr4
mov ecx, cr0
and ebx, not (CR4_OSFXSR+CR4_OSXMMEXPT)
and ecx, not CR0_EM
or ecx, CR0_MP+CR0_NE
mov cr0, ecx
mov cr4, ebx
.clts:
clts
fninit
.set_cr:
mov edi, irq_tab
xor eax, eax
mov ecx, 16

268
kernel/trunk/proc32.inc Normal file
View File

@ -0,0 +1,268 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }