diff --git a/README.markdown b/README.markdown index 9c749a1..9db4331 100644 --- a/README.markdown +++ b/README.markdown @@ -78,6 +78,10 @@ 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. +Similarly, there is a `repeat` construct. The same branch instructions can +be used in the condition to this construct. In this case, they branch back +to the top of the `repeat` loop. + 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 inconsistently (e.g. updated in one branch of the test, but not the other,) @@ -94,34 +98,6 @@ that has a natural symmetrical opcode (e.g. `pha`, `sei`). These instructions take a block. The natural symmetrical opcode is inserted at the end of the block. -### Loops ### - -Still need to figure this out. - -Typical `repeat` loop looks like: - - ldy #0 - _loop: - lda #65 - sta screen, y - iny - cpy #250 - bne _loop - -This might be - - routine blah { - ldy# 0 - repeat bne { - lda# 65 - sta,y screen - iny - cpy# 250 - } - } - -Note, `screen` must be a `byte table` here. - Instruction Support so far -------------------------- @@ -438,3 +414,32 @@ No duplicate declarations. = _past: = sta screen = rts + + | assign byte screen 4000 + | reserve byte zero + | routine main { + | ldy zero + | repeat bne { + | inc screen + | dey + | cpy zero + | } + | sty screen + | } + = .org 0 + = .word $0801 + = .org $0801 + = .byte $10, $08, $c9, $07, $9e, $32, $30, $36, $31, $00, $00, $00 + = jmp main + = .alias screen 4000 + = zero: .byte 0 + = main: + = ldy zero + = + = _repeat: + = inc screen + = dey + = cpy zero + = BNE _repeat + = sty screen + = rts diff --git a/eg/screen.60pical b/eg/screen.60pical new file mode 100644 index 0000000..9448e06 --- /dev/null +++ b/eg/screen.60pical @@ -0,0 +1,11 @@ +assign byte screen 1024 +reserve byte zero +routine main { + ldy zero + repeat bne { + inc screen + dey + cpy zero + } + sty screen +} diff --git a/eg/screen2.60pical b/eg/screen2.60pical new file mode 100644 index 0000000..ff5a3ec --- /dev/null +++ b/eg/screen2.60pical @@ -0,0 +1,7 @@ +assign byte screen 1024 +routine main { + repeat bcc { + inc screen + clc + } +} diff --git a/src/SixtyPical/Emitter.hs b/src/SixtyPical/Emitter.hs index 860428a..aeef3e0 100644 --- a/src/SixtyPical/Emitter.hs +++ b/src/SixtyPical/Emitter.hs @@ -70,5 +70,10 @@ emitInstr p r (IF branch b1 b2) = emitInstrs p r b1 ++ "_past:" +emitInstr p r (REPEAT branch blk) = + "\n_repeat:\n" ++ + emitInstrs p r blk ++ + " " ++ (show branch) ++ " _repeat" + emitInstr p r i = error "Internal error: sixtypical doesn't know how to emit assembler code for '" ++ show i ++ "'" diff --git a/src/SixtyPical/Model.hs b/src/SixtyPical/Model.hs index a531596..412ef1b 100644 --- a/src/SixtyPical/Model.hs +++ b/src/SixtyPical/Model.hs @@ -54,6 +54,7 @@ data Instruction = LOADIMM StorageLocation DataValue | CMP StorageLocation StorageLocation | JSR RoutineName | IF Branch [Instruction] [Instruction] + | REPEAT Branch [Instruction] | DELTA StorageLocation DataValue | NOP deriving (Show, Ord, Eq) diff --git a/src/SixtyPical/Parser.hs b/src/SixtyPical/Parser.hs index 4411a70..f7972f9 100644 --- a/src/SixtyPical/Parser.hs +++ b/src/SixtyPical/Parser.hs @@ -83,7 +83,7 @@ command = (try lda) <|> (try ldx) <|> (try ldy) <|> (try cmp) <|> (try cpx) <|> (try cpy) <|> (try inx) <|> (try iny) <|> (try dex) <|> (try dey) <|> (try inc) <|> (try dec) <|> - if_statement <|> nop + if_statement <|> repeat_statement <|> nop nop :: Parser Instruction nop = do @@ -227,6 +227,14 @@ if_statement = do b2 <- block return (IF brch b1 b2) +repeat_statement :: Parser Instruction +repeat_statement = do + string "repeat" + spaces + brch <- branch + blk <- block + return (REPEAT brch blk) + 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) <|>