1 /* codecop4.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegeneratormodul COP4-Familie                                           */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 
13 #include "bpemu.h"
14 #include "asmdef.h"
15 #include "asmpars.h"
16 #include "asmsub.h"
17 #include "asmitree.h"
18 #include "headids.h"
19 #include "codevars.h"
20 #include "intpseudo.h"
21 #include "natpseudo.h"
22 #include "errmsg.h"
23 
24 #include "codecop4.h"
25 
26 #define FixedOrderCnt 44
27 #define ImmOrderCnt 3
28 
29 #define M_CPUCOP410 (1 << 0)
30 #define M_CPUCOP420 (1 << 1)
31 #define M_CPUCOP440 (1 << 2)
32 #define M_CPUCOP444 (1 << 3)
33 
34 typedef struct
35 {
36   Word CPUMask;
37   Word Code;
38 } FixedOrder;
39 
40 static CPUVar CPUCOP410, CPUCOP420, CPUCOP440, CPUCOP444;
41 static IntType AdrInt;
42 
43 static FixedOrder *FixedOrders, *ImmOrders;
44 
45 /*---------------------------------------------------------------------------*/
46 /* Code Generators */
47 
DecodeFixed(Word Index)48 static void DecodeFixed(Word Index)
49 {
50   FixedOrder *pOrder = FixedOrders + Index;
51 
52   if (ChkArgCnt(0, 0)
53    && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
54   {
55     if (Hi(pOrder->Code))
56       BAsmCode[CodeLen++] = Hi(pOrder->Code);
57     BAsmCode[CodeLen++] = Lo(pOrder->Code);
58   }
59 }
60 
DecodeSK(Word Index)61 static void DecodeSK(Word Index)
62 {
63   if (ChkArgCnt(1, 1))
64   {
65     Byte Bit;
66     Boolean OK;
67 
68     Bit = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
69     if (OK)
70     {
71       if (Index)
72         BAsmCode[CodeLen++] = Index;
73       BAsmCode[CodeLen++] = 0x01 | ((Bit & 1) << 4) | (Bit & 2);
74     }
75   }
76 }
77 
DecodeImm(Word Index)78 static void DecodeImm(Word Index)
79 {
80   FixedOrder *pOrder = ImmOrders + Index;
81 
82   if (ChkArgCnt(1, 1)
83    && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
84   {
85     Byte Val;
86     Boolean OK;
87 
88     Val = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
89     if (OK)
90     {
91       if (Hi(pOrder->Code))
92         BAsmCode[CodeLen++] = Hi(pOrder->Code);
93       BAsmCode[CodeLen++] = Lo(pOrder->Code) | (Val & 0x0f);
94     }
95   }
96 }
97 
DecodeJmp(Word Index)98 static void DecodeJmp(Word Index)
99 {
100   if (ChkArgCnt(1, 1))
101   {
102     Word Addr;
103     Boolean OK;
104 
105     Addr = EvalStrIntExpression(&ArgStr[1], AdrInt, &OK);
106     if (OK)
107     {
108       BAsmCode[CodeLen++] = Index | Hi(Addr);
109       BAsmCode[CodeLen++] = Lo(Addr);
110     }
111   }
112 }
113 
DecodeReg(Word Index)114 static void DecodeReg(Word Index)
115 {
116   if (ChkArgCnt(1, 1))
117   {
118     Byte Reg;
119     Boolean OK;
120 
121     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
122     if (OK)
123     {
124       BAsmCode[CodeLen++] = Index | ((Reg & 3) << 4);;
125     }
126   }
127 }
128 
DecodeAISC(Word Index)129 static void DecodeAISC(Word Index)
130 {
131   UNUSED(Index);
132 
133   if (ChkArgCnt(1, 1))
134   {
135     Byte Val;
136     Boolean OK;
137     tSymbolFlags Flags;
138 
139     Val = EvalStrIntExpressionWithFlags(&ArgStr[1], Int4, &OK, &Flags);
140     if (mFirstPassUnknown(Flags))
141       Val = 1;
142     if (OK)
143     {
144       if (!Val) WrError(ErrNum_UnderRange);
145       else
146         BAsmCode[CodeLen++] = 0x50 | (Val & 0x0f);
147     }
148   }
149 }
150 
DecodeRMB(Word Index)151 static void DecodeRMB(Word Index)
152 {
153   UNUSED(Index);
154 
155   if (ChkArgCnt(1, 1))
156   {
157     Byte Reg;
158     Boolean OK;
159     static Byte Vals[4] = { 0x4c, 0x45, 0x42, 0x43 };
160 
161     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
162     if (OK)
163     {
164       BAsmCode[CodeLen++] = Vals[Reg & 3];
165     }
166   }
167 }
168 
DecodeSMB(Word Index)169 static void DecodeSMB(Word Index)
170 {
171   UNUSED(Index);
172 
173   if (ChkArgCnt(1, 1))
174   {
175     Byte Reg;
176     Boolean OK;
177     static Byte Vals[4] = { 0x4d, 0x47, 0x46, 0x4b };
178 
179     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
180     if (OK)
181     {
182       BAsmCode[CodeLen++] = Vals[Reg & 3];
183     }
184   }
185 }
186 
DecodeXAD(Word Index)187 static void DecodeXAD(Word Index)
188 {
189   UNUSED(Index);
190 
191   if (ChkArgCnt(2, 2))
192   {
193     Byte Reg1, Reg2;
194     Boolean OK;
195     tSymbolFlags Flags;
196 
197     Reg1 = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt2, &OK, &Flags);
198     if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
199       Reg1 = 3;
200     if (OK)
201     {
202       Reg2 = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
203       if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
204         Reg2 = 15;
205       if (OK)
206       {
207         if ((MomCPU < CPUCOP420) && ((Reg1 != 3) || (Reg2 != 15))) WrError(ErrNum_InvAddrMode);
208         else
209         {
210           BAsmCode[CodeLen++] = 0x23;
211           BAsmCode[CodeLen++] = 0x80 | (Reg1 << 4) | Reg2;
212         }
213       }
214     }
215   }
216 }
217 
DecodeLBI(Word Index)218 static void DecodeLBI(Word Index)
219 {
220   UNUSED(Index);
221 
222   if (ChkArgCnt(2, 2))
223   {
224     Byte Reg, Val;
225     Boolean OK;
226 
227     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
228     if (OK)
229     {
230       tSymbolFlags Flags;
231 
232       Val = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
233       if (mFirstPassUnknown(Flags))
234         Val = 0;
235       if (OK)
236       {
237         if ((Val > 0) && (Val < 9))
238         {
239           if (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0)
240           {
241             BAsmCode[CodeLen++] = 0x33;
242             BAsmCode[CodeLen++] = 0x80 | (Reg << 4) | Val;
243           }
244         }
245         else
246         {
247           Val = (Val - 1) & 0x0f;
248           BAsmCode[CodeLen++] = (Reg << 4) | Val;
249         }
250       }
251     }
252   }
253 }
254 
DecodeLDD(Word Index)255 static void DecodeLDD(Word Index)
256 {
257   UNUSED(Index);
258 
259   if (ChkArgCnt(2, 2)
260    && (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0))
261   {
262     Byte Reg, Val;
263     Boolean OK;
264 
265     Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
266     if (OK)
267     {
268       Val = EvalStrIntExpression(&ArgStr[2], UInt4, &OK);
269       if (OK)
270       {
271         BAsmCode[CodeLen++] = 0x23;
272         BAsmCode[CodeLen++] = (Reg << 4) | Val;
273       }
274     }
275   }
276 }
277 
DecodeJSRP(Word Index)278 static void DecodeJSRP(Word Index)
279 {
280   UNUSED(Index);
281 
282   if (ChkArgCnt(1, 1))
283   {
284     Word Addr;
285     Boolean OK;
286     tSymbolFlags Flags;
287 
288     Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
289     if (mFirstPassUnknown(Flags))
290       Addr = 2 << 6;
291     if (OK)
292     {
293       if (((Addr >> 6) != 2) || (Addr == 0xbf)) WrError(ErrNum_NotFromThisAddress);
294       else if ((EProgCounter() >> 7) == 1) WrError(ErrNum_NotOnThisAddress);
295       else
296         BAsmCode[CodeLen++] = 0x80 | (Addr & 0x3f);
297     }
298   }
299 }
300 
DecodeJP(Word Index)301 static void DecodeJP(Word Index)
302 {
303   UNUSED(Index);
304 
305   if (ChkArgCnt(1, 1))
306   {
307     Word Addr, CurrPC;
308     Boolean OK;
309     tSymbolFlags Flags;
310 
311     Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
312     if (mFirstPassUnknown(Flags))
313       Addr = EProgCounter() & (~0x1f);
314     if (OK)
315     {
316       CurrPC = EProgCounter();
317       if ((Addr & 0x3f) == 0x3f)
318         WrError(ErrNum_NotFromThisAddress);
319       if (((CurrPC >> 7) == 1) && ((Addr >> 7) == 1))
320         BAsmCode[CodeLen++] = 0x80 | (Addr & 0x7f);
321       else
322       {
323         Word PossPage;
324 
325         PossPage = CurrPC >> 6;
326         if ((CurrPC & 0x3f) == 0x3f)
327         {
328           PossPage++;
329           if (mFirstPassUnknown(Flags))
330             Addr += 0x40;
331         }
332 
333         if (PossPage == (Addr >> 6))
334           BAsmCode[CodeLen++] = 0xc0 | (Addr & 0x3f);
335         else
336           WrError(ErrNum_NotFromThisAddress);
337       }
338     }
339   }
340 }
341 
342 /*---------------------------------------------------------------------------*/
343 /* Code Table Handling */
344 
AddFixed(const char * NName,Word NCode,Word NMask)345 static void AddFixed(const char *NName, Word NCode, Word NMask)
346 {
347   if (InstrZ >= FixedOrderCnt)
348     exit(0);
349   else
350   {
351     FixedOrders[InstrZ].Code = NCode;
352     FixedOrders[InstrZ].CPUMask = NMask;
353     AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
354   }
355 }
356 
AddImm(const char * NName,Word NCode,Word NMask)357 static void AddImm(const char *NName, Word NCode, Word NMask)
358 {
359   if (InstrZ >= ImmOrderCnt)
360     exit(0);
361   else
362   {
363     ImmOrders[InstrZ].Code = NCode;
364     ImmOrders[InstrZ].CPUMask = NMask;
365     AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
366   }
367 }
368 
InitFields(void)369 static void InitFields(void)
370 {
371   InstTable = CreateInstTable(173);
372 
373   FixedOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * FixedOrderCnt);
374   InstrZ = 0;
375   AddFixed("ASC"  , 0x30,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
376   AddFixed("ADD"  , 0x31,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
377   AddFixed("CLRA" , 0x00,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
378   AddFixed("COMP" , 0x40,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
379   AddFixed("NOP"  , 0x44,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
380   AddFixed("RC"   , 0x32,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
381   AddFixed("SC"   , 0x22,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
382   AddFixed("XOR"  , 0x02,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
383   AddFixed("JID"  , 0xff,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
384   AddFixed("RET"  , 0x48,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
385   AddFixed("RETSK", 0x49,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
386   AddFixed("CAMQ" , 0x333c, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
387   AddFixed("CAME" , 0x331f,                             M_CPUCOP440              );
388   AddFixed("CAMT" , 0x333f,                             M_CPUCOP440 | M_CPUCOP444);
389   AddFixed("CAMR" , 0x333d,                             M_CPUCOP440              );
390   AddFixed("CEMA" , 0x330f,                             M_CPUCOP440              );
391   AddFixed("CTMA" , 0x332f,                             M_CPUCOP440 | M_CPUCOP444);
392   AddFixed("LQID" , 0xbf,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
393   AddFixed("CAB"  , 0x50,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
394   AddFixed("CBA"  , 0x4e,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
395   AddFixed("SKC"  , 0x20,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
396   AddFixed("SKE"  , 0x21,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
397   AddFixed("SKGZ" , 0x3321, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
398   AddFixed("SKSZ" , 0x331c,                             M_CPUCOP440 | M_CPUCOP444);
399   AddFixed("ING"  , 0x332a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
400   AddFixed("INH"  , 0x332b,                             M_CPUCOP440              );
401   AddFixed("INL"  , 0x332e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
402   AddFixed("INR"  , 0x332d,                             M_CPUCOP440              );
403   AddFixed("OBD"  , 0x333e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
404   AddFixed("OMG"  , 0x333a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
405   AddFixed("OMH"  , 0x333b,                             M_CPUCOP440              );
406   AddFixed("XAS"  , 0x4f,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
407   AddFixed("ADT"  , 0x4a,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
408   AddFixed("CASC" , 0x10,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
409   AddFixed("CQMA" , 0x332c,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
410   AddFixed("SKT"  , 0x41,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
411   AddFixed("XABR" , 0x12,                 M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
412   AddFixed("ININ" , 0x3328,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
413   AddFixed("INIL" , 0x3329,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
414   AddFixed("OR"   , 0x331a,                             M_CPUCOP440              );
415   AddFixed("LID"  , 0x3319,                             M_CPUCOP440              );
416   AddFixed("XAN"  , 0x330b,                             M_CPUCOP440              );
417   AddFixed("HALT" , 0x3338,                                           M_CPUCOP444);
418   AddFixed("IT"   , 0x3339,                                           M_CPUCOP444);
419 
420   AddInstTable(InstTable, "SKGBZ", 0x33, DecodeSK);
421   AddInstTable(InstTable, "SKMBZ", 0x00, DecodeSK);
422 
423   ImmOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * ImmOrderCnt);
424   InstrZ = 0;
425   AddImm("STII" , 0x70,   M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
426   AddImm("LEI"  , 0x3360, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
427   AddImm("OGI"  , 0x3350,               M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
428 
429   AddInstTable(InstTable, "JMP"  , 0x60, DecodeJmp);
430   AddInstTable(InstTable, "JSR"  , 0x68, DecodeJmp);
431 
432   AddInstTable(InstTable, "LD"   , 0x05, DecodeReg);
433   AddInstTable(InstTable, "X"    , 0x06, DecodeReg);
434   AddInstTable(InstTable, "XDS"  , 0x07, DecodeReg);
435   AddInstTable(InstTable, "XIS"  , 0x04, DecodeReg);
436 
437   AddInstTable(InstTable, "AISC" , 0x00, DecodeAISC);
438   AddInstTable(InstTable, "RMB"  , 0x00, DecodeRMB);
439   AddInstTable(InstTable, "SMB"  , 0x00, DecodeSMB);
440 
441   AddInstTable(InstTable, "XAD"  , 0x00, DecodeXAD);
442 
443   AddInstTable(InstTable, "LBI"  , 0x00, DecodeLBI);
444 
445   AddInstTable(InstTable, "LDD"  , 0x00, DecodeLDD);
446 
447   AddInstTable(InstTable, "JSRP"  , 0x00, DecodeJSRP);
448 
449   AddInstTable(InstTable, "JP"    , 0x00, DecodeJP);
450 }
451 
DeinitFields(void)452 static void DeinitFields(void)
453 {
454   free(FixedOrders);
455   free(ImmOrders);
456   DestroyInstTable(InstTable);
457 }
458 
459 /*---------------------------------------------------------------------------*/
460 
MakeCode_COP4(void)461 static void MakeCode_COP4(void)
462 {
463   CodeLen = 0; DontPrint = False;
464 
465   /* zu ignorierendes */
466 
467   if (*OpPart.Str == '\0') return;
468 
469   /* pseudo instructions */
470 
471   if (DecodeNatPseudo()) return;
472   if (DecodeIntelPseudo(False)) return;
473 
474   /* machine instructions */
475 
476   if (!LookupInstTable(InstTable, OpPart.Str))
477     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
478 }
479 
SwitchFrom_COP4(void)480 static void SwitchFrom_COP4(void)
481 {
482   DeinitFields();
483 }
484 
IsDef_COP4(void)485 static Boolean IsDef_COP4(void)
486 {
487   return False;
488 }
489 
SwitchTo_COP4(void)490 static void SwitchTo_COP4(void)
491 {
492   PFamilyDescr pDescr;
493 
494   pDescr = FindFamilyByName("COP4");
495 
496   TurnWords = False; ConstMode = ConstModeC;
497 
498   PCSymbol = "."; HeaderID = pDescr->Id;
499   NOPCode = 0x44;
500   DivideChars = ","; HasAttrs = False;
501 
502   ValidSegs = (1 << SegCode);
503   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
504   if (MomCPU >= CPUCOP440)
505   {
506     SegLimits[SegCode] = 0x7ff;
507     AdrInt = UInt11;
508   }
509   else if (MomCPU >= CPUCOP420)
510   {
511     SegLimits[SegCode] = 0x3ff;
512     AdrInt = UInt10;
513   }
514   else
515   {
516     SegLimits[SegCode] = 0x1ff;
517     AdrInt = UInt9;
518   }
519 
520   MakeCode = MakeCode_COP4; IsDef = IsDef_COP4;
521   SwitchFrom = SwitchFrom_COP4; InitFields();
522 }
523 
codecop4_init(void)524 void codecop4_init(void)
525 {
526   CPUCOP410 = AddCPU("COP410", SwitchTo_COP4);
527   CPUCOP420 = AddCPU("COP420", SwitchTo_COP4);
528   CPUCOP440 = AddCPU("COP440", SwitchTo_COP4);
529   CPUCOP444 = AddCPU("COP444", SwitchTo_COP4);
530 }
531