Machine model is a bit fuller now.
Cat's Eye Technologies
11 years ago
91 | 91 | take a block. The natural symmetrical opcode is inserted at the end of the |
92 | 92 | block. |
93 | 93 | |
94 | ### Loops ### | |
95 | ||
96 | Still need to figure this out. | |
97 | ||
98 | Typical `repeat` loop looks like: | |
99 | ||
100 | ldy #0 | |
101 | _loop: | |
102 | lda #65 | |
103 | sta screen, y | |
104 | iny | |
105 | cpy #250 | |
106 | bne _loop | |
107 | ||
108 | This might be | |
109 | ||
110 | routine blah { | |
111 | ldy# 0 | |
112 | repeat bne { | |
113 | lda# 65 | |
114 | sta,y screen | |
115 | iny | |
116 | cpy# 250 | |
117 | } | |
118 | } | |
119 | ||
120 | Note, `screen` must be a `byte table` here. | |
121 | ||
94 | 122 | TODO |
95 | 123 | ---- |
96 | 124 | |
97 | 125 | * Parse HEX values like $40A3 |
98 | * Full machine model | |
126 | * Fuller machine model | |
99 | 127 | * Addressing modes; rename instructions to match |
100 | 128 | |
101 | 129 | Tests |
8 | 8 | -- -- -- -- data-flow-analysis context -- -- -- -- |
9 | 9 | |
10 | 10 | data Usage = Unknown |
11 | | Value LocationName -- obviously a bit daft for now | |
12 | | Retained Register | |
11 | | Value StorageLocation -- obviously a bit daft for now | |
12 | | Retained StorageLocation | |
13 | 13 | deriving (Show, Ord, Eq) |
14 | 14 | |
15 | type RoutineContext = Map.Map Register Usage | |
15 | type RoutineContext = Map.Map StorageLocation Usage | |
16 | 16 | |
17 | 17 | type ProgramContext = Map.Map RoutineName RoutineContext |
18 | 18 |
20 | 20 | elem locName (map (getDeclLocationName) decls) |
21 | 21 | where |
22 | 22 | |
23 | -- in the following, we mean Named locations | |
24 | ||
23 | 25 | routineUsedLocations (Routine _ instrs) = blockUsedLocations instrs |
24 | 26 | |
25 | 27 | blockUsedLocations [] = [] |
26 | 28 | blockUsedLocations (instr:instrs) = |
27 | 29 | (instrUsedLocations instr) ++ blockUsedLocations instrs |
28 | 30 | |
29 | instrUsedLocations (LOAD reg loc) = [loc] | |
30 | instrUsedLocations (CMP reg loc) = [loc] | |
31 | instrUsedLocations (LOAD reg (NamedLocation loc)) = [loc] | |
32 | instrUsedLocations (CMP reg (NamedLocation loc)) = [loc] | |
31 | 33 | -- TODO: JSR... |
32 | 34 | instrUsedLocations (IFEQ b1 b2) = |
33 | 35 | blockUsedLocations b1 ++ blockUsedLocations b2 |
34 | 34 | emitInstrs p r (instr:instrs) = |
35 | 35 | " " ++ emitInstr p r instr ++ "\n" ++ emitInstrs p r instrs |
36 | 36 | |
37 | emitInstr p r (LOAD A label) = "lda " ++ label | |
38 | emitInstr p r (LOAD X label) = "ldx " ++ label | |
39 | emitInstr p r (LOAD Y label) = "ldy " ++ label | |
40 | emitInstr p r (CMP A label) = "cmp " ++ label | |
37 | emitInstr p r (LOAD A (NamedLocation label)) = "lda " ++ label | |
38 | emitInstr p r (LOAD X (NamedLocation label)) = "ldx " ++ label | |
39 | emitInstr p r (LOAD Y (NamedLocation label)) = "ldy " ++ label | |
40 | emitInstr p r (CMP A (NamedLocation label)) = "cmp " ++ label | |
41 | 41 | |
42 | 42 | emitInstr p r (COPY A X) = "tax" |
43 | 43 | emitInstr p r (COPY A Y) = "tay" |
7 | 7 | |
8 | 8 | type LocationName = String |
9 | 9 | |
10 | data Register = A | X | Y -- | MemLoc LocationName | |
10 | -- We do not include the PC as it of course changes constantly. | |
11 | -- We do not include the stack pointer, as it should not change over | |
12 | -- the lifetime of a single routine. (Always pop what you pushed.) | |
13 | -- Ditto the I flag. (always enable interrupts after disabling them.) | |
14 | -- We do not include the B flag, because for us, BRK is game over, man. | |
15 | ||
16 | -- One of these should never refer to the program code. We can only police | |
17 | -- this up to a point. | |
18 | ||
19 | data StorageLocation = A | |
20 | | Y | |
21 | | X | |
22 | | FlagN | |
23 | | FlagV | |
24 | | FlagD | |
25 | | FlagZ | |
26 | | FlagC | |
27 | | NamedLocation LocationName | |
11 | 28 | deriving (Show, Ord, Eq) |
12 | 29 | |
13 | allRegisters = [A, X, Y] | |
30 | -- this is bunk, man. if a location does not appear in an analysis | |
31 | -- map the meaning should be taken to be "preserved". | |
32 | ||
33 | allRegisters = [A, X, Y, FlagN, FlagV, FlagD, FlagZ, FlagC] | |
14 | 34 | |
15 | 35 | -- -- -- -- program model -- -- -- -- |
16 | 36 | |
24 | 44 | |
25 | 45 | type RoutineName = String |
26 | 46 | |
27 | data Instruction = LOAD Register LocationName | |
28 | | COPY Register Register | |
29 | | CMP Register LocationName | |
47 | data Instruction = LOAD StorageLocation StorageLocation | |
48 | | COPY StorageLocation StorageLocation | |
49 | | CMP StorageLocation StorageLocation | |
30 | 50 | | JSR RoutineName |
31 | 51 | | IFEQ [Instruction] [Instruction] |
32 | 52 | | NOP |
87 | 87 | string "cmp" |
88 | 88 | spaces |
89 | 89 | l <- locationName |
90 | return (CMP A l) | |
90 | return (CMP A (NamedLocation l)) | |
91 | 91 | |
92 | 92 | lda :: Parser Instruction |
93 | 93 | lda = do |
94 | 94 | string "lda" |
95 | 95 | spaces |
96 | 96 | l <- locationName |
97 | return (LOAD A l) | |
97 | return (LOAD A (NamedLocation l)) | |
98 | 98 | |
99 | 99 | ldx :: Parser Instruction |
100 | 100 | ldx = do |
101 | 101 | string "ldx" |
102 | 102 | spaces |
103 | 103 | l <- locationName |
104 | return (LOAD X l) | |
104 | return (LOAD X (NamedLocation l)) | |
105 | 105 | |
106 | 106 | ldy :: Parser Instruction |
107 | 107 | ldy = do |
108 | 108 | string "ldy" |
109 | 109 | spaces |
110 | 110 | l <- locationName |
111 | return (LOAD Y l) | |
111 | return (LOAD Y (NamedLocation l)) | |
112 | 112 | |
113 | 113 | txa :: Parser Instruction |
114 | 114 | txa = do |