1 /* code48.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegeneratormodul MCS-48-Familie                                         */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include "bpemu.h"
13 #include <string.h>
14 #include <ctype.h>
15 
16 #include "nls.h"
17 #include "strutil.h"
18 #include "stringlists.h"
19 #include "asmdef.h"
20 #include "asmsub.h"
21 #include "asmpars.h"
22 #include "asmallg.h"
23 #include "asmitree.h"
24 #include "intpseudo.h"
25 #include "codevars.h"
26 #include "errmsg.h"
27 
28 #include "code48.h"
29 
30 typedef struct
31 {
32   const char *Name;
33   Byte Code;
34 } SelOrder;
35 
36 typedef enum
37 {
38   ModImm = 0,
39   ModReg = 1,
40   ModInd = 2,
41   ModAcc = 3,
42   ModNone = -1
43 } tAdrMode;
44 
45 #define MModImm (1 << ModImm)
46 #define MModReg (1 << ModReg)
47 #define MModInd (1 << ModInd)
48 #define MModAcc (1 << ModAcc)
49 
50 #define eCPUFlagCMOS (1ul << 0)
51 #define eCPUFlagSiemens (1ul << 1)
52 #define eCPUFlagDEC_DJNZ_IREG (1ul << 2)
53 #define eCPUFlagXMem (1ul << 3)
54 #define eCPUFlagUPIPort (1ul << 4)
55 #define eCPUFlagPort0 (1ul << 5)
56 #define eCPUFlagPort1 (1ul << 6)
57 #define eCPUFlagPort2 (1ul << 7)
58 #define eCPUFlagIOExpander (1ul << 8)
59 #define eCPUFlagUserFlags (1ul << 9)
60 #define eCPUFlagT0 (1ul << 10)
61 #define eCPUFlagT0CLK (1ul << 11)
62 #define eCPUFlagCondBitJmp (1ul << 12)
63 #define eCPUFlagTransferA_PSW (1ul << 13)
64 #define eCPUFlagBUS (1ul << 14)
65 #define eCPUFlagRegBanks (1ul << 15)
66 #define eCPUFlagADConv (1ul << 16)
67 #define eCPUFlagLogToPort (1ul << 17)
68 #define eCPUFlagDEC_REG (1ul << 18)
69 #define eCPUFlagMOVP3 (1ul << 19)
70 #define eCPUFlagINTLogic (1ul << 20)
71 #define eCPUFlagOKI (1ul << 21)
72 #define eCPUFlagSerial (1ul << 22)
73 #define eCPUFlag84xx (1ul << 23)
74 
75 #define MB_NOTHING 0xff
76 
77 typedef struct
78 {
79   const char *pName;
80   Word CodeSize;
81   LongWord Flags;
82 } tCPUProps;
83 
84 #define ClrCplCnt 4
85 #define SelOrderCnt 8
86 
87 static const tCPUProps *pCurrCPUProps;
88 static tAdrMode AdrMode;
89 static Byte AdrVal;
90 static const char **ClrCplVals;
91 static Byte *ClrCplCodes;
92 static SelOrder *SelOrders;
93 static LongInt Reg_MB;
94 
95 /****************************************************************************/
96 
97 /*!------------------------------------------------------------------------
98  * \fn     DecodeRegCore(const char *pAsc, tRegInt *pValue, tSymbolSize *pSize)
99  * \brief  check whether argument describes a CPU register
100  * \param  pAsc argument
101  * \param  pValue resulting register # if yes
102  * \param  pSize resulting register size if yes
103  * \return true if yes
104  * ------------------------------------------------------------------------ */
105 
DecodeRegCore(const char * pAsc,tRegInt * pValue,tSymbolSize * pSize)106 static Boolean DecodeRegCore(const char *pAsc, tRegInt *pValue, tSymbolSize *pSize)
107 {
108   if ((strlen(pAsc) != 2)
109    || (as_toupper(pAsc[0]) != 'R')
110    || (!isdigit(pAsc[1])))
111     return False;
112 
113   *pValue = pAsc[1] - '0';
114   *pSize = eSymbolSize8Bit;
115   return (*pValue <= 7);
116 }
117 
118 /*!------------------------------------------------------------------------
119  * \fn     DissectReg_48(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
120  * \brief  dissect register symbols - 8048 variant
121  * \param  pDest destination buffer
122  * \param  DestSize destination buffer size
123  * \param  Value numeric register value
124  * \param  InpSize register size
125  * ------------------------------------------------------------------------ */
126 
DissectReg_48(char * pDest,size_t DestSize,tRegInt Value,tSymbolSize InpSize)127 static void DissectReg_48(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
128 {
129   switch (InpSize)
130   {
131     case eSymbolSize8Bit:
132       as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
133       break;
134     default:
135       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
136   }
137 }
138 
139 /*!------------------------------------------------------------------------
140  * \fn     DecodeReg(const tStrComp *pArg, Byte *pValue, Boolean MustBeReg)
141  * \brief  check whether argument is a CPU register or user-defined register alias
142  * \param  pArg argument
143  * \param  pValue resulting register # if yes
144  * \param  MustBeReg expect register at this arg?
145  * \return eIsReg/eIsNoReg/eRegAbort
146  * ------------------------------------------------------------------------ */
147 
DecodeReg(const tStrComp * pArg,Byte * pValue,Boolean MustBeReg)148 static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pValue, Boolean MustBeReg)
149 {
150   tSymbolSize Size;
151   tRegDescr RegDescr;
152   tEvalResult EvalResult;
153   tRegEvalResult RegEvalResult;
154 
155   if (DecodeRegCore(pArg->Str, &RegDescr.Reg, &Size))
156   {
157     *pValue = RegDescr.Reg;
158     return eIsReg;
159   }
160 
161   RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
162   *pValue = RegDescr.Reg;
163   return RegEvalResult;
164 }
165 
IsPort(const char * pArg,Word PortMask,Byte * pPortNum)166 static Boolean IsPort(const char *pArg, Word PortMask, Byte *pPortNum)
167 {
168   if (!as_strcasecmp(pArg, "BUS"))
169     *pPortNum = 8;
170   else if ((strlen(pArg) == 2)
171         && (as_toupper(pArg[0]) == 'P')
172         && isdigit(pArg[1]))
173     *pPortNum = pArg[1] - '0';
174   else
175     return False;
176 
177   return !!(PortMask & (1 << *pPortNum));
178 }
179 
IsSerialPort(const char * pArg,Word PortMask,Byte * pPortNum)180 static Boolean IsSerialPort(const char *pArg, Word PortMask, Byte *pPortNum)
181 {
182   if ((strlen(pArg) == 2)
183    && (as_toupper(pArg[0]) == 'S')
184    && isdigit(pArg[1]))
185     *pPortNum = pArg[1] - '0';
186   else
187     return False;
188 
189   return !!(PortMask & (1 << *pPortNum));
190 }
191 
DecodeAdr(const tStrComp * pArg,unsigned Mask)192 static tAdrMode DecodeAdr(const tStrComp *pArg, unsigned Mask)
193 {
194   Boolean OK;
195 
196   AdrMode = ModNone;
197 
198   if (*pArg->Str == '\0') return ModNone;
199 
200   if (!as_strcasecmp(pArg->Str, "A"))
201   {
202     AdrMode = ModAcc;
203     goto found;
204   }
205 
206   if (*pArg->Str == '#')
207   {
208     AdrVal = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK);
209     if (OK)
210     {
211       AdrMode = ModImm;
212       BAsmCode[1] = AdrVal;
213       goto found;
214     }
215   }
216 
217   switch (DecodeReg(pArg, &AdrVal, False))
218   {
219     case eIsReg:
220       AdrMode = ModReg;
221       goto found;
222     case eRegAbort:
223       return ModNone;
224     default:
225       break;
226   }
227 
228   if (*pArg->Str == '@')
229   {
230     tStrComp Arg;
231 
232     StrCompRefRight(&Arg, pArg, 1);
233     if (!DecodeReg(&Arg, &AdrVal, True))
234       return ModNone;
235     if (AdrVal > 1)
236     {
237       WrStrErrorPos(ErrNum_InvReg, &Arg);
238       return ModNone;
239     }
240     AdrMode = ModInd;
241     goto found;
242   }
243 
244   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
245 
246 found:
247   if ((AdrMode != ModNone) && !(Mask & (1 << AdrMode)))
248   {
249     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
250      AdrMode= ModNone;
251   }
252   return AdrMode;
253 }
254 
ChkCPUFlags(LongWord CPUFlags)255 static Boolean ChkCPUFlags(LongWord CPUFlags)
256 {
257   if (pCurrCPUProps->Flags & CPUFlags)
258     return True;
259   WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
260   return False;
261 }
262 
AChkCPUFlags(LongWord CPUFlags,const tStrComp * pArg)263 static Boolean AChkCPUFlags(LongWord CPUFlags, const tStrComp *pArg)
264 {
265   if (pCurrCPUProps->Flags & CPUFlags)
266     return True;
267   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
268   return False;
269 }
270 
ChkPx(Byte PortNum,const tStrComp * pArg)271 static void ChkPx(Byte PortNum, const tStrComp *pArg)
272 {
273   if (!(pCurrCPUProps->Flags & (eCPUFlagPort0 << PortNum)))
274   {
275     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
276     CodeLen = 0;
277   }
278 }
279 
IsIReg3(const tStrComp * pArg)280 static Boolean IsIReg3(const tStrComp *pArg)
281 {
282   tStrComp Arg;
283   Byte RegNum;
284 
285   if (*pArg->Str != '@')
286     return False;
287   StrCompRefRight(&Arg, pArg, 1);
288   if (!DecodeReg(&Arg, &RegNum, True))
289     return False;
290   if (RegNum != 3)
291   {
292     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
293     return False;
294   }
295   return True;
296 }
297 
298 /****************************************************************************/
299 
DecodeADD_ADDC(Word Code)300 static void DecodeADD_ADDC(Word Code)
301 {
302   if (!ChkArgCnt(2, 2));
303   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
304   else
305   {
306     switch (DecodeAdr(&ArgStr[2], MModImm | MModReg | MModInd))
307     {
308       case ModImm:
309         CodeLen = 2;
310         BAsmCode[0] = Code + 0x03;
311         break;
312       case ModReg:
313         CodeLen = 1;
314         BAsmCode[0] = Code + 0x68 + AdrVal;
315         break;
316       case ModInd:
317         CodeLen = 1;
318         BAsmCode[0] = Code + 0x60 + AdrVal;
319         break;
320       default:
321         break;
322     }
323   }
324 }
325 
DecodeANL_ORL_XRL(Word Code)326 static void DecodeANL_ORL_XRL(Word Code)
327 {
328   Byte PortNum;
329   Word PortMask = 0x06;
330 
331   if (pCurrCPUProps->Flags & eCPUFlagBUS)
332     PortMask |= 0x100;
333   if (pCurrCPUProps->Flags & eCPUFlag84xx)
334     PortMask |= 0x01;
335 
336   if (!ChkArgCnt(2, 2));
337   else if (!as_strcasecmp(ArgStr[1].Str, "A"))
338   {
339     switch (DecodeAdr(&ArgStr[2], MModImm | MModReg | MModInd))
340     {
341       case ModImm:
342         CodeLen = 2;
343         BAsmCode[0] = Code + 0x43;
344         break;
345       case ModReg:
346         CodeLen = 1;
347         BAsmCode[0] = Code + 0x48 + AdrVal;
348         break;
349       case ModInd:
350         CodeLen = 1;
351         BAsmCode[0] = Code + 0x40 + AdrVal;
352         break;
353       default:
354         break;
355     }
356   }
357   else if (IsPort(ArgStr[1].Str, PortMask, &PortNum))
358   {
359     if (Code == 0x90) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]); /* no XRL to ports */
360     else if (AChkCPUFlags(eCPUFlagLogToPort, &ArgStr[1]))
361     {
362       if (DecodeAdr(&ArgStr[2], MModImm) == ModImm)
363       {
364         CodeLen = 2;
365         BAsmCode[0] = Code + 0x88 + (PortNum & 3);
366         if (PortNum)
367           ChkPx(PortNum, &ArgStr[1]);
368       }
369     }
370   }
371   else
372     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
373 }
374 
DecodeCALL_JMP(Word Code)375 static void DecodeCALL_JMP(Word Code)
376 {
377   if (!ChkArgCnt(1, 1));
378   else if ((EProgCounter() & 0x7fe) == 0x7fe) WrError(ErrNum_NotOnThisAddress);
379   else
380   {
381     tEvalResult EvalResult;
382     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
383 
384     if (EvalResult.OK)
385     {
386       if (AdrWord > SegLimits[SegCode]) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
387       else
388       {
389         Word DestBank = (AdrWord >> 11) & 3,
390              CurrBank = (EProgCounter() >> 11) & 3;
391 
392         if (Reg_MB == MB_NOTHING)
393         {
394           if (CurrBank != DestBank)
395           {
396             BAsmCode[0] = SelOrders[DestBank].Code;
397             CodeLen = 1;
398           }
399         }
400         else if ((DestBank != Reg_MB) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags))
401           WrStrErrorPos(ErrNum_InAccPage, &ArgStr[1]);
402         BAsmCode[CodeLen + 1] = AdrWord & 0xff;
403         BAsmCode[CodeLen] = Code + ((AdrWord & 0x700) >> 3);
404         CodeLen += 2;
405         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
406       }
407     }
408   }
409 }
410 
DecodeCLR_CPL(Word Code)411 static void DecodeCLR_CPL(Word Code)
412 {
413   if (!ChkArgCnt(1, 1));
414   else
415   {
416     int z = 0;
417     Boolean OK = False;
418 
419     NLS_UpString(ArgStr[1].Str);
420     do
421     {
422       if (!strcmp(ClrCplVals[z], ArgStr[1].Str))
423       {
424         if ((*ArgStr[1].Str == 'F') && !(pCurrCPUProps->Flags & eCPUFlagUserFlags)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
425         else
426         {
427           CodeLen = 1;
428           BAsmCode[0] = ClrCplCodes[z];
429           OK = True;
430         }
431       }
432       z++;
433     }
434     while ((z < ClrCplCnt) && (CodeLen != 1));
435     if (!OK)
436       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
437     else
438       BAsmCode[0] += Code;
439   }
440 }
441 
DecodeAcc(Word Code)442 static void DecodeAcc(Word Code)
443 {
444   if (!ChkArgCnt(1, 1));
445   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
446   else
447   {
448     CodeLen = 1;
449     BAsmCode[0] = Code;
450   }
451 }
452 
DecodeDEC(Word Code)453 static void DecodeDEC(Word Code)
454 {
455   UNUSED(Code);
456 
457   if (!ChkArgCnt(1, 1));
458   else
459   {
460     switch (DecodeAdr(&ArgStr[1], MModAcc | MModReg | MModInd))
461     {
462       case ModAcc:
463         CodeLen = 1;
464         BAsmCode[0] = 0x07;
465         break;
466       case ModReg:
467         if (AChkCPUFlags(eCPUFlagDEC_REG, &ArgStr[1]))
468         {
469           CodeLen = 1;
470           BAsmCode[0] = 0xc8 + AdrVal;
471         }
472         break;
473       case ModInd:
474         if (AChkCPUFlags(eCPUFlagDEC_DJNZ_IREG, &ArgStr[1]))
475         {
476           CodeLen = 1;
477           BAsmCode[0] = 0xc0 | AdrVal;
478         }
479         break;
480       default:
481         break;
482     }
483   }
484 }
485 
DecodeDIS_EN(Word Code)486 static void DecodeDIS_EN(Word Code)
487 {
488   if (ChkArgCnt(1, 1))
489   {
490     NLS_UpString(ArgStr[1].Str);
491     if (!strcmp(ArgStr[1].Str, "I"))
492     {
493       if (AChkCPUFlags(eCPUFlagINTLogic, &ArgStr[1]))
494       {
495         CodeLen = 1;
496         BAsmCode[0] = Code + 0x05;
497       }
498     }
499     else if (!strcmp(ArgStr[1].Str, "TCNTI"))
500     {
501       if (AChkCPUFlags(eCPUFlagINTLogic, &ArgStr[1]))
502       {
503         CodeLen = 1;
504         BAsmCode[0] = Code + 0x25;
505       }
506     }
507     else if (!strcmp(ArgStr[1].Str, "SI"))
508     {
509       if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[1]))
510       {
511         CodeLen = 1;
512         BAsmCode[0] = Code + 0x85;
513       }
514     }
515     else if ((Memo("EN")) && (!strcmp(ArgStr[1].Str, "DMA")))
516     {
517       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
518       {
519         BAsmCode[0] = Code + 0xe5;
520         CodeLen = 1;
521       }
522     }
523     else if ((Memo("EN")) && (!strcmp(ArgStr[1].Str, "FLAGS")))
524     {
525       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
526       {
527         BAsmCode[0] = Code + 0xf5;
528         CodeLen = 1;
529       }
530     }
531     else
532       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
533   }
534 }
535 
DecodeDJNZ(Word Code)536 static void DecodeDJNZ(Word Code)
537 {
538   UNUSED(Code);
539 
540   if (!ChkArgCnt(2, 2));
541   else
542   {
543     switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
544     {
545       case ModReg:
546         CodeLen = 1;
547         BAsmCode[0] = 0xe8 + AdrVal;
548         break;
549       case ModInd:
550         if (AChkCPUFlags(eCPUFlagDEC_DJNZ_IREG, &ArgStr[1]))
551         {
552           CodeLen = 1;
553           BAsmCode[0] = 0xe0 + AdrVal;
554         }
555         break;
556       default:
557         break;
558     }
559     if (CodeLen > 0)
560     {
561       Boolean OK;
562       Word AdrWord;
563       tSymbolFlags Flags;
564 
565       AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], Int16, &OK, &Flags);
566       if (OK)
567       {
568         if (ChkSamePage(EProgCounter() + CodeLen, AdrWord, 8, Flags))
569           BAsmCode[CodeLen++] = AdrWord & 0xff;
570       }
571     }
572   }
573 }
574 
DecodeENT0(Word Code)575 static void DecodeENT0(Word Code)
576 {
577   UNUSED(Code);
578 
579   if (ChkArgCnt(1, 1) && ChkCPUFlags(eCPUFlagT0CLK))
580   {
581     if (as_strcasecmp(ArgStr[1].Str, "CLK")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
582     else
583     {
584       CodeLen = 1;
585       BAsmCode[0] = 0x75;
586     }
587   }
588 }
589 
DecodeINC(Word Code)590 static void DecodeINC(Word Code)
591 {
592   UNUSED(Code);
593 
594   if (!ChkArgCnt(1, 1));
595   else
596   {
597     switch (DecodeAdr(&ArgStr[1], MModAcc | MModReg | MModInd))
598     {
599       case ModAcc:
600         CodeLen = 1;
601         BAsmCode[0] = 0x17;
602         break;
603       case ModReg:
604         CodeLen = 1;
605         BAsmCode[0] = 0x18 + AdrVal;
606         break;
607       case ModInd:
608         CodeLen = 1;
609         BAsmCode[0] = 0x10 + AdrVal;
610         break;
611       default:
612         break;
613     }
614   }
615 }
616 
DecodeIN(Word Code)617 static void DecodeIN(Word Code)
618 {
619   Byte PortNum;
620 
621   UNUSED(Code);
622 
623   if (!ChkArgCnt(2, 2));
624   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
625   else if (!as_strcasecmp(ArgStr[2].Str, "DBB"))
626   {
627     if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[2]))
628     {
629       CodeLen = 1;
630       BAsmCode[0] = 0x22;
631     }
632   }
633   else if (!IsPort(ArgStr[2].Str, 0x07, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
634   else
635   {
636     CodeLen = 1;
637     BAsmCode[0] = 0x08 + PortNum;
638     ChkPx(PortNum, &ArgStr[2]);
639   }
640 }
641 
DecodeINS(Word Code)642 static void DecodeINS(Word Code)
643 {
644   UNUSED(Code);
645 
646   if (!ChkArgCnt(2, 2));
647   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
648   else if (as_strcasecmp(ArgStr[2].Str, "BUS")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
649   else if (AChkCPUFlags(eCPUFlagBUS, &ArgStr[2]))
650   {
651     CodeLen = 1;
652     BAsmCode[0] = 0x08;
653   }
654 }
655 
DecodeJMPP(Word Code)656 static void DecodeJMPP(Word Code)
657 {
658   UNUSED(Code);
659 
660   if (!ChkArgCnt(1, 1));
661   else if (as_strcasecmp(ArgStr[1].Str, "@A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
662   else
663   {
664     CodeLen = 1;
665     BAsmCode[0] = 0xb3;
666   }
667 }
668 
DecodeCond(Word Code)669 static void DecodeCond(Word Code)
670 {
671   if (ChkArgCnt(1, 1))
672   {
673     tEvalResult EvalResult;
674     Word AdrWord;
675 
676     AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &EvalResult);
677     if (EvalResult.OK && ChkSamePage(EProgCounter() + 1, AdrWord, 8, EvalResult.Flags))
678     {
679       CodeLen = 2;
680       BAsmCode[0] = Code;
681       BAsmCode[1] = AdrWord & 0xff;
682       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
683     }
684   }
685 }
686 
DecodeJB(Word Code)687 static void DecodeJB(Word Code)
688 {
689   UNUSED(Code);
690 
691   if (ChkArgCnt(2, 2) && ChkCPUFlags(eCPUFlagCondBitJmp))
692   {
693     Boolean OK;
694     AdrVal = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
695     if (OK)
696     {
697       Word AdrWord;
698       tSymbolFlags Flags;
699 
700       AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt12, &OK, &Flags);
701       if (OK && ChkSamePage(EProgCounter() + 1, AdrWord, 8, Flags))
702       {
703         CodeLen = 2;
704         BAsmCode[0] = 0x12 + (AdrVal << 5);
705         BAsmCode[1] = AdrWord & 0xff;
706       }
707     }
708   }
709 }
710 
DecodeMOV(Word Code)711 static void DecodeMOV(Word Code)
712 {
713   Byte PortNum;
714 
715   UNUSED(Code);
716 
717   if (!ChkArgCnt(2, 2));
718   else if (!as_strcasecmp(ArgStr[1].Str, "A"))
719   {
720     if (!as_strcasecmp(ArgStr[2].Str, "T"))
721     {
722       CodeLen = 1;
723       BAsmCode[0] = 0x42;
724     }
725     else if (IsPort(ArgStr[2].Str, 0x06, &PortNum))
726     {
727       if (AChkCPUFlags(eCPUFlagOKI, &ArgStr[2]))
728       {
729         CodeLen = 1;
730         BAsmCode[0] = 0x53 + (PortNum << 4);
731       }
732     }
733     else if (!as_strcasecmp(ArgStr[2].Str, "PSW"))
734     {
735       if (AChkCPUFlags(eCPUFlagTransferA_PSW, &ArgStr[2]))
736       {
737         CodeLen = 1;
738         BAsmCode[0] = 0xc7;
739       }
740     }
741     else if (IsSerialPort(ArgStr[2].Str, 0x03, &PortNum))
742     {
743       if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[2]))
744       {
745         CodeLen = 1;
746         BAsmCode[0] = 0x0c + PortNum;
747       }
748     }
749     else
750     {
751        switch (DecodeAdr(&ArgStr[2], MModReg | MModInd | MModImm))
752        {
753          case ModReg:
754            CodeLen = 1;
755            BAsmCode[0] = 0xf8 + AdrVal;
756            break;
757          case ModInd:
758            CodeLen = 1;
759            BAsmCode[0] = 0xf0 + AdrVal;
760            break;
761          case ModImm:
762            CodeLen = 2;
763            BAsmCode[0] = 0x23;
764            break;
765          default:
766            break;
767        }
768     }
769   }
770   else if (IsPort(ArgStr[1].Str, 0x02, &PortNum))
771   {
772     if (IsIReg3(&ArgStr[2]))
773     {
774       if (AChkCPUFlags(eCPUFlagOKI, &ArgStr[1]))
775       {
776         CodeLen = 1;
777         BAsmCode[0] = 0xe3 | (PortNum << 4);
778       }
779     }
780   }
781   else if (IsSerialPort(ArgStr[1].Str, 0x07, &PortNum))
782   {
783     if (AChkCPUFlags(eCPUFlagSerial, &ArgStr[1]))
784     {
785       switch (DecodeAdr(&ArgStr[2], MModAcc | MModImm))
786       {
787         case ModAcc:
788           CodeLen = 1;
789           BAsmCode[0] = 0x3c + PortNum;
790           break;
791         case ModImm:
792           CodeLen = 2;
793           BAsmCode[0] = 0x9c + PortNum;
794           break;
795         default:
796           break;
797       }
798     }
799   }
800   else if (!as_strcasecmp(ArgStr[2].Str, "A"))
801   {
802     if (!as_strcasecmp(ArgStr[1].Str, "STS"))
803     {
804       if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
805       {
806         CodeLen = 1;
807         BAsmCode[0] = 0x90;
808       }
809     }
810     else if (!as_strcasecmp(ArgStr[1].Str, "T"))
811     {
812       CodeLen = 1;
813       BAsmCode[0] = 0x62;
814     }
815     else if (!as_strcasecmp(ArgStr[1].Str, "PSW"))
816     {
817       if (AChkCPUFlags(eCPUFlagTransferA_PSW, &ArgStr[1]))
818       {
819         CodeLen = 1;
820         BAsmCode[0] = 0xd7;
821       }
822     }
823     else
824     {
825       switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
826       {
827         case ModReg:
828           CodeLen = 1;
829           BAsmCode[0] = 0xa8 + AdrVal;
830           break;
831         case ModInd:
832           CodeLen = 1;
833           BAsmCode[0] = 0xa0 + AdrVal;
834           break;
835         default:
836           break;
837       }
838     }
839   }
840   else if (*ArgStr[2].Str == '#')
841   {
842     Boolean OK;
843     Word AdrWord = EvalStrIntExpressionOffs(&ArgStr[2], 1, Int8, &OK);
844     if (OK)
845     {
846       switch (DecodeAdr(&ArgStr[1], MModReg | MModInd))
847       {
848         case ModReg:
849           CodeLen = 2;
850           BAsmCode[0] = 0xb8 + AdrVal;
851           BAsmCode[1] = AdrWord;
852           break;
853         case ModInd:
854           CodeLen = 2;
855           BAsmCode[0] = 0xb0 + AdrVal;
856           BAsmCode[1] = AdrWord;
857           break;
858         default:
859           break;
860       }
861     }
862   }
863   else
864     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
865 }
866 
DecodeANLD_ORLD_MOVD(Word Code)867 static void DecodeANLD_ORLD_MOVD(Word Code)
868 {
869   Byte PortNum;
870 
871   if (ChkArgCnt(2, 2) && ChkCPUFlags(eCPUFlagIOExpander))
872   {
873     const tStrComp *pArg1 = &ArgStr[1],
874                    *pArg2 = &ArgStr[2];
875 
876     if ((Code == 0x3c) && (!as_strcasecmp(ArgStr[1].Str, "A"))) /* MOVD */
877     {
878       pArg1 = &ArgStr[2];
879       pArg2 = &ArgStr[1];
880       Code = 0x0c;
881     }
882     if (as_strcasecmp(pArg2->Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
883     else if (!IsPort(pArg1->Str, 0xf0, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
884     else
885     {
886       PortNum -= 4;
887 
888       if ((PortNum == 3) && (pCurrCPUProps->Flags & eCPUFlagSiemens)) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
889       else
890       {
891         CodeLen = 1;
892         BAsmCode[0] = Code + PortNum;
893       }
894     }
895   }
896 }
897 
DecodeMOVP_MOVP3(Word Code)898 static void DecodeMOVP_MOVP3(Word Code)
899 {
900   if (!ChkArgCnt(2, 2));
901   else if ((Code == 0xe3) && !ChkCPUFlags(eCPUFlagMOVP3));
902   else if (as_strcasecmp(ArgStr[1].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
903   else if (as_strcasecmp(ArgStr[2].Str, "@A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
904   else
905   {
906     CodeLen = 1;
907     BAsmCode[0] = Code;
908   }
909 }
910 
DecodeMOVP1(Word Code)911 static void DecodeMOVP1(Word Code)
912 {
913   UNUSED(Code);
914 
915   if (!ChkArgCnt(2, 2));
916   else if (!ChkCPUFlags(eCPUFlagOKI));
917   else if (as_strcasecmp(ArgStr[1].Str, "P")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
918   else if (IsIReg3(&ArgStr[2]))
919   {
920     CodeLen = 1;
921     BAsmCode[0] = 0xc3;
922   }
923 }
924 
DecodeMOVX(Word Code)925 static void DecodeMOVX(Word Code)
926 {
927   UNUSED(Code);
928 
929   if (ChkArgCnt(2, 2)
930    && ChkCPUFlags(eCPUFlagXMem))
931   {
932     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
933     Byte Code = 0x80;
934 
935     if (!as_strcasecmp(pArg2->Str, "A"))
936     {
937       pArg2 = &ArgStr[1];
938       pArg1 = &ArgStr[2];
939       Code += 0x10;
940     }
941     if (as_strcasecmp(pArg1->Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
942     else
943     {
944       if (DecodeAdr(pArg2, MModInd) == ModInd)
945       {
946         CodeLen = 1;
947         BAsmCode[0] = Code + AdrVal;
948       }
949     }
950   }
951 }
952 
DecodeNOP(Word Code)953 static void DecodeNOP(Word Code)
954 {
955   UNUSED(Code);
956 
957   if (!ChkArgCnt(0, 0));
958   else
959   {
960     CodeLen = 1;
961     BAsmCode[0] = 0x00;
962   }
963 }
964 
DecodeOUT(Word Code)965 static void DecodeOUT(Word Code)
966 {
967   UNUSED(Code);
968 
969   if (!ChkArgCnt(2, 2));
970   else if (as_strcasecmp(ArgStr[1].Str, "DBB")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
971   else if (as_strcasecmp(ArgStr[2].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
972   else if (AChkCPUFlags(eCPUFlagUPIPort, &ArgStr[1]))
973   {
974     BAsmCode[0] = 0x02;
975     CodeLen = 1;
976   }
977 }
978 
DecodeOUTL(Word Code)979 static void DecodeOUTL(Word Code)
980 {
981   UNUSED(Code);
982 
983   NLS_UpString(ArgStr[1].Str);
984   if (!ChkArgCnt(2, 2));
985   else
986   {
987     Word PortMask = 0x07;
988     Byte PortNum;
989 
990     if (pCurrCPUProps->Flags & eCPUFlagBUS)
991       PortMask |= 0x100;
992     if (as_strcasecmp(ArgStr[2].Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
993     else if (!IsPort(ArgStr[1].Str, PortMask, &PortNum)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
994     else if (PortNum == 8)
995     {
996       CodeLen = 1;
997       BAsmCode[0] = 0x02;
998     }
999     else
1000     {
1001       CodeLen = 1;
1002       BAsmCode[0] = PortNum ? (0x38 + PortNum) : 0x90;
1003       ChkPx(PortNum, &ArgStr[1]);
1004     }
1005   }
1006 }
1007 
DecodeRET_RETR(Word Code)1008 static void DecodeRET_RETR(Word Code)
1009 {
1010   if (ChkArgCnt(0, 0))
1011   {
1012     /* RETR not present if no interrupts at all (8021), or replaced by RETI (8022) */
1013     if ((Code == 0x93) && (!(pCurrCPUProps->Flags & eCPUFlagINTLogic) || (pCurrCPUProps->Flags & eCPUFlagADConv))) WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
1014     else
1015     {
1016       CodeLen = 1;
1017       BAsmCode[0] = Code;
1018     }
1019   }
1020 }
1021 
DecodeSEL(Word Code)1022 static void DecodeSEL(Word Code)
1023 {
1024   UNUSED(Code);
1025 
1026   if (ChkArgCnt(1, 1))
1027   {
1028     Boolean OK = False;
1029     int z;
1030 
1031     NLS_UpString(ArgStr[1].Str);
1032     for (z = 0; z < SelOrderCnt; z++)
1033       if (!strcmp(ArgStr[1].Str, SelOrders[z].Name))
1034       {
1035         /* SEL MBx not allowed if program memory cannot be larger than 2K.
1036            Similar is true for the Philips-specific MB2/MB3 arguments if
1037            less than 6K/8K ROM is present: */
1038 
1039         if (!strncmp(SelOrders[z].Name, "MB", 2) && (pCurrCPUProps->CodeSize <= 0x7ff));
1040         else if (!strcmp(SelOrders[z].Name, "MB2") && (pCurrCPUProps->CodeSize <= 0xfff));
1041         else if (!strcmp(SelOrders[z].Name, "MB32") && (pCurrCPUProps->CodeSize <= 0x17ff));
1042 
1043         else if (!strncmp(SelOrders[z].Name, "RB", 2) && !(pCurrCPUProps->Flags & eCPUFlagRegBanks));
1044 
1045         else if (!strncmp(SelOrders[z].Name, "AN", 2) && !(pCurrCPUProps->Flags & eCPUFlagADConv));
1046 
1047         else
1048         {
1049           CodeLen = 1;
1050           BAsmCode[0] = SelOrders[z].Code;
1051           OK = True;
1052         }
1053       }
1054     if (!OK)
1055       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1056   }
1057 }
1058 
DecodeSTOP(Word Code)1059 static void DecodeSTOP(Word Code)
1060 {
1061   UNUSED(Code);
1062 
1063   if (!ChkArgCnt(1, 1));
1064   else if (as_strcasecmp(ArgStr[1].Str, "TCNT")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1065   else
1066   {
1067     CodeLen = 1;
1068     BAsmCode[0] = 0x65;
1069   }
1070 }
1071 
DecodeSTRT(Word Code)1072 static void DecodeSTRT(Word Code)
1073 {
1074   UNUSED(Code);
1075 
1076   if (!ChkArgCnt(1, 1));
1077   else
1078   {
1079     NLS_UpString(ArgStr[1].Str);
1080     if (!strcmp(ArgStr[1].Str, "CNT"))
1081     {
1082       CodeLen = 1;
1083       BAsmCode[0] = 0x45;
1084     }
1085     else if (!strcmp(ArgStr[1].Str, "T"))
1086     {
1087       CodeLen = 1;
1088       BAsmCode[0] = 0x55;
1089     }
1090     else
1091       WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1092   }
1093 }
1094 
DecodeXCH(Word Code)1095 static void DecodeXCH(Word Code)
1096 {
1097   UNUSED(Code);
1098 
1099   if (!ChkArgCnt(2, 2));
1100   else
1101   {
1102     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
1103 
1104     if (!as_strcasecmp(pArg2->Str, "A"))
1105     {
1106       pArg2 = &ArgStr[1];
1107       pArg1 = &ArgStr[2];
1108     }
1109     if (as_strcasecmp(pArg1->Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
1110     else
1111     {
1112       switch (DecodeAdr(pArg2, MModReg | MModInd))
1113       {
1114         case ModReg:
1115           CodeLen = 1;
1116           BAsmCode[0] = 0x28 + AdrVal;
1117           break;
1118         case ModInd:
1119           CodeLen = 1;
1120           BAsmCode[0] = 0x20 + AdrVal;
1121           break;
1122         default:
1123           break;
1124       }
1125     }
1126   }
1127 }
1128 
DecodeXCHD(Word Code)1129 static void DecodeXCHD(Word Code)
1130 {
1131   UNUSED(Code);
1132 
1133   if (!ChkArgCnt(2, 2));
1134   else
1135   {
1136     const tStrComp *pArg1 = &ArgStr[1], *pArg2 = &ArgStr[2];
1137 
1138     if (!as_strcasecmp(pArg2->Str, "A"))
1139     {
1140       pArg2 = &ArgStr[1];
1141       pArg1 = &ArgStr[2];
1142     }
1143     if (as_strcasecmp(pArg1->Str, "A")) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
1144     else
1145     {
1146       if (DecodeAdr(pArg2, MModInd) == ModInd)
1147       {
1148         CodeLen = 1;
1149         BAsmCode[0] = 0x30 + AdrVal;
1150       }
1151     }
1152   }
1153 }
1154 
DecodeRAD(Word Code)1155 static void DecodeRAD(Word Code)
1156 {
1157   UNUSED(Code);
1158 
1159   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagADConv))
1160   {
1161     CodeLen = 1;
1162     BAsmCode[0] = 0x80;
1163   }
1164 }
1165 
DecodeRETI(Word Code)1166 static void DecodeRETI(Word Code)
1167 {
1168   UNUSED(Code);
1169 
1170   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagADConv)) /* check for 8022 */
1171   {
1172     CodeLen = 1;
1173     BAsmCode[0] = 0x93;
1174   }
1175 }
1176 
DecodeIDL_HALT(Word Code)1177 static void DecodeIDL_HALT(Word Code)
1178 {
1179   UNUSED(Code);
1180 
1181   if (ChkArgCnt(0, 0)
1182    && ChkCPUFlags(eCPUFlagCMOS))
1183   {
1184     CodeLen = 1;
1185     BAsmCode[0] = (pCurrCPUProps->Flags & eCPUFlagSiemens) ? 0xf3 : 0x01;
1186   }
1187 }
1188 
DecodeOKIFixed(Word Code)1189 static void DecodeOKIFixed(Word Code)
1190 {
1191   if (ChkArgCnt(0, 0) && ChkCPUFlags(eCPUFlagOKI))
1192   {
1193     CodeLen = 1;
1194     BAsmCode[0] = Code;
1195   }
1196 }
1197 
1198 /****************************************************************************/
1199 
AddAcc(const char * Name,Byte Code)1200 static void AddAcc(const char *Name, Byte Code)
1201 {
1202   AddInstTable(InstTable, Name, Code, DecodeAcc);
1203 }
1204 
AddCond(const char * Name,Byte Code)1205 static void AddCond(const char *Name, Byte Code)
1206 {
1207   AddInstTable(InstTable, Name, Code, DecodeCond);
1208 }
1209 
AddSel(const char * Name,Byte Code)1210 static void AddSel(const char *Name, Byte Code)
1211 {
1212   if (InstrZ == SelOrderCnt) exit(255);
1213   SelOrders[InstrZ].Name = Name;
1214   SelOrders[InstrZ].Code = Code;
1215   InstrZ++;
1216 }
1217 
InitFields(void)1218 static void InitFields(void)
1219 {
1220   InstTable = CreateInstTable(203);
1221   AddInstTable(InstTable, "ADD", 0x00, DecodeADD_ADDC);
1222   AddInstTable(InstTable, "ADDC", 0x10, DecodeADD_ADDC);
1223   AddInstTable(InstTable, "ORL", 0x00, DecodeANL_ORL_XRL);
1224   AddInstTable(InstTable, "ANL", 0x10, DecodeANL_ORL_XRL);
1225   AddInstTable(InstTable, "XRL", 0x90, DecodeANL_ORL_XRL);
1226   AddInstTable(InstTable, "CALL", 0x14, DecodeCALL_JMP);
1227   AddInstTable(InstTable, "JMP", 0x04, DecodeCALL_JMP);
1228   AddInstTable(InstTable, "CLR", 0x00, DecodeCLR_CPL);
1229   AddInstTable(InstTable, "CPL", 0x10, DecodeCLR_CPL);
1230   AddInstTable(InstTable, "DEC", 0, DecodeDEC);
1231   AddInstTable(InstTable, "DIS", 0x10, DecodeDIS_EN);
1232   AddInstTable(InstTable, "EN", 0x00, DecodeDIS_EN);
1233   AddInstTable(InstTable, "DJNZ", 0x00, DecodeDJNZ);
1234   AddInstTable(InstTable, "ENT0", 0x00, DecodeENT0);
1235   AddInstTable(InstTable, "INC", 0x00, DecodeINC);
1236   AddInstTable(InstTable, "IN", 0x00, DecodeIN);
1237   AddInstTable(InstTable, "INS", 0x00, DecodeINS);
1238   AddInstTable(InstTable, "JMPP", 0x00, DecodeJMPP);
1239   AddInstTable(InstTable, "JB", 0x00, DecodeJB);
1240   AddInstTable(InstTable, "MOV", 0x00, DecodeMOV);
1241   AddInstTable(InstTable, "ANLD", 0x9c, DecodeANLD_ORLD_MOVD);
1242   AddInstTable(InstTable, "ORLD", 0x8c, DecodeANLD_ORLD_MOVD);
1243   AddInstTable(InstTable, "MOVD", 0x3c, DecodeANLD_ORLD_MOVD);
1244   AddInstTable(InstTable, "MOVP", 0xa3, DecodeMOVP_MOVP3);
1245   AddInstTable(InstTable, "MOVP3", 0xe3, DecodeMOVP_MOVP3);
1246   AddInstTable(InstTable, "MOVP1", 0x00, DecodeMOVP1);
1247   AddInstTable(InstTable, "MOVX", 0x00, DecodeMOVX);
1248   AddInstTable(InstTable, "NOP", 0x00, DecodeNOP);
1249   AddInstTable(InstTable, "OUT", 0x00, DecodeOUT);
1250   AddInstTable(InstTable, "OUTL", 0x00, DecodeOUTL);
1251   AddInstTable(InstTable, "RET", 0x83, DecodeRET_RETR);
1252   AddInstTable(InstTable, "RETR", 0x93, DecodeRET_RETR);
1253   AddInstTable(InstTable, "SEL", 0x00, DecodeSEL);
1254   AddInstTable(InstTable, "STOP", 0x00, DecodeSTOP);
1255   AddInstTable(InstTable, "STRT", 0x00, DecodeSTRT);
1256   AddInstTable(InstTable, "XCH", 0x00, DecodeXCH);
1257   AddInstTable(InstTable, "XCHD", 0x00, DecodeXCHD);
1258   AddInstTable(InstTable, "RAD", 0x00, DecodeRAD);
1259   AddInstTable(InstTable, "RETI", 0x00, DecodeRETI);
1260   AddInstTable(InstTable, "IDL", 0x00, DecodeIDL_HALT);
1261   AddInstTable(InstTable, "HALT", 0x00, DecodeIDL_HALT);
1262   AddInstTable(InstTable, "HLTS", 0x82, DecodeOKIFixed);
1263   AddInstTable(InstTable, "FLT", 0xa2, DecodeOKIFixed);
1264   AddInstTable(InstTable, "FLTT", 0xc2, DecodeOKIFixed);
1265   AddInstTable(InstTable, "FRES", 0xe2, DecodeOKIFixed);
1266 
1267   ClrCplVals = (const char **) malloc(sizeof(char *)*ClrCplCnt);
1268   ClrCplCodes = (Byte *) malloc(sizeof(Byte)*ClrCplCnt);
1269   ClrCplVals[0] = "A"; ClrCplVals[1] = "C"; ClrCplVals[2] = "F0"; ClrCplVals[3] = "F1";
1270   ClrCplCodes[0] = 0x27; ClrCplCodes[1] = 0x97; ClrCplCodes[2] = 0x85; ClrCplCodes[3] = 0xa5;
1271 
1272   AddCond("JTF"  , 0x16);
1273   AddCond("JC"   , 0xf6);
1274   AddCond("JNC"  , 0xe6);
1275   AddCond("JZ"   , 0xc6);
1276   AddCond("JNZ"  , 0x96);
1277   if (pCurrCPUProps->Flags & eCPUFlagT0)
1278   {
1279     AddCond("JT0"  , 0x36);
1280     AddCond("JNT0" , 0x26);
1281   }
1282   AddCond("JT1"  , 0x56);
1283   AddCond("JNT1" , 0x46);
1284   if (pCurrCPUProps->Flags & eCPUFlagUserFlags)
1285   {
1286     AddCond("JF0"  , 0xb6);
1287     AddCond("JF1"  , 0x76);
1288   }
1289   if (pCurrCPUProps->Flags & eCPUFlagUPIPort)
1290   {
1291     AddCond("JNIBF", 0xd6);
1292     AddCond("JOBF" , 0x86);
1293   }
1294   else
1295     AddCond("JNI"  , (pCurrCPUProps->Flags & eCPUFlagSiemens) ? 0x66 : 0x86);
1296   if (pCurrCPUProps->Flags & eCPUFlagCondBitJmp)
1297   {
1298     AddCond("JB0"  , 0x12);
1299     AddCond("JB1"  , 0x32);
1300     AddCond("JB2"  , 0x52);
1301     AddCond("JB3"  , 0x72);
1302     AddCond("JB4"  , 0x92);
1303     AddCond("JB5"  , 0xb2);
1304     AddCond("JB6"  , 0xd2);
1305     AddCond("JB7"  , 0xf2);
1306   }
1307   if (pCurrCPUProps->Flags & eCPUFlag84xx)
1308     AddCond("JNTF", 0x06);
1309 
1310   AddAcc("DA"  , 0x57);
1311   AddAcc("RL"  , 0xe7);
1312   AddAcc("RLC" , 0xf7);
1313   AddAcc("RR"  , 0x77);
1314   AddAcc("RRC" , 0x67);
1315   AddAcc("SWAP", 0x47);
1316 
1317   /* Leave MBx first, used by CALL/JMP! */
1318 
1319   SelOrders = (SelOrder *) malloc(sizeof(SelOrder) * SelOrderCnt); InstrZ = 0;
1320   AddSel("MB0" , 0xe5);
1321   AddSel("MB1" , 0xf5);
1322   AddSel("MB2" , 0xa5);
1323   AddSel("MB3" , 0xb5);
1324   AddSel("RB0" , 0xc5);
1325   AddSel("RB1" , 0xd5);
1326   AddSel("AN0" , 0x95);
1327   AddSel("AN1" , 0x85);
1328 
1329   AddInstTable(InstTable, "REG", 0, CodeREG);
1330 }
1331 
DeinitFields(void)1332 static void DeinitFields(void)
1333 {
1334   DestroyInstTable(InstTable);
1335   free(ClrCplVals);
1336   free(ClrCplCodes);
1337   free(SelOrders);
1338 }
1339 
MakeCode_48(void)1340 static void MakeCode_48(void)
1341 {
1342   CodeLen = 0;
1343   DontPrint = False;
1344 
1345   /* zu ignorierendes */
1346 
1347   if (Memo(""))
1348     return;
1349 
1350   /* Pseudoanweisungen */
1351 
1352   if (DecodeIntelPseudo(False))
1353     return;
1354 
1355   if (!LookupInstTable(InstTable, OpPart.Str))
1356     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
1357 }
1358 
IsDef_48(void)1359 static Boolean IsDef_48(void)
1360 {
1361   return Memo("REG");
1362 }
1363 
1364 /*!------------------------------------------------------------------------
1365  * \fn     InternSymbol_48(char *pArg, TempResult *pResult)
1366  * \brief  handle built-in symbols on MCS-48
1367  * \param  pArg source argument
1368  * \param  pResult result buffer
1369  * ------------------------------------------------------------------------ */
1370 
InternSymbol_48(char * pArg,TempResult * pResult)1371 static void InternSymbol_48(char *pArg, TempResult *pResult)
1372 {
1373   tRegInt Erg;
1374   tSymbolSize Size;
1375 
1376   if (DecodeRegCore(pArg, &Erg, &Size))
1377   {
1378     pResult->Typ = TempReg;
1379     pResult->DataSize = Size;
1380     pResult->Contents.RegDescr.Reg = Erg;
1381     pResult->Contents.RegDescr.Dissect = DissectReg_48;
1382   }
1383 }
1384 
SwitchFrom_48(void)1385 static void SwitchFrom_48(void)
1386 {
1387   DeinitFields();
1388 }
1389 
InitCode_48(void)1390 static void InitCode_48(void)
1391 {
1392   Reg_MB = MB_NOTHING;
1393 }
1394 
SwitchTo_48(void * pUser)1395 static void SwitchTo_48(void *pUser)
1396 {
1397 #define ASSUME48Count (sizeof(ASSUME48s) / sizeof(*ASSUME48s))
1398   static ASSUMERec ASSUME48s[] =
1399   {
1400     { "MB"   , &Reg_MB   , 0,  1, MB_NOTHING, NULL },
1401   };
1402 
1403   pCurrCPUProps = (const tCPUProps*)pUser;
1404   ASSUME48s[0].Max = (pCurrCPUProps->CodeSize >> 11) & 3;
1405 
1406   TurnWords = False;
1407   ConstMode = ConstModeIntel;
1408 
1409   PCSymbol = "$";
1410   HeaderID = 0x21;
1411   NOPCode = 0x00;
1412   DivideChars = ",";
1413   HasAttrs = False;
1414 
1415   /* limit code segement size only vor variants known to have no
1416      external program memory */
1417 
1418   ValidSegs = (1 << SegCode) | (1 << SegIData);
1419   Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
1420   SegLimits[SegCode] = pCurrCPUProps->CodeSize;
1421   Grans[SegIData] = 1; ListGrans[SegIData] = 1; SegInits[SegIData] = 0x20;
1422   SegLimits[SegIData] = 0xff;
1423   if (pCurrCPUProps->Flags & eCPUFlagXMem)
1424   {
1425     ValidSegs |= (1 << SegXData);
1426     Grans[SegXData] = 1; ListGrans[SegXData] = 1; SegInits[SegXData] = 0;
1427     SegLimits[SegXData] = 0xff;
1428   }
1429 
1430   MakeCode = MakeCode_48;
1431   IsDef = IsDef_48;
1432   InternSymbol = InternSymbol_48;
1433   DissectReg = DissectReg_48;
1434   SwitchFrom = SwitchFrom_48;
1435   InitFields();
1436 
1437   pASSUMERecs = ASSUME48s;
1438   ASSUMERecCnt = ASSUME48Count;
1439 }
1440 
1441 /* Limit code segment size only for variants known to have no
1442    external program memory: */
1443 
1444 static tCPUProps CPUProps[] =
1445 {
1446   { "8021"     , 0x3ff, eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 },
1447   { "8022"     , 0x7ff, eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagBUS | eCPUFlagADConv | eCPUFlagINTLogic },
1448   { "8401"     , 0x1fff,eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
1449   { "8421"     , 0x7ff, eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
1450   { "8441"     , 0xfff, eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
1451   { "8461"     , 0x17ff,eCPUFlagDEC_DJNZ_IREG | eCPUFlagPort0 | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagINTLogic | eCPUFlagSerial | eCPUFlag84xx },
1452   { "8039"     , 0xfff, eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1453   { "8048"     , 0xfff, eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1454   { "80C39"    , 0xfff, eCPUFlagCMOS | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1455   { "80C48"    , 0xfff, eCPUFlagCMOS | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1456   { "8041"     , 0x3ff, eCPUFlagUPIPort | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1457   { "8042"     , 0x7ff, eCPUFlagUPIPort | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1458   { "80C382"   , 0xfff, eCPUFlagCMOS | eCPUFlagSiemens | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagIOExpander | eCPUFlagT0 | eCPUFlagCondBitJmp | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic },
1459   { "MSM80C39" , 0xfff, eCPUFlagCMOS | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic | eCPUFlagOKI },
1460   { "MSM80C48" , 0xfff, eCPUFlagCMOS | eCPUFlagDEC_DJNZ_IREG | eCPUFlagXMem | eCPUFlagPort1 | eCPUFlagPort2 | eCPUFlagIOExpander | eCPUFlagUserFlags | eCPUFlagT0 | eCPUFlagT0CLK | eCPUFlagCondBitJmp | eCPUFlagTransferA_PSW | eCPUFlagBUS | eCPUFlagRegBanks | eCPUFlagLogToPort | eCPUFlagDEC_REG | eCPUFlagMOVP3 | eCPUFlagINTLogic | eCPUFlagOKI },
1461   { NULL, 0, 0 }
1462 };
1463 
code48_init(void)1464 void code48_init(void)
1465 {
1466   tCPUProps *pProp;
1467 
1468   for (pProp = CPUProps; pProp->pName; pProp++)
1469     (void)AddCPUUser(pProp->pName, SwitchTo_48, (void*)pProp, NULL);
1470 
1471   AddInitPassProc(InitCode_48);
1472 }
1473