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