1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-21 17:24:39 +00:00
kickc/src/test/ref/sandbox.asm

860 lines
15 KiB
NASM

.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label zp1 = $61
// #define zp1 *(byte *)0x61 -- allows "zp1" vs "*zp1" below -- not supported -- https://gitlab.com/camelot/kickc/issues/169
.label zp2 = $62
.label TIMEHI = $a1
.label TIMELO = $a2
.label VICBANK = $d018
main: {
.label __4 = 6
.label __13 = 6
.label __18 = 6
.label __19 = $11
.label __20 = 6
.label __21 = $f
.label v = 4
// test performance of 'div16u(10)'
// test performance of 'div10'
.label u = 2
// *VICBANK = 23
lda #$17
sta VICBANK
// *zp1 = 0
lda #0
sta zp1
sta.z v
sta.z v+1
lda #<$6e85
sta.z u
lda #>$6e85
sta.z u+1
__b1:
// for (*zp1 = 0; *zp1 < 10; ++*zp1)
lda zp1
cmp #$a
bcc __b2
// *zp1 = 0
lda #0
sta zp1
lda #<$6e85
sta.z u
lda #>$6e85
sta.z u+1
__b7:
// for (*zp1 = 0; *zp1 < 10; ++*zp1)
lda zp1
cmp #$a
bcc __b8
// }
rts
__b8:
// *TIMEHI = 0
lda #0
sta TIMEHI
// *TIMELO = 0
sta TIMELO
// *zp2 = 0
sta zp2
__b9:
// for (*zp2 = 0; *zp2 < 200; ++*zp2)
lda zp2
cmp #$c8
bcc __b10
// (word)*TIMEHI << 8
lda TIMEHI
sta.z __20
lda #0
sta.z __20+1
lda.z __13
sta.z __13+1
lda #0
sta.z __13
// ((word)*TIMEHI << 8) + (word)*TIMELO
lda TIMELO
sta.z __21
lda #0
sta.z __21+1
// myprintf(strTemp, "200 DIV10 : %5d,%4d IN %04d FRAMESm", u, v, ((word)*TIMEHI << 8) + (word)*TIMELO)
lda.z myprintf.w3
clc
adc.z __21
sta.z myprintf.w3
lda.z myprintf.w3+1
adc.z __21+1
sta.z myprintf.w3+1
lda #<str1
sta.z myprintf.str
lda #>str1
sta.z myprintf.str+1
jsr myprintf
// Print()
jsr Print
// u -= 1234
lda.z u
sec
sbc #<$4d2
sta.z u
lda.z u+1
sbc #>$4d2
sta.z u+1
// for (*zp1 = 0; *zp1 < 10; ++*zp1)
inc zp1
jmp __b7
__b10:
// div10(u)
jsr div10
// v = div10(u)
// for (*zp2 = 0; *zp2 < 200; ++*zp2)
inc zp2
jmp __b9
__b2:
// *TIMEHI = 0
lda #0
sta TIMEHI
// *TIMELO = 0
sta TIMELO
// *zp2 = 0
sta zp2
__b4:
// for (*zp2 = 0; *zp2 < 200; ++*zp2)
lda zp2
cmp #$c8
bcc __b5
// (word)*TIMEHI << 8
lda TIMEHI
sta.z __18
lda #0
sta.z __18+1
lda.z __4
sta.z __4+1
lda #0
sta.z __4
// ((word)*TIMEHI << 8) + (word)*TIMELO
lda TIMELO
sta.z __19
lda #0
sta.z __19+1
// myprintf(strTemp, "200 DIV16U: %5d,%4d IN %04d FRAMESm", u, v, ((word)*TIMEHI << 8) + (word)*TIMELO)
lda.z myprintf.w3
clc
adc.z __19
sta.z myprintf.w3
lda.z myprintf.w3+1
adc.z __19+1
sta.z myprintf.w3+1
// lower case letters in string literal are placed in string as 0x01-0x1A, should be 0x61-0x7A
// -- as a side-effect of above issue, we can use "m" for carriage return. The normal way is the escape code "\r" but that is not supported --
lda #<str
sta.z myprintf.str
lda #>str
sta.z myprintf.str+1
jsr myprintf
// Print()
jsr Print
// u -= 1234
lda.z u
sec
sbc #<$4d2
sta.z u
lda.z u+1
sbc #>$4d2
sta.z u+1
// for (*zp1 = 0; *zp1 < 10; ++*zp1)
inc zp1
jmp __b1
__b5:
// div16u(u, 10)
jsr div16u
// v = div16u(u, 10)
// for (*zp2 = 0; *zp2 < 200; ++*zp2)
inc zp2
jmp __b4
str: .text "200 DIV16U: %5d,%4d IN %04d FRAMESm"
.byte 0
str1: .text "200 DIV10 : %5d,%4d IN %04d FRAMESm"
.byte 0
}
// Performs division on two 16 bit unsigned ints
// Returns the quotient dividend/divisor.
// The remainder will be set into the global variable rem16u
// Implemented using simple binary division
// div16u(word zp(2) dividend)
div16u: {
.label divisor = $a
.label return = 4
.label dividend = 2
// divr16u(dividend, divisor, 0)
lda.z dividend
sta.z divr16u.dividend
lda.z dividend+1
sta.z divr16u.dividend+1
jsr divr16u
// divr16u(dividend, divisor, 0)
// }
rts
}
// Performs division on two 16 bit unsigned ints and an initial remainder
// Returns the quotient dividend/divisor.
// The final remainder will be set into the global variable rem16u
// Implemented using simple binary division
// divr16u(word zp($17) dividend, word zp(6) rem)
divr16u: {
.label rem = 6
.label dividend = $17
.label quotient = 4
.label return = 4
ldx #0
txa
sta.z quotient
sta.z quotient+1
sta.z rem
sta.z rem+1
__b1:
// rem = rem << 1
asl.z rem
rol.z rem+1
// >dividend
lda.z dividend+1
// >dividend & $80
and #$80
// if( (>dividend & $80) != 0 )
cmp #0
beq __b2
// rem = rem | 1
lda #1
ora.z rem
sta.z rem
__b2:
// dividend = dividend << 1
asl.z dividend
rol.z dividend+1
// quotient = quotient << 1
asl.z quotient
rol.z quotient+1
// if(rem>=divisor)
lda.z rem+1
cmp #>div16u.divisor
bcc __b3
bne !+
lda.z rem
cmp #<div16u.divisor
bcc __b3
!:
// quotient++;
inc.z quotient
bne !+
inc.z quotient+1
!:
// rem = rem - divisor
lda.z rem
sec
sbc #<div16u.divisor
sta.z rem
lda.z rem+1
sbc #>div16u.divisor
sta.z rem+1
__b3:
// for( char i : 0..15)
inx
cpx #$10
bne __b1
// }
rts
}
Print: {
// asm
// can this assembly be placed in a separate file and call it from the C code here?
ldy #0
loop:
lda strTemp,y
beq done
jsr $ffd2
iny
jmp loop
done:
// }
rts
}
// myprintf(byte* zp($17) str, word zp(2) w1, word zp(4) w2, word zp(6) w3)
myprintf: {
.label str = $17
.label bDigits = $d
.label bLen = $e
// formats
.label b = $c
.label bArg = 9
.label w1 = 2
.label w2 = 4
.label w3 = 6
.label w = $f
.label bFormat = 8
.label bTrailing = $a
.label bLeadZero = $b
lda #0
sta.z bLeadZero
sta.z bDigits
sta.z bTrailing
sta.z w
sta.z w+1
sta.z bArg
sta.z bLen
sta.z bFormat
__b1:
// for (; *str != 0; ++str)
ldy #0
lda (str),y
cmp #0
bne __b2
// dst[bLen] = 0
tya
ldy.z bLen
sta strTemp,y
// }
rts
__b2:
// b = *str
ldy #0
lda (str),y
tax
// if (bFormat != 0)
lda.z bFormat
cmp #0
bne !__b4+
jmp __b4
!__b4:
// if (b == '0')
cpx #'0'
bne __b5
lda #1
sta.z bLeadZero
__b32:
// for (; *str != 0; ++str)
inc.z str
bne !+
inc.z str+1
!:
jmp __b1
__b5:
// if (b >= '1' && b <= '9')
cpx #'1'
bcc __b6
cpx #'9'
bcs !__b28+
jmp __b28
!__b28:
bne !__b28+
jmp __b28
!__b28:
__b6:
// if (b == '-')
cpx #'-'
bne __b7
lda #1
sta.z bTrailing
jmp __b32
__b7:
// if (b == 'c')
cpx #'c'
bne !__b8+
jmp __b8
!__b8:
// if (b == 'd')
cpx #'d'
beq __b9
// if (b == 'x' || b == 'X')
cpx #'x'
beq __b31
cpx #'X'
beq __b31
__b3:
lda #0
sta.z bFormat
jmp __b32
__b31:
// (byte)w >> 4
lda.z w
lsr
lsr
lsr
lsr
// b = ((byte)w >> 4) & 0xF
ldx #$f
axs #0
// b < 10 ? '0' : 0x57
cpx #$a
bcc __b10
lda #$57
jmp __b11
__b10:
// b < 10 ? '0' : 0x57
lda #'0'
__b11:
// (b < 10 ? '0' : 0x57) + b
stx.z $ff
clc
adc.z $ff
// dst[bLen++] = (b < 10 ? '0' : 0x57) + b
ldy.z bLen
sta strTemp,y
// dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
iny
// (byte)w & 0xF
lda.z w
// b = (byte)w & 0xF
ldx #$f
axs #0
// b < 10 ? '0' : 0x57
cpx #$a
bcc __b12
lda #$57
jmp __b13
__b12:
// b < 10 ? '0' : 0x57
lda #'0'
__b13:
// (b < 10 ? '0' : 0x57) + b
stx.z $ff
clc
adc.z $ff
// dst[bLen++] = (b < 10 ? '0' : 0x57) + b
sta strTemp,y
// dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
iny
sty.z bLen
jmp __b3
__b9:
// utoa(w, buf6)
lda.z w
sta.z utoa.value
lda.z w+1
sta.z utoa.value+1
jsr utoa
lda #1
sta.z b
__b14:
// while(buf6[b] != 0)
ldy.z b
lda buf6,y
cmp #0
bne __b15
// if (bTrailing == 0 && bDigits > b)
lda.z bTrailing
cmp #0
bne __b17
tya
cmp.z bDigits
bcs __b17
__b18:
// for (; bDigits > b; --bDigits)
lda.z b
cmp.z bDigits
bcc __b19
__b17:
ldx #0
__b22:
// for (digit = 0; digit < b; ++digit)
cpx.z b
bcc __b23
// if (bTrailing != 0 && bDigits > b)
lda.z bTrailing
cmp #0
beq __b3
lda.z b
cmp.z bDigits
bcc !__b3+
jmp __b3
!__b3:
__b25:
// for (; bDigits > b; --bDigits)
lda.z b
cmp.z bDigits
bcc __b26
jmp __b3
__b26:
// dst[bLen++] = ' '
lda #' '
ldy.z bLen
sta strTemp,y
// dst[bLen++] = ' ';
inc.z bLen
// for (; bDigits > b; --bDigits)
dec.z bDigits
jmp __b25
__b23:
// dst[bLen++] = buf6[digit]
lda buf6,x
ldy.z bLen
sta strTemp,y
// dst[bLen++] = buf6[digit];
inc.z bLen
// for (digit = 0; digit < b; ++digit)
inx
jmp __b22
__b19:
// (bLeadZero == 0) ? ' ' : '0'
lda.z bLeadZero
cmp #0
beq __b20
lda #'0'
jmp __b21
__b20:
// (bLeadZero == 0) ? ' ' : '0'
lda #' '
__b21:
// dst[bLen++] = (bLeadZero == 0) ? ' ' : '0'
ldy.z bLen
sta strTemp,y
// dst[bLen++] = (bLeadZero == 0) ? ' ' : '0';
inc.z bLen
// for (; bDigits > b; --bDigits)
dec.z bDigits
jmp __b18
__b15:
// ++b;
inc.z b
jmp __b14
__b8:
// dst[bLen++] = (byte)w
// "switch" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/170
ldy.z bLen
lda.z w
sta strTemp,y
// dst[bLen++] = (byte)w;
inc.z bLen
jmp __b3
__b28:
// bDigits = b - '0'
txa
axs #'0'
stx.z bDigits
jmp __b32
__b4:
// if (b == '%')
cpx #'%'
bne __b33
// if (bArg == 0)
// default format
//w = (bArg == 0) ? w1 : ((bArg == 1) ? w2 : w3); -- "?" is the normal way, but error "sequence does not contain all blocks" -- https://gitlab.com/camelot/kickc/issues/185 [FIXED]
lda.z bArg
cmp #0
beq __b34
// if (bArg == 1)
lda #1
cmp.z bArg
beq __b35
lda.z w3
sta.z w
lda.z w3+1
sta.z w+1
__b36:
// ++bArg;
inc.z bArg
lda #0
sta.z bLeadZero
lda #1
sta.z bDigits
lda #0
sta.z bTrailing
lda #1
sta.z bFormat
jmp __b32
__b35:
lda.z w2
sta.z w
lda.z w2+1
sta.z w+1
jmp __b36
__b34:
lda.z w1
sta.z w
lda.z w1+1
sta.z w+1
jmp __b36
__b33:
// if (b >= 0x41 && b <= 0x5A)
cpx #$41
bcc __b37
cpx #$5a+1
bcs __b37
// b += 0x20
txa
axs #-[$20]
__b37:
// dst[bLen++] = b
// swap 0x41 / 0x61 when in lower case mode
ldy.z bLen
txa
sta strTemp,y
// dst[bLen++] = b;
inc.z bLen
jmp __b32
buf6: .fill 6, 0
}
// utoa(word zp($11) value, byte* zp($13) dst)
utoa: {
.label value = $11
.label dst = $13
// if (bStarted == 1 || value >= 10000)
lda.z value+1
cmp #>$2710
bcc !+
beq !__b5+
jmp __b5
!__b5:
lda.z value
cmp #<$2710
bcc !__b5+
jmp __b5
!__b5:
!:
lda #<myprintf.buf6
sta.z dst
lda #>myprintf.buf6
sta.z dst+1
ldx #0
__b1:
// if (bStarted == 1 || value >= 1000)
cpx #1
beq __b6
lda.z value+1
cmp #>$3e8
bcc !+
bne __b6
lda.z value
cmp #<$3e8
bcs __b6
!:
__b2:
// if (bStarted == 1 || value >= 100)
cpx #1
beq __b7
lda.z value+1
bne __b7
lda.z value
cmp #$64
bcs __b7
!:
__b3:
// if (bStarted == 1 || value >= 10)
cpx #1
beq __b8
lda.z value+1
bne __b8
lda.z value
cmp #$a
bcs __b8
!:
__b4:
// '0' + (byte)value
lda.z value
clc
adc #'0'
// *dst++ = '0' + (byte)value
ldy #0
sta (dst),y
// *dst++ = '0' + (byte)value;
inc.z dst
bne !+
inc.z dst+1
!:
// *dst = 0
lda #0
tay
sta (dst),y
// }
rts
__b8:
// append(dst++, value, 10)
lda #<$a
sta.z append.sub
lda #>$a
sta.z append.sub+1
jsr append
// append(dst++, value, 10)
// value = append(dst++, value, 10)
// value = append(dst++, value, 10);
inc.z dst
bne !+
inc.z dst+1
!:
jmp __b4
__b7:
// append(dst++, value, 100)
lda #<$64
sta.z append.sub
lda #>$64
sta.z append.sub+1
jsr append
// append(dst++, value, 100)
// value = append(dst++, value, 100)
// value = append(dst++, value, 100);
inc.z dst
bne !+
inc.z dst+1
!:
ldx #1
jmp __b3
__b6:
// append(dst++, value, 1000)
lda #<$3e8
sta.z append.sub
lda #>$3e8
sta.z append.sub+1
jsr append
// append(dst++, value, 1000)
// value = append(dst++, value, 1000)
// value = append(dst++, value, 1000);
inc.z dst
bne !+
inc.z dst+1
!:
ldx #1
jmp __b2
__b5:
// append(dst++, value, 10000)
lda #<$2710
sta.z append.sub
lda #>$2710
sta.z append.sub+1
lda #<myprintf.buf6
sta.z append.dst
lda #>myprintf.buf6
sta.z append.dst+1
jsr append
// append(dst++, value, 10000)
// value = append(dst++, value, 10000)
lda #<myprintf.buf6+1
sta.z dst
lda #>myprintf.buf6+1
sta.z dst+1
ldx #1
jmp __b1
}
// simple 'utoa' without using multiply or divide
// append(byte* zp($13) dst, word zp($11) value, word zp($15) sub)
append: {
.label value = $11
.label return = $11
.label dst = $13
.label sub = $15
// *dst = '0'
lda #'0'
ldy #0
sta (dst),y
__b1:
// while (value >= sub)
lda.z sub+1
cmp.z value+1
bne !+
lda.z sub
cmp.z value
beq __b2
!:
bcc __b2
// }
rts
__b2:
// ++*dst;
ldy #0
lda (dst),y
clc
adc #1
sta (dst),y
// value -= sub
lda.z value
sec
sbc.z sub
sta.z value
lda.z value+1
sbc.z sub+1
sta.z value+1
jmp __b1
}
// div10(word zp($13) val)
div10: {
.label __0 = $13
.label __2 = $15
.label __3 = $17
.label __4 = 4
.label val = $13
.label val_1 = $15
.label val_2 = $17
.label val_3 = 4
.label return = 4
.label val_4 = 2
// val >> 1
lda.z val_4+1
lsr
sta.z __0+1
lda.z val_4
ror
sta.z __0
// val = (val >> 1) + 1
inc.z val
bne !+
inc.z val+1
!:
// val << 1
lda.z val
asl
sta.z __2
lda.z val+1
rol
sta.z __2+1
// val += val << 1
lda.z val_1
clc
adc.z val
sta.z val_1
lda.z val_1+1
adc.z val+1
sta.z val_1+1
// val >> 4
lsr
sta.z __3+1
lda.z val_1
ror
sta.z __3
lsr.z __3+1
ror.z __3
lsr.z __3+1
ror.z __3
lsr.z __3+1
ror.z __3
// val += val >> 4
lda.z val_2
clc
adc.z val_1
sta.z val_2
lda.z val_2+1
adc.z val_1+1
sta.z val_2+1
// val >> 8
sta.z __4
lda #0
sta.z __4+1
// val += val >> 8
lda.z val_3
clc
adc.z val_2
sta.z val_3
lda.z val_3+1
adc.z val_2+1
sta.z val_3+1
// val >> 4
lsr.z return+1
ror.z return
lsr.z return+1
ror.z return
lsr.z return+1
ror.z return
lsr.z return+1
ror.z return
// }
rts
}
// "char buf16[16]" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/162
strTemp: .fill $64, 0