mirror of
https://github.com/irmen/prog8.git
synced 2025-06-18 08:23:37 +00:00
Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
f1ee3b4e60 | |||
6395e39d63 | |||
2a6d9d7e31 | |||
32a7cd31da | |||
dd4a56cb5f | |||
d110d1cb5f | |||
48858019b7 | |||
aff6b1fca5 | |||
d260182ef3 | |||
e39a38b0d9 | |||
82d7179c92 | |||
f42746ba06 | |||
1f69deaccd | |||
ea8b7ab193 | |||
9938959026 | |||
d5e5485d2e | |||
97b9c8f320 | |||
35aebbc209 | |||
81f7419f70 | |||
2f951bd54d | |||
18f5963b09 | |||
836509c1d1 | |||
949d536e42 | |||
f69b17e165 | |||
49a0584c54 | |||
e21aa2c8f0 | |||
40071b1431 | |||
02e29e6990 | |||
e19de0901e | |||
137d506e42 | |||
90c4a26d52 | |||
f378a8997b | |||
1377bed988 | |||
8f9f947c42 | |||
37f6c2858f | |||
13d7f239ab | |||
a6f3c84e28 | |||
fe4e0e9835 |
@ -1,11 +1,11 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
// id "org.jetbrains.kotlin.jvm" version "1.4.0"
|
// id "org.jetbrains.kotlin.jvm" version "1.4.10"
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'org.jetbrains.dokka' version "0.9.18"
|
id 'org.jetbrains.dokka' version "0.9.18"
|
||||||
id 'com.github.johnrengelman.shadow' version '5.2.0'
|
id 'com.github.johnrengelman.shadow' version '5.2.0'
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
; --- low level floating point assembly routines for the C64
|
; --- low level floating point assembly routines for the C64
|
||||||
|
|
||||||
|
FL_ONE_const .byte 129 ; 1.0
|
||||||
|
FL_ZERO_const .byte 0,0,0,0,0 ; 0.0
|
||||||
|
|
||||||
|
floats_store_reg .byte 0 ; temp storage
|
||||||
|
|
||||||
|
|
||||||
ub2float .proc
|
ub2float .proc
|
||||||
; -- convert ubyte in SCRATCH_ZPB1 to float at address A/Y
|
; -- convert ubyte in SCRATCH_ZPB1 to float at address A/Y
|
||||||
; clobbers A, Y
|
; clobbers A, Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
sty P8ZP_SCRATCH_W2+1
|
sty P8ZP_SCRATCH_W2+1
|
||||||
ldy P8ZP_SCRATCH_B1
|
ldy P8ZP_SCRATCH_B1
|
||||||
@ -13,14 +18,14 @@ ub2float .proc
|
|||||||
_fac_to_mem ldx P8ZP_SCRATCH_W2
|
_fac_to_mem ldx P8ZP_SCRATCH_W2
|
||||||
ldy P8ZP_SCRATCH_W2+1
|
ldy P8ZP_SCRATCH_W2+1
|
||||||
jsr MOVMF
|
jsr MOVMF
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
b2float .proc
|
b2float .proc
|
||||||
; -- convert byte in SCRATCH_ZPB1 to float at address A/Y
|
; -- convert byte in SCRATCH_ZPB1 to float at address A/Y
|
||||||
; clobbers A, Y
|
; clobbers A, Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
sty P8ZP_SCRATCH_W2+1
|
sty P8ZP_SCRATCH_W2+1
|
||||||
lda P8ZP_SCRATCH_B1
|
lda P8ZP_SCRATCH_B1
|
||||||
@ -30,7 +35,7 @@ b2float .proc
|
|||||||
|
|
||||||
uw2float .proc
|
uw2float .proc
|
||||||
; -- convert uword in SCRATCH_ZPWORD1 to float at address A/Y
|
; -- convert uword in SCRATCH_ZPWORD1 to float at address A/Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
sty P8ZP_SCRATCH_W2+1
|
sty P8ZP_SCRATCH_W2+1
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
@ -41,7 +46,7 @@ uw2float .proc
|
|||||||
|
|
||||||
w2float .proc
|
w2float .proc
|
||||||
; -- convert word in SCRATCH_ZPWORD1 to float at address A/Y
|
; -- convert word in SCRATCH_ZPWORD1 to float at address A/Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
sty P8ZP_SCRATCH_W2+1
|
sty P8ZP_SCRATCH_W2+1
|
||||||
ldy P8ZP_SCRATCH_W1
|
ldy P8ZP_SCRATCH_W1
|
||||||
@ -54,7 +59,7 @@ stack_b2float .proc
|
|||||||
; -- b2float operating on the stack
|
; -- b2float operating on the stack
|
||||||
inx
|
inx
|
||||||
lda P8ESTACK_LO,x
|
lda P8ESTACK_LO,x
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr FREADSA
|
jsr FREADSA
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -64,7 +69,7 @@ stack_w2float .proc
|
|||||||
inx
|
inx
|
||||||
ldy P8ESTACK_LO,x
|
ldy P8ESTACK_LO,x
|
||||||
lda P8ESTACK_HI,x
|
lda P8ESTACK_HI,x
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr GIVAYF
|
jsr GIVAYF
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -73,7 +78,7 @@ stack_ub2float .proc
|
|||||||
; -- ub2float operating on the stack
|
; -- ub2float operating on the stack
|
||||||
inx
|
inx
|
||||||
lda P8ESTACK_LO,x
|
lda P8ESTACK_LO,x
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
tay
|
tay
|
||||||
lda #0
|
lda #0
|
||||||
jsr GIVAYF
|
jsr GIVAYF
|
||||||
@ -85,16 +90,16 @@ stack_uw2float .proc
|
|||||||
inx
|
inx
|
||||||
lda P8ESTACK_LO,x
|
lda P8ESTACK_LO,x
|
||||||
ldy P8ESTACK_HI,x
|
ldy P8ESTACK_HI,x
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr GIVUAYFAY
|
jsr GIVUAYFAY
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
stack_float2w .proc ; also used for float2b
|
stack_float2w .proc ; also used for float2b
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr AYINT
|
jsr AYINT
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
lda $64
|
lda $64
|
||||||
sta P8ESTACK_HI,x
|
sta P8ESTACK_HI,x
|
||||||
lda $65
|
lda $65
|
||||||
@ -105,9 +110,9 @@ stack_float2w .proc ; also used for float2b
|
|||||||
|
|
||||||
stack_float2uw .proc ; also used for float2ub
|
stack_float2uw .proc ; also used for float2ub
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr GETADR
|
jsr GETADR
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
sta P8ESTACK_HI,x
|
sta P8ESTACK_HI,x
|
||||||
tya
|
tya
|
||||||
sta P8ESTACK_LO,x
|
sta P8ESTACK_LO,x
|
||||||
@ -231,15 +236,15 @@ inc_var_f .proc
|
|||||||
; -- add 1 to float pointed to by A/Y
|
; -- add 1 to float pointed to by A/Y
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr MOVFM
|
jsr MOVFM
|
||||||
lda #<FL_FONE
|
lda #<FL_ONE_const
|
||||||
ldy #>FL_FONE
|
ldy #>FL_ONE_const
|
||||||
jsr FADD
|
jsr FADD
|
||||||
ldx P8ZP_SCRATCH_W1
|
ldx P8ZP_SCRATCH_W1
|
||||||
ldy P8ZP_SCRATCH_W1+1
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
jsr MOVMF
|
jsr MOVMF
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
@ -247,9 +252,9 @@ dec_var_f .proc
|
|||||||
; -- subtract 1 from float pointed to by A/Y
|
; -- subtract 1 from float pointed to by A/Y
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_W1+1
|
sty P8ZP_SCRATCH_W1+1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<FL_FONE
|
lda #<FL_ONE_const
|
||||||
ldy #>FL_FONE
|
ldy #>FL_ONE_const
|
||||||
jsr MOVFM
|
jsr MOVFM
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
ldy P8ZP_SCRATCH_W1+1
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
@ -257,7 +262,7 @@ dec_var_f .proc
|
|||||||
ldx P8ZP_SCRATCH_W1
|
ldx P8ZP_SCRATCH_W1
|
||||||
ldy P8ZP_SCRATCH_W1+1
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
jsr MOVMF
|
jsr MOVMF
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
@ -286,7 +291,7 @@ push_fac1_as_result .proc
|
|||||||
jsr MOVMF
|
jsr MOVMF
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
jmp push_float
|
jmp push_float
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
@ -298,21 +303,21 @@ pow_f .proc
|
|||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr pop_float
|
jsr pop_float
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr CONUPK ; fac2 = float1
|
jsr CONUPK ; fac2 = float1
|
||||||
lda #<fmath_float2
|
lda #<fmath_float2
|
||||||
ldy #>fmath_float2
|
ldy #>fmath_float2
|
||||||
jsr FPWR
|
jsr FPWR
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
div_f .proc
|
div_f .proc
|
||||||
; -- push f1/f2 on stack
|
; -- push f1/f2 on stack
|
||||||
jsr pop_2_floats_f2_in_fac1
|
jsr pop_2_floats_f2_in_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr FDIV
|
jsr FDIV
|
||||||
@ -322,7 +327,7 @@ div_f .proc
|
|||||||
add_f .proc
|
add_f .proc
|
||||||
; -- push f1+f2 on stack
|
; -- push f1+f2 on stack
|
||||||
jsr pop_2_floats_f2_in_fac1
|
jsr pop_2_floats_f2_in_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr FADD
|
jsr FADD
|
||||||
@ -332,7 +337,7 @@ add_f .proc
|
|||||||
sub_f .proc
|
sub_f .proc
|
||||||
; -- push f1-f2 on stack
|
; -- push f1-f2 on stack
|
||||||
jsr pop_2_floats_f2_in_fac1
|
jsr pop_2_floats_f2_in_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr FSUB
|
jsr FSUB
|
||||||
@ -342,7 +347,7 @@ sub_f .proc
|
|||||||
mul_f .proc
|
mul_f .proc
|
||||||
; -- push f1*f2 on stack
|
; -- push f1*f2 on stack
|
||||||
jsr pop_2_floats_f2_in_fac1
|
jsr pop_2_floats_f2_in_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<fmath_float1
|
lda #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr FMULT
|
jsr FMULT
|
||||||
@ -352,7 +357,7 @@ mul_f .proc
|
|||||||
neg_f .proc
|
neg_f .proc
|
||||||
; -- push -flt back on stack
|
; -- push -flt back on stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr NEGOP
|
jsr NEGOP
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -360,7 +365,7 @@ neg_f .proc
|
|||||||
abs_f .proc
|
abs_f .proc
|
||||||
; -- push abs(float) on stack (as float)
|
; -- push abs(float) on stack (as float)
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr ABS
|
jsr ABS
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -466,7 +471,7 @@ _return_true lda #1
|
|||||||
func_sin .proc
|
func_sin .proc
|
||||||
; -- push sin(f) back onto stack
|
; -- push sin(f) back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr SIN
|
jsr SIN
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -474,7 +479,7 @@ func_sin .proc
|
|||||||
func_cos .proc
|
func_cos .proc
|
||||||
; -- push cos(f) back onto stack
|
; -- push cos(f) back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr COS
|
jsr COS
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -482,7 +487,7 @@ func_cos .proc
|
|||||||
func_tan .proc
|
func_tan .proc
|
||||||
; -- push tan(f) back onto stack
|
; -- push tan(f) back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr TAN
|
jsr TAN
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -490,7 +495,7 @@ func_tan .proc
|
|||||||
func_atan .proc
|
func_atan .proc
|
||||||
; -- push atan(f) back onto stack
|
; -- push atan(f) back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr ATN
|
jsr ATN
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -498,7 +503,7 @@ func_atan .proc
|
|||||||
func_ln .proc
|
func_ln .proc
|
||||||
; -- push ln(f) back onto stack
|
; -- push ln(f) back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr LOG
|
jsr LOG
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -506,7 +511,7 @@ func_ln .proc
|
|||||||
func_log2 .proc
|
func_log2 .proc
|
||||||
; -- push log base 2, ln(f)/ln(2), back onto stack
|
; -- push log base 2, ln(f)/ln(2), back onto stack
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr LOG
|
jsr LOG
|
||||||
jsr MOVEF
|
jsr MOVEF
|
||||||
lda #<c64.FL_LOG2
|
lda #<c64.FL_LOG2
|
||||||
@ -518,7 +523,7 @@ func_log2 .proc
|
|||||||
|
|
||||||
func_sqrt .proc
|
func_sqrt .proc
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr SQR
|
jsr SQR
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -526,7 +531,7 @@ func_sqrt .proc
|
|||||||
func_rad .proc
|
func_rad .proc
|
||||||
; -- convert degrees to radians (d * pi / 180)
|
; -- convert degrees to radians (d * pi / 180)
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<_pi_div_180
|
lda #<_pi_div_180
|
||||||
ldy #>_pi_div_180
|
ldy #>_pi_div_180
|
||||||
jsr FMULT
|
jsr FMULT
|
||||||
@ -537,7 +542,7 @@ _pi_div_180 .byte 123, 14, 250, 53, 18 ; pi / 180
|
|||||||
func_deg .proc
|
func_deg .proc
|
||||||
; -- convert radians to degrees (d * (1/ pi * 180))
|
; -- convert radians to degrees (d * (1/ pi * 180))
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #<_one_over_pi_div_180
|
lda #<_one_over_pi_div_180
|
||||||
ldy #>_one_over_pi_div_180
|
ldy #>_one_over_pi_div_180
|
||||||
jsr FMULT
|
jsr FMULT
|
||||||
@ -547,7 +552,7 @@ _one_over_pi_div_180 .byte 134, 101, 46, 224, 211 ; 1 / (pi * 180)
|
|||||||
|
|
||||||
func_round .proc
|
func_round .proc
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr FADDH
|
jsr FADDH
|
||||||
jsr INT
|
jsr INT
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
@ -555,7 +560,7 @@ func_round .proc
|
|||||||
|
|
||||||
func_floor .proc
|
func_floor .proc
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr INT
|
jsr INT
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -563,7 +568,7 @@ func_floor .proc
|
|||||||
func_ceil .proc
|
func_ceil .proc
|
||||||
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
||||||
jsr pop_float_fac1
|
jsr pop_float_fac1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
ldx #<fmath_float1
|
ldx #<fmath_float1
|
||||||
ldy #>fmath_float1
|
ldy #>fmath_float1
|
||||||
jsr MOVMF
|
jsr MOVMF
|
||||||
@ -573,8 +578,8 @@ func_ceil .proc
|
|||||||
jsr FCOMP
|
jsr FCOMP
|
||||||
cmp #0
|
cmp #0
|
||||||
beq +
|
beq +
|
||||||
lda #<FL_FONE
|
lda #<FL_ONE_const
|
||||||
ldy #>FL_FONE
|
ldy #>FL_ONE_const
|
||||||
jsr FADD
|
jsr FADD
|
||||||
+ jmp push_fac1_as_result
|
+ jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
@ -630,7 +635,7 @@ func_max_f .proc
|
|||||||
ldy #>_largest_neg_float
|
ldy #>_largest_neg_float
|
||||||
_minmax_entry jsr MOVFM
|
_minmax_entry jsr MOVFM
|
||||||
jsr prog8_lib.pop_array_and_lengthmin1Y
|
jsr prog8_lib.pop_array_and_lengthmin1Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx floats_store_reg
|
||||||
- sty P8ZP_SCRATCH_REG
|
- sty P8ZP_SCRATCH_REG
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
ldy P8ZP_SCRATCH_W1+1
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
@ -650,6 +655,8 @@ _minmax_cmp cmp #255 ; modified
|
|||||||
dey
|
dey
|
||||||
cpy #255
|
cpy #255
|
||||||
bne -
|
bne -
|
||||||
|
ldx floats_store_reg
|
||||||
|
stx P8ZP_SCRATCH_REG
|
||||||
jmp push_fac1_as_result
|
jmp push_fac1_as_result
|
||||||
_largest_neg_float .byte 255,255,255,255,255 ; largest negative float -1.7014118345e+38
|
_largest_neg_float .byte 255,255,255,255,255 ; largest negative float -1.7014118345e+38
|
||||||
.pend
|
.pend
|
||||||
@ -665,11 +672,11 @@ _largest_pos_float .byte 255,127,255,255,255 ; largest positive float
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
func_sum_f .proc
|
func_sum_f .proc
|
||||||
lda #<ZERO
|
lda #<FL_ZERO_const
|
||||||
ldy #>ZERO
|
ldy #>FL_ZERO_const
|
||||||
jsr MOVFM
|
jsr MOVFM
|
||||||
jsr prog8_lib.pop_array_and_lengthmin1Y
|
jsr prog8_lib.pop_array_and_lengthmin1Y
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx floats_store_reg
|
||||||
- sty P8ZP_SCRATCH_REG
|
- sty P8ZP_SCRATCH_REG
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
ldy P8ZP_SCRATCH_W1+1
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
@ -685,7 +692,9 @@ func_sum_f .proc
|
|||||||
bcc -
|
bcc -
|
||||||
inc P8ZP_SCRATCH_W1+1
|
inc P8ZP_SCRATCH_W1+1
|
||||||
bne -
|
bne -
|
||||||
+ jmp push_fac1_as_result
|
+ ldx floats_store_reg
|
||||||
|
stx P8ZP_SCRATCH_REG
|
||||||
|
jmp push_fac1_as_result
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
sign_f .proc
|
sign_f .proc
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
;
|
;
|
||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
%target c64
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
|
|
||||||
c64flt {
|
c64flt {
|
||||||
; ---- this block contains C-64 floating point related functions ----
|
; ---- this block contains C-64 floating point related functions ----
|
||||||
|
|
||||||
const float PI = 3.141592653589793
|
const float PI = 3.141592653589793
|
||||||
const float TWOPI = 6.283185307179586
|
const float TWOPI = 6.283185307179586
|
||||||
const float ZERO = 0.0
|
|
||||||
|
|
||||||
|
|
||||||
; ---- C64 basic and kernal ROM float constants and functions ----
|
; ---- C64 basic and kernal ROM float constants and functions ----
|
||||||
@ -194,20 +194,20 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
|||||||
sub print_f (float value) {
|
sub print_f (float value) {
|
||||||
; ---- prints the floating point value (without a newline).
|
; ---- prints the floating point value (without a newline).
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx floats_store_reg
|
||||||
lda #<value
|
lda #<value
|
||||||
ldy #>value
|
ldy #>value
|
||||||
jsr MOVFM ; load float into fac1
|
jsr MOVFM ; load float into fac1
|
||||||
jsr FOUT ; fac1 to string in A/Y
|
jsr FOUT ; fac1 to string in A/Y
|
||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_REG
|
sty P8ZP_SCRATCH_W1+1
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda (P8ZP_SCRATCH_B1),y
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
beq +
|
beq +
|
||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
iny
|
iny
|
||||||
bne -
|
bne -
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx floats_store_reg
|
||||||
+ rts
|
+ rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
%target c64
|
||||||
%import c64textio
|
%import c64textio
|
||||||
|
|
||||||
; bitmap pixel graphics module for the C64
|
; bitmap pixel graphics module for the C64
|
||||||
@ -180,9 +181,7 @@ graphics {
|
|||||||
; @(addr) |= ormask[lsb(px) & 7]
|
; @(addr) |= ormask[lsb(px) & 7]
|
||||||
; }
|
; }
|
||||||
|
|
||||||
; TODO fix the use of X (or XY) as parameter so we can actually use this plot() routine
|
asmsub plot(uword plotx @XY, ubyte ploty @A) clobbers (A, X, Y) {
|
||||||
; calling it with a byte results in a compiler crash, calling it with word results in clobbering X register I think
|
|
||||||
asmsub plotXXX(uword plotx @XY, ubyte ploty @A) {
|
|
||||||
%asm {{
|
%asm {{
|
||||||
stx internal_plotx
|
stx internal_plotx
|
||||||
sty internal_plotx+1
|
sty internal_plotx+1
|
||||||
@ -190,12 +189,14 @@ graphics {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; for efficiency of internal algorithms here is the internal plot routine
|
||||||
|
; that takes the plotx coordinate in a separate variable instead of the XY register pair:
|
||||||
|
|
||||||
uword internal_plotx ; 0..319 ; separate 'parameter' for internal_plot()
|
uword internal_plotx ; 0..319 ; separate 'parameter' for internal_plot()
|
||||||
|
|
||||||
asmsub internal_plot(ubyte ploty @A) { ; internal_plotx is 16 bits 0 to 319... doesn't fit in a register
|
asmsub internal_plot(ubyte ploty @A) clobbers (A, X, Y) { ; internal_plotx is 16 bits 0 to 319... doesn't fit in a register
|
||||||
%asm {{
|
%asm {{
|
||||||
tay
|
tay
|
||||||
stx P8ZP_SCRATCH_REG_X
|
|
||||||
lda internal_plotx+1
|
lda internal_plotx+1
|
||||||
sta P8ZP_SCRATCH_W2+1
|
sta P8ZP_SCRATCH_W2+1
|
||||||
lsr a ; 0
|
lsr a ; 0
|
||||||
@ -219,8 +220,6 @@ graphics {
|
|||||||
lda (P8ZP_SCRATCH_W2),y
|
lda (P8ZP_SCRATCH_W2),y
|
||||||
ora _ormask,x
|
ora _ormask,x
|
||||||
sta (P8ZP_SCRATCH_W2),y
|
sta (P8ZP_SCRATCH_W2),y
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
;
|
;
|
||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
%target c64
|
||||||
|
|
||||||
c64 {
|
c64 {
|
||||||
&ubyte TIME_HI = $a0 ; software jiffy clock, hi byte
|
&ubyte TIME_HI = $a0 ; software jiffy clock, hi byte
|
||||||
@ -298,8 +299,6 @@ _irq_handler_init
|
|||||||
sta IRQ_SCRATCH_ZPB1
|
sta IRQ_SCRATCH_ZPB1
|
||||||
lda P8ZP_SCRATCH_REG
|
lda P8ZP_SCRATCH_REG
|
||||||
sta IRQ_SCRATCH_ZPREG
|
sta IRQ_SCRATCH_ZPREG
|
||||||
lda P8ZP_SCRATCH_REG_X
|
|
||||||
sta IRQ_SCRATCH_ZPREGX
|
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
sta IRQ_SCRATCH_ZPWORD1
|
sta IRQ_SCRATCH_ZPWORD1
|
||||||
lda P8ZP_SCRATCH_W1+1
|
lda P8ZP_SCRATCH_W1+1
|
||||||
@ -324,8 +323,6 @@ _irq_handler_end
|
|||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_B1
|
||||||
lda IRQ_SCRATCH_ZPREG
|
lda IRQ_SCRATCH_ZPREG
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
lda IRQ_SCRATCH_ZPREGX
|
|
||||||
sta P8ZP_SCRATCH_REG_X
|
|
||||||
lda IRQ_SCRATCH_ZPWORD1
|
lda IRQ_SCRATCH_ZPWORD1
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
lda IRQ_SCRATCH_ZPWORD1+1
|
lda IRQ_SCRATCH_ZPWORD1+1
|
||||||
@ -340,7 +337,6 @@ _irq_handler_end
|
|||||||
IRQ_X_REG .byte 0
|
IRQ_X_REG .byte 0
|
||||||
IRQ_SCRATCH_ZPB1 .byte 0
|
IRQ_SCRATCH_ZPB1 .byte 0
|
||||||
IRQ_SCRATCH_ZPREG .byte 0
|
IRQ_SCRATCH_ZPREG .byte 0
|
||||||
IRQ_SCRATCH_ZPREGX .byte 0
|
|
||||||
IRQ_SCRATCH_ZPWORD1 .word 0
|
IRQ_SCRATCH_ZPWORD1 .word 0
|
||||||
IRQ_SCRATCH_ZPWORD2 .word 0
|
IRQ_SCRATCH_ZPWORD2 .word 0
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
|
||||||
|
%target c64
|
||||||
%import c64lib
|
%import c64lib
|
||||||
%import conv
|
%import conv
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ asmsub scroll_left_full (ubyte alsocolors @ Pc) clobbers(A, Y) {
|
|||||||
; Carry flag determines if screen color data must be scrolled too
|
; Carry flag determines if screen color data must be scrolled too
|
||||||
|
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
bcs +
|
bcs +
|
||||||
jmp _scroll_screen
|
jmp _scroll_screen
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ _scroll_screen ; scroll the screen memory
|
|||||||
dey
|
dey
|
||||||
bpl -
|
bpl -
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -112,7 +113,7 @@ asmsub scroll_right_full (ubyte alsocolors @ Pc) clobbers(A) {
|
|||||||
; contents of the leftmost column are unchanged, you should clear/refill this yourself
|
; contents of the leftmost column are unchanged, you should clear/refill this yourself
|
||||||
; Carry flag determines if screen color data must be scrolled too
|
; Carry flag determines if screen color data must be scrolled too
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
bcs +
|
bcs +
|
||||||
jmp _scroll_screen
|
jmp _scroll_screen
|
||||||
|
|
||||||
@ -136,7 +137,7 @@ _scroll_screen ; scroll the screen memory
|
|||||||
dex
|
dex
|
||||||
bpl -
|
bpl -
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -146,7 +147,7 @@ asmsub scroll_up_full (ubyte alsocolors @ Pc) clobbers(A) {
|
|||||||
; contents of the bottom row are unchanged, you should refill/clear this yourself
|
; contents of the bottom row are unchanged, you should refill/clear this yourself
|
||||||
; Carry flag determines if screen color data must be scrolled too
|
; Carry flag determines if screen color data must be scrolled too
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
bcs +
|
bcs +
|
||||||
jmp _scroll_screen
|
jmp _scroll_screen
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ _scroll_screen ; scroll the screen memory
|
|||||||
dex
|
dex
|
||||||
bpl -
|
bpl -
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -180,7 +181,7 @@ asmsub scroll_down_full (ubyte alsocolors @ Pc) clobbers(A) {
|
|||||||
; contents of the top row are unchanged, you should refill/clear this yourself
|
; contents of the top row are unchanged, you should refill/clear this yourself
|
||||||
; Carry flag determines if screen color data must be scrolled too
|
; Carry flag determines if screen color data must be scrolled too
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
bcs +
|
bcs +
|
||||||
jmp _scroll_screen
|
jmp _scroll_screen
|
||||||
|
|
||||||
@ -204,7 +205,7 @@ _scroll_screen ; scroll the screen memory
|
|||||||
dex
|
dex
|
||||||
bpl -
|
bpl -
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -230,7 +231,7 @@ asmsub print (str text @ AY) clobbers(A,Y) {
|
|||||||
asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
|
asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
|
||||||
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
|
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr conv.ubyte2decimal
|
jsr conv.ubyte2decimal
|
||||||
pha
|
pha
|
||||||
tya
|
tya
|
||||||
@ -239,7 +240,7 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
|
|||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
txa
|
txa
|
||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -247,7 +248,7 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
|
|||||||
asmsub print_ub (ubyte value @ A) clobbers(A,Y) {
|
asmsub print_ub (ubyte value @ A) clobbers(A,Y) {
|
||||||
; ---- print the ubyte in A in decimal form, without left padding 0s
|
; ---- print the ubyte in A in decimal form, without left padding 0s
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr conv.ubyte2decimal
|
jsr conv.ubyte2decimal
|
||||||
_print_byte_digits
|
_print_byte_digits
|
||||||
pha
|
pha
|
||||||
@ -264,7 +265,7 @@ _print_byte_digits
|
|||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
_ones txa
|
_ones txa
|
||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -272,7 +273,7 @@ _ones txa
|
|||||||
asmsub print_b (byte value @ A) clobbers(A,Y) {
|
asmsub print_b (byte value @ A) clobbers(A,Y) {
|
||||||
; ---- print the byte in A in decimal form, without left padding 0s
|
; ---- print the byte in A in decimal form, without left padding 0s
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
pha
|
pha
|
||||||
cmp #0
|
cmp #0
|
||||||
bpl +
|
bpl +
|
||||||
@ -280,16 +281,14 @@ asmsub print_b (byte value @ A) clobbers(A,Y) {
|
|||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
+ pla
|
+ pla
|
||||||
jsr conv.byte2decimal
|
jsr conv.byte2decimal
|
||||||
jsr print_ub._print_byte_digits
|
jmp print_ub._print_byte_digits
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
|
||||||
rts
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||||
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
|
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
bcc +
|
bcc +
|
||||||
pha
|
pha
|
||||||
lda #'$'
|
lda #'$'
|
||||||
@ -299,7 +298,7 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
|||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
tya
|
tya
|
||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -307,7 +306,7 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
|||||||
asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||||
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
|
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_B1
|
||||||
bcc +
|
bcc +
|
||||||
lda #'%'
|
lda #'%'
|
||||||
@ -320,7 +319,7 @@ asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
|||||||
+ jsr c64.CHROUT
|
+ jsr c64.CHROUT
|
||||||
dey
|
dey
|
||||||
bne -
|
bne -
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -353,7 +352,7 @@ asmsub print_uwhex (uword value @ AY, ubyte prefix @ Pc) clobbers(A,Y) {
|
|||||||
asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
|
asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
|
||||||
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
|
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr conv.uword2decimal
|
jsr conv.uword2decimal
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda conv.uword2decimal.decTenThousands,y
|
- lda conv.uword2decimal.decTenThousands,y
|
||||||
@ -361,7 +360,7 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
|
|||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
iny
|
iny
|
||||||
bne -
|
bne -
|
||||||
+ ldx P8ZP_SCRATCH_REG_X
|
+ ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -369,9 +368,9 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
|
|||||||
asmsub print_uw (uword value @ AY) clobbers(A,Y) {
|
asmsub print_uw (uword value @ AY) clobbers(A,Y) {
|
||||||
; ---- print the uword in A/Y in decimal form, without left padding 0s
|
; ---- print the uword in A/Y in decimal form, without left padding 0s
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
jsr conv.uword2decimal
|
jsr conv.uword2decimal
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda conv.uword2decimal.decTenThousands,y
|
- lda conv.uword2decimal.decTenThousands,y
|
||||||
beq _allzero
|
beq _allzero
|
||||||
@ -545,11 +544,11 @@ _colormod sta $ffff ; modified
|
|||||||
asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) {
|
asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) {
|
||||||
; ---- safe wrapper around PLOT kernel routine, to save the X register.
|
; ---- safe wrapper around PLOT kernel routine, to save the X register.
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
tax
|
tax
|
||||||
clc
|
clc
|
||||||
jsr c64.PLOT
|
jsr c64.PLOT
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ asmsub byte2decimal (byte value @ A) -> ubyte @ Y, ubyte @ A, ubyte @ X {
|
|||||||
asmsub ubyte2hex (ubyte value @ A) -> ubyte @ A, ubyte @ Y {
|
asmsub ubyte2hex (ubyte value @ A) -> ubyte @ A, ubyte @ Y {
|
||||||
; ---- A to hex petscii string in AY (first hex char in A, second hex char in Y)
|
; ---- A to hex petscii string in AY (first hex char in A, second hex char in Y)
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
pha
|
pha
|
||||||
and #$0f
|
and #$0f
|
||||||
tax
|
tax
|
||||||
@ -225,7 +225,7 @@ asmsub ubyte2hex (ubyte value @ A) -> ubyte @ A, ubyte @ Y {
|
|||||||
lsr a
|
lsr a
|
||||||
tax
|
tax
|
||||||
lda _hex_digits,x
|
lda _hex_digits,x
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
|
|
||||||
_hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well
|
_hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
;
|
;
|
||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
%target cx16
|
||||||
%option enable_floats
|
%option enable_floats
|
||||||
|
|
||||||
c64flt {
|
c64flt {
|
||||||
; ---- this block contains C-64 floating point related functions ----
|
; ---- this block contains C-64 floating point related functions ----
|
||||||
|
|
||||||
const float PI = 3.141592653589793
|
const float PI = 3.141592653589793
|
||||||
const float TWOPI = 6.283185307179586
|
const float TWOPI = 6.283185307179586
|
||||||
const float ZERO = 0.0
|
|
||||||
|
|
||||||
|
|
||||||
; ---- ROM float functions ----
|
; ---- ROM float functions ----
|
||||||
@ -130,20 +130,20 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
|||||||
sub print_f (float value) {
|
sub print_f (float value) {
|
||||||
; ---- prints the floating point value (without a newline).
|
; ---- prints the floating point value (without a newline).
|
||||||
%asm {{
|
%asm {{
|
||||||
stx P8ZP_SCRATCH_REG_X
|
phx
|
||||||
lda #<value
|
lda #<value
|
||||||
ldy #>value
|
ldy #>value
|
||||||
jsr MOVFM ; load float into fac1
|
jsr MOVFM ; load float into fac1
|
||||||
jsr FOUT ; fac1 to string in A/Y
|
jsr FOUT ; fac1 to string in A/Y
|
||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_W1
|
||||||
sty P8ZP_SCRATCH_REG
|
sty P8ZP_SCRATCH_W1+1
|
||||||
ldy #0
|
ldy #0
|
||||||
- lda (P8ZP_SCRATCH_B1),y
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
beq +
|
beq +
|
||||||
jsr c64.CHROUT
|
jsr c64.CHROUT
|
||||||
iny
|
iny
|
||||||
bne -
|
bne -
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
plx
|
||||||
+ rts
|
+ rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
;
|
;
|
||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
%target cx16
|
||||||
|
|
||||||
|
|
||||||
c64 {
|
c64 {
|
||||||
|
|
||||||
@ -14,42 +16,42 @@ c64 {
|
|||||||
; CLEARSCR -> use screen.clear_screen
|
; CLEARSCR -> use screen.clear_screen
|
||||||
; HOMECRSR -> use screen.plot
|
; HOMECRSR -> use screen.plot
|
||||||
|
|
||||||
romsub $FF81 = CINT() clobbers(A,X,Y) ; (alias: SCINIT) initialize screen editor and video chip
|
romsub $FF81 = CINT() clobbers(A,X,Y) ; (alias: SCINIT) initialize screen editor and video chip
|
||||||
romsub $FF84 = IOINIT() clobbers(A, X) ; initialize I/O devices (CIA, SID, IRQ)
|
romsub $FF84 = IOINIT() clobbers(A, X) ; initialize I/O devices (CIA, SID, IRQ)
|
||||||
romsub $FF87 = RAMTAS() clobbers(A,X,Y) ; initialize RAM, tape buffer, screen
|
romsub $FF87 = RAMTAS() clobbers(A,X,Y) ; initialize RAM, tape buffer, screen
|
||||||
romsub $FF8A = RESTOR() clobbers(A,X,Y) ; restore default I/O vectors
|
romsub $FF8A = RESTOR() clobbers(A,X,Y) ; restore default I/O vectors
|
||||||
romsub $FF8D = VECTOR(uword userptr @ XY, ubyte dir @ Pc) clobbers(A,Y) ; read/set I/O vector table
|
romsub $FF8D = VECTOR(uword userptr @ XY, ubyte dir @ Pc) clobbers(A,Y) ; read/set I/O vector table
|
||||||
romsub $FF90 = SETMSG(ubyte value @ A) ; set Kernal message control flag
|
romsub $FF90 = SETMSG(ubyte value @ A) ; set Kernal message control flag
|
||||||
romsub $FF93 = SECOND(ubyte address @ A) clobbers(A) ; (alias: LSTNSA) send secondary address after LISTEN
|
romsub $FF93 = SECOND(ubyte address @ A) clobbers(A) ; (alias: LSTNSA) send secondary address after LISTEN
|
||||||
romsub $FF96 = TKSA(ubyte address @ A) clobbers(A) ; (alias: TALKSA) send secondary address after TALK
|
romsub $FF96 = TKSA(ubyte address @ A) clobbers(A) ; (alias: TALKSA) send secondary address after TALK
|
||||||
romsub $FF99 = MEMTOP(uword address @ XY, ubyte dir @ Pc) -> uword @ XY ; read/set top of memory pointer
|
romsub $FF99 = MEMTOP(uword address @ XY, ubyte dir @ Pc) -> uword @ XY ; read/set top of memory pointer
|
||||||
romsub $FF9C = MEMBOT(uword address @ XY, ubyte dir @ Pc) -> uword @ XY ; read/set bottom of memory pointer
|
romsub $FF9C = MEMBOT(uword address @ XY, ubyte dir @ Pc) -> uword @ XY ; read/set bottom of memory pointer
|
||||||
romsub $FF9F = SCNKEY() clobbers(A,X,Y) ; scan the keyboard
|
romsub $FF9F = SCNKEY() clobbers(A,X,Y) ; scan the keyboard
|
||||||
romsub $FFA2 = SETTMO(ubyte timeout @ A) ; set time-out flag for IEEE bus
|
romsub $FFA2 = SETTMO(ubyte timeout @ A) ; set time-out flag for IEEE bus
|
||||||
romsub $FFA5 = ACPTR() -> ubyte @ A ; (alias: IECIN) input byte from serial bus
|
romsub $FFA5 = ACPTR() -> ubyte @ A ; (alias: IECIN) input byte from serial bus
|
||||||
romsub $FFA8 = CIOUT(ubyte databyte @ A) ; (alias: IECOUT) output byte to serial bus
|
romsub $FFA8 = CIOUT(ubyte databyte @ A) ; (alias: IECOUT) output byte to serial bus
|
||||||
romsub $FFAB = UNTLK() clobbers(A) ; command serial bus device to UNTALK
|
romsub $FFAB = UNTLK() clobbers(A) ; command serial bus device to UNTALK
|
||||||
romsub $FFAE = UNLSN() clobbers(A) ; command serial bus device to UNLISTEN
|
romsub $FFAE = UNLSN() clobbers(A) ; command serial bus device to UNLISTEN
|
||||||
romsub $FFB1 = LISTEN(ubyte device @ A) clobbers(A) ; command serial bus device to LISTEN
|
romsub $FFB1 = LISTEN(ubyte device @ A) clobbers(A) ; command serial bus device to LISTEN
|
||||||
romsub $FFB4 = TALK(ubyte device @ A) clobbers(A) ; command serial bus device to TALK
|
romsub $FFB4 = TALK(ubyte device @ A) clobbers(A) ; command serial bus device to TALK
|
||||||
romsub $FFB7 = READST() -> ubyte @ A ; read I/O status word
|
romsub $FFB7 = READST() -> ubyte @ A ; read I/O status word
|
||||||
romsub $FFBA = SETLFS(ubyte logical @ A, ubyte device @ X, ubyte address @ Y) ; set logical file parameters
|
romsub $FFBA = SETLFS(ubyte logical @ A, ubyte device @ X, ubyte address @ Y) ; set logical file parameters
|
||||||
romsub $FFBD = SETNAM(ubyte namelen @ A, str filename @ XY) ; set filename parameters
|
romsub $FFBD = SETNAM(ubyte namelen @ A, str filename @ XY) ; set filename parameters
|
||||||
romsub $FFC0 = OPEN() clobbers(A,X,Y) ; (via 794 ($31A)) open a logical file
|
romsub $FFC0 = OPEN() clobbers(A,X,Y) ; (via 794 ($31A)) open a logical file
|
||||||
romsub $FFC3 = CLOSE(ubyte logical @ A) clobbers(A,X,Y) ; (via 796 ($31C)) close a logical file
|
romsub $FFC3 = CLOSE(ubyte logical @ A) clobbers(A,X,Y) ; (via 796 ($31C)) close a logical file
|
||||||
romsub $FFC6 = CHKIN(ubyte logical @ X) clobbers(A,X) ; (via 798 ($31E)) define an input channel
|
romsub $FFC6 = CHKIN(ubyte logical @ X) clobbers(A,X) ; (via 798 ($31E)) define an input channel
|
||||||
romsub $FFC9 = CHKOUT(ubyte logical @ X) clobbers(A,X) ; (via 800 ($320)) define an output channel
|
romsub $FFC9 = CHKOUT(ubyte logical @ X) clobbers(A,X) ; (via 800 ($320)) define an output channel
|
||||||
romsub $FFCC = CLRCHN() clobbers(A,X) ; (via 802 ($322)) restore default devices
|
romsub $FFCC = CLRCHN() clobbers(A,X) ; (via 802 ($322)) restore default devices
|
||||||
romsub $FFCF = CHRIN() clobbers(Y) -> ubyte @ A ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read.
|
romsub $FFCF = CHRIN() clobbers(Y) -> ubyte @ A ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read.
|
||||||
romsub $FFD2 = CHROUT(ubyte char @ A) ; (via 806 ($326)) output a character
|
romsub $FFD2 = CHROUT(ubyte char @ A) ; (via 806 ($326)) output a character
|
||||||
romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> ubyte @Pc, ubyte @ A, ubyte @ X, ubyte @ Y ; (via 816 ($330)) load from device
|
romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> ubyte @Pc, ubyte @ A, ubyte @ X, ubyte @ Y ; (via 816 ($330)) load from device
|
||||||
romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> ubyte @ Pc, ubyte @ A ; (via 818 ($332)) save to a device
|
romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> ubyte @ Pc, ubyte @ A ; (via 818 ($332)) save to a device
|
||||||
romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock
|
romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock
|
||||||
romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock
|
romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock
|
||||||
romsub $FFE1 = STOP() clobbers(A,X) -> ubyte @ Pz, ubyte @ Pc ; (via 808 ($328)) check the STOP key
|
romsub $FFE1 = STOP() clobbers(A,X) -> ubyte @ Pz, ubyte @ Pc ; (via 808 ($328)) check the STOP key
|
||||||
romsub $FFE4 = GETIN() clobbers(X,Y) -> ubyte @ A ; (via 810 ($32A)) get a character
|
romsub $FFE4 = GETIN() clobbers(X,Y) -> ubyte @ A ; (via 810 ($32A)) get a character
|
||||||
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
|
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
|
||||||
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
|
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
|
||||||
romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns
|
romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns
|
||||||
romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, ubyte dir @ Pc) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use screen.plot for a 'safe' wrapper that preserves X.
|
romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, ubyte dir @ Pc) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use screen.plot for a 'safe' wrapper that preserves X.
|
||||||
romsub $FFF3 = IOBASE() -> uword @ XY ; read base address of I/O devices
|
romsub $FFF3 = IOBASE() -> uword @ XY ; read base address of I/O devices
|
||||||
@ -58,8 +60,11 @@ romsub $FFF3 = IOBASE() -> uword @ XY ; read base addr
|
|||||||
|
|
||||||
cx16 {
|
cx16 {
|
||||||
|
|
||||||
; ---- Commander X-16 additions on top of C64 kernal routines ----
|
; 65c02 hardware vectors:
|
||||||
; spelling of the names is taken from the Commander X-16 rom sources
|
&uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in
|
||||||
|
&uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in
|
||||||
|
&uword IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in
|
||||||
|
|
||||||
|
|
||||||
; the sixteen virtual 16-bit registers
|
; the sixteen virtual 16-bit registers
|
||||||
&uword r0 = $02
|
&uword r0 = $02
|
||||||
@ -82,116 +87,159 @@ cx16 {
|
|||||||
; VERA registers
|
; VERA registers
|
||||||
|
|
||||||
const uword VERA_BASE = $9F20
|
const uword VERA_BASE = $9F20
|
||||||
&uword VERA_ADDR_L = VERA_BASE + $00
|
&ubyte VERA_ADDR_L = VERA_BASE + $00
|
||||||
&uword VERA_ADDR_M = VERA_BASE + $01
|
&ubyte VERA_ADDR_M = VERA_BASE + $01
|
||||||
&uword VERA_ADDR_H = VERA_BASE + $02
|
&ubyte VERA_ADDR_H = VERA_BASE + $02
|
||||||
&uword VERA_DATA0 = VERA_BASE + $03
|
&ubyte VERA_DATA0 = VERA_BASE + $03
|
||||||
&uword VERA_DATA1 = VERA_BASE + $04
|
&ubyte VERA_DATA1 = VERA_BASE + $04
|
||||||
&uword VERA_CTRL = VERA_BASE + $05
|
&ubyte VERA_CTRL = VERA_BASE + $05
|
||||||
&uword VERA_IEN = VERA_BASE + $06
|
&ubyte VERA_IEN = VERA_BASE + $06
|
||||||
&uword VERA_ISR = VERA_BASE + $07
|
&ubyte VERA_ISR = VERA_BASE + $07
|
||||||
&uword VERA_IRQ_LINE_L = VERA_BASE + $08
|
&ubyte VERA_IRQ_LINE_L = VERA_BASE + $08
|
||||||
&uword VERA_DC_VIDEO = VERA_BASE + $09
|
&ubyte VERA_DC_VIDEO = VERA_BASE + $09
|
||||||
&uword VERA_DC_HSCALE = VERA_BASE + $0A
|
&ubyte VERA_DC_HSCALE = VERA_BASE + $0A
|
||||||
&uword VERA_DC_VSCALE = VERA_BASE + $0B
|
&ubyte VERA_DC_VSCALE = VERA_BASE + $0B
|
||||||
&uword VERA_DC_BORDER = VERA_BASE + $0C
|
&ubyte VERA_DC_BORDER = VERA_BASE + $0C
|
||||||
&uword VERA_DC_HSTART = VERA_BASE + $09
|
&ubyte VERA_DC_HSTART = VERA_BASE + $09
|
||||||
&uword VERA_DC_HSTOP = VERA_BASE + $0A
|
&ubyte VERA_DC_HSTOP = VERA_BASE + $0A
|
||||||
&uword VERA_DC_VSTART = VERA_BASE + $0B
|
&ubyte VERA_DC_VSTART = VERA_BASE + $0B
|
||||||
&uword VERA_DC_VSTOP = VERA_BASE + $0C
|
&ubyte VERA_DC_VSTOP = VERA_BASE + $0C
|
||||||
&uword VERA_L0_CONFIG = VERA_BASE + $0D
|
&ubyte VERA_L0_CONFIG = VERA_BASE + $0D
|
||||||
&uword VERA_L0_MAPBASE = VERA_BASE + $0E
|
&ubyte VERA_L0_MAPBASE = VERA_BASE + $0E
|
||||||
&uword VERA_L0_TILEBASE = VERA_BASE + $0F
|
&ubyte VERA_L0_TILEBASE = VERA_BASE + $0F
|
||||||
&uword VERA_L0_HSCROLL_L = VERA_BASE + $10
|
&ubyte VERA_L0_HSCROLL_L = VERA_BASE + $10
|
||||||
&uword VERA_L0_HSCROLL_H = VERA_BASE + $11
|
&ubyte VERA_L0_HSCROLL_H = VERA_BASE + $11
|
||||||
&uword VERA_L0_VSCROLL_L = VERA_BASE + $12
|
&ubyte VERA_L0_VSCROLL_L = VERA_BASE + $12
|
||||||
&uword VERA_L0_VSCROLL_H = VERA_BASE + $13
|
&ubyte VERA_L0_VSCROLL_H = VERA_BASE + $13
|
||||||
&uword VERA_L1_CONFIG = VERA_BASE + $14
|
&ubyte VERA_L1_CONFIG = VERA_BASE + $14
|
||||||
&uword VERA_L1_MAPBASE = VERA_BASE + $15
|
&ubyte VERA_L1_MAPBASE = VERA_BASE + $15
|
||||||
&uword VERA_L1_TILEBASE = VERA_BASE + $16
|
&ubyte VERA_L1_TILEBASE = VERA_BASE + $16
|
||||||
&uword VERA_L1_HSCROLL_L = VERA_BASE + $17
|
&ubyte VERA_L1_HSCROLL_L = VERA_BASE + $17
|
||||||
&uword VERA_L1_HSCROLL_H = VERA_BASE + $18
|
&ubyte VERA_L1_HSCROLL_H = VERA_BASE + $18
|
||||||
&uword VERA_L1_VSCROLL_L = VERA_BASE + $19
|
&ubyte VERA_L1_VSCROLL_L = VERA_BASE + $19
|
||||||
&uword VERA_L1_VSCROLL_H = VERA_BASE + $1A
|
&ubyte VERA_L1_VSCROLL_H = VERA_BASE + $1A
|
||||||
&uword VERA_AUDIO_CTRL = VERA_BASE + $1B
|
&ubyte VERA_AUDIO_CTRL = VERA_BASE + $1B
|
||||||
&uword VERA_AUDIO_RATE = VERA_BASE + $1C
|
&ubyte VERA_AUDIO_RATE = VERA_BASE + $1C
|
||||||
&uword VERA_AUDIO_DATA = VERA_BASE + $1D
|
&ubyte VERA_AUDIO_DATA = VERA_BASE + $1D
|
||||||
&uword VERA_SPI_DATA = VERA_BASE + $1E
|
&ubyte VERA_SPI_DATA = VERA_BASE + $1E
|
||||||
&uword VERA_SPI_CTRL = VERA_BASE + $1F
|
&ubyte VERA_SPI_CTRL = VERA_BASE + $1F
|
||||||
; VERA_PSG_BASE = $1F9C0
|
; VERA_PSG_BASE = $1F9C0
|
||||||
; VERA_PALETTE_BASE = $1FA00
|
; VERA_PALETTE_BASE = $1FA00
|
||||||
; VERA_SPRITES_BASE = $1FC00
|
; VERA_SPRITES_BASE = $1FC00
|
||||||
|
|
||||||
|
; I/O
|
||||||
|
|
||||||
|
const uword via1 = $9f60 ;VIA 6522 #1
|
||||||
|
&ubyte d1prb = via1+0
|
||||||
|
&ubyte d1pra = via1+1
|
||||||
|
&ubyte d1ddrb = via1+2
|
||||||
|
&ubyte d1ddra = via1+3
|
||||||
|
&ubyte d1t1l = via1+4
|
||||||
|
&ubyte d1t1h = via1+5
|
||||||
|
&ubyte d1t1ll = via1+6
|
||||||
|
&ubyte d1t1lh = via1+7
|
||||||
|
&ubyte d1t2l = via1+8
|
||||||
|
&ubyte d1t2h = via1+9
|
||||||
|
&ubyte d1sr = via1+10
|
||||||
|
&ubyte d1acr = via1+11
|
||||||
|
&ubyte d1pcr = via1+12
|
||||||
|
&ubyte d1ifr = via1+13
|
||||||
|
&ubyte d1ier = via1+14
|
||||||
|
&ubyte d1ora = via1+15
|
||||||
|
|
||||||
|
const uword via2 = $9f70 ;VIA 6522 #2
|
||||||
|
&ubyte d2prb =via2+0
|
||||||
|
&ubyte d2pra =via2+1
|
||||||
|
&ubyte d2ddrb =via2+2
|
||||||
|
&ubyte d2ddra =via2+3
|
||||||
|
&ubyte d2t1l =via2+4
|
||||||
|
&ubyte d2t1h =via2+5
|
||||||
|
&ubyte d2t1ll =via2+6
|
||||||
|
&ubyte d2t1lh =via2+7
|
||||||
|
&ubyte d2t2l =via2+8
|
||||||
|
&ubyte d2t2h =via2+9
|
||||||
|
&ubyte d2sr =via2+10
|
||||||
|
&ubyte d2acr =via2+11
|
||||||
|
&ubyte d2pcr =via2+12
|
||||||
|
&ubyte d2ifr =via2+13
|
||||||
|
&ubyte d2ier =via2+14
|
||||||
|
&ubyte d2ora =via2+15
|
||||||
|
|
||||||
|
|
||||||
|
; ---- Commander X-16 additions on top of C64 kernal routines ----
|
||||||
|
; spelling of the names is taken from the Commander X-16 rom sources
|
||||||
|
|
||||||
|
; TODO specify the correct clobbers for alle these functions, for simplicity all 3 regs are marked clobbered atm
|
||||||
|
|
||||||
; supported C128 additions
|
; supported C128 additions
|
||||||
romsub $ff4a = close_all()
|
romsub $ff4a = close_all() clobbers(A,X,Y)
|
||||||
romsub $ff59 = lkupla()
|
romsub $ff59 = lkupla() clobbers(A,X,Y)
|
||||||
romsub $ff5c = lkupsa()
|
romsub $ff5c = lkupsa() clobbers(A,X,Y)
|
||||||
romsub $ff5f = screen_set_mode(ubyte mode @A) clobbers(A, X, Y) -> ubyte @Pc
|
romsub $ff5f = screen_set_mode(ubyte mode @A) clobbers(A, X, Y) -> ubyte @Pc
|
||||||
romsub $ff62 = screen_set_charset(ubyte charset @A, uword charsetptr @XY) clobbers(A,X,Y) ; incompatible with C128 dlchr()
|
romsub $ff62 = screen_set_charset(ubyte charset @A, uword charsetptr @XY) clobbers(A,X,Y) ; incompatible with C128 dlchr()
|
||||||
romsub $ff65 = pfkey()
|
romsub $ff65 = pfkey() clobbers(A,X,Y)
|
||||||
romsub $ff6e = jsrfar()
|
romsub $ff6e = jsrfar() clobbers(A,X,Y)
|
||||||
romsub $ff74 = fetch()
|
romsub $ff74 = fetch() clobbers(A,X,Y)
|
||||||
romsub $ff77 = stash()
|
romsub $ff77 = stash() clobbers(A,X,Y)
|
||||||
romsub $ff7a = cmpare()
|
romsub $ff7a = cmpare() clobbers(A,X,Y)
|
||||||
romsub $ff7d = primm()
|
romsub $ff7d = primm() clobbers(A,X,Y)
|
||||||
|
|
||||||
; X16 additions
|
; X16 additions
|
||||||
romsub $ff44 = macptr()
|
romsub $ff44 = macptr() clobbers(A,X,Y)
|
||||||
romsub $ff47 = enter_basic(ubyte cold_or_warm @Pc)
|
romsub $ff47 = enter_basic(ubyte cold_or_warm @Pc) clobbers(A,X,Y)
|
||||||
romsub $ff68 = mouse_config(ubyte shape @A, ubyte scale @X) clobbers (A, X, Y)
|
romsub $ff68 = mouse_config(ubyte shape @A, ubyte scale @X) clobbers (A, X, Y)
|
||||||
romsub $ff6b = mouse_get(ubyte zpdataptr @X) clobbers(A)
|
romsub $ff6b = mouse_get(ubyte zpdataptr @X) clobbers(A)
|
||||||
romsub $ff71 = mouse_scan() clobbers(A, X, Y)
|
romsub $ff71 = mouse_scan() clobbers(A, X, Y)
|
||||||
romsub $ff53 = joystick_scan() clobbers(A, X, Y)
|
romsub $ff53 = joystick_scan() clobbers(A, X, Y)
|
||||||
romsub $ff56 = joystick_get(ubyte joynr @A) -> ubyte @A, ubyte @X, ubyte @Y
|
romsub $ff56 = joystick_get(ubyte joynr @A) -> ubyte @A, ubyte @X, ubyte @Y
|
||||||
romsub $ff4d = clock_set_date_time() clobbers(A, X, Y) ; args: r0, r1, r2, r3L
|
romsub $ff4d = clock_set_date_time() clobbers(A, X, Y) ; args: r0, r1, r2, r3L
|
||||||
romsub $ff50 = clock_get_date_time() clobbers(A) ; outout args: r0, r1, r2, r3L
|
romsub $ff50 = clock_get_date_time() clobbers(A) ; outout args: r0, r1, r2, r3L
|
||||||
|
|
||||||
; high level graphics & fonts
|
; high level graphics & fonts
|
||||||
romsub $ff20 = GRAPH_init() ; uses vectors=r0
|
romsub $ff20 = GRAPH_init() clobbers(A,X,Y) ; uses vectors=r0
|
||||||
romsub $ff23 = GRAPH_clear()
|
romsub $ff23 = GRAPH_clear() clobbers(A,X,Y)
|
||||||
romsub $ff26 = GRAPH_set_window() ; uses x=r0, y=r1, width=r2, height=r3
|
romsub $ff26 = GRAPH_set_window() clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3
|
||||||
romsub $ff29 = GRAPH_set_colors(ubyte stroke @A, ubyte fill @X, ubyte background @Y)
|
romsub $ff29 = GRAPH_set_colors(ubyte stroke @A, ubyte fill @X, ubyte background @Y) clobbers (A,X,Y)
|
||||||
romsub $ff2c = GRAPH_draw_line() ; uses x1=r0, y1=r1, x2=r2, y2=r3
|
romsub $ff2c = GRAPH_draw_line() clobbers(A,X,Y) ; uses x1=r0, y1=r1, x2=r2, y2=r3
|
||||||
romsub $ff2f = GRAPH_draw_rect(ubyte fill @Pc) ; uses x=r0, y=r1, width=r2, height=r3, cornerradius=r4
|
romsub $ff2f = GRAPH_draw_rect(ubyte fill @Pc) clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3, cornerradius=r4
|
||||||
romsub $ff32 = GRAPH_move_rect() ; uses sx=r0, sy=r1, tx=r2, ty=r3, width=r4, height=r5
|
romsub $ff32 = GRAPH_move_rect() clobbers(A,X,Y) ; uses sx=r0, sy=r1, tx=r2, ty=r3, width=r4, height=r5
|
||||||
romsub $ff35 = GRAPH_draw_oval(ubyte fill @Pc) ; uses x=r0, y=r1, width=r2, height=r3
|
romsub $ff35 = GRAPH_draw_oval(ubyte fill @Pc) clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3
|
||||||
romsub $ff38 = GRAPH_draw_image() ; uses x=r0, y=r1, ptr=r2, width=r3, height=r4
|
romsub $ff38 = GRAPH_draw_image() clobbers(A,X,Y) ; uses x=r0, y=r1, ptr=r2, width=r3, height=r4
|
||||||
romsub $ff3b = GRAPH_set_font() ; uses ptr=r0
|
romsub $ff3b = GRAPH_set_font() clobbers(A,X,Y) ; uses ptr=r0
|
||||||
romsub $ff3e = GRAPH_get_char_size(ubyte baseline @A, ubyte width @X, ubyte height_or_style @Y, ubyte is_control @Pc)
|
romsub $ff3e = GRAPH_get_char_size(ubyte baseline @A, ubyte width @X, ubyte height_or_style @Y, ubyte is_control @Pc) clobbers(A,X,Y)
|
||||||
romsub $ff41 = GRAPH_put_char(ubyte char @A) ; uses x=r0, y=r1
|
romsub $ff41 = GRAPH_put_char(ubyte char @A) clobbers(A,X,Y) ; uses x=r0, y=r1
|
||||||
|
|
||||||
; framebuffer
|
; framebuffer
|
||||||
romsub $fef6 = FB_init()
|
romsub $fef6 = FB_init() clobbers(A,X,Y)
|
||||||
romsub $fef9 = FB_get_info() -> byte @A ; also outputs width=r0, height=r1
|
romsub $fef9 = FB_get_info() clobbers(X,Y) -> byte @A ; also outputs width=r0, height=r1
|
||||||
romsub $fefc = FB_set_palette(ubyte index @A, ubyte bytecount @X) ; also uses pointer=r0
|
romsub $fefc = FB_set_palette(ubyte index @A, ubyte bytecount @X) clobbers(A,X,Y) ; also uses pointer=r0
|
||||||
romsub $feff = FB_cursor_position() ; uses x=r0, y=r1
|
romsub $feff = FB_cursor_position() clobbers(A,X,Y) ; uses x=r0, y=r1
|
||||||
romsub $ff02 = FB_cursor_next_line() ; uses x=r0
|
romsub $ff02 = FB_cursor_next_line() clobbers(A,X,Y) ; uses x=r0
|
||||||
romsub $ff05 = FB_get_pixel() -> ubyte @A
|
romsub $ff05 = FB_get_pixel() clobbers(X,Y) -> ubyte @A
|
||||||
romsub $ff08 = FB_get_pixels() ; uses ptr=r0, count=r1
|
romsub $ff08 = FB_get_pixels() clobbers(A,X,Y) ; uses ptr=r0, count=r1
|
||||||
romsub $ff0b = FB_set_pixel(ubyte color @A)
|
romsub $ff0b = FB_set_pixel(ubyte color @A) clobbers(A,X,Y)
|
||||||
romsub $ff0e = FB_set_pixels() ; uses ptr=r0, count=r1
|
romsub $ff0e = FB_set_pixels() clobbers(A,X,Y) ; uses ptr=r0, count=r1
|
||||||
romsub $ff11 = FB_set_8_pixels(ubyte pattern @A, ubyte color @X)
|
romsub $ff11 = FB_set_8_pixels(ubyte pattern @A, ubyte color @X) clobbers(A,X,Y)
|
||||||
romsub $ff14 = FB_set_8_pixels_opaque(ubyte pattern @A, ubyte color1 @X, ubyte color2 @Y) ; also uses mask=r0L
|
romsub $ff14 = FB_set_8_pixels_opaque(ubyte pattern @A, ubyte color1 @X, ubyte color2 @Y) clobbers(A,X,Y) ; also uses mask=r0L
|
||||||
romsub $ff17 = FB_fill_pixels(ubyte color @A) ; also uses count=r0, step=r1
|
romsub $ff17 = FB_fill_pixels(ubyte color @A) clobbers(A,X,Y) ; also uses count=r0, step=r1
|
||||||
romsub $ff1a = FB_filter_pixels() ; uses ptr=r0, count=r1
|
romsub $ff1a = FB_filter_pixels() clobbers(A,X,Y) ; uses ptr=r0, count=r1
|
||||||
romsub $ff1d = FB_move_pixels() ; uses sx=r0, sy=r1, tx=r2, ty=r3, count=r4
|
romsub $ff1d = FB_move_pixels() clobbers(A,X,Y) ; uses sx=r0, sy=r1, tx=r2, ty=r3, count=r4
|
||||||
|
|
||||||
; misc
|
; misc
|
||||||
romsub $fef0 = sprite_set_image(ubyte number @A, ubyte width @X, ubyte height @Y, ubyte apply_mask @Pc) -> ubyte @Pc ; also uses pixels=r0, mask=r1, bpp=r2L
|
romsub $fef0 = sprite_set_image(ubyte number @A, ubyte width @X, ubyte height @Y, ubyte apply_mask @Pc) clobbers(A,X,Y) -> ubyte @Pc ; also uses pixels=r0, mask=r1, bpp=r2L
|
||||||
romsub $fef3 = sprite_set_position(ubyte number @A) ; also uses x=r0 and y=r1
|
romsub $fef3 = sprite_set_position(ubyte number @A) clobbers(A,X,Y) ; also uses x=r0 and y=r1
|
||||||
romsub $fee4 = memory_fill(ubyte value @A) ; uses address=r0, num_bytes=r1
|
romsub $fee4 = memory_fill(ubyte value @A) clobbers(A,X,Y) ; uses address=r0, num_bytes=r1
|
||||||
romsub $fee7 = memory_copy() ; uses source=r0, target=r1, num_bytes=r2
|
romsub $fee7 = memory_copy() clobbers(A,X,Y) ; uses source=r0, target=r1, num_bytes=r2
|
||||||
romsub $feea = memory_crc() ; uses address=r0, num_bytes=r1 result->r2
|
romsub $feea = memory_crc() clobbers(A,X,Y) ; uses address=r0, num_bytes=r1 result->r2
|
||||||
romsub $feed = memory_decompress() ; uses input=r0, output=r1 result->r1
|
romsub $feed = memory_decompress() clobbers(A,X,Y) ; uses input=r0, output=r1 result->r1
|
||||||
romsub $fedb = console_init() ; uses x=r0, y=r1, width=r2, height=r3
|
romsub $fedb = console_init() clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3
|
||||||
romsub $fede = console_put_char(ubyte char @A, ubyte wrapping @Pc)
|
romsub $fede = console_put_char(ubyte char @A, ubyte wrapping @Pc) clobbers(A,X,Y)
|
||||||
romsub $fee1 = console_get_char() -> ubyte @A
|
romsub $fee1 = console_get_char() clobbers(X,Y) -> ubyte @A
|
||||||
romsub $fed8 = console_put_image() ; uses ptr=r0, width=r1, height=r2
|
romsub $fed8 = console_put_image() clobbers(A,X,Y) ; uses ptr=r0, width=r1, height=r2
|
||||||
romsub $fed5 = console_set_paging_message() ; uses messageptr=r0
|
romsub $fed5 = console_set_paging_message() clobbers(A,X,Y) ; uses messageptr=r0
|
||||||
romsub $fed2 = kbdbuf_put(ubyte key @A)
|
romsub $fed2 = kbdbuf_put(ubyte key @A) clobbers(A,X,Y)
|
||||||
romsub $fecf = entropy_get() -> ubyte @A, ubyte @X, ubyte @Y
|
romsub $fecf = entropy_get() -> ubyte @A, ubyte @X, ubyte @Y
|
||||||
romsub $fecc = monitor()
|
romsub $fecc = monitor() clobbers(A,X,Y)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -203,8 +251,11 @@ asmsub init_system() {
|
|||||||
%asm {{
|
%asm {{
|
||||||
sei
|
sei
|
||||||
cld
|
cld
|
||||||
stz $00
|
;stz $00
|
||||||
stz $01
|
;stz $01
|
||||||
|
;stz d1prb ; select rom bank 0
|
||||||
|
lda #$80
|
||||||
|
sta VERA_CTRL
|
||||||
jsr c64.IOINIT
|
jsr c64.IOINIT
|
||||||
jsr c64.RESTOR
|
jsr c64.RESTOR
|
||||||
jsr c64.CINT
|
jsr c64.CINT
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
;
|
;
|
||||||
; indent format: TABS, size=8
|
; indent format: TABS, size=8
|
||||||
|
|
||||||
|
%target cx16
|
||||||
%import cx16lib
|
%import cx16lib
|
||||||
%import conv
|
%import conv
|
||||||
|
|
||||||
@ -54,6 +54,36 @@ asmsub fill_screen (ubyte char @ A, ubyte txtcolor @ Y) clobbers(A) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asmsub clear_screenchars (ubyte char @ A) clobbers(Y) {
|
||||||
|
; ---- clear the character screen with the given fill character (leaves colors)
|
||||||
|
; (assumes screen matrix is at the default address)
|
||||||
|
%asm {{
|
||||||
|
pha
|
||||||
|
phx
|
||||||
|
jsr c64.SCREEN ; get dimensions in X/Y
|
||||||
|
dex
|
||||||
|
dey
|
||||||
|
txa
|
||||||
|
asl a
|
||||||
|
sta P8ZP_SCRATCH_B1
|
||||||
|
pla
|
||||||
|
- ldx P8ZP_SCRATCH_B1
|
||||||
|
- stz cx16.VERA_ADDR_H
|
||||||
|
stx cx16.VERA_ADDR_L
|
||||||
|
sty cx16.VERA_ADDR_M
|
||||||
|
sta cx16.VERA_DATA0
|
||||||
|
dex
|
||||||
|
dex
|
||||||
|
cpx #254
|
||||||
|
bne -
|
||||||
|
dey
|
||||||
|
bpl --
|
||||||
|
plx
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ubyte[16] color_to_charcode = [$90,$05,$1c,$9f,$9c,$1e,$1f,$9e,$81,$95,$96,$97,$98,$99,$9a,$9b]
|
ubyte[16] color_to_charcode = [$90,$05,$1c,$9f,$9c,$1e,$1f,$9e,$81,$95,$96,$97,$98,$99,$9a,$9b]
|
||||||
|
|
||||||
sub color (ubyte txtcol) {
|
sub color (ubyte txtcol) {
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
; http://codebase64.org/doku.php?id=base:6502_6510_maths
|
; http://codebase64.org/doku.php?id=base:6502_6510_maths
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
math_store_reg .byte 0 ; temporary storage
|
||||||
|
|
||||||
|
|
||||||
multiply_bytes .proc
|
multiply_bytes .proc
|
||||||
; -- multiply 2 bytes A and Y, result as byte in A (signed or unsigned)
|
; -- multiply 2 bytes A and Y, result as byte in A (signed or unsigned)
|
||||||
sta P8ZP_SCRATCH_B1 ; num1
|
sta P8ZP_SCRATCH_B1 ; num1
|
||||||
@ -31,7 +35,7 @@ multiply_bytes_16 .proc
|
|||||||
; -- multiply 2 bytes A and Y, result as word in A/Y (unsigned)
|
; -- multiply 2 bytes A and Y, result as word in A/Y (unsigned)
|
||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_B1
|
||||||
sty P8ZP_SCRATCH_REG
|
sty P8ZP_SCRATCH_REG
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx math_store_reg
|
||||||
lda #0
|
lda #0
|
||||||
ldx #8
|
ldx #8
|
||||||
lsr P8ZP_SCRATCH_B1
|
lsr P8ZP_SCRATCH_B1
|
||||||
@ -44,7 +48,7 @@ multiply_bytes_16 .proc
|
|||||||
bne -
|
bne -
|
||||||
tay
|
tay
|
||||||
lda P8ZP_SCRATCH_B1
|
lda P8ZP_SCRATCH_B1
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx math_store_reg
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
@ -57,7 +61,7 @@ multiply_words .proc
|
|||||||
|
|
||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
sty P8ZP_SCRATCH_W2+1
|
sty P8ZP_SCRATCH_W2+1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
|
|
||||||
mult16 lda #0
|
mult16 lda #0
|
||||||
sta result+2 ; clear upper bits of product
|
sta result+2 ; clear upper bits of product
|
||||||
@ -79,7 +83,7 @@ mult16 lda #0
|
|||||||
ror result
|
ror result
|
||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
|
|
||||||
result .byte 0,0,0,0
|
result .byte 0,0,0,0
|
||||||
@ -124,7 +128,7 @@ divmod_ub_asm .proc
|
|||||||
; division by zero will result in quotient = 255 and remainder = original number
|
; division by zero will result in quotient = 255 and remainder = original number
|
||||||
sty P8ZP_SCRATCH_REG
|
sty P8ZP_SCRATCH_REG
|
||||||
sta P8ZP_SCRATCH_B1
|
sta P8ZP_SCRATCH_B1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx math_store_reg
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
ldx #8
|
ldx #8
|
||||||
@ -137,7 +141,7 @@ divmod_ub_asm .proc
|
|||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
ldy P8ZP_SCRATCH_B1
|
ldy P8ZP_SCRATCH_B1
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx math_store_reg
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
@ -197,7 +201,7 @@ result = dividend ;save memory by reusing divident to store the result
|
|||||||
|
|
||||||
sta _divisor
|
sta _divisor
|
||||||
sty _divisor+1
|
sty _divisor+1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda #0 ;preset remainder to 0
|
lda #0 ;preset remainder to 0
|
||||||
sta remainder
|
sta remainder
|
||||||
sta remainder+1
|
sta remainder+1
|
||||||
@ -224,7 +228,7 @@ result = dividend ;save memory by reusing divident to store the result
|
|||||||
|
|
||||||
lda result
|
lda result
|
||||||
ldy result+1
|
ldy result+1
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
rts
|
rts
|
||||||
_divisor .word 0
|
_divisor .word 0
|
||||||
.pend
|
.pend
|
||||||
@ -308,7 +312,8 @@ _seed .word $2c9e
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
mul_byte_3 .proc
|
; ----------- optimized multiplications (stack) : ---------
|
||||||
|
stack_mul_byte_3 .proc
|
||||||
; X + X*2
|
; X + X*2
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -318,7 +323,7 @@ mul_byte_3 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_3 .proc
|
stack_mul_word_3 .proc
|
||||||
; W*2 + W
|
; W*2 + W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -335,7 +340,7 @@ mul_word_3 .proc
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
mul_byte_5 .proc
|
stack_mul_byte_5 .proc
|
||||||
; X*4 + X
|
; X*4 + X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -346,7 +351,7 @@ mul_byte_5 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_5 .proc
|
stack_mul_word_5 .proc
|
||||||
; W*4 + W
|
; W*4 + W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -365,7 +370,7 @@ mul_word_5 .proc
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
mul_byte_6 .proc
|
stack_mul_byte_6 .proc
|
||||||
; (X*2 + X)*2
|
; (X*2 + X)*2
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -376,7 +381,7 @@ mul_byte_6 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_6 .proc
|
stack_mul_word_6 .proc
|
||||||
; (W*2 + W)*2
|
; (W*2 + W)*2
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -394,7 +399,7 @@ mul_word_6 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_7 .proc
|
stack_mul_byte_7 .proc
|
||||||
; X*8 - X
|
; X*8 - X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -406,7 +411,7 @@ mul_byte_7 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_7 .proc
|
stack_mul_word_7 .proc
|
||||||
; W*8 - W
|
; W*8 - W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -426,7 +431,7 @@ mul_word_7 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_9 .proc
|
stack_mul_byte_9 .proc
|
||||||
; X*8 + X
|
; X*8 + X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -438,7 +443,7 @@ mul_byte_9 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_9 .proc
|
stack_mul_word_9 .proc
|
||||||
; W*8 + W
|
; W*8 + W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -458,7 +463,7 @@ mul_word_9 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_10 .proc
|
stack_mul_byte_10 .proc
|
||||||
; (X*4 + X)*2
|
; (X*4 + X)*2
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -470,7 +475,7 @@ mul_byte_10 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_10 .proc
|
stack_mul_word_10 .proc
|
||||||
; (W*4 + W)*2
|
; (W*4 + W)*2
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -490,7 +495,7 @@ mul_word_10 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_11 .proc
|
stack_mul_byte_11 .proc
|
||||||
; (X*2 + X)*4 - X
|
; (X*2 + X)*4 - X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -506,7 +511,7 @@ mul_byte_11 .proc
|
|||||||
|
|
||||||
; mul_word_11 is skipped (too much code)
|
; mul_word_11 is skipped (too much code)
|
||||||
|
|
||||||
mul_byte_12 .proc
|
stack_mul_byte_12 .proc
|
||||||
; (X*2 + X)*4
|
; (X*2 + X)*4
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -518,7 +523,7 @@ mul_byte_12 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_12 .proc
|
stack_mul_word_12 .proc
|
||||||
; (W*2 + W)*4
|
; (W*2 + W)*4
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -538,7 +543,7 @@ mul_word_12 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_13 .proc
|
stack_mul_byte_13 .proc
|
||||||
; (X*2 + X)*4 + X
|
; (X*2 + X)*4 + X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -554,7 +559,7 @@ mul_byte_13 .proc
|
|||||||
|
|
||||||
; mul_word_13 is skipped (too much code)
|
; mul_word_13 is skipped (too much code)
|
||||||
|
|
||||||
mul_byte_14 .proc
|
stack_mul_byte_14 .proc
|
||||||
; (X*8 - X)*2
|
; (X*8 - X)*2
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -569,7 +574,7 @@ mul_byte_14 .proc
|
|||||||
|
|
||||||
; mul_word_14 is skipped (too much code)
|
; mul_word_14 is skipped (too much code)
|
||||||
|
|
||||||
mul_byte_15 .proc
|
stack_mul_byte_15 .proc
|
||||||
; X*16 - X
|
; X*16 - X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -582,7 +587,7 @@ mul_byte_15 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_15 .proc
|
stack_mul_word_15 .proc
|
||||||
; W*16 - W
|
; W*16 - W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -604,7 +609,7 @@ mul_word_15 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_20 .proc
|
stack_mul_byte_20 .proc
|
||||||
; (X*4 + X)*4
|
; (X*4 + X)*4
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -617,7 +622,7 @@ mul_byte_20 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_20 .proc
|
stack_mul_word_20 .proc
|
||||||
; (W*4 + W)*4
|
; (W*4 + W)*4
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -639,7 +644,7 @@ mul_word_20 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_25 .proc
|
stack_mul_byte_25 .proc
|
||||||
; (X*2 + X)*8 + X
|
; (X*2 + X)*8 + X
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
@ -654,27 +659,26 @@ mul_byte_25 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_25 .proc
|
stack_mul_word_25 .proc
|
||||||
; W + W*8 + W*16
|
; W = (W*2 + W) *8 + W
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_W1+1
|
sta P8ZP_SCRATCH_W1+1
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
asl a
|
||||||
rol P8ZP_SCRATCH_W1+1
|
rol P8ZP_SCRATCH_W1+1
|
||||||
asl a
|
|
||||||
rol P8ZP_SCRATCH_W1+1
|
|
||||||
asl a
|
|
||||||
rol P8ZP_SCRATCH_W1+1
|
|
||||||
sta P8ZP_SCRATCH_W1
|
|
||||||
clc
|
clc
|
||||||
adc P8ESTACK_LO+1,x
|
adc P8ESTACK_LO+1,x
|
||||||
sta P8ESTACK_LO+1,x
|
sta P8ZP_SCRATCH_W1
|
||||||
lda P8ZP_SCRATCH_W1+1
|
lda P8ZP_SCRATCH_W1+1
|
||||||
adc P8ESTACK_HI+1,x
|
adc P8ESTACK_HI+1,x
|
||||||
sta P8ESTACK_HI+1,x
|
sta P8ZP_SCRATCH_W1+1
|
||||||
lda P8ZP_SCRATCH_W1
|
lda P8ZP_SCRATCH_W1
|
||||||
asl a
|
asl a
|
||||||
rol P8ZP_SCRATCH_W1+1
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
clc
|
clc
|
||||||
adc P8ESTACK_LO+1,x
|
adc P8ESTACK_LO+1,x
|
||||||
sta P8ESTACK_LO+1,x
|
sta P8ESTACK_LO+1,x
|
||||||
@ -684,21 +688,16 @@ mul_word_25 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_byte_40 .proc
|
stack_mul_byte_40 .proc
|
||||||
; (X*4 + X)*8
|
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
asl a
|
and #7
|
||||||
asl a
|
tay
|
||||||
clc
|
lda mul_byte_40._forties,y
|
||||||
adc P8ESTACK_LO+1,x
|
|
||||||
asl a
|
|
||||||
asl a
|
|
||||||
asl a
|
|
||||||
sta P8ESTACK_LO+1,x
|
sta P8ESTACK_LO+1,x
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
mul_word_40 .proc
|
stack_mul_word_40 .proc
|
||||||
; (W*4 + W)*8
|
; (W*4 + W)*8
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_REG
|
sta P8ZP_SCRATCH_REG
|
||||||
@ -722,6 +721,529 @@ mul_word_40 .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
stack_mul_byte_50 .proc
|
||||||
|
lda P8ESTACK_LO+1,x
|
||||||
|
and #7
|
||||||
|
tay
|
||||||
|
lda mul_byte_50._fifties, y
|
||||||
|
sta P8ESTACK_LO+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
stack_mul_word_50 .proc
|
||||||
|
; W = W * 25 * 2
|
||||||
|
jsr stack_mul_word_25
|
||||||
|
asl P8ESTACK_LO+1,x
|
||||||
|
rol P8ESTACK_HI+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
stack_mul_byte_80 .proc
|
||||||
|
lda P8ESTACK_LO+1,x
|
||||||
|
and #3
|
||||||
|
tay
|
||||||
|
lda mul_byte_80._eighties, y
|
||||||
|
sta P8ESTACK_LO+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
stack_mul_word_80 .proc
|
||||||
|
; W = W * 40 * 2
|
||||||
|
jsr stack_mul_word_40
|
||||||
|
asl P8ESTACK_LO+1,x
|
||||||
|
rol P8ESTACK_HI+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
stack_mul_byte_100 .proc
|
||||||
|
lda P8ESTACK_LO+1,x
|
||||||
|
and #3
|
||||||
|
tay
|
||||||
|
lda mul_byte_100._hundreds, y
|
||||||
|
sta P8ESTACK_LO+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
stack_mul_word_100 .proc
|
||||||
|
; W = W * 25 * 4
|
||||||
|
jsr stack_mul_word_25
|
||||||
|
asl P8ESTACK_LO+1,x
|
||||||
|
rol P8ESTACK_HI+1,x
|
||||||
|
asl P8ESTACK_LO+1,x
|
||||||
|
rol P8ESTACK_HI+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
; ----------- optimized multiplications (in-place A (byte) and ?? (word)) : ---------
|
||||||
|
mul_byte_3 .proc
|
||||||
|
; A = A + A*2
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8P_P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_3 .proc
|
||||||
|
; AY = AY*2 + AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
mul_byte_5 .proc
|
||||||
|
; A = A*4 + A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_5 .proc
|
||||||
|
; AY = AY*4 + AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
mul_byte_6 .proc
|
||||||
|
; A = (A*2 + A)*2
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_6 .proc
|
||||||
|
; AY = (AY*2 + AY)*2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
tya
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_7 .proc
|
||||||
|
; A = A*8 - A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_7 .proc
|
||||||
|
; AY = AY*8 - AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
sbc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_9 .proc
|
||||||
|
; A = A*8 + A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_9 .proc
|
||||||
|
; AY = AY*8 + AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_10 .proc
|
||||||
|
; A=(A*4 + A)*2
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_10 .proc
|
||||||
|
; AY=(AY*4 + AY)*2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_11 .proc
|
||||||
|
; A=(A*2 + A)*4 - A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
; mul_word_11 is skipped (too much code)
|
||||||
|
|
||||||
|
mul_byte_12 .proc
|
||||||
|
; A=(A*2 + A)*4
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_12 .proc
|
||||||
|
; AY=(AY*2 + AY)*4
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
ldy P8ZP_SCRATCH_W1+1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_13 .proc
|
||||||
|
; A=(A*2 + A)*4 + A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
; mul_word_13 is skipped (too much code)
|
||||||
|
|
||||||
|
mul_byte_14 .proc
|
||||||
|
; A=(A*8 - A)*2
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
; mul_word_14 is skipped (too much code)
|
||||||
|
|
||||||
|
mul_byte_15 .proc
|
||||||
|
; A=A*16 - A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_15 .proc
|
||||||
|
; AY = AY * 16 - AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
sbc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_20 .proc
|
||||||
|
; A=(A*4 + A)*4
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_20 .proc
|
||||||
|
; AY = AY * 10 * 2
|
||||||
|
jsr mul_word_10
|
||||||
|
sty P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_REG
|
||||||
|
ldy P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_25 .proc
|
||||||
|
; A=(A*2 + A)*8 + A
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
asl a
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_25 .proc
|
||||||
|
; AY = (AY*2 + AY) *8 + AY
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_40 .proc
|
||||||
|
and #7
|
||||||
|
tay
|
||||||
|
lda _forties,y
|
||||||
|
rts
|
||||||
|
_forties .byte 0*40, 1*40, 2*40, 3*40, 4*40, 5*40, 6*40, 7*40 & 255
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_40 .proc
|
||||||
|
; AY = (AY*4 + AY)*8
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_W1+1
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W1+1
|
||||||
|
adc P8ZP_SCRATCH_W2+1
|
||||||
|
asl P8ZP_SCRATCH_W1
|
||||||
|
rol a
|
||||||
|
asl P8ZP_SCRATCH_W1
|
||||||
|
rol a
|
||||||
|
asl P8ZP_SCRATCH_W1
|
||||||
|
rol a
|
||||||
|
asl P8ZP_SCRATCH_W1
|
||||||
|
rol a
|
||||||
|
tay
|
||||||
|
lda P8ZP_SCRATCH_W1
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_50 .proc
|
||||||
|
and #7
|
||||||
|
tay
|
||||||
|
lda _fifties, y
|
||||||
|
rts
|
||||||
|
_fifties .byte 0*50, 1*50, 2*50, 3*50, 4*50, 5*50, 6*50 & 255, 7*50 & 255
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_50 .proc
|
||||||
|
; AY = AY * 25 * 2
|
||||||
|
jsr mul_word_25
|
||||||
|
sty P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_REG
|
||||||
|
ldy P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_80 .proc
|
||||||
|
and #3
|
||||||
|
tay
|
||||||
|
lda _eighties, y
|
||||||
|
rts
|
||||||
|
_eighties .byte 0*80, 1*80, 2*80, 3*80
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_80 .proc
|
||||||
|
; AY = AY * 40 * 2
|
||||||
|
jsr mul_word_40
|
||||||
|
sty P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_REG
|
||||||
|
ldy P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_byte_100 .proc
|
||||||
|
and #3
|
||||||
|
tay
|
||||||
|
lda _hundreds, y
|
||||||
|
rts
|
||||||
|
_hundreds .byte 0*100, 1*100, 2*100, 3*100 & 255
|
||||||
|
.pend
|
||||||
|
|
||||||
|
mul_word_100 .proc
|
||||||
|
; AY = AY * 25 * 4
|
||||||
|
jsr mul_word_25
|
||||||
|
sty P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_REG
|
||||||
|
asl a
|
||||||
|
rol P8ZP_SCRATCH_REG
|
||||||
|
ldy P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
; ----------- end optimized multiplications -----------
|
||||||
|
|
||||||
|
|
||||||
sign_b .proc
|
sign_b .proc
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
beq _sign_zero
|
beq _sign_zero
|
||||||
|
@ -686,7 +686,7 @@ func_sqrt16 .proc
|
|||||||
sta P8ZP_SCRATCH_W2
|
sta P8ZP_SCRATCH_W2
|
||||||
lda P8ESTACK_HI+1,x
|
lda P8ESTACK_HI+1,x
|
||||||
sta P8ZP_SCRATCH_W2+1
|
sta P8ZP_SCRATCH_W2+1
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
ldy #$00 ; r = 0
|
ldy #$00 ; r = 0
|
||||||
ldx #$07
|
ldx #$07
|
||||||
clc ; clear bit 16 of m
|
clc ; clear bit 16 of m
|
||||||
@ -721,7 +721,7 @@ _skip1
|
|||||||
_skip2
|
_skip2
|
||||||
iny ; r = r or d (d is 1 here)
|
iny ; r = r or d (d is 1 here)
|
||||||
_skip3
|
_skip3
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
tya
|
tya
|
||||||
sta P8ESTACK_LO+1,x
|
sta P8ESTACK_LO+1,x
|
||||||
lda #0
|
lda #0
|
||||||
@ -1216,7 +1216,7 @@ func_rndw .proc
|
|||||||
func_memcopy .proc
|
func_memcopy .proc
|
||||||
; note: clobbers A,Y
|
; note: clobbers A,Y
|
||||||
inx
|
inx
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda P8ESTACK_LO+2,x
|
lda P8ESTACK_LO+2,x
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
lda P8ESTACK_HI+2,x
|
lda P8ESTACK_HI+2,x
|
||||||
@ -1233,7 +1233,7 @@ func_memcopy .proc
|
|||||||
iny
|
iny
|
||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
inx
|
inx
|
||||||
inx
|
inx
|
||||||
rts
|
rts
|
||||||
@ -1242,7 +1242,7 @@ func_memcopy .proc
|
|||||||
func_memset .proc
|
func_memset .proc
|
||||||
; note: clobbers A,Y
|
; note: clobbers A,Y
|
||||||
inx
|
inx
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda P8ESTACK_LO+2,x
|
lda P8ESTACK_LO+2,x
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
lda P8ESTACK_HI+2,x
|
lda P8ESTACK_HI+2,x
|
||||||
@ -1253,7 +1253,7 @@ func_memset .proc
|
|||||||
lda P8ESTACK_LO,x
|
lda P8ESTACK_LO,x
|
||||||
ldx P8ZP_SCRATCH_B1
|
ldx P8ZP_SCRATCH_B1
|
||||||
jsr memset
|
jsr memset
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
inx
|
inx
|
||||||
inx
|
inx
|
||||||
rts
|
rts
|
||||||
@ -1264,7 +1264,7 @@ func_memsetw .proc
|
|||||||
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
||||||
|
|
||||||
inx
|
inx
|
||||||
stx P8ZP_SCRATCH_REG_X
|
stx P8ZP_SCRATCH_REG
|
||||||
lda P8ESTACK_LO+2,x
|
lda P8ESTACK_LO+2,x
|
||||||
sta P8ZP_SCRATCH_W1
|
sta P8ZP_SCRATCH_W1
|
||||||
lda P8ESTACK_HI+2,x
|
lda P8ESTACK_HI+2,x
|
||||||
@ -1276,7 +1276,7 @@ func_memsetw .proc
|
|||||||
lda P8ESTACK_LO,x
|
lda P8ESTACK_LO,x
|
||||||
ldy P8ESTACK_HI,x
|
ldy P8ESTACK_HI,x
|
||||||
jsr memsetw
|
jsr memsetw
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
ldx P8ZP_SCRATCH_REG
|
||||||
inx
|
inx
|
||||||
inx
|
inx
|
||||||
rts
|
rts
|
||||||
@ -1328,9 +1328,9 @@ memset .proc
|
|||||||
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
|
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
|
||||||
; clobbers X, Y
|
; clobbers X, Y
|
||||||
stx P8ZP_SCRATCH_B1
|
stx P8ZP_SCRATCH_B1
|
||||||
sty P8ZP_SCRATCH_REG
|
sty _save_reg
|
||||||
ldy #0
|
ldy #0
|
||||||
ldx P8ZP_SCRATCH_REG
|
ldx _save_reg
|
||||||
beq _lastpage
|
beq _lastpage
|
||||||
|
|
||||||
_fullpage sta (P8ZP_SCRATCH_W1),y
|
_fullpage sta (P8ZP_SCRATCH_W1),y
|
||||||
@ -1347,6 +1347,7 @@ _lastpage ldy P8ZP_SCRATCH_B1
|
|||||||
bne -
|
bne -
|
||||||
|
|
||||||
+ rts
|
+ rts
|
||||||
|
_save_reg .byte 0
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
4.1
|
4.2
|
||||||
|
@ -4,13 +4,10 @@ import kotlinx.cli.*
|
|||||||
import prog8.ast.base.AstException
|
import prog8.ast.base.AstException
|
||||||
import prog8.compiler.CompilationResult
|
import prog8.compiler.CompilationResult
|
||||||
import prog8.compiler.compileProgram
|
import prog8.compiler.compileProgram
|
||||||
|
import prog8.compiler.target.C64Target
|
||||||
|
import prog8.compiler.target.Cx16Target
|
||||||
import prog8.compiler.target.CompilationTarget
|
import prog8.compiler.target.CompilationTarget
|
||||||
import prog8.compiler.target.c64.C64MachineDefinition
|
|
||||||
import prog8.compiler.target.c64.Petscii
|
|
||||||
import prog8.compiler.target.c64.codegen.AsmGen
|
|
||||||
import prog8.compiler.target.cx16.CX16MachineDefinition
|
|
||||||
import prog8.parser.ParsingFailedError
|
import prog8.parser.ParsingFailedError
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.file.FileSystems
|
import java.nio.file.FileSystems
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardWatchEventKinds
|
import java.nio.file.StandardWatchEventKinds
|
||||||
@ -41,7 +38,8 @@ private fun compileMain(args: Array<String>) {
|
|||||||
val dontWriteAssembly by cli.flagArgument("-noasm", "don't create assembly code")
|
val dontWriteAssembly by cli.flagArgument("-noasm", "don't create assembly code")
|
||||||
val dontOptimize by cli.flagArgument("-noopt", "don't perform any optimizations")
|
val dontOptimize by cli.flagArgument("-noopt", "don't perform any optimizations")
|
||||||
val watchMode by cli.flagArgument("-watch", "continuous compilation mode (watches for file changes), greatly increases compilation speed")
|
val watchMode by cli.flagArgument("-watch", "continuous compilation mode (watches for file changes), greatly increases compilation speed")
|
||||||
val compilationTarget by cli.flagValueArgument("-target", "compilertarget", "target output of the compiler, currently 'c64' and 'cx16' available", "c64")
|
val compilationTarget by cli.flagValueArgument("-target", "compilertarget",
|
||||||
|
"target output of the compiler, currently '${C64Target.name}' and '${Cx16Target.name}' available", C64Target.name)
|
||||||
val moduleFiles by cli.positionalArgumentsList("modules", "main module file(s) to compile", minArgs = 1)
|
val moduleFiles by cli.positionalArgumentsList("modules", "main module file(s) to compile", minArgs = 1)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -50,39 +48,6 @@ private fun compileMain(args: Array<String>) {
|
|||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
when(compilationTarget) {
|
|
||||||
"c64" -> {
|
|
||||||
with(CompilationTarget) {
|
|
||||||
name = "Commodore-64"
|
|
||||||
machine = C64MachineDefinition
|
|
||||||
encodeString = { str, altEncoding ->
|
|
||||||
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
|
|
||||||
}
|
|
||||||
decodeString = { bytes, altEncoding ->
|
|
||||||
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
|
||||||
}
|
|
||||||
asmGenerator = ::AsmGen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"cx16" -> {
|
|
||||||
with(CompilationTarget) {
|
|
||||||
name = "Commander X16"
|
|
||||||
machine = CX16MachineDefinition
|
|
||||||
encodeString = { str, altEncoding ->
|
|
||||||
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
|
|
||||||
}
|
|
||||||
decodeString = { bytes, altEncoding ->
|
|
||||||
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
|
||||||
}
|
|
||||||
asmGenerator = ::AsmGen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
System.err.println("invalid compilation target. Available are: c64, cx16")
|
|
||||||
exitProcess(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val outputPath = pathFrom(outputDir)
|
val outputPath = pathFrom(outputDir)
|
||||||
if(!outputPath.toFile().isDirectory) {
|
if(!outputPath.toFile().isDirectory) {
|
||||||
System.err.println("Output path doesn't exist")
|
System.err.println("Output path doesn't exist")
|
||||||
@ -97,7 +62,7 @@ private fun compileMain(args: Array<String>) {
|
|||||||
println("Continuous watch mode active. Main module: $filepath")
|
println("Continuous watch mode active. Main module: $filepath")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, outputDir=outputPath)
|
val compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, compilationTarget, outputPath)
|
||||||
println("Imported files (now watching:)")
|
println("Imported files (now watching:)")
|
||||||
for (importedFile in compilationResult.importedFiles) {
|
for (importedFile in compilationResult.importedFiles) {
|
||||||
print(" ")
|
print(" ")
|
||||||
@ -122,7 +87,7 @@ private fun compileMain(args: Array<String>) {
|
|||||||
val filepath = pathFrom(filepathRaw).normalize()
|
val filepath = pathFrom(filepathRaw).normalize()
|
||||||
val compilationResult: CompilationResult
|
val compilationResult: CompilationResult
|
||||||
try {
|
try {
|
||||||
compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, outputDir=outputPath)
|
compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, compilationTarget, outputPath)
|
||||||
if(!compilationResult.success)
|
if(!compilationResult.success)
|
||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
} catch (x: ParsingFailedError) {
|
} catch (x: ParsingFailedError) {
|
||||||
@ -135,7 +100,7 @@ private fun compileMain(args: Array<String>) {
|
|||||||
if (compilationResult.programName.isEmpty())
|
if (compilationResult.programName.isEmpty())
|
||||||
println("\nCan't start emulator because no program was assembled.")
|
println("\nCan't start emulator because no program was assembled.")
|
||||||
else if(startEmulator) {
|
else if(startEmulator) {
|
||||||
CompilationTarget.machine.launchEmulator(compilationResult.programName)
|
CompilationTarget.instance.machine.launchEmulator(compilationResult.programName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||||||
param.second.stack -> "stack"
|
param.second.stack -> "stack"
|
||||||
param.second.registerOrPair!=null -> param.second.registerOrPair.toString()
|
param.second.registerOrPair!=null -> param.second.registerOrPair.toString()
|
||||||
param.second.statusflag!=null -> param.second.statusflag.toString()
|
param.second.statusflag!=null -> param.second.statusflag.toString()
|
||||||
else -> "?????1"
|
else -> "?????"
|
||||||
}
|
}
|
||||||
output("${datatypeString(param.first.type)} ${param.first.name} @$reg")
|
output("${datatypeString(param.first.type)} ${param.first.name} @$reg")
|
||||||
if(param.first!==subroutine.parameters.last())
|
if(param.first!==subroutine.parameters.last())
|
||||||
|
@ -254,7 +254,7 @@ private fun prog8Parser.Asmsub_declContext.toAst(): AsmsubDecl {
|
|||||||
val clobbers = asmsub_clobbers()?.clobber()?.toAst() ?: emptySet()
|
val clobbers = asmsub_clobbers()?.clobber()?.toAst() ?: emptySet()
|
||||||
val normalParameters = params.map { SubroutineParameter(it.name, it.type, it.position) }
|
val normalParameters = params.map { SubroutineParameter(it.name, it.type, it.position) }
|
||||||
val normalReturntypes = returns.map { it.type }
|
val normalReturntypes = returns.map { it.type }
|
||||||
val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, it.stack) }
|
val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, false) }
|
||||||
val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, it.stack) }
|
val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, it.stack) }
|
||||||
return AsmsubDecl(name, normalParameters, normalReturntypes, paramRegisters, returnRegisters, clobbers)
|
return AsmsubDecl(name, normalParameters, normalReturntypes, paramRegisters, returnRegisters, clobbers)
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ private class AsmSubroutineParameter(name: String,
|
|||||||
type: DataType,
|
type: DataType,
|
||||||
val registerOrPair: RegisterOrPair?,
|
val registerOrPair: RegisterOrPair?,
|
||||||
val statusflag: Statusflag?,
|
val statusflag: Statusflag?,
|
||||||
val stack: Boolean,
|
// TODO implement: val stack: Boolean,
|
||||||
position: Position) : SubroutineParameter(name, type, position)
|
position: Position) : SubroutineParameter(name, type, position)
|
||||||
|
|
||||||
private class AsmSubroutineReturn(val type: DataType,
|
private class AsmSubroutineReturn(val type: DataType,
|
||||||
@ -305,8 +305,7 @@ private fun prog8Parser.Asmsub_paramsContext.toAst(): List<AsmSubroutineParamete
|
|||||||
else -> throw FatalAstException("invalid register or status flag '$name'")
|
else -> throw FatalAstException("invalid register or status flag '$name'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister,
|
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister, toPosition())
|
||||||
!it.stack?.text.isNullOrEmpty(), toPosition())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prog8Parser.Functioncall_stmtContext.toAst(): Statement {
|
private fun prog8Parser.Functioncall_stmtContext.toAst(): Statement {
|
||||||
@ -472,7 +471,7 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
|
|||||||
litval.charliteral()!=null -> {
|
litval.charliteral()!=null -> {
|
||||||
try {
|
try {
|
||||||
val cc=litval.charliteral()
|
val cc=litval.charliteral()
|
||||||
NumericLiteralValue(DataType.UBYTE, CompilationTarget.encodeString(
|
NumericLiteralValue(DataType.UBYTE, CompilationTarget.instance.encodeString(
|
||||||
unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()),
|
unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()),
|
||||||
litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition())
|
litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition())
|
||||||
} catch (ce: CharConversionException) {
|
} catch (ce: CharConversionException) {
|
||||||
|
@ -56,8 +56,8 @@ enum class DataType {
|
|||||||
return when(this) {
|
return when(this) {
|
||||||
in ByteDatatypes -> 1
|
in ByteDatatypes -> 1
|
||||||
in WordDatatypes -> 2
|
in WordDatatypes -> 2
|
||||||
FLOAT -> CompilationTarget.machine.FLOAT_MEM_SIZE
|
FLOAT -> CompilationTarget.instance.machine.FLOAT_MEM_SIZE
|
||||||
in PassByReferenceDatatypes -> CompilationTarget.machine.POINTER_MEM_SIZE
|
in PassByReferenceDatatypes -> CompilationTarget.instance.machine.POINTER_MEM_SIZE
|
||||||
else -> -9999999
|
else -> -9999999
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,8 +671,8 @@ class RangeExpr(var from: Expression,
|
|||||||
val toString = to as? StringLiteralValue
|
val toString = to as? StringLiteralValue
|
||||||
if(fromString!=null && toString!=null ) {
|
if(fromString!=null && toString!=null ) {
|
||||||
// string range -> int range over character values
|
// string range -> int range over character values
|
||||||
fromVal = CompilationTarget.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
|
fromVal = CompilationTarget.instance.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
|
||||||
toVal = CompilationTarget.encodeString(toString.value, fromString.altEncoding)[0].toInt()
|
toVal = CompilationTarget.instance.encodeString(toString.value, fromString.altEncoding)[0].toInt()
|
||||||
} else {
|
} else {
|
||||||
val fromLv = from as? NumericLiteralValue
|
val fromLv = from as? NumericLiteralValue
|
||||||
val toLv = to as? NumericLiteralValue
|
val toLv = to as? NumericLiteralValue
|
||||||
|
@ -7,7 +7,9 @@ import prog8.ast.base.*
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.compiler.CompilationOptions
|
import prog8.compiler.CompilationOptions
|
||||||
|
import prog8.compiler.target.C64Target
|
||||||
import prog8.compiler.target.CompilationTarget
|
import prog8.compiler.target.CompilationTarget
|
||||||
|
import prog8.compiler.target.Cx16Target
|
||||||
import prog8.functions.BuiltinFunctions
|
import prog8.functions.BuiltinFunctions
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@ -471,14 +473,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(decl: VarDecl) {
|
override fun visit(decl: VarDecl) {
|
||||||
fun err(msg: String, position: Position?=null) {
|
fun err(msg: String, position: Position?=null) = errors.err(msg, position ?: decl.position)
|
||||||
errors.err(msg, position ?: decl.position)
|
|
||||||
}
|
|
||||||
|
|
||||||
// the initializer value can't refer to the variable itself (recursive definition)
|
// the initializer value can't refer to the variable itself (recursive definition)
|
||||||
if(decl.value?.referencesIdentifiers(decl.name) == true || decl.arraysize?.index?.referencesIdentifiers(decl.name) == true) {
|
if(decl.value?.referencesIdentifiers(decl.name) == true || decl.arraysize?.index?.referencesIdentifiers(decl.name) == true)
|
||||||
err("recursive var declaration")
|
err("recursive var declaration")
|
||||||
}
|
|
||||||
|
|
||||||
// CONST can only occur on simple types (byte, word, float)
|
// CONST can only occur on simple types (byte, word, float)
|
||||||
if(decl.type== VarDeclType.CONST) {
|
if(decl.type== VarDeclType.CONST) {
|
||||||
@ -486,10 +485,12 @@ internal class AstChecker(private val program: Program,
|
|||||||
err("const modifier can only be used on numeric types (byte, word, float)")
|
err("const modifier can only be used on numeric types (byte, word, float)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FLOATS
|
// FLOATS enabled?
|
||||||
if(!compilerOptions.floats && decl.datatype in setOf(DataType.FLOAT, DataType.ARRAY_F) && decl.type!= VarDeclType.MEMORY) {
|
if(!compilerOptions.floats && decl.datatype in setOf(DataType.FLOAT, DataType.ARRAY_F) && decl.type!= VarDeclType.MEMORY)
|
||||||
err("floating point used, but that is not enabled via options")
|
err("floating point used, but that is not enabled via options")
|
||||||
}
|
|
||||||
|
if(decl.datatype == DataType.FLOAT && (decl.zeropage==ZeropageWish.REQUIRE_ZEROPAGE || decl.zeropage==ZeropageWish.PREFER_ZEROPAGE))
|
||||||
|
errors.warn("floating point values won't be placed in Zeropage due to size constraints", decl.position)
|
||||||
|
|
||||||
// ARRAY without size specifier MUST have an iterable initializer value
|
// ARRAY without size specifier MUST have an iterable initializer value
|
||||||
if(decl.isArray && decl.arraysize==null) {
|
if(decl.isArray && decl.arraysize==null) {
|
||||||
@ -558,9 +559,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
checkValueTypeAndRange(decl.datatype, decl.value as NumericLiteralValue)
|
checkValueTypeAndRange(decl.datatype, decl.value as NumericLiteralValue)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!.javaClass.simpleName}")
|
if(decl.type==VarDeclType.CONST) {
|
||||||
super.visit(decl)
|
err("const declaration needs a compile-time constant initializer value, or range")
|
||||||
return
|
super.visit(decl)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -709,6 +712,14 @@ internal class AstChecker(private val program: Program,
|
|||||||
else if(directive.args.map{it.name in setOf("enable_floats", "force_output")}.any { !it })
|
else if(directive.args.map{it.name in setOf("enable_floats", "force_output")}.any { !it })
|
||||||
err("invalid option directive argument(s)")
|
err("invalid option directive argument(s)")
|
||||||
}
|
}
|
||||||
|
"%target" -> {
|
||||||
|
if(directive.parent !is Block && directive.parent !is Module)
|
||||||
|
err("this directive may only occur in a block or at module level")
|
||||||
|
if(directive.args.size != 1)
|
||||||
|
err("directive requires one argument")
|
||||||
|
if(directive.args.single().name !in setOf(C64Target.name, Cx16Target.name))
|
||||||
|
err("invalid compilation target")
|
||||||
|
}
|
||||||
else -> throw SyntaxError("invalid directive ${directive.directive}", directive.position)
|
else -> throw SyntaxError("invalid directive ${directive.directive}", directive.position)
|
||||||
}
|
}
|
||||||
super.visit(directive)
|
super.visit(directive)
|
||||||
@ -1156,7 +1167,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
// check if the floating point values are all within range
|
// check if the floating point values are all within range
|
||||||
val doubles = value.value.map {it.constValue(program)?.number!!.toDouble()}.toDoubleArray()
|
val doubles = value.value.map {it.constValue(program)?.number!!.toDouble()}.toDoubleArray()
|
||||||
if(doubles.any { it < CompilationTarget.machine.FLOAT_MAX_NEGATIVE || it > CompilationTarget.machine.FLOAT_MAX_POSITIVE })
|
if(doubles.any { it < CompilationTarget.instance.machine.FLOAT_MAX_NEGATIVE || it > CompilationTarget.instance.machine.FLOAT_MAX_POSITIVE })
|
||||||
return err("floating point value overflow")
|
return err("floating point value overflow")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(block: Block) {
|
override fun visit(block: Block) {
|
||||||
if(block.name in CompilationTarget.machine.opcodeNames)
|
if(block.name in CompilationTarget.instance.machine.opcodeNames)
|
||||||
errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position)
|
errors.err("can't use a cpu opcode name as a symbol: '${block.name}'", block.position)
|
||||||
|
|
||||||
val existing = blocks[block.name]
|
val existing = blocks[block.name]
|
||||||
@ -40,7 +40,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||||||
if(decl.name in BuiltinFunctions)
|
if(decl.name in BuiltinFunctions)
|
||||||
errors.err("builtin function cannot be redefined", decl.position)
|
errors.err("builtin function cannot be redefined", decl.position)
|
||||||
|
|
||||||
if(decl.name in CompilationTarget.machine.opcodeNames)
|
if(decl.name in CompilationTarget.instance.machine.opcodeNames)
|
||||||
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
|
errors.err("can't use a cpu opcode name as a symbol: '${decl.name}'", decl.position)
|
||||||
|
|
||||||
if(decl.datatype==DataType.STRUCT) {
|
if(decl.datatype==DataType.STRUCT) {
|
||||||
@ -74,7 +74,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(subroutine: Subroutine) {
|
override fun visit(subroutine: Subroutine) {
|
||||||
if(subroutine.name in CompilationTarget.machine.opcodeNames) {
|
if(subroutine.name in CompilationTarget.instance.machine.opcodeNames) {
|
||||||
errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position)
|
errors.err("can't use a cpu opcode name as a symbol: '${subroutine.name}'", subroutine.position)
|
||||||
} else if(subroutine.name in BuiltinFunctions) {
|
} else if(subroutine.name in BuiltinFunctions) {
|
||||||
// the builtin functions can't be redefined
|
// the builtin functions can't be redefined
|
||||||
@ -119,7 +119,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(label: Label) {
|
override fun visit(label: Label) {
|
||||||
if(label.name in CompilationTarget.machine.opcodeNames)
|
if(label.name in CompilationTarget.instance.machine.opcodeNames)
|
||||||
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
|
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
|
||||||
|
|
||||||
if(label.name in BuiltinFunctions) {
|
if(label.name in BuiltinFunctions) {
|
||||||
|
@ -12,6 +12,7 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker()
|
|||||||
|
|
||||||
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||||
if(functionCallStatement.target.nameInSource == listOf("swap")) {
|
if(functionCallStatement.target.nameInSource == listOf("swap")) {
|
||||||
|
// TODO don't replace swap(), let the code generator figure this all out
|
||||||
// if x and y are both just identifiers, do not rewrite (there should be asm generation for that)
|
// if x and y are both just identifiers, do not rewrite (there should be asm generation for that)
|
||||||
// otherwise:
|
// otherwise:
|
||||||
// rewrite swap(x,y) as follows:
|
// rewrite swap(x,y) as follows:
|
||||||
|
@ -71,23 +71,6 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
|
||||||
val declValue = decl.value
|
|
||||||
if(declValue!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
|
||||||
val declConstValue = declValue.constValue(program)
|
|
||||||
if(declConstValue==null) {
|
|
||||||
// move the vardecl (without value) to the scope and replace this with a regular assignment
|
|
||||||
decl.value = null
|
|
||||||
val target = AssignTarget(IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position)
|
|
||||||
val assign = Assignment(target, declValue, decl.position)
|
|
||||||
return listOf(
|
|
||||||
IAstModification.ReplaceNode(decl, assign, parent),
|
|
||||||
IAstModification.InsertFirst(decl, decl.definingScope() as Node)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noModifications
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun after(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> {
|
override fun after(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> {
|
||||||
val choices = whenStatement.choiceValues(program).sortedBy {
|
val choices = whenStatement.choiceValues(program).sortedBy {
|
||||||
|
@ -18,6 +18,21 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
|
|||||||
|
|
||||||
private val noModifications = emptyList<IAstModification>()
|
private val noModifications = emptyList<IAstModification>()
|
||||||
|
|
||||||
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
|
val declValue = decl.value
|
||||||
|
if(decl.type==VarDeclType.VAR && declValue!=null && decl.struct==null) {
|
||||||
|
val valueDt = declValue.inferType(program)
|
||||||
|
if(!valueDt.istype(decl.datatype)) {
|
||||||
|
return listOf(IAstModification.ReplaceNode(
|
||||||
|
declValue,
|
||||||
|
TypecastExpression(declValue, decl.datatype, true, declValue.position),
|
||||||
|
decl
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||||
val leftDt = expr.left.inferType(program)
|
val leftDt = expr.left.inferType(program)
|
||||||
val rightDt = expr.right.inferType(program)
|
val rightDt = expr.right.inferType(program)
|
||||||
@ -139,6 +154,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
|
|||||||
call.args[arg.second.index],
|
call.args[arg.second.index],
|
||||||
TypecastExpression(arg.second.value, possibleType, true, arg.second.value.position),
|
TypecastExpression(arg.second.value, possibleType, true, arg.second.value.position),
|
||||||
call as Node)
|
call as Node)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package prog8.compiler
|
package prog8.compiler
|
||||||
|
|
||||||
|
import prog8.ast.IFunctionCall
|
||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
@ -14,7 +15,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
private val noModifications = emptyList<IAstModification>()
|
private val noModifications = emptyList<IAstModification>()
|
||||||
|
|
||||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
if (decl.value == null && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
if (decl.value == null && !decl.autogeneratedDontRemove && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||||
// a numeric vardecl without an initial value is initialized with zero.
|
// a numeric vardecl without an initial value is initialized with zero.
|
||||||
decl.value = decl.zeroElementValue()
|
decl.value = decl.zeroElementValue()
|
||||||
}
|
}
|
||||||
@ -54,7 +55,8 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!conflicts) {
|
if (!conflicts) {
|
||||||
val numericVarsWithValue = decls.filter { it.value != null && it.datatype in NumericDatatypes }
|
// move vardecls of the scope into the upper scope. Make sure the order remains the same!
|
||||||
|
val numericVarsWithValue = decls.filter { it.value != null && it.datatype in NumericDatatypes }.reversed()
|
||||||
return numericVarsWithValue.map {
|
return numericVarsWithValue.map {
|
||||||
val initValue = it.value!! // assume here that value has always been set by now
|
val initValue = it.value!! // assume here that value has always been set by now
|
||||||
it.value = null // make sure no value init assignment for this vardecl will be created later (would be superfluous)
|
it.value = null // make sure no value init assignment for this vardecl will be created later (would be superfluous)
|
||||||
@ -114,6 +116,18 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
// that the types of assignment values and their target are the same,
|
// that the types of assignment values and their target are the same,
|
||||||
// and that the types of both operands of a binaryexpression node are the same.
|
// and that the types of both operands of a binaryexpression node are the same.
|
||||||
// So, it is not easily possible to remove the typecasts that are there to make these conditions true.
|
// So, it is not easily possible to remove the typecasts that are there to make these conditions true.
|
||||||
|
// The only place for now where we can do this is for:
|
||||||
|
// asmsub register pair parameter.
|
||||||
|
|
||||||
|
if(typecast.type in WordDatatypes) {
|
||||||
|
val fcall = typecast.parent as? IFunctionCall
|
||||||
|
if (fcall != null) {
|
||||||
|
val sub = fcall.target.targetStatement(program.namespace) as? Subroutine
|
||||||
|
if (sub != null && sub.isAsmSubroutine) {
|
||||||
|
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(sourceDt in PassByReferenceDatatypes) {
|
if(sourceDt in PassByReferenceDatatypes) {
|
||||||
if(typecast.type==DataType.UWORD) {
|
if(typecast.type==DataType.UWORD) {
|
||||||
|
@ -27,7 +27,8 @@ data class CompilationOptions(val output: OutputType,
|
|||||||
val launcher: LauncherType,
|
val launcher: LauncherType,
|
||||||
val zeropage: ZeropageType,
|
val zeropage: ZeropageType,
|
||||||
val zpReserved: List<IntRange>,
|
val zpReserved: List<IntRange>,
|
||||||
val floats: Boolean)
|
val floats: Boolean,
|
||||||
|
val compilationTarget: String?)
|
||||||
|
|
||||||
|
|
||||||
class CompilerException(message: String?) : Exception(message)
|
class CompilerException(message: String?) : Exception(message)
|
||||||
|
@ -4,7 +4,9 @@ import prog8.ast.AstToSourceCode
|
|||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
|
import prog8.compiler.target.C64Target
|
||||||
import prog8.compiler.target.CompilationTarget
|
import prog8.compiler.target.CompilationTarget
|
||||||
|
import prog8.compiler.target.Cx16Target
|
||||||
import prog8.optimizer.UnusedCodeRemover
|
import prog8.optimizer.UnusedCodeRemover
|
||||||
import prog8.optimizer.constantFold
|
import prog8.optimizer.constantFold
|
||||||
import prog8.optimizer.optimizeStatements
|
import prog8.optimizer.optimizeStatements
|
||||||
@ -13,6 +15,7 @@ import prog8.parser.ModuleImporter
|
|||||||
import prog8.parser.ParsingFailedError
|
import prog8.parser.ParsingFailedError
|
||||||
import prog8.parser.moduleName
|
import prog8.parser.moduleName
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import kotlin.system.exitProcess
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
|
||||||
@ -25,12 +28,22 @@ class CompilationResult(val success: Boolean,
|
|||||||
fun compileProgram(filepath: Path,
|
fun compileProgram(filepath: Path,
|
||||||
optimize: Boolean,
|
optimize: Boolean,
|
||||||
writeAssembly: Boolean,
|
writeAssembly: Boolean,
|
||||||
|
compilationTarget: String,
|
||||||
outputDir: Path): CompilationResult {
|
outputDir: Path): CompilationResult {
|
||||||
var programName = ""
|
var programName = ""
|
||||||
lateinit var programAst: Program
|
lateinit var programAst: Program
|
||||||
lateinit var importedFiles: List<Path>
|
lateinit var importedFiles: List<Path>
|
||||||
val errors = ErrorReporter()
|
val errors = ErrorReporter()
|
||||||
|
|
||||||
|
when(compilationTarget) {
|
||||||
|
C64Target.name -> CompilationTarget.instance = C64Target
|
||||||
|
Cx16Target.name -> CompilationTarget.instance = Cx16Target
|
||||||
|
else -> {
|
||||||
|
System.err.println("invalid compilation target")
|
||||||
|
exitProcess(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val totalTime = measureTimeMillis {
|
val totalTime = measureTimeMillis {
|
||||||
// import main module and everything it needs
|
// import main module and everything it needs
|
||||||
@ -90,8 +103,8 @@ private fun parseImports(filepath: Path, errors: ErrorReporter): Triple<Program,
|
|||||||
if (compilerOptions.launcher == LauncherType.BASIC && compilerOptions.output != OutputType.PRG)
|
if (compilerOptions.launcher == LauncherType.BASIC && compilerOptions.output != OutputType.PRG)
|
||||||
throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.")
|
throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.")
|
||||||
|
|
||||||
// depending on the mach9ine and compiler options we may have to include some libraries
|
// depending on the machine and compiler options we may have to include some libraries
|
||||||
CompilationTarget.machine.importLibs(compilerOptions, importer, programAst)
|
CompilationTarget.instance.machine.importLibs(compilerOptions, importer, programAst)
|
||||||
|
|
||||||
// always import prog8lib and math
|
// always import prog8lib and math
|
||||||
importer.importLibraryModule(programAst, "math")
|
importer.importLibraryModule(programAst, "math")
|
||||||
@ -129,16 +142,26 @@ private fun determineCompilationOptions(program: Program): CompilationOptions {
|
|||||||
.map { it[0].int!!..it[1].int!! }
|
.map { it[0].int!!..it[1].int!! }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
|
var target = (mainModule.statements.singleOrNull { it is Directive && it.directive == "%target" }
|
||||||
|
as? Directive)?.args?.single()?.name
|
||||||
|
|
||||||
|
when(target) {
|
||||||
|
C64Target.name -> CompilationTarget.instance = C64Target
|
||||||
|
Cx16Target.name -> CompilationTarget.instance = Cx16Target
|
||||||
|
null -> target = CompilationTarget.instance.name
|
||||||
|
else -> throw FatalAstException("invalid target")
|
||||||
|
}
|
||||||
|
|
||||||
return CompilationOptions(
|
return CompilationOptions(
|
||||||
if (outputType == null) OutputType.PRG else OutputType.valueOf(outputType),
|
if (outputType == null) OutputType.PRG else OutputType.valueOf(outputType),
|
||||||
if (launcherType == null) LauncherType.BASIC else LauncherType.valueOf(launcherType),
|
if (launcherType == null) LauncherType.BASIC else LauncherType.valueOf(launcherType),
|
||||||
zpType, zpReserved, floatsEnabled
|
zpType, zpReserved, floatsEnabled, target
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) {
|
private fun processAst(programAst: Program, errors: ErrorReporter, compilerOptions: CompilationOptions) {
|
||||||
// perform initial syntax checks and processings
|
// perform initial syntax checks and processings
|
||||||
println("Processing...")
|
println("Processing for target ${CompilationTarget.instance.name}...")
|
||||||
programAst.checkIdentifiers(errors)
|
programAst.checkIdentifiers(errors)
|
||||||
errors.handle()
|
errors.handle()
|
||||||
programAst.constantFold(errors)
|
programAst.constantFold(errors)
|
||||||
@ -191,11 +214,14 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir:
|
|||||||
|
|
||||||
// printAst(programAst)
|
// printAst(programAst)
|
||||||
|
|
||||||
CompilationTarget.machine.initializeZeropage(compilerOptions)
|
if(compilerOptions.compilationTarget!=null && compilerOptions.compilationTarget != CompilationTarget.instance.name)
|
||||||
val assembly = CompilationTarget.asmGenerator(
|
throw AssemblyError("program's compilation target differs from configured target")
|
||||||
|
|
||||||
|
CompilationTarget.instance.machine.initializeZeropage(compilerOptions)
|
||||||
|
val assembly = CompilationTarget.instance.asmGenerator(
|
||||||
programAst,
|
programAst,
|
||||||
errors,
|
errors,
|
||||||
CompilationTarget.machine.zeropage,
|
CompilationTarget.instance.machine.zeropage,
|
||||||
compilerOptions,
|
compilerOptions,
|
||||||
outputDir).compileToAssembly(optimize)
|
outputDir).compileToAssembly(optimize)
|
||||||
assembly.assemble(compilerOptions)
|
assembly.assemble(compilerOptions)
|
||||||
|
@ -10,7 +10,6 @@ abstract class Zeropage(protected val options: CompilationOptions) {
|
|||||||
|
|
||||||
abstract val SCRATCH_B1 : Int // temp storage for a single byte
|
abstract val SCRATCH_B1 : Int // temp storage for a single byte
|
||||||
abstract val SCRATCH_REG : Int // temp storage for a register
|
abstract val SCRATCH_REG : Int // temp storage for a register
|
||||||
abstract val SCRATCH_REG_X : Int // temp storage for register X (the evaluation stack pointer)
|
|
||||||
abstract val SCRATCH_W1 : Int // temp storage 1 for a word $fb+$fc
|
abstract val SCRATCH_W1 : Int // temp storage 1 for a word $fb+$fc
|
||||||
abstract val SCRATCH_W2 : Int // temp storage 2 for a word $fb+$fc
|
abstract val SCRATCH_W2 : Int // temp storage 2 for a word $fb+$fc
|
||||||
|
|
||||||
|
@ -4,15 +4,50 @@ import prog8.ast.Program
|
|||||||
import prog8.ast.base.ErrorReporter
|
import prog8.ast.base.ErrorReporter
|
||||||
import prog8.compiler.CompilationOptions
|
import prog8.compiler.CompilationOptions
|
||||||
import prog8.compiler.Zeropage
|
import prog8.compiler.Zeropage
|
||||||
|
import prog8.compiler.target.c64.C64MachineDefinition
|
||||||
|
import prog8.compiler.target.c64.Petscii
|
||||||
|
import prog8.compiler.target.c64.codegen.AsmGen
|
||||||
|
import prog8.compiler.target.cx16.CX16MachineDefinition
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
internal interface CompilationTarget {
|
internal interface CompilationTarget {
|
||||||
|
val name: String
|
||||||
|
val machine: IMachineDefinition
|
||||||
|
fun encodeString(str: String, altEncoding: Boolean): List<Short>
|
||||||
|
fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
|
||||||
|
fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path): IAssemblyGenerator
|
||||||
|
val asmForSystemReset: String
|
||||||
|
val initProcName: String?
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var name: String
|
lateinit var instance: CompilationTarget
|
||||||
lateinit var machine: IMachineDefinition
|
|
||||||
lateinit var encodeString: (str: String, altEncoding: Boolean) -> List<Short>
|
|
||||||
lateinit var decodeString: (bytes: List<Short>, altEncoding: Boolean) -> String
|
|
||||||
lateinit var asmGenerator: (Program, ErrorReporter, Zeropage, CompilationOptions, Path) -> IAssemblyGenerator
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal object C64Target: CompilationTarget {
|
||||||
|
override val name = "c64"
|
||||||
|
override val machine = C64MachineDefinition
|
||||||
|
override fun encodeString(str: String, altEncoding: Boolean) =
|
||||||
|
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
|
||||||
|
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) =
|
||||||
|
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
||||||
|
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
|
||||||
|
AsmGen(program, errors, zp, options, path)
|
||||||
|
override val asmForSystemReset = " sei | lda #14 | sta $1 | jmp (c64.RESET_VEC)"
|
||||||
|
override val initProcName = "c64.init_system"
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object Cx16Target: CompilationTarget {
|
||||||
|
override val name = "cx16"
|
||||||
|
override val machine = CX16MachineDefinition
|
||||||
|
override fun encodeString(str: String, altEncoding: Boolean) =
|
||||||
|
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
|
||||||
|
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) =
|
||||||
|
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
|
||||||
|
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
|
||||||
|
AsmGen(program, errors, zp, options, path)
|
||||||
|
override val asmForSystemReset = " sei | stz cx16.d1prb | jmp (cx16.RESET_VEC)"
|
||||||
|
override val initProcName = "cx16.init_system"
|
||||||
|
}
|
||||||
|
@ -28,7 +28,6 @@ internal interface IMachineDefinition {
|
|||||||
|
|
||||||
val opcodeNames: Set<String>
|
val opcodeNames: Set<String>
|
||||||
var zeropage: Zeropage
|
var zeropage: Zeropage
|
||||||
val initSystemProcname: String
|
|
||||||
val cpu: CpuType
|
val cpu: CpuType
|
||||||
|
|
||||||
fun initializeZeropage(compilerOptions: CompilationOptions)
|
fun initializeZeropage(compilerOptions: CompilationOptions)
|
||||||
|
@ -2,6 +2,7 @@ package prog8.compiler.target.c64
|
|||||||
|
|
||||||
import prog8.compiler.CompilationOptions
|
import prog8.compiler.CompilationOptions
|
||||||
import prog8.compiler.OutputType
|
import prog8.compiler.OutputType
|
||||||
|
import prog8.compiler.target.CompilationTarget
|
||||||
import prog8.compiler.target.IAssemblyProgram
|
import prog8.compiler.target.IAssemblyProgram
|
||||||
import prog8.compiler.target.generatedLabelPrefix
|
import prog8.compiler.target.generatedLabelPrefix
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -22,12 +23,12 @@ class AssemblyProgram(override val name: String, outputDir: Path) : IAssemblyPro
|
|||||||
val outFile = when (options.output) {
|
val outFile = when (options.output) {
|
||||||
OutputType.PRG -> {
|
OutputType.PRG -> {
|
||||||
command.add("--cbm-prg")
|
command.add("--cbm-prg")
|
||||||
println("\nCreating prg.")
|
println("\nCreating prg for target ${CompilationTarget.instance.name}.")
|
||||||
prgFile
|
prgFile
|
||||||
}
|
}
|
||||||
OutputType.RAW -> {
|
OutputType.RAW -> {
|
||||||
command.add("--nostart")
|
command.add("--nostart")
|
||||||
println("\nCreating raw binary.")
|
println("\nCreating raw binary for target ${CompilationTarget.instance.name}.")
|
||||||
binFile
|
binFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ internal object C64MachineDefinition: IMachineDefinition {
|
|||||||
override val ESTACK_HI = 0xcf00 // $ce00-$ceff inclusive
|
override val ESTACK_HI = 0xcf00 // $ce00-$ceff inclusive
|
||||||
|
|
||||||
override lateinit var zeropage: Zeropage
|
override lateinit var zeropage: Zeropage
|
||||||
override val initSystemProcname = "c64.init_system"
|
|
||||||
|
|
||||||
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
|
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
|
||||||
|
|
||||||
@ -109,7 +108,6 @@ internal object C64MachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
override val SCRATCH_B1 = 0x02 // temp storage for a single byte
|
override val SCRATCH_B1 = 0x02 // temp storage for a single byte
|
||||||
override val SCRATCH_REG = 0x03 // temp storage for a register
|
override val SCRATCH_REG = 0x03 // temp storage for a register
|
||||||
override val SCRATCH_REG_X = 0xfa // temp storage for register X (the evaluation stack pointer)
|
|
||||||
override val SCRATCH_W1 = 0xfb // temp storage 1 for a word $fb+$fc
|
override val SCRATCH_W1 = 0xfb // temp storage 1 for a word $fb+$fc
|
||||||
override val SCRATCH_W2 = 0xfd // temp storage 2 for a word $fb+$fc
|
override val SCRATCH_W2 = 0xfd // temp storage 2 for a word $fb+$fc
|
||||||
|
|
||||||
@ -127,7 +125,7 @@ internal object C64MachineDefinition: IMachineDefinition {
|
|||||||
if (options.zeropage == ZeropageType.FULL) {
|
if (options.zeropage == ZeropageType.FULL) {
|
||||||
free.addAll(0x04..0xf9)
|
free.addAll(0x04..0xf9)
|
||||||
free.add(0xff)
|
free.add(0xff)
|
||||||
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
||||||
free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ
|
free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ
|
||||||
} else {
|
} else {
|
||||||
if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) {
|
if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) {
|
||||||
@ -170,7 +168,6 @@ internal object C64MachineDefinition: IMachineDefinition {
|
|||||||
}
|
}
|
||||||
require(SCRATCH_B1 !in free)
|
require(SCRATCH_B1 !in free)
|
||||||
require(SCRATCH_REG !in free)
|
require(SCRATCH_REG !in free)
|
||||||
require(SCRATCH_REG_X !in free)
|
|
||||||
require(SCRATCH_W1 !in free)
|
require(SCRATCH_W1 !in free)
|
||||||
require(SCRATCH_W2 !in free)
|
require(SCRATCH_W2 !in free)
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ internal class AsmGen(private val program: Program,
|
|||||||
val options: CompilationOptions,
|
val options: CompilationOptions,
|
||||||
private val outputDir: Path): IAssemblyGenerator {
|
private val outputDir: Path): IAssemblyGenerator {
|
||||||
|
|
||||||
|
// for expressions and augmented assignments:
|
||||||
|
val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100)
|
||||||
|
val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40,50,80,100)
|
||||||
|
|
||||||
private val assemblyLines = mutableListOf<String>()
|
private val assemblyLines = mutableListOf<String>()
|
||||||
private val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname)
|
private val globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname)
|
||||||
private val allocatedZeropageVariables = mutableMapOf<String, Pair<Int, DataType>>()
|
private val allocatedZeropageVariables = mutableMapOf<String, Pair<Int, DataType>>()
|
||||||
@ -79,7 +83,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
|
|
||||||
private fun header() {
|
private fun header() {
|
||||||
val ourName = this.javaClass.name
|
val ourName = this.javaClass.name
|
||||||
val cpu = when(CompilationTarget.machine.cpu) {
|
val cpu = when(CompilationTarget.instance.machine.cpu) {
|
||||||
CpuType.CPU6502 -> "6502"
|
CpuType.CPU6502 -> "6502"
|
||||||
CpuType.CPU65c02 -> "65c02"
|
CpuType.CPU65c02 -> "65c02"
|
||||||
else -> "unsupported"
|
else -> "unsupported"
|
||||||
@ -94,18 +98,16 @@ internal class AsmGen(private val program: Program,
|
|||||||
program.actualLoadAddress = program.definedLoadAddress
|
program.actualLoadAddress = program.definedLoadAddress
|
||||||
if (program.actualLoadAddress == 0) // fix load address
|
if (program.actualLoadAddress == 0) // fix load address
|
||||||
program.actualLoadAddress = if (options.launcher == LauncherType.BASIC)
|
program.actualLoadAddress = if (options.launcher == LauncherType.BASIC)
|
||||||
CompilationTarget.machine.BASIC_LOAD_ADDRESS else CompilationTarget.machine.RAW_LOAD_ADDRESS
|
CompilationTarget.instance.machine.BASIC_LOAD_ADDRESS else CompilationTarget.instance.machine.RAW_LOAD_ADDRESS
|
||||||
|
|
||||||
// the global prog8 variables needed
|
// the global prog8 variables needed
|
||||||
val zp = CompilationTarget.machine.zeropage
|
val zp = CompilationTarget.instance.machine.zeropage
|
||||||
val initproc = CompilationTarget.machine.initSystemProcname
|
|
||||||
out("P8ZP_SCRATCH_B1 = ${zp.SCRATCH_B1}")
|
out("P8ZP_SCRATCH_B1 = ${zp.SCRATCH_B1}")
|
||||||
out("P8ZP_SCRATCH_REG = ${zp.SCRATCH_REG}")
|
out("P8ZP_SCRATCH_REG = ${zp.SCRATCH_REG}")
|
||||||
out("P8ZP_SCRATCH_REG_X = ${zp.SCRATCH_REG_X}")
|
|
||||||
out("P8ZP_SCRATCH_W1 = ${zp.SCRATCH_W1} ; word")
|
out("P8ZP_SCRATCH_W1 = ${zp.SCRATCH_W1} ; word")
|
||||||
out("P8ZP_SCRATCH_W2 = ${zp.SCRATCH_W2} ; word")
|
out("P8ZP_SCRATCH_W2 = ${zp.SCRATCH_W2} ; word")
|
||||||
out("P8ESTACK_LO = ${CompilationTarget.machine.ESTACK_LO.toHex()}")
|
out("P8ESTACK_LO = ${CompilationTarget.instance.machine.ESTACK_LO.toHex()}")
|
||||||
out("P8ESTACK_HI = ${CompilationTarget.machine.ESTACK_HI.toHex()}")
|
out("P8ESTACK_HI = ${CompilationTarget.instance.machine.ESTACK_HI.toHex()}")
|
||||||
|
|
||||||
when {
|
when {
|
||||||
options.launcher == LauncherType.BASIC -> {
|
options.launcher == LauncherType.BASIC -> {
|
||||||
@ -120,16 +122,16 @@ internal class AsmGen(private val program: Program,
|
|||||||
out("_prog8_entrypoint\t; assembly code starts here\n")
|
out("_prog8_entrypoint\t; assembly code starts here\n")
|
||||||
out(" tsx")
|
out(" tsx")
|
||||||
out(" stx prog8_lib.orig_stackpointer")
|
out(" stx prog8_lib.orig_stackpointer")
|
||||||
if(!initproc.isNullOrEmpty())
|
if(!CompilationTarget.instance.initProcName.isNullOrEmpty())
|
||||||
out(" jsr $initproc")
|
out(" jsr ${CompilationTarget.instance.initProcName}")
|
||||||
}
|
}
|
||||||
options.output == OutputType.PRG -> {
|
options.output == OutputType.PRG -> {
|
||||||
out("; ---- program without basic sys call ----")
|
out("; ---- program without basic sys call ----")
|
||||||
out("* = ${program.actualLoadAddress.toHex()}\n")
|
out("* = ${program.actualLoadAddress.toHex()}\n")
|
||||||
out(" tsx")
|
out(" tsx")
|
||||||
out(" stx prog8_lib.orig_stackpointer")
|
out(" stx prog8_lib.orig_stackpointer")
|
||||||
if(!initproc.isNullOrEmpty())
|
if(!CompilationTarget.instance.initProcName.isNullOrEmpty())
|
||||||
out(" jsr $initproc")
|
out(" jsr ${CompilationTarget.instance.initProcName}")
|
||||||
}
|
}
|
||||||
options.output == OutputType.RAW -> {
|
options.output == OutputType.RAW -> {
|
||||||
out("; ---- raw assembler program ----")
|
out("; ---- raw assembler program ----")
|
||||||
@ -161,7 +163,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
Zeropage.ExitProgramStrategy.SYSTEM_RESET -> {
|
Zeropage.ExitProgramStrategy.SYSTEM_RESET -> {
|
||||||
out(" jsr main.start\t; call program entrypoint")
|
out(" jsr main.start\t; call program entrypoint")
|
||||||
out(" jmp (c64.RESET_VEC)\t; cold reset")
|
out(CompilationTarget.instance.asmForSystemReset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +172,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
// the global list of all floating point constants for the whole program
|
// the global list of all floating point constants for the whole program
|
||||||
out("; global float constants")
|
out("; global float constants")
|
||||||
for (flt in globalFloatConsts) {
|
for (flt in globalFloatConsts) {
|
||||||
val floatFill = CompilationTarget.machine.getFloat(flt.key).makeFloatFillAsm()
|
val floatFill = CompilationTarget.instance.machine.getFloat(flt.key).makeFloatFillAsm()
|
||||||
val floatvalue = flt.key
|
val floatvalue = flt.key
|
||||||
out("${flt.value}\t.byte $floatFill ; float $floatvalue")
|
out("${flt.value}\t.byte $floatFill ; float $floatvalue")
|
||||||
}
|
}
|
||||||
@ -340,7 +342,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
val floatFills = array.map {
|
val floatFills = array.map {
|
||||||
val number = (it as NumericLiteralValue).number
|
val number = (it as NumericLiteralValue).number
|
||||||
CompilationTarget.machine.getFloat(number).makeFloatFillAsm()
|
CompilationTarget.instance.machine.getFloat(number).makeFloatFillAsm()
|
||||||
}
|
}
|
||||||
out(name)
|
out(name)
|
||||||
for (f in array.zip(floatFills))
|
for (f in array.zip(floatFills))
|
||||||
@ -474,7 +476,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun getFloatAsmConst(number: Double): String {
|
internal fun getFloatAsmConst(number: Double): String {
|
||||||
var asmName = CompilationTarget.machine.getFloatRomConst(number)
|
var asmName = CompilationTarget.instance.machine.getFloatRomConst(number)
|
||||||
if(asmName.isNullOrEmpty()) {
|
if(asmName.isNullOrEmpty()) {
|
||||||
// no ROM float const for this value, create our own
|
// no ROM float const for this value, create our own
|
||||||
asmName = globalFloatConsts[number]
|
asmName = globalFloatConsts[number]
|
||||||
@ -548,16 +550,35 @@ internal class AsmGen(private val program: Program,
|
|||||||
|
|
||||||
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
|
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
|
||||||
|
|
||||||
|
|
||||||
|
private val saveRegisterLabels = Stack<String>();
|
||||||
|
|
||||||
internal fun saveRegister(register: CpuRegister) {
|
internal fun saveRegister(register: CpuRegister) {
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" pha")
|
CpuRegister.A -> out(" pha")
|
||||||
CpuRegister.X -> {
|
CpuRegister.X -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
|
||||||
out(" phx")
|
else {
|
||||||
else
|
val save = makeLabel("saveX")
|
||||||
out(" stx P8ZP_SCRATCH_REG_X")
|
saveRegisterLabels.push(save)
|
||||||
|
out("""
|
||||||
|
stx $save
|
||||||
|
jmp +
|
||||||
|
$save .byte 0
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuRegister.Y -> {
|
||||||
|
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
|
||||||
|
else {
|
||||||
|
val save = makeLabel("saveY")
|
||||||
|
out("""
|
||||||
|
sty $save
|
||||||
|
jmp +
|
||||||
|
$save .byte 0
|
||||||
|
+""")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> out(" tya | pha")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,15 +586,23 @@ internal class AsmGen(private val program: Program,
|
|||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" pla")
|
CpuRegister.A -> out(" pla")
|
||||||
CpuRegister.X -> {
|
CpuRegister.X -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" plx")
|
||||||
out(" plx")
|
else {
|
||||||
else
|
val save = saveRegisterLabels.pop()
|
||||||
out(" ldx P8ZP_SCRATCH_REG_X")
|
out(" ldx $save")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuRegister.Y -> {
|
||||||
|
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" ply")
|
||||||
|
else {
|
||||||
|
val save = saveRegisterLabels.pop()
|
||||||
|
out(" ldy $save")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> out(" pla | tay")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun translate(stmt: Statement) {
|
internal fun translate(stmt: Statement) {
|
||||||
outputSourceLine(stmt)
|
outputSourceLine(stmt)
|
||||||
when(stmt) {
|
when(stmt) {
|
||||||
@ -684,7 +713,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
+""")
|
+""")
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
||||||
CpuRegister.X -> throw AssemblyError("can't use X here")
|
CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax")
|
||||||
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -722,7 +751,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
expressionsAsmGen.translateExpression(index)
|
expressionsAsmGen.translateExpression(index)
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x")
|
||||||
CpuRegister.X -> throw AssemblyError("can't use X here")
|
CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax")
|
||||||
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -792,16 +821,38 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: IfStatement) {
|
private fun translate(stmt: IfStatement) {
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
when {
|
||||||
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
stmt.elsepart.containsNoCodeNorVars() -> {
|
||||||
val elseLabel = makeLabel("if_else")
|
// empty else
|
||||||
val endLabel = makeLabel("if_end")
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
out(" beq $elseLabel")
|
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
||||||
translate(stmt.truepart)
|
val endLabel = makeLabel("if_end")
|
||||||
out(" jmp $endLabel")
|
out(" beq $endLabel")
|
||||||
out(elseLabel)
|
translate(stmt.truepart)
|
||||||
translate(stmt.elsepart)
|
out(endLabel)
|
||||||
out(endLabel)
|
}
|
||||||
|
stmt.truepart.containsNoCodeNorVars() -> {
|
||||||
|
// empty true part
|
||||||
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
|
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
out(" bne $endLabel")
|
||||||
|
translate(stmt.elsepart)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
|
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
||||||
|
val elseLabel = makeLabel("if_else")
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
out(" beq $elseLabel")
|
||||||
|
translate(stmt.truepart)
|
||||||
|
out(" jmp $endLabel")
|
||||||
|
out(elseLabel)
|
||||||
|
translate(stmt.elsepart)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateTestStack(dataType: DataType) {
|
private fun translateTestStack(dataType: DataType) {
|
||||||
|
@ -47,7 +47,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
||||||
RegisterOrPair.X -> {
|
RegisterOrPair.X -> {
|
||||||
// return value in X register has been discarded, just push a zero
|
// return value in X register has been discarded, just push a zero
|
||||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
asmgen.out(" stz P8ESTACK_LO,x")
|
asmgen.out(" stz P8ESTACK_LO,x")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||||
@ -56,7 +56,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
RegisterOrPair.AX -> {
|
RegisterOrPair.AX -> {
|
||||||
// return value in X register has been discarded, just push a zero in this place
|
// return value in X register has been discarded, just push a zero in this place
|
||||||
asmgen.out(" sta P8ESTACK_LO,x")
|
asmgen.out(" sta P8ESTACK_LO,x")
|
||||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
asmgen.out(" stz P8ESTACK_HI,x")
|
asmgen.out(" stz P8ESTACK_HI,x")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
||||||
@ -64,7 +64,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
RegisterOrPair.XY -> {
|
RegisterOrPair.XY -> {
|
||||||
// return value in X register has been discarded, just push a zero in this place
|
// return value in X register has been discarded, just push a zero in this place
|
||||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
asmgen.out(" stz P8ESTACK_LO,x")
|
asmgen.out(" stz P8ESTACK_LO,x")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||||
@ -85,7 +85,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
when(expr.type) {
|
when(expr.type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {}
|
DataType.UBYTE, DataType.BYTE -> {}
|
||||||
DataType.UWORD, DataType.WORD -> {
|
DataType.UWORD, DataType.WORD -> {
|
||||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
asmgen.out(" stz P8ESTACK_HI+1,x")
|
asmgen.out(" stz P8ESTACK_HI+1,x")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")
|
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")
|
||||||
@ -103,14 +103,9 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda P8ESTACK_LO+1,x
|
lda P8ESTACK_LO+1,x
|
||||||
ora #$7f
|
ora #$7f
|
||||||
bmi +""")
|
bmi +
|
||||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
lda #0
|
||||||
asmgen.out("""
|
+ sta P8ESTACK_HI+1,x""")
|
||||||
+ stz P8ESTACK_HI+1,x""")
|
|
||||||
else
|
|
||||||
asmgen.out("""
|
|
||||||
lda #0
|
|
||||||
+ sta P8ESTACK_HI+1,x""")
|
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> asmgen.out(" jsr c64flt.stack_b2float")
|
DataType.FLOAT -> asmgen.out(" jsr c64flt.stack_b2float")
|
||||||
in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype")
|
in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype")
|
||||||
@ -212,9 +207,6 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)
|
|
||||||
private val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40)
|
|
||||||
|
|
||||||
private fun translateExpression(expr: BinaryExpression) {
|
private fun translateExpression(expr: BinaryExpression) {
|
||||||
val leftIDt = expr.left.inferType(program)
|
val leftIDt = expr.left.inferType(program)
|
||||||
val rightIDt = expr.right.inferType(program)
|
val rightIDt = expr.right.inferType(program)
|
||||||
@ -308,40 +300,40 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
val amount = value.number.toInt()
|
val amount = value.number.toInt()
|
||||||
when(rightDt) {
|
when(rightDt) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
if(amount in optimizedByteMultiplications) {
|
if(amount in asmgen.optimizedByteMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr math.mul_byte_$amount")
|
asmgen.out(" jsr math.stack_mul_byte_$amount")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
if(amount in optimizedByteMultiplications) {
|
if(amount in asmgen.optimizedByteMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr math.mul_byte_$amount")
|
asmgen.out(" jsr math.stack_mul_byte_$amount")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(amount.absoluteValue in optimizedByteMultiplications) {
|
if(amount.absoluteValue in asmgen.optimizedByteMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr prog8_lib.neg_b | jsr math.mul_byte_${amount.absoluteValue}")
|
asmgen.out(" jsr prog8_lib.neg_b | jsr math.stack_mul_byte_${amount.absoluteValue}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
if(amount in optimizedWordMultiplications) {
|
if(amount in asmgen.optimizedWordMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr math.mul_word_$amount")
|
asmgen.out(" jsr math.stack_mul_word_$amount")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
if(amount in optimizedWordMultiplications) {
|
if(amount in asmgen.optimizedWordMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr math.mul_word_$amount")
|
asmgen.out(" jsr math.stack_mul_word_$amount")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(amount.absoluteValue in optimizedWordMultiplications) {
|
if(amount.absoluteValue in asmgen.optimizedWordMultiplications) {
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
asmgen.out(" jsr prog8_lib.neg_w | jsr math.mul_word_${amount.absoluteValue}")
|
asmgen.out(" jsr prog8_lib.neg_w | jsr math.stack_mul_word_${amount.absoluteValue}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import prog8.ast.IFunctionCall
|
|||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
|
import prog8.ast.statements.RegisterOrStatusflag
|
||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.statements.SubroutineParameter
|
import prog8.ast.statements.SubroutineParameter
|
||||||
import prog8.compiler.AssemblyError
|
import prog8.compiler.AssemblyError
|
||||||
@ -18,7 +19,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
||||||
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
|
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
|
||||||
if(saveX)
|
if(saveX)
|
||||||
asmgen.saveRegister(CpuRegister.X) // we only save X for now (required! is the eval stack pointer), screw A and Y...
|
asmgen.saveRegister(CpuRegister.X)
|
||||||
|
|
||||||
val subName = asmgen.asmSymbolName(stmt.target)
|
val subName = asmgen.asmSymbolName(stmt.target)
|
||||||
if(stmt.args.isNotEmpty()) {
|
if(stmt.args.isNotEmpty()) {
|
||||||
@ -63,33 +64,79 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
||||||
// this is called when one or more of the arguments are 'complex' and
|
// this is called when one or more of the arguments are 'complex' and
|
||||||
// cannot be assigned to a register easily or risk clobbering other registers.
|
// cannot be assigned to a register easily or risk clobbering other registers.
|
||||||
|
|
||||||
|
if(sub.parameters.isEmpty())
|
||||||
|
return
|
||||||
|
|
||||||
|
// 1. load all arguments reversed onto the stack: first arg goes last (is on top).
|
||||||
for (arg in stmt.args.reversed())
|
for (arg in stmt.args.reversed())
|
||||||
asmgen.translateExpression(arg)
|
asmgen.translateExpression(arg)
|
||||||
for (regparam in sub.asmParameterRegisters) {
|
|
||||||
|
var argForCarry: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
var argForXregister: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
var argForAregister: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
|
||||||
|
asmgen.out(" inx") // align estack pointer
|
||||||
|
|
||||||
|
for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) {
|
||||||
when {
|
when {
|
||||||
regparam.statusflag==Statusflag.Pc -> {
|
argi.value.second.stack -> TODO("asmsub @stack parameter")
|
||||||
asmgen.out("""
|
argi.value.second.statusflag == Statusflag.Pc -> {
|
||||||
inx
|
require(argForCarry == null)
|
||||||
pha
|
argForCarry = argi
|
||||||
lda P8ESTACK_LO,x
|
|
||||||
beq +
|
|
||||||
sec
|
|
||||||
bcs ++
|
|
||||||
+ clc
|
|
||||||
+ pla""")
|
|
||||||
}
|
}
|
||||||
regparam.statusflag!=null -> {
|
argi.value.second.statusflag != null -> throw AssemblyError("can only use Carry as status flag parameter")
|
||||||
throw AssemblyError("can only use Carry as status flag parameter")
|
argi.value.second.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) -> {
|
||||||
|
require(argForXregister==null)
|
||||||
|
argForXregister = argi
|
||||||
}
|
}
|
||||||
regparam.registerOrPair!=null -> {
|
argi.value.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.AY) -> {
|
||||||
val tgt = AsmAssignTarget.fromRegisters(regparam.registerOrPair, program, asmgen)
|
require(argForAregister == null)
|
||||||
val source = AsmAssignSource(SourceStorageKind.STACK, program, tgt.datatype)
|
argForAregister = argi
|
||||||
val asgn = AsmAssignment(source, tgt, false, Position.DUMMY)
|
|
||||||
asmgen.translateNormalAssignment(asgn)
|
|
||||||
}
|
}
|
||||||
else -> {}
|
argi.value.second.registerOrPair == RegisterOrPair.Y -> {
|
||||||
|
asmgen.out(" ldy P8ESTACK_LO+${argi.index},x")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird argument")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(argForCarry!=null) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda P8ESTACK_LO+${argForCarry.index},x
|
||||||
|
beq +
|
||||||
|
sec
|
||||||
|
bcs ++
|
||||||
|
+ clc
|
||||||
|
+ php""") // push the status flags
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForAregister!=null) {
|
||||||
|
when(argForAregister.value.second.registerOrPair) {
|
||||||
|
RegisterOrPair.A -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x | ldy P8ESTACK_HI+${argForAregister.index},x")
|
||||||
|
else -> throw AssemblyError("weird arg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForXregister!=null) {
|
||||||
|
|
||||||
|
if(argForAregister!=null)
|
||||||
|
asmgen.out(" pha")
|
||||||
|
when(argForXregister.value.second.registerOrPair) {
|
||||||
|
RegisterOrPair.X -> asmgen.out(" lda P8ESTACK_LO+${argForXregister.index},x | tax")
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" ldy P8ESTACK_LO+${argForXregister.index},x | lda P8ESTACK_HI+${argForXregister.index},x | tax | tya")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy P8ESTACK_HI+${argForXregister.index},x | lda P8ESTACK_LO+${argForXregister.index},x | tax")
|
||||||
|
else -> throw AssemblyError("weird arg")
|
||||||
|
}
|
||||||
|
if(argForAregister!=null)
|
||||||
|
asmgen.out(" pla")
|
||||||
|
} else {
|
||||||
|
repeat(sub.parameters.size - 1) { asmgen.out(" inx") } // unwind stack
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForCarry!=null)
|
||||||
|
asmgen.out(" plp") // set the carry flag back to correct value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun argumentViaVariable(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
private fun argumentViaVariable(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
||||||
|
@ -159,6 +159,7 @@ internal class AsmAssignment(val source: AsmAssignSource,
|
|||||||
val position: Position) {
|
val position: Position) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(source.datatype==target.datatype) {"source and target datatype must be identical"}
|
if(target.register !in setOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY))
|
||||||
|
require(source.datatype.memorySize() == target.datatype.memorySize()) { "source and target datatype must be same storage class" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,17 +120,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
is IdentifierReference -> throw AssemblyError("source kind should have been variable")
|
is IdentifierReference -> throw AssemblyError("source kind should have been variable")
|
||||||
is ArrayIndexedExpression -> throw AssemblyError("source kind should have been array")
|
is ArrayIndexedExpression -> throw AssemblyError("source kind should have been array")
|
||||||
is DirectMemoryRead -> throw AssemblyError("source kind should have been memory")
|
is DirectMemoryRead -> throw AssemblyError("source kind should have been memory")
|
||||||
// is TypecastExpression -> {
|
is TypecastExpression -> assignTypeCastedValue(assign.target, value.type, value.expression, assign)
|
||||||
// if(assign.target.kind == TargetStorageKind.STACK) {
|
|
||||||
// asmgen.translateExpression(value)
|
|
||||||
// assignStackValue(assign.target)
|
|
||||||
// } else {
|
|
||||||
// println("!!!!TYPECAST to ${assign.target.kind} $value")
|
|
||||||
// // TODO maybe we can do the typecast on the target directly instead of on the stack?
|
|
||||||
// asmgen.translateExpression(value)
|
|
||||||
// assignStackValue(assign.target)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// is FunctionCall -> {
|
// is FunctionCall -> {
|
||||||
// if (assign.target.kind == TargetStorageKind.STACK) {
|
// if (assign.target.kind == TargetStorageKind.STACK) {
|
||||||
// asmgen.translateExpression(value)
|
// asmgen.translateExpression(value)
|
||||||
@ -161,6 +151,52 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun assignTypeCastedValue(target: AsmAssignTarget, targetDt: DataType, value: Expression, origAssign: AsmAssignment) {
|
||||||
|
val valueDt = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
|
when(value) {
|
||||||
|
is IdentifierReference -> {
|
||||||
|
if (valueDt == DataType.UBYTE || valueDt == DataType.BYTE) {
|
||||||
|
if(targetDt in WordDatatypes) {
|
||||||
|
assignVariableByteIntoWord(target, value, valueDt)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is DirectMemoryRead -> {
|
||||||
|
if(targetDt in WordDatatypes) {
|
||||||
|
if (value.addressExpression is NumericLiteralValue) {
|
||||||
|
val address = (value.addressExpression as NumericLiteralValue).number.toInt()
|
||||||
|
assignMemoryByteIntoWord(target, address, null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if (value.addressExpression is IdentifierReference) {
|
||||||
|
assignMemoryByteIntoWord(target, null, value.addressExpression as IdentifierReference)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is NumericLiteralValue -> throw AssemblyError("a cast of a literal value should have been const-folded away")
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
when(value) {
|
||||||
|
is PrefixExpression -> {}
|
||||||
|
is BinaryExpression -> {}
|
||||||
|
is ArrayIndexedExpression -> {}
|
||||||
|
is TypecastExpression -> {}
|
||||||
|
is RangeExpr -> {}
|
||||||
|
is FunctionCall -> {}
|
||||||
|
else -> {
|
||||||
|
// TODO optimize the others further?
|
||||||
|
println("warning: slow stack evaluation used for typecast: into $targetDt at ${value.position}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// give up, do it via eval stack
|
||||||
|
asmgen.translateExpression(origAssign.source.expression!!)
|
||||||
|
assignStackValue(target)
|
||||||
|
}
|
||||||
|
|
||||||
private fun assignStackValue(target: AsmAssignTarget) {
|
private fun assignStackValue(target: AsmAssignTarget) {
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
@ -260,16 +296,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
when(target.register!!) {
|
when(target.register!!) {
|
||||||
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
||||||
RegisterOrPair.X -> throw AssemblyError("can't use X here")
|
RegisterOrPair.X -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
||||||
else -> throw AssemblyError("can't assign byte to register pair word")
|
RegisterOrPair.AX -> asmgen.out(" inx | lda P8ESTACK_LO,x | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy #0")
|
||||||
|
else -> throw AssemblyError("can't assign byte from stack to register pair XY")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
||||||
when(target.register!!) {
|
when(target.register!!) {
|
||||||
RegisterOrPair.AX -> throw AssemblyError("can't use X here")
|
RegisterOrPair.AX -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
RegisterOrPair.AY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x")
|
RegisterOrPair.AY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x")
|
||||||
RegisterOrPair.XY-> throw AssemblyError("can't use X here")
|
RegisterOrPair.XY-> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
else -> throw AssemblyError("can't assign word to single byte register")
|
else -> throw AssemblyError("can't assign word to single byte register")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,6 +556,59 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun assignVariableByteIntoWord(wordtarget: AsmAssignTarget, bytevar: IdentifierReference, valueDt: DataType) {
|
||||||
|
if(valueDt == DataType.BYTE)
|
||||||
|
TODO("sign extend byte to word")
|
||||||
|
|
||||||
|
val sourceName = asmgen.asmVariableName(bytevar)
|
||||||
|
when(wordtarget.kind) {
|
||||||
|
TargetStorageKind.VARIABLE -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $sourceName
|
||||||
|
sta ${wordtarget.asmVarname}
|
||||||
|
lda #0
|
||||||
|
sta ${wordtarget.asmVarname}+1
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
TargetStorageKind.ARRAY -> {
|
||||||
|
val index = wordtarget.array!!.arrayspec.index
|
||||||
|
when {
|
||||||
|
wordtarget.constArrayIndexValue!=null -> {
|
||||||
|
val scaledIdx = wordtarget.constArrayIndexValue!! * 2
|
||||||
|
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}+$scaledIdx | lda #0 | sta ${wordtarget.asmVarname}+$scaledIdx+1")
|
||||||
|
}
|
||||||
|
index is IdentifierReference -> {
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, wordtarget.datatype, CpuRegister.Y)
|
||||||
|
asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname},y | lda #0 | iny | sta ${wordtarget.asmVarname},y")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x | lda #0 | sta P8ESTACK_HI,x | dex")
|
||||||
|
asmgen.translateExpression(index)
|
||||||
|
asmgen.out(" inx | lda P8ESTACK_LO,x")
|
||||||
|
popAndWriteArrayvalueWithUnscaledIndexA(wordtarget.datatype, wordtarget.asmVarname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TargetStorageKind.REGISTER -> {
|
||||||
|
when(wordtarget.register!!) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" lda $sourceName | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda $sourceName | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName | ldy #0")
|
||||||
|
else -> throw AssemblyError("only reg pairs are words")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TargetStorageKind.STACK -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #$sourceName
|
||||||
|
sta P8ESTACK_LO,x
|
||||||
|
lda #0
|
||||||
|
sta P8ESTACK_HI,x
|
||||||
|
dex""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("other types aren't word")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) {
|
private fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) {
|
||||||
require(target.datatype in ByteDatatypes)
|
require(target.datatype in ByteDatatypes)
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
@ -571,19 +662,25 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> {}
|
RegisterOrPair.A -> {}
|
||||||
RegisterOrPair.X -> { asmgen.out(" tax") }
|
RegisterOrPair.X -> { asmgen.out(" tax") }
|
||||||
RegisterOrPair.Y -> { asmgen.out(" tay") }
|
RegisterOrPair.Y -> { asmgen.out(" tay") }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" tax | ldy #0") }
|
||||||
}
|
}
|
||||||
CpuRegister.X -> when(target.register!!) {
|
CpuRegister.X -> when(target.register!!) {
|
||||||
RegisterOrPair.A -> { asmgen.out(" txa") }
|
RegisterOrPair.A -> { asmgen.out(" txa") }
|
||||||
RegisterOrPair.X -> { }
|
RegisterOrPair.X -> { }
|
||||||
RegisterOrPair.Y -> { asmgen.out(" txy") }
|
RegisterOrPair.Y -> { asmgen.out(" txy") }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" txa | ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" txa | ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" ldy #0") }
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> when(target.register!!) {
|
CpuRegister.Y -> when(target.register!!) {
|
||||||
RegisterOrPair.A -> { asmgen.out(" tya") }
|
RegisterOrPair.A -> { asmgen.out(" tya") }
|
||||||
RegisterOrPair.X -> { asmgen.out(" tyx") }
|
RegisterOrPair.X -> { asmgen.out(" tyx") }
|
||||||
RegisterOrPair.Y -> { }
|
RegisterOrPair.Y -> { }
|
||||||
else -> throw AssemblyError("attempt to assign byte to register pair word")
|
RegisterOrPair.AY -> { asmgen.out(" tya | ldy #0") }
|
||||||
|
RegisterOrPair.AX -> { asmgen.out(" tya | ldx #0") }
|
||||||
|
RegisterOrPair.XY -> { asmgen.out(" tya | tax | ldy #0") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,7 +789,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> asmgen.out(" lda #${byte.toHex()}")
|
RegisterOrPair.A -> asmgen.out(" lda #${byte.toHex()}")
|
||||||
RegisterOrPair.X -> asmgen.out(" ldx #${byte.toHex()}")
|
RegisterOrPair.X -> asmgen.out(" ldx #${byte.toHex()}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" ldy #${byte.toHex()}")
|
RegisterOrPair.Y -> asmgen.out(" ldy #${byte.toHex()}")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" lda #${byte.toHex()} | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda #${byte.toHex()} | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldx #${byte.toHex()} | ldy #0")
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -708,7 +807,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
// optimized case for float zero
|
// optimized case for float zero
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
stz ${target.asmVarname}
|
stz ${target.asmVarname}
|
||||||
stz ${target.asmVarname}+1
|
stz ${target.asmVarname}+1
|
||||||
@ -847,7 +946,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> asmgen.out(" lda ${address.toHex()}")
|
RegisterOrPair.A -> asmgen.out(" lda ${address.toHex()}")
|
||||||
RegisterOrPair.X -> asmgen.out(" ldx ${address.toHex()}")
|
RegisterOrPair.X -> asmgen.out(" ldx ${address.toHex()}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" ldy ${address.toHex()}")
|
RegisterOrPair.Y -> asmgen.out(" ldy ${address.toHex()}")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" lda ${address.toHex()} | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda ${address.toHex()} | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy ${address.toHex()} | ldy #0")
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@ -875,7 +976,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
RegisterOrPair.A -> {}
|
RegisterOrPair.A -> {}
|
||||||
RegisterOrPair.X -> asmgen.out(" tax")
|
RegisterOrPair.X -> asmgen.out(" tax")
|
||||||
RegisterOrPair.Y -> asmgen.out(" tay")
|
RegisterOrPair.Y -> asmgen.out(" tay")
|
||||||
else -> throw AssemblyError("can't assign byte to word register apir")
|
RegisterOrPair.AX -> asmgen.out(" ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" tax | ldy #0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
@ -886,6 +989,63 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun assignMemoryByteIntoWord(wordtarget: AsmAssignTarget, address: Int?, identifier: IdentifierReference?) {
|
||||||
|
if (address != null) {
|
||||||
|
when(wordtarget.kind) {
|
||||||
|
TargetStorageKind.VARIABLE -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda ${address.toHex()}
|
||||||
|
sta ${wordtarget.asmVarname}
|
||||||
|
lda #0
|
||||||
|
sta ${wordtarget.asmVarname}+1
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
TargetStorageKind.ARRAY -> {
|
||||||
|
throw AssemblyError("no asm gen for assign memory byte at $address to array ${wordtarget.asmVarname}")
|
||||||
|
}
|
||||||
|
TargetStorageKind.REGISTER -> when(wordtarget.register!!) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" lda ${address.toHex()} | ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda ${address.toHex()} | ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy ${address.toHex()} | ldy #0")
|
||||||
|
else -> throw AssemblyError("word regs can only be pair")
|
||||||
|
}
|
||||||
|
TargetStorageKind.STACK -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda ${address.toHex()}
|
||||||
|
sta P8ESTACK_LO,x
|
||||||
|
lda #0
|
||||||
|
sta P8ESTACK_HI,x
|
||||||
|
dex""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("other types aren't word")
|
||||||
|
}
|
||||||
|
} else if (identifier != null) {
|
||||||
|
when(wordtarget.kind) {
|
||||||
|
TargetStorageKind.VARIABLE -> {
|
||||||
|
asmgen.loadByteFromPointerIntoA(identifier)
|
||||||
|
asmgen.out(" sta ${wordtarget.asmVarname} | lda #0 | sta ${wordtarget.asmVarname}+1")
|
||||||
|
}
|
||||||
|
TargetStorageKind.ARRAY -> {
|
||||||
|
throw AssemblyError("no asm gen for assign memory byte $identifier to array ${wordtarget.asmVarname} ")
|
||||||
|
}
|
||||||
|
TargetStorageKind.REGISTER -> {
|
||||||
|
asmgen.loadByteFromPointerIntoA(identifier)
|
||||||
|
when(wordtarget.register!!) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" ldx #0")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" ldy #0")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" tax | ldy #0")
|
||||||
|
else -> throw AssemblyError("word regs can only be pair")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TargetStorageKind.STACK -> {
|
||||||
|
asmgen.loadByteFromPointerIntoA(identifier)
|
||||||
|
asmgen.out(" sta P8ESTACK_LO,x | lda #0 | sta P8ESTACK_HI,x | dex")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("other types aren't word")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun storeByteViaRegisterAInMemoryAddress(ldaInstructionArg: String, memoryAddress: DirectMemoryWrite) {
|
private fun storeByteViaRegisterAInMemoryAddress(ldaInstructionArg: String, memoryAddress: DirectMemoryWrite) {
|
||||||
val addressExpr = memoryAddress.addressExpression
|
val addressExpr = memoryAddress.addressExpression
|
||||||
val addressLv = addressExpr as? NumericLiteralValue
|
val addressLv = addressExpr as? NumericLiteralValue
|
||||||
|
@ -8,6 +8,7 @@ import prog8.compiler.target.CompilationTarget
|
|||||||
import prog8.compiler.target.CpuType
|
import prog8.compiler.target.CpuType
|
||||||
import prog8.compiler.target.c64.codegen.AsmGen
|
import prog8.compiler.target.c64.codegen.AsmGen
|
||||||
import prog8.compiler.toHex
|
import prog8.compiler.toHex
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||||
private val assignmentAsmGen: AssignmentAsmGen,
|
private val assignmentAsmGen: AssignmentAsmGen,
|
||||||
@ -22,8 +23,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// A = -A , A = +A, A = ~A, A = not A
|
// A = -A , A = +A, A = ~A, A = not A
|
||||||
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
when (value.operator) {
|
when (value.operator) {
|
||||||
"+" -> {
|
"+" -> {}
|
||||||
}
|
|
||||||
"-" -> inplaceNegate(assign.target, type)
|
"-" -> inplaceNegate(assign.target, type)
|
||||||
"~" -> inplaceInvert(assign.target, type)
|
"~" -> inplaceInvert(assign.target, type)
|
||||||
"not" -> inplaceBooleanNot(assign.target, type)
|
"not" -> inplaceBooleanNot(assign.target, type)
|
||||||
@ -193,7 +193,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
asmgen.translateExpression(memory.addressExpression)
|
asmgen.translateExpression(memory.addressExpression)
|
||||||
// TODO buggy?:
|
// TODO buggy?:
|
||||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
|
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
|
||||||
val zp = CompilationTarget.machine.zeropage
|
val zp = CompilationTarget.instance.machine.zeropage
|
||||||
when {
|
when {
|
||||||
valueLv != null -> inplaceModification_byte_litval_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv.toInt())
|
valueLv != null -> inplaceModification_byte_litval_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv.toInt())
|
||||||
ident != null -> inplaceModification_byte_variable_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident)
|
ident != null -> inplaceModification_byte_variable_to_variable(zp.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident)
|
||||||
@ -250,7 +250,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
else
|
else
|
||||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||||
}
|
}
|
||||||
"*" -> TODO("mul mem byte")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> {
|
||||||
|
TODO("mul mem byte")// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
|
}
|
||||||
"/" -> TODO("div mem byte")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
"/" -> TODO("div mem byte")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("mem byte remainder")
|
TODO("mem byte remainder")
|
||||||
@ -309,7 +311,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
else
|
else
|
||||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||||
}
|
}
|
||||||
"*" -> TODO("mem mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> {
|
||||||
|
TODO("mem mul")// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
|
}
|
||||||
"/" -> TODO("mem div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
"/" -> TODO("mem div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("mem byte remainder")
|
TODO("mem byte remainder")
|
||||||
@ -367,8 +371,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
TODO("mem mul byte litval")
|
if(value in asmgen.optimizedByteMultiplications) {
|
||||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
TODO("optimized mem mul ubyte litval $value")
|
||||||
|
} else {
|
||||||
|
TODO("mem mul ubyte litval $value")
|
||||||
|
// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if(value==0)
|
if(value==0)
|
||||||
@ -443,7 +451,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
"-" -> asmgen.out(" lda $name | sec | sbc P8ESTACK_LO+1,x | sta $name")
|
"-" -> asmgen.out(" lda $name | sec | sbc P8ESTACK_LO+1,x | sta $name")
|
||||||
"*" -> {
|
"*" -> {
|
||||||
TODO("var mul byte expr")
|
TODO("var mul byte expr")
|
||||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
TODO("var div byte expr")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
TODO("var div byte expr")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
@ -572,9 +580,21 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
"+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name")
|
"+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name")
|
||||||
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
|
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
|
||||||
"*" -> {
|
"*" -> {
|
||||||
// TODO what about the optimized mul_5 etc routines?
|
if(dt == DataType.UBYTE) {
|
||||||
TODO("var byte mul litval")
|
if(value in asmgen.optimizedByteMultiplications) {
|
||||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
asmgen.out(" lda $name | jsr math.mul_byte_$value | sta $name")
|
||||||
|
} else {
|
||||||
|
TODO("var mul ubyte litval $value")
|
||||||
|
// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(value.absoluteValue in asmgen.optimizedByteMultiplications) {
|
||||||
|
asmgen.out(" lda $name | jsr math.mul_byte_$value | sta $name")
|
||||||
|
} else {
|
||||||
|
TODO("var mul sbyte litval $value")
|
||||||
|
// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if (dt == DataType.UBYTE) {
|
if (dt == DataType.UBYTE) {
|
||||||
@ -669,19 +689,32 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
// TODO what about the optimized mul_5 etc routines?
|
if(dt == DataType.UWORD){
|
||||||
asmgen.out("""
|
if(value in asmgen.optimizedWordMultiplications) {
|
||||||
lda $name
|
asmgen.out(" lda $name | ldy $name+1 | jsr math.mul_word_$value | sta $name | sty $name+1")
|
||||||
sta P8ZP_SCRATCH_W1
|
} else {
|
||||||
lda $name+1
|
TODO("var uword mul litval $value")
|
||||||
sta P8ZP_SCRATCH_W1+1
|
}
|
||||||
lda #<$value
|
} else {
|
||||||
ldy #>$value
|
if(value.absoluteValue in asmgen.optimizedWordMultiplications) {
|
||||||
jsr math.multiply_words
|
asmgen.out(" lda $name | ldy $name+1 | jsr math.mul_word_$value | sta $name | sty $name+1")
|
||||||
lda math.multiply_words.result
|
} else {
|
||||||
sta $name
|
// TODO don't use stack here
|
||||||
lda math.multiply_words.result+1
|
// TODO does this work for signed words?
|
||||||
sta $name+1""")
|
asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda $name+1
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
lda #<$value
|
||||||
|
ldy #>$value
|
||||||
|
jsr math.multiply_words
|
||||||
|
lda math.multiply_words.result
|
||||||
|
sta $name
|
||||||
|
lda math.multiply_words.result+1
|
||||||
|
sta $name+1""")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if(value==0)
|
if(value==0)
|
||||||
@ -747,13 +780,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
"&" -> {
|
"&" -> {
|
||||||
when {
|
when {
|
||||||
value == 0 -> {
|
value == 0 -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz $name | stz $name+1")
|
asmgen.out(" stz $name | stz $name+1")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta $name | sta $name+1")
|
asmgen.out(" lda #0 | sta $name | sta $name+1")
|
||||||
}
|
}
|
||||||
value and 255 == 0 -> {
|
value and 255 == 0 -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz $name")
|
asmgen.out(" stz $name")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta $name")
|
asmgen.out(" lda #0 | sta $name")
|
||||||
@ -761,7 +794,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
value < 0x0100 -> {
|
value < 0x0100 -> {
|
||||||
asmgen.out(" lda $name | and #$value | sta $name")
|
asmgen.out(" lda $name | and #$value | sta $name")
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz $name+1")
|
asmgen.out(" stz $name+1")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta $name+1")
|
asmgen.out(" lda #0 | sta $name+1")
|
||||||
@ -1088,11 +1121,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// because the value is evaluated onto the eval stack (=slow).
|
// because the value is evaluated onto the eval stack (=slow).
|
||||||
println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
||||||
asmgen.translateExpression(value)
|
asmgen.translateExpression(value)
|
||||||
|
asmgen.out(" jsr c64flt.pop_float_fac1")
|
||||||
asmgen.saveRegister(CpuRegister.X)
|
asmgen.saveRegister(CpuRegister.X)
|
||||||
when (operator) {
|
when (operator) {
|
||||||
"**" -> {
|
"**" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
jsr c64flt.pop_float_fac1
|
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
jsr c64flt.CONUPK
|
jsr c64flt.CONUPK
|
||||||
@ -1101,7 +1134,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
"+" -> {
|
"+" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
jsr c64flt.pop_float_fac1
|
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
jsr c64flt.FADD
|
jsr c64flt.FADD
|
||||||
@ -1109,7 +1141,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
"-" -> {
|
"-" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
jsr c64flt.pop_float_fac1
|
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
jsr c64flt.FSUB
|
jsr c64flt.FSUB
|
||||||
@ -1117,7 +1148,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
jsr c64flt.pop_float_fac1
|
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
jsr c64flt.FMULT
|
jsr c64flt.FMULT
|
||||||
@ -1125,7 +1155,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
jsr c64flt.pop_float_fac1
|
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
jsr c64flt.FDIV
|
jsr c64flt.FDIV
|
||||||
@ -1133,7 +1162,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid operator for in-place float modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place float modification $operator")
|
||||||
}
|
}
|
||||||
// store Fac1 back into memory
|
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
ldx #<$name
|
ldx #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
@ -1250,6 +1278,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
|
// assume that code optimization is already done on the AST level for special cases such as 0, 1, 2...
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda #<$name
|
lda #<$name
|
||||||
ldy #>$name
|
ldy #>$name
|
||||||
@ -1285,7 +1314,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {
|
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {
|
||||||
val outerCastDt = cast.type
|
val outerCastDt = cast.type
|
||||||
val innerCastDt = (cast.expression as? TypecastExpression)?.type
|
val innerCastDt = (cast.expression as? TypecastExpression)?.type
|
||||||
|
|
||||||
if (innerCastDt == null) {
|
if (innerCastDt == null) {
|
||||||
// simple typecast where the value is the target
|
// simple typecast where the value is the target
|
||||||
when (target.datatype) {
|
when (target.datatype) {
|
||||||
@ -1295,20 +1323,20 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz ${target.asmVarname}+1")
|
asmgen.out(" stz ${target.asmVarname}+1")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta ${target.asmVarname}+1")
|
asmgen.out(" lda #0 | sta ${target.asmVarname}+1")
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, target.datatype, CpuRegister.Y, true)
|
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, target.datatype, CpuRegister.Y, true)
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz ${target.asmVarname},y")
|
asmgen.out(" stz ${target.asmVarname},y")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta ${target.asmVarname},y")
|
asmgen.out(" lda #0 | sta ${target.asmVarname},y")
|
||||||
}
|
}
|
||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||||
asmgen.out(" stz P8ESTACK_HI+1,x")
|
asmgen.out(" stz P8ESTACK_HI+1,x")
|
||||||
else
|
else
|
||||||
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")
|
asmgen.out(" lda #0 | sta P8ESTACK_HI+1,x")
|
||||||
|
@ -26,7 +26,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
|||||||
override val ESTACK_HI = 0x0500 // $0500-$05ff inclusive
|
override val ESTACK_HI = 0x0500 // $0500-$05ff inclusive
|
||||||
|
|
||||||
override lateinit var zeropage: Zeropage
|
override lateinit var zeropage: Zeropage
|
||||||
override val initSystemProcname = "cx16.init_system"
|
|
||||||
|
|
||||||
override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num)
|
override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num)
|
||||||
|
|
||||||
@ -75,7 +74,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
override val SCRATCH_B1 = 0x79 // temp storage for a single byte
|
override val SCRATCH_B1 = 0x79 // temp storage for a single byte
|
||||||
override val SCRATCH_REG = 0x7a // temp storage for a register
|
override val SCRATCH_REG = 0x7a // temp storage for a register
|
||||||
override val SCRATCH_REG_X = 0x7b // temp storage for register X (the evaluation stack pointer)
|
|
||||||
override val SCRATCH_W1 = 0x7c // temp storage 1 for a word $7c+$7d
|
override val SCRATCH_W1 = 0x7c // temp storage 1 for a word $7c+$7d
|
||||||
override val SCRATCH_W2 = 0x7e // temp storage 2 for a word $7e+$7f
|
override val SCRATCH_W2 = 0x7e // temp storage 2 for a word $7e+$7f
|
||||||
|
|
||||||
@ -96,16 +94,16 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
|||||||
when (options.zeropage) {
|
when (options.zeropage) {
|
||||||
ZeropageType.FULL -> {
|
ZeropageType.FULL -> {
|
||||||
free.addAll(0x22..0xff)
|
free.addAll(0x22..0xff)
|
||||||
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
||||||
}
|
}
|
||||||
ZeropageType.KERNALSAFE -> {
|
ZeropageType.KERNALSAFE -> {
|
||||||
free.addAll(0x22..0x7f)
|
free.addAll(0x22..0x7f)
|
||||||
free.addAll(0xa9..0xff)
|
free.addAll(0xa9..0xff)
|
||||||
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
||||||
}
|
}
|
||||||
ZeropageType.BASICSAFE -> {
|
ZeropageType.BASICSAFE -> {
|
||||||
free.addAll(0x22..0x7f)
|
free.addAll(0x22..0x7f)
|
||||||
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1, SCRATCH_W2, SCRATCH_W2 + 1))
|
||||||
}
|
}
|
||||||
ZeropageType.DONTUSE -> {
|
ZeropageType.DONTUSE -> {
|
||||||
free.clear() // don't use zeropage at all
|
free.clear() // don't use zeropage at all
|
||||||
@ -115,7 +113,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
require(SCRATCH_B1 !in free)
|
require(SCRATCH_B1 !in free)
|
||||||
require(SCRATCH_REG !in free)
|
require(SCRATCH_REG !in free)
|
||||||
require(SCRATCH_REG_X !in free)
|
|
||||||
require(SCRATCH_W1 !in free)
|
require(SCRATCH_W1 !in free)
|
||||||
require(SCRATCH_W2 !in free)
|
require(SCRATCH_W2 !in free)
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||||||
if(rangeExpr==null && litval!=null) {
|
if(rangeExpr==null && litval!=null) {
|
||||||
// arraysize initializer is a single int, and we know the size.
|
// arraysize initializer is a single int, and we know the size.
|
||||||
val fillvalue = litval.number.toDouble()
|
val fillvalue = litval.number.toDouble()
|
||||||
if (fillvalue < CompilationTarget.machine.FLOAT_MAX_NEGATIVE || fillvalue > CompilationTarget.machine.FLOAT_MAX_POSITIVE)
|
if (fillvalue < CompilationTarget.instance.machine.FLOAT_MAX_NEGATIVE || fillvalue > CompilationTarget.instance.machine.FLOAT_MAX_POSITIVE)
|
||||||
errors.err("float value overflow", litval.position)
|
errors.err("float value overflow", litval.position)
|
||||||
else {
|
else {
|
||||||
// create the array itself, filled with the fillvalue.
|
// create the array itself, filled with the fillvalue.
|
||||||
|
@ -297,6 +297,49 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
||||||
|
if(functionCall.target.nameInSource == listOf("lsb")) {
|
||||||
|
val arg = functionCall.args[0]
|
||||||
|
if(arg is TypecastExpression) {
|
||||||
|
val valueDt = arg.expression.inferType(program)
|
||||||
|
if (valueDt.istype(DataType.BYTE) || valueDt.istype(DataType.UBYTE)) {
|
||||||
|
// useless lsb() of byte value that was casted to word
|
||||||
|
return listOf(IAstModification.ReplaceNode(functionCall, arg.expression, parent))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val argDt = arg.inferType(program)
|
||||||
|
if (argDt.istype(DataType.BYTE) || argDt.istype(DataType.UBYTE)) {
|
||||||
|
// useless lsb() of byte value
|
||||||
|
return listOf(IAstModification.ReplaceNode(functionCall, arg, parent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(functionCall.target.nameInSource == listOf("msb")) {
|
||||||
|
val arg = functionCall.args[0]
|
||||||
|
if(arg is TypecastExpression) {
|
||||||
|
val valueDt = arg.expression.inferType(program)
|
||||||
|
if (valueDt.istype(DataType.BYTE) || valueDt.istype(DataType.UBYTE)) {
|
||||||
|
// useless msb() of byte value that was casted to word, replace with 0
|
||||||
|
return listOf(IAstModification.ReplaceNode(
|
||||||
|
functionCall,
|
||||||
|
NumericLiteralValue(valueDt.typeOrElse(DataType.UBYTE), 0, arg.expression.position),
|
||||||
|
parent))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val argDt = arg.inferType(program)
|
||||||
|
if (argDt.istype(DataType.BYTE) || argDt.istype(DataType.UBYTE)) {
|
||||||
|
// useless msb() of byte value, replace with 0
|
||||||
|
return listOf(IAstModification.ReplaceNode(
|
||||||
|
functionCall,
|
||||||
|
NumericLiteralValue(argDt.typeOrElse(DataType.UBYTE), 0, arg.position),
|
||||||
|
parent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
private fun determineY(x: Expression, subBinExpr: BinaryExpression): Expression? {
|
private fun determineY(x: Expression, subBinExpr: BinaryExpression): Expression? {
|
||||||
return when {
|
return when {
|
||||||
subBinExpr.left isSameAs x -> subBinExpr.right
|
subBinExpr.left isSameAs x -> subBinExpr.right
|
||||||
|
@ -104,7 +104,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
if(string!=null) {
|
if(string!=null) {
|
||||||
val pos = functionCallStatement.position
|
val pos = functionCallStatement.position
|
||||||
if (string.value.length == 1) {
|
if (string.value.length == 1) {
|
||||||
val firstCharEncoded = CompilationTarget.encodeString(string.value, string.altEncoding)[0]
|
val firstCharEncoded = CompilationTarget.instance.encodeString(string.value, string.altEncoding)[0]
|
||||||
val chrout = FunctionCallStatement(
|
val chrout = FunctionCallStatement(
|
||||||
IdentifierReference(listOf("c64", "CHROUT"), pos),
|
IdentifierReference(listOf("c64", "CHROUT"), pos),
|
||||||
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstCharEncoded.toInt(), pos)),
|
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstCharEncoded.toInt(), pos)),
|
||||||
@ -112,7 +112,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
)
|
)
|
||||||
return listOf(IAstModification.ReplaceNode(functionCallStatement, chrout, parent))
|
return listOf(IAstModification.ReplaceNode(functionCallStatement, chrout, parent))
|
||||||
} else if (string.value.length == 2) {
|
} else if (string.value.length == 2) {
|
||||||
val firstTwoCharsEncoded = CompilationTarget.encodeString(string.value.take(2), string.altEncoding)
|
val firstTwoCharsEncoded = CompilationTarget.instance.encodeString(string.value.take(2), string.altEncoding)
|
||||||
val chrout1 = FunctionCallStatement(
|
val chrout1 = FunctionCallStatement(
|
||||||
IdentifierReference(listOf("c64", "CHROUT"), pos),
|
IdentifierReference(listOf("c64", "CHROUT"), pos),
|
||||||
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstTwoCharsEncoded[0].toInt(), pos)),
|
mutableListOf(NumericLiteralValue(DataType.UBYTE, firstTwoCharsEncoded[0].toInt(), pos)),
|
||||||
@ -220,7 +220,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
val size = sv.value.length
|
val size = sv.value.length
|
||||||
if(size==1) {
|
if(size==1) {
|
||||||
// loop over string of length 1 -> just assign the single character
|
// loop over string of length 1 -> just assign the single character
|
||||||
val character = CompilationTarget.encodeString(sv.value, sv.altEncoding)[0]
|
val character = CompilationTarget.instance.encodeString(sv.value, sv.altEncoding)[0]
|
||||||
val byte = NumericLiteralValue(DataType.UBYTE, character, iterable.position)
|
val byte = NumericLiteralValue(DataType.UBYTE, character, iterable.position)
|
||||||
val scope = AnonymousScope(mutableListOf(), forLoop.position)
|
val scope = AnonymousScope(mutableListOf(), forLoop.position)
|
||||||
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, forLoop.position))
|
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, forLoop.position))
|
||||||
|
@ -129,7 +129,7 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNames() {
|
fun testNames() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, "c64"))
|
||||||
|
|
||||||
zp.allocate("", DataType.UBYTE, null, errors)
|
zp.allocate("", DataType.UBYTE, null, errors)
|
||||||
zp.allocate("", DataType.UBYTE, null, errors)
|
zp.allocate("", DataType.UBYTE, null, errors)
|
||||||
@ -142,37 +142,37 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testZpFloatEnable() {
|
fun testZpFloatEnable() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||||
assertFailsWith<CompilerException> {
|
assertFailsWith<CompilerException> {
|
||||||
zp.allocate("", DataType.FLOAT, null, errors)
|
zp.allocate("", DataType.FLOAT, null, errors)
|
||||||
}
|
}
|
||||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true))
|
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, "c64"))
|
||||||
assertFailsWith<CompilerException> {
|
assertFailsWith<CompilerException> {
|
||||||
zp2.allocate("", DataType.FLOAT, null, errors)
|
zp2.allocate("", DataType.FLOAT, null, errors)
|
||||||
}
|
}
|
||||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true))
|
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, "c64"))
|
||||||
zp3.allocate("", DataType.FLOAT, null, errors)
|
zp3.allocate("", DataType.FLOAT, null, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testZpModesWithFloats() {
|
fun testZpModesWithFloats() {
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, "c64"))
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, "c64"))
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, "c64"))
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, "c64"))
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, "c64"))
|
||||||
assertFailsWith<CompilerException> {
|
assertFailsWith<CompilerException> {
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, "c64"))
|
||||||
}
|
}
|
||||||
assertFailsWith<CompilerException> {
|
assertFailsWith<CompilerException> {
|
||||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true))
|
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, "c64"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testZpDontuse() {
|
fun testZpDontuse() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, "c64"))
|
||||||
println(zp.free)
|
println(zp.free)
|
||||||
assertEquals(0, zp.available())
|
assertEquals(0, zp.available())
|
||||||
assertFailsWith<CompilerException> {
|
assertFailsWith<CompilerException> {
|
||||||
@ -182,19 +182,19 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFreeSpaces() {
|
fun testFreeSpaces() {
|
||||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, "c64"))
|
||||||
assertEquals(16, zp1.available())
|
assertEquals(16, zp1.available())
|
||||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false))
|
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, "c64"))
|
||||||
assertEquals(91, zp2.available())
|
assertEquals(91, zp2.available())
|
||||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false))
|
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, "c64"))
|
||||||
assertEquals(125, zp3.available())
|
assertEquals(125, zp3.available())
|
||||||
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||||
assertEquals(238, zp4.available())
|
assertEquals(238, zp4.available())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testReservedSpace() {
|
fun testReservedSpace() {
|
||||||
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||||
assertEquals(238, zp1.available())
|
assertEquals(238, zp1.available())
|
||||||
assertTrue(50 in zp1.free)
|
assertTrue(50 in zp1.free)
|
||||||
assertTrue(100 in zp1.free)
|
assertTrue(100 in zp1.free)
|
||||||
@ -203,7 +203,7 @@ class TestC64Zeropage {
|
|||||||
assertTrue(200 in zp1.free)
|
assertTrue(200 in zp1.free)
|
||||||
assertTrue(255 in zp1.free)
|
assertTrue(255 in zp1.free)
|
||||||
assertTrue(199 in zp1.free)
|
assertTrue(199 in zp1.free)
|
||||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false))
|
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false, "c64"))
|
||||||
assertEquals(139, zp2.available())
|
assertEquals(139, zp2.available())
|
||||||
assertFalse(50 in zp2.free)
|
assertFalse(50 in zp2.free)
|
||||||
assertFalse(100 in zp2.free)
|
assertFalse(100 in zp2.free)
|
||||||
@ -216,7 +216,7 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBasicsafeAllocation() {
|
fun testBasicsafeAllocation() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, "c64"))
|
||||||
assertEquals(16, zp.available())
|
assertEquals(16, zp.available())
|
||||||
|
|
||||||
assertFailsWith<ZeropageDepletedError> {
|
assertFailsWith<ZeropageDepletedError> {
|
||||||
@ -239,7 +239,7 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFullAllocation() {
|
fun testFullAllocation() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||||
assertEquals(238, zp.available())
|
assertEquals(238, zp.available())
|
||||||
val loc = zp.allocate("", DataType.UWORD, null, errors)
|
val loc = zp.allocate("", DataType.UWORD, null, errors)
|
||||||
assertTrue(loc > 3)
|
assertTrue(loc > 3)
|
||||||
@ -269,7 +269,7 @@ class TestC64Zeropage {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEfficientAllocation() {
|
fun testEfficientAllocation() {
|
||||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, "c64"))
|
||||||
assertEquals(16, zp.available())
|
assertEquals(16, zp.available())
|
||||||
assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors))
|
assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors))
|
||||||
assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors))
|
assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors))
|
||||||
|
@ -33,6 +33,14 @@ This makes it easier to understand and relate the generated code. Examples::
|
|||||||
Directives
|
Directives
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
.. data:: %target <target>
|
||||||
|
|
||||||
|
Level: module.
|
||||||
|
Global setting, selects a compilation target from within the source file.
|
||||||
|
The default compilation target is "c64" which targets the Commodore-64 machine.
|
||||||
|
You can also omit this and use the ``-target`` command line option.
|
||||||
|
|
||||||
|
|
||||||
.. data:: %output <type>
|
.. data:: %output <type>
|
||||||
|
|
||||||
Level: module.
|
Level: module.
|
||||||
@ -514,18 +522,20 @@ and returning stuff in several registers as well. The ``clobbers`` clause is use
|
|||||||
what CPU registers are clobbered by the call instead of being unchanged or returning a meaningful result value.
|
what CPU registers are clobbered by the call instead of being unchanged or returning a meaningful result value.
|
||||||
|
|
||||||
|
|
||||||
Subroutines that are implemented purely in assembly code and which have an assembly calling convention (i.e.
|
User subroutines in the program source code that are implemented purely in assembly and which have an assembly calling convention (i.e.
|
||||||
the parameters are strictly passed via cpu registers), are defined like this::
|
the parameters are strictly passed via cpu registers), are defined with ``asmsub`` like this::
|
||||||
|
|
||||||
asmsub FREADS32() clobbers(A,X,Y) {
|
asmsub clear_screenchars (ubyte char @ A) clobbers(Y) {
|
||||||
%asm {{
|
%asm {{
|
||||||
lda $62
|
ldy #0
|
||||||
eor #$ff
|
_loop sta c64.Screen,y
|
||||||
asl a
|
sta c64.Screen+$0100,y
|
||||||
lda #0
|
sta c64.Screen+$0200,y
|
||||||
ldx #$a0
|
sta c64.Screen+$02e8,y
|
||||||
jmp $bc4f
|
iny
|
||||||
}}
|
bne _loop
|
||||||
|
rts
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
the statement body of such a subroutine should consist of just an inline assembly block.
|
the statement body of such a subroutine should consist of just an inline assembly block.
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- optimize assignment codegeneration
|
- get rid of all other TODO's in the code ;-)
|
||||||
- get rid of all TODO's ;-)
|
- line-circle-gfx examples are now a few hundred bytes larger than before. Why is that, can it be fixed?
|
||||||
|
- compiler errors and warnings in standard format so the IDE shows them as clickable links; ./test.asm:2578:3: blablabla
|
||||||
|
- further optimize assignment codegeneration
|
||||||
|
- auto select correct library to import based on target, instead of having c64- and cx16- prefix variants
|
||||||
|
- implement @stack for asmsub parameters
|
||||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
|
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
|
||||||
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
||||||
- aliases for imported symbols for example perhaps '%alias print = c64scr.print' ?
|
- aliases for imported symbols for example perhaps '%alias print = c64scr.print' ?
|
||||||
- investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs
|
|
||||||
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
|
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ main {
|
|||||||
float Azy = cosb*sinc
|
float Azy = cosb*sinc
|
||||||
float Azz = cosb*cosc
|
float Azz = cosb*cosc
|
||||||
|
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 0 to len(xcoor)-1 {
|
for i in 0 to len(xcoor)-1 {
|
||||||
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
||||||
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
|
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
|
||||||
@ -69,7 +69,7 @@ main {
|
|||||||
|
|
||||||
; plot the points of the 3d cube
|
; plot the points of the 3d cube
|
||||||
; first the points on the back, then the points on the front (painter algorithm)
|
; first the points on the back, then the points on the front (painter algorithm)
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
float rz
|
float rz
|
||||||
float persp
|
float persp
|
||||||
ubyte sx
|
ubyte sx
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
%import c64lib
|
%import c64lib
|
||||||
%import c64graphics
|
%import c64graphics
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
const uword width = 255
|
|
||||||
const uword height = 200
|
|
||||||
|
|
||||||
; vertices
|
; vertices
|
||||||
word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
||||||
word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
||||||
@ -69,7 +65,7 @@ main {
|
|||||||
word Azy = wcosb*wsinc / 128
|
word Azy = wcosb*wsinc / 128
|
||||||
word Azz = wcosb*wcosc / 128
|
word Azz = wcosb*wcosc / 128
|
||||||
|
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 0 to len(xcoor)-1 {
|
for i in 0 to len(xcoor)-1 {
|
||||||
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||||
rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i])
|
rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i])
|
||||||
@ -78,17 +74,21 @@ main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uword screen_width = 320
|
||||||
|
const ubyte screen_height = 200
|
||||||
|
|
||||||
|
|
||||||
sub draw_lines() {
|
sub draw_lines() {
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in len(edgesFrom) -1 downto 0 {
|
for i in len(edgesFrom) -1 downto 0 {
|
||||||
ubyte vFrom = edgesFrom[i]
|
ubyte @zp vFrom = edgesFrom[i]
|
||||||
ubyte vTo = edgesTo[i]
|
ubyte @zp vTo = edgesTo[i] ; TODO need compiler error for double declaration if also declared outside the for loop!
|
||||||
word persp1 = 256 + rotatedz[vFrom]/256
|
word @zp persp1 = 256 + rotatedz[vFrom]/256
|
||||||
word persp2 = 256 + rotatedz[vTo]/256
|
word @zp persp2 = 256 + rotatedz[vTo]/256
|
||||||
graphics.line(rotatedx[vFrom] / persp1 + 160.w as uword,
|
graphics.line(rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||||
rotatedy[vFrom] / persp1 + 100 as ubyte,
|
rotatedy[vFrom] / persp1 + screen_height/2 as ubyte,
|
||||||
rotatedx[vTo] / persp2 + 160.w as uword,
|
rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||||
rotatedy[vTo] / persp2 + 100 as ubyte)
|
rotatedy[vTo] / persp2 + screen_height/2 as ubyte)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ main {
|
|||||||
word Azy = wcosb*wsinc / 128
|
word Azy = wcosb*wsinc / 128
|
||||||
word Azz = wcosb*wcosc / 128
|
word Azz = wcosb*wcosc / 128
|
||||||
|
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 0 to len(xcoor)-1 {
|
for i in 0 to len(xcoor)-1 {
|
||||||
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||||
rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i])
|
rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i])
|
||||||
@ -138,8 +138,8 @@ main {
|
|||||||
|
|
||||||
; first sort vertices to sprite order so the back/front order is correct as well
|
; first sort vertices to sprite order so the back/front order is correct as well
|
||||||
; (simple bubble sort as it's only 8 items to sort)
|
; (simple bubble sort as it's only 8 items to sort)
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
ubyte i1
|
ubyte @zp i1
|
||||||
for i in 6 downto 0 {
|
for i in 6 downto 0 {
|
||||||
for i1 in 0 to i {
|
for i1 in 0 to i {
|
||||||
ubyte i2 = i1+1
|
ubyte i2 = i1+1
|
||||||
@ -154,7 +154,7 @@ main {
|
|||||||
ubyte[] spritecolors = [1,1,7,15,12,11,9,9]
|
ubyte[] spritecolors = [1,1,7,15,12,11,9,9]
|
||||||
|
|
||||||
for i in 0 to 7 {
|
for i in 0 to 7 {
|
||||||
word zc = rotatedz[i]
|
word @zp zc = rotatedz[i]
|
||||||
word persp = 300+zc/256
|
word persp = 300+zc/256
|
||||||
ubyte sx = rotatedx[i] / persp + width/2 as ubyte + 20
|
ubyte sx = rotatedx[i] / persp + width/2 as ubyte + 20
|
||||||
ubyte sy = rotatedy[i] / persp + height/2 as ubyte + 40
|
ubyte sy = rotatedy[i] / persp + height/2 as ubyte + 40
|
||||||
|
@ -62,7 +62,7 @@ main {
|
|||||||
word Azy = wcosb*wsinc / 128
|
word Azy = wcosb*wsinc / 128
|
||||||
word Azz = wcosb*wcosc / 128
|
word Azz = wcosb*wcosc / 128
|
||||||
|
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 0 to len(xcoor)-1 {
|
for i in 0 to len(xcoor)-1 {
|
||||||
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||||
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
||||||
@ -76,9 +76,9 @@ main {
|
|||||||
; plot the points of the 3d cube
|
; plot the points of the 3d cube
|
||||||
; first the points on the back, then the points on the front (painter algorithm)
|
; first the points on the back, then the points on the front (painter algorithm)
|
||||||
|
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
word rz
|
word @zp rz
|
||||||
word persp
|
word @zp persp
|
||||||
byte sx
|
byte sx
|
||||||
byte sy
|
byte sy
|
||||||
|
|
||||||
|
109
examples/cx16/arithmetic/aggregates.p8
Normal file
109
examples/cx16/arithmetic/aggregates.p8
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
ubyte[] ubarr = [100, 0, 99, 199, 22]
|
||||||
|
byte[] barr = [-100, 0, 99, -122, 22]
|
||||||
|
uword[] uwarr = [1000, 0, 222, 4444, 999]
|
||||||
|
word[] warr = [-1000, 0, 999, -4444, 222]
|
||||||
|
float[] farr = [-1000.1, 0, 999.9, -4444.4, 222.2]
|
||||||
|
str name = "irmen"
|
||||||
|
ubyte ub
|
||||||
|
byte bb
|
||||||
|
word ww
|
||||||
|
uword uw
|
||||||
|
float ff
|
||||||
|
|
||||||
|
; LEN/STRLEN
|
||||||
|
ubyte length = len(name)
|
||||||
|
if length!=5 txt.print("error len1\n")
|
||||||
|
length = len(uwarr)
|
||||||
|
if length!=5 txt.print("error len2\n")
|
||||||
|
length=strlen(name)
|
||||||
|
if length!=5 txt.print("error strlen1\n")
|
||||||
|
name[3] = 0
|
||||||
|
length=strlen(name)
|
||||||
|
if length!=3 txt.print("error strlen2\n")
|
||||||
|
|
||||||
|
; MAX
|
||||||
|
ub = max(ubarr)
|
||||||
|
if ub!=199 txt.print("error max1\n")
|
||||||
|
bb = max(barr)
|
||||||
|
if bb!=99 txt.print("error max2\n")
|
||||||
|
uw = max(uwarr)
|
||||||
|
if uw!=4444 txt.print("error max3\n")
|
||||||
|
ww = max(warr)
|
||||||
|
if ww!=999 txt.print("error max4\n")
|
||||||
|
ff = max(farr)
|
||||||
|
if ff!=999.9 txt.print("error max5\n")
|
||||||
|
|
||||||
|
; MIN
|
||||||
|
ub = min(ubarr)
|
||||||
|
if ub!=0 txt.print("error min1\n")
|
||||||
|
bb = min(barr)
|
||||||
|
if bb!=-122 txt.print("error min2\n")
|
||||||
|
uw = min(uwarr)
|
||||||
|
if uw!=0 txt.print("error min3\n")
|
||||||
|
ww = min(warr)
|
||||||
|
if ww!=-4444 txt.print("error min4\n")
|
||||||
|
ff = min(farr)
|
||||||
|
if ff!=-4444.4 txt.print("error min5\n")
|
||||||
|
|
||||||
|
; SUM
|
||||||
|
uw = sum(ubarr)
|
||||||
|
if uw!=420 txt.print("error sum1\n")
|
||||||
|
ww = sum(barr)
|
||||||
|
if ww!=-101 txt.print("error sum2\n")
|
||||||
|
uw = sum(uwarr)
|
||||||
|
if uw!=6665 txt.print("error sum3\n")
|
||||||
|
ww = sum(warr)
|
||||||
|
if ww!=-4223 txt.print("error sum4\n")
|
||||||
|
ff = sum(farr)
|
||||||
|
if ff!=-4222.4 txt.print("error sum5\n")
|
||||||
|
|
||||||
|
; ANY
|
||||||
|
ub = any(ubarr)
|
||||||
|
if ub==0 txt.print("error any1\n")
|
||||||
|
ub = any(barr)
|
||||||
|
if ub==0 txt.print("error any2\n")
|
||||||
|
ub = any(uwarr)
|
||||||
|
if ub==0 txt.print("error any3\n")
|
||||||
|
ub = any(warr)
|
||||||
|
if ub==0 txt.print("error any4\n")
|
||||||
|
ub = any(farr)
|
||||||
|
if ub==0 txt.print("error any5\n")
|
||||||
|
|
||||||
|
; ALL
|
||||||
|
ub = all(ubarr)
|
||||||
|
if ub==1 txt.print("error all1\n")
|
||||||
|
ub = all(barr)
|
||||||
|
if ub==1 txt.print("error all2\n")
|
||||||
|
ub = all(uwarr)
|
||||||
|
if ub==1 txt.print("error all3\n")
|
||||||
|
ub = all(warr)
|
||||||
|
if ub==1 txt.print("error all4\n")
|
||||||
|
ub = all(farr)
|
||||||
|
if ub==1 txt.print("error all5\n")
|
||||||
|
ubarr[1]=$40
|
||||||
|
barr[1]=$40
|
||||||
|
uwarr[1]=$4000
|
||||||
|
warr[1]=$4000
|
||||||
|
farr[1]=1.1
|
||||||
|
ub = all(ubarr)
|
||||||
|
if ub==0 txt.print("error all6\n")
|
||||||
|
ub = all(barr)
|
||||||
|
if ub==0 txt.print("error all7\n")
|
||||||
|
ub = all(uwarr)
|
||||||
|
if ub==0 txt.print("error all8\n")
|
||||||
|
ub = all(warr)
|
||||||
|
if ub==0 txt.print("error all9\n")
|
||||||
|
ub = all(farr)
|
||||||
|
if ub==0 txt.print("error all10\n")
|
||||||
|
|
||||||
|
txt.print("\nyou should see no errors printed above (only at first run).")
|
||||||
|
}
|
||||||
|
}
|
924
examples/cx16/arithmetic/bitshift.p8
Normal file
924
examples/cx16/arithmetic/bitshift.p8
Normal file
@ -0,0 +1,924 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
ubyte A
|
||||||
|
|
||||||
|
txt.print("ubyte shift left\n")
|
||||||
|
A = shiftlb0()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb1()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb2()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb3()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb4()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb5()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb6()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb7()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb8()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftlb9()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
txt.print("ubyte shift right\n")
|
||||||
|
A = shiftrb0()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb1()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb2()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb3()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb4()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb5()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb6()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb7()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb8()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
A = shiftrb9()
|
||||||
|
txt.print_ubbin(A, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
txt.print("signed byte shift left\n")
|
||||||
|
byte signedb
|
||||||
|
signedb = shiftlsb0()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb1()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb2()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb3()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb4()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb5()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb6()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb7()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb8()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftlsb9()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
txt.print("signed byte shift right\n")
|
||||||
|
signedb = shiftrsb0()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb1()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb2()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb3()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb4()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb5()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb6()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb7()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb8()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
signedb = shiftrsb9()
|
||||||
|
txt.print_ubbin(signedb as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
txt.print("uword shift left\n")
|
||||||
|
uword uw
|
||||||
|
uw = shiftluw0()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw1()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw2()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw3()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw4()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw5()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw6()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw7()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw8()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw9()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw10()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw11()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw12()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw13()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw14()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw15()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw16()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftluw17()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
txt.print("uword shift right\n")
|
||||||
|
uw = shiftruw0()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw1()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw2()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw3()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw4()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw5()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw6()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw7()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw8()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw9()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw10()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw11()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw12()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw13()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw14()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw15()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw16()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = shiftruw17()
|
||||||
|
txt.print_uwbin(uw, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
txt.print("signed word shift left\n")
|
||||||
|
word sw
|
||||||
|
sw = shiftlsw0()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw1()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw2()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw3()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw4()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw5()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw6()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw7()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw8()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw9()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw10()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw11()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw12()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw13()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw14()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw15()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw16()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftlsw17()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
txt.print("enter to continue:\n")
|
||||||
|
void c64.CHRIN()
|
||||||
|
|
||||||
|
txt.print("signed word shift right\n")
|
||||||
|
sw = shiftrsw0()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw1()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw2()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw3()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw4()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw5()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw6()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw7()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw8()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw9()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw10()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw11()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw12()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw13()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw14()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw15()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw16()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
sw = shiftrsw17()
|
||||||
|
txt.print_uwbin(sw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw0() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw1() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw2() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw3() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 3
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw4() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 4
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw5() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 5
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw6() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 6
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw7() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q >> 7
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw8() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw9() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw10() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw11() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 11)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw12() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw13() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw14() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 14)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw15() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 15)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw16() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftruw17() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return (q >> 17)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub shiftrsw0() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw1() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw2() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw3() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 3
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw4() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 4
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw5() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 5
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw6() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 6
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw7() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q >> 7
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw8() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw9() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw10() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw11() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 11)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw12() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw13() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw14() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 14)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw15() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 15)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw16() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsw17() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return (q >> 17)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub shiftluw0() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw1() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw2() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw3() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw4() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw5() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 5
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw6() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 6
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw7() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 7
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw8() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 8
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw9() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 9
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw10() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 10
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw11() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 11
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw12() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 12
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw13() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 13
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw14() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 14
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw15() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 15
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw16() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 16
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftluw17() -> uword {
|
||||||
|
uword q = $a49f
|
||||||
|
return q << 17
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub shiftlsw0() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw1() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw2() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw3() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw4() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 4
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw5() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 5
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw6() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 6
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw7() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 7
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw8() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 8
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw9() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 9
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw10() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 10
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw11() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 11
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw12() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 12
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw13() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 13
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw14() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 14
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw15() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 15
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw16() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 16
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftlsw17() -> word {
|
||||||
|
word q = -12345
|
||||||
|
return q << 17
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub shiftlb0() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 0
|
||||||
|
}
|
||||||
|
sub shiftlb1() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 1
|
||||||
|
}
|
||||||
|
sub shiftlb2() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 2
|
||||||
|
}
|
||||||
|
sub shiftlb3() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 3
|
||||||
|
}
|
||||||
|
sub shiftlb4() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 4
|
||||||
|
}
|
||||||
|
sub shiftlb5() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 5
|
||||||
|
}
|
||||||
|
sub shiftlb6() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 6
|
||||||
|
}
|
||||||
|
sub shiftlb7() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 7
|
||||||
|
}
|
||||||
|
sub shiftlb8() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 8
|
||||||
|
}
|
||||||
|
sub shiftlb9() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy << 9
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrb0() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 0
|
||||||
|
}
|
||||||
|
sub shiftrb1() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 1
|
||||||
|
}
|
||||||
|
sub shiftrb2() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 2
|
||||||
|
}
|
||||||
|
sub shiftrb3() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 3
|
||||||
|
}
|
||||||
|
sub shiftrb4() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 4
|
||||||
|
}
|
||||||
|
sub shiftrb5() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 5
|
||||||
|
}
|
||||||
|
sub shiftrb6() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 6
|
||||||
|
}
|
||||||
|
sub shiftrb7() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 7
|
||||||
|
}
|
||||||
|
sub shiftrb8() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 8
|
||||||
|
}
|
||||||
|
sub shiftrb9() -> ubyte {
|
||||||
|
ubyte yy=$ed
|
||||||
|
return yy >> 9
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sub shiftlsb0() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 0
|
||||||
|
}
|
||||||
|
sub shiftlsb1() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 1
|
||||||
|
}
|
||||||
|
sub shiftlsb2() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 2
|
||||||
|
}
|
||||||
|
sub shiftlsb3() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 3
|
||||||
|
}
|
||||||
|
sub shiftlsb4() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 4
|
||||||
|
}
|
||||||
|
sub shiftlsb5() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 5
|
||||||
|
}
|
||||||
|
sub shiftlsb6() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 6
|
||||||
|
}
|
||||||
|
sub shiftlsb7() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 7
|
||||||
|
}
|
||||||
|
sub shiftlsb8() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 8
|
||||||
|
}
|
||||||
|
sub shiftlsb9() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy << 9
|
||||||
|
}
|
||||||
|
|
||||||
|
sub shiftrsb0() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 0
|
||||||
|
}
|
||||||
|
sub shiftrsb1() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 1
|
||||||
|
}
|
||||||
|
sub shiftrsb2() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 2
|
||||||
|
}
|
||||||
|
sub shiftrsb3() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 3
|
||||||
|
}
|
||||||
|
sub shiftrsb4() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 4
|
||||||
|
}
|
||||||
|
sub shiftrsb5() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 5
|
||||||
|
}
|
||||||
|
sub shiftrsb6() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 6
|
||||||
|
}
|
||||||
|
sub shiftrsb7() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 7
|
||||||
|
}
|
||||||
|
sub shiftrsb8() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 8
|
||||||
|
}
|
||||||
|
sub shiftrsb9() -> byte {
|
||||||
|
byte yy=-123
|
||||||
|
return yy >> 9
|
||||||
|
}
|
||||||
|
}
|
104
examples/cx16/arithmetic/div.p8
Normal file
104
examples/cx16/arithmetic/div.p8
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
div_ubyte(0, 1, 0)
|
||||||
|
div_ubyte(100, 6, 16)
|
||||||
|
div_ubyte(255, 2, 127)
|
||||||
|
|
||||||
|
div_byte(0, 1, 0)
|
||||||
|
div_byte(100, -6, -16)
|
||||||
|
div_byte(127, -2, -63)
|
||||||
|
|
||||||
|
div_uword(0,1,0)
|
||||||
|
div_uword(40000,500,80)
|
||||||
|
div_uword(43211,2,21605)
|
||||||
|
|
||||||
|
div_word(0,1,0)
|
||||||
|
div_word(-20000,500,-40)
|
||||||
|
div_word(-2222,2,-1111)
|
||||||
|
|
||||||
|
div_float(0,1,0)
|
||||||
|
div_float(999.9,111.0,9.008108108108107)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub div_ubyte(ubyte a1, ubyte a2, ubyte c) {
|
||||||
|
ubyte r = a1/a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("ubyte ")
|
||||||
|
txt.print_ub(a1)
|
||||||
|
txt.print(" / ")
|
||||||
|
txt.print_ub(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_ub(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub div_byte(byte a1, byte a2, byte c) {
|
||||||
|
byte r = a1/a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("byte ")
|
||||||
|
txt.print_b(a1)
|
||||||
|
txt.print(" / ")
|
||||||
|
txt.print_b(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_b(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub div_uword(uword a1, uword a2, uword c) {
|
||||||
|
uword r = a1/a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("uword ")
|
||||||
|
txt.print_uw(a1)
|
||||||
|
txt.print(" / ")
|
||||||
|
txt.print_uw(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_uw(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub div_word(word a1, word a2, word c) {
|
||||||
|
word r = a1/a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("word ")
|
||||||
|
txt.print_w(a1)
|
||||||
|
txt.print(" / ")
|
||||||
|
txt.print_w(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_w(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub div_float(float a1, float a2, float c) {
|
||||||
|
float r = a1/a2
|
||||||
|
if abs(r-c)<0.00001
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
|
||||||
|
txt.print("float ")
|
||||||
|
c64flt.print_f(a1)
|
||||||
|
txt.print(" / ")
|
||||||
|
c64flt.print_f(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
c64flt.print_f(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
112
examples/cx16/arithmetic/minus.p8
Normal file
112
examples/cx16/arithmetic/minus.p8
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
minus_ubyte(0, 0, 0)
|
||||||
|
minus_ubyte(200, 0, 200)
|
||||||
|
minus_ubyte(200, 100, 100)
|
||||||
|
minus_ubyte(100, 200, 156)
|
||||||
|
|
||||||
|
minus_byte(0, 0, 0)
|
||||||
|
minus_byte(100, 100, 0)
|
||||||
|
minus_byte(50, -50, 100)
|
||||||
|
minus_byte(0, -30, 30)
|
||||||
|
minus_byte(-30, 0, -30)
|
||||||
|
|
||||||
|
minus_uword(0,0,0)
|
||||||
|
minus_uword(50000,0, 50000)
|
||||||
|
minus_uword(50000,20000,30000)
|
||||||
|
minus_uword(20000,50000,35536)
|
||||||
|
|
||||||
|
minus_word(0,0,0)
|
||||||
|
minus_word(1000,1000,0)
|
||||||
|
minus_word(-1000,1000,-2000)
|
||||||
|
minus_word(1000,500,500)
|
||||||
|
minus_word(0,-3333,3333)
|
||||||
|
minus_word(-3333,0,-3333)
|
||||||
|
|
||||||
|
minus_float(0,0,0)
|
||||||
|
minus_float(2.5,1.5,1.0)
|
||||||
|
minus_float(-1.5,3.5,-5.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub minus_ubyte(ubyte a1, ubyte a2, ubyte c) {
|
||||||
|
ubyte r = a1-a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("ubyte ")
|
||||||
|
txt.print_ub(a1)
|
||||||
|
txt.print(" - ")
|
||||||
|
txt.print_ub(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_ub(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub minus_byte(byte a1, byte a2, byte c) {
|
||||||
|
byte r = a1-a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("byte ")
|
||||||
|
txt.print_b(a1)
|
||||||
|
txt.print(" - ")
|
||||||
|
txt.print_b(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_b(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub minus_uword(uword a1, uword a2, uword c) {
|
||||||
|
uword r = a1-a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("uword ")
|
||||||
|
txt.print_uw(a1)
|
||||||
|
txt.print(" - ")
|
||||||
|
txt.print_uw(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_uw(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub minus_word(word a1, word a2, word c) {
|
||||||
|
word r = a1-a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("word ")
|
||||||
|
txt.print_w(a1)
|
||||||
|
txt.print(" - ")
|
||||||
|
txt.print_w(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_w(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub minus_float(float a1, float a2, float c) {
|
||||||
|
float r = a1-a2
|
||||||
|
if abs(r-c)<0.00001
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
|
||||||
|
txt.print("float ")
|
||||||
|
c64flt.print_f(a1)
|
||||||
|
txt.print(" - ")
|
||||||
|
c64flt.print_f(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
c64flt.print_f(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
106
examples/cx16/arithmetic/mult.p8
Normal file
106
examples/cx16/arithmetic/mult.p8
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
mul_ubyte(0, 0, 0)
|
||||||
|
mul_ubyte(20, 1, 20)
|
||||||
|
mul_ubyte(20, 10, 200)
|
||||||
|
|
||||||
|
mul_byte(0, 0, 0)
|
||||||
|
mul_byte(10, 10, 100)
|
||||||
|
mul_byte(5, -5, -25)
|
||||||
|
mul_byte(0, -30, 0)
|
||||||
|
|
||||||
|
mul_uword(0,0,0)
|
||||||
|
mul_uword(50000,1, 50000)
|
||||||
|
mul_uword(500,100,50000)
|
||||||
|
|
||||||
|
mul_word(0,0,0)
|
||||||
|
mul_word(-10,1000,-10000)
|
||||||
|
mul_word(1,-3333,-3333)
|
||||||
|
|
||||||
|
mul_float(0,0,0)
|
||||||
|
mul_float(2.5,10,25)
|
||||||
|
mul_float(-1.5,10,-15)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul_ubyte(ubyte a1, ubyte a2, ubyte c) {
|
||||||
|
ubyte r = a1*a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("ubyte ")
|
||||||
|
txt.print_ub(a1)
|
||||||
|
txt.print(" * ")
|
||||||
|
txt.print_ub(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_ub(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul_byte(byte a1, byte a2, byte c) {
|
||||||
|
byte r = a1*a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("byte ")
|
||||||
|
txt.print_b(a1)
|
||||||
|
txt.print(" * ")
|
||||||
|
txt.print_b(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_b(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul_uword(uword a1, uword a2, uword c) {
|
||||||
|
uword r = a1*a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("uword ")
|
||||||
|
txt.print_uw(a1)
|
||||||
|
txt.print(" * ")
|
||||||
|
txt.print_uw(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_uw(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul_word(word a1, word a2, word c) {
|
||||||
|
word r = a1*a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("word ")
|
||||||
|
txt.print_w(a1)
|
||||||
|
txt.print(" * ")
|
||||||
|
txt.print_w(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_w(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul_float(float a1, float a2, float c) {
|
||||||
|
float r = a1*a2
|
||||||
|
if abs(r-c)<0.00001
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
|
||||||
|
txt.print("float ")
|
||||||
|
c64flt.print_f(a1)
|
||||||
|
txt.print(" * ")
|
||||||
|
c64flt.print_f(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
c64flt.print_f(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
110
examples/cx16/arithmetic/plus.p8
Normal file
110
examples/cx16/arithmetic/plus.p8
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
plus_ubyte(0, 0, 0)
|
||||||
|
plus_ubyte(0, 200, 200)
|
||||||
|
plus_ubyte(100, 200, 44)
|
||||||
|
|
||||||
|
plus_byte(0, 0, 0)
|
||||||
|
plus_byte(-100, 100, 0)
|
||||||
|
plus_byte(-50, 100, 50)
|
||||||
|
plus_byte(0, -30, -30)
|
||||||
|
plus_byte(-30, 0, -30)
|
||||||
|
|
||||||
|
plus_uword(0,0,0)
|
||||||
|
plus_uword(0,50000,50000)
|
||||||
|
plus_uword(50000,20000,4464)
|
||||||
|
|
||||||
|
plus_word(0,0,0)
|
||||||
|
plus_word(-1000,1000,0)
|
||||||
|
plus_word(-500,1000,500)
|
||||||
|
plus_word(0,-3333,-3333)
|
||||||
|
plus_word(-3333,0,-3333)
|
||||||
|
|
||||||
|
plus_float(0,0,0)
|
||||||
|
plus_float(1.5,2.5,4.0)
|
||||||
|
plus_float(-1.5,3.5,2.0)
|
||||||
|
plus_float(-1.1,3.3,2.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plus_ubyte(ubyte a1, ubyte a2, ubyte c) {
|
||||||
|
ubyte r = a1+a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("ubyte ")
|
||||||
|
txt.print_ub(a1)
|
||||||
|
txt.print(" + ")
|
||||||
|
txt.print_ub(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_ub(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plus_byte(byte a1, byte a2, byte c) {
|
||||||
|
byte r = a1+a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("byte ")
|
||||||
|
txt.print_b(a1)
|
||||||
|
txt.print(" + ")
|
||||||
|
txt.print_b(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_b(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plus_uword(uword a1, uword a2, uword c) {
|
||||||
|
uword r = a1+a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("uword ")
|
||||||
|
txt.print_uw(a1)
|
||||||
|
txt.print(" + ")
|
||||||
|
txt.print_uw(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_uw(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plus_word(word a1, word a2, word c) {
|
||||||
|
word r = a1+a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("word ")
|
||||||
|
txt.print_w(a1)
|
||||||
|
txt.print(" + ")
|
||||||
|
txt.print_w(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_w(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plus_float(float a1, float a2, float c) {
|
||||||
|
float r = a1+a2
|
||||||
|
if abs(r-c)<0.00001
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
|
||||||
|
txt.print("float ")
|
||||||
|
c64flt.print_f(a1)
|
||||||
|
txt.print(" + ")
|
||||||
|
c64flt.print_f(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
c64flt.print_f(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
141
examples/cx16/arithmetic/postincrdecr.p8
Normal file
141
examples/cx16/arithmetic/postincrdecr.p8
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
|
||||||
|
txt.plot(0,24)
|
||||||
|
|
||||||
|
ubyte Y
|
||||||
|
ubyte ub=200
|
||||||
|
byte bb=-100
|
||||||
|
uword uw = 2000
|
||||||
|
word ww = -1000
|
||||||
|
float fl = 999.99
|
||||||
|
ubyte[3] ubarr = 200
|
||||||
|
byte[3] barr = -100
|
||||||
|
uword[3] uwarr = 2000
|
||||||
|
word[3] warr = -1000
|
||||||
|
float[3] flarr = 999.99
|
||||||
|
|
||||||
|
txt.print("++\n")
|
||||||
|
ub++
|
||||||
|
bb++
|
||||||
|
uw++
|
||||||
|
ww++
|
||||||
|
fl++
|
||||||
|
ubarr[1]++
|
||||||
|
barr[1]++
|
||||||
|
uwarr[1]++
|
||||||
|
warr[1]++
|
||||||
|
flarr[1] ++
|
||||||
|
|
||||||
|
check_ub(ub, 201)
|
||||||
|
Y=100
|
||||||
|
Y++
|
||||||
|
check_ub(Y, 101)
|
||||||
|
check_fl(fl, 1000.99)
|
||||||
|
check_b(bb, -99)
|
||||||
|
check_uw(uw, 2001)
|
||||||
|
check_w(ww, -999)
|
||||||
|
check_ub(ubarr[0], 200)
|
||||||
|
check_fl(flarr[0], 999.99)
|
||||||
|
check_b(barr[0], -100)
|
||||||
|
check_uw(uwarr[0], 2000)
|
||||||
|
check_w(warr[0], -1000)
|
||||||
|
check_ub(ubarr[1], 201)
|
||||||
|
check_fl(flarr[1], 1000.99)
|
||||||
|
check_b(barr[1], -99)
|
||||||
|
check_uw(uwarr[1], 2001)
|
||||||
|
check_w(warr[1], -999)
|
||||||
|
|
||||||
|
txt.print("--\n")
|
||||||
|
ub--
|
||||||
|
bb--
|
||||||
|
uw--
|
||||||
|
ww--
|
||||||
|
fl--
|
||||||
|
ubarr[1]--
|
||||||
|
barr[1]--
|
||||||
|
uwarr[1]--
|
||||||
|
warr[1]--
|
||||||
|
flarr[1] --
|
||||||
|
check_ub(ub, 200)
|
||||||
|
|
||||||
|
Y=100
|
||||||
|
Y--
|
||||||
|
check_ub(Y, 99)
|
||||||
|
check_fl(fl, 999.99)
|
||||||
|
check_b(bb, -100)
|
||||||
|
check_uw(uw, 2000)
|
||||||
|
check_w(ww, -1000)
|
||||||
|
check_ub(ubarr[1], 200)
|
||||||
|
check_fl(flarr[1], 999.99)
|
||||||
|
check_b(barr[1], -100)
|
||||||
|
check_uw(uwarr[1], 2000)
|
||||||
|
check_w(warr[1], -1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_ub(ubyte value, ubyte expected) {
|
||||||
|
if value==expected
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print(" ubyte ")
|
||||||
|
txt.print_ub(value)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
txt.print_ub(expected)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_b(byte value, byte expected) {
|
||||||
|
if value==expected
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print(" byte ")
|
||||||
|
txt.print_b(value)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
txt.print_b(expected)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_uw(uword value, uword expected) {
|
||||||
|
if value==expected
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print(" uword ")
|
||||||
|
txt.print_uw(value)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
txt.print_uw(expected)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_w(word value, word expected) {
|
||||||
|
if value==expected
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print(" word ")
|
||||||
|
txt.print_w(value)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
txt.print_w(expected)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_fl(float value, float expected) {
|
||||||
|
if value==expected
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print(" float ")
|
||||||
|
c64flt.print_f(value)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
c64flt.print_f(expected)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
48
examples/cx16/arithmetic/remainder.p8
Normal file
48
examples/cx16/arithmetic/remainder.p8
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
remainder_ubyte(0, 1, 0)
|
||||||
|
remainder_ubyte(100, 6, 4)
|
||||||
|
remainder_ubyte(255, 2, 1)
|
||||||
|
remainder_ubyte(255, 20, 15)
|
||||||
|
|
||||||
|
remainder_uword(0,1,0)
|
||||||
|
remainder_uword(40000,511,142)
|
||||||
|
remainder_uword(40000,500,0)
|
||||||
|
remainder_uword(43211,12,11)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub remainder_ubyte(ubyte a1, ubyte a2, ubyte c) {
|
||||||
|
ubyte r = a1%a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("ubyte ")
|
||||||
|
txt.print_ub(a1)
|
||||||
|
txt.print(" % ")
|
||||||
|
txt.print_ub(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_ub(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
sub remainder_uword(uword a1, uword a2, uword c) {
|
||||||
|
uword r = a1%a2
|
||||||
|
if r==c
|
||||||
|
txt.print(" ok ")
|
||||||
|
else
|
||||||
|
txt.print("err! ")
|
||||||
|
txt.print("uword ")
|
||||||
|
txt.print_uw(a1)
|
||||||
|
txt.print(" % ")
|
||||||
|
txt.print_uw(a2)
|
||||||
|
txt.print(" = ")
|
||||||
|
txt.print_uw(r)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
}
|
132
examples/cx16/arithmetic/sgn.p8
Normal file
132
examples/cx16/arithmetic/sgn.p8
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
byte b1
|
||||||
|
byte b2
|
||||||
|
ubyte ub1
|
||||||
|
ubyte ub2
|
||||||
|
word w1
|
||||||
|
word w2
|
||||||
|
uword uw1
|
||||||
|
uword uw2
|
||||||
|
float f1
|
||||||
|
float f2
|
||||||
|
|
||||||
|
b1 = 10
|
||||||
|
b2 = 10
|
||||||
|
if sgn(b2-b1) != 0
|
||||||
|
txt.print("sgn1 error1\n")
|
||||||
|
|
||||||
|
b1 = -100
|
||||||
|
b2 = -100
|
||||||
|
if sgn(b2-b1) != 0
|
||||||
|
txt.print("sgn1 error2\n")
|
||||||
|
|
||||||
|
ub1 = 200
|
||||||
|
ub2 = 200
|
||||||
|
if sgn(ub2-ub1) != 0
|
||||||
|
txt.print("sgn1 error3\n")
|
||||||
|
|
||||||
|
w1 = 100
|
||||||
|
w2 = 100
|
||||||
|
if sgn(w2-w1) != 0
|
||||||
|
txt.print("sgn1 error4\n")
|
||||||
|
|
||||||
|
w1 = -2000
|
||||||
|
w2 = -2000
|
||||||
|
if sgn(w2-w1) != 0
|
||||||
|
txt.print("sgn1 error5\n")
|
||||||
|
|
||||||
|
uw1 = 999
|
||||||
|
uw2 = 999
|
||||||
|
if sgn(uw2-uw1) != 0
|
||||||
|
txt.print("sgn1 error6\n")
|
||||||
|
|
||||||
|
f1 = 3.45
|
||||||
|
f2 = 3.45
|
||||||
|
if sgn(f2-f1) != 0
|
||||||
|
txt.print("sgn1 error7\n")
|
||||||
|
|
||||||
|
|
||||||
|
; -1
|
||||||
|
b1 = 11
|
||||||
|
b2 = 10
|
||||||
|
if sgn(b2-b1) != -1
|
||||||
|
txt.print("sgn2 error1\n")
|
||||||
|
|
||||||
|
b1 = -10
|
||||||
|
b2 = -100
|
||||||
|
if sgn(b2-b1) != -1
|
||||||
|
txt.print("sgn2 error2\n")
|
||||||
|
|
||||||
|
ub1 = 202
|
||||||
|
ub2 = 200
|
||||||
|
if sgn(ub2 as byte - ub1 as byte) != -1
|
||||||
|
txt.print("sgn2 error3\n")
|
||||||
|
|
||||||
|
w1 = 101
|
||||||
|
w2 = 100
|
||||||
|
if sgn(w2-w1) != -1
|
||||||
|
txt.print("sgn2 error4\n")
|
||||||
|
|
||||||
|
w1 = -200
|
||||||
|
w2 = -2000
|
||||||
|
if sgn(w2-w1) != -1
|
||||||
|
txt.print("sgn2 error5\n")
|
||||||
|
|
||||||
|
uw1 = 2222
|
||||||
|
uw2 = 999
|
||||||
|
if sgn((uw2 as word) - (uw1 as word)) != -1
|
||||||
|
txt.print("sgn2 error6a\n")
|
||||||
|
if sgn(uw2 - uw1) != 1 ; always 0 or 1 if unsigned
|
||||||
|
txt.print("sgn2 error6b\n")
|
||||||
|
|
||||||
|
f1 = 3.45
|
||||||
|
f2 = 1.11
|
||||||
|
if sgn(f2-f1) != -1
|
||||||
|
txt.print("sgn2 error7\n")
|
||||||
|
|
||||||
|
; +1
|
||||||
|
b1 = 11
|
||||||
|
b2 = 20
|
||||||
|
if sgn(b2-b1) != 1
|
||||||
|
txt.print("sgn3 error1\n")
|
||||||
|
|
||||||
|
b1 = -10
|
||||||
|
b2 = -1
|
||||||
|
if sgn(b2-b1) != 1
|
||||||
|
txt.print("sgn3 error2\n")
|
||||||
|
|
||||||
|
ub1 = 202
|
||||||
|
ub2 = 205
|
||||||
|
if sgn(ub2-ub1) != 1
|
||||||
|
txt.print("sgn3 error3\n")
|
||||||
|
|
||||||
|
w1 = 101
|
||||||
|
w2 = 200
|
||||||
|
if sgn(w2-w1) != 1
|
||||||
|
txt.print("sgn3 error4\n")
|
||||||
|
|
||||||
|
w1 = -200
|
||||||
|
w2 = -20
|
||||||
|
if sgn(w2-w1) != 1
|
||||||
|
txt.print("sgn3 error5\n")
|
||||||
|
|
||||||
|
uw1 = 2222
|
||||||
|
uw2 = 9999
|
||||||
|
if sgn(uw2-uw1) != 1
|
||||||
|
txt.print("sgn3 error6\n")
|
||||||
|
|
||||||
|
f1 = 3.45
|
||||||
|
f2 = 5.11
|
||||||
|
if sgn(f2-f1) != 1
|
||||||
|
txt.print("sgn3 error7\n")
|
||||||
|
|
||||||
|
txt.print("should see no sgn errors\n")
|
||||||
|
}
|
||||||
|
}
|
211
examples/cx16/cobramk3-gfx.p8
Normal file
211
examples/cx16/cobramk3-gfx.p8
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16lib
|
||||||
|
%import conv
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
; storage for rotated coordinates
|
||||||
|
word[shipdata.totalNumberOfPoints] rotatedx
|
||||||
|
word[shipdata.totalNumberOfPoints] rotatedy
|
||||||
|
word[shipdata.totalNumberOfPoints] rotatedz
|
||||||
|
|
||||||
|
|
||||||
|
; TODO hidden surface removal - this needs surfaces data and surface normal calculations.
|
||||||
|
; TODO add all other Elite's ships, show their name, advance to next ship on keypress
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
uword anglex
|
||||||
|
uword angley
|
||||||
|
uword anglez
|
||||||
|
|
||||||
|
void cx16.screen_set_mode($80)
|
||||||
|
cx16.r0 = 0
|
||||||
|
cx16.GRAPH_init()
|
||||||
|
cx16.GRAPH_set_colors(13, 6, 6)
|
||||||
|
cx16.GRAPH_clear()
|
||||||
|
print_ship_name()
|
||||||
|
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||||
|
|
||||||
|
cx16.GRAPH_set_colors(0, 0, 0)
|
||||||
|
cx16.r0 = 32
|
||||||
|
cx16.r1 = 10
|
||||||
|
cx16.r2 = 256
|
||||||
|
cx16.r3 = 185
|
||||||
|
cx16.r4 = 0
|
||||||
|
cx16.GRAPH_draw_rect(true)
|
||||||
|
|
||||||
|
cx16.GRAPH_set_colors(1, 0, 0)
|
||||||
|
draw_lines()
|
||||||
|
|
||||||
|
anglex -= 505
|
||||||
|
angley += 217
|
||||||
|
anglez += 452
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_ship_name() {
|
||||||
|
cx16.r0 = 32
|
||||||
|
cx16.r1 = 8
|
||||||
|
ubyte c
|
||||||
|
for c in "ship: "
|
||||||
|
cx16.GRAPH_put_char(c)
|
||||||
|
for c in shipdata.shipName
|
||||||
|
cx16.GRAPH_put_char(c)
|
||||||
|
|
||||||
|
cx16.r0 += 16
|
||||||
|
print_number_gfx(shipdata.totalNumberOfPoints)
|
||||||
|
for c in " vertices, "
|
||||||
|
cx16.GRAPH_put_char(c)
|
||||||
|
print_number_gfx(shipdata.totalNumberOfEdges)
|
||||||
|
for c in " edges, "
|
||||||
|
cx16.GRAPH_put_char(c)
|
||||||
|
print_number_gfx(shipdata.totalNumberOfFaces)
|
||||||
|
for c in " faces"
|
||||||
|
cx16.GRAPH_put_char(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub print_number_gfx(ubyte num @ A) clobbers(A,Y) {
|
||||||
|
%asm {{
|
||||||
|
phx
|
||||||
|
jsr conv.ubyte2decimal
|
||||||
|
phx
|
||||||
|
pha
|
||||||
|
cpy #'0'
|
||||||
|
beq +
|
||||||
|
tya
|
||||||
|
jsr cx16.GRAPH_put_char
|
||||||
|
pla
|
||||||
|
jsr cx16.GRAPH_put_char
|
||||||
|
jmp _ones
|
||||||
|
+ pla
|
||||||
|
cmp #'0'
|
||||||
|
beq _ones
|
||||||
|
jsr cx16.GRAPH_put_char
|
||||||
|
_ones pla
|
||||||
|
jsr cx16.GRAPH_put_char
|
||||||
|
plx
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||||
|
; rotate around origin (0,0,0)
|
||||||
|
|
||||||
|
; set up the 3d rotation matrix values
|
||||||
|
word wcosa = cos8(ax)
|
||||||
|
word wsina = sin8(ax)
|
||||||
|
word wcosb = cos8(ay)
|
||||||
|
word wsinb = sin8(ay)
|
||||||
|
word wcosc = cos8(az)
|
||||||
|
word wsinc = sin8(az)
|
||||||
|
|
||||||
|
word wcosa_sinb = wcosa*wsinb / 128
|
||||||
|
word wsina_sinb = wsina*wsinb / 128
|
||||||
|
|
||||||
|
word Axx = wcosa*wcosb / 128
|
||||||
|
word Axy = (wcosa_sinb*wsinc - wsina*wcosc) / 128
|
||||||
|
word Axz = (wcosa_sinb*wcosc + wsina*wsinc) / 128
|
||||||
|
word Ayx = wsina*wcosb / 128
|
||||||
|
word Ayy = (wsina_sinb*wsinc + wcosa*wcosc) / 128
|
||||||
|
word Ayz = (wsina_sinb*wcosc - wcosa*wsinc) / 128
|
||||||
|
word Azx = -wsinb
|
||||||
|
word Azy = wcosb*wsinc / 128
|
||||||
|
word Azz = wcosb*wcosc / 128
|
||||||
|
|
||||||
|
ubyte @zp i
|
||||||
|
for i in 0 to shipdata.totalNumberOfPoints-1 {
|
||||||
|
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||||
|
rotatedx[i] = Axx*shipdata.xcoor[i] + Axy*shipdata.ycoor[i] + Axz*shipdata.zcoor[i]
|
||||||
|
rotatedy[i] = Ayx*shipdata.xcoor[i] + Ayy*shipdata.ycoor[i] + Ayz*shipdata.zcoor[i]
|
||||||
|
rotatedz[i] = Azx*shipdata.xcoor[i] + Azy*shipdata.ycoor[i] + Azz*shipdata.zcoor[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uword screen_width = 320
|
||||||
|
const ubyte screen_height = 200
|
||||||
|
|
||||||
|
sub draw_lines() {
|
||||||
|
ubyte @zp i
|
||||||
|
for i in shipdata.totalNumberOfEdges -1 downto 0 {
|
||||||
|
ubyte @zp vFrom = shipdata.edgesFrom[i]
|
||||||
|
ubyte @zp vTo = shipdata.edgesTo[i]
|
||||||
|
word persp1 = 200 + rotatedz[vFrom]/256
|
||||||
|
word persp2 = 200 + rotatedz[vTo]/256
|
||||||
|
cx16.r0 = rotatedx[vFrom] / persp1 + screen_width/2 as uword
|
||||||
|
cx16.r1 = rotatedy[vFrom] / persp1 + screen_height/2 as uword
|
||||||
|
cx16.r2 = rotatedx[vTo] / persp2 + screen_width/2 as uword
|
||||||
|
cx16.r3 = rotatedy[vTo] / persp2 + screen_height/2 as uword
|
||||||
|
cx16.GRAPH_draw_line()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shipdata {
|
||||||
|
|
||||||
|
; Ship model data converted from BBC Elite's Cobra MK 3
|
||||||
|
; downloaded from http://www.elitehomepage.org/archive/index.htm
|
||||||
|
|
||||||
|
const ubyte totalNumberOfEdges = 51
|
||||||
|
const ubyte totalNumberOfFaces = 22
|
||||||
|
const ubyte totalNumberOfPoints = 34
|
||||||
|
str shipName = "cobra-mk3"
|
||||||
|
; vertices
|
||||||
|
word[] xcoor = [ 32,-32,0,-120,120,-88,88,128,-128,0,-32,32,-36,-8,8,36,36,8,-8,-36,-1,-1,-80,-80,-88,80,88,80,1,1,1,1,-1,-1 ]
|
||||||
|
word[] ycoor = [ 0,0,26,-3,-3,16,16,-8,-8,26,-24,-24,8,12,12,8,-12,-16,-16,-12,-1,-1,-6,6,0,6,0,-6,-1,-1,1,1,1,1 ]
|
||||||
|
word[] zcoor = [ 76,76,24,-8,-8,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,76,90,-40,-40,-40,-40,-40,-40,76,90,76,90,76,90 ]
|
||||||
|
; edges and faces
|
||||||
|
ubyte[] edgesFrom = [ 0,1,0,10,1,0,2,0,4,0,4,7,2,1,1,3,8,3,2,5,6,5,6,16,15,14,14,18,13,12,12,26,25,25,22,23,22,20,28,21,20,28,29,30,31,30,32,20,21,20,20 ]
|
||||||
|
ubyte[] edgesTo = [ 1,2,2,11,10,11,6,6,6,4,7,11,5,5,3,5,10,8,9,9,9,8,7,17,16,15,17,19,18,13,19,27,26,27,23,24,24,28,29,29,21,30,31,31,33,32,33,32,33,33,29 ]
|
||||||
|
ubyte[] facesPoints = [
|
||||||
|
0,1,2 ,255,
|
||||||
|
11,10,1,0 ,255,
|
||||||
|
0,2,6 ,255,
|
||||||
|
6,4,0 ,255,
|
||||||
|
4,7,11,0 ,255,
|
||||||
|
5,2,1 ,255,
|
||||||
|
1,3,5 ,255,
|
||||||
|
10,8,3,1 ,255,
|
||||||
|
9,2,5 ,255,
|
||||||
|
9,6,2 ,255,
|
||||||
|
3,8,5 ,255,
|
||||||
|
4,6,7 ,255,
|
||||||
|
5,8,10,11,7,6,9 ,255,
|
||||||
|
17,16,15,14 ,255,
|
||||||
|
19,18,13,12 ,255,
|
||||||
|
27,26,25 ,255,
|
||||||
|
22,23,24 ,255,
|
||||||
|
20,28,29,21 ,255,
|
||||||
|
30,28,29,31 ,255,
|
||||||
|
33,31,30,32 ,255,
|
||||||
|
20,32,33,21 ,255,
|
||||||
|
29,31,33,20 ,255
|
||||||
|
]
|
||||||
|
ubyte[] facesEdges = [
|
||||||
|
0,1,2 ,255,
|
||||||
|
3,4,0,5 ,255,
|
||||||
|
2,6,7 ,255,
|
||||||
|
8,9,7 ,255,
|
||||||
|
10,11,5,9 ,255,
|
||||||
|
12,1,13 ,255,
|
||||||
|
14,15,13 ,255,
|
||||||
|
16,17,14,4 ,255,
|
||||||
|
18,12,19 ,255,
|
||||||
|
20,6,18 ,255,
|
||||||
|
17,21,15 ,255,
|
||||||
|
8,22,10 ,255,
|
||||||
|
21,16,3,11,22,20,19 ,255,
|
||||||
|
23,24,25,26 ,255,
|
||||||
|
27,28,29,30 ,255,
|
||||||
|
31,32,33 ,255,
|
||||||
|
34,35,36 ,255,
|
||||||
|
37,38,39,40 ,255,
|
||||||
|
41,38,42,43 ,255,
|
||||||
|
44,43,45,46 ,255,
|
||||||
|
47,46,48,40 ,255,
|
||||||
|
42,44,49,50 ,255
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
110
examples/cx16/cube3d-float.p8
Normal file
110
examples/cx16/cube3d-float.p8
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16flt
|
||||||
|
%import cx16textio
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
const uword width = 80
|
||||||
|
const uword height = 60
|
||||||
|
|
||||||
|
; vertices
|
||||||
|
float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
|
||||||
|
float[] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
|
||||||
|
float[] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
|
||||||
|
|
||||||
|
; storage for rotated coordinates
|
||||||
|
float[len(xcoor)] rotatedx=0.0
|
||||||
|
float[len(ycoor)] rotatedy=0.0
|
||||||
|
float[len(zcoor)] rotatedz=-1.0
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
float time=0.0
|
||||||
|
ubyte timer_jiffies
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
rotate_vertices(time)
|
||||||
|
txt.clear_screenchars(' ')
|
||||||
|
draw_edges()
|
||||||
|
time+=0.1
|
||||||
|
|
||||||
|
txt.plot(0,0)
|
||||||
|
txt.print("3d cube! (floating point calc) ")
|
||||||
|
|
||||||
|
%asm {{
|
||||||
|
phx
|
||||||
|
jsr c64.RDTIM ; A/X/Y
|
||||||
|
sta timer_jiffies
|
||||||
|
lda #0
|
||||||
|
jsr c64.SETTIM
|
||||||
|
plx
|
||||||
|
}}
|
||||||
|
txt.print_ub(timer_jiffies)
|
||||||
|
txt.print(" jiffies/fr = ")
|
||||||
|
txt.print_ub(60/timer_jiffies)
|
||||||
|
txt.print(" fps")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rotate_vertices(float t) {
|
||||||
|
; rotate around origin (0,0,0)
|
||||||
|
|
||||||
|
; set up the 3d rotation matrix values
|
||||||
|
float cosa = cos(t)
|
||||||
|
float sina = sin(t)
|
||||||
|
float cosb = cos(t*0.33)
|
||||||
|
float sinb = sin(t*0.33)
|
||||||
|
float cosc = cos(t*0.78)
|
||||||
|
float sinc = sin(t*0.78)
|
||||||
|
|
||||||
|
float cosa_sinb = cosa*sinb
|
||||||
|
float sina_sinb = sina*sinb
|
||||||
|
float Axx = cosa*cosb
|
||||||
|
float Axy = cosa_sinb*sinc - sina*cosc
|
||||||
|
float Axz = cosa_sinb*cosc + sina*sinc
|
||||||
|
float Ayx = sina*cosb
|
||||||
|
float Ayy = sina_sinb*sinc + cosa*cosc
|
||||||
|
float Ayz = sina_sinb*cosc - cosa*sinc
|
||||||
|
float Azx = -sinb
|
||||||
|
float Azy = cosb*sinc
|
||||||
|
float Azz = cosb*cosc
|
||||||
|
|
||||||
|
ubyte @zp i
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
||||||
|
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
|
||||||
|
rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub draw_edges() {
|
||||||
|
|
||||||
|
; plot the points of the 3d cube
|
||||||
|
; first the points on the back, then the points on the front (painter algorithm)
|
||||||
|
ubyte @zp i
|
||||||
|
float rz
|
||||||
|
float persp
|
||||||
|
ubyte sx
|
||||||
|
ubyte sy
|
||||||
|
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
rz = rotatedz[i]
|
||||||
|
if rz >= 0.1 {
|
||||||
|
persp = (5.0+rz)/(height as float)
|
||||||
|
sx = rotatedx[i] / persp + width/2.0 as ubyte
|
||||||
|
sy = rotatedy[i] / persp + height/2.0 as ubyte
|
||||||
|
txt.setcc(sx, sy, 46, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
rz = rotatedz[i]
|
||||||
|
if rz < 0.1 {
|
||||||
|
persp = (5.0+rz)/(height as float)
|
||||||
|
sx = rotatedx[i] / persp + width/2.0 as ubyte
|
||||||
|
sy = rotatedy[i] / persp + height/2.0 as ubyte
|
||||||
|
txt.setcc(sx, sy, 81, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
100
examples/cx16/cube3d.p8
Normal file
100
examples/cx16/cube3d.p8
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
%target cx16
|
||||||
|
%import cx16textio
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
const uword screen_width = 80
|
||||||
|
const uword screen_height = 60
|
||||||
|
|
||||||
|
; vertices
|
||||||
|
word[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||||
|
word[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||||
|
word[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||||
|
|
||||||
|
; storage for rotated coordinates
|
||||||
|
word[len(xcoor)] rotatedx
|
||||||
|
word[len(ycoor)] rotatedy
|
||||||
|
word[len(zcoor)] rotatedz
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
|
||||||
|
uword anglex
|
||||||
|
uword angley
|
||||||
|
uword anglez
|
||||||
|
ubyte timer_jiffies
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||||
|
txt.clear_screenchars(' ')
|
||||||
|
draw_edges()
|
||||||
|
anglex+=500
|
||||||
|
angley+=215
|
||||||
|
anglez+=453
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||||
|
; rotate around origin (0,0,0)
|
||||||
|
|
||||||
|
; set up the 3d rotation matrix values
|
||||||
|
word wcosa = cos8(ax)
|
||||||
|
word wsina = sin8(ax)
|
||||||
|
word wcosb = cos8(ay)
|
||||||
|
word wsinb = sin8(ay)
|
||||||
|
word wcosc = cos8(az)
|
||||||
|
word wsinc = sin8(az)
|
||||||
|
|
||||||
|
word wcosa_sinb = wcosa*wsinb / 128
|
||||||
|
word wsina_sinb = wsina*wsinb / 128
|
||||||
|
|
||||||
|
word Axx = wcosa*wcosb / 128
|
||||||
|
word Axy = (wcosa_sinb*wsinc - wsina*wcosc) / 128
|
||||||
|
word Axz = (wcosa_sinb*wcosc + wsina*wsinc) / 128
|
||||||
|
word Ayx = wsina*wcosb / 128
|
||||||
|
word Ayy = (wsina_sinb*wsinc + wcosa*wcosc) / 128
|
||||||
|
word Ayz = (wsina_sinb*wcosc - wcosa*wsinc) / 128
|
||||||
|
word Azx = -wsinb
|
||||||
|
word Azy = wcosb*wsinc / 128
|
||||||
|
word Azz = wcosb*wcosc / 128
|
||||||
|
|
||||||
|
ubyte @zp i
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||||
|
rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]
|
||||||
|
rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]
|
||||||
|
rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub draw_edges() {
|
||||||
|
|
||||||
|
; plot the points of the 3d cube
|
||||||
|
; first the points on the back, then the points on the front (painter algorithm)
|
||||||
|
|
||||||
|
ubyte @zp i
|
||||||
|
word @zp rz
|
||||||
|
word @zp persp
|
||||||
|
byte sx
|
||||||
|
byte sy
|
||||||
|
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
rz = rotatedz[i]
|
||||||
|
if rz >= 10 {
|
||||||
|
persp = 500 + rz/64
|
||||||
|
sx = rotatedx[i] / persp as byte + screen_width/2
|
||||||
|
sy = rotatedy[i] / persp as byte + screen_height/2
|
||||||
|
txt.setcc(sx as ubyte, sy as ubyte, 46, 7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0 to len(xcoor)-1 {
|
||||||
|
rz = rotatedz[i]
|
||||||
|
if rz < 10 {
|
||||||
|
persp = 500 + rz/64
|
||||||
|
sx = rotatedx[i] / persp as byte + screen_width/2
|
||||||
|
sy = rotatedy[i] / persp as byte + screen_height/2
|
||||||
|
txt.setcc(sx as ubyte, sy as ubyte, 81, 7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
; CommanderX16 text clock example!
|
; CommanderX16 text datetime example!
|
||||||
; make sure to compile with the cx16 compiler target.
|
; make sure to compile with the cx16 compiler target.
|
||||||
|
|
||||||
|
%target cx16
|
||||||
%import cx16textio
|
%import cx16textio
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
@ -8,28 +9,6 @@ main {
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
; %asm {{
|
|
||||||
; lda #$80
|
|
||||||
; jsr cx16.screen_set_mode
|
|
||||||
; }}
|
|
||||||
; cx16.r0=0
|
|
||||||
; cx16.GRAPH_init()
|
|
||||||
; %asm {{
|
|
||||||
; lda #4
|
|
||||||
; ldy #0
|
|
||||||
; ldx #1
|
|
||||||
; jsr cx16.GRAPH_set_colors
|
|
||||||
; }}
|
|
||||||
; cx16.GRAPH_clear()
|
|
||||||
; cx16.r0=10
|
|
||||||
; cx16.r1=10
|
|
||||||
; cx16.r2=100
|
|
||||||
; cx16.r3=150
|
|
||||||
; cx16.GRAPH_draw_line()
|
|
||||||
;
|
|
||||||
; repeat {
|
|
||||||
; }
|
|
||||||
|
|
||||||
cx16.r0 = mkword(8, 2020 - 1900)
|
cx16.r0 = mkword(8, 2020 - 1900)
|
||||||
cx16.r1 = mkword(19, 27)
|
cx16.r1 = mkword(19, 27)
|
||||||
cx16.r2 = mkword(0, 16)
|
cx16.r2 = mkword(0, 16)
|
@ -1,23 +0,0 @@
|
|||||||
; CommanderX16 floating point example!
|
|
||||||
; make sure to compile with the cx16 compiler target.
|
|
||||||
|
|
||||||
%import cx16textio
|
|
||||||
%import cx16flt
|
|
||||||
%zeropage basicsafe
|
|
||||||
|
|
||||||
main {
|
|
||||||
|
|
||||||
sub start() {
|
|
||||||
float f1 = 5.55
|
|
||||||
float f2 = 33.3
|
|
||||||
float f3 = f1 * f2
|
|
||||||
|
|
||||||
c64flt.print_f(f1)
|
|
||||||
c64.CHROUT('*')
|
|
||||||
c64flt.print_f(f2)
|
|
||||||
c64.CHROUT('=')
|
|
||||||
c64flt.print_f(f3)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
%target cx16
|
||||||
%import cx16textio
|
%import cx16textio
|
||||||
%import cx16flt
|
%import cx16flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
@ -5,7 +6,7 @@
|
|||||||
main {
|
main {
|
||||||
const uword width = 256
|
const uword width = 256
|
||||||
const uword height = 200
|
const uword height = 200
|
||||||
const ubyte max_iter = 16 ; 32 looks pretty nice
|
const ubyte max_iter = 16 ; 32 actually looks pretty nice but takes longer
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
initialize()
|
initialize()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
%target cx16
|
||||||
%import cx16textio
|
%import cx16textio
|
||||||
%import cx16flt
|
%import cx16flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
; CommanderX16 text clock example!
|
; CommanderX16 simple graphics example!
|
||||||
; make sure to compile with the cx16 compiler target.
|
; make sure to compile with the cx16 compiler target.
|
||||||
|
|
||||||
|
%target cx16
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
@ -1,3 +1,4 @@
|
|||||||
|
%target cx16
|
||||||
%import cx16textio
|
%import cx16textio
|
||||||
%import cx16flt
|
%import cx16flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
%target cx16
|
||||||
%import cx16lib
|
%import cx16lib
|
||||||
%import cx16textio
|
%import cx16textio
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
@ -38,9 +38,7 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if iter & 1
|
if iter & 1
|
||||||
; TODO fix plot() so we don't have to use separate internal variable
|
graphics.plot(pixelx, pixely)
|
||||||
graphics.internal_plotx = pixelx
|
|
||||||
graphics.internal_plot(pixely)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,9 +385,9 @@ waitkey:
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub drawBlock(ubyte x, ubyte y, ubyte character) {
|
sub drawBlock(ubyte x, ubyte y, ubyte character) {
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 15 downto 0 {
|
for i in 15 downto 0 {
|
||||||
ubyte c=blocklogic.currentBlock[i]
|
ubyte @zp c=blocklogic.currentBlock[i]
|
||||||
if c
|
if c
|
||||||
txt.setcc((i&3)+x, (i/4)+y, character, c)
|
txt.setcc((i&3)+x, (i/4)+y, character, c)
|
||||||
}
|
}
|
||||||
@ -534,7 +534,7 @@ blocklogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub noCollision(ubyte xpos, ubyte ypos) -> ubyte {
|
sub noCollision(ubyte xpos, ubyte ypos) -> ubyte {
|
||||||
ubyte i
|
ubyte @zp i
|
||||||
for i in 15 downto 0 {
|
for i in 15 downto 0 {
|
||||||
if currentBlock[i] and txt.getchr(xpos + (i&3), ypos+i/4)!=32
|
if currentBlock[i] and txt.getchr(xpos + (i&3), ypos+i/4)!=32
|
||||||
return false
|
return false
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
%import c64lib
|
||||||
|
%import c64graphics
|
||||||
%import c64textio
|
%import c64textio
|
||||||
|
;%import c64flt
|
||||||
|
;%option enable_floats
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
|
||||||
|
|
||||||
;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...}
|
;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...}
|
||||||
; TODO dont cause name conflict if we define sub or sub with param 'color' or even a var 'color' later.
|
; TODO dont cause name conflict if we define sub or sub with param 'color' or even a var 'color' later.
|
||||||
@ -10,6 +14,7 @@ main {
|
|||||||
; sub color(...) {}
|
; sub color(...) {}
|
||||||
; sub other(ubyte color) {} ; TODO don't cause name conflict
|
; sub other(ubyte color) {} ; TODO don't cause name conflict
|
||||||
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
sub start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ unconditionaljump : 'goto' (integerliteral | scoped_identifier) ;
|
|||||||
|
|
||||||
directive :
|
directive :
|
||||||
directivename=('%output' | '%launcher' | '%zeropage' | '%zpreserved' | '%address' | '%import' |
|
directivename=('%output' | '%launcher' | '%zeropage' | '%zpreserved' | '%address' | '%import' |
|
||||||
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option')
|
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option' | '%target' )
|
||||||
(directivearg? | directivearg (',' directivearg)*)
|
(directivearg? | directivearg (',' directivearg)*)
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns?
|
|||||||
|
|
||||||
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
||||||
|
|
||||||
asmsub_param : vardecl '@' (identifier | stack='stack') ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed. TODO implement stack='stack'
|
||||||
|
|
||||||
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user