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 #define AdrShiftOrderCnt 5
44 #define ImmOrderCnt 3
45
46
47 static Word AdrMode;
48 static Boolean AdrOK;
49
50 static CPUVar CPU32010, CPU32015;
51
52 static AdrShiftOrder *AdrShiftOrders;
53 static ImmOrder *ImmOrders;
54
55 /*----------------------------------------------------------------------------*/
56
EvalARExpression(const tStrComp * pArg,Boolean * OK)57 static Word EvalARExpression(const tStrComp *pArg, Boolean *OK)
58 {
59 *OK = True;
60 if (!as_strcasecmp(pArg->Str, "AR0"))
61 return 0;
62 if (!as_strcasecmp(pArg->Str, "AR1"))
63 return 1;
64 return EvalStrIntExpression(pArg, UInt1, OK);
65 }
66
DecodeAdr(const tStrComp * pArg,int Aux,Boolean Must1)67 static void DecodeAdr(const tStrComp *pArg, int Aux, Boolean Must1)
68 {
69 Byte h;
70 char *p;
71 char *Arg = pArg->Str;
72
73 AdrOK = False;
74
75 if ((!strcmp(pArg->Str, "*")) || (!strcmp(pArg->Str, "*-")) || (!strcmp(pArg->Str, "*+")))
76 {
77 AdrMode = 0x88;
78 if (strlen(Arg) == 2)
79 AdrMode += (pArg->Str[1] == '+') ? 0x20 : 0x10;
80 if (Aux <= ArgCnt)
81 {
82 h = EvalARExpression(&ArgStr[Aux], &AdrOK);
83 if (AdrOK)
84 {
85 AdrMode &= 0xf7;
86 AdrMode += h;
87 }
88 }
89 else
90 AdrOK = True;
91 }
92 else if (ChkArgCnt(1, Aux - 1))
93 {
94 tEvalResult EvalResult;
95
96 h = 0;
97 if ((strlen(pArg->Str) > 3) && (!as_strncasecmp(pArg->Str, "DAT", 3)))
98 {
99 AdrOK = True;
100 for (p = pArg->Str + 3; *p != '\0'; p++)
101 if ((*p > '9') || (*p < '0'))
102 AdrOK = False;
103 if (AdrOK)
104 {
105 h = EvalStrIntExpressionOffsWithResult(pArg, 3, UInt8, &EvalResult);
106 AdrOK = EvalResult.OK;
107 }
108 }
109 if (!AdrOK)
110 {
111 h = EvalStrIntExpressionWithResult(pArg, Int8, &EvalResult);
112 AdrOK = EvalResult.OK;
113 }
114 if (AdrOK)
115 {
116 if (Must1 && (h < 0x80) && !mFirstPassUnknown(EvalResult.Flags))
117 {
118 WrError(ErrNum_UnderRange);
119 AdrOK = False;
120 }
121 else
122 {
123 AdrMode = h & 0x7f;
124 ChkSpace(SegData, EvalResult.AddrSpaceMask);
125 }
126 }
127 }
128 }
129
130 /*----------------------------------------------------------------------------*/
131
132 /* kein Argument */
133
DecodeFixed(Word Code)134 static void DecodeFixed(Word Code)
135 {
136 if (ChkArgCnt(0, 0))
137 {
138 CodeLen = 1;
139 WAsmCode[0] = Code;
140 }
141 }
142
143 /* Spruenge */
144
DecodeJmp(Word Code)145 static void DecodeJmp(Word Code)
146 {
147 if (ChkArgCnt(1, 1))
148 {
149 Boolean OK;
150
151 WAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt12, &OK);
152 if (OK)
153 {
154 CodeLen = 2;
155 WAsmCode[0] = Code;
156 }
157 }
158 }
159
160 /* nur Adresse */
161
DecodeAdrInst(Word Code)162 static void DecodeAdrInst(Word Code)
163 {
164 if (ChkArgCnt(1, 2))
165 {
166 DecodeAdr(&ArgStr[1], 2, Code & 1);
167 if (AdrOK)
168 {
169 CodeLen = 1;
170 WAsmCode[0] = (Code & 0xfffe) + AdrMode;
171 }
172 }
173 }
174
175 /* Adresse & schieben */
176
DecodeAdrShift(Word Index)177 static void DecodeAdrShift(Word Index)
178 {
179 Boolean HasSh;
180 int Cnt;
181 const AdrShiftOrder *pOrder = AdrShiftOrders + Index;
182
183 if (ChkArgCnt(1, 3))
184 {
185 if (*ArgStr[1].Str == '*')
186 {
187 if (ArgCnt == 2)
188 {
189 if (!as_strncasecmp(ArgStr[2].Str, "AR", 2))
190 {
191 HasSh = False;
192 Cnt = 2;
193 }
194 else
195 {
196 HasSh = True;
197 Cnt = 3;
198 }
199 }
200 else
201 {
202 HasSh = True;
203 Cnt = 3;
204 }
205 }
206 else
207 {
208 Cnt = 3;
209 HasSh = (ArgCnt == 2);
210 }
211 DecodeAdr(&ArgStr[1], Cnt, 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
DecodeIN_OUT(Word Code)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
DecodeImm(Word Index)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
DecodeLARP(Word Code)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
DecodeLAR_SAR(Word Code)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
DecodeLARK(Word Code)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
DecodePORT(Word Code)347 static void DecodePORT(Word Code)
348 {
349 UNUSED(Code);
350
351 CodeEquate(SegIO, 0, 7);
352 }
353
DecodeDATA_3201x(Word Code)354 static void DecodeDATA_3201x(Word Code)
355 {
356 UNUSED(Code);
357
358 DecodeDATA(Int16, Int16);
359 }
360
361 /*----------------------------------------------------------------------------*/
362
AddFixed(const char * NName,Word NCode)363 static void AddFixed(const char *NName, Word NCode)
364 {
365 AddInstTable(InstTable, NName, NCode, DecodeFixed);
366 }
367
AddJmp(const char * NName,Word NCode)368 static void AddJmp(const char *NName, Word NCode)
369 {
370 AddInstTable(InstTable, NName, NCode, DecodeJmp);
371 }
372
AddAdr(const char * NName,Word NCode,Word NMust1)373 static void AddAdr(const char *NName, Word NCode, Word NMust1)
374 {
375 AddInstTable(InstTable, NName, NCode | NMust1, DecodeAdrInst);
376 }
377
AddAdrShift(const char * NName,Word NCode,Word NAllow)378 static void AddAdrShift(const char *NName, Word NCode, Word NAllow)
379 {
380 if (InstrZ >= AdrShiftOrderCnt) exit(255);
381 AdrShiftOrders[InstrZ].Code = NCode;
382 AdrShiftOrders[InstrZ].AllowShifts = NAllow;
383 AddInstTable(InstTable, NName, InstrZ++, DecodeAdrShift);
384 }
385
AddImm(const char * NName,Word NCode,Integer NMin,Integer NMax,Word NMask)386 static void AddImm(const char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask)
387 {
388 if (InstrZ >= ImmOrderCnt) exit(255);
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
InitFields(void)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 AdrShiftOrders = (AdrShiftOrder *) malloc(sizeof(AdrShiftOrder) * AdrShiftOrderCnt); 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 ImmOrders = (ImmOrder *) malloc(sizeof(ImmOrder)*ImmOrderCnt); 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
DeinitFields(void)449 static void DeinitFields(void)
450 {
451 DestroyInstTable(InstTable);
452
453 free(AdrShiftOrders);
454 free(ImmOrders);
455 }
456
457 /*----------------------------------------------------------------------------*/
458
MakeCode_3201X(void)459 static void MakeCode_3201X(void)
460 {
461 CodeLen = 0;
462 DontPrint = False;
463
464 /* zu ignorierendes */
465
466 if (Memo(""))
467 return;
468
469 if (!LookupInstTable(InstTable, OpPart.Str))
470 WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
471 }
472
IsDef_3201X(void)473 static Boolean IsDef_3201X(void)
474 {
475 return (Memo("PORT"));
476 }
477
SwitchFrom_3201X(void)478 static void SwitchFrom_3201X(void)
479 {
480 DeinitFields();
481 }
482
SwitchTo_3201X(void)483 static void SwitchTo_3201X(void)
484 {
485 TurnWords = False;
486 ConstMode = ConstModeIntel;
487
488 PCSymbol = "$";
489 HeaderID = 0x74;
490 NOPCode = 0x7f80;
491 DivideChars = ",";
492 HasAttrs = False;
493
494 ValidSegs = (1 << SegCode)|(1 << SegData)|(1 << SegIO);
495 Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
496 SegLimits[SegCode] = 0xfff;
497 Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
498 SegLimits[SegData] = (MomCPU == CPU32010) ? 0x8f : 0xff;
499 Grans[SegIO ] = 2; ListGrans[SegIO ] = 2; SegInits[SegIO ] = 0;
500 SegLimits[SegIO ] = 7;
501
502 MakeCode = MakeCode_3201X;
503 IsDef = IsDef_3201X;
504 SwitchFrom = SwitchFrom_3201X;
505 InitFields();
506 }
507
code3201x_init(void)508 void code3201x_init(void)
509 {
510 CPU32010 = AddCPU("32010", SwitchTo_3201X);
511 CPU32015 = AddCPU("32015", SwitchTo_3201X);
512 }
513