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:
parent
9ae3a621b6
commit
c441f96921
@ -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
|
||||
|
@ -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) ++ "'")
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user