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