mirror of
https://github.com/irmen/prog8.git
synced 2026-10-23 12:02:29 +00:00
Compare 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 |
No files matched your search
@@ -1,11 +1,11 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
// id "org.jetbrains.kotlin.jvm" version "1.4.0"
|
||||
// id "org.jetbrains.kotlin.jvm" version "1.4.10"
|
||||
id 'application'
|
||||
id 'org.jetbrains.dokka' version "0.9.18"
|
||||
id 'com.github.johnrengelman.shadow' version '5.2.0'
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
; --- 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
|
||||
; -- convert ubyte in SCRATCH_ZPB1 to float at address A/Y
|
||||
; clobbers A, Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
ldy P8ZP_SCRATCH_B1
|
||||
@@ -13,14 +18,14 @@ ub2float .proc
|
||||
_fac_to_mem ldx P8ZP_SCRATCH_W2
|
||||
ldy P8ZP_SCRATCH_W2+1
|
||||
jsr MOVMF
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
b2float .proc
|
||||
; -- convert byte in SCRATCH_ZPB1 to float at address A/Y
|
||||
; clobbers A, Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
lda P8ZP_SCRATCH_B1
|
||||
@@ -30,7 +35,7 @@ b2float .proc
|
||||
|
||||
uw2float .proc
|
||||
; -- convert uword in SCRATCH_ZPWORD1 to float at address A/Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
lda P8ZP_SCRATCH_W1
|
||||
@@ -41,7 +46,7 @@ uw2float .proc
|
||||
|
||||
w2float .proc
|
||||
; -- convert word in SCRATCH_ZPWORD1 to float at address A/Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
ldy P8ZP_SCRATCH_W1
|
||||
@@ -54,7 +59,7 @@ stack_b2float .proc
|
||||
; -- b2float operating on the stack
|
||||
inx
|
||||
lda P8ESTACK_LO,x
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr FREADSA
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -64,7 +69,7 @@ stack_w2float .proc
|
||||
inx
|
||||
ldy P8ESTACK_LO,x
|
||||
lda P8ESTACK_HI,x
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr GIVAYF
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -73,7 +78,7 @@ stack_ub2float .proc
|
||||
; -- ub2float operating on the stack
|
||||
inx
|
||||
lda P8ESTACK_LO,x
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
tay
|
||||
lda #0
|
||||
jsr GIVAYF
|
||||
@@ -85,16 +90,16 @@ stack_uw2float .proc
|
||||
inx
|
||||
lda P8ESTACK_LO,x
|
||||
ldy P8ESTACK_HI,x
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr GIVUAYFAY
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
stack_float2w .proc ; also used for float2b
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr AYINT
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
lda $64
|
||||
sta P8ESTACK_HI,x
|
||||
lda $65
|
||||
@@ -105,9 +110,9 @@ stack_float2w .proc ; also used for float2b
|
||||
|
||||
stack_float2uw .proc ; also used for float2ub
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr GETADR
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
sta P8ESTACK_HI,x
|
||||
tya
|
||||
sta P8ESTACK_LO,x
|
||||
@@ -231,15 +236,15 @@ inc_var_f .proc
|
||||
; -- add 1 to float pointed to by A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr MOVFM
|
||||
lda #<FL_FONE
|
||||
ldy #>FL_FONE
|
||||
lda #<FL_ONE_const
|
||||
ldy #>FL_ONE_const
|
||||
jsr FADD
|
||||
ldx P8ZP_SCRATCH_W1
|
||||
ldy P8ZP_SCRATCH_W1+1
|
||||
jsr MOVMF
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
@@ -247,9 +252,9 @@ dec_var_f .proc
|
||||
; -- subtract 1 from float pointed to by A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
lda #<FL_FONE
|
||||
ldy #>FL_FONE
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<FL_ONE_const
|
||||
ldy #>FL_ONE_const
|
||||
jsr MOVFM
|
||||
lda P8ZP_SCRATCH_W1
|
||||
ldy P8ZP_SCRATCH_W1+1
|
||||
@@ -257,7 +262,7 @@ dec_var_f .proc
|
||||
ldx P8ZP_SCRATCH_W1
|
||||
ldy P8ZP_SCRATCH_W1+1
|
||||
jsr MOVMF
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
@@ -286,7 +291,7 @@ push_fac1_as_result .proc
|
||||
jsr MOVMF
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
jmp push_float
|
||||
.pend
|
||||
|
||||
@@ -298,21 +303,21 @@ pow_f .proc
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr pop_float
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr CONUPK ; fac2 = float1
|
||||
lda #<fmath_float2
|
||||
ldy #>fmath_float2
|
||||
jsr FPWR
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
div_f .proc
|
||||
; -- push f1/f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FDIV
|
||||
@@ -322,7 +327,7 @@ div_f .proc
|
||||
add_f .proc
|
||||
; -- push f1+f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FADD
|
||||
@@ -332,7 +337,7 @@ add_f .proc
|
||||
sub_f .proc
|
||||
; -- push f1-f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FSUB
|
||||
@@ -342,7 +347,7 @@ sub_f .proc
|
||||
mul_f .proc
|
||||
; -- push f1*f2 on stack
|
||||
jsr pop_2_floats_f2_in_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FMULT
|
||||
@@ -352,7 +357,7 @@ mul_f .proc
|
||||
neg_f .proc
|
||||
; -- push -flt back on stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr NEGOP
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -360,7 +365,7 @@ neg_f .proc
|
||||
abs_f .proc
|
||||
; -- push abs(float) on stack (as float)
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr ABS
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -466,7 +471,7 @@ _return_true lda #1
|
||||
func_sin .proc
|
||||
; -- push sin(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SIN
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -474,7 +479,7 @@ func_sin .proc
|
||||
func_cos .proc
|
||||
; -- push cos(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr COS
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -482,7 +487,7 @@ func_cos .proc
|
||||
func_tan .proc
|
||||
; -- push tan(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr TAN
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -490,7 +495,7 @@ func_tan .proc
|
||||
func_atan .proc
|
||||
; -- push atan(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr ATN
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -498,7 +503,7 @@ func_atan .proc
|
||||
func_ln .proc
|
||||
; -- push ln(f) back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -506,7 +511,7 @@ func_ln .proc
|
||||
func_log2 .proc
|
||||
; -- push log base 2, ln(f)/ln(2), back onto stack
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
jsr MOVEF
|
||||
lda #<c64.FL_LOG2
|
||||
@@ -518,7 +523,7 @@ func_log2 .proc
|
||||
|
||||
func_sqrt .proc
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SQR
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -526,7 +531,7 @@ func_sqrt .proc
|
||||
func_rad .proc
|
||||
; -- convert degrees to radians (d * pi / 180)
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_pi_div_180
|
||||
ldy #>_pi_div_180
|
||||
jsr FMULT
|
||||
@@ -537,7 +542,7 @@ _pi_div_180 .byte 123, 14, 250, 53, 18 ; pi / 180
|
||||
func_deg .proc
|
||||
; -- convert radians to degrees (d * (1/ pi * 180))
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_one_over_pi_div_180
|
||||
ldy #>_one_over_pi_div_180
|
||||
jsr FMULT
|
||||
@@ -547,7 +552,7 @@ _one_over_pi_div_180 .byte 134, 101, 46, 224, 211 ; 1 / (pi * 180)
|
||||
|
||||
func_round .proc
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr FADDH
|
||||
jsr INT
|
||||
jmp push_fac1_as_result
|
||||
@@ -555,7 +560,7 @@ func_round .proc
|
||||
|
||||
func_floor .proc
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr INT
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -563,7 +568,7 @@ func_floor .proc
|
||||
func_ceil .proc
|
||||
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
||||
jsr pop_float_fac1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
ldx #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr MOVMF
|
||||
@@ -573,8 +578,8 @@ func_ceil .proc
|
||||
jsr FCOMP
|
||||
cmp #0
|
||||
beq +
|
||||
lda #<FL_FONE
|
||||
ldy #>FL_FONE
|
||||
lda #<FL_ONE_const
|
||||
ldy #>FL_ONE_const
|
||||
jsr FADD
|
||||
+ jmp push_fac1_as_result
|
||||
.pend
|
||||
@@ -630,7 +635,7 @@ func_max_f .proc
|
||||
ldy #>_largest_neg_float
|
||||
_minmax_entry jsr MOVFM
|
||||
jsr prog8_lib.pop_array_and_lengthmin1Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx floats_store_reg
|
||||
- sty P8ZP_SCRATCH_REG
|
||||
lda P8ZP_SCRATCH_W1
|
||||
ldy P8ZP_SCRATCH_W1+1
|
||||
@@ -650,6 +655,8 @@ _minmax_cmp cmp #255 ; modified
|
||||
dey
|
||||
cpy #255
|
||||
bne -
|
||||
ldx floats_store_reg
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jmp push_fac1_as_result
|
||||
_largest_neg_float .byte 255,255,255,255,255 ; largest negative float -1.7014118345e+38
|
||||
.pend
|
||||
@@ -665,11 +672,11 @@ _largest_pos_float .byte 255,127,255,255,255 ; largest positive float
|
||||
.pend
|
||||
|
||||
func_sum_f .proc
|
||||
lda #<ZERO
|
||||
ldy #>ZERO
|
||||
lda #<FL_ZERO_const
|
||||
ldy #>FL_ZERO_const
|
||||
jsr MOVFM
|
||||
jsr prog8_lib.pop_array_and_lengthmin1Y
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx floats_store_reg
|
||||
- sty P8ZP_SCRATCH_REG
|
||||
lda P8ZP_SCRATCH_W1
|
||||
ldy P8ZP_SCRATCH_W1+1
|
||||
@@ -685,7 +692,9 @@ func_sum_f .proc
|
||||
bcc -
|
||||
inc P8ZP_SCRATCH_W1+1
|
||||
bne -
|
||||
+ jmp push_fac1_as_result
|
||||
+ ldx floats_store_reg
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jmp push_fac1_as_result
|
||||
.pend
|
||||
|
||||
sign_f .proc
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
%target c64
|
||||
%option enable_floats
|
||||
|
||||
c64flt {
|
||||
; ---- this block contains C-64 floating point related functions ----
|
||||
|
||||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
const float ZERO = 0.0
|
||||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
|
||||
|
||||
; ---- C64 basic and kernal ROM float constants and functions ----
|
||||
@@ -194,20 +194,20 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx floats_store_reg
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_B1
|
||||
sty P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_B1),y
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx floats_store_reg
|
||||
+ rts
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
%target c64
|
||||
%import c64textio
|
||||
|
||||
; bitmap pixel graphics module for the C64
|
||||
@@ -180,9 +181,7 @@ graphics {
|
||||
; @(addr) |= ormask[lsb(px) & 7]
|
||||
; }
|
||||
|
||||
; TODO fix the use of X (or XY) as parameter so we can actually use this plot() routine
|
||||
; 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) {
|
||||
asmsub plot(uword plotx @XY, ubyte ploty @A) clobbers (A, X, Y) {
|
||||
%asm {{
|
||||
stx internal_plotx
|
||||
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()
|
||||
|
||||
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 {{
|
||||
tay
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
lda internal_plotx+1
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
lsr a ; 0
|
||||
@@ -219,8 +220,6 @@ graphics {
|
||||
lda (P8ZP_SCRATCH_W2),y
|
||||
ora _ormask,x
|
||||
sta (P8ZP_SCRATCH_W2),y
|
||||
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
rts
|
||||
|
||||
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
%target c64
|
||||
|
||||
c64 {
|
||||
&ubyte TIME_HI = $a0 ; software jiffy clock, hi byte
|
||||
@@ -298,8 +299,6 @@ _irq_handler_init
|
||||
sta IRQ_SCRATCH_ZPB1
|
||||
lda P8ZP_SCRATCH_REG
|
||||
sta IRQ_SCRATCH_ZPREG
|
||||
lda P8ZP_SCRATCH_REG_X
|
||||
sta IRQ_SCRATCH_ZPREGX
|
||||
lda P8ZP_SCRATCH_W1
|
||||
sta IRQ_SCRATCH_ZPWORD1
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
@@ -324,8 +323,6 @@ _irq_handler_end
|
||||
sta P8ZP_SCRATCH_B1
|
||||
lda IRQ_SCRATCH_ZPREG
|
||||
sta P8ZP_SCRATCH_REG
|
||||
lda IRQ_SCRATCH_ZPREGX
|
||||
sta P8ZP_SCRATCH_REG_X
|
||||
lda IRQ_SCRATCH_ZPWORD1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda IRQ_SCRATCH_ZPWORD1+1
|
||||
@@ -340,7 +337,6 @@ _irq_handler_end
|
||||
IRQ_X_REG .byte 0
|
||||
IRQ_SCRATCH_ZPB1 .byte 0
|
||||
IRQ_SCRATCH_ZPREG .byte 0
|
||||
IRQ_SCRATCH_ZPREGX .byte 0
|
||||
IRQ_SCRATCH_ZPWORD1 .word 0
|
||||
IRQ_SCRATCH_ZPWORD2 .word 0
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
; indent format: TABS, size=8
|
||||
|
||||
|
||||
%target c64
|
||||
%import c64lib
|
||||
%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
|
||||
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
bcs +
|
||||
jmp _scroll_screen
|
||||
|
||||
@@ -102,7 +103,7 @@ _scroll_screen ; scroll the screen memory
|
||||
dey
|
||||
bpl -
|
||||
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
bcs +
|
||||
jmp _scroll_screen
|
||||
|
||||
@@ -136,7 +137,7 @@ _scroll_screen ; scroll the screen memory
|
||||
dex
|
||||
bpl -
|
||||
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
bcs +
|
||||
jmp _scroll_screen
|
||||
|
||||
@@ -170,7 +171,7 @@ _scroll_screen ; scroll the screen memory
|
||||
dex
|
||||
bpl -
|
||||
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
bcs +
|
||||
jmp _scroll_screen
|
||||
|
||||
@@ -204,7 +205,7 @@ _scroll_screen ; scroll the screen memory
|
||||
dex
|
||||
bpl -
|
||||
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@@ -230,7 +231,7 @@ asmsub print (str text @ AY) 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)
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr conv.ubyte2decimal
|
||||
pha
|
||||
tya
|
||||
@@ -239,7 +240,7 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
|
||||
jsr c64.CHROUT
|
||||
txa
|
||||
jsr c64.CHROUT
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@@ -247,7 +248,7 @@ asmsub print_ub0 (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
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr conv.ubyte2decimal
|
||||
_print_byte_digits
|
||||
pha
|
||||
@@ -264,7 +265,7 @@ _print_byte_digits
|
||||
jsr c64.CHROUT
|
||||
_ones txa
|
||||
jsr c64.CHROUT
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@@ -272,7 +273,7 @@ _ones txa
|
||||
asmsub print_b (byte value @ A) clobbers(A,Y) {
|
||||
; ---- print the byte in A in decimal form, without left padding 0s
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
pha
|
||||
cmp #0
|
||||
bpl +
|
||||
@@ -280,16 +281,14 @@ asmsub print_b (byte value @ A) clobbers(A,Y) {
|
||||
jsr c64.CHROUT
|
||||
+ pla
|
||||
jsr conv.byte2decimal
|
||||
jsr print_ub._print_byte_digits
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
rts
|
||||
jmp print_ub._print_byte_digits
|
||||
}}
|
||||
}
|
||||
|
||||
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)
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
bcc +
|
||||
pha
|
||||
lda #'$'
|
||||
@@ -299,7 +298,7 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
jsr c64.CHROUT
|
||||
tya
|
||||
jsr c64.CHROUT
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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) {
|
||||
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_B1
|
||||
bcc +
|
||||
lda #'%'
|
||||
@@ -320,7 +319,7 @@ asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
|
||||
+ jsr c64.CHROUT
|
||||
dey
|
||||
bne -
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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) {
|
||||
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr conv.uword2decimal
|
||||
ldy #0
|
||||
- lda conv.uword2decimal.decTenThousands,y
|
||||
@@ -361,7 +360,7 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ ldx P8ZP_SCRATCH_REG_X
|
||||
+ ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@@ -369,9 +368,9 @@ asmsub print_uw0 (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
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr conv.uword2decimal
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
ldy #0
|
||||
- lda conv.uword2decimal.decTenThousands,y
|
||||
beq _allzero
|
||||
@@ -545,11 +544,11 @@ _colormod sta $ffff ; modified
|
||||
asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) {
|
||||
; ---- safe wrapper around PLOT kernel routine, to save the X register.
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
tax
|
||||
clc
|
||||
jsr c64.PLOT
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
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 {
|
||||
; ---- A to hex petscii string in AY (first hex char in A, second hex char in Y)
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
pha
|
||||
and #$0f
|
||||
tax
|
||||
@@ -225,7 +225,7 @@ asmsub ubyte2hex (ubyte value @ A) -> ubyte @ A, ubyte @ Y {
|
||||
lsr a
|
||||
tax
|
||||
lda _hex_digits,x
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
|
||||
_hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
%target cx16
|
||||
%option enable_floats
|
||||
|
||||
c64flt {
|
||||
; ---- this block contains C-64 floating point related functions ----
|
||||
|
||||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
const float ZERO = 0.0
|
||||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
|
||||
|
||||
; ---- ROM float functions ----
|
||||
@@ -130,20 +130,20 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_B1
|
||||
sty P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_B1),y
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
plx
|
||||
+ rts
|
||||
}}
|
||||
}
|
||||
|
||||
+171
-120
@@ -5,6 +5,8 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
%target cx16
|
||||
|
||||
|
||||
c64 {
|
||||
|
||||
@@ -14,42 +16,42 @@ c64 {
|
||||
; CLEARSCR -> use screen.clear_screen
|
||||
; HOMECRSR -> use screen.plot
|
||||
|
||||
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 $FF87 = RAMTAS() clobbers(A,X,Y) ; initialize RAM, tape buffer, screen
|
||||
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 $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 $FF87 = RAMTAS() clobbers(A,X,Y) ; initialize RAM, tape buffer, screen
|
||||
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 $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 $FF96 = TKSA(ubyte address @ A) clobbers(A) ; (alias: TALKSA) send secondary address after TALK
|
||||
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 $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 $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 $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 $FFAB = UNTLK() clobbers(A) ; command serial bus device to UNTALK
|
||||
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 $FFB4 = TALK(ubyte device @ A) clobbers(A) ; command serial bus device to TALK
|
||||
romsub $FFAB = UNTLK() clobbers(A) ; command serial bus device to UNTALK
|
||||
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 $FFB4 = TALK(ubyte device @ A) clobbers(A) ; command serial bus device to TALK
|
||||
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 $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 $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 $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 $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 $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 $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 $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 $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 $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 $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 $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 $FFEA = UDTIM() clobbers(A,X) ; update the software clock
|
||||
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 $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
|
||||
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 $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
|
||||
@@ -58,8 +60,11 @@ romsub $FFF3 = IOBASE() -> uword @ XY ; read base addr
|
||||
|
||||
cx16 {
|
||||
|
||||
; ---- Commander X-16 additions on top of C64 kernal routines ----
|
||||
; spelling of the names is taken from the Commander X-16 rom sources
|
||||
; 65c02 hardware vectors:
|
||||
&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
|
||||
&uword r0 = $02
|
||||
@@ -82,116 +87,159 @@ cx16 {
|
||||
; VERA registers
|
||||
|
||||
const uword VERA_BASE = $9F20
|
||||
&uword VERA_ADDR_L = VERA_BASE + $00
|
||||
&uword VERA_ADDR_M = VERA_BASE + $01
|
||||
&uword VERA_ADDR_H = VERA_BASE + $02
|
||||
&uword VERA_DATA0 = VERA_BASE + $03
|
||||
&uword VERA_DATA1 = VERA_BASE + $04
|
||||
&uword VERA_CTRL = VERA_BASE + $05
|
||||
&uword VERA_IEN = VERA_BASE + $06
|
||||
&uword VERA_ISR = VERA_BASE + $07
|
||||
&uword VERA_IRQ_LINE_L = VERA_BASE + $08
|
||||
&uword VERA_DC_VIDEO = VERA_BASE + $09
|
||||
&uword VERA_DC_HSCALE = VERA_BASE + $0A
|
||||
&uword VERA_DC_VSCALE = VERA_BASE + $0B
|
||||
&uword VERA_DC_BORDER = VERA_BASE + $0C
|
||||
&uword VERA_DC_HSTART = VERA_BASE + $09
|
||||
&uword VERA_DC_HSTOP = VERA_BASE + $0A
|
||||
&uword VERA_DC_VSTART = VERA_BASE + $0B
|
||||
&uword VERA_DC_VSTOP = VERA_BASE + $0C
|
||||
&uword VERA_L0_CONFIG = VERA_BASE + $0D
|
||||
&uword VERA_L0_MAPBASE = VERA_BASE + $0E
|
||||
&uword VERA_L0_TILEBASE = VERA_BASE + $0F
|
||||
&uword VERA_L0_HSCROLL_L = VERA_BASE + $10
|
||||
&uword VERA_L0_HSCROLL_H = VERA_BASE + $11
|
||||
&uword VERA_L0_VSCROLL_L = VERA_BASE + $12
|
||||
&uword VERA_L0_VSCROLL_H = VERA_BASE + $13
|
||||
&uword VERA_L1_CONFIG = VERA_BASE + $14
|
||||
&uword VERA_L1_MAPBASE = VERA_BASE + $15
|
||||
&uword VERA_L1_TILEBASE = VERA_BASE + $16
|
||||
&uword VERA_L1_HSCROLL_L = VERA_BASE + $17
|
||||
&uword VERA_L1_HSCROLL_H = VERA_BASE + $18
|
||||
&uword VERA_L1_VSCROLL_L = VERA_BASE + $19
|
||||
&uword VERA_L1_VSCROLL_H = VERA_BASE + $1A
|
||||
&uword VERA_AUDIO_CTRL = VERA_BASE + $1B
|
||||
&uword VERA_AUDIO_RATE = VERA_BASE + $1C
|
||||
&uword VERA_AUDIO_DATA = VERA_BASE + $1D
|
||||
&uword VERA_SPI_DATA = VERA_BASE + $1E
|
||||
&uword VERA_SPI_CTRL = VERA_BASE + $1F
|
||||
&ubyte VERA_ADDR_L = VERA_BASE + $00
|
||||
&ubyte VERA_ADDR_M = VERA_BASE + $01
|
||||
&ubyte VERA_ADDR_H = VERA_BASE + $02
|
||||
&ubyte VERA_DATA0 = VERA_BASE + $03
|
||||
&ubyte VERA_DATA1 = VERA_BASE + $04
|
||||
&ubyte VERA_CTRL = VERA_BASE + $05
|
||||
&ubyte VERA_IEN = VERA_BASE + $06
|
||||
&ubyte VERA_ISR = VERA_BASE + $07
|
||||
&ubyte VERA_IRQ_LINE_L = VERA_BASE + $08
|
||||
&ubyte VERA_DC_VIDEO = VERA_BASE + $09
|
||||
&ubyte VERA_DC_HSCALE = VERA_BASE + $0A
|
||||
&ubyte VERA_DC_VSCALE = VERA_BASE + $0B
|
||||
&ubyte VERA_DC_BORDER = VERA_BASE + $0C
|
||||
&ubyte VERA_DC_HSTART = VERA_BASE + $09
|
||||
&ubyte VERA_DC_HSTOP = VERA_BASE + $0A
|
||||
&ubyte VERA_DC_VSTART = VERA_BASE + $0B
|
||||
&ubyte VERA_DC_VSTOP = VERA_BASE + $0C
|
||||
&ubyte VERA_L0_CONFIG = VERA_BASE + $0D
|
||||
&ubyte VERA_L0_MAPBASE = VERA_BASE + $0E
|
||||
&ubyte VERA_L0_TILEBASE = VERA_BASE + $0F
|
||||
&ubyte VERA_L0_HSCROLL_L = VERA_BASE + $10
|
||||
&ubyte VERA_L0_HSCROLL_H = VERA_BASE + $11
|
||||
&ubyte VERA_L0_VSCROLL_L = VERA_BASE + $12
|
||||
&ubyte VERA_L0_VSCROLL_H = VERA_BASE + $13
|
||||
&ubyte VERA_L1_CONFIG = VERA_BASE + $14
|
||||
&ubyte VERA_L1_MAPBASE = VERA_BASE + $15
|
||||
&ubyte VERA_L1_TILEBASE = VERA_BASE + $16
|
||||
&ubyte VERA_L1_HSCROLL_L = VERA_BASE + $17
|
||||
&ubyte VERA_L1_HSCROLL_H = VERA_BASE + $18
|
||||
&ubyte VERA_L1_VSCROLL_L = VERA_BASE + $19
|
||||
&ubyte VERA_L1_VSCROLL_H = VERA_BASE + $1A
|
||||
&ubyte VERA_AUDIO_CTRL = VERA_BASE + $1B
|
||||
&ubyte VERA_AUDIO_RATE = VERA_BASE + $1C
|
||||
&ubyte VERA_AUDIO_DATA = VERA_BASE + $1D
|
||||
&ubyte VERA_SPI_DATA = VERA_BASE + $1E
|
||||
&ubyte VERA_SPI_CTRL = VERA_BASE + $1F
|
||||
; VERA_PSG_BASE = $1F9C0
|
||||
; VERA_PALETTE_BASE = $1FA00
|
||||
; 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
|
||||
romsub $ff4a = close_all()
|
||||
romsub $ff59 = lkupla()
|
||||
romsub $ff5c = lkupsa()
|
||||
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 $ff65 = pfkey()
|
||||
romsub $ff6e = jsrfar()
|
||||
romsub $ff74 = fetch()
|
||||
romsub $ff77 = stash()
|
||||
romsub $ff7a = cmpare()
|
||||
romsub $ff7d = primm()
|
||||
romsub $ff4a = close_all() clobbers(A,X,Y)
|
||||
romsub $ff59 = lkupla() clobbers(A,X,Y)
|
||||
romsub $ff5c = lkupsa() clobbers(A,X,Y)
|
||||
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 $ff65 = pfkey() clobbers(A,X,Y)
|
||||
romsub $ff6e = jsrfar() clobbers(A,X,Y)
|
||||
romsub $ff74 = fetch() clobbers(A,X,Y)
|
||||
romsub $ff77 = stash() clobbers(A,X,Y)
|
||||
romsub $ff7a = cmpare() clobbers(A,X,Y)
|
||||
romsub $ff7d = primm() clobbers(A,X,Y)
|
||||
|
||||
; X16 additions
|
||||
romsub $ff44 = macptr()
|
||||
romsub $ff47 = enter_basic(ubyte cold_or_warm @Pc)
|
||||
romsub $ff68 = mouse_config(ubyte shape @A, ubyte scale @X) clobbers (A, X, Y)
|
||||
romsub $ff6b = mouse_get(ubyte zpdataptr @X) clobbers(A)
|
||||
romsub $ff71 = mouse_scan() clobbers(A, X, Y)
|
||||
romsub $ff53 = joystick_scan() clobbers(A, X, Y)
|
||||
romsub $ff44 = macptr() clobbers(A,X,Y)
|
||||
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 $ff6b = mouse_get(ubyte zpdataptr @X) clobbers(A)
|
||||
romsub $ff71 = mouse_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 $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 $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
|
||||
|
||||
; high level graphics & fonts
|
||||
romsub $ff20 = GRAPH_init() ; uses vectors=r0
|
||||
romsub $ff23 = GRAPH_clear()
|
||||
romsub $ff26 = GRAPH_set_window() ; uses x=r0, y=r1, width=r2, height=r3
|
||||
romsub $ff29 = GRAPH_set_colors(ubyte stroke @A, ubyte fill @X, ubyte background @Y)
|
||||
romsub $ff2c = GRAPH_draw_line() ; 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 $ff32 = GRAPH_move_rect() ; 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 $ff38 = GRAPH_draw_image() ; uses x=r0, y=r1, ptr=r2, width=r3, height=r4
|
||||
romsub $ff3b = GRAPH_set_font() ; 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 $ff41 = GRAPH_put_char(ubyte char @A) ; uses x=r0, y=r1
|
||||
romsub $ff20 = GRAPH_init() clobbers(A,X,Y) ; uses vectors=r0
|
||||
romsub $ff23 = GRAPH_clear() clobbers(A,X,Y)
|
||||
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) clobbers (A,X,Y)
|
||||
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) clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3, cornerradius=r4
|
||||
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) clobbers(A,X,Y) ; uses x=r0, y=r1, width=r2, height=r3
|
||||
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() 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) clobbers(A,X,Y)
|
||||
romsub $ff41 = GRAPH_put_char(ubyte char @A) clobbers(A,X,Y) ; uses x=r0, y=r1
|
||||
|
||||
; framebuffer
|
||||
romsub $fef6 = FB_init()
|
||||
romsub $fef9 = FB_get_info() -> byte @A ; also outputs width=r0, height=r1
|
||||
romsub $fefc = FB_set_palette(ubyte index @A, ubyte bytecount @X) ; also uses pointer=r0
|
||||
romsub $feff = FB_cursor_position() ; uses x=r0, y=r1
|
||||
romsub $ff02 = FB_cursor_next_line() ; uses x=r0
|
||||
romsub $ff05 = FB_get_pixel() -> ubyte @A
|
||||
romsub $ff08 = FB_get_pixels() ; uses ptr=r0, count=r1
|
||||
romsub $ff0b = FB_set_pixel(ubyte color @A)
|
||||
romsub $ff0e = FB_set_pixels() ; uses ptr=r0, count=r1
|
||||
romsub $ff11 = FB_set_8_pixels(ubyte pattern @A, ubyte color @X)
|
||||
romsub $ff14 = FB_set_8_pixels_opaque(ubyte pattern @A, ubyte color1 @X, ubyte color2 @Y) ; also uses mask=r0L
|
||||
romsub $ff17 = FB_fill_pixels(ubyte color @A) ; also uses count=r0, step=r1
|
||||
romsub $ff1a = FB_filter_pixels() ; uses ptr=r0, count=r1
|
||||
romsub $ff1d = FB_move_pixels() ; uses sx=r0, sy=r1, tx=r2, ty=r3, count=r4
|
||||
romsub $fef6 = FB_init() clobbers(A,X,Y)
|
||||
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) clobbers(A,X,Y) ; also uses pointer=r0
|
||||
romsub $feff = FB_cursor_position() clobbers(A,X,Y) ; uses x=r0, y=r1
|
||||
romsub $ff02 = FB_cursor_next_line() clobbers(A,X,Y) ; uses x=r0
|
||||
romsub $ff05 = FB_get_pixel() clobbers(X,Y) -> ubyte @A
|
||||
romsub $ff08 = FB_get_pixels() clobbers(A,X,Y) ; uses ptr=r0, count=r1
|
||||
romsub $ff0b = FB_set_pixel(ubyte color @A) clobbers(A,X,Y)
|
||||
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) clobbers(A,X,Y)
|
||||
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) clobbers(A,X,Y) ; also uses count=r0, step=r1
|
||||
romsub $ff1a = FB_filter_pixels() clobbers(A,X,Y) ; uses ptr=r0, count=r1
|
||||
romsub $ff1d = FB_move_pixels() clobbers(A,X,Y) ; uses sx=r0, sy=r1, tx=r2, ty=r3, count=r4
|
||||
|
||||
; 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 $fef3 = sprite_set_position(ubyte number @A) ; also uses x=r0 and y=r1
|
||||
romsub $fee4 = memory_fill(ubyte value @A) ; uses address=r0, num_bytes=r1
|
||||
romsub $fee7 = memory_copy() ; uses source=r0, target=r1, num_bytes=r2
|
||||
romsub $feea = memory_crc() ; uses address=r0, num_bytes=r1 result->r2
|
||||
romsub $feed = memory_decompress() ; uses input=r0, output=r1 result->r1
|
||||
romsub $fedb = console_init() ; uses x=r0, y=r1, width=r2, height=r3
|
||||
romsub $fede = console_put_char(ubyte char @A, ubyte wrapping @Pc)
|
||||
romsub $fee1 = console_get_char() -> ubyte @A
|
||||
romsub $fed8 = console_put_image() ; uses ptr=r0, width=r1, height=r2
|
||||
romsub $fed5 = console_set_paging_message() ; uses messageptr=r0
|
||||
romsub $fed2 = kbdbuf_put(ubyte key @A)
|
||||
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) clobbers(A,X,Y) ; also uses x=r0 and y=r1
|
||||
romsub $fee4 = memory_fill(ubyte value @A) clobbers(A,X,Y) ; uses address=r0, num_bytes=r1
|
||||
romsub $fee7 = memory_copy() clobbers(A,X,Y) ; uses source=r0, target=r1, num_bytes=r2
|
||||
romsub $feea = memory_crc() clobbers(A,X,Y) ; uses address=r0, num_bytes=r1 result->r2
|
||||
romsub $feed = memory_decompress() clobbers(A,X,Y) ; uses input=r0, output=r1 result->r1
|
||||
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) clobbers(A,X,Y)
|
||||
romsub $fee1 = console_get_char() clobbers(X,Y) -> ubyte @A
|
||||
romsub $fed8 = console_put_image() clobbers(A,X,Y) ; uses ptr=r0, width=r1, height=r2
|
||||
romsub $fed5 = console_set_paging_message() clobbers(A,X,Y) ; uses messageptr=r0
|
||||
romsub $fed2 = kbdbuf_put(ubyte key @A) clobbers(A,X,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 {{
|
||||
sei
|
||||
cld
|
||||
stz $00
|
||||
stz $01
|
||||
;stz $00
|
||||
;stz $01
|
||||
;stz d1prb ; select rom bank 0
|
||||
lda #$80
|
||||
sta VERA_CTRL
|
||||
jsr c64.IOINIT
|
||||
jsr c64.RESTOR
|
||||
jsr c64.CINT
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
;
|
||||
; indent format: TABS, size=8
|
||||
|
||||
|
||||
%target cx16
|
||||
%import cx16lib
|
||||
%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]
|
||||
|
||||
sub color (ubyte txtcol) {
|
||||
|
||||
+571
-49
@@ -11,6 +11,10 @@
|
||||
; http://codebase64.org/doku.php?id=base:6502_6510_maths
|
||||
;
|
||||
|
||||
|
||||
math_store_reg .byte 0 ; temporary storage
|
||||
|
||||
|
||||
multiply_bytes .proc
|
||||
; -- multiply 2 bytes A and Y, result as byte in A (signed or unsigned)
|
||||
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)
|
||||
sta P8ZP_SCRATCH_B1
|
||||
sty P8ZP_SCRATCH_REG
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx math_store_reg
|
||||
lda #0
|
||||
ldx #8
|
||||
lsr P8ZP_SCRATCH_B1
|
||||
@@ -44,7 +48,7 @@ multiply_bytes_16 .proc
|
||||
bne -
|
||||
tay
|
||||
lda P8ZP_SCRATCH_B1
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx math_store_reg
|
||||
rts
|
||||
.pend
|
||||
|
||||
@@ -57,7 +61,7 @@ multiply_words .proc
|
||||
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
|
||||
mult16 lda #0
|
||||
sta result+2 ; clear upper bits of product
|
||||
@@ -79,7 +83,7 @@ mult16 lda #0
|
||||
ror result
|
||||
dex
|
||||
bne -
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
|
||||
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
|
||||
sty P8ZP_SCRATCH_REG
|
||||
sta P8ZP_SCRATCH_B1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx math_store_reg
|
||||
|
||||
lda #0
|
||||
ldx #8
|
||||
@@ -137,7 +141,7 @@ divmod_ub_asm .proc
|
||||
dex
|
||||
bne -
|
||||
ldy P8ZP_SCRATCH_B1
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx math_store_reg
|
||||
rts
|
||||
.pend
|
||||
|
||||
@@ -197,7 +201,7 @@ result = dividend ;save memory by reusing divident to store the result
|
||||
|
||||
sta _divisor
|
||||
sty _divisor+1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #0 ;preset remainder to 0
|
||||
sta remainder
|
||||
sta remainder+1
|
||||
@@ -224,7 +228,7 @@ result = dividend ;save memory by reusing divident to store the result
|
||||
|
||||
lda result
|
||||
ldy result+1
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
_divisor .word 0
|
||||
.pend
|
||||
@@ -308,7 +312,8 @@ _seed .word $2c9e
|
||||
.pend
|
||||
|
||||
|
||||
mul_byte_3 .proc
|
||||
; ----------- optimized multiplications (stack) : ---------
|
||||
stack_mul_byte_3 .proc
|
||||
; X + X*2
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -318,7 +323,7 @@ mul_byte_3 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_3 .proc
|
||||
stack_mul_word_3 .proc
|
||||
; W*2 + W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -335,7 +340,7 @@ mul_word_3 .proc
|
||||
.pend
|
||||
|
||||
|
||||
mul_byte_5 .proc
|
||||
stack_mul_byte_5 .proc
|
||||
; X*4 + X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -346,7 +351,7 @@ mul_byte_5 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_5 .proc
|
||||
stack_mul_word_5 .proc
|
||||
; W*4 + W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -365,7 +370,7 @@ mul_word_5 .proc
|
||||
.pend
|
||||
|
||||
|
||||
mul_byte_6 .proc
|
||||
stack_mul_byte_6 .proc
|
||||
; (X*2 + X)*2
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -376,7 +381,7 @@ mul_byte_6 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_6 .proc
|
||||
stack_mul_word_6 .proc
|
||||
; (W*2 + W)*2
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -394,7 +399,7 @@ mul_word_6 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_7 .proc
|
||||
stack_mul_byte_7 .proc
|
||||
; X*8 - X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -406,7 +411,7 @@ mul_byte_7 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_7 .proc
|
||||
stack_mul_word_7 .proc
|
||||
; W*8 - W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -426,7 +431,7 @@ mul_word_7 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_9 .proc
|
||||
stack_mul_byte_9 .proc
|
||||
; X*8 + X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -438,7 +443,7 @@ mul_byte_9 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_9 .proc
|
||||
stack_mul_word_9 .proc
|
||||
; W*8 + W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -458,7 +463,7 @@ mul_word_9 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_10 .proc
|
||||
stack_mul_byte_10 .proc
|
||||
; (X*4 + X)*2
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -470,7 +475,7 @@ mul_byte_10 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_10 .proc
|
||||
stack_mul_word_10 .proc
|
||||
; (W*4 + W)*2
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -490,7 +495,7 @@ mul_word_10 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_11 .proc
|
||||
stack_mul_byte_11 .proc
|
||||
; (X*2 + X)*4 - X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -506,7 +511,7 @@ mul_byte_11 .proc
|
||||
|
||||
; mul_word_11 is skipped (too much code)
|
||||
|
||||
mul_byte_12 .proc
|
||||
stack_mul_byte_12 .proc
|
||||
; (X*2 + X)*4
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -518,7 +523,7 @@ mul_byte_12 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_12 .proc
|
||||
stack_mul_word_12 .proc
|
||||
; (W*2 + W)*4
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -538,7 +543,7 @@ mul_word_12 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_13 .proc
|
||||
stack_mul_byte_13 .proc
|
||||
; (X*2 + X)*4 + X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -554,7 +559,7 @@ mul_byte_13 .proc
|
||||
|
||||
; mul_word_13 is skipped (too much code)
|
||||
|
||||
mul_byte_14 .proc
|
||||
stack_mul_byte_14 .proc
|
||||
; (X*8 - X)*2
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -569,7 +574,7 @@ mul_byte_14 .proc
|
||||
|
||||
; mul_word_14 is skipped (too much code)
|
||||
|
||||
mul_byte_15 .proc
|
||||
stack_mul_byte_15 .proc
|
||||
; X*16 - X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -582,7 +587,7 @@ mul_byte_15 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_15 .proc
|
||||
stack_mul_word_15 .proc
|
||||
; W*16 - W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -604,7 +609,7 @@ mul_word_15 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_20 .proc
|
||||
stack_mul_byte_20 .proc
|
||||
; (X*4 + X)*4
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -617,7 +622,7 @@ mul_byte_20 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_20 .proc
|
||||
stack_mul_word_20 .proc
|
||||
; (W*4 + W)*4
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -639,7 +644,7 @@ mul_word_20 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_25 .proc
|
||||
stack_mul_byte_25 .proc
|
||||
; (X*2 + X)*8 + X
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
@@ -654,27 +659,26 @@ mul_byte_25 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_25 .proc
|
||||
; W + W*8 + W*16
|
||||
stack_mul_word_25 .proc
|
||||
; W = (W*2 + W) *8 + W
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_W1+1
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
rol P8ZP_SCRATCH_W1+1
|
||||
asl a
|
||||
rol P8ZP_SCRATCH_W1+1
|
||||
asl a
|
||||
rol P8ZP_SCRATCH_W1+1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
clc
|
||||
adc P8ESTACK_LO+1,x
|
||||
sta P8ESTACK_LO+1,x
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
adc P8ESTACK_HI+1,x
|
||||
sta P8ESTACK_HI+1,x
|
||||
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 P8ESTACK_LO+1,x
|
||||
sta P8ESTACK_LO+1,x
|
||||
@@ -684,21 +688,16 @@ mul_word_25 .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_byte_40 .proc
|
||||
; (X*4 + X)*8
|
||||
stack_mul_byte_40 .proc
|
||||
lda P8ESTACK_LO+1,x
|
||||
asl a
|
||||
asl a
|
||||
clc
|
||||
adc P8ESTACK_LO+1,x
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
and #7
|
||||
tay
|
||||
lda mul_byte_40._forties,y
|
||||
sta P8ESTACK_LO+1,x
|
||||
rts
|
||||
.pend
|
||||
|
||||
mul_word_40 .proc
|
||||
stack_mul_word_40 .proc
|
||||
; (W*4 + W)*8
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_REG
|
||||
@@ -722,6 +721,529 @@ mul_word_40 .proc
|
||||
rts
|
||||
.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
|
||||
lda P8ESTACK_LO+1,x
|
||||
beq _sign_zero
|
||||
|
||||
@@ -686,7 +686,7 @@ func_sqrt16 .proc
|
||||
sta P8ZP_SCRATCH_W2
|
||||
lda P8ESTACK_HI+1,x
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
ldy #$00 ; r = 0
|
||||
ldx #$07
|
||||
clc ; clear bit 16 of m
|
||||
@@ -721,7 +721,7 @@ _skip1
|
||||
_skip2
|
||||
iny ; r = r or d (d is 1 here)
|
||||
_skip3
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
tya
|
||||
sta P8ESTACK_LO+1,x
|
||||
lda #0
|
||||
@@ -1216,7 +1216,7 @@ func_rndw .proc
|
||||
func_memcopy .proc
|
||||
; note: clobbers A,Y
|
||||
inx
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda P8ESTACK_LO+2,x
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda P8ESTACK_HI+2,x
|
||||
@@ -1233,7 +1233,7 @@ func_memcopy .proc
|
||||
iny
|
||||
dex
|
||||
bne -
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
inx
|
||||
inx
|
||||
rts
|
||||
@@ -1242,7 +1242,7 @@ func_memcopy .proc
|
||||
func_memset .proc
|
||||
; note: clobbers A,Y
|
||||
inx
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda P8ESTACK_LO+2,x
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda P8ESTACK_HI+2,x
|
||||
@@ -1253,7 +1253,7 @@ func_memset .proc
|
||||
lda P8ESTACK_LO,x
|
||||
ldx P8ZP_SCRATCH_B1
|
||||
jsr memset
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
inx
|
||||
inx
|
||||
rts
|
||||
@@ -1264,7 +1264,7 @@ func_memsetw .proc
|
||||
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
|
||||
|
||||
inx
|
||||
stx P8ZP_SCRATCH_REG_X
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda P8ESTACK_LO+2,x
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda P8ESTACK_HI+2,x
|
||||
@@ -1276,7 +1276,7 @@ func_memsetw .proc
|
||||
lda P8ESTACK_LO,x
|
||||
ldy P8ESTACK_HI,x
|
||||
jsr memsetw
|
||||
ldx P8ZP_SCRATCH_REG_X
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
inx
|
||||
inx
|
||||
rts
|
||||
@@ -1328,9 +1328,9 @@ memset .proc
|
||||
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
|
||||
; clobbers X, Y
|
||||
stx P8ZP_SCRATCH_B1
|
||||
sty P8ZP_SCRATCH_REG
|
||||
sty _save_reg
|
||||
ldy #0
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
ldx _save_reg
|
||||
beq _lastpage
|
||||
|
||||
_fullpage sta (P8ZP_SCRATCH_W1),y
|
||||
@@ -1347,6 +1347,7 @@ _lastpage ldy P8ZP_SCRATCH_B1
|
||||
bne -
|
||||
|
||||
+ rts
|
||||
_save_reg .byte 0
|
||||
.pend
|
||||
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.1
|
||||
4.2
|
||||
@@ -4,13 +4,10 @@ import kotlinx.cli.*
|
||||
import prog8.ast.base.AstException
|
||||
import prog8.compiler.CompilationResult
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.Cx16Target
|
||||
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 java.io.IOException
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
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 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 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)
|
||||
|
||||
try {
|
||||
@@ -50,39 +48,6 @@ private fun compileMain(args: Array<String>) {
|
||||
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)
|
||||
if(!outputPath.toFile().isDirectory) {
|
||||
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")
|
||||
|
||||
try {
|
||||
val compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, outputDir=outputPath)
|
||||
val compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, compilationTarget, outputPath)
|
||||
println("Imported files (now watching:)")
|
||||
for (importedFile in compilationResult.importedFiles) {
|
||||
print(" ")
|
||||
@@ -122,7 +87,7 @@ private fun compileMain(args: Array<String>) {
|
||||
val filepath = pathFrom(filepathRaw).normalize()
|
||||
val compilationResult: CompilationResult
|
||||
try {
|
||||
compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, outputDir=outputPath)
|
||||
compilationResult = compileProgram(filepath, !dontOptimize, !dontWriteAssembly, compilationTarget, outputPath)
|
||||
if(!compilationResult.success)
|
||||
exitProcess(1)
|
||||
} catch (x: ParsingFailedError) {
|
||||
@@ -135,7 +100,7 @@ private fun compileMain(args: Array<String>) {
|
||||
if (compilationResult.programName.isEmpty())
|
||||
println("\nCan't start emulator because no program was assembled.")
|
||||
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.registerOrPair!=null -> param.second.registerOrPair.toString()
|
||||
param.second.statusflag!=null -> param.second.statusflag.toString()
|
||||
else -> "?????1"
|
||||
else -> "?????"
|
||||
}
|
||||
output("${datatypeString(param.first.type)} ${param.first.name} @$reg")
|
||||
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 normalParameters = params.map { SubroutineParameter(it.name, it.type, it.position) }
|
||||
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) }
|
||||
return AsmsubDecl(name, normalParameters, normalReturntypes, paramRegisters, returnRegisters, clobbers)
|
||||
}
|
||||
@@ -263,7 +263,7 @@ private class AsmSubroutineParameter(name: String,
|
||||
type: DataType,
|
||||
val registerOrPair: RegisterOrPair?,
|
||||
val statusflag: Statusflag?,
|
||||
val stack: Boolean,
|
||||
// TODO implement: val stack: Boolean,
|
||||
position: Position) : SubroutineParameter(name, type, position)
|
||||
|
||||
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'")
|
||||
}
|
||||
}
|
||||
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister,
|
||||
!it.stack?.text.isNullOrEmpty(), toPosition())
|
||||
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister, toPosition())
|
||||
}
|
||||
|
||||
private fun prog8Parser.Functioncall_stmtContext.toAst(): Statement {
|
||||
@@ -472,7 +471,7 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
|
||||
litval.charliteral()!=null -> {
|
||||
try {
|
||||
val cc=litval.charliteral()
|
||||
NumericLiteralValue(DataType.UBYTE, CompilationTarget.encodeString(
|
||||
NumericLiteralValue(DataType.UBYTE, CompilationTarget.instance.encodeString(
|
||||
unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()),
|
||||
litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition())
|
||||
} catch (ce: CharConversionException) {
|
||||
|
||||
@@ -56,8 +56,8 @@ enum class DataType {
|
||||
return when(this) {
|
||||
in ByteDatatypes -> 1
|
||||
in WordDatatypes -> 2
|
||||
FLOAT -> CompilationTarget.machine.FLOAT_MEM_SIZE
|
||||
in PassByReferenceDatatypes -> CompilationTarget.machine.POINTER_MEM_SIZE
|
||||
FLOAT -> CompilationTarget.instance.machine.FLOAT_MEM_SIZE
|
||||
in PassByReferenceDatatypes -> CompilationTarget.instance.machine.POINTER_MEM_SIZE
|
||||
else -> -9999999
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,8 +671,8 @@ class RangeExpr(var from: Expression,
|
||||
val toString = to as? StringLiteralValue
|
||||
if(fromString!=null && toString!=null ) {
|
||||
// string range -> int range over character values
|
||||
fromVal = CompilationTarget.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
|
||||
toVal = CompilationTarget.encodeString(toString.value, fromString.altEncoding)[0].toInt()
|
||||
fromVal = CompilationTarget.instance.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
|
||||
toVal = CompilationTarget.instance.encodeString(toString.value, fromString.altEncoding)[0].toInt()
|
||||
} else {
|
||||
val fromLv = from as? NumericLiteralValue
|
||||
val toLv = to as? NumericLiteralValue
|
||||
|
||||
@@ -7,7 +7,9 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.CompilationOptions
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.CompilationTarget
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.functions.BuiltinFunctions
|
||||
import java.io.File
|
||||
|
||||
@@ -471,14 +473,11 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
override fun visit(decl: VarDecl) {
|
||||
fun err(msg: String, position: Position?=null) {
|
||||
errors.err(msg, position ?: decl.position)
|
||||
}
|
||||
fun err(msg: String, position: Position?=null) = errors.err(msg, position ?: decl.position)
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
// CONST can only occur on simple types (byte, word, float)
|
||||
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)")
|
||||
}
|
||||
|
||||
// FLOATS
|
||||
if(!compilerOptions.floats && decl.datatype in setOf(DataType.FLOAT, DataType.ARRAY_F) && decl.type!= VarDeclType.MEMORY) {
|
||||
// FLOATS enabled?
|
||||
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")
|
||||
}
|
||||
|
||||
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
|
||||
if(decl.isArray && decl.arraysize==null) {
|
||||
@@ -558,9 +559,11 @@ internal class AstChecker(private val program: Program,
|
||||
checkValueTypeAndRange(decl.datatype, decl.value as NumericLiteralValue)
|
||||
}
|
||||
else -> {
|
||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!.javaClass.simpleName}")
|
||||
super.visit(decl)
|
||||
return
|
||||
if(decl.type==VarDeclType.CONST) {
|
||||
err("const declaration needs a compile-time constant initializer value, or range")
|
||||
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 })
|
||||
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)
|
||||
}
|
||||
super.visit(directive)
|
||||
@@ -1156,7 +1167,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
// check if the floating point values are all within range
|
||||
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 true
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
val existing = blocks[block.name]
|
||||
@@ -40,7 +40,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
||||
if(decl.name in BuiltinFunctions)
|
||||
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)
|
||||
|
||||
if(decl.datatype==DataType.STRUCT) {
|
||||
@@ -74,7 +74,7 @@ internal class AstIdentifiersChecker(private val program: Program, private val e
|
||||
}
|
||||
|
||||
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)
|
||||
} else if(subroutine.name in BuiltinFunctions) {
|
||||
// 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) {
|
||||
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)
|
||||
|
||||
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> {
|
||||
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)
|
||||
// otherwise:
|
||||
// rewrite swap(x,y) as follows:
|
||||
|
||||
@@ -71,23 +71,6 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
|
||||
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> {
|
||||
val choices = whenStatement.choiceValues(program).sortedBy {
|
||||
|
||||
@@ -18,6 +18,21 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
|
||||
|
||||
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> {
|
||||
val leftDt = expr.left.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],
|
||||
TypecastExpression(arg.second.value, possibleType, true, arg.second.value.position),
|
||||
call as Node)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package prog8.compiler
|
||||
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
@@ -14,7 +15,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
||||
private val noModifications = emptyList<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.
|
||||
decl.value = decl.zeroElementValue()
|
||||
}
|
||||
@@ -54,7 +55,8 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
@@ -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,
|
||||
// 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.
|
||||
// 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(typecast.type==DataType.UWORD) {
|
||||
|
||||
@@ -27,7 +27,8 @@ data class CompilationOptions(val output: OutputType,
|
||||
val launcher: LauncherType,
|
||||
val zeropage: ZeropageType,
|
||||
val zpReserved: List<IntRange>,
|
||||
val floats: Boolean)
|
||||
val floats: Boolean,
|
||||
val compilationTarget: String?)
|
||||
|
||||
|
||||
class CompilerException(message: String?) : Exception(message)
|
||||
|
||||
@@ -4,7 +4,9 @@ import prog8.ast.AstToSourceCode
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.statements.Directive
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compiler.target.CompilationTarget
|
||||
import prog8.compiler.target.Cx16Target
|
||||
import prog8.optimizer.UnusedCodeRemover
|
||||
import prog8.optimizer.constantFold
|
||||
import prog8.optimizer.optimizeStatements
|
||||
@@ -13,6 +15,7 @@ import prog8.parser.ModuleImporter
|
||||
import prog8.parser.ParsingFailedError
|
||||
import prog8.parser.moduleName
|
||||
import java.nio.file.Path
|
||||
import kotlin.system.exitProcess
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
|
||||
@@ -25,12 +28,22 @@ class CompilationResult(val success: Boolean,
|
||||
fun compileProgram(filepath: Path,
|
||||
optimize: Boolean,
|
||||
writeAssembly: Boolean,
|
||||
compilationTarget: String,
|
||||
outputDir: Path): CompilationResult {
|
||||
var programName = ""
|
||||
lateinit var programAst: Program
|
||||
lateinit var importedFiles: List<Path>
|
||||
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 {
|
||||
val totalTime = measureTimeMillis {
|
||||
// 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)
|
||||
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
|
||||
CompilationTarget.machine.importLibs(compilerOptions, importer, programAst)
|
||||
// depending on the machine and compiler options we may have to include some libraries
|
||||
CompilationTarget.instance.machine.importLibs(compilerOptions, importer, programAst)
|
||||
|
||||
// always import prog8lib and math
|
||||
importer.importLibraryModule(programAst, "math")
|
||||
@@ -129,16 +142,26 @@ private fun determineCompilationOptions(program: Program): CompilationOptions {
|
||||
.map { it[0].int!!..it[1].int!! }
|
||||
.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(
|
||||
if (outputType == null) OutputType.PRG else OutputType.valueOf(outputType),
|
||||
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) {
|
||||
// perform initial syntax checks and processings
|
||||
println("Processing...")
|
||||
println("Processing for target ${CompilationTarget.instance.name}...")
|
||||
programAst.checkIdentifiers(errors)
|
||||
errors.handle()
|
||||
programAst.constantFold(errors)
|
||||
@@ -191,11 +214,14 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir:
|
||||
|
||||
// printAst(programAst)
|
||||
|
||||
CompilationTarget.machine.initializeZeropage(compilerOptions)
|
||||
val assembly = CompilationTarget.asmGenerator(
|
||||
if(compilerOptions.compilationTarget!=null && compilerOptions.compilationTarget != CompilationTarget.instance.name)
|
||||
throw AssemblyError("program's compilation target differs from configured target")
|
||||
|
||||
CompilationTarget.instance.machine.initializeZeropage(compilerOptions)
|
||||
val assembly = CompilationTarget.instance.asmGenerator(
|
||||
programAst,
|
||||
errors,
|
||||
CompilationTarget.machine.zeropage,
|
||||
CompilationTarget.instance.machine.zeropage,
|
||||
compilerOptions,
|
||||
outputDir).compileToAssembly(optimize)
|
||||
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_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_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.compiler.CompilationOptions
|
||||
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
|
||||
|
||||
|
||||
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 {
|
||||
lateinit var name: String
|
||||
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
|
||||
lateinit var instance: CompilationTarget
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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>
|
||||
var zeropage: Zeropage
|
||||
val initSystemProcname: String
|
||||
val cpu: CpuType
|
||||
|
||||
fun initializeZeropage(compilerOptions: CompilationOptions)
|
||||
|
||||
@@ -2,6 +2,7 @@ package prog8.compiler.target.c64
|
||||
|
||||
import prog8.compiler.CompilationOptions
|
||||
import prog8.compiler.OutputType
|
||||
import prog8.compiler.target.CompilationTarget
|
||||
import prog8.compiler.target.IAssemblyProgram
|
||||
import prog8.compiler.target.generatedLabelPrefix
|
||||
import java.nio.file.Path
|
||||
@@ -22,12 +23,12 @@ class AssemblyProgram(override val name: String, outputDir: Path) : IAssemblyPro
|
||||
val outFile = when (options.output) {
|
||||
OutputType.PRG -> {
|
||||
command.add("--cbm-prg")
|
||||
println("\nCreating prg.")
|
||||
println("\nCreating prg for target ${CompilationTarget.instance.name}.")
|
||||
prgFile
|
||||
}
|
||||
OutputType.RAW -> {
|
||||
command.add("--nostart")
|
||||
println("\nCreating raw binary.")
|
||||
println("\nCreating raw binary for target ${CompilationTarget.instance.name}.")
|
||||
binFile
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ internal object C64MachineDefinition: IMachineDefinition {
|
||||
override val ESTACK_HI = 0xcf00 // $ce00-$ceff inclusive
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override val initSystemProcname = "c64.init_system"
|
||||
|
||||
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_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_W2 = 0xfd // temp storage 2 for a word $fb+$fc
|
||||
|
||||
@@ -127,7 +125,7 @@ internal object C64MachineDefinition: IMachineDefinition {
|
||||
if (options.zeropage == ZeropageType.FULL) {
|
||||
free.addAll(0x04..0xf9)
|
||||
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
|
||||
} else {
|
||||
if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) {
|
||||
@@ -170,7 +168,6 @@ internal object C64MachineDefinition: IMachineDefinition {
|
||||
}
|
||||
require(SCRATCH_B1 !in free)
|
||||
require(SCRATCH_REG !in free)
|
||||
require(SCRATCH_REG_X !in free)
|
||||
require(SCRATCH_W1 !in free)
|
||||
require(SCRATCH_W2 !in free)
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ internal class AsmGen(private val program: Program,
|
||||
val options: CompilationOptions,
|
||||
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 globalFloatConsts = mutableMapOf<Double, String>() // all float values in the entire program (value -> varname)
|
||||
private val allocatedZeropageVariables = mutableMapOf<String, Pair<Int, DataType>>()
|
||||
@@ -79,7 +83,7 @@ internal class AsmGen(private val program: Program,
|
||||
|
||||
private fun header() {
|
||||
val ourName = this.javaClass.name
|
||||
val cpu = when(CompilationTarget.machine.cpu) {
|
||||
val cpu = when(CompilationTarget.instance.machine.cpu) {
|
||||
CpuType.CPU6502 -> "6502"
|
||||
CpuType.CPU65c02 -> "65c02"
|
||||
else -> "unsupported"
|
||||
@@ -94,18 +98,16 @@ internal class AsmGen(private val program: Program,
|
||||
program.actualLoadAddress = program.definedLoadAddress
|
||||
if (program.actualLoadAddress == 0) // fix load address
|
||||
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
|
||||
val zp = CompilationTarget.machine.zeropage
|
||||
val initproc = CompilationTarget.machine.initSystemProcname
|
||||
val zp = CompilationTarget.instance.machine.zeropage
|
||||
out("P8ZP_SCRATCH_B1 = ${zp.SCRATCH_B1}")
|
||||
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_W2 = ${zp.SCRATCH_W2} ; word")
|
||||
out("P8ESTACK_LO = ${CompilationTarget.machine.ESTACK_LO.toHex()}")
|
||||
out("P8ESTACK_HI = ${CompilationTarget.machine.ESTACK_HI.toHex()}")
|
||||
out("P8ESTACK_LO = ${CompilationTarget.instance.machine.ESTACK_LO.toHex()}")
|
||||
out("P8ESTACK_HI = ${CompilationTarget.instance.machine.ESTACK_HI.toHex()}")
|
||||
|
||||
when {
|
||||
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(" tsx")
|
||||
out(" stx prog8_lib.orig_stackpointer")
|
||||
if(!initproc.isNullOrEmpty())
|
||||
out(" jsr $initproc")
|
||||
if(!CompilationTarget.instance.initProcName.isNullOrEmpty())
|
||||
out(" jsr ${CompilationTarget.instance.initProcName}")
|
||||
}
|
||||
options.output == OutputType.PRG -> {
|
||||
out("; ---- program without basic sys call ----")
|
||||
out("* = ${program.actualLoadAddress.toHex()}\n")
|
||||
out(" tsx")
|
||||
out(" stx prog8_lib.orig_stackpointer")
|
||||
if(!initproc.isNullOrEmpty())
|
||||
out(" jsr $initproc")
|
||||
if(!CompilationTarget.instance.initProcName.isNullOrEmpty())
|
||||
out(" jsr ${CompilationTarget.instance.initProcName}")
|
||||
}
|
||||
options.output == OutputType.RAW -> {
|
||||
out("; ---- raw assembler program ----")
|
||||
@@ -161,7 +163,7 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
Zeropage.ExitProgramStrategy.SYSTEM_RESET -> {
|
||||
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
|
||||
out("; global float constants")
|
||||
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
|
||||
out("${flt.value}\t.byte $floatFill ; float $floatvalue")
|
||||
}
|
||||
@@ -340,7 +342,7 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
val floatFills = array.map {
|
||||
val number = (it as NumericLiteralValue).number
|
||||
CompilationTarget.machine.getFloat(number).makeFloatFillAsm()
|
||||
CompilationTarget.instance.machine.getFloat(number).makeFloatFillAsm()
|
||||
}
|
||||
out(name)
|
||||
for (f in array.zip(floatFills))
|
||||
@@ -474,7 +476,7 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
|
||||
internal fun getFloatAsmConst(number: Double): String {
|
||||
var asmName = CompilationTarget.machine.getFloatRomConst(number)
|
||||
var asmName = CompilationTarget.instance.machine.getFloatRomConst(number)
|
||||
if(asmName.isNullOrEmpty()) {
|
||||
// no ROM float const for this value, create our own
|
||||
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
|
||||
|
||||
|
||||
private val saveRegisterLabels = Stack<String>();
|
||||
|
||||
internal fun saveRegister(register: CpuRegister) {
|
||||
when(register) {
|
||||
CpuRegister.A -> out(" pha")
|
||||
CpuRegister.X -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
out(" phx")
|
||||
else
|
||||
out(" stx P8ZP_SCRATCH_REG_X")
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
|
||||
else {
|
||||
val save = makeLabel("saveX")
|
||||
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) {
|
||||
CpuRegister.A -> out(" pla")
|
||||
CpuRegister.X -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
out(" plx")
|
||||
else
|
||||
out(" ldx P8ZP_SCRATCH_REG_X")
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" plx")
|
||||
else {
|
||||
val save = saveRegisterLabels.pop()
|
||||
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) {
|
||||
outputSourceLine(stmt)
|
||||
when(stmt) {
|
||||
@@ -684,7 +713,7 @@ internal class AsmGen(private val program: Program,
|
||||
+""")
|
||||
when(register) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -722,7 +751,7 @@ internal class AsmGen(private val program: Program,
|
||||
expressionsAsmGen.translateExpression(index)
|
||||
when(register) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -792,16 +821,38 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
|
||||
private fun translate(stmt: IfStatement) {
|
||||
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)
|
||||
when {
|
||||
stmt.elsepart.containsNoCodeNorVars() -> {
|
||||
// empty else
|
||||
expressionsAsmGen.translateExpression(stmt.condition)
|
||||
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
||||
val endLabel = makeLabel("if_end")
|
||||
out(" beq $endLabel")
|
||||
translate(stmt.truepart)
|
||||
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) {
|
||||
|
||||
@@ -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.X -> {
|
||||
// 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")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||
@@ -56,7 +56,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
RegisterOrPair.AX -> {
|
||||
// return value in X register has been discarded, just push a zero in this place
|
||||
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")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
||||
@@ -64,7 +64,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
}
|
||||
RegisterOrPair.XY -> {
|
||||
// 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")
|
||||
else
|
||||
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) {
|
||||
DataType.UBYTE, DataType.BYTE -> {}
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_HI+1,x")
|
||||
else
|
||||
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("""
|
||||
lda P8ESTACK_LO+1,x
|
||||
ora #$7f
|
||||
bmi +""")
|
||||
if(CompilationTarget.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out("""
|
||||
+ stz P8ESTACK_HI+1,x""")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
+ sta P8ESTACK_HI+1,x""")
|
||||
bmi +
|
||||
lda #0
|
||||
+ sta P8ESTACK_HI+1,x""")
|
||||
}
|
||||
DataType.FLOAT -> asmgen.out(" jsr c64flt.stack_b2float")
|
||||
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) {
|
||||
val leftIDt = expr.left.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()
|
||||
when(rightDt) {
|
||||
DataType.UBYTE -> {
|
||||
if(amount in optimizedByteMultiplications) {
|
||||
if(amount in asmgen.optimizedByteMultiplications) {
|
||||
translateExpression(expr.left)
|
||||
asmgen.out(" jsr math.mul_byte_$amount")
|
||||
asmgen.out(" jsr math.stack_mul_byte_$amount")
|
||||
return
|
||||
}
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
if(amount in optimizedByteMultiplications) {
|
||||
if(amount in asmgen.optimizedByteMultiplications) {
|
||||
translateExpression(expr.left)
|
||||
asmgen.out(" jsr math.mul_byte_$amount")
|
||||
asmgen.out(" jsr math.stack_mul_byte_$amount")
|
||||
return
|
||||
}
|
||||
if(amount.absoluteValue in optimizedByteMultiplications) {
|
||||
if(amount.absoluteValue in asmgen.optimizedByteMultiplications) {
|
||||
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
|
||||
}
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
if(amount in optimizedWordMultiplications) {
|
||||
if(amount in asmgen.optimizedWordMultiplications) {
|
||||
translateExpression(expr.left)
|
||||
asmgen.out(" jsr math.mul_word_$amount")
|
||||
asmgen.out(" jsr math.stack_mul_word_$amount")
|
||||
return
|
||||
}
|
||||
}
|
||||
DataType.WORD -> {
|
||||
if(amount in optimizedWordMultiplications) {
|
||||
if(amount in asmgen.optimizedWordMultiplications) {
|
||||
translateExpression(expr.left)
|
||||
asmgen.out(" jsr math.mul_word_$amount")
|
||||
asmgen.out(" jsr math.stack_mul_word_$amount")
|
||||
return
|
||||
}
|
||||
if(amount.absoluteValue in optimizedWordMultiplications) {
|
||||
if(amount.absoluteValue in asmgen.optimizedWordMultiplications) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.SubroutineParameter
|
||||
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 saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
|
||||
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)
|
||||
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) {
|
||||
// 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.
|
||||
|
||||
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())
|
||||
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 {
|
||||
regparam.statusflag==Statusflag.Pc -> {
|
||||
asmgen.out("""
|
||||
inx
|
||||
pha
|
||||
lda P8ESTACK_LO,x
|
||||
beq +
|
||||
sec
|
||||
bcs ++
|
||||
+ clc
|
||||
+ pla""")
|
||||
argi.value.second.stack -> TODO("asmsub @stack parameter")
|
||||
argi.value.second.statusflag == Statusflag.Pc -> {
|
||||
require(argForCarry == null)
|
||||
argForCarry = argi
|
||||
}
|
||||
regparam.statusflag!=null -> {
|
||||
throw AssemblyError("can only use Carry as status flag parameter")
|
||||
argi.value.second.statusflag != null -> 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 -> {
|
||||
val tgt = AsmAssignTarget.fromRegisters(regparam.registerOrPair, program, asmgen)
|
||||
val source = AsmAssignSource(SourceStorageKind.STACK, program, tgt.datatype)
|
||||
val asgn = AsmAssignment(source, tgt, false, Position.DUMMY)
|
||||
asmgen.translateNormalAssignment(asgn)
|
||||
argi.value.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.AY) -> {
|
||||
require(argForAregister == null)
|
||||
argForAregister = argi
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -159,6 +159,7 @@ internal class AsmAssignment(val source: AsmAssignSource,
|
||||
val position: Position) {
|
||||
|
||||
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 ArrayIndexedExpression -> throw AssemblyError("source kind should have been array")
|
||||
is DirectMemoryRead -> throw AssemblyError("source kind should have been memory")
|
||||
// is TypecastExpression -> {
|
||||
// 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 TypecastExpression -> assignTypeCastedValue(assign.target, value.type, value.expression, assign)
|
||||
// is FunctionCall -> {
|
||||
// if (assign.target.kind == TargetStorageKind.STACK) {
|
||||
// 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) {
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
@@ -260,16 +296,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
when(target.register!!) {
|
||||
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")
|
||||
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 -> {
|
||||
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.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")
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
require(target.datatype in ByteDatatypes)
|
||||
when(target.kind) {
|
||||
@@ -571,19 +662,25 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
RegisterOrPair.A -> {}
|
||||
RegisterOrPair.X -> { asmgen.out(" tax") }
|
||||
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!!) {
|
||||
RegisterOrPair.A -> { asmgen.out(" txa") }
|
||||
RegisterOrPair.X -> { }
|
||||
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!!) {
|
||||
RegisterOrPair.A -> { asmgen.out(" tya") }
|
||||
RegisterOrPair.X -> { asmgen.out(" tyx") }
|
||||
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.X -> asmgen.out(" ldx #${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 -> {
|
||||
asmgen.out("""
|
||||
@@ -708,7 +807,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
// optimized case for float zero
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out("""
|
||||
stz ${target.asmVarname}
|
||||
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.X -> asmgen.out(" ldx ${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 -> {
|
||||
asmgen.out("""
|
||||
@@ -875,7 +976,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
RegisterOrPair.A -> {}
|
||||
RegisterOrPair.X -> asmgen.out(" tax")
|
||||
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 -> {
|
||||
@@ -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) {
|
||||
val addressExpr = memoryAddress.addressExpression
|
||||
val addressLv = addressExpr as? NumericLiteralValue
|
||||
|
||||
+65
-37
@@ -8,6 +8,7 @@ import prog8.compiler.target.CompilationTarget
|
||||
import prog8.compiler.target.CpuType
|
||||
import prog8.compiler.target.c64.codegen.AsmGen
|
||||
import prog8.compiler.toHex
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
private val assignmentAsmGen: AssignmentAsmGen,
|
||||
@@ -22,8 +23,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
// A = -A , A = +A, A = ~A, A = not A
|
||||
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
when (value.operator) {
|
||||
"+" -> {
|
||||
}
|
||||
"+" -> {}
|
||||
"-" -> inplaceNegate(assign.target, type)
|
||||
"~" -> inplaceInvert(assign.target, type)
|
||||
"not" -> inplaceBooleanNot(assign.target, type)
|
||||
@@ -193,7 +193,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.translateExpression(memory.addressExpression)
|
||||
// TODO buggy?:
|
||||
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 {
|
||||
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)
|
||||
@@ -250,7 +250,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else
|
||||
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("mem byte remainder")
|
||||
@@ -309,7 +311,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else
|
||||
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 byte remainder")
|
||||
@@ -367,8 +371,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||
}
|
||||
"*" -> {
|
||||
TODO("mem mul byte litval")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
if(value in asmgen.optimizedByteMultiplications) {
|
||||
TODO("optimized mem mul ubyte litval $value")
|
||||
} else {
|
||||
TODO("mem mul ubyte litval $value")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte")
|
||||
}
|
||||
}
|
||||
"/" -> {
|
||||
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")
|
||||
"*" -> {
|
||||
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")
|
||||
@@ -572,9 +580,21 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name")
|
||||
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
|
||||
"*" -> {
|
||||
// TODO what about the optimized mul_5 etc routines?
|
||||
TODO("var byte mul litval")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
if(dt == DataType.UBYTE) {
|
||||
if(value in asmgen.optimizedByteMultiplications) {
|
||||
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) {
|
||||
@@ -669,19 +689,32 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
"*" -> {
|
||||
// TODO what about the optimized mul_5 etc routines?
|
||||
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(dt == DataType.UWORD){
|
||||
if(value in asmgen.optimizedWordMultiplications) {
|
||||
asmgen.out(" lda $name | ldy $name+1 | jsr math.mul_word_$value | sta $name | sty $name+1")
|
||||
} else {
|
||||
TODO("var uword mul litval $value")
|
||||
}
|
||||
} else {
|
||||
if(value.absoluteValue in asmgen.optimizedWordMultiplications) {
|
||||
asmgen.out(" lda $name | ldy $name+1 | jsr math.mul_word_$value | sta $name | sty $name+1")
|
||||
} else {
|
||||
// TODO don't use stack here
|
||||
// TODO does this work for signed words?
|
||||
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)
|
||||
@@ -747,13 +780,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"&" -> {
|
||||
when {
|
||||
value == 0 -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out(" stz $name | stz $name+1")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta $name | sta $name+1")
|
||||
}
|
||||
value and 255 == 0 -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out(" stz $name")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta $name")
|
||||
@@ -761,7 +794,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
value < 0x0100 -> {
|
||||
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")
|
||||
else
|
||||
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).
|
||||
println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
||||
asmgen.translateExpression(value)
|
||||
asmgen.out(" jsr c64flt.pop_float_fac1")
|
||||
asmgen.saveRegister(CpuRegister.X)
|
||||
when (operator) {
|
||||
"**" -> {
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.CONUPK
|
||||
@@ -1101,7 +1134,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"+" -> {
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.FADD
|
||||
@@ -1109,7 +1141,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"-" -> {
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.FSUB
|
||||
@@ -1117,7 +1148,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"*" -> {
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.FMULT
|
||||
@@ -1125,7 +1155,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"/" -> {
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
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")
|
||||
}
|
||||
// store Fac1 back into memory
|
||||
asmgen.out("""
|
||||
ldx #<$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("""
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
@@ -1285,7 +1314,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {
|
||||
val outerCastDt = cast.type
|
||||
val innerCastDt = (cast.expression as? TypecastExpression)?.type
|
||||
|
||||
if (innerCastDt == null) {
|
||||
// simple typecast where the value is the target
|
||||
when (target.datatype) {
|
||||
@@ -1295,20 +1323,20 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out(" stz ${target.asmVarname}+1")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta ${target.asmVarname}+1")
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
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")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta ${target.asmVarname},y")
|
||||
}
|
||||
TargetStorageKind.STACK -> {
|
||||
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
|
||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_HI+1,x")
|
||||
else
|
||||
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 lateinit var zeropage: Zeropage
|
||||
override val initSystemProcname = "cx16.init_system"
|
||||
|
||||
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_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_W2 = 0x7e // temp storage 2 for a word $7e+$7f
|
||||
|
||||
@@ -96,16 +94,16 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
||||
when (options.zeropage) {
|
||||
ZeropageType.FULL -> {
|
||||
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 -> {
|
||||
free.addAll(0x22..0x7f)
|
||||
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 -> {
|
||||
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 -> {
|
||||
free.clear() // don't use zeropage at all
|
||||
@@ -115,7 +113,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
||||
|
||||
require(SCRATCH_B1 !in free)
|
||||
require(SCRATCH_REG !in free)
|
||||
require(SCRATCH_REG_X !in free)
|
||||
require(SCRATCH_W1 !in free)
|
||||
require(SCRATCH_W2 !in free)
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
||||
if(rangeExpr==null && litval!=null) {
|
||||
// arraysize initializer is a single int, and we know the size.
|
||||
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)
|
||||
else {
|
||||
// create the array itself, filled with the fillvalue.
|
||||
|
||||
@@ -297,6 +297,49 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
||||
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? {
|
||||
return when {
|
||||
subBinExpr.left isSameAs x -> subBinExpr.right
|
||||
|
||||
@@ -104,7 +104,7 @@ internal class StatementOptimizer(private val program: Program,
|
||||
if(string!=null) {
|
||||
val pos = functionCallStatement.position
|
||||
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(
|
||||
IdentifierReference(listOf("c64", "CHROUT"), 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))
|
||||
} 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(
|
||||
IdentifierReference(listOf("c64", "CHROUT"), 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
|
||||
if(size==1) {
|
||||
// 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 scope = AnonymousScope(mutableListOf(), forLoop.position)
|
||||
scope.statements.add(Assignment(AssignTarget(forLoop.loopVar, null, null, forLoop.position), byte, forLoop.position))
|
||||
|
||||
+22
-22
@@ -129,7 +129,7 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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)
|
||||
@@ -142,37 +142,37 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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> {
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testZpModesWithFloats() {
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, "c64"))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, "c64"))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, "c64"))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, "c64"))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, "c64"))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, "c64"))
|
||||
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> {
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true))
|
||||
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, "c64"))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
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)
|
||||
assertEquals(0, zp.available())
|
||||
assertFailsWith<CompilerException> {
|
||||
@@ -182,19 +182,19 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
}
|
||||
|
||||
@Test
|
||||
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())
|
||||
assertTrue(50 in zp1.free)
|
||||
assertTrue(100 in zp1.free)
|
||||
@@ -203,7 +203,7 @@ class TestC64Zeropage {
|
||||
assertTrue(200 in zp1.free)
|
||||
assertTrue(255 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())
|
||||
assertFalse(50 in zp2.free)
|
||||
assertFalse(100 in zp2.free)
|
||||
@@ -216,7 +216,7 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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())
|
||||
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
@@ -239,7 +239,7 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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())
|
||||
val loc = zp.allocate("", DataType.UWORD, null, errors)
|
||||
assertTrue(loc > 3)
|
||||
@@ -269,7 +269,7 @@ class TestC64Zeropage {
|
||||
|
||||
@Test
|
||||
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(0x04, zp.allocate("", DataType.WORD, 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
|
||||
-----------
|
||||
|
||||
.. 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>
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Subroutines that are implemented purely in assembly code and which have an assembly calling convention (i.e.
|
||||
the parameters are strictly passed via cpu registers), are defined like this::
|
||||
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 with ``asmsub`` like this::
|
||||
|
||||
asmsub FREADS32() clobbers(A,X,Y) {
|
||||
asmsub clear_screenchars (ubyte char @ A) clobbers(Y) {
|
||||
%asm {{
|
||||
lda $62
|
||||
eor #$ff
|
||||
asl a
|
||||
lda #0
|
||||
ldx #$a0
|
||||
jmp $bc4f
|
||||
}}
|
||||
ldy #0
|
||||
_loop sta c64.Screen,y
|
||||
sta c64.Screen+$0100,y
|
||||
sta c64.Screen+$0200,y
|
||||
sta c64.Screen+$02e8,y
|
||||
iny
|
||||
bne _loop
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
the statement body of such a subroutine should consist of just an inline assembly block.
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- optimize assignment codegeneration
|
||||
- get rid of all TODO's ;-)
|
||||
- get rid of all other TODO's in the code ;-)
|
||||
- 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 '_'
|
||||
- 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' ?
|
||||
- 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
|
||||
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -57,7 +57,7 @@ main {
|
||||
float Azy = cosb*sinc
|
||||
float Azz = cosb*cosc
|
||||
|
||||
ubyte i
|
||||
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]
|
||||
@@ -69,7 +69,7 @@ main {
|
||||
|
||||
; plot the points of the 3d cube
|
||||
; first the points on the back, then the points on the front (painter algorithm)
|
||||
ubyte i
|
||||
ubyte @zp i
|
||||
float rz
|
||||
float persp
|
||||
ubyte sx
|
||||
|
||||
+14
-14
@@ -1,12 +1,8 @@
|
||||
%import c64lib
|
||||
%import c64graphics
|
||||
|
||||
|
||||
main {
|
||||
|
||||
const uword width = 255
|
||||
const uword height = 200
|
||||
|
||||
; vertices
|
||||
word[] xcoor = [ -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 Azz = wcosb*wcosc / 128
|
||||
|
||||
ubyte i
|
||||
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])
|
||||
@@ -78,17 +74,21 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
const uword screen_width = 320
|
||||
const ubyte screen_height = 200
|
||||
|
||||
|
||||
sub draw_lines() {
|
||||
ubyte i
|
||||
ubyte @zp i
|
||||
for i in len(edgesFrom) -1 downto 0 {
|
||||
ubyte vFrom = edgesFrom[i]
|
||||
ubyte vTo = edgesTo[i]
|
||||
word persp1 = 256 + rotatedz[vFrom]/256
|
||||
word persp2 = 256 + rotatedz[vTo]/256
|
||||
graphics.line(rotatedx[vFrom] / persp1 + 160.w as uword,
|
||||
rotatedy[vFrom] / persp1 + 100 as ubyte,
|
||||
rotatedx[vTo] / persp2 + 160.w as uword,
|
||||
rotatedy[vTo] / persp2 + 100 as ubyte)
|
||||
ubyte @zp vFrom = edgesFrom[i]
|
||||
ubyte @zp vTo = edgesTo[i] ; TODO need compiler error for double declaration if also declared outside the for loop!
|
||||
word @zp persp1 = 256 + rotatedz[vFrom]/256
|
||||
word @zp persp2 = 256 + rotatedz[vTo]/256
|
||||
graphics.line(rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||
rotatedy[vFrom] / persp1 + screen_height/2 as ubyte,
|
||||
rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||
rotatedy[vTo] / persp2 + screen_height/2 as ubyte)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ main {
|
||||
word Azy = wcosb*wsinc / 128
|
||||
word Azz = wcosb*wcosc / 128
|
||||
|
||||
ubyte i
|
||||
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])
|
||||
@@ -138,8 +138,8 @@ main {
|
||||
|
||||
; 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)
|
||||
ubyte i
|
||||
ubyte i1
|
||||
ubyte @zp i
|
||||
ubyte @zp i1
|
||||
for i in 6 downto 0 {
|
||||
for i1 in 0 to i {
|
||||
ubyte i2 = i1+1
|
||||
@@ -154,7 +154,7 @@ main {
|
||||
ubyte[] spritecolors = [1,1,7,15,12,11,9,9]
|
||||
|
||||
for i in 0 to 7 {
|
||||
word zc = rotatedz[i]
|
||||
word @zp zc = rotatedz[i]
|
||||
word persp = 300+zc/256
|
||||
ubyte sx = rotatedx[i] / persp + width/2 as ubyte + 20
|
||||
ubyte sy = rotatedy[i] / persp + height/2 as ubyte + 40
|
||||
|
||||
+4
-4
@@ -62,7 +62,7 @@ main {
|
||||
word Azy = wcosb*wsinc / 128
|
||||
word Azz = wcosb*wcosc / 128
|
||||
|
||||
ubyte i
|
||||
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]
|
||||
@@ -76,9 +76,9 @@ main {
|
||||
; plot the points of the 3d cube
|
||||
; first the points on the back, then the points on the front (painter algorithm)
|
||||
|
||||
ubyte i
|
||||
word rz
|
||||
word persp
|
||||
ubyte @zp i
|
||||
word @zp rz
|
||||
word @zp persp
|
||||
byte sx
|
||||
byte sy
|
||||
|
||||
|
||||
@@ -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).")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
]
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
%target cx16
|
||||
%import cx16textio
|
||||
%zeropage basicsafe
|
||||
|
||||
@@ -8,28 +9,6 @@ main {
|
||||
|
||||
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.r1 = mkword(19, 27)
|
||||
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 cx16flt
|
||||
%zeropage basicsafe
|
||||
@@ -5,7 +6,7 @@
|
||||
main {
|
||||
const uword width = 256
|
||||
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() {
|
||||
initialize()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
%target cx16
|
||||
%import cx16textio
|
||||
%import cx16flt
|
||||
%zeropage basicsafe
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
; CommanderX16 text clock example!
|
||||
; CommanderX16 simple graphics example!
|
||||
; make sure to compile with the cx16 compiler target.
|
||||
|
||||
%target cx16
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
@@ -1,3 +1,4 @@
|
||||
%target cx16
|
||||
%import cx16textio
|
||||
%import cx16flt
|
||||
%zeropage basicsafe
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
%target cx16
|
||||
%import cx16lib
|
||||
%import cx16textio
|
||||
%zeropage basicsafe
|
||||
|
||||
@@ -38,9 +38,7 @@ main {
|
||||
}
|
||||
|
||||
if iter & 1
|
||||
; TODO fix plot() so we don't have to use separate internal variable
|
||||
graphics.internal_plotx = pixelx
|
||||
graphics.internal_plot(pixely)
|
||||
graphics.plot(pixelx, pixely)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -385,9 +385,9 @@ waitkey:
|
||||
}
|
||||
|
||||
sub drawBlock(ubyte x, ubyte y, ubyte character) {
|
||||
ubyte i
|
||||
ubyte @zp i
|
||||
for i in 15 downto 0 {
|
||||
ubyte c=blocklogic.currentBlock[i]
|
||||
ubyte @zp c=blocklogic.currentBlock[i]
|
||||
if c
|
||||
txt.setcc((i&3)+x, (i/4)+y, character, c)
|
||||
}
|
||||
@@ -534,7 +534,7 @@ blocklogic {
|
||||
}
|
||||
|
||||
sub noCollision(ubyte xpos, ubyte ypos) -> ubyte {
|
||||
ubyte i
|
||||
ubyte @zp i
|
||||
for i in 15 downto 0 {
|
||||
if currentBlock[i] and txt.getchr(xpos + (i&3), ypos+i/4)!=32
|
||||
return false
|
||||
|
||||
+7
-2
@@ -1,8 +1,12 @@
|
||||
%import c64lib
|
||||
%import c64graphics
|
||||
%import c64textio
|
||||
;%import c64flt
|
||||
;%option enable_floats
|
||||
%zeropage basicsafe
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
|
||||
;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.
|
||||
@@ -10,6 +14,7 @@ main {
|
||||
; sub color(...) {}
|
||||
; 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 :
|
||||
directivename=('%output' | '%launcher' | '%zeropage' | '%zpreserved' | '%address' | '%import' |
|
||||
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option')
|
||||
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option' | '%target' )
|
||||
(directivearg? | directivearg (',' directivearg)*)
|
||||
;
|
||||
|
||||
@@ -273,7 +273,7 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns?
|
||||
|
||||
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? ')' ;
|
||||
|
||||
|
||||
Reference in new issue
Block a user