Subversion Repositories Kolibri OS

Rev

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)