Rev 7983 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7983 | leency | 1 | (* |
2 | BSD 2-Clause License |
||
3 | |||
4 | Copyright (c) 2019-2020, Anton Krotov |
||
5 | All rights reserved. |
||
6 | *) |
||
7 | |||
8 | MODULE MSP430; |
||
9 | |||
10 | IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX, |
||
11 | UTILS, C := CONSOLE, PROG, RTL := MSP430RTL; |
||
12 | |||
13 | |||
14 | CONST |
||
15 | |||
16 | minRAM* = 128; maxRAM* = 2048; |
||
17 | minROM* = 2048; maxROM* = 24576; |
||
18 | |||
19 | minStackSize = 64; |
||
20 | |||
21 | IntVectorSize* = RTL.IntVectorSize; |
||
22 | |||
23 | PC = 0; SP = 1; SR = 2; CG = 3; |
||
24 | |||
25 | R4 = 4; R5 = 5; R6 = 6; R7 = 7; |
||
26 | |||
27 | HP = 14; IR = 15; |
||
28 | |||
29 | ACC = R4; |
||
30 | |||
31 | opRRC = 1000H; opSWPB = 1080H; opRRA = 1100H; opSXT = 1180H; |
||
32 | opPUSH = 1200H; opCALL = 1280H; opRETI = 1300H; |
||
33 | |||
34 | opMOV = 04000H; opADD = 05000H; opADDC = 06000H; opSUBC = 07000H; |
||
35 | opSUB = 08000H; opCMP = 09000H; opDADD = 0A000H; opBIT = 0B000H; |
||
36 | opBIC = 0C000H; opBIS = 0D000H; opXOR = 0E000H; opAND = 0F000H; |
||
37 | |||
38 | opJNE = 2000H; opJEQ = 2400H; opJNC = 2800H; opJC = 2C00H; |
||
39 | opJN = 3000H; opJGE = 3400H; opJL = 3800H; opJMP = 3C00H; |
||
40 | |||
41 | sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128; |
||
42 | |||
43 | NOWORD = 10000H; |
||
44 | |||
45 | RCODE = 0; RDATA = 1; RBSS = 2; |
||
46 | |||
47 | je = 0; jne = je + 1; |
||
48 | jge = 2; jl = jge + 1; |
||
49 | jle = 4; jg = jle + 1; |
||
50 | jb = 6; |
||
51 | |||
52 | |||
53 | TYPE |
||
54 | |||
55 | ANYCODE = POINTER TO RECORD (LISTS.ITEM) |
||
56 | |||
57 | offset: INTEGER |
||
58 | |||
59 | END; |
||
60 | |||
61 | WORD = POINTER TO RECORD (ANYCODE) |
||
62 | |||
63 | val: INTEGER |
||
64 | |||
65 | END; |
||
66 | |||
67 | LABEL = POINTER TO RECORD (ANYCODE) |
||
68 | |||
69 | num: INTEGER |
||
70 | |||
71 | END; |
||
72 | |||
73 | JMP = POINTER TO RECORD (ANYCODE) |
||
74 | |||
75 | cc, label: INTEGER; |
||
76 | short: BOOLEAN |
||
77 | |||
78 | END; |
||
79 | |||
80 | CALL = POINTER TO RECORD (ANYCODE) |
||
81 | |||
82 | label: INTEGER |
||
83 | |||
84 | END; |
||
85 | |||
86 | COMMAND = IL.COMMAND; |
||
87 | |||
88 | RELOC = POINTER TO RECORD (LISTS.ITEM) |
||
89 | |||
90 | section: INTEGER; |
||
91 | WordPtr: WORD |
||
92 | |||
93 | END; |
||
94 | |||
95 | |||
96 | VAR |
||
97 | |||
98 | R: REG.REGS; |
||
99 | |||
100 | CodeList: LISTS.LIST; |
||
101 | RelList: LISTS.LIST; |
||
102 | |||
103 | mem: ARRAY 65536 OF BYTE; |
||
104 | |||
105 | Labels: CHL.INTLIST; |
||
106 | |||
107 | IV: ARRAY RTL.LenIV OF INTEGER; |
||
108 | |||
109 | IdxWords: RECORD src, dst: INTEGER END; |
||
110 | |||
111 | StkCnt: INTEGER; |
||
112 | |||
113 | |||
114 | PROCEDURE EmitLabel (L: INTEGER); |
||
115 | VAR |
||
116 | label: LABEL; |
||
117 | |||
118 | BEGIN |
||
119 | NEW(label); |
||
120 | label.num := L; |
||
121 | LISTS.push(CodeList, label) |
||
122 | END EmitLabel; |
||
123 | |||
124 | |||
125 | PROCEDURE EmitWord (val: INTEGER); |
||
126 | VAR |
||
127 | word: WORD; |
||
128 | |||
129 | BEGIN |
||
130 | IF val < 0 THEN |
||
131 | ASSERT(val >= -32768); |
||
132 | val := val MOD 65536 |
||
133 | ELSE |
||
134 | ASSERT(val <= 65535) |
||
135 | END; |
||
136 | NEW(word); |
||
137 | word.val := val; |
||
138 | LISTS.push(CodeList, word) |
||
139 | END EmitWord; |
||
140 | |||
141 | |||
142 | PROCEDURE EmitJmp (cc, label: INTEGER); |
||
143 | VAR |
||
144 | jmp: JMP; |
||
145 | |||
146 | BEGIN |
||
147 | NEW(jmp); |
||
148 | jmp.cc := cc; |
||
149 | jmp.label := label; |
||
150 | jmp.short := FALSE; |
||
151 | LISTS.push(CodeList, jmp) |
||
152 | END EmitJmp; |
||
153 | |||
154 | |||
155 | PROCEDURE EmitCall (label: INTEGER); |
||
156 | VAR |
||
157 | call: CALL; |
||
158 | |||
159 | BEGIN |
||
160 | NEW(call); |
||
161 | call.label := label; |
||
162 | LISTS.push(CodeList, call) |
||
163 | END EmitCall; |
||
164 | |||
165 | |||
166 | PROCEDURE bw (b: BOOLEAN): INTEGER; |
||
167 | RETURN BW * ORD(b) |
||
168 | END bw; |
||
169 | |||
170 | |||
171 | PROCEDURE src_x (x, Rn: INTEGER): INTEGER; |
||
172 | VAR |
||
173 | res: INTEGER; |
||
174 | |||
175 | BEGIN |
||
176 | IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN |
||
177 | res := Rn * 256 + sINDIR |
||
178 | ELSE |
||
179 | IdxWords.src := x; |
||
180 | res := Rn * 256 + sIDX |
||
181 | END |
||
182 | |||
183 | RETURN res |
||
184 | END src_x; |
||
185 | |||
186 | |||
187 | PROCEDURE dst_x (x, Rn: INTEGER): INTEGER; |
||
188 | BEGIN |
||
189 | IdxWords.dst := x |
||
190 | RETURN Rn + dIDX |
||
191 | END dst_x; |
||
192 | |||
193 | |||
194 | PROCEDURE indir (Rn: INTEGER): INTEGER; |
||
195 | RETURN Rn * 256 + sINDIR |
||
196 | END indir; |
||
197 | |||
198 | |||
199 | PROCEDURE incr (Rn: INTEGER): INTEGER; |
||
200 | RETURN Rn * 256 + sINCR |
||
201 | END incr; |
||
202 | |||
203 | |||
204 | PROCEDURE imm (x: INTEGER): INTEGER; |
||
205 | VAR |
||
206 | res: INTEGER; |
||
207 | |||
208 | BEGIN |
||
209 | CASE x OF |
||
210 | | 0: res := CG * 256 |
||
211 | | 1: res := CG * 256 + sIDX |
||
212 | | 2: res := indir(CG) |
||
213 | | 4: res := indir(SR) |
||
214 | | 8: res := incr(SR) |
||
215 | |-1: res := incr(CG) |
||
216 | ELSE |
||
217 | res := incr(PC); |
||
218 | IdxWords.src := x |
||
219 | END |
||
220 | |||
221 | RETURN res |
||
222 | END imm; |
||
223 | |||
224 | |||
225 | PROCEDURE Op2 (op, src, dst: INTEGER); |
||
226 | BEGIN |
||
227 | ASSERT(BITS(op) - {6, 12..15} = {}); |
||
228 | ASSERT(BITS(src) - {4, 5, 8..11} = {}); |
||
229 | ASSERT(BITS(dst) - {0..3, 7} = {}); |
||
230 | |||
231 | EmitWord(op + src + dst); |
||
232 | |||
233 | IF IdxWords.src # NOWORD THEN |
||
234 | EmitWord(IdxWords.src); |
||
235 | IdxWords.src := NOWORD |
||
236 | END; |
||
237 | |||
238 | IF IdxWords.dst # NOWORD THEN |
||
239 | EmitWord(IdxWords.dst); |
||
240 | IdxWords.dst := NOWORD |
||
241 | END |
||
242 | END Op2; |
||
243 | |||
244 | |||
245 | PROCEDURE Op1 (op, reg, As: INTEGER); |
||
246 | BEGIN |
||
247 | EmitWord(op + reg + As) |
||
248 | END Op1; |
||
249 | |||
250 | |||
251 | PROCEDURE MovRR (src, dst: INTEGER); |
||
252 | BEGIN |
||
253 | Op2(opMOV, src * 256, dst) |
||
254 | END MovRR; |
||
255 | |||
256 | |||
257 | PROCEDURE PushImm (imm: INTEGER); |
||
258 | BEGIN |
||
259 | imm := UTILS.Long(imm); |
||
260 | CASE imm OF |
||
261 | | 0: Op1(opPUSH, CG, sREG) |
||
262 | | 1: Op1(opPUSH, CG, sIDX) |
||
263 | | 2: Op1(opPUSH, CG, sINDIR) |
||
264 | |-1: Op1(opPUSH, CG, sINCR) |
||
265 | ELSE |
||
266 | Op1(opPUSH, PC, sINCR); |
||
267 | EmitWord(imm) |
||
268 | END; |
||
269 | INC(StkCnt) |
||
270 | END PushImm; |
||
271 | |||
272 | |||
273 | PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER); |
||
274 | BEGIN |
||
275 | ASSERT(~ODD(adr)); |
||
276 | ASSERT((0 <= word) & (word <= 65535)); |
||
277 | mem[adr] := word MOD 256; |
||
278 | mem[adr + 1] := word DIV 256; |
||
279 | INC(adr, 2) |
||
280 | END PutWord; |
||
281 | |||
282 | |||
283 | PROCEDURE NewLabel (): INTEGER; |
||
284 | BEGIN |
||
285 | CHL.PushInt(Labels, 0) |
||