feat(asm&go4k): Rewrote both library & player to use text/template compiler

There is no more plain .asms, both library & player are created from the templates using go text/template package.
This commit is contained in:
Veikko Sariola
2020-12-14 15:46:12 +02:00
parent 2ad61ff6b2
commit d0bd877b3f
141 changed files with 1195 additions and 5542 deletions

View File

@ -1,113 +1,10 @@
; source file for compiling sointu as a library
%define SU_DISABLE_PLAYER
%include "sointu/header.inc"
; use every opcode
USE_ADD
USE_ADDP
USE_POP
USE_LOADNOTE
USE_MUL
USE_MULP
USE_PUSH
USE_XCH
USE_DISTORT
USE_HOLD
USE_CRUSH
USE_GAIN
USE_INVGAIN
USE_FILTER
USE_CLIP
USE_PAN
USE_DELAY
USE_COMPRES
USE_SPEED
USE_OUT
USE_OUTAUX
USE_AUX
USE_SEND
USE_ENVELOPE
USE_NOISE
USE_OSCILLAT
USE_LOAD_VAL
USE_RECEIVE
USE_IN
; include stereo variant of each opcode
%define INCLUDE_STEREO_ADD
%define INCLUDE_STEREO_ADDP
%define INCLUDE_STEREO_POP
%define INCLUDE_STEREO_LOADNOTE
%define INCLUDE_STEREO_MUL
%define INCLUDE_STEREO_MULP
%define INCLUDE_STEREO_PUSH
%define INCLUDE_STEREO_XCH
%define INCLUDE_STEREO_DISTORT
%define INCLUDE_STEREO_HOLD
%define INCLUDE_STEREO_CRUSH
%define INCLUDE_STEREO_GAIN
%define INCLUDE_STEREO_INVGAIN
%define INCLUDE_STEREO_FILTER
%define INCLUDE_STEREO_CLIP
%define INCLUDE_STEREO_PAN
%define INCLUDE_STEREO_DELAY
%define INCLUDE_STEREO_COMPRES
%define INCLUDE_STEREO_SPEED
%define INCLUDE_STEREO_OUT
%define INCLUDE_STEREO_OUTAUX
%define INCLUDE_STEREO_AUX
%define INCLUDE_STEREO_SEND
%define INCLUDE_STEREO_ENVELOPE
%define INCLUDE_STEREO_NOISE
%define INCLUDE_STEREO_OSCILLAT
%define INCLUDE_STEREO_LOADVAL
%define INCLUDE_STEREO_RECEIVE
%define INCLUDE_STEREO_IN
; include all features inside all opcodes
%define INCLUDE_TRISAW
%define INCLUDE_SINE
%define INCLUDE_PULSE
%define INCLUDE_GATE
%define INCLUDE_UNISONS
%define INCLUDE_POLYPHONY
%define INCLUDE_MULTIVOICE_TRACKS
%define INCLUDE_DELAY_MODULATION
%define INCLUDE_LOWPASS
%define INCLUDE_BANDPASS
%define INCLUDE_HIGHPASS
%define INCLUDE_NEGBANDPASS
%define INCLUDE_NEGHIGHPASS
%define INCLUDE_GLOBAL_SEND
%define INCLUDE_DELAY_NOTETRACKING
%define INCLUDE_DELAY_FLOAT_TIME
%ifidn __OUTPUT_FORMAT__,win32
%define INCLUDE_SAMPLES
%define INCLUDE_GMDLS
%endif
%ifidn __OUTPUT_FORMAT__,win64
%define INCLUDE_SAMPLES
%define INCLUDE_GMDLS
%endif
%include "sointu/footer.inc"
section .text
struc su_sampleoff
.start resd 1
.loopstart resw 1
.looplength resw 1
.size:
endstruc
{{template "structs.asm" .}}
struc su_synth
.synthwrk resb su_synthworkspace.size
.delaywrks resb su_delayline_wrk.size * 64
.synth_wrk resb su_synthworkspace.size
.delay_wrks resb su_delayline_wrk.size * 64
.delaytimes resw 768
.sampleoffs resb su_sampleoff.size * 256
.sampleoffs resb su_sample_offset.size * 256
.randseed resd 1
.globaltime resd 1
.commands resb 32 * 64
@ -116,189 +13,122 @@ struc su_synth
.numvoices resd 1
endstruc
SECT_TEXT(sursampl)
EXPORT MANGLE_FUNC(su_render,16)
%if BITS == 32 ; stdcall
pushad ; push registers
mov ecx, [esp + 4 + 32] ; ecx = &synthState
mov edx, [esp + 8 + 32] ; edx = &buffer
mov esi, [esp + 12 + 32] ; esi = &samples
mov ebx, [esp + 16 + 32] ; ebx = &time
%else
%ifidn __OUTPUT_FORMAT__,win64 ; win64 ABI: rcx = &synth, rdx = &buffer, r8 = &bufsize, r9 = &time
push_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile
mov rsi, r8 ; rsi = &samples
mov rbx, r9 ; rbx = &time
%else ; System V ABI: rdi = &synth, rsi = &buffer, rdx = &samples, rcx = &time
push_registers rbx, rbp ; System V ABI: these registers are non-volatile
mov rbx, rcx ; rbx points to time
xchg rsi, rdx ; rdx points to buffer, rsi points to samples
mov rcx, rdi ; rcx = &Synthstate
%endif
%endif
sub _SP,108 ; allocate space on stack for the FPU state
fsave [_SP] ; save the FPU state to stack & reset the FPU
push _SI ; push the pointer to samples
push _BX ; push the pointer to time
{{.ExportFunc "su_render" "SynthStateParam" "BufferPtrParam" "SamplesParam" "TimeParam"}}
{{- if .Amd64}}
{{- if eq .OS "windows"}}
{{- .PushRegs "rdi" "NonVolatileRDI" "rsi" "NonVolatileRSI" "rbx" "NonVolatileRBX" "rbp" "NonVolatileRBP" | indent 4}}
mov rsi, r8 ; rsi = &samples
mov rbx, r9 ; rbx = &time
{{- else}} ; SystemV amd64 ABI, linux mac or hopefully something similar
{{- .PushRegs "rbx" "NonVolatileRBX" "rbp" "NonVolatileRBP" | indent 4}}
mov rbx, rcx ; rbx points to time
xchg rsi, rdx ; rdx points to buffer, rsi points to samples
mov rcx, rdi ; rcx = &Synthstate
{{- end}}
{{- else}}
{{- .PushRegs | indent 4 }} ; push registers
mov ecx, [{{.Stack "SynthStateParam"}}] ; ecx = &synthState
mov edx, [{{.Stack "BufferPtrParam"}}] ; edx = &buffer
mov esi, [{{.Stack "SamplesParam"}}] ; esi = &samples
mov ebx, [{{.Stack "TimeParam"}}] ; ebx = &time
{{- end}}
{{.SaveFPUState | indent 4}} ; save the FPU state to stack & reset the FPU
{{.Push .SI "Samples"}}
{{.Push .BX "Time"}}
xor eax, eax ; samplenumber starts at 0
push _AX ; push samplenumber to stack
mov esi, [_SI] ; zero extend dereferenced pointer
push _SI ; push bufsize
push _DX ; push bufptr
push _CX ; this takes place of the voicetrack
lea _AX, [_CX + su_synth.sampleoffs]
push _AX
lea _AX, [_CX + su_synth.delaytimes]
push _AX
mov eax, [_CX + su_synth.randseed]
push _AX ; randseed
mov eax, [_CX + su_synth.globaltime]
push _AX ; global tick time
mov ebx, dword [_BX] ; zero extend dereferenced pointer
push _BX ; the nominal rowlength should be time_in
{{.Push .AX "BufSample"}}
mov esi, [{{.SI}}] ; zero extend dereferenced pointer
{{.Push .SI "BufSize"}}
{{.Push .DX "BufPtr"}}
{{.Push .CX "SynthState"}}
lea {{.AX}}, [{{.CX}} + su_synth.sampleoffs]
{{.Push .AX "SampleTable"}}
lea {{.AX}}, [{{.CX}} + su_synth.delaytimes]
{{.Push .AX "DelayTable"}}
mov eax, [{{.CX}} + su_synth.randseed]
{{.Push .AX "RandSeed"}}
mov eax, [{{.CX}} + su_synth.globaltime]
{{.Push .AX "GlobalTick"}}
mov ebx, dword [{{.BX}}] ; zero extend dereferenced pointer
{{.Push .BX "RowLength"}} ; the nominal rowlength should be time_in
xor eax, eax ; rowtick starts at 0
su_render_samples_loop:
push _DI
fnstsw [_SP] ; store the FPU status flag to stack top
pop _DI ; _DI = FPU status flag
and _DI, 0011100001000101b ; mask TOP pointer, stack error, zero divide and invalid operation
test _DI,_DI ; all the aforementioned bits should be 0!
push {{.DI}}
fnstsw [{{.SP}}] ; store the FPU status flag to stack top
pop {{.DI}} ; {{.DI}} = FPU status flag
and {{.DI}}, 0b0011100001000101 ; mask TOP pointer, stack error, zero divide and in{{.VAL}}id operation
test {{.DI}},{{.DI}} ; all the aforementioned bits should be 0!
jne su_render_samples_time_finish ; otherwise, we exit due to error
cmp eax, [_SP] ; if rowtick >= maxtime
cmp eax, [{{.Stack "RowLength"}}] ; if rowtick >= maxtime
jge su_render_samples_time_finish ; goto finish
mov ecx, [_SP + PTRSIZE*7] ; ecx = buffer length in samples
cmp [_SP + PTRSIZE*8], ecx ; if samples >= maxsamples
mov ecx, [{{.Stack "BufSize"}}] ; ecx = buffer length in samples
cmp [{{.Stack "BufSample"}}], ecx ; if samples >= maxsamples
jge su_render_samples_time_finish ; goto finish
inc eax ; time++
inc dword [_SP + PTRSIZE*8] ; samples++
mov _CX, [_SP + PTRSIZE*5]
push _AX ; push rowtick
mov eax, [_CX + su_synth.polyphony]
push _AX ;polyphony
mov eax, [_CX + su_synth.numvoices]
push _AX ;numvoices
lea _DX, [_CX+ su_synth.synthwrk]
lea COM, [_CX+ su_synth.commands]
lea VAL, [_CX+ su_synth.values]
lea WRK, [_DX + su_synthworkspace.voices]
lea _CX, [_CX+ su_synth.delaywrks - su_delayline_wrk.filtstate]
call MANGLE_FUNC(su_run_vm,0)
pop _AX
pop _AX
mov _DI, [_SP + PTRSIZE*7] ; edi containts buffer ptr
mov _CX, [_SP + PTRSIZE*6]
lea _SI, [_CX + su_synth.synthwrk + su_synthworkspace.left]
inc dword [{{.Stack "BufSample"}}] ; samples++
mov {{.CX}}, [{{.Stack "SynthState"}}]
{{.Push .AX "Sample"}}
mov eax, [{{.CX}} + su_synth.polyphony]
{{.Push .AX "PolyphonyBitmask"}}
mov eax, [{{.CX}} + su_synth.numvoices]
{{.Push .AX "VoicesRemain"}}
lea {{.DX}}, [{{.CX}}+ su_synth.synth_wrk]
lea {{.COM}}, [{{.CX}}+ su_synth.commands]
lea {{.VAL}}, [{{.CX}}+ su_synth.values]
lea {{.WRK}}, [{{.DX}} + su_synthworkspace.voices]
lea {{.CX}}, [{{.CX}}+ su_synth.delay_wrks - su_delayline_wrk.filtstate]
{{.Call "su_run_vm"}}
{{.Pop .AX}}
{{.Pop .AX}}
mov {{.DI}}, [{{.Stack "BufPtr"}}] ; edi containts buffer ptr
mov {{.CX}}, [{{.Stack "SynthState"}}]
lea {{.SI}}, [{{.CX}} + su_synth.synth_wrk + su_synthworkspace.left]
movsd ; copy left channel to output buffer
movsd ; copy right channel to output buffer
mov [_SP + PTRSIZE*7], _DI ; save back the updated ptr
lea _DI, [_SI-8]
mov [{{.Stack "BufPtr"}}], {{.DI}} ; save back the updated ptr
lea {{.DI}}, [{{.SI}}-8]
xor eax, eax
stosd ; clear left channel so the VM is ready to write them again
stosd ; clear right channel so the VM is ready to write them again
pop _AX
inc dword [_SP + PTRSIZE] ; increment global time, used by delays
{{.Pop .AX}}
inc dword [{{.Stack "GlobalTick"}}] ; increment global time, used by delays
jmp su_render_samples_loop
su_render_samples_time_finish:
pop _CX
pop _BX
pop _DX
pop _CX ; discard delaytimes ptr
pop _CX ; discard samplesoffs ptr
pop _CX
mov [_CX + su_synth.randseed], edx
mov [_CX + su_synth.globaltime], ebx
pop _BX
pop _BX
pop _DX
pop _BX ; pop the pointer to time
pop _SI ; pop the pointer to samples
mov dword [_SI], edx ; *samples = samples rendered
mov dword [_BX], eax ; *time = time ticks rendered
mov _AX,_DI ; _DI was the masked FPU status flag, _AX is return value
frstor [_SP] ; restore fpu state
add _SP,108 ; rewind the stack allocate for FPU state
%if BITS == 32 ; stdcall
mov [_SP + 28],eax ; we want to return eax, but popad pops everything, so put eax to stack for popad to pop
popad
ret 16
%else
%ifidn __OUTPUT_FORMAT__,win64
pop_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile
%else
pop_registers rbx, rbp ; System V ABI: these registers are non-volatile
%endif
{{.Pop .CX}}
{{.Pop .BX}}
{{.Pop .DX}}
{{.Pop .CX}}
{{.Pop .CX}}
{{.Pop .CX}}
mov [{{.CX}} + su_synth.randseed], edx
mov [{{.CX}} + su_synth.globaltime], ebx
{{.Pop .BX}}
{{.Pop .BX}}
{{.Pop .DX}}
{{.Pop .BX}}
{{.Pop .SI}}
mov dword [{{.SI}}], edx ; *samples = samples rendered
mov dword [{{.BX}}], eax ; *time = time ticks rendered
mov {{.AX}},{{.DI}} ; {{.DI}} was the masked FPU status flag, {{.AX}} is return {{.VAL}}ue
{{.LoadFPUState | indent 4}} ; load the FPU state from stack
{{- if .Amd64}}
{{- if eq .OS "windows"}}
{{- .PopRegs "rdi" "rsi" "rbx" "rbp" | indent 4}}
{{- else}} ; SystemV amd64 ABI, linux mac or hopefully something similar
{{- .PopRegs "rbx" "rbp" | indent 4}}
{{- end}}
ret
%endif
{{- else}}
mov [{{.Stack "eax"}}],eax ; we want to return eax, but popad pops everything, so put eax to stack for popad to pop
{{- .PopRegs | indent 4 }} ; popad
ret 16
{{- end}}
SECT_DATA(opcodeid)
; Arithmetic opcode ids
EXPORT MANGLE_DATA(su_add_id)
dd ADD_ID
EXPORT MANGLE_DATA(su_addp_id)
dd ADDP_ID
EXPORT MANGLE_DATA(su_pop_id)
dd POP_ID
EXPORT MANGLE_DATA(su_loadnote_id)
dd LOADNOTE_ID
EXPORT MANGLE_DATA(su_mul_id)
dd MUL_ID
EXPORT MANGLE_DATA(su_mulp_id)
dd MULP_ID
EXPORT MANGLE_DATA(su_push_id)
dd PUSH_ID
EXPORT MANGLE_DATA(su_xch_id)
dd XCH_ID
{{template "patch.asm" .}}
; Effect opcode ids
EXPORT MANGLE_DATA(su_distort_id)
dd DISTORT_ID
EXPORT MANGLE_DATA(su_hold_id)
dd HOLD_ID
EXPORT MANGLE_DATA(su_crush_id)
dd CRUSH_ID
EXPORT MANGLE_DATA(su_gain_id)
dd GAIN_ID
EXPORT MANGLE_DATA(su_invgain_id)
dd INVGAIN_ID
EXPORT MANGLE_DATA(su_filter_id)
dd FILTER_ID
EXPORT MANGLE_DATA(su_clip_id)
dd CLIP_ID
EXPORT MANGLE_DATA(su_pan_id)
dd PAN_ID
EXPORT MANGLE_DATA(su_delay_id)
dd DELAY_ID
EXPORT MANGLE_DATA(su_compres_id)
dd COMPRES_ID
; Flowcontrol opcode ids
EXPORT MANGLE_DATA(su_advance_id)
dd SU_ADVANCE_ID
EXPORT MANGLE_DATA(su_speed_id)
dd SPEED_ID
; Sink opcode ids
EXPORT MANGLE_DATA(su_out_id)
dd OUT_ID
EXPORT MANGLE_DATA(su_outaux_id)
dd OUTAUX_ID
EXPORT MANGLE_DATA(su_aux_id)
dd AUX_ID
EXPORT MANGLE_DATA(su_send_id)
dd SEND_ID
; Source opcode ids
EXPORT MANGLE_DATA(su_envelope_id)
dd ENVELOPE_ID
EXPORT MANGLE_DATA(su_noise_id)
dd NOISE_ID
EXPORT MANGLE_DATA(su_oscillat_id)
dd OSCILLAT_ID
EXPORT MANGLE_DATA(su_loadval_id)
dd LOADVAL_ID
EXPORT MANGLE_DATA(su_receive_id)
dd RECEIVE_ID
EXPORT MANGLE_DATA(su_in_id)
dd IN_ID
;-------------------------------------------------------------------------------
; Constants
;-------------------------------------------------------------------------------
{{.SectData "constants"}}
{{.Constants}}