Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 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
 
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
 
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.p_str, RegNames[z]))
86
   {
87
     AdrType = z;
88
     if (z != ModIHL) SetOpSize(Ord(z == ModHL));
89
     goto chk;
90
   }
91
 
92
  if (*pArg->str.p_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.p_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
 
154
static void ChkCPU(Byte Mask)
155
{
156
  if (ChkExactCPUMask(Mask, CPU47C00) < 0)
157
    CodeLen = 0;
158
}
159
 
160
static Boolean DualOp(const char *s1, const char *s2)
161
{
162
  return (((!as_strcasecmp(ArgStr[1].str.p_str, s1)) && (!as_strcasecmp(ArgStr[2].str.p_str, s2)))
163
       || ((!as_strcasecmp(ArgStr[2].str.p_str, s1)) && (!as_strcasecmp(ArgStr[1].str.p_str, s2))));
164
}
165
 
166
/*---------------------------------------------------------------------------*/
167
 
168
/* ohne Argument */
169
 
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
 
181
static void DecodeLD(Word Code)
182
{
183
  UNUSED(Code);
184
 
185
  if (!ChkArgCnt(2, 2));
186
  else if (!as_strcasecmp(ArgStr[1].str.p_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
 
266
static void DecodeLDL(Word Code)
267
{
268
  UNUSED(Code);
269
 
270
  if (!ChkArgCnt(2, 2));
271
  else if ((as_strcasecmp(ArgStr[1].str.p_str, "A")) || (as_strcasecmp(ArgStr[2].str.p_str, "@DC"))) WrError(ErrNum_InvAddrMode);
272
  else
273
  {
274
    CodeLen = 1;
275
    BAsmCode[0] = 0x33;
276
  }
277
}
278
 
279
static void DecodeLDH(Word Code)
280
{
281
  UNUSED(Code);
282
 
283
  if (!ChkArgCnt(2, 2));
284
  else if ((as_strcasecmp(ArgStr[1].str.p_str, "A")) || (as_strcasecmp(ArgStr[2].str.p_str, "@DC+"))) WrError(ErrNum_InvAddrMode);
285
  else
286
  {
287
    CodeLen = 1;
288
    BAsmCode[0] = 0x32;
289
  }
290
}
291
 
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.p_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.p_str, "@HL+"))
319
        {
320
          CodeLen = 1;
321
          BAsmCode[0] = 0x1a;
322
        }
323
        else if (!as_strcasecmp(ArgStr[2].str.p_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.p_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
 
371
static void DecodeMOV(Word Code)
372
{
373
  UNUSED(Code);
374
 
375
  if (!ChkArgCnt(2, 2));
376
  else if ((!as_strcasecmp(ArgStr[1].str.p_str, "A")) && (!as_strcasecmp(ArgStr[2].str.p_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.p_str, "DMB")) && (!as_strcasecmp(ArgStr[2].str.p_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.p_str, "A")) && (!as_strcasecmp(ArgStr[2].str.p_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.p_str, "STK13")) && (!as_strcasecmp(ArgStr[2].str.p_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.p_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
 
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.p_str, "A")) && (as_strcasecmp(pArg1->str.p_str, "HL")))
448
    {
449
      pArg1 = &ArgStr[2];
450
      pArg2 = &ArgStr[1];
451
    }
452
    if ((as_strcasecmp(pArg1->str.p_str, "A")) && (as_strcasecmp(pArg1->str.p_str, "HL"))) WrError(ErrNum_InvAddrMode);
453
    else
454
    {
455
      DecodeAdr(pArg2, MModAbs);
456
      if (AdrType != ModNone)
457
      {
458
        if ((!as_strcasecmp(pArg1->str.p_str, "HL")) && (AdrVal & 3)) WrError(ErrNum_NotAligned);
459
        else
460
        {
461
          CodeLen = 2;
462
          BAsmCode[0] = 0x29 + (0x14 * Ord(!as_strcasecmp(pArg1->str.p_str, "A")));
463
          BAsmCode[1] = AdrVal;
464
        }
465
      }
466
    }
467
  }
468
}
469
 
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
 
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
 
536
static void DecodeOUTB(Word Code)
537
{
538
  UNUSED(Code);
539
 
540
  if (!ChkArgCnt(1, 1));
541
  else if (as_strcasecmp(ArgStr[1].str.p_str, "@HL")) WrError(ErrNum_InvAddrMode);
542
  else
543
  {
544
    CodeLen = 1;
545
    BAsmCode[0] = 0x12;
546
  }
547
}
548
 
549
/* Arithmetik */
550
 
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
 
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
 
669
static void DecodeADDC(Word Code)
670
{
671
  UNUSED(Code);
672
 
673
  if (!ChkArgCnt(2, 2));
674
  else if ((as_strcasecmp(ArgStr[1].str.p_str, "A")) || (as_strcasecmp(ArgStr[2].str.p_str, "@HL"))) WrError(ErrNum_InvAddrMode);
675
  else
676
  {
677
    CodeLen = 1;
678
    BAsmCode[0] = 0x15;
679
  }
680
}
681
 
682
static void DecodeSUBRC(Word Code)
683
{
684
  UNUSED(Code);
685
 
686
  if (!ChkArgCnt(2, 2));
687
  else if ((as_strcasecmp(ArgStr[1].str.p_str, "A")) || (as_strcasecmp(ArgStr[2].str.p_str, "@HL"))) WrError(ErrNum_InvAddrMode);
688
  else
689
  {
690
    CodeLen = 1;
691
    BAsmCode[0] = 0x14;
692
  }
693
}
694
 
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
 
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
 
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
 
787
static void DecodeXOR(Word Code)
788
{
789
  UNUSED(Code);
790
 
791
  if (!ChkArgCnt(2, 2));
792
  else if ((as_strcasecmp(ArgStr[1].str.p_str, "A")) || (as_strcasecmp(ArgStr[2].str.p_str, "@HL"))) WrError(ErrNum_InvAddrMode);
793
  else
794
  {
795
    CodeLen = 1;
796
    BAsmCode[0] = 0x1f;
797
  }
798
}
799
 
800
static void DecodeROLC_RORC(Word Code)
801
{
802
  if (!ChkArgCnt(1, 2));
803
  else if (as_strcasecmp(ArgStr[1].str.p_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
 
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.p_str, "@L"))
838
    {
839
      if (3 == Code) WrError(ErrNum_InvAddrMode); /* !TESTP */
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.p_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.p_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.p_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.p_str, "DMB")) || (!as_strcasecmp(ArgStr[1].str.p_str, "DMB0")))
877
    {
878
      CodeLen = 2;
879
      BAsmCode[0] = 0x3b;
880
      BAsmCode[1] = 0x39 + (Code << 6);
881
      ChkCPU(as_strcasecmp(ArgStr[1].str.p_str, "DMB0") ? M_CPU470C00 : M_CPU470AC00);
882
    }
883
    else if (!as_strcasecmp(ArgStr[1].str.p_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.p_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.p_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
 
968
static void DecodeEICLR_DICLR(Word Code)
969
{
970
  if (!ChkArgCnt(2, 2));
971
  else if (as_strcasecmp(ArgStr[1].str.p_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
 
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
 
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
 
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
 
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
 
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
 
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
 
1144
static void DecodePORT(Word Code)
1145
{
1146
  UNUSED(Code);
1147
 
1148
  CodeEquate(SegIO, 0, SegLimits[SegIO]);
1149
}
1150
 
1151
/*---------------------------------------------------------------------------*/
1152
 
1153
static void AddFixed(const char *NName, Byte NCode)
1154
{
1155
  AddInstTable(InstTable, NName, NCode, DecodeFixed);
1156
}
1157
 
1158
static void InitFields(void)
1159
{
1160
  InstTable = CreateInstTable(203);
1161
 
1162
  add_null_pseudo(InstTable);
1163
 
1164
  AddInstTable(InstTable, "LD", 0, DecodeLD);
1165
  AddInstTable(InstTable, "LDL", 0, DecodeLDL);
1166
  AddInstTable(InstTable, "LDH", 0, DecodeLDH);
1167
  AddInstTable(InstTable, "ST", 0, DecodeST);
1168
  AddInstTable(InstTable, "MOV", 0, DecodeMOV);
1169
  AddInstTable(InstTable, "XCH", 0, DecodeXCH);
1170
  AddInstTable(InstTable, "IN", 0, DecodeIN);
1171
  AddInstTable(InstTable, "OUT", 0, DecodeOUT);
1172
  AddInstTable(InstTable, "OUTB", 0, DecodeOUTB);
1173
  AddInstTable(InstTable, "CMPR", 0, DecodeCMPR);
1174
  AddInstTable(InstTable, "ADD", 0, DecodeADD);
1175
  AddInstTable(InstTable, "ADDC", 0, DecodeADDC);
1176
  AddInstTable(InstTable, "SUBRC", 0, DecodeSUBRC);
1177
  AddInstTable(InstTable, "SUBR", 0, DecodeSUBR);
1178
  AddInstTable(InstTable, "INC", 0, DecodeINC_DEC);
1179
  AddInstTable(InstTable, "DEC", 1, DecodeINC_DEC);
1180
  AddInstTable(InstTable, "AND", 0, DecodeAND_OR);
1181
  AddInstTable(InstTable, "OR", 1, DecodeAND_OR);
1182
  AddInstTable(InstTable, "XOR", 0, DecodeXOR);
1183
  AddInstTable(InstTable, "ROLC", 0x05, DecodeROLC_RORC);
1184
  AddInstTable(InstTable, "RORC", 0x07, DecodeROLC_RORC);
1185
  AddInstTable(InstTable, "EICLR", 0x40, DecodeEICLR_DICLR);
1186
  AddInstTable(InstTable, "DICLR", 0x80, DecodeEICLR_DICLR);
1187
  AddInstTable(InstTable, "BSS", 0, DecodeBSS);
1188
  AddInstTable(InstTable, "BS", 0, DecodeBS);
1189
  AddInstTable(InstTable, "BSL", 0, DecodeBSL);
1190
  AddInstTable(InstTable, "B", 0, DecodeB);
1191
  AddInstTable(InstTable, "CALLS", 0, DecodeCALLS);
1192
  AddInstTable(InstTable, "CALL", 0, DecodeCALL);
1193
  AddInstTable(InstTable, "PORT", 0, DecodePORT);
1194
 
1195
  AddFixed("RET" , 0x2a);
1196
  AddFixed("RETI", 0x2b);
1197
  AddFixed("NOP" , 0x00);
1198
 
1199
  AddInstTable(InstTable, "SET", 0, DecodeBit);
1200
  AddInstTable(InstTable, "CLR", 1, DecodeBit);
1201
  AddInstTable(InstTable, "TEST", 2, DecodeBit);
1202
  AddInstTable(InstTable, "TESTP", 3, DecodeBit);
1203
 
1204
  AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
1205
}
1206
 
1207
static void DeinitFields(void)
1208
{
1209
  DestroyInstTable(InstTable);
1210
}
1211
 
1212
/*--------------------------------------------------------------------------*/
1213
 
1214
static void MakeCode_47C00(void)
1215
{
1216
  OpSize = eSymbolSizeUnknown;
1217
 
1218
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
1219
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
1220
}
1221
 
1222
static Boolean IsDef_47C00(void)
1223
{
1224
  return (Memo("PORT"));
1225
}
1226
 
1227
static void SwitchFrom_47C00(void)
1228
{
1229
  DeinitFields();
1230
}
1231
 
1232
static Boolean TrueFnc(void)
1233
{
1234
  return True;
1235
}
1236
 
1237
static void SwitchTo_47C00(void)
1238
{
1239
#define ASSUME47Count (sizeof(ASSUME47s) / sizeof(*ASSUME47s))
1240
  static ASSUMERec ASSUME47s[] =
1241
  {
1242
    { "DMB", &DMBAssume, 0, 3, 4, NULL }
1243
  };
1244
 
1245
  TurnWords = False;
1246
  SetIntConstMode(eIntConstModeIntel);
1247
  SetIsOccupiedFnc = TrueFnc;
1248
 
1249
  PCSymbol = "$";
1250
  HeaderID = 0x55;
1251
  NOPCode = 0x00;
1252
  DivideChars = ",";
1253
  HasAttrs = False;
1254
 
1255
  ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
1256
  Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
1257
  Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
1258
  Grans[SegIO  ] = 1; ListGrans[SegIO  ] = 1; SegInits[SegIO  ] = 0;
1259
  if (MomCPU == CPU47C00)
1260
  {
1261
    SegLimits[SegCode] = 0xfff;
1262
    SegLimits[SegData] = 0xff;
1263
    SegLimits[SegIO] = 0x0f;
1264
  }
1265
  else if (MomCPU == CPU470C00)
1266
  {
1267
    SegLimits[SegCode] = 0x1fff;
1268
    SegLimits[SegData] = 0x1ff;
1269
    SegLimits[SegIO] = 0x1f;
1270
  }
1271
  else if (MomCPU == CPU470AC00)
1272
  {
1273
    SegLimits[SegCode] = 0x3fff;
1274
    SegLimits[SegData] = 0x3ff;
1275
    SegLimits[SegIO] = 0x1f;
1276
  }
1277
 
1278
  pASSUMERecs = ASSUME47s;
1279
  ASSUMERecCnt = ASSUME47Count;
1280
 
1281
  MakeCode = MakeCode_47C00;
1282
  IsDef = IsDef_47C00;
1283
  SwitchFrom = SwitchFrom_47C00;
1284
  InitFields();
1285
}
1286
 
1287
static void InitCode_47C00(void)
1288
{
1289
  DMBAssume = 0;
1290
}
1291
 
1292
void code47c00_init(void)
1293
{
1294
  CPU47C00 = AddCPU("47C00", SwitchTo_47C00);
1295
  CPU470C00 = AddCPU("470C00", SwitchTo_47C00);
1296
  CPU470AC00 = AddCPU("470AC00", SwitchTo_47C00);
1297
 
1298
  AddInitPassProc(InitCode_47C00);
1299
}