1 /* code47c00.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegenerator Toshiba TLCS-47(0(A))                                       */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 
13 #include <string.h>
14 
15 #include "bpemu.h"
16 #include "strutil.h"
17 #include "asmdef.h"
18 #include "asmsub.h"
19 #include "asmpars.h"
20 #include "asmitree.h"
21 #include "codepseudo.h"
22 #include "intpseudo.h"
23 #include "codevars.h"
24 #include "errmsg.h"
25 
26 #include "code47c00.h"
27 
28 #define BitOrderCnt 4
29 
30 enum
31 {
32   ModNone = -1,
33   ModAcc = 0,
34   ModL = 1,
35   ModH = 2,
36   ModHL = 3,
37   ModIHL = 4,
38   ModAbs = 5,
39   ModPort = 6,
40   ModImm = 7,
41   ModSAbs = 8
42 };
43 
44 #define MModAcc (1 << ModAcc)
45 #define MModL (1 << ModL)
46 #define MModH (1 << ModH)
47 #define MModHL (1 << ModHL)
48 #define MModIHL (1 << ModIHL)
49 #define MModAbs (1 << ModAbs)
50 #define MModPort (1 << ModPort)
51 #define MModImm (1 << ModImm)
52 #define MModSAbs (1 << ModSAbs)
53 
54 #define M_CPU47C00 1
55 #define M_CPU470C00 2
56 #define M_CPU470AC00 4
57 
58 static CPUVar CPU47C00, CPU470C00, CPU470AC00;
59 static ShortInt AdrType, OpSize;
60 static Byte AdrVal;
61 static LongInt DMBAssume;
62 
63 /*---------------------------------------------------------------------------*/
64 
SetOpSize(ShortInt NewSize)65 static void SetOpSize(ShortInt NewSize)
66 {
67   if (OpSize == -1) OpSize = NewSize;
68   else if (OpSize != NewSize)
69   {
70     WrError(ErrNum_ConfOpSizes); AdrType = ModNone;
71   }
72 }
73 
DecodeAdr(const tStrComp * pArg,Word Mask)74 static void DecodeAdr(const tStrComp *pArg, Word Mask)
75 {
76   static const char RegNames[ModIHL + 1][4] = {"A", "L", "H", "HL", "@HL"};
77 
78   Byte z;
79   Word AdrWord;
80   tEvalResult EvalResult;
81 
82   AdrType = ModNone;
83 
84   for (z = 0; z <= ModIHL; z++)
85    if (!as_strcasecmp(pArg->Str, RegNames[z]))
86    {
87      AdrType = z;
88      if (z != ModIHL) SetOpSize(Ord(z == ModHL));
89      goto chk;
90    }
91 
92   if (*pArg->Str == '#')
93   {
94     switch (OpSize)
95     {
96       case -1:
97         WrError(ErrNum_UndefOpSizes);
98         break;
99       case 2:
100         AdrVal = EvalStrIntExpressionOffsWithResult(pArg, 1, UInt2, &EvalResult) & 3;
101         if (EvalResult.OK)
102           AdrType = ModImm;
103         break;
104       case 0:
105         AdrVal = EvalStrIntExpressionOffsWithResult(pArg, 1, Int4, &EvalResult) & 15;
106         if (EvalResult.OK)
107           AdrType = ModImm;
108         break;
109       case 1:
110         AdrVal = EvalStrIntExpressionOffsWithResult(pArg, 1, Int8, &EvalResult);
111         if (EvalResult.OK)
112           AdrType = ModImm;
113         break;
114     }
115     goto chk;
116   }
117 
118   if (*pArg->Str == '%')
119   {
120     AdrVal = EvalStrIntExpressionOffsWithResult(pArg, 1, Int5, &EvalResult);
121     if (EvalResult.OK)
122     {
123       AdrType = ModPort;
124       ChkSpace(SegIO, EvalResult.AddrSpaceMask);
125     }
126     goto chk;
127   }
128 
129   AdrWord = EvalStrIntExpressionWithResult(pArg, Int16, &EvalResult);
130   if (EvalResult.OK)
131   {
132     ChkSpace(SegData, EvalResult.AddrSpaceMask);
133 
134     if (mFirstPassUnknown(EvalResult.Flags))
135       AdrWord &= SegLimits[SegData];
136     else if (Hi(AdrWord) != DMBAssume)
137       WrError(ErrNum_InAccPage);
138 
139     AdrVal = Lo(AdrWord);
140     if (mFirstPassUnknown(EvalResult.Flags))
141       AdrVal &= 15;
142 
143     AdrType = (((Mask & MModSAbs) != 0) && (AdrVal < 16)) ? ModSAbs : ModAbs;
144   }
145 
146 chk:
147   if ((AdrType != ModNone) && (!((1 << AdrType) & Mask)))
148   {
149     WrError(ErrNum_InvAddrMode);
150     AdrType = ModNone;
151   }
152 }
153 
ChkCPU(Byte Mask)154 static void ChkCPU(Byte Mask)
155 {
156   if (ChkExactCPUMask(Mask, CPU47C00) < 0)
157     CodeLen = 0;
158 }
159 
DualOp(const char * s1,const char * s2)160 static Boolean DualOp(const char *s1, const char *s2)
161 {
162   return (((!as_strcasecmp(ArgStr[1].Str, s1)) && (!as_strcasecmp(ArgStr[2].Str, s2)))
163        || ((!as_strcasecmp(ArgStr[2].Str, s1)) && (!as_strcasecmp(ArgStr[1].Str, s2))));
164 }
165 
166 /*---------------------------------------------------------------------------*/
167 
168 /* ohne Argument */
169 
DecodeFixed(Word Code)170 static void DecodeFixed(Word Code)
171 {
172   if (ChkArgCnt(0, 0))
173   {
174     CodeLen = 1;
175     BAsmCode[0] = Code;
176   }
177 }
178 
179 /* Datentransfer */
180 
DecodeLD(Word Code)181 static void DecodeLD(Word Code)
182 {
183   UNUSED(Code);
184 
185   if (!ChkArgCnt(2, 2));
186   else if (!as_strcasecmp(ArgStr[1].Str, "DMB"))
187   {
188     SetOpSize(2);
189     DecodeAdr(&ArgStr[2], MModImm | MModIHL);
190     switch (AdrType)
191     {
192       case ModIHL:
193         CodeLen = 3;
194         BAsmCode[0] = 0x03;
195         BAsmCode[1] = 0x3a;
196         BAsmCode[2] = 0xe9;
197         ChkCPU(M_CPU470AC00);
198         break;
199       case ModImm:
200         CodeLen = 3;
201         BAsmCode[0] = 0x03;
202         BAsmCode[1] = 0x2c;
203         BAsmCode[2] = 0x09 + (AdrVal << 4);
204         ChkCPU(M_CPU470AC00);
205         break;
206     }
207   }
208   else
209   {
210     DecodeAdr(&ArgStr[1], MModAcc | MModHL | MModH | MModL);
211     switch (AdrType)
212     {
213       case ModAcc:
214         DecodeAdr(&ArgStr[2], MModIHL | MModAbs | MModImm);
215         switch (AdrType)
216         {
217           case ModIHL:
218             CodeLen = 1;
219             BAsmCode[0] = 0x0c;
220             break;
221           case ModAbs:
222             CodeLen = 2;
223             BAsmCode[0] = 0x3c;
224             BAsmCode[1] = AdrVal;
225             break;
226           case ModImm:
227             CodeLen = 1;
228             BAsmCode[0] = 0x40 + AdrVal;
229             break;
230         }
231         break;
232       case ModHL:
233         DecodeAdr(&ArgStr[2], MModAbs | MModImm);
234         switch (AdrType)
235         {
236           case ModAbs:
237             if (AdrVal & 3) WrError(ErrNum_NotAligned);
238             else
239             {
240               CodeLen = 2;
241               BAsmCode[0] = 0x28;
242               BAsmCode[1] = AdrVal;
243             }
244             break;
245           case ModImm:
246             CodeLen = 2;
247             BAsmCode[0] = 0xc0 + (AdrVal >> 4);
248             BAsmCode[1] = 0xe0 + (AdrVal & 15);
249             break;
250         }
251         break;
252       case ModH:
253       case ModL:
254         BAsmCode[0] = 0xc0 + (Ord(AdrType == ModL) << 5);
255         DecodeAdr(&ArgStr[2], MModImm);
256         if (AdrType != ModNone)
257         {
258           CodeLen = 1;
259           BAsmCode[0] += AdrVal;
260         }
261         break;
262     }
263   }
264 }
265 
DecodeLDL(Word Code)266 static void DecodeLDL(Word Code)
267 {
268   UNUSED(Code);
269 
270   if (!ChkArgCnt(2, 2));
271   else if ((as_strcasecmp(ArgStr[1].Str, "A")) || (as_strcasecmp(ArgStr[2].Str, "@DC"))) WrError(ErrNum_InvAddrMode);
272   else
273   {
274     CodeLen = 1;
275     BAsmCode[0] = 0x33;
276   }
277 }
278 
DecodeLDH(Word Code)279 static void DecodeLDH(Word Code)
280 {
281   UNUSED(Code);
282 
283   if (!ChkArgCnt(2, 2));
284   else if ((as_strcasecmp(ArgStr[1].Str, "A")) || (as_strcasecmp(ArgStr[2].Str, "@DC+"))) WrError(ErrNum_InvAddrMode);
285   else
286   {
287     CodeLen = 1;
288     BAsmCode[0] = 0x32;
289   }
290 }
291 
DecodeST(Word Code)292 static void DecodeST(Word Code)
293 {
294   Byte HReg;
295 
296   UNUSED(Code);
297 
298   if (!ChkArgCnt(2, 2));
299   else if (!as_strcasecmp(ArgStr[1].Str, "DMB"))
300   {
301     DecodeAdr(&ArgStr[2], MModIHL);
302     if (AdrType != ModNone)
303     {
304       CodeLen = 3;
305       BAsmCode[0] = 0x03;
306       BAsmCode[1] = 0x3a;
307       BAsmCode[2] = 0x69;
308       ChkCPU(M_CPU470AC00);
309     }
310   }
311   else
312   {
313     OpSize = 0;
314     DecodeAdr(&ArgStr[1], MModImm | MModAcc);
315     switch (AdrType)
316     {
317       case ModAcc:
318         if (!as_strcasecmp(ArgStr[2].Str, "@HL+"))
319         {
320           CodeLen = 1;
321           BAsmCode[0] = 0x1a;
322         }
323         else if (!as_strcasecmp(ArgStr[2].Str, "@HL-"))
324         {
325           CodeLen = 1;
326           BAsmCode[0] = 0x1b;
327         }
328         else
329         {
330           DecodeAdr(&ArgStr[2], MModAbs | MModIHL);
331           switch (AdrType)
332           {
333             case ModAbs:
334               CodeLen = 2;
335               BAsmCode[0] = 0x3f;
336               BAsmCode[1] = AdrVal;
337               break;
338             case ModIHL:
339               CodeLen = 1;
340               BAsmCode[0] = 0x0f;
341               break;
342           }
343         }
344         break;
345       case ModImm:
346         HReg = AdrVal;
347         if (!as_strcasecmp(ArgStr[2].Str, "@HL+"))
348         {
349           CodeLen = 1;
350           BAsmCode[0] = 0xf0 + HReg;
351         }
352         else
353         {
354           DecodeAdr(&ArgStr[2], MModSAbs);
355           if (AdrType != ModNone)
356           {
357             if (AdrVal>0x0f) WrError(ErrNum_OverRange);
358             else
359             {
360               CodeLen = 2;
361               BAsmCode[0] = 0x2d;
362               BAsmCode[1] = (HReg << 4) + AdrVal;
363             }
364           }
365         }
366         break;
367     }
368   }
369 }
370 
DecodeMOV(Word Code)371 static void DecodeMOV(Word Code)
372 {
373   UNUSED(Code);
374 
375   if (!ChkArgCnt(2, 2));
376   else if ((!as_strcasecmp(ArgStr[1].Str, "A")) && (!as_strcasecmp(ArgStr[2].Str, "DMB")))
377   {
378     CodeLen = 3;
379     BAsmCode[0] = 0x03;
380     BAsmCode[1] = 0x3a;
381     BAsmCode[2] = 0xa9;
382     ChkCPU(M_CPU470AC00);
383   }
384   else if ((!as_strcasecmp(ArgStr[1].Str, "DMB")) && (!as_strcasecmp(ArgStr[2].Str, "A")))
385   {
386     CodeLen = 3;
387     BAsmCode[0] = 0x03;
388     BAsmCode[1] = 0x3a;
389     BAsmCode[2] = 0x29;
390     ChkCPU(M_CPU470AC00);
391   }
392   else if ((!as_strcasecmp(ArgStr[1].Str, "A")) && (!as_strcasecmp(ArgStr[2].Str, "SPW13")))
393   {
394     CodeLen = 2;
395     BAsmCode[0] = 0x3a;
396     BAsmCode[1] = 0x84;
397     ChkCPU(M_CPU470AC00);
398   }
399   else if ((!as_strcasecmp(ArgStr[1].Str, "STK13")) && (!as_strcasecmp(ArgStr[2].Str, "A")))
400   {
401     CodeLen = 2;
402     BAsmCode[0] = 0x3a;
403     BAsmCode[1] = 0x04;
404     ChkCPU(M_CPU470AC00);
405   }
406   else if (as_strcasecmp(ArgStr[2].Str, "A")) WrError(ErrNum_InvAddrMode);
407   else
408   {
409     DecodeAdr(&ArgStr[1], MModH | MModL);
410     if (AdrType != ModNone)
411     {
412       CodeLen = 1;
413       BAsmCode[0] = 0x10 + Ord(AdrType == ModL);
414     }
415   }
416 }
417 
DecodeXCH(Word Code)418 static void DecodeXCH(Word Code)
419 {
420   UNUSED(Code);
421 
422   if (!ChkArgCnt(2, 2));
423   else if (DualOp("A", "EIR"))
424   {
425     CodeLen = 1;
426     BAsmCode[0] = 0x13;
427   }
428   else if (DualOp("A", "@HL"))
429   {
430     CodeLen = 1;
431     BAsmCode[0] = 0x0d;
432   }
433   else if (DualOp("A", "H"))
434   {
435     CodeLen = 1;
436     BAsmCode[0] = 0x30;
437   }
438   else if (DualOp("A", "L"))
439   {
440     CodeLen = 1;
441     BAsmCode[0] = 0x31;
442   }
443   else
444   {
445     tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
446 
447     if ((as_strcasecmp(pArg1->Str, "A")) && (as_strcasecmp(pArg1->Str, "HL")))
448     {
449       pArg1 = &ArgStr[2];
450       pArg2 = &ArgStr[1];
451     }
452     if ((as_strcasecmp(pArg1->Str, "A")) && (as_strcasecmp(pArg1->Str, "HL"))) WrError(ErrNum_InvAddrMode);
453     else
454     {
455       DecodeAdr(pArg2, MModAbs);
456       if (AdrType != ModNone)
457       {
458         if ((!as_strcasecmp(pArg1->Str, "HL")) && (AdrVal & 3)) WrError(ErrNum_NotAligned);
459         else
460         {
461           CodeLen = 2;
462           BAsmCode[0] = 0x29 + (0x14 * Ord(!as_strcasecmp(pArg1->Str, "A")));
463           BAsmCode[1] = AdrVal;
464         }
465       }
466     }
467   }
468 }
469 
DecodeIN(Word Code)470 static void DecodeIN(Word Code)
471 {
472   UNUSED(Code);
473 
474   if (ChkArgCnt(2, 2))
475   {
476     DecodeAdr(&ArgStr[1], MModPort);
477     if (AdrType != ModNone)
478     {
479       Byte HReg = AdrVal;
480       DecodeAdr(&ArgStr[2], MModAcc | MModIHL);
481       switch (AdrType)
482       {
483         case ModAcc:
484           CodeLen = 2;
485           BAsmCode[0] = 0x3a;
486           BAsmCode[1] = (HReg & 0x0f) + (((HReg & 0x10) ^ 0x10) << 1);
487           break;
488         case ModIHL:
489           CodeLen = 2;
490           BAsmCode[0] = 0x3a;
491           BAsmCode[1] = 0x40 + (HReg & 0x0f) + (((HReg & 0x10) ^ 0x10) << 1);
492           break;
493       }
494     }
495   }
496 }
497 
DecodeOUT(Word Code)498 static void DecodeOUT(Word Code)
499 {
500   UNUSED(Code);
501 
502   if (ChkArgCnt(2, 2))
503   {
504     DecodeAdr(&ArgStr[2], MModPort);
505     if (AdrType != ModNone)
506     {
507       Byte HReg = AdrVal;
508       OpSize = 0;
509       DecodeAdr(&ArgStr[1], MModAcc | MModIHL | MModImm);
510       switch (AdrType)
511       {
512         case ModAcc:
513           CodeLen = 2;
514           BAsmCode[0] = 0x3a;
515           BAsmCode[1] = 0x80 + ((HReg & 0x10) << 1) + ((HReg & 0x0f) ^ 4);
516           break;
517         case ModIHL:
518           CodeLen = 2;
519           BAsmCode[0] = 0x3a;
520           BAsmCode[1] = 0xc0 + ((HReg & 0x10) << 1) + ((HReg & 0x0f) ^ 4);
521           break;
522         case ModImm:
523           if (HReg > 0x0f) WrError(ErrNum_InvAddrMode);
524           else
525           {
526             CodeLen = 2;
527             BAsmCode[0] = 0x2c;
528             BAsmCode[1] = (AdrVal << 4) + HReg;
529           }
530           break;
531       }
532     }
533   }
534 }
535 
DecodeOUTB(Word Code)536 static void DecodeOUTB(Word Code)
537 {
538   UNUSED(Code);
539 
540   if (!ChkArgCnt(1, 1));
541   else if (as_strcasecmp(ArgStr[1].Str, "@HL")) WrError(ErrNum_InvAddrMode);
542   else
543   {
544     CodeLen = 1;
545     BAsmCode[0] = 0x12;
546   }
547 }
548 
549 /* Arithmetik */
550 
DecodeCMPR(Word Code)551 static void DecodeCMPR(Word Code)
552 {
553   Byte HReg;
554 
555   UNUSED(Code);
556 
557   if (ChkArgCnt(2, 2))
558   {
559     DecodeAdr(&ArgStr[1], MModAcc | MModSAbs | MModH | MModL);
560     switch (AdrType)
561     {
562       case ModAcc:
563         DecodeAdr(&ArgStr[2], MModIHL | MModAbs | MModImm);
564         switch (AdrType)
565         {
566           case ModIHL:
567             CodeLen = 1;
568             BAsmCode[0] = 0x16;
569             break;
570           case ModAbs:
571             CodeLen = 2;
572             BAsmCode[0] = 0x3e;
573             BAsmCode[1] = AdrVal;
574             break;
575           case ModImm:
576             CodeLen = 1;
577             BAsmCode[0] = 0xd0 + AdrVal;
578             break;
579         }
580         break;
581       case ModSAbs:
582         OpSize = 0;
583         HReg = AdrVal;
584         DecodeAdr(&ArgStr[2], MModImm);
585         if (AdrType != ModNone)
586         {
587           CodeLen = 2;
588           BAsmCode[0] = 0x2e;
589           BAsmCode[1] = (AdrVal << 4) + HReg;
590         }
591         break;
592       case ModH:
593       case ModL:
594         HReg = AdrType;
595         DecodeAdr(&ArgStr[2], MModImm);
596         if (AdrType != ModNone)
597         {
598           CodeLen = 2;
599           BAsmCode[0] = 0x38;
600           BAsmCode[1] = 0x90 + (Ord(HReg == ModH) << 6) + AdrVal;
601         }
602         break;
603     }
604   }
605 }
606 
DecodeADD(Word Code)607 static void DecodeADD(Word Code)
608 {
609   Byte HReg;
610 
611   UNUSED(Code);
612 
613   if (ChkArgCnt(2, 2))
614   {
615     DecodeAdr(&ArgStr[1], MModAcc | MModIHL | MModSAbs | MModL | MModH);
616     switch (AdrType)
617     {
618       case ModAcc:
619         DecodeAdr(&ArgStr[2], MModIHL | MModImm);
620         switch (AdrType)
621         {
622           case ModIHL:
623             CodeLen = 1;
624             BAsmCode[0] = 0x17;
625             break;
626           case ModImm:
627             CodeLen = 2;
628             BAsmCode[0] = 0x38;
629             BAsmCode[1] = AdrVal;
630             break;
631         }
632         break;
633       case ModIHL:
634         OpSize = 0;
635         DecodeAdr(&ArgStr[2], MModImm);
636         if (AdrType != ModNone)
637         {
638           CodeLen = 2;
639           BAsmCode[0] = 0x38;
640           BAsmCode[1] = 0x40 + AdrVal;
641         }
642         break;
643       case ModSAbs:
644         HReg = AdrVal;
645         OpSize = 0;
646         DecodeAdr(&ArgStr[2], MModImm);
647         if (AdrType != ModNone)
648         {
649           CodeLen = 2;
650           BAsmCode[0] = 0x2f;
651           BAsmCode[1] = (AdrVal << 4) + HReg;
652         }
653         break;
654       case ModH:
655       case ModL:
656         HReg = Ord(AdrType == ModH);
657         DecodeAdr(&ArgStr[2], MModImm);
658         if (AdrType != ModNone)
659         {
660           CodeLen = 2;
661           BAsmCode[0] = 0x38;
662           BAsmCode[1] = 0x80 + (HReg << 6) + AdrVal;
663         }
664         break;
665     }
666   }
667 }
668 
DecodeADDC(Word Code)669 static void DecodeADDC(Word Code)
670 {
671   UNUSED(Code);
672 
673   if (!ChkArgCnt(2, 2));
674   else if ((as_strcasecmp(ArgStr[1].Str, "A")) || (as_strcasecmp(ArgStr[2].Str, "@HL"))) WrError(ErrNum_InvAddrMode);
675   else
676   {
677     CodeLen = 1;
678     BAsmCode[0] = 0x15;
679   }
680 }
681 
DecodeSUBRC(Word Code)682 static void DecodeSUBRC(Word Code)
683 {
684   UNUSED(Code);
685 
686   if (!ChkArgCnt(2, 2));
687   else if ((as_strcasecmp(ArgStr[1].Str, "A")) || (as_strcasecmp(ArgStr[2].Str, "@HL"))) WrError(ErrNum_InvAddrMode);
688   else
689   {
690     CodeLen = 1;
691     BAsmCode[0] = 0x14;
692   }
693 }
694 
DecodeSUBR(Word Code)695 static void DecodeSUBR(Word Code)
696 {
697   Byte HReg;
698 
699   UNUSED(Code);
700 
701   if (ChkArgCnt(2, 2))
702   {
703     OpSize = 0;
704     DecodeAdr(&ArgStr[2], MModImm);
705     if (AdrType != ModNone)
706     {
707       HReg = AdrVal;
708       DecodeAdr(&ArgStr[1], MModAcc | MModIHL);
709       switch (AdrType)
710       {
711         case ModAcc:
712           CodeLen = 2;
713           BAsmCode[0] = 0x38;
714           BAsmCode[1] = 0x10 + HReg;
715           break;
716         case ModIHL:
717           CodeLen = 2;
718           BAsmCode[0] = 0x38;
719           BAsmCode[1] = 0x50 + HReg;
720           break;
721       }
722     }
723   }
724 }
725 
DecodeINC_DEC(Word Code)726 static void DecodeINC_DEC(Word Code)
727 {
728   if (ChkArgCnt(1, 1))
729   {
730     DecodeAdr(&ArgStr[1], MModAcc | MModIHL | MModL);
731     switch (AdrType)
732     {
733       case ModAcc:
734         CodeLen = 1;
735         BAsmCode[0] = 0x08 + Code;
736         break;
737       case ModL:
738         CodeLen = 1;
739         BAsmCode[0] = 0x18 + Code;
740         break;
741       case ModIHL:
742         CodeLen = 1;
743         BAsmCode[0] = 0x0a + Code;
744         break;
745     }
746   }
747 }
748 
749 /* Logik */
750 
DecodeAND_OR(Word Code)751 static void DecodeAND_OR(Word Code)
752 {
753   if (ChkArgCnt(2, 2))
754   {
755     DecodeAdr(&ArgStr[1], MModAcc | MModIHL);
756     switch (AdrType)
757     {
758       case ModAcc:
759         DecodeAdr(&ArgStr[2], MModImm | MModIHL);
760         switch (AdrType)
761         {
762           case ModIHL:
763             CodeLen = 1;
764             BAsmCode[0] = 0x1e - Code;
765             break;
766           case ModImm:
767             CodeLen = 2;
768             BAsmCode[0] = 0x38;
769             BAsmCode[1] = 0x30 - (Code << 4) + AdrVal;
770             break;
771         }
772         break;
773       case ModIHL:
774         SetOpSize(0);
775         DecodeAdr(&ArgStr[2], MModImm);
776         if (AdrType != ModNone)
777         {
778           CodeLen = 2;
779           BAsmCode[0] = 0x38;
780           BAsmCode[1] = 0x70 - (Code << 4) + AdrVal;
781         }
782         break;
783     }
784   }
785 }
786 
DecodeXOR(Word Code)787 static void DecodeXOR(Word Code)
788 {
789   UNUSED(Code);
790 
791   if (!ChkArgCnt(2, 2));
792   else if ((as_strcasecmp(ArgStr[1].Str, "A")) || (as_strcasecmp(ArgStr[2].Str, "@HL"))) WrError(ErrNum_InvAddrMode);
793   else
794   {
795     CodeLen = 1;
796     BAsmCode[0] = 0x1f;
797   }
798 }
799 
DecodeROLC_RORC(Word Code)800 static void DecodeROLC_RORC(Word Code)
801 {
802   if (!ChkArgCnt(1, 2));
803   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrError(ErrNum_InvAddrMode);
804   else
805   {
806     Boolean OK;
807     Byte HReg;
808 
809     if (ArgCnt == 1)
810     {
811       HReg = 1;
812       OK = True;
813     }
814     else
815       HReg = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
816     if (OK)
817     {
818       int z;
819 
820       BAsmCode[0] = Code;
821       for (z = 1; z < HReg; z++)
822         BAsmCode[z] = BAsmCode[0];
823       CodeLen = HReg;
824       if (HReg >= 4)
825         WrError(ErrNum_Senseless);
826     }
827   }
828 }
829 
DecodeBit(Word Code)830 static void DecodeBit(Word Code)
831 {
832   Byte HReg;
833   Boolean OK;
834 
835   if (ArgCnt == 1)
836   {
837     if (!as_strcasecmp(ArgStr[1].Str, "@L"))
838     {
839       if (Memo("TESTP")) WrError(ErrNum_InvAddrMode);
840       else
841       {
842         if (Code == 2)
843           Code = 3;
844         CodeLen = 1;
845         BAsmCode[0] = 0x34 + Code;
846       }
847     }
848     else if (!as_strcasecmp(ArgStr[1].Str, "CF"))
849     {
850       if (Code < 2) WrError(ErrNum_InvAddrMode);
851       else
852       {
853         CodeLen = 1;
854         BAsmCode[0] = 10 -2 * Code;
855       }
856     }
857     else if (!as_strcasecmp(ArgStr[1].Str, "ZF"))
858     {
859       if (Code != 3) WrError(ErrNum_InvAddrMode);
860       else
861       {
862         CodeLen = 1;
863         BAsmCode[0] = 0x0e;
864       }
865     }
866     else if (!as_strcasecmp(ArgStr[1].Str, "GF"))
867     {
868       if (Code == 2) WrError(ErrNum_InvAddrMode);
869       else
870       {
871         CodeLen = 1;
872         BAsmCode[0] = (Code == 3) ? 1 : 3 - Code;
873         ChkCPU(M_CPU47C00);
874       }
875     }
876     else if ((!as_strcasecmp(ArgStr[1].Str, "DMB")) || (!as_strcasecmp(ArgStr[1].Str, "DMB0")))
877     {
878       CodeLen = 2;
879       BAsmCode[0] = 0x3b;
880       BAsmCode[1] = 0x39 + (Code << 6);
881       ChkCPU(as_strcasecmp(ArgStr[1].Str, "DMB0") ? M_CPU470C00 : M_CPU470AC00);
882     }
883     else if (!as_strcasecmp(ArgStr[1].Str, "DMB1"))
884     {
885       CodeLen = 3;
886       BAsmCode[0] = 3;
887       BAsmCode[1] = 0x3b;
888       BAsmCode[2] = 0x19 + (Code << 6);
889       ChkCPU(M_CPU470AC00);
890     }
891     else if (!as_strcasecmp(ArgStr[1].Str, "STK13"))
892     {
893       if (Code > 1) WrError(ErrNum_InvAddrMode);
894       else
895       {
896         CodeLen = 3;
897         BAsmCode[0] = 3 - Code;
898         BAsmCode[1] = 0x3a;
899         BAsmCode[2] = 0x84;
900         ChkCPU(M_CPU470AC00);
901       }
902     }
903     else
904       WrError(ErrNum_InvAddrMode);
905   }
906   else if (ArgCnt == 2)
907   {
908     if (!as_strcasecmp(ArgStr[1].Str, "IL"))
909     {
910       if (Code != 1) WrError(ErrNum_InvAddrMode);
911       else
912       {
913         HReg = EvalStrIntExpression(&ArgStr[2], UInt6, &OK);
914         if (OK)
915         {
916           CodeLen = 2;
917           BAsmCode[0] = 0x36;
918           BAsmCode[1] = 0xc0 + HReg;
919         }
920       }
921     }
922     else
923     {
924       HReg = EvalStrIntExpression(&ArgStr[2], UInt2, &OK);
925       if (OK)
926       {
927         DecodeAdr(&ArgStr[1], MModAcc | MModIHL | MModPort | MModSAbs);
928         switch (AdrType)
929         {
930           case ModAcc:
931             if (Code != 2) WrError(ErrNum_InvAddrMode);
932             else
933             {
934               CodeLen = 1;
935               BAsmCode[0] = 0x5c + HReg;
936             }
937             break;
938           case ModIHL:
939             if (Code == 3) WrError(ErrNum_InvAddrMode);
940             else
941             {
942               CodeLen = 1;
943               BAsmCode[0] = 0x50 + HReg + (Code << 2);
944             }
945             break;
946           case ModPort:
947             if (AdrVal>15) WrError(ErrNum_OverRange);
948             else
949             {
950               CodeLen = 2;
951               BAsmCode[0] = 0x3b;
952               BAsmCode[1] = (Code << 6) + (HReg << 4) + AdrVal;
953             }
954             break;
955           case ModSAbs:
956             CodeLen = 2;
957             BAsmCode[0] = 0x39;
958             BAsmCode[1] = (Code << 6) + (HReg << 4) + AdrVal;
959             break;
960         }
961       }
962     }
963   }
964   else
965     (void)ChkArgCnt(1, 2);
966 }
967 
DecodeEICLR_DICLR(Word Code)968 static void DecodeEICLR_DICLR(Word Code)
969 {
970   if (!ChkArgCnt(2, 2));
971   else if (as_strcasecmp(ArgStr[1].Str, "IL")) WrError(ErrNum_InvAddrMode);
972   else
973   {
974     Boolean OK;
975 
976     BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt6, &OK);
977     if (OK)
978     {
979       CodeLen = 2;
980       BAsmCode[0] = 0x36;
981       BAsmCode[1] += Code;
982     }
983   }
984 }
985 
986 /* Spruenge */
987 
DecodeBSS(Word Code)988 static void DecodeBSS(Word Code)
989 {
990   UNUSED(Code);
991 
992   if (ChkArgCnt(1, 1))
993   {
994     tEvalResult EvalResult;
995     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
996 
997     if (EvalResult.OK && ChkSamePage(AdrWord, EProgCounter() + 1, 6, EvalResult.Flags))
998     {
999       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1000       CodeLen = 1;
1001       BAsmCode[0] = 0x80 + (AdrWord & 0x3f);
1002     }
1003   }
1004 }
1005 
DecodeBS(Word Code)1006 static void DecodeBS(Word Code)
1007 {
1008   UNUSED(Code);
1009 
1010   if (ChkArgCnt(1, 1))
1011   {
1012     tEvalResult EvalResult;
1013     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
1014 
1015     if (EvalResult.OK && ChkSamePage(AdrWord, EProgCounter() + 2, 12, EvalResult.Flags))
1016     {
1017       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1018       CodeLen = 2;
1019       BAsmCode[0] = 0x60 + (Hi(AdrWord) & 15);
1020       BAsmCode[1] = Lo(AdrWord);
1021     }
1022   }
1023 }
1024 
DecodeBSL(Word Code)1025 static void DecodeBSL(Word Code)
1026 {
1027   UNUSED(Code);
1028 
1029   if (ChkArgCnt(1, 1))
1030   {
1031     tEvalResult EvalResult;
1032     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
1033 
1034     if (EvalResult.OK)
1035     {
1036       if (AdrWord > SegLimits[SegCode]) WrError(ErrNum_OverRange);
1037       else
1038       {
1039         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1040         CodeLen = 3;
1041         switch (AdrWord >> 12)
1042         {
1043           case 0: BAsmCode[0] = 0x02; break;
1044           case 1: BAsmCode[0] = 0x03; break;
1045           case 2: BAsmCode[0] = 0x1c; break;
1046           case 3: BAsmCode[0] = 0x01; break;
1047         }
1048         BAsmCode[1] = 0x60 + (Hi(AdrWord) & 0x0f);
1049         BAsmCode[2] = Lo(AdrWord);
1050       }
1051     }
1052   }
1053 }
1054 
DecodeB(Word Code)1055 static void DecodeB(Word Code)
1056 {
1057   UNUSED(Code);
1058 
1059   if (ChkArgCnt(1, 1))
1060   {
1061     tEvalResult EvalResult;
1062     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult),
1063          Curr = EProgCounter();
1064 
1065     if (EvalResult.OK)
1066     {
1067       if (AdrWord > SegLimits[SegCode]) WrError(ErrNum_OverRange);
1068       else
1069       {
1070         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1071         if ((AdrWord >> 6) == ((Curr + 1) >> 6))
1072         {
1073           CodeLen = 1;
1074           BAsmCode[0] = 0x80 + (AdrWord & 0x3f);
1075         }
1076         else if ((AdrWord >> 12) == ((Curr + 2) >> 12))
1077         {
1078           CodeLen = 2;
1079           BAsmCode[0] = 0x60 + (Hi(AdrWord) & 0x0f);
1080           BAsmCode[1] = Lo(AdrWord);
1081         }
1082         else
1083         {
1084           CodeLen = 3;
1085           switch (AdrWord >> 12)
1086           {
1087             case 0: BAsmCode[0] = 0x02; break;
1088             case 1: BAsmCode[0] = 0x03; break;
1089             case 2: BAsmCode[0] = 0x1c; break;
1090             case 3: BAsmCode[0] = 0x01; break;
1091           }
1092           BAsmCode[1] = 0x60 + (Hi(AdrWord) & 0x0f);
1093           BAsmCode[2] = Lo(AdrWord);
1094         }
1095       }
1096     }
1097   }
1098 }
1099 
DecodeCALLS(Word Code)1100 static void DecodeCALLS(Word Code)
1101 {
1102   UNUSED(Code);
1103 
1104   if (ChkArgCnt(1, 1))
1105   {
1106     Boolean OK;
1107     Word AdrWord;
1108     tSymbolFlags Flags;
1109 
1110     AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
1111     if (OK)
1112     {
1113       if (AdrWord == 0x86)
1114         AdrWord = 0x06;
1115       if (!mFirstPassUnknown(Flags) && ((AdrWord & 0xff87) != 6)) WrStrErrorPos(ErrNum_NotAligned, &ArgStr[1]);
1116       else
1117       {
1118         CodeLen = 1;
1119         BAsmCode[0] = (AdrWord >> 3) + 0x70;
1120       }
1121     }
1122   }
1123 }
1124 
DecodeCALL(Word Code)1125 static void DecodeCALL(Word Code)
1126 {
1127   UNUSED(Code);
1128 
1129   if (ChkArgCnt(1, 1))
1130   {
1131     tEvalResult EvalResult;
1132     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
1133 
1134     if (EvalResult.OK && ChkSamePage(AdrWord, EProgCounter(), 11, EvalResult.Flags))
1135     {
1136       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1137       CodeLen = 2;
1138       BAsmCode[0] = 0x20 + (Hi(AdrWord) & 7);
1139       BAsmCode[1] = Lo(AdrWord);
1140     }
1141   }
1142 }
1143 
DecodePORT(Word Code)1144 static void DecodePORT(Word Code)
1145 {
1146   UNUSED(Code);
1147 
1148   CodeEquate(SegIO, 0, SegLimits[SegIO]);
1149 }
1150 
1151 /*---------------------------------------------------------------------------*/
1152 
AddFixed(const char * NName,Byte NCode)1153 static void AddFixed(const char *NName, Byte NCode)
1154 {
1155   AddInstTable(InstTable, NName, NCode, DecodeFixed);
1156 }
1157 
InitFields(void)1158 static void InitFields(void)
1159 {
1160   InstTable = CreateInstTable(203);
1161   AddInstTable(InstTable, "LD", 0, DecodeLD);
1162   AddInstTable(InstTable, "LDL", 0, DecodeLDL);
1163   AddInstTable(InstTable, "LDH", 0, DecodeLDH);
1164   AddInstTable(InstTable, "ST", 0, DecodeST);
1165   AddInstTable(InstTable, "MOV", 0, DecodeMOV);
1166   AddInstTable(InstTable, "XCH", 0, DecodeXCH);
1167   AddInstTable(InstTable, "IN", 0, DecodeIN);
1168   AddInstTable(InstTable, "OUT", 0, DecodeOUT);
1169   AddInstTable(InstTable, "OUTB", 0, DecodeOUTB);
1170   AddInstTable(InstTable, "CMPR", 0, DecodeCMPR);
1171   AddInstTable(InstTable, "ADD", 0, DecodeADD);
1172   AddInstTable(InstTable, "ADDC", 0, DecodeADDC);
1173   AddInstTable(InstTable, "SUBRC", 0, DecodeSUBRC);
1174   AddInstTable(InstTable, "SUBR", 0, DecodeSUBR);
1175   AddInstTable(InstTable, "INC", 0, DecodeINC_DEC);
1176   AddInstTable(InstTable, "DEC", 1, DecodeINC_DEC);
1177   AddInstTable(InstTable, "AND", 0, DecodeAND_OR);
1178   AddInstTable(InstTable, "OR", 1, DecodeAND_OR);
1179   AddInstTable(InstTable, "XOR", 0, DecodeXOR);
1180   AddInstTable(InstTable, "ROLC", 0x05, DecodeROLC_RORC);
1181   AddInstTable(InstTable, "RORC", 0x07, DecodeROLC_RORC);
1182   AddInstTable(InstTable, "EICLR", 0x40, DecodeEICLR_DICLR);
1183   AddInstTable(InstTable, "DICLR", 0x80, DecodeEICLR_DICLR);
1184   AddInstTable(InstTable, "BSS", 0, DecodeBSS);
1185   AddInstTable(InstTable, "BS", 0, DecodeBS);
1186   AddInstTable(InstTable, "BSL", 0, DecodeBSL);
1187   AddInstTable(InstTable, "B", 0, DecodeB);
1188   AddInstTable(InstTable, "CALLS", 0, DecodeCALLS);
1189   AddInstTable(InstTable, "CALL", 0, DecodeCALL);
1190   AddInstTable(InstTable, "PORT", 0, DecodePORT);
1191 
1192   AddFixed("RET" , 0x2a);
1193   AddFixed("RETI", 0x2b);
1194   AddFixed("NOP" , 0x00);
1195 
1196   InstrZ = 0;
1197   AddInstTable(InstTable, "SET", InstrZ++, DecodeBit);
1198   AddInstTable(InstTable, "CLR", InstrZ++, DecodeBit);
1199   AddInstTable(InstTable, "TEST", InstrZ++, DecodeBit);
1200   AddInstTable(InstTable, "TESTP", InstrZ++, DecodeBit);
1201 }
1202 
DeinitFields(void)1203 static void DeinitFields(void)
1204 {
1205   DestroyInstTable(InstTable);
1206 }
1207 
1208 /*--------------------------------------------------------------------------*/
1209 
MakeCode_47C00(void)1210 static void MakeCode_47C00(void)
1211 {
1212   CodeLen = 0;
1213   DontPrint = False;
1214   OpSize = -1;
1215 
1216   /* zu ignorierendes */
1217 
1218   if (Memo(""))
1219     return;
1220 
1221   /* Pseudoanweisungen */
1222 
1223   if (DecodeIntelPseudo(False))
1224     return;
1225 
1226   if (!LookupInstTable(InstTable, OpPart.Str))
1227     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
1228 }
1229 
IsDef_47C00(void)1230 static Boolean IsDef_47C00(void)
1231 {
1232   return (Memo("PORT"));
1233 }
1234 
SwitchFrom_47C00(void)1235 static void SwitchFrom_47C00(void)
1236 {
1237   DeinitFields();
1238 }
1239 
TrueFnc(void)1240 static Boolean TrueFnc(void)
1241 {
1242   return True;
1243 }
1244 
SwitchTo_47C00(void)1245 static void SwitchTo_47C00(void)
1246 {
1247 #define ASSUME47Count (sizeof(ASSUME47s) / sizeof(*ASSUME47s))
1248   static ASSUMERec ASSUME47s[] =
1249   {
1250     { "DMB", &DMBAssume, 0, 3, 4, NULL }
1251   };
1252 
1253   TurnWords = False;
1254   ConstMode = ConstModeIntel;
1255   SetIsOccupiedFnc = TrueFnc;
1256 
1257   PCSymbol = "$";
1258   HeaderID = 0x55;
1259   NOPCode = 0x00;
1260   DivideChars = ",";
1261   HasAttrs = False;
1262 
1263   ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
1264   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
1265   Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
1266   Grans[SegIO  ] = 1; ListGrans[SegIO  ] = 1; SegInits[SegIO  ] = 0;
1267   if (MomCPU == CPU47C00)
1268   {
1269     SegLimits[SegCode] = 0xfff;
1270     SegLimits[SegData] = 0xff;
1271     SegLimits[SegIO] = 0x0f;
1272   }
1273   else if (MomCPU == CPU470C00)
1274   {
1275     SegLimits[SegCode] = 0x1fff;
1276     SegLimits[SegData] = 0x1ff;
1277     SegLimits[SegIO] = 0x1f;
1278   }
1279   else if (MomCPU == CPU470AC00)
1280   {
1281     SegLimits[SegCode] = 0x3fff;
1282     SegLimits[SegData] = 0x3ff;
1283     SegLimits[SegIO] = 0x1f;
1284   }
1285 
1286   pASSUMERecs = ASSUME47s;
1287   ASSUMERecCnt = ASSUME47Count;
1288 
1289   MakeCode = MakeCode_47C00;
1290   IsDef = IsDef_47C00;
1291   SwitchFrom = SwitchFrom_47C00;
1292   InitFields();
1293 }
1294 
InitCode_47C00(void)1295 static void InitCode_47C00(void)
1296 {
1297   DMBAssume = 0;
1298 }
1299 
code47c00_init(void)1300 void code47c00_init(void)
1301 {
1302   CPU47C00 = AddCPU("47C00", SwitchTo_47C00);
1303   CPU470C00 = AddCPU("470C00", SwitchTo_47C00);
1304   CPU470AC00 = AddCPU("470AC00", SwitchTo_47C00);
1305 
1306   AddInitPassProc(InitCode_47C00);
1307 }
1308