mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-09 16:31:42 +00:00
if statement takes any kind of branch. instruction support table
This commit is contained in:
parent
b458569edb
commit
6132b05b27
150
README.markdown
150
README.markdown
@ -74,9 +74,9 @@ Each routine is a block. It may be composed of inner blocks, attached to
|
||||
some instructions.
|
||||
|
||||
SixtyPical does not have instructions that map literally to the 6502 branch
|
||||
instructions. Instead, each branch instruction has a corresponding
|
||||
"if-then-else"-like construct with the same name as the branch instruction.
|
||||
These _test_ instructions each have two blocks, for the then and the else.
|
||||
instructions. Instead, it has an `if` construct, with two blocks (for the
|
||||
"then" and `else` parts), and the branch instructions map to conditions for
|
||||
this construct.
|
||||
|
||||
The abstract states of the machine at each of the different block exits are
|
||||
merged during analysis. If any register or memory location is treated
|
||||
@ -85,7 +85,9 @@ that register cannot subsequently be used without a declaration to the effect
|
||||
that we know what's going on. (This is all a bit fuzzy right now.)
|
||||
|
||||
There is also no `rts` instruction. It is included at the end of a routine,
|
||||
but only when the routine is used as a subroutine.
|
||||
but only when the routine is used as a subroutine. Also, if the routine
|
||||
ends by `jsr`ing another routine, it reserves the right to do a tail-call
|
||||
or even a fallthrough.
|
||||
|
||||
There are also _with_ instructions, which are associated with an opcode
|
||||
that has a natural symmetrical opcode (e.g. `pha`, `sei`). These instructions
|
||||
@ -120,12 +122,150 @@ This might be
|
||||
|
||||
Note, `screen` must be a `byte table` here.
|
||||
|
||||
Instruction Support so far
|
||||
--------------------------
|
||||
|
||||
A `X` indicates unsupported. A `!` indicates will-not-support.
|
||||
|
||||
Funny syntax indicates use of a special form.
|
||||
|
||||
In these, `absolute` must be a `reserve`d or `locate`d address.
|
||||
|
||||
X adc #immediate
|
||||
X adc absolute
|
||||
|
||||
X and #immediate
|
||||
X and absolute
|
||||
|
||||
X asl
|
||||
X asl absolute
|
||||
|
||||
if bcc { block } else { block }
|
||||
|
||||
if bcs { block } else { block }
|
||||
|
||||
if beq { block } else { block }
|
||||
|
||||
X bit absolute
|
||||
|
||||
if bmi { block } else { block }
|
||||
|
||||
if bne { block } else { block }
|
||||
|
||||
if bpl { block } else { block }
|
||||
|
||||
! brk
|
||||
|
||||
if bvc { block } else { block }
|
||||
|
||||
if bvs { block } else { block }
|
||||
|
||||
X clc
|
||||
|
||||
X cld
|
||||
|
||||
! cli
|
||||
|
||||
X clv
|
||||
|
||||
cmp absolute
|
||||
X cmp #immediate
|
||||
|
||||
X cpx absolute
|
||||
X cpx #immediate
|
||||
|
||||
X cpy absolute
|
||||
X cpy #immediate
|
||||
|
||||
X dec absolute
|
||||
|
||||
X dex
|
||||
|
||||
X dey
|
||||
|
||||
X eor #immediate
|
||||
X eor absolute
|
||||
|
||||
X inc absolute
|
||||
|
||||
X inx
|
||||
|
||||
X iny
|
||||
|
||||
! jmp
|
||||
|
||||
* jsr routine
|
||||
|
||||
lda absolute
|
||||
X lda #immediate
|
||||
|
||||
ldx absolute
|
||||
X ldx #immediate
|
||||
|
||||
ldy absolute
|
||||
X ldy #immediate
|
||||
|
||||
X lsr
|
||||
X lsr absolute
|
||||
|
||||
nop
|
||||
|
||||
X ora #immediate
|
||||
X ora absolute
|
||||
|
||||
X pha { block }
|
||||
|
||||
X php { block }
|
||||
|
||||
! pla -- (although note this does change flags)
|
||||
|
||||
! plp -- (although note this does change flags -- obviously)
|
||||
|
||||
X rol
|
||||
X rol absolute
|
||||
|
||||
X ror
|
||||
X ror absolute
|
||||
|
||||
! rti
|
||||
|
||||
! rts
|
||||
|
||||
X sbc #immediate
|
||||
X sbc absolute
|
||||
|
||||
X sec
|
||||
|
||||
X sed
|
||||
|
||||
X sei { block }
|
||||
|
||||
sta absolute
|
||||
|
||||
stx absolute
|
||||
|
||||
sty absolute
|
||||
|
||||
tax
|
||||
|
||||
tay
|
||||
|
||||
X tsx
|
||||
|
||||
txa
|
||||
|
||||
X txs
|
||||
|
||||
tya
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
* Parse HEX values like $40A3
|
||||
* Fuller machine model
|
||||
* parse support immediate loads, compares
|
||||
* Addressing modes; rename instructions to match
|
||||
* Generate code for BEQ
|
||||
|
||||
Tests
|
||||
-----
|
||||
@ -192,7 +332,7 @@ Even in inner blocks.
|
||||
| routine main {
|
||||
| lda score
|
||||
| cmp screen
|
||||
| beq {
|
||||
| if beq {
|
||||
| lda score
|
||||
| } else {
|
||||
| lda fnord
|
||||
|
@ -6,7 +6,7 @@ reserve byte n_low
|
||||
routine compare_16_bit {
|
||||
lda m_high
|
||||
cmp n_high
|
||||
beq {
|
||||
if beq {
|
||||
lda m_low
|
||||
cmp n_low
|
||||
} else {
|
||||
|
@ -75,7 +75,7 @@ checkInstr (JSR name) progCtx routCtx =
|
||||
checkInstr (CMP reg addr) progCtx routCtx =
|
||||
-- TODO: mark Carry bit as "touched" here
|
||||
routCtx
|
||||
checkInstr (IFEQ b1 b2) progCtx routCtx =
|
||||
checkInstr (IF branch b1 b2) progCtx routCtx =
|
||||
-- TODO: oooh, this one's gonna be fun
|
||||
routCtx
|
||||
checkInstr NOP progCtx routCtx =
|
||||
|
@ -34,7 +34,7 @@ instrUsedLocations (COPY (NamedLocation loc) _) = [loc]
|
||||
instrUsedLocations (COPY _ (NamedLocation loc)) = [loc]
|
||||
instrUsedLocations (CMP reg (NamedLocation loc)) = [loc]
|
||||
-- TODO: JSR...
|
||||
instrUsedLocations (IFEQ b1 b2) =
|
||||
instrUsedLocations (IF branch b1 b2) =
|
||||
blockUsedLocations b1 ++ blockUsedLocations b2
|
||||
instrUsedLocations _ = []
|
||||
|
||||
|
@ -46,11 +46,14 @@ data Decl = Assign LocationName Size Address -- .alias
|
||||
|
||||
type RoutineName = String
|
||||
|
||||
data Branch = BCC | BCS | BEQ | BMI | BNE | BPL | BVC | BVS
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
data Instruction = LOADIMM StorageLocation DataValue
|
||||
| COPY StorageLocation StorageLocation
|
||||
| CMP StorageLocation StorageLocation
|
||||
| JSR RoutineName
|
||||
| IFEQ [Instruction] [Instruction]
|
||||
| IF Branch [Instruction] [Instruction]
|
||||
| NOP
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
|
@ -13,13 +13,14 @@ Decl := "reserve" Size LocationName
|
||||
Size := "byte" | "word".
|
||||
Routine := "routine" RoutineName Block.
|
||||
Block := "{" {Command} "}".
|
||||
Command := "beq" Block "else" Block
|
||||
Command := "if" Branch Block "else" Block
|
||||
| "lda" (LocationName | Immediate)
|
||||
| "ldx" (LocationName | Immediate)
|
||||
| "ldy" (LocationName | Immediate)
|
||||
| "txa" | "tax" | "tya" | "tay"
|
||||
| "cmp" (LocationName | Immediate)
|
||||
| "nop".
|
||||
Branch := "bcc" | "bcs" | "beq" | "bmi" | "bne" | "bpl" | "bvc" | "bvs".
|
||||
|
||||
-}
|
||||
|
||||
@ -76,7 +77,7 @@ command :: Parser Instruction
|
||||
command = cmp <|> (try lda) <|> (try ldx) <|> (try ldy) <|>
|
||||
(try sta) <|> (try stx) <|> (try sty) <|>
|
||||
(try txa) <|> (try tax) <|> (try tya) <|> (try tay) <|>
|
||||
beq <|> nop
|
||||
if_statement <|> nop
|
||||
|
||||
nop :: Parser Instruction
|
||||
nop = do
|
||||
@ -157,15 +158,27 @@ tay = do
|
||||
spaces
|
||||
return (COPY A Y)
|
||||
|
||||
beq :: Parser Instruction
|
||||
beq = do
|
||||
string "beq"
|
||||
if_statement :: Parser Instruction
|
||||
if_statement = do
|
||||
string "if"
|
||||
spaces
|
||||
brch <- branch
|
||||
b1 <- block
|
||||
string "else"
|
||||
spaces
|
||||
b2 <- block
|
||||
return (IFEQ b1 b2)
|
||||
return (IF brch b1 b2)
|
||||
|
||||
branch :: Parser Branch
|
||||
branch = try (b "bcc" BCC) <|> try (b "bcs" BCS) <|> try (b "beq" BEQ) <|>
|
||||
try (b "bmi" BMI) <|> try (b "bne" BNE) <|> try (b "bpl" BPL) <|>
|
||||
try (b "bvc" BVC) <|> (b "bvs" BVS)
|
||||
|
||||
b :: String -> Branch -> Parser Branch
|
||||
b s k = do
|
||||
string s
|
||||
spaces
|
||||
return k
|
||||
|
||||
routineName :: Parser String
|
||||
routineName = do
|
||||
|
Loading…
x
Reference in New Issue
Block a user