Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1126 | savelij | 1 | /* code3201x.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS-Portierung */ |
||
6 | /* */ |
||
7 | /* Codegenerator TMS3201x-Familie */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "stdinc.h" |
||
12 | #include <string.h> |
||
13 | #include <ctype.h> |
||
14 | |||
15 | #include "bpemu.h" |
||
16 | #include "strutil.h" |
||
17 | #include "chunks.h" |
||
18 | #include "asmdef.h" |
||
19 | #include "asmsub.h" |
||
20 | #include "asmpars.h" |
||
21 | #include "asmitree.h" |
||
22 | #include "codepseudo.h" |
||
23 | #include "fourpseudo.h" |
||
24 | #include "codevars.h" |
||
25 | #include "errmsg.h" |
||
26 | |||
27 | #include "code3201x.h" |
||
28 | |||
29 | typedef struct |
||
30 | { |
||
31 | Word Code; |
||
32 | Word AllowShifts; |
||
33 | } AdrShiftOrder; |
||
34 | |||
35 | typedef struct |
||
36 | { |
||
37 | Word Code; |
||
38 | Integer Min, Max; |
||
39 | Word Mask; |
||
40 | } ImmOrder; |
||
41 | |||
42 | |||
43 | static Word AdrMode; |
||
44 | static Boolean AdrOK; |
||
45 | |||
46 | static CPUVar CPU32010, CPU32015; |
||
47 | |||
48 | static AdrShiftOrder *AdrShiftOrders; |
||
49 | static ImmOrder *ImmOrders; |
||
50 | |||
51 | /*----------------------------------------------------------------------------*/ |
||
52 | |||
53 | static Word EvalARExpression(const tStrComp *pArg, Boolean *OK) |
||
54 | { |
||
55 | *OK = True; |
||
56 | if (!as_strcasecmp(pArg->str.p_str, "AR0")) |
||
57 | return 0; |
||
58 | if (!as_strcasecmp(pArg->str.p_str, "AR1")) |
||
59 | return 1; |
||
60 | return EvalStrIntExpression(pArg, UInt1, OK); |
||
61 | } |
||
62 | |||
63 | static void DecodeAdr(const tStrComp *pArg, int Aux, Boolean Must1) |
||
64 | { |
||
65 | Byte h; |
||
66 | char *p; |
||
67 | char *Arg = pArg->str.p_str; |
||
68 | |||
69 | AdrOK = False; |
||
70 | |||
71 | if ((!strcmp(pArg->str.p_str, "*")) || (!strcmp(pArg->str.p_str, "*-")) || (!strcmp(pArg->str.p_str, "*+"))) |
||
72 | { |
||
73 | AdrMode = 0x88; |
||
74 | if (strlen(Arg) == 2) |
||
75 | AdrMode += (pArg->str.p_str[1] == '+') ? 0x20 : 0x10; |
||
76 | if (Aux <= ArgCnt) |
||
77 | { |
||
78 | h = EvalARExpression(&ArgStr[Aux], &AdrOK); |
||
79 | if (AdrOK) |
||
80 | { |
||
81 | AdrMode &= 0xf7; |
||
82 | AdrMode += h; |
||
83 | } |
||
84 | } |
||
85 | else |
||
86 | AdrOK = True; |
||
87 | } |
||
88 | else if (ChkArgCnt(1, Aux - 1)) |
||
89 | { |
||
90 | tEvalResult EvalResult; |
||
91 | |||
92 | h = 0; |
||
93 | if ((strlen(pArg->str.p_str) > 3) && (!as_strncasecmp(pArg->str.p_str, "DAT", 3))) |
||
94 | { |
||
95 | AdrOK = True; |
||
96 | for (p = pArg->str.p_str + 3; *p != '\0'; p++) |
||
97 | if ((*p > '9') || (*p < '0')) |
||
98 | AdrOK = False; |
||
99 | if (AdrOK) |
||
100 | { |
||
101 | h = EvalStrIntExpressionOffsWithResult(pArg, 3, UInt8, &EvalResult); |
||
102 | AdrOK = EvalResult.OK; |
||
103 | } |
||
104 | } |
||
105 | if (!AdrOK) |
||
106 | { |
||
107 | h = EvalStrIntExpressionWithResult(pArg, Int8, &EvalResult); |
||
108 | AdrOK = EvalResult.OK; |
||
109 | } |
||
110 | if (AdrOK) |
||
111 | { |
||
112 | if (Must1 && (h < 0x80) && !mFirstPassUnknown(EvalResult.Flags)) |
||
113 | { |
||
114 | WrError(ErrNum_UnderRange); |
||
115 | AdrOK = False; |
||
116 | } |
||
117 | else |
||
118 | { |
||
119 | AdrMode = h & 0x7f; |
||
120 | ChkSpace(SegData, EvalResult.AddrSpaceMask); |
||
121 | } |
||
122 | } |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /*----------------------------------------------------------------------------*/ |
||
127 | |||
128 | /* kein Argument */ |
||
129 | |||
130 | static void DecodeFixed(Word Code) |
||
131 | { |
||
132 | if (ChkArgCnt(0, 0)) |
||
133 | { |
||
134 | CodeLen = 1; |
||
135 | WAsmCode[0] = Code; |
||
136 | } |
||
137 | } |
||
138 | |||
139 | /* Spruenge */ |
||
140 | |||
141 | static void DecodeJmp(Word Code) |
||
142 | { |
||
143 | if (ChkArgCnt(1, 1)) |
||
144 | { |
||
145 | Boolean OK; |
||
146 | |||
147 | WAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt12, &OK); |
||
148 | if (OK) |
||
149 | { |
||
150 | CodeLen = 2; |
||
151 | WAsmCode[0] = Code; |
||
152 | } |
||
153 | } |
||
154 | } |
||
155 | |||
156 | /* nur Adresse */ |
||
157 | |||
158 | static void DecodeAdrInst(Word Code) |
||
159 | { |
||
160 | if (ChkArgCnt(1, 2)) |
||
161 | { |
||
162 | DecodeAdr(&ArgStr[1], 2, Code & 1); |
||
163 | if (AdrOK) |
||
164 | { |
||
165 | CodeLen = 1; |
||
166 | WAsmCode[0] = (Code & 0xfffe) + AdrMode; |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | |||
171 | /* Adresse & schieben */ |
||
172 | |||
173 | static void DecodeAdrShift(Word Index) |
||
174 | { |
||
175 | Boolean HasSh; |
||
176 | int AuxArgIndex; |
||
177 | const AdrShiftOrder *pOrder = AdrShiftOrders + Index; |
||
178 | |||
179 | if (ChkArgCnt(1, 3)) |
||
180 | { |
||
181 | if (*ArgStr[1].str.p_str == '*') |
||
182 | { |
||
183 | switch (ArgCnt) |
||
184 | { |
||
185 | case 1: |
||
186 | HasSh = False; |
||
187 | AuxArgIndex = 3; |
||
188 | break; |
||
189 | case 2: |
||
190 | if (!as_strncasecmp(ArgStr[2].str.p_str, "AR", 2)) |
||
191 | { |
||
192 | HasSh = False; |
||
193 | AuxArgIndex = 2; |
||
194 | } |
||
195 | else |
||
196 | { |
||
197 | HasSh = True; |
||
198 | AuxArgIndex = 3; |
||
199 | } |
||
200 | break; |
||
201 | default: /* 3 */ |
||
202 | HasSh = True; |
||
203 | AuxArgIndex = 3; |
||
204 | } |
||
205 | } |
||
206 | else |
||
207 | { |
||
208 | AuxArgIndex = 3; |
||
209 | HasSh = (ArgCnt == 2); |
||
210 | } |
||
211 | DecodeAdr(&ArgStr[1], AuxArgIndex, False); |
||
212 | if (AdrOK) |
||
213 | { |
||
214 | Boolean OK; |
||
215 | Word AdrWord; |
||
216 | |||
217 | if (!HasSh) |
||
218 | { |
||
219 | OK = True; |
||
220 | AdrWord = 0; |
||
221 | } |
||
222 | else |
||
223 | { |
||
224 | tSymbolFlags Flags; |
||
225 | |||
226 | AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], Int4, &OK, &Flags); |
||
227 | if (OK && mFirstPassUnknown(Flags)) |
||
228 | AdrWord = 0; |
||
229 | } |
||
230 | if (OK) |
||
231 | { |
||
232 | if ((pOrder->AllowShifts & (1 << AdrWord)) == 0) WrError(ErrNum_InvShiftArg); |
||
233 | else |
||
234 | { |
||
235 | CodeLen = 1; |
||
236 | WAsmCode[0] = pOrder->Code + AdrMode + (AdrWord << 8); |
||
237 | } |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | /* Ein/Ausgabe */ |
||
244 | |||
245 | static void DecodeIN_OUT(Word Code) |
||
246 | { |
||
247 | if (ChkArgCnt(2, 3)) |
||
248 | { |
||
249 | DecodeAdr(&ArgStr[1], 3, False); |
||
250 | if (AdrOK) |
||
251 | { |
||
252 | tEvalResult EvalResult; |
||
253 | Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[2], UInt3, &EvalResult); |
||
254 | if (EvalResult.OK) |
||
255 | { |
||
256 | ChkSpace(SegIO, EvalResult.AddrSpaceMask); |
||
257 | CodeLen = 1; |
||
258 | WAsmCode[0] = Code + AdrMode + (AdrWord << 8); |
||
259 | } |
||
260 | } |
||
261 | } |
||
262 | } |
||
263 | |||
264 | /* konstantes Argument */ |
||
265 | |||
266 | static void DecodeImm(Word Index) |
||
267 | { |
||
268 | const ImmOrder *pOrder = ImmOrders + Index; |
||
269 | |||
270 | if (ChkArgCnt(1, 1)) |
||
271 | { |
||
272 | Boolean OK; |
||
273 | tSymbolFlags Flags; |
||
274 | LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags); |
||
275 | |||
276 | if (OK) |
||
277 | { |
||
278 | if (mFirstPassUnknown(Flags)) |
||
279 | AdrLong &= pOrder->Mask; |
||
280 | if (AdrLong < pOrder->Min) WrError(ErrNum_UnderRange); |
||
281 | else if (AdrLong > pOrder->Max) WrError(ErrNum_OverRange); |
||
282 | else |
||
283 | { |
||
284 | CodeLen = 1; |
||
285 | WAsmCode[0] = pOrder->Code + (AdrLong & pOrder->Mask); |
||
286 | } |
||
287 | } |
||
288 | } |
||
289 | } |
||
290 | |||
291 | /* mit Hilfsregistern */ |
||
292 | |||
293 | static void DecodeLARP(Word Code) |
||
294 | { |
||
295 | UNUSED(Code); |
||
296 | |||
297 | if (ChkArgCnt(1, 1)) |
||
298 | { |
||
299 | Boolean OK; |
||
300 | Word AdrWord = EvalARExpression(&ArgStr[1], &OK); |
||
301 | if (OK) |
||
302 | { |
||
303 | CodeLen = 1; |
||
304 | WAsmCode[0] = 0x6880 + AdrWord; |
||
305 | } |
||
306 | } |
||
307 | } |
||
308 | |||
309 | static void DecodeLAR_SAR(Word Code) |
||
310 | { |
||
311 | if (ChkArgCnt(2, 3)) |
||
312 | { |
||
313 | Boolean OK; |
||
314 | Word AdrWord = EvalARExpression(&ArgStr[1], &OK); |
||
315 | if (OK) |
||
316 | { |
||
317 | DecodeAdr(&ArgStr[2], 3, False); |
||
318 | if (AdrOK) |
||
319 | { |
||
320 | CodeLen = 1; |
||
321 | WAsmCode[0] = Code + AdrMode + (AdrWord << 8); |
||
322 | } |
||
323 | } |
||
324 | } |
||
325 | } |
||
326 | |||
327 | static void DecodeLARK(Word Code) |
||
328 | { |
||
329 | UNUSED(Code); |
||
330 | |||
331 | if (ChkArgCnt(2, 2)) |
||
332 | { |
||
333 | Boolean OK; |
||
334 | Word AdrWord = EvalARExpression(&ArgStr[1], &OK); |
||
335 | if (OK) |
||
336 | { |
||
337 | WAsmCode[0] = EvalStrIntExpression(&ArgStr[2], Int8, &OK); |
||
338 | if (OK) |
||
339 | { |
||
340 | CodeLen = 1; |
||
341 | WAsmCode[0] = Lo(WAsmCode[0]) + 0x7000 + (AdrWord << 8); |
||
342 | } |
||
343 | } |
||
344 | } |
||
345 | } |
||
346 | |||
347 | static void DecodePORT(Word Code) |
||
348 | { |
||
349 | UNUSED(Code); |
||
350 | |||
351 | CodeEquate(SegIO, 0, 7); |
||
352 | } |
||
353 | |||
354 | static void DecodeDATA_3201x(Word Code) |
||
355 | { |
||
356 | UNUSED(Code); |
||
357 | |||
358 | DecodeDATA(Int16, Int16); |
||
359 | } |
||
360 | |||
361 | /*----------------------------------------------------------------------------*/ |
||
362 | |||
363 | static void AddFixed(const char *NName, Word NCode) |
||
364 | { |
||
365 | AddInstTable(InstTable, NName, NCode, DecodeFixed); |
||
366 | } |
||
367 | |||
368 | static void AddJmp(const char *NName, Word NCode) |
||
369 | { |
||
370 | AddInstTable(InstTable, NName, NCode, DecodeJmp); |
||
371 | } |
||
372 | |||
373 | static void AddAdr(const char *NName, Word NCode, Word NMust1) |
||
374 | { |
||
375 | AddInstTable(InstTable, NName, NCode | NMust1, DecodeAdrInst); |
||
376 | } |
||
377 | |||
378 | static void AddAdrShift(const char *NName, Word NCode, Word NAllow) |
||
379 | { |
||
380 | order_array_rsv_end(AdrShiftOrders, AdrShiftOrder); |
||
381 | AdrShiftOrders[InstrZ].Code = NCode; |
||
382 | AdrShiftOrders[InstrZ].AllowShifts = NAllow; |
||
383 | AddInstTable(InstTable, NName, InstrZ++, DecodeAdrShift); |
||
384 | } |
||
385 | |||
386 | static void AddImm(const char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask) |
||
387 | { |
||
388 | order_array_rsv_end(ImmOrders, ImmOrder); |
||
389 | ImmOrders[InstrZ].Code = NCode; |
||
390 | ImmOrders[InstrZ].Min = NMin; |
||
391 | ImmOrders[InstrZ].Max = NMax; |
||
392 | ImmOrders[InstrZ].Mask = NMask; |
||
393 | AddInstTable(InstTable, NName, InstrZ++, DecodeImm); |
||
394 | } |
||
395 | |||
396 | static void InitFields(void) |
||
397 | { |
||
398 | InstTable = CreateInstTable(203); |
||
399 | AddInstTable(InstTable, "IN", 0x4000, DecodeIN_OUT); |
||
400 | AddInstTable(InstTable, "OUT", 0x4800, DecodeIN_OUT); |
||
401 | AddInstTable(InstTable, "LARP", 0, DecodeLARP); |
||
402 | AddInstTable(InstTable, "LAR", 0x3800, DecodeLAR_SAR); |
||
403 | AddInstTable(InstTable, "SAR", 0x3000, DecodeLAR_SAR); |
||
404 | AddInstTable(InstTable, "LARK", 0, DecodeLARK); |
||
405 | AddInstTable(InstTable, "PORT", 0, DecodePORT); |
||
406 | AddInstTable(InstTable, "RES", 0, DecodeRES); |
||
407 | AddInstTable(InstTable, "DATA", 0, DecodeDATA_3201x); |
||
408 | |||
409 | AddFixed("ABS" , 0x7f88); AddFixed("APAC" , 0x7f8f); |
||
410 | AddFixed("CALA" , 0x7f8c); AddFixed("DINT" , 0x7f81); |
||
411 | AddFixed("EINT" , 0x7f82); AddFixed("NOP" , 0x7f80); |
||
412 | AddFixed("PAC" , 0x7f8e); AddFixed("POP" , 0x7f9d); |
||
413 | AddFixed("PUSH" , 0x7f9c); AddFixed("RET" , 0x7f8d); |
||
414 | AddFixed("ROVM" , 0x7f8a); AddFixed("SOVM" , 0x7f8b); |
||
415 | AddFixed("SPAC" , 0x7f90); AddFixed("ZAC" , 0x7f89); |
||
416 | |||
417 | AddJmp("B" , 0xf900); AddJmp("BANZ" , 0xf400); |
||
418 | AddJmp("BGEZ" , 0xfd00); AddJmp("BGZ" , 0xfc00); |
||
419 | AddJmp("BIOZ" , 0xf600); AddJmp("BLEZ" , 0xfb00); |
||
420 | AddJmp("BLZ" , 0xfa00); AddJmp("BNZ" , 0xfe00); |
||
421 | AddJmp("BV" , 0xf500); AddJmp("BZ" , 0xff00); |
||
422 | AddJmp("CALL" , 0xf800); |
||
423 | |||
424 | AddAdr("ADDH" , 0x6000, False); AddAdr("ADDS" , 0x6100, False); |
||
425 | AddAdr("AND" , 0x7900, False); AddAdr("DMOV" , 0x6900, False); |
||
426 | AddAdr("LDP" , 0x6f00, False); AddAdr("LST" , 0x7b00, False); |
||
427 | AddAdr("LT" , 0x6a00, False); AddAdr("LTA" , 0x6c00, False); |
||
428 | AddAdr("LTD" , 0x6b00, False); AddAdr("MAR" , 0x6800, False); |
||
429 | AddAdr("MPY" , 0x6d00, False); AddAdr("OR" , 0x7a00, False); |
||
430 | AddAdr("SST" , 0x7c00, True ); AddAdr("SUBC" , 0x6400, False); |
||
431 | AddAdr("SUBH" , 0x6200, False); AddAdr("SUBS" , 0x6300, False); |
||
432 | AddAdr("TBLR" , 0x6700, False); AddAdr("TBLW" , 0x7d00, False); |
||
433 | AddAdr("XOR" , 0x7800, False); AddAdr("ZALH" , 0x6500, False); |
||
434 | AddAdr("ZALS" , 0x6600, False); |
||
435 | |||
436 | InstrZ = 0; |
||
437 | AddAdrShift("ADD" , 0x0000, 0xffff); |
||
438 | AddAdrShift("LAC" , 0x2000, 0xffff); |
||
439 | AddAdrShift("SACH" , 0x5800, 0x0013); |
||
440 | AddAdrShift("SACL" , 0x5000, 0x0001); |
||
441 | AddAdrShift("SUB" , 0x1000, 0xffff); |
||
442 | |||
443 | InstrZ = 0; |
||
444 | AddImm("LACK", 0x7e00, 0, 255, 0xff); |
||
445 | AddImm("LDPK", 0x6e00, 0, 1, 0x1); |
||
446 | AddImm("MPYK", 0x8000, -4096, 4095, 0x1fff); |
||
447 | } |
||
448 | |||
449 | static void DeinitFields(void) |
||
450 | { |
||
451 | DestroyInstTable(InstTable); |
||
452 | |||
453 | order_array_free(AdrShiftOrders); |
||
454 | order_array_free(ImmOrders); |
||
455 | } |
||
456 | |||
457 | /*----------------------------------------------------------------------------*/ |
||
458 | |||
459 | /*!------------------------------------------------------------------------ |
||
460 | * \fn InternSymbol_3201X(char *pArg, TempResult *pResult) |
||
461 | * \brief parse for built-in symbols |
||
462 | * \param pArg source argument |
||
463 | * \param pResult possible result |
||
464 | * ------------------------------------------------------------------------ */ |
||
465 | |||
466 | static void InternSymbol_3201X(char *pArg, TempResult *pResult) |
||
467 | { |
||
468 | if ((strlen(pArg) == 3) |
||
469 | && (as_toupper(pArg[0]) == 'P') |
||
470 | && (as_toupper(pArg[1]) == 'A') |
||
471 | && ((pArg[2] >= '0') && (pArg[2] <= '7'))) |
||
472 | { |
||
473 | as_tempres_set_int(pResult, pArg[2] - '0'); |
||
474 | pResult->AddrSpaceMask |= 1 << SegIO; |
||
475 | } |
||
476 | } |
||
477 | |||
478 | static void MakeCode_3201X(void) |
||
479 | { |
||
480 | CodeLen = 0; |
||
481 | DontPrint = False; |
||
482 | |||
483 | /* zu ignorierendes */ |
||
484 | |||
485 | if (Memo("")) |
||
486 | return; |
||
487 | |||
488 | if (!LookupInstTable(InstTable, OpPart.str.p_str)) |
||
489 | WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart); |
||
490 | } |
||
491 | |||
492 | static Boolean IsDef_3201X(void) |
||
493 | { |
||
494 | return (Memo("PORT")); |
||
495 | } |
||
496 | |||
497 | static void SwitchFrom_3201X(void) |
||
498 | { |
||
499 | DeinitFields(); |
||
500 | } |
||
501 | |||
502 | static void SwitchTo_3201X(void) |
||
503 | { |
||
504 | TurnWords = False; |
||
505 | SetIntConstMode(eIntConstModeIntel); |
||
506 | |||
507 | PCSymbol = "$"; |
||
508 | HeaderID = 0x74; |
||
509 | NOPCode = 0x7f80; |
||
510 | DivideChars = ","; |
||
511 | HasAttrs = False; |
||
512 | |||
513 | ValidSegs = (1 << SegCode)|(1 << SegData)|(1 << SegIO); |
||
514 | Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0; |
||
515 | SegLimits[SegCode] = 0xfff; |
||
516 | Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0; |
||
517 | SegLimits[SegData] = (MomCPU == CPU32010) ? 0x8f : 0xff; |
||
518 | Grans[SegIO ] = 2; ListGrans[SegIO ] = 2; SegInits[SegIO ] = 0; |
||
519 | SegLimits[SegIO ] = 7; |
||
520 | |||
521 | MakeCode = MakeCode_3201X; |
||
522 | IsDef = IsDef_3201X; |
||
523 | InternSymbol = InternSymbol_3201X; |
||
524 | SwitchFrom = SwitchFrom_3201X; |
||
525 | InitFields(); |
||
526 | } |
||
527 | |||
528 | void code3201x_init(void) |
||
529 | { |
||
530 | CPU32010 = AddCPU("32010", SwitchTo_3201X); |
||
531 | CPU32015 = AddCPU("32015", SwitchTo_3201X); |
||
532 | } |