1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00
kickc/src/test/ref/min-fmul-16.asm

335 lines
5.4 KiB
NASM

.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label RASTER = $d012
.label BORDERCOL = $d020
.label SCREEN = $400
.label print_char_cursor = 5
main: {
.label a = $4d2
.label b = $929
.label r = $e
jsr mulf_init
sei
lda #<$400
sta.z print_char_cursor
lda #>$400
sta.z print_char_cursor+1
b2:
lda #$ff
cmp RASTER
bne b2
inc BORDERCOL
jsr mulf16u
dec BORDERCOL
jsr print_dword
jsr print_set_screen
lda #<SCREEN
sta.z print_char_cursor
lda #>SCREEN
sta.z print_char_cursor+1
jmp b2
}
// Set the screen to print on. Also resets current line/char cursor.
print_set_screen: {
rts
}
// Print a dword as HEX
// print_dword(dword zeropage($e) dw)
print_dword: {
.label dw = $e
lda.z dw+2
sta.z print_word.w
lda.z dw+3
sta.z print_word.w+1
jsr print_word
lda.z dw
sta.z print_word.w
lda.z dw+1
sta.z print_word.w+1
jsr print_word
rts
}
// Print a word as HEX
// print_word(word zeropage(2) w)
print_word: {
.label w = 2
lda.z w+1
tax
jsr print_byte
lda.z w
tax
jsr print_byte
rts
}
// Print a byte as HEX
// print_byte(byte register(X) b)
print_byte: {
txa
lsr
lsr
lsr
lsr
tay
lda print_hextab,y
jsr print_char
lda #$f
axs #0
lda print_hextab,x
jsr print_char
rts
}
// Print a single char
// print_char(byte register(A) ch)
print_char: {
ldy #0
sta (print_char_cursor),y
inc.z print_char_cursor
bne !+
inc.z print_char_cursor+1
!:
rts
}
// Fast multiply two unsigned words to a double word result
// Done in assembler to utilize fast addition A+X
mulf16u: {
.label memA = $f8
.label memB = $fa
.label memR = $fc
.label return = $e
lda #<main.a
sta memA
lda #>main.a
sta memA+1
lda #<main.b
sta memB
lda #>main.b
sta memB+1
lda memA
sta sm1a+1
sta sm3a+1
sta sm5a+1
sta sm7a+1
eor #$ff
sta sm2a+1
sta sm4a+1
sta sm6a+1
sta sm8a+1
lda memA+1
sta sm1b+1
sta sm3b+1
sta sm5b+1
sta sm7b+1
eor #$ff
sta sm2b+1
sta sm4b+1
sta sm6b+1
sta sm8b+1
ldx memB
sec
sm1a:
lda mulf_sqr1_lo,x
sm2a:
sbc mulf_sqr2_lo,x
sta memR+0
sm3a:
lda mulf_sqr1_hi,x
sm4a:
sbc mulf_sqr2_hi,x
sta _AA+1
sec
sm1b:
lda mulf_sqr1_lo,x
sm2b:
sbc mulf_sqr2_lo,x
sta _cc+1
sm3b:
lda mulf_sqr1_hi,x
sm4b:
sbc mulf_sqr2_hi,x
sta _CC+1
ldx memB+1
sec
sm5a:
lda mulf_sqr1_lo,x
sm6a:
sbc mulf_sqr2_lo,x
sta _bb+1
sm7a:
lda mulf_sqr1_hi,x
sm8a:
sbc mulf_sqr2_hi,x
sta _BB+1
sec
sm5b:
lda mulf_sqr1_lo,x
sm6b:
sbc mulf_sqr2_lo,x
sta _dd+1
sm7b:
lda mulf_sqr1_hi,x
sm8b:
sbc mulf_sqr2_hi,x
sta memR+3
clc
_AA:
lda #0
_bb:
adc #0
sta memR+1
_BB:
lda #0
_CC:
adc #0
sta memR+2
bcc !+
inc memR+3
clc
!:
_cc:
lda #0
adc memR+1
sta memR+1
_dd:
lda #0
adc memR+2
sta memR+2
bcc !+
inc memR+3
!:
lda memR
sta.z return
lda memR+1
sta.z return+1
lda memR+2
sta.z return+2
lda memR+3
sta.z return+3
rts
}
// Initialize the mulf_sqr multiplication tables with f(x)=int(x*x/4)
mulf_init: {
.label c = 4
.label sqr1_hi = 5
.label sqr = $c
.label sqr1_lo = 2
.label sqr2_hi = 9
.label sqr2_lo = 7
.label dir = $b
ldx #0
lda #<mulf_sqr1_hi+1
sta.z sqr1_hi
lda #>mulf_sqr1_hi+1
sta.z sqr1_hi+1
txa
sta.z sqr
sta.z sqr+1
sta.z c
lda #<mulf_sqr1_lo+1
sta.z sqr1_lo
lda #>mulf_sqr1_lo+1
sta.z sqr1_lo+1
b1:
lda.z sqr1_lo+1
cmp #>mulf_sqr1_lo+$200
bne b2
lda.z sqr1_lo
cmp #<mulf_sqr1_lo+$200
bne b2
lda #$ff
sta.z dir
lda #<mulf_sqr2_hi
sta.z sqr2_hi
lda #>mulf_sqr2_hi
sta.z sqr2_hi+1
ldx #-1
lda #<mulf_sqr2_lo
sta.z sqr2_lo
lda #>mulf_sqr2_lo
sta.z sqr2_lo+1
b5:
lda.z sqr2_lo+1
cmp #>mulf_sqr2_lo+$1ff
bne b6
lda.z sqr2_lo
cmp #<mulf_sqr2_lo+$1ff
bne b6
// Set the very last value g(511) = f(256)
lda mulf_sqr1_lo+$100
sta mulf_sqr2_lo+$1ff
lda mulf_sqr1_hi+$100
sta mulf_sqr2_hi+$1ff
rts
b6:
lda mulf_sqr1_lo,x
ldy #0
sta (sqr2_lo),y
lda mulf_sqr1_hi,x
sta (sqr2_hi),y
inc.z sqr2_hi
bne !+
inc.z sqr2_hi+1
!:
txa
clc
adc.z dir
tax
cpx #0
bne b8
lda #1
sta.z dir
b8:
inc.z sqr2_lo
bne !+
inc.z sqr2_lo+1
!:
jmp b5
b2:
inc.z c
lda #1
and.z c
cmp #0
bne b3
inx
inc.z sqr
bne !+
inc.z sqr+1
!:
b3:
lda.z sqr
ldy #0
sta (sqr1_lo),y
lda.z sqr+1
sta (sqr1_hi),y
inc.z sqr1_hi
bne !+
inc.z sqr1_hi+1
!:
txa
clc
adc.z sqr
sta.z sqr
bcc !+
inc.z sqr+1
!:
inc.z sqr1_lo
bne !+
inc.z sqr1_lo+1
!:
jmp b1
}
print_hextab: .text "0123456789abcdef"
// mulf_sqr tables will contain f(x)=int(x*x/4) and g(x) = f(x-255).
// <f(x) = <(( x * x )/4)
.align $100
mulf_sqr1_lo: .fill $200, 0
// >f(x) = >(( x * x )/4)
.align $100
mulf_sqr1_hi: .fill $200, 0
// <g(x) = <((( x - 255) * ( x - 255 ))/4)
.align $100
mulf_sqr2_lo: .fill $200, 0
// >g(x) = >((( x - 255) * ( x - 255 ))/4)
.align $100
mulf_sqr2_hi: .fill $200, 0