1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-02-13 11:33:16 +00:00

Re-introducing specialform jmp vector. Inching towards okayness.

This commit is contained in:
Cat's Eye Technologies 2014-04-01 21:06:35 +01:00
parent 9ae3a621b6
commit c441f96921
4 changed files with 80 additions and 10 deletions

View File

@ -7,7 +7,7 @@ with block structure and static analysis through abstract interpretation.
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
for the Commodore 64, VIC-20, Apple ][, etc.
for the Commodore 64 and other 6502-based computers such as the VIC-20.
Many SixtyPical instructions map precisely to 6502 opcodes. However, SixtyPical
is not an assembly language. The programmer does not have total control over
@ -73,18 +73,25 @@ An address knows what kind of data is stored at the address:
* `byte`: an 8-bit byte. not part of a word. not to be used as an address.
(could be an index though.)
* `word`: a 16-bit word. not to be used as an address.
* `vector`: a 16-bit address of a routine. two operations are supported
on vectors: copying the contents of one vector to another, and jumping
to the code at the address contained in the vector (and this can only
happen at the end of a routine.)
* `vector`: a 16-bit address of a routine. Only a handful of operations
are supported on vectors:
* copying the contents of one vector to another
* copying the address of a routine into a vector
* jumping indirectly to a vector (i.e. to the code at the address
contained in the vector (and this can only happen at the end of a
routine)
* `jsr`'ing indirectly to a vector (which is done with a fun
generated trick
* `byte table`: (not yet implemented) a series of `byte`s
contiguous in memory starting from the address.
this is the only kind of address that can be used in indexed addressing.
### Blocks ###
Each routine is a block. It may be composed of inner blocks, attached to
some instructions.
Each routine is a block. It may be composed of inner blocks, if those
inner blocks are attached to certain instructions.
SixtyPical does not have instructions that map literally to the 6502 branch
instructions. Instead, it has an `if` construct, with two blocks (for the
@ -115,7 +122,7 @@ Unsupported Opcodes
-------------------
6502 opcodes with no language-level equivalent instructions in SixtyPical
are `brk`, `cli`, `jmp`, `pla`, `plp`, `rti`, and `rts`. These may be
are `brk`, `cli`, `pla`, `plp`, `rti`, and `rts`. These may be
inserted into the output program as a SixtyPical → 6502 compiler sees fit,
however.
@ -188,6 +195,10 @@ In these, `absolute` must be a `reserve`d or `locate`d address.
iny
* jsr routine
X jsr vector
X jmp routine
* jmp vector
lda #immediate
lda absolute
@ -337,6 +348,22 @@ No duplicate declarations.
| }
? duplicate declaration
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
*| }
*? wtf
-> Tests for functionality "Emit ASM for SixtyPical program"
-> Functionality "Emit ASM for SixtyPical program" is implemented by
@ -515,12 +542,13 @@ Nested ifs.
= _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 patch_cinv {
| routine main {
| sei {
| copy vector cinv to save_cinv
| copy routine our_cinv to cinv

View File

@ -23,6 +23,7 @@ emitDecls p (decl:decls) =
emitDecl p (Assign name _ addr) = ".alias " ++ name ++ " " ++ (show addr)
emitDecl p (Reserve name Byte) = name ++ ": .byte 0"
emitDecl p (Reserve name Word) = name ++ ": .word 0"
emitDecl p (Reserve name Vector) = name ++ ": .word 0"
emitRoutines _ [] = ""
emitRoutines p (rout:routs) =
@ -85,5 +86,21 @@ emitInstr p r (REPEAT iid branch blk) =
emitInstrs p r blk ++
" " ++ (show branch) ++ " _repeat_" ++ (show iid)
emitInstr p r i = error "Internal error: sixtypical doesn't know how to emit assembler code for '" ++ show i ++ "'"
emitInstr p r (SEI blk) =
"sei\n" ++
emitInstrs p r blk ++
"cli"
emitInstr p r (COPYVECTOR (NamedLocation src) (NamedLocation dst)) =
"COPYVECTOR " ++ src ++ " " ++ dst
emitInstr p r (COPYROUTINE src (NamedLocation dst)) =
"COPYROUTINE " ++ src ++ " " ++ dst
emitInstr p r (JMPVECTOR (NamedLocation dst)) =
"jmp (" ++ dst ++ ")"
emitInstr p r i = error (
"Internal error: sixtypical doesn't know how to " ++
"emit assembler code for '" ++ (show i) ++ "'")

View File

@ -57,6 +57,8 @@ data Instruction = LOADIMM StorageLocation DataValue
| CMPIMM StorageLocation DataValue
| CMP StorageLocation StorageLocation
| JSR RoutineName
-- | JSRVECTOR StorageLocation
| JMPVECTOR StorageLocation
| IF InternalID Branch [Instruction] [Instruction]
| REPEAT InternalID Branch [Instruction]
| DELTA StorageLocation DataValue
@ -71,3 +73,17 @@ data Routine = Routine RoutineName [Instruction]
data Program = Program [Decl] [Routine]
deriving (Show, Ord, Eq)
mapBlock :: (Instruction -> Instruction) -> [Instruction] -> [Instruction]
mapBlock = map
mapRoutine :: (Instruction -> Instruction) -> Routine -> Routine
mapRoutine f (Routine name instrs) = Routine name (mapBlock f instrs)
mapRoutines :: (Instruction -> Instruction) -> [Routine] -> [Routine]
mapRoutines f [] = []
mapRoutines f (rout:routs) =
(mapRoutine f rout):(mapRoutines f routs)
mapProgramRoutines :: (Instruction -> Instruction) -> Program -> Program
mapProgramRoutines f (Program decls routs) = Program decls $ mapRoutines f routs

View File

@ -24,6 +24,7 @@ Command := "if" Branch Block "else" Block
| "inx" | "iny" | "dex" | "dey" | "inc" Location | "dec" Location
| "clc" | "cld" | "clv" | "sec" | "sed"
| "sei" Block
| "jmp" LocationName
| "nop".
Branch := "bcc" | "bcs" | "beq" | "bmi" | "bne" | "bpl" | "bvc" | "bvs".
@ -91,6 +92,7 @@ command = (try lda) <|>
(try inc) <|> (try dec) <|>
(try clc) <|> (try cld) <|> (try clv) <|> (try sec) <|> (try sed) <|>
(try sei) <|>
(try jmp) <|>
(try copy_vector_statement) <|>
(try copy_routine_statement) <|>
if_statement <|> repeat_statement <|> nop
@ -274,6 +276,13 @@ sei = do
blk <- block
return (SEI blk)
jmp :: Parser Instruction
jmp = do
string "jmp"
spaces
l <- locationName
return $ JMPVECTOR (NamedLocation l)
if_statement :: Parser Instruction
if_statement = do
string "if"