mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-08-10 06:24:56 +00:00
Move tests to own files in doc.
This commit is contained in:
480
README.markdown
480
README.markdown
@@ -2,9 +2,9 @@ SixtyPical
|
|||||||
==========
|
==========
|
||||||
|
|
||||||
SixtyPical is a very low-level programming language, similar to 6502 assembly,
|
SixtyPical is a very low-level programming language, similar to 6502 assembly,
|
||||||
with block structure and static analysis through abstract interpretation.
|
with static analysis through type-checking and abstract interpretation.
|
||||||
|
|
||||||
It is a work in progress, currently at the proof-of-concept stage.
|
It is a **work in progress**, currently at the **proof-of-concept** stage.
|
||||||
|
|
||||||
It is expected that a common use case for SixtyPical would be retroprogramming
|
It is expected that a common use case for SixtyPical would be retroprogramming
|
||||||
for the Commodore 64 and other 6502-based computers such as the VIC-20.
|
for the Commodore 64 and other 6502-based computers such as the VIC-20.
|
||||||
@@ -19,8 +19,8 @@ opcodes, but generate slightly different (safer, but intuitively related)
|
|||||||
sequences of opcodes. Et cetera.
|
sequences of opcodes. Et cetera.
|
||||||
|
|
||||||
`sixtypical` is the reference implementation of SixtyPical. It is written in
|
`sixtypical` is the reference implementation of SixtyPical. It is written in
|
||||||
Haskell. It can currently parse and analyze a SixtyPical program, and will
|
Haskell. It can currently parse and check a SixtyPical program, and can
|
||||||
eventually be able to compile it to an Ophis assembler listing.
|
emit an Ophis assembler listing for it.
|
||||||
|
|
||||||
Concepts
|
Concepts
|
||||||
--------
|
--------
|
||||||
@@ -131,11 +131,13 @@ Note to self, the `pl` opcodes *do* change flags.
|
|||||||
Instruction Support so far
|
Instruction Support so far
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
A `X` indicates unsupported. A `!` indicates will-not-support.
|
A `X` indicates unsupported.
|
||||||
|
|
||||||
Funny syntax indicates use of a special form.
|
Funny syntax indicates use of a special form.
|
||||||
|
|
||||||
In these, `absolute` must be a `reserve`d or `locate`d address.
|
In these, `absolute` must be a `reserve`d or `locate`d address.
|
||||||
|
`immediate` must be a literal decimal or hexadecimal number
|
||||||
|
(or in future, a declared constant.)
|
||||||
|
|
||||||
.
|
.
|
||||||
adc #immediate
|
adc #immediate
|
||||||
@@ -268,472 +270,4 @@ TODO
|
|||||||
* give length for tables, must be there for reserved
|
* give length for tables, must be there for reserved
|
||||||
* Character tables ("strings" to everybody else)
|
* Character tables ("strings" to everybody else)
|
||||||
* Work out the analyses again and document them
|
* Work out the analyses again and document them
|
||||||
* lda wordaddress --> is not legal. use lda <wordaddr or lda >wordaddr
|
|
||||||
* Addressing modes; rename instructions to match
|
* Addressing modes; rename instructions to match
|
||||||
|
|
||||||
Tests
|
|
||||||
-----
|
|
||||||
|
|
||||||
-> Tests for functionality "Parse SixtyPical program"
|
|
||||||
|
|
||||||
-> Functionality "Parse SixtyPical program" is implemented by
|
|
||||||
-> shell command "bin/sixtypical parse %(test-file)"
|
|
||||||
|
|
||||||
-> Tests for functionality "Check SixtyPical program"
|
|
||||||
|
|
||||||
-> Functionality "Check SixtyPical program" is implemented by
|
|
||||||
-> shell command "bin/sixtypical check %(test-file)"
|
|
||||||
|
|
||||||
`main` must be present.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
| routine frog {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
? missing 'main' routine
|
|
||||||
|
|
||||||
A comment may appear at the start of a block.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| ; this program does nothing
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
A comment may appear after each command.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| lda #1 ; we assemble the fnord using
|
|
||||||
| ldx #1 ; multiple lorem ipsums which
|
|
||||||
| ldy #1
|
|
||||||
| lda #1 ; we
|
|
||||||
| ldx #1 ; found under the bridge by the old mill yesterday
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
A comment may appear after each declaration.
|
|
||||||
|
|
||||||
| reserve byte lives ; fnord
|
|
||||||
| assign byte gdcol 647 ; fnord
|
|
||||||
| external blastoff 4 ; fnnnnnnnnnnnnnnnnfffffffff
|
|
||||||
|
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
A program may `reserve` and `assign`.
|
|
||||||
|
|
||||||
| reserve byte lives
|
|
||||||
| assign byte gdcol 647
|
|
||||||
| reserve word score
|
|
||||||
| assign word memstr 641
|
|
||||||
| reserve vector v
|
|
||||||
| assign vector cinv 788
|
|
||||||
| reserve byte table frequencies
|
|
||||||
| assign byte table screen 1024
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
A program may declare an `external`.
|
|
||||||
|
|
||||||
| external blastoff 49152
|
|
||||||
| routine main {
|
|
||||||
| jsr blastoff
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
All declarations (`reserve`s and `assign`s) must come before any `routines`.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| lda score
|
|
||||||
| }
|
|
||||||
| reserve word score
|
|
||||||
? expecting "routine"
|
|
||||||
|
|
||||||
All locations used in all routines must be declared first.
|
|
||||||
|
|
||||||
| reserve byte score
|
|
||||||
| routine main {
|
|
||||||
| lda score
|
|
||||||
| cmp screen
|
|
||||||
| }
|
|
||||||
? undeclared location
|
|
||||||
|
|
||||||
Even in inner blocks.
|
|
||||||
|
|
||||||
| reserve byte score
|
|
||||||
| assign byte screen 1024
|
|
||||||
| routine main {
|
|
||||||
| lda score
|
|
||||||
| cmp screen
|
|
||||||
| if beq {
|
|
||||||
| lda score
|
|
||||||
| } else {
|
|
||||||
| lda fnord
|
|
||||||
| }
|
|
||||||
| }
|
|
||||||
? undeclared location
|
|
||||||
|
|
||||||
All routines jsr'ed to must be defined, or external.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| jsr blastoff
|
|
||||||
| }
|
|
||||||
? undeclared routine
|
|
||||||
|
|
||||||
No duplicate location names in declarations.
|
|
||||||
|
|
||||||
| reserve word score
|
|
||||||
| assign word score 4000
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
? duplicate location name
|
|
||||||
|
|
||||||
No duplicate routine names.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
| routine main {
|
|
||||||
| txa
|
|
||||||
| }
|
|
||||||
? duplicate routine name
|
|
||||||
|
|
||||||
No duplicate routine names, including externals.
|
|
||||||
|
|
||||||
| external main 7000
|
|
||||||
| routine main {
|
|
||||||
| nop
|
|
||||||
| }
|
|
||||||
? duplicate routine name
|
|
||||||
|
|
||||||
We can jump to a vector.
|
|
||||||
|
|
||||||
| reserve vector blah
|
|
||||||
| routine main {
|
|
||||||
| jmp blah
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
We can't jump to a word.
|
|
||||||
|
|
||||||
| reserve word blah
|
|
||||||
| routine main {
|
|
||||||
| jmp blah
|
|
||||||
| }
|
|
||||||
? jmp to non-vector
|
|
||||||
|
|
||||||
We can't jump to a byte.
|
|
||||||
|
|
||||||
| assign byte screen 1024
|
|
||||||
| routine main {
|
|
||||||
| jmp screen
|
|
||||||
| }
|
|
||||||
? jmp to non-vector
|
|
||||||
|
|
||||||
We can absolute-indexed a byte table.
|
|
||||||
|
|
||||||
| assign byte table screen 1024
|
|
||||||
| routine main {
|
|
||||||
| sta screen, x
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
We cannot absolute-indexed a byte.
|
|
||||||
|
|
||||||
| assign byte screen 1024
|
|
||||||
| routine main {
|
|
||||||
| sta screen, x
|
|
||||||
| }
|
|
||||||
? indexed access of non-table
|
|
||||||
|
|
||||||
We cannot absolute-indexed a word.
|
|
||||||
|
|
||||||
| assign word screen 1024
|
|
||||||
| routine main {
|
|
||||||
| sta screen, x
|
|
||||||
| }
|
|
||||||
? indexed access of non-table
|
|
||||||
|
|
||||||
We cannot absolute access a word.
|
|
||||||
|
|
||||||
| assign word screen 1024
|
|
||||||
| routine main {
|
|
||||||
| ldx screen
|
|
||||||
| }
|
|
||||||
? incompatible types 'Word' and 'Byte'
|
|
||||||
|
|
||||||
No, not even with `ora`.
|
|
||||||
|
|
||||||
| assign word screen 1024
|
|
||||||
| routine main {
|
|
||||||
| ora screen
|
|
||||||
| }
|
|
||||||
? incompatible types 'Byte' and 'Word'
|
|
||||||
|
|
||||||
Instead, we have to do this.
|
|
||||||
|
|
||||||
| assign word screen 1024
|
|
||||||
| routine main {
|
|
||||||
| lda <screen
|
|
||||||
| lda >screen
|
|
||||||
| }
|
|
||||||
= True
|
|
||||||
|
|
||||||
We cannot absolute access a vector.
|
|
||||||
|
|
||||||
| assign vector screen 1024
|
|
||||||
| routine main {
|
|
||||||
| lda screen
|
|
||||||
| }
|
|
||||||
? incompatible types 'Vector' and 'Byte'
|
|
||||||
|
|
||||||
-> Tests for functionality "Emit ASM for SixtyPical program"
|
|
||||||
|
|
||||||
-> Functionality "Emit ASM for SixtyPical program" is implemented by
|
|
||||||
-> shell command "bin/sixtypical emit %(test-file)"
|
|
||||||
|
|
||||||
| reserve word vword
|
|
||||||
| reserve byte vbyte
|
|
||||||
| assign byte table table 1024
|
|
||||||
| routine main {
|
|
||||||
| lda #4
|
|
||||||
| ldx #0
|
|
||||||
| ldy #$FF
|
|
||||||
| lda vbyte
|
|
||||||
| lda table, x
|
|
||||||
| lda table, y
|
|
||||||
| lda (vword), y
|
|
||||||
| lda <vword
|
|
||||||
| lda >vword
|
|
||||||
| inc vbyte
|
|
||||||
| tax
|
|
||||||
| inx
|
|
||||||
| dex
|
|
||||||
| stx vbyte
|
|
||||||
| tay
|
|
||||||
| iny
|
|
||||||
| dey
|
|
||||||
| sty vbyte
|
|
||||||
| cmp vbyte
|
|
||||||
| cmp #30
|
|
||||||
| cmp <vword
|
|
||||||
| cmp >vword
|
|
||||||
| ldx vbyte
|
|
||||||
| cpx vbyte
|
|
||||||
| cpx #31
|
|
||||||
| txa
|
|
||||||
| ldy vbyte
|
|
||||||
| cpy vbyte
|
|
||||||
| cpy #32
|
|
||||||
| tya
|
|
||||||
| sta vbyte
|
|
||||||
| sta table, x
|
|
||||||
| sta table, y
|
|
||||||
| sta (vword), y
|
|
||||||
| sta <vword
|
|
||||||
| sta >vword
|
|
||||||
| dec vbyte
|
|
||||||
| clc
|
|
||||||
| cld
|
|
||||||
| clv
|
|
||||||
| sec
|
|
||||||
| sed
|
|
||||||
| adc #8
|
|
||||||
| adc vbyte
|
|
||||||
| and #8
|
|
||||||
| and vbyte
|
|
||||||
| sbc #8
|
|
||||||
| sbc vbyte
|
|
||||||
| ora #8
|
|
||||||
| ora vbyte
|
|
||||||
| }
|
|
||||||
= main:
|
|
||||||
= lda #4
|
|
||||||
= ldx #0
|
|
||||||
= ldy #255
|
|
||||||
= lda vbyte
|
|
||||||
= lda table, x
|
|
||||||
= lda table, y
|
|
||||||
= lda (vword), y
|
|
||||||
= lda vword
|
|
||||||
= lda vword+1
|
|
||||||
= inc vbyte
|
|
||||||
= tax
|
|
||||||
= inx
|
|
||||||
= dex
|
|
||||||
= stx vbyte
|
|
||||||
= tay
|
|
||||||
= iny
|
|
||||||
= dey
|
|
||||||
= sty vbyte
|
|
||||||
= cmp vbyte
|
|
||||||
= cmp #30
|
|
||||||
= cmp vword
|
|
||||||
= cmp vword+1
|
|
||||||
= ldx vbyte
|
|
||||||
= cpx vbyte
|
|
||||||
= cpx #31
|
|
||||||
= txa
|
|
||||||
= ldy vbyte
|
|
||||||
= cpy vbyte
|
|
||||||
= cpy #32
|
|
||||||
= tya
|
|
||||||
= sta vbyte
|
|
||||||
= sta table, x
|
|
||||||
= sta table, y
|
|
||||||
= sta (vword), y
|
|
||||||
= sta vword
|
|
||||||
= sta vword+1
|
|
||||||
= dec vbyte
|
|
||||||
= clc
|
|
||||||
= cld
|
|
||||||
= clv
|
|
||||||
= sec
|
|
||||||
= sed
|
|
||||||
= adc #8
|
|
||||||
= adc vbyte
|
|
||||||
= and #8
|
|
||||||
= and vbyte
|
|
||||||
= sbc #8
|
|
||||||
= sbc vbyte
|
|
||||||
= ora #8
|
|
||||||
= ora vbyte
|
|
||||||
= rts
|
|
||||||
=
|
|
||||||
= vword: .word 0
|
|
||||||
= vbyte: .byte 0
|
|
||||||
= .alias table 1024
|
|
||||||
|
|
||||||
| assign byte screen $0400
|
|
||||||
| routine main {
|
|
||||||
| lda screen
|
|
||||||
| cmp screen
|
|
||||||
| if beq {
|
|
||||||
| tax
|
|
||||||
| } else {
|
|
||||||
| tay
|
|
||||||
| }
|
|
||||||
| sta screen
|
|
||||||
| }
|
|
||||||
= main:
|
|
||||||
= lda screen
|
|
||||||
= cmp screen
|
|
||||||
= BEQ _label_1
|
|
||||||
= tay
|
|
||||||
= jmp _past_1
|
|
||||||
= _label_1:
|
|
||||||
= tax
|
|
||||||
= _past_1:
|
|
||||||
= sta screen
|
|
||||||
= rts
|
|
||||||
=
|
|
||||||
= .alias screen 1024
|
|
||||||
|
|
||||||
| assign byte screen 1024
|
|
||||||
| reserve byte zero
|
|
||||||
| routine main {
|
|
||||||
| ldy zero
|
|
||||||
| repeat bne {
|
|
||||||
| inc screen
|
|
||||||
| dey
|
|
||||||
| cpy zero
|
|
||||||
| }
|
|
||||||
| sty screen
|
|
||||||
| }
|
|
||||||
= main:
|
|
||||||
= ldy zero
|
|
||||||
=
|
|
||||||
= _repeat_1:
|
|
||||||
= inc screen
|
|
||||||
= dey
|
|
||||||
= cpy zero
|
|
||||||
= BNE _repeat_1
|
|
||||||
= sty screen
|
|
||||||
= rts
|
|
||||||
=
|
|
||||||
= .alias screen 1024
|
|
||||||
= zero: .byte 0
|
|
||||||
|
|
||||||
Nested ifs.
|
|
||||||
|
|
||||||
| routine main {
|
|
||||||
| if beq {
|
|
||||||
| if bcc {
|
|
||||||
| lda #0
|
|
||||||
| } else {
|
|
||||||
| if bvs {
|
|
||||||
| lda #1
|
|
||||||
| } else {
|
|
||||||
| lda #2
|
|
||||||
| }
|
|
||||||
| }
|
|
||||||
| } else {
|
|
||||||
| lda #3
|
|
||||||
| }
|
|
||||||
| }
|
|
||||||
= main:
|
|
||||||
= BEQ _label_3
|
|
||||||
= lda #3
|
|
||||||
= jmp _past_3
|
|
||||||
= _label_3:
|
|
||||||
= BCC _label_2
|
|
||||||
= BVS _label_1
|
|
||||||
= lda #2
|
|
||||||
= jmp _past_1
|
|
||||||
= _label_1:
|
|
||||||
= lda #1
|
|
||||||
= _past_1:
|
|
||||||
= jmp _past_2
|
|
||||||
= _label_2:
|
|
||||||
= lda #0
|
|
||||||
= _past_2:
|
|
||||||
= _past_3:
|
|
||||||
= rts
|
|
||||||
|
|
||||||
Installing an interrupt handler (at the Kernal level, i.e. with CINV)
|
|
||||||
|
|
||||||
| assign byte screen 1024
|
|
||||||
| assign vector cinv 788
|
|
||||||
| reserve vector save_cinv
|
|
||||||
|
|
|
||||||
| routine main {
|
|
||||||
| sei {
|
|
||||||
| copy vector cinv to save_cinv
|
|
||||||
| copy routine our_cinv to cinv
|
|
||||||
| }
|
|
||||||
| }
|
|
||||||
|
|
|
||||||
| routine our_cinv {
|
|
||||||
| inc screen
|
|
||||||
| jmp save_cinv
|
|
||||||
| }
|
|
||||||
= main:
|
|
||||||
= sei
|
|
||||||
= lda cinv
|
|
||||||
= sta save_cinv
|
|
||||||
= lda cinv+1
|
|
||||||
= sta save_cinv+1
|
|
||||||
= lda #<our_cinv
|
|
||||||
= sta cinv
|
|
||||||
= lda #>our_cinv
|
|
||||||
= sta cinv+1
|
|
||||||
= cli
|
|
||||||
= rts
|
|
||||||
=
|
|
||||||
= our_cinv:
|
|
||||||
= inc screen
|
|
||||||
= jmp (save_cinv)
|
|
||||||
= rts
|
|
||||||
=
|
|
||||||
= .alias screen 1024
|
|
||||||
= .alias cinv 788
|
|
||||||
= save_cinv: .word 0
|
|
||||||
|
224
doc/Checking.markdown
Normal file
224
doc/Checking.markdown
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
Checking SixtyPical Programs
|
||||||
|
============================
|
||||||
|
|
||||||
|
-> Tests for functionality "Parse SixtyPical program"
|
||||||
|
|
||||||
|
-> Functionality "Parse SixtyPical program" is implemented by
|
||||||
|
-> shell command "bin/sixtypical parse %(test-file)"
|
||||||
|
|
||||||
|
-> Tests for functionality "Check SixtyPical program"
|
||||||
|
|
||||||
|
-> Functionality "Check SixtyPical program" is implemented by
|
||||||
|
-> shell command "bin/sixtypical check %(test-file)"
|
||||||
|
|
||||||
|
`main` must be present.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
| routine frog {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
? missing 'main' routine
|
||||||
|
|
||||||
|
A comment may appear at the start of a block.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| ; this program does nothing
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
A comment may appear after each command.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| lda #1 ; we assemble the fnord using
|
||||||
|
| ldx #1 ; multiple lorem ipsums which
|
||||||
|
| ldy #1
|
||||||
|
| lda #1 ; we
|
||||||
|
| ldx #1 ; found under the bridge by the old mill yesterday
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
A comment may appear after each declaration.
|
||||||
|
|
||||||
|
| reserve byte lives ; fnord
|
||||||
|
| assign byte gdcol 647 ; fnord
|
||||||
|
| external blastoff 4 ; fnnnnnnnnnnnnnnnnfffffffff
|
||||||
|
|
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
A program may `reserve` and `assign`.
|
||||||
|
|
||||||
|
| reserve byte lives
|
||||||
|
| assign byte gdcol 647
|
||||||
|
| reserve word score
|
||||||
|
| assign word memstr 641
|
||||||
|
| reserve vector v
|
||||||
|
| assign vector cinv 788
|
||||||
|
| reserve byte table frequencies
|
||||||
|
| assign byte table screen 1024
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
A program may declare an `external`.
|
||||||
|
|
||||||
|
| external blastoff 49152
|
||||||
|
| routine main {
|
||||||
|
| jsr blastoff
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
All declarations (`reserve`s and `assign`s) must come before any `routines`.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| lda score
|
||||||
|
| }
|
||||||
|
| reserve word score
|
||||||
|
? expecting "routine"
|
||||||
|
|
||||||
|
All locations used in all routines must be declared first.
|
||||||
|
|
||||||
|
| reserve byte score
|
||||||
|
| routine main {
|
||||||
|
| lda score
|
||||||
|
| cmp screen
|
||||||
|
| }
|
||||||
|
? undeclared location
|
||||||
|
|
||||||
|
Even in inner blocks.
|
||||||
|
|
||||||
|
| reserve byte score
|
||||||
|
| assign byte screen 1024
|
||||||
|
| routine main {
|
||||||
|
| lda score
|
||||||
|
| cmp screen
|
||||||
|
| if beq {
|
||||||
|
| lda score
|
||||||
|
| } else {
|
||||||
|
| lda fnord
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
? undeclared location
|
||||||
|
|
||||||
|
All routines jsr'ed to must be defined, or external.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| jsr blastoff
|
||||||
|
| }
|
||||||
|
? undeclared routine
|
||||||
|
|
||||||
|
No duplicate location names in declarations.
|
||||||
|
|
||||||
|
| reserve word score
|
||||||
|
| assign word score 4000
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
? duplicate location name
|
||||||
|
|
||||||
|
No duplicate routine names.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
| routine main {
|
||||||
|
| txa
|
||||||
|
| }
|
||||||
|
? duplicate routine name
|
||||||
|
|
||||||
|
No duplicate routine names, including externals.
|
||||||
|
|
||||||
|
| external main 7000
|
||||||
|
| routine main {
|
||||||
|
| nop
|
||||||
|
| }
|
||||||
|
? duplicate routine name
|
||||||
|
|
||||||
|
We can jump to a vector.
|
||||||
|
|
||||||
|
| reserve vector blah
|
||||||
|
| routine main {
|
||||||
|
| jmp blah
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
We can't jump to a word.
|
||||||
|
|
||||||
|
| reserve word blah
|
||||||
|
| routine main {
|
||||||
|
| jmp blah
|
||||||
|
| }
|
||||||
|
? jmp to non-vector
|
||||||
|
|
||||||
|
We can't jump to a byte.
|
||||||
|
|
||||||
|
| assign byte screen 1024
|
||||||
|
| routine main {
|
||||||
|
| jmp screen
|
||||||
|
| }
|
||||||
|
? jmp to non-vector
|
||||||
|
|
||||||
|
We can absolute-indexed a byte table.
|
||||||
|
|
||||||
|
| assign byte table screen 1024
|
||||||
|
| routine main {
|
||||||
|
| sta screen, x
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
We cannot absolute-indexed a byte.
|
||||||
|
|
||||||
|
| assign byte screen 1024
|
||||||
|
| routine main {
|
||||||
|
| sta screen, x
|
||||||
|
| }
|
||||||
|
? indexed access of non-table
|
||||||
|
|
||||||
|
We cannot absolute-indexed a word.
|
||||||
|
|
||||||
|
| assign word screen 1024
|
||||||
|
| routine main {
|
||||||
|
| sta screen, x
|
||||||
|
| }
|
||||||
|
? indexed access of non-table
|
||||||
|
|
||||||
|
We cannot absolute access a word.
|
||||||
|
|
||||||
|
| assign word screen 1024
|
||||||
|
| routine main {
|
||||||
|
| ldx screen
|
||||||
|
| }
|
||||||
|
? incompatible types 'Word' and 'Byte'
|
||||||
|
|
||||||
|
No, not even with `ora`.
|
||||||
|
|
||||||
|
| assign word screen 1024
|
||||||
|
| routine main {
|
||||||
|
| ora screen
|
||||||
|
| }
|
||||||
|
? incompatible types 'Byte' and 'Word'
|
||||||
|
|
||||||
|
Instead, we have to do this.
|
||||||
|
|
||||||
|
| assign word screen 1024
|
||||||
|
| routine main {
|
||||||
|
| lda <screen
|
||||||
|
| lda >screen
|
||||||
|
| }
|
||||||
|
= True
|
||||||
|
|
||||||
|
We cannot absolute access a vector.
|
||||||
|
|
||||||
|
| assign vector screen 1024
|
||||||
|
| routine main {
|
||||||
|
| lda screen
|
||||||
|
| }
|
||||||
|
? incompatible types 'Vector' and 'Byte'
|
244
doc/Emitting.markdown
Normal file
244
doc/Emitting.markdown
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
Emitting Ophis from SixtyPical Programs
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
-> Tests for functionality "Emit ASM for SixtyPical program"
|
||||||
|
|
||||||
|
-> Functionality "Emit ASM for SixtyPical program" is implemented by
|
||||||
|
-> shell command "bin/sixtypical emit %(test-file)"
|
||||||
|
|
||||||
|
| reserve word vword
|
||||||
|
| reserve byte vbyte
|
||||||
|
| assign byte table table 1024
|
||||||
|
| routine main {
|
||||||
|
| lda #4
|
||||||
|
| ldx #0
|
||||||
|
| ldy #$FF
|
||||||
|
| lda vbyte
|
||||||
|
| lda table, x
|
||||||
|
| lda table, y
|
||||||
|
| lda (vword), y
|
||||||
|
| lda <vword
|
||||||
|
| lda >vword
|
||||||
|
| inc vbyte
|
||||||
|
| tax
|
||||||
|
| inx
|
||||||
|
| dex
|
||||||
|
| stx vbyte
|
||||||
|
| tay
|
||||||
|
| iny
|
||||||
|
| dey
|
||||||
|
| sty vbyte
|
||||||
|
| cmp vbyte
|
||||||
|
| cmp #30
|
||||||
|
| cmp <vword
|
||||||
|
| cmp >vword
|
||||||
|
| ldx vbyte
|
||||||
|
| cpx vbyte
|
||||||
|
| cpx #31
|
||||||
|
| txa
|
||||||
|
| ldy vbyte
|
||||||
|
| cpy vbyte
|
||||||
|
| cpy #32
|
||||||
|
| tya
|
||||||
|
| sta vbyte
|
||||||
|
| sta table, x
|
||||||
|
| sta table, y
|
||||||
|
| sta (vword), y
|
||||||
|
| sta <vword
|
||||||
|
| sta >vword
|
||||||
|
| dec vbyte
|
||||||
|
| clc
|
||||||
|
| cld
|
||||||
|
| clv
|
||||||
|
| sec
|
||||||
|
| sed
|
||||||
|
| adc #8
|
||||||
|
| adc vbyte
|
||||||
|
| and #8
|
||||||
|
| and vbyte
|
||||||
|
| sbc #8
|
||||||
|
| sbc vbyte
|
||||||
|
| ora #8
|
||||||
|
| ora vbyte
|
||||||
|
| }
|
||||||
|
= main:
|
||||||
|
= lda #4
|
||||||
|
= ldx #0
|
||||||
|
= ldy #255
|
||||||
|
= lda vbyte
|
||||||
|
= lda table, x
|
||||||
|
= lda table, y
|
||||||
|
= lda (vword), y
|
||||||
|
= lda vword
|
||||||
|
= lda vword+1
|
||||||
|
= inc vbyte
|
||||||
|
= tax
|
||||||
|
= inx
|
||||||
|
= dex
|
||||||
|
= stx vbyte
|
||||||
|
= tay
|
||||||
|
= iny
|
||||||
|
= dey
|
||||||
|
= sty vbyte
|
||||||
|
= cmp vbyte
|
||||||
|
= cmp #30
|
||||||
|
= cmp vword
|
||||||
|
= cmp vword+1
|
||||||
|
= ldx vbyte
|
||||||
|
= cpx vbyte
|
||||||
|
= cpx #31
|
||||||
|
= txa
|
||||||
|
= ldy vbyte
|
||||||
|
= cpy vbyte
|
||||||
|
= cpy #32
|
||||||
|
= tya
|
||||||
|
= sta vbyte
|
||||||
|
= sta table, x
|
||||||
|
= sta table, y
|
||||||
|
= sta (vword), y
|
||||||
|
= sta vword
|
||||||
|
= sta vword+1
|
||||||
|
= dec vbyte
|
||||||
|
= clc
|
||||||
|
= cld
|
||||||
|
= clv
|
||||||
|
= sec
|
||||||
|
= sed
|
||||||
|
= adc #8
|
||||||
|
= adc vbyte
|
||||||
|
= and #8
|
||||||
|
= and vbyte
|
||||||
|
= sbc #8
|
||||||
|
= sbc vbyte
|
||||||
|
= ora #8
|
||||||
|
= ora vbyte
|
||||||
|
= rts
|
||||||
|
=
|
||||||
|
= vword: .word 0
|
||||||
|
= vbyte: .byte 0
|
||||||
|
= .alias table 1024
|
||||||
|
|
||||||
|
| assign byte screen $0400
|
||||||
|
| routine main {
|
||||||
|
| lda screen
|
||||||
|
| cmp screen
|
||||||
|
| if beq {
|
||||||
|
| tax
|
||||||
|
| } else {
|
||||||
|
| tay
|
||||||
|
| }
|
||||||
|
| sta screen
|
||||||
|
| }
|
||||||
|
= main:
|
||||||
|
= lda screen
|
||||||
|
= cmp screen
|
||||||
|
= BEQ _label_1
|
||||||
|
= tay
|
||||||
|
= jmp _past_1
|
||||||
|
= _label_1:
|
||||||
|
= tax
|
||||||
|
= _past_1:
|
||||||
|
= sta screen
|
||||||
|
= rts
|
||||||
|
=
|
||||||
|
= .alias screen 1024
|
||||||
|
|
||||||
|
| assign byte screen 1024
|
||||||
|
| reserve byte zero
|
||||||
|
| routine main {
|
||||||
|
| ldy zero
|
||||||
|
| repeat bne {
|
||||||
|
| inc screen
|
||||||
|
| dey
|
||||||
|
| cpy zero
|
||||||
|
| }
|
||||||
|
| sty screen
|
||||||
|
| }
|
||||||
|
= main:
|
||||||
|
= ldy zero
|
||||||
|
=
|
||||||
|
= _repeat_1:
|
||||||
|
= inc screen
|
||||||
|
= dey
|
||||||
|
= cpy zero
|
||||||
|
= BNE _repeat_1
|
||||||
|
= sty screen
|
||||||
|
= rts
|
||||||
|
=
|
||||||
|
= .alias screen 1024
|
||||||
|
= zero: .byte 0
|
||||||
|
|
||||||
|
Nested ifs.
|
||||||
|
|
||||||
|
| routine main {
|
||||||
|
| if beq {
|
||||||
|
| if bcc {
|
||||||
|
| lda #0
|
||||||
|
| } else {
|
||||||
|
| if bvs {
|
||||||
|
| lda #1
|
||||||
|
| } else {
|
||||||
|
| lda #2
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
| } else {
|
||||||
|
| lda #3
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
= main:
|
||||||
|
= BEQ _label_3
|
||||||
|
= lda #3
|
||||||
|
= jmp _past_3
|
||||||
|
= _label_3:
|
||||||
|
= BCC _label_2
|
||||||
|
= BVS _label_1
|
||||||
|
= lda #2
|
||||||
|
= jmp _past_1
|
||||||
|
= _label_1:
|
||||||
|
= lda #1
|
||||||
|
= _past_1:
|
||||||
|
= jmp _past_2
|
||||||
|
= _label_2:
|
||||||
|
= lda #0
|
||||||
|
= _past_2:
|
||||||
|
= _past_3:
|
||||||
|
= rts
|
||||||
|
|
||||||
|
Installing an interrupt handler (at the Kernal level, i.e. with CINV)
|
||||||
|
|
||||||
|
| assign byte screen 1024
|
||||||
|
| assign vector cinv 788
|
||||||
|
| reserve vector save_cinv
|
||||||
|
|
|
||||||
|
| routine main {
|
||||||
|
| sei {
|
||||||
|
| copy vector cinv to save_cinv
|
||||||
|
| copy routine our_cinv to cinv
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| routine our_cinv {
|
||||||
|
| inc screen
|
||||||
|
| jmp save_cinv
|
||||||
|
| }
|
||||||
|
= main:
|
||||||
|
= sei
|
||||||
|
= lda cinv
|
||||||
|
= sta save_cinv
|
||||||
|
= lda cinv+1
|
||||||
|
= sta save_cinv+1
|
||||||
|
= lda #<our_cinv
|
||||||
|
= sta cinv
|
||||||
|
= lda #>our_cinv
|
||||||
|
= sta cinv+1
|
||||||
|
= cli
|
||||||
|
= rts
|
||||||
|
=
|
||||||
|
= our_cinv:
|
||||||
|
= inc screen
|
||||||
|
= jmp (save_cinv)
|
||||||
|
= rts
|
||||||
|
=
|
||||||
|
= .alias screen 1024
|
||||||
|
= .alias cinv 788
|
||||||
|
= save_cinv: .word 0
|
@@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
./build.sh || exit 1
|
||||||
bin/sixtypical emit $1 > tmp.oph || exit 1
|
bin/sixtypical emit $1 > tmp.oph || exit 1
|
||||||
cat lib/basic_header.oph tmp.oph > tmp2.oph || exit 1
|
cat lib/basic_header.oph tmp.oph > tmp2.oph || exit 1
|
||||||
ophis tmp2.oph -o tmp.prg || exit 1
|
ophis tmp2.oph -o tmp.prg || exit 1
|
||||||
|
Reference in New Issue
Block a user