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