1 /* code2650.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegenerator Signetics 2650                                              */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include <string.h>
13 #include <ctype.h>
14 
15 #include "nls.h"
16 #include "chunks.h"
17 #include "bpemu.h"
18 #include "strutil.h"
19 
20 #include "asmdef.h"
21 #include "asmsub.h"
22 #include "asmpars.h"
23 #include "asmitree.h"
24 #include "codevars.h"
25 #include "headids.h"
26 #include "intpseudo.h"
27 #include "errmsg.h"
28 
29 #include "code2650.h"
30 
31 /*--------------------------------------------------------------------------*/
32 /* Local Variables */
33 
34 static CPUVar CPU2650;
35 
36 /*--------------------------------------------------------------------------*/
37 /* Expression Parsers */
38 
DecodeReg(const char * pAsc,Byte * pRes)39 static Boolean DecodeReg(const char *pAsc, Byte *pRes)
40 {
41   Boolean Result;
42 
43   Result = ((strlen(pAsc) == 2) && (as_toupper(pAsc[0]) == 'R') && (pAsc[1] >= '0') && (pAsc[1] <= '3'));
44   if (Result)
45     *pRes = pAsc[1] - '0';
46   return Result;
47 }
48 
DecodeCondition(const char * pAsc,Byte * pRes)49 static Boolean DecodeCondition(const char *pAsc, Byte *pRes)
50 {
51   Boolean Result = TRUE;
52 
53   if (!as_strcasecmp(pAsc, "EQ"))
54     *pRes = 0;
55   else if (!as_strcasecmp(pAsc, "GT"))
56     *pRes = 1;
57   else if (!as_strcasecmp(pAsc, "LT"))
58     *pRes = 2;
59   else if ((!as_strcasecmp(pAsc, "ALWAYS")) || (!as_strcasecmp(pAsc, "UN")))
60     *pRes = 3;
61   else
62     Result = FALSE;
63 
64   return Result;
65 }
66 
67 /*--------------------------------------------------------------------------*/
68 /* Instruction Decoders */
69 
DecodeFixed(Word Index)70 static void DecodeFixed(Word Index)
71 {
72   if (ChkArgCnt(0, 0))
73   {
74     BAsmCode[0] = Index; CodeLen = 1;
75   }
76 }
77 
DecodeOneReg(Word Index)78 static void DecodeOneReg(Word Index)
79 {
80   Byte Reg;
81 
82   if (!ChkArgCnt(1, 1));
83   else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
84   else
85   {
86     BAsmCode[0] = Index | Reg; CodeLen = 1;
87   }
88 }
89 
DecodeImm(Word Index)90 static void DecodeImm(Word Index)
91 {
92   Boolean OK;
93 
94   if (ChkArgCnt(1, 1))
95   {
96     BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
97     if (OK)
98     {
99       BAsmCode[0] = Index; CodeLen = 2;
100     }
101   }
102 }
103 
DecodeRegImm(Word Index)104 static void DecodeRegImm(Word Index)
105 {
106   Byte Reg;
107   Boolean OK;
108 
109   if (!ChkArgCnt(2, 2));
110   else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
111   else
112   {
113     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
114     if (OK)
115     {
116       BAsmCode[0] = Index | Reg; CodeLen = 2;
117     }
118   }
119 }
120 
DecodeRegAbs(Word Index)121 static void DecodeRegAbs(Word Index)
122 {
123   Byte DReg, IReg;
124   Word AbsVal;
125   Boolean OK, IndFlag;
126 
127   if (!ChkArgCnt(2, 4));
128   else if (!DecodeReg(ArgStr[1].Str, &DReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
129   else
130   {
131     IndFlag = *ArgStr[2].Str == '*';
132     AbsVal = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
133     if (OK)
134     {
135       BAsmCode[0] = Index;
136       BAsmCode[1] = Hi(AbsVal);
137       BAsmCode[2] = Lo(AbsVal);
138       if (IndFlag)
139         BAsmCode[1] |= 0x80;
140       if (ArgCnt == 2)
141       {
142         BAsmCode[0] |= DReg;
143         CodeLen = 3;
144       }
145       else
146       {
147         if (!DecodeReg(ArgStr[3].Str, &IReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[3]);
148         else if (DReg != 0) WrError(ErrNum_InvAddrMode);
149         else
150         {
151           BAsmCode[0] |= IReg;
152           if (ArgCnt == 3)
153           {
154             BAsmCode[1] |= 0x60;
155             CodeLen = 3;
156           }
157           else if (!strcmp(ArgStr[4].Str, "-"))
158           {
159             BAsmCode[1] |= 0x40;
160             CodeLen = 3;
161           }
162           else if (!strcmp(ArgStr[4].Str, "+"))
163           {
164             BAsmCode[1] |= 0x20;
165             CodeLen = 3;
166           }
167           else
168             WrError(ErrNum_InvAddrMode);
169         }
170       }
171     }
172   }
173 }
174 
DecodeRegRel(Word Index)175 static void DecodeRegRel(Word Index)
176 {
177   Byte Reg;
178   Boolean IndFlag, OK;
179   int Dist;
180   tSymbolFlags Flags;
181 
182   if (!ChkArgCnt(2, 2));
183   else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
184   else
185   {
186     BAsmCode[0] = Index | Reg;
187     IndFlag = *ArgStr[2].Str == '*';
188     Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], IndFlag, UInt13, &OK, &Flags) - (EProgCounter() + 2);
189     if (OK)
190     {
191       if (((Dist < - 64) || (Dist > 63)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
192       else
193       {
194         BAsmCode[1] = Dist & 0x7f;
195         if (IndFlag)
196           BAsmCode[1] |= 0x80;
197         CodeLen = 2;
198       }
199     }
200   }
201 }
202 
DecodeCondAbs(Word Index)203 static void DecodeCondAbs(Word Index)
204 {
205   Byte Cond;
206   Word Address;
207   Boolean OK, IndFlag;
208 
209   if (!ChkArgCnt(2, 2));
210   else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
211   else
212   {
213     IndFlag = *ArgStr[2].Str == '*';
214     Address = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
215     if (OK)
216     {
217       BAsmCode[0] = Index | Cond;
218       BAsmCode[1] = Hi(Address);
219       if (IndFlag)
220         BAsmCode[1] |= 0x80;
221       BAsmCode[2] = Lo(Address);
222       CodeLen = 3;
223     }
224   }
225 }
226 
DecodeCondRel(Word Index)227 static void DecodeCondRel(Word Index)
228 {
229   Byte Cond;
230   Boolean IndFlag, OK;
231   tSymbolFlags Flags;
232   int Dist;
233 
234   if (!ChkArgCnt(2, 2));
235   else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
236   else
237   {
238     BAsmCode[0] = Index | Cond;
239     IndFlag = *ArgStr[2].Str == '*';
240     Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], IndFlag, UInt13, &OK, &Flags) - (EProgCounter() + 2);
241     if (OK)
242     {
243       if (((Dist < - 64) || (Dist > 63)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
244       else
245       {
246         BAsmCode[1] = Dist & 0x7f;
247         if (IndFlag)
248           BAsmCode[1] |= 0x80;
249         CodeLen = 2;
250       }
251     }
252   }
253 }
254 
DecodeRegAbs2(Word Index)255 static void DecodeRegAbs2(Word Index)
256 {
257   Byte Reg;
258   Word AbsVal;
259   Boolean IndFlag, OK;
260 
261   if (!ChkArgCnt(2, 2));
262   else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
263   else
264   {
265     BAsmCode[0] = Index | Reg;
266     IndFlag = *ArgStr[2].Str == '*';
267     AbsVal = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
268     if (OK)
269     {
270       BAsmCode[1] = Hi(AbsVal);
271       if (IndFlag)
272         BAsmCode[1] |= 0x80;
273       BAsmCode[2] = Lo(AbsVal);
274       CodeLen = 3;
275     }
276   }
277 }
278 
DecodeBrAbs(Word Index)279 static void DecodeBrAbs(Word Index)
280 {
281   Byte Reg = 3;
282   Word AbsVal;
283   Boolean IndFlag, OK;
284 
285   if (!ChkArgCnt(1, 2));
286   else if ((ArgCnt == 2) && (!DecodeReg(ArgStr[2].Str, &Reg))) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
287   else if (Reg != 3) WrError(ErrNum_InvAddrMode);
288   else
289   {
290     BAsmCode[0] = Index | Reg;
291     IndFlag = *ArgStr[1].Str == '*';
292     AbsVal = EvalStrIntExpressionOffs(&ArgStr[1], IndFlag, UInt13, &OK);
293     if (OK)
294     {
295       BAsmCode[1] = Hi(AbsVal);
296       if (IndFlag)
297         BAsmCode[1] |= 0x80;
298       BAsmCode[2] = Lo(AbsVal);
299       CodeLen = 3;
300     }
301   }
302 }
303 
DecodeCond(Word Index)304 static void DecodeCond(Word Index)
305 {
306   Byte Cond;
307 
308   if (!ChkArgCnt(1, 1));
309   else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
310   else
311   {
312     BAsmCode[0] = Index | Cond;
313     CodeLen = 1;
314   }
315 }
316 
DecodeZero(Word Index)317 static void DecodeZero(Word Index)
318 {
319   Boolean IndFlag, OK;
320 
321   if (ChkArgCnt(1, 1))
322   {
323     BAsmCode[0] = Index;
324     IndFlag = *ArgStr[1].Str == '*';
325     BAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[1], IndFlag, UInt7, &OK);
326     if (OK)
327     {
328       if (IndFlag)
329         BAsmCode[1] |= 0x80;
330       CodeLen = 2;
331     }
332   }
333 }
334 
335 /*--------------------------------------------------------------------------*/
336 /* Code Table Handling */
337 
AddFixed(const char * pName,Word Code)338 static void AddFixed(const char *pName, Word Code)
339 {
340   AddInstTable(InstTable, pName, Code, DecodeFixed);
341 }
342 
AddOneReg(const char * pName,Word Code)343 static void AddOneReg(const char *pName, Word Code)
344 {
345   AddInstTable(InstTable, pName, Code, DecodeOneReg);
346 }
347 
AddImm(const char * pName,Word Code)348 static void AddImm(const char *pName, Word Code)
349 {
350   AddInstTable(InstTable, pName, Code, DecodeImm);
351 }
352 
AddRegImm(const char * pName,Word Code)353 static void AddRegImm(const char *pName, Word Code)
354 {
355   AddInstTable(InstTable, pName, Code, DecodeRegImm);
356 }
357 
AddRegAbs(const char * pName,Word Code)358 static void AddRegAbs(const char *pName, Word Code)
359 {
360   AddInstTable(InstTable, pName, Code, DecodeRegAbs);
361 }
362 
AddRegRel(const char * pName,Word Code)363 static void AddRegRel(const char *pName, Word Code)
364 {
365   AddInstTable(InstTable, pName, Code, DecodeRegRel);
366 }
367 
AddCondAbs(const char * pName,Word Code)368 static void AddCondAbs(const char *pName, Word Code)
369 {
370   AddInstTable(InstTable, pName, Code, DecodeCondAbs);
371 }
372 
AddCondRel(const char * pName,Word Code)373 static void AddCondRel(const char *pName, Word Code)
374 {
375   AddInstTable(InstTable, pName, Code, DecodeCondRel);
376 }
377 
AddRegAbs2(const char * pName,Word Code)378 static void AddRegAbs2(const char *pName, Word Code)
379 {
380   AddInstTable(InstTable, pName, Code, DecodeRegAbs2);
381 }
382 
AddBrAbs(const char * pName,Word Code)383 static void AddBrAbs(const char *pName, Word Code)
384 {
385   AddInstTable(InstTable, pName, Code, DecodeBrAbs);
386 }
387 
AddCond(const char * pName,Word Code)388 static void AddCond(const char *pName, Word Code)
389 {
390   AddInstTable(InstTable, pName, Code, DecodeCond);
391 }
392 
AddZero(const char * pName,Word Code)393 static void AddZero(const char *pName, Word Code)
394 {
395   AddInstTable(InstTable, pName, Code, DecodeZero);
396 }
397 
InitFields(void)398 static void InitFields(void)
399 {
400   InstTable = CreateInstTable(203);
401 
402   AddFixed("NOP", 0xc0);
403   AddFixed("HALT", 0x40);
404   AddFixed("LPSL", 0x93);
405   AddFixed("LPSU", 0x92);
406   AddFixed("SPSL", 0x13);
407   AddFixed("SPSU", 0x12);
408 
409   AddOneReg("ADDZ", 0x80);
410   AddOneReg("ANDZ", 0x40);
411   AddOneReg("COMZ", 0xe0);
412   AddOneReg("DAR", 0x94);
413   AddOneReg("EORZ", 0x20);
414   AddOneReg("IORZ", 0x60);
415   AddOneReg("LODZ", 0x00);
416   AddOneReg("REDC", 0x30);
417   AddOneReg("REDD", 0x70);
418   AddOneReg("RRL", 0xd0);
419   AddOneReg("RRR", 0x50);
420   AddOneReg("STRZ", 0xc0);
421   AddOneReg("SUBZ", 0xa0);
422   AddOneReg("WRTC", 0xb0);
423   AddOneReg("WRTD", 0xf0);
424 
425   AddImm("CPSL", 0x75);
426   AddImm("CPSU", 0x74);
427   AddImm("PPSL", 0x77);
428   AddImm("PPSU", 0x76);
429   AddImm("TPSL", 0xb5);
430   AddImm("TPSU", 0xb4);
431 
432   AddRegImm("ADDI", 0x84);
433   AddRegImm("ANDI", 0x44);
434   AddRegImm("COMI", 0xe4);
435   AddRegImm("EORI", 0x24);
436   AddRegImm("IORI", 0x64);
437   AddRegImm("LODI", 0x04);
438   AddRegImm("REDE", 0x54);
439   AddRegImm("SUBI", 0xa4);
440   AddRegImm("TMI", 0xf4);
441   AddRegImm("WRTE", 0xd4);
442 
443   AddRegAbs("ADDA", 0x8c);
444   AddRegAbs("ANDA", 0x4c);
445   AddRegAbs("COMA", 0xec);
446   AddRegAbs("EORA", 0x2c);
447   AddRegAbs("IORA", 0x6c);
448   AddRegAbs("LODA", 0x0c);
449   AddRegAbs("STRA", 0xcc);
450   AddRegAbs("SUBA", 0xac);
451 
452   AddRegRel("ADDR", 0x88);
453   AddRegRel("ANDR", 0x48);
454   AddRegRel("BDRR", 0xf8);
455   AddRegRel("BIRR", 0xd8);
456   AddRegRel("BRNR", 0x58);
457   AddRegRel("BSNR", 0x78);
458   AddRegRel("COMR", 0xe8);
459   AddRegRel("EORR", 0x28);
460   AddRegRel("IORR", 0x68);
461   AddRegRel("LODR", 0x08);
462   AddRegRel("STRR", 0xc8);
463   AddRegRel("SUBR", 0xa8);
464 
465   AddCondAbs("BCFA", 0x9c);
466   AddCondAbs("BCTA", 0x1c);
467   AddCondAbs("BSFA", 0xbc);
468   AddCondAbs("BSTA", 0x3c);
469 
470   AddCondRel("BCFR", 0x98);
471   AddCondRel("BCTR", 0x18);
472   AddCondRel("BSFR", 0xb8);
473   AddCondRel("BSTR", 0x38);
474 
475   AddRegAbs2("BDRA", 0xfc);
476   AddRegAbs2("BIRA", 0xdc);
477   AddRegAbs2("BRNA", 0x5c);
478   AddRegAbs2("BSNA", 0x7c);
479 
480   AddBrAbs("BSXA", 0xbf);
481   AddBrAbs("BXA", 0x9f);
482 
483   AddCond("RETC", 0x14);
484   AddCond("RETE", 0x34);
485 
486   AddZero("ZBRR", 0x9b);
487   AddZero("ZBSR", 0xbb);
488 }
489 
DeinitFields(void)490 static void DeinitFields(void)
491 {
492   DestroyInstTable(InstTable);
493 }
494 
495 /*--------------------------------------------------------------------------*/
496 /* Callbacks */
497 
MakeCode_2650(void)498 static void MakeCode_2650(void)
499 {
500   char *pPos;
501 
502   CodeLen = 0;
503 
504   DontPrint = False;
505 
506   /* Nullanweisung */
507 
508   if ((*OpPart.Str == '\0') && (ArgCnt == 0))
509     return;
510 
511   /* Pseudoanweisungen */
512 
513   if (DecodeIntelPseudo(False)) return;
514 
515   /* try to split off first (register) operand from instruction */
516 
517   pPos = strchr(OpPart.Str, ',');
518   if (pPos)
519   {
520     int ArgC;
521 
522     IncArgCnt();
523     for (ArgC = ArgCnt - 1; ArgC >= 1; ArgC--)
524       StrCompCopy(&ArgStr[ArgC + 1], &ArgStr[ArgC]);
525     StrCompSplitRight(&OpPart, &ArgStr[1], pPos);
526   }
527 
528   /* alles aus der Tabelle */
529 
530   if (!LookupInstTable(InstTable, OpPart.Str))
531     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
532 }
533 
IsDef_2650(void)534 static Boolean IsDef_2650(void)
535 {
536   return FALSE;
537 }
538 
SwitchFrom_2650(void)539 static void SwitchFrom_2650(void)
540 {
541   DeinitFields();
542 }
543 
SwitchTo_2650(void)544 static void SwitchTo_2650(void)
545 {
546   PFamilyDescr pDescr;
547 
548   TurnWords = False; ConstMode = ConstModeMoto;
549 
550   pDescr = FindFamilyByName("2650");
551   PCSymbol = "$"; HeaderID = pDescr->Id; NOPCode = 0xc0;
552   DivideChars = ","; HasAttrs = False;
553 
554   ValidSegs = (1 << SegCode);
555   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
556   SegLimits[SegCode] = 0x1fffl;
557 
558   MakeCode = MakeCode_2650; IsDef = IsDef_2650;
559 
560   SwitchFrom = SwitchFrom_2650; InitFields();
561 }
562 
563 /*--------------------------------------------------------------------------*/
564 /* Initialisierung */
565 
code2650_init(void)566 void code2650_init(void)
567 {
568   CPU2650 = AddCPU("2650", SwitchTo_2650);
569 }
570