Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* code870c.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* Codegenerator TLCS-870/C                                                  */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
 
13
#include <ctype.h>
14
#include <string.h>
15
 
16
#include "nls.h"
17
#include "bpemu.h"
18
#include "strutil.h"
19
#include "asmdef.h"
20
#include "asmsub.h"
21
#include "asmpars.h"
22
#include "asmitree.h"
23
#include "asmcode.h"
24
#include "codepseudo.h"
25
#include "intpseudo.h"
26
#include "codevars.h"
27
#include "headids.h"
28
#include "errmsg.h"
29
 
30
#include "code870c.h"
31
 
32
typedef struct
33
{
34
  const char *Name;
35
  Word Code;
36
} CondRec;
37
 
38
enum
39
{
40
  ModNone = -1,
41
  ModReg8 = 0,
42
  ModReg16 = 1,
43
  ModImm = 2,
44
  ModMem = 3
45
};
46
 
47
#define MModReg8 (1 << ModReg8)
48
#define MModReg16 (1 << ModReg16)
49
#define MModImm (1 << ModImm)
50
#define MModAbs (1 << ModAbs)
51
#define MModMem (1 << ModMem)
52
 
53
#define AccReg 0
54
#define WAReg 0
55
 
56
#define COND_CODE_TRUE 0xde
57
 
58
#define Reg8Cnt 8
59
static const char Reg8Names[] = "AWCBEDLH";
60
 
61
static CPUVar CPU870C;
62
static ShortInt OpSize;
63
static Byte AdrVals[4];
64
static ShortInt AdrType;
65
static Byte AdrMode;
66
 
67
static CondRec *Conditions;
68
 
69
/*--------------------------------------------------------------------------*/
70
 
71
typedef struct
72
{
73
  as_eval_cb_data_t cb_data;
74
  Word reg_flag;
75
} tlcs870c1_eval_cb_data_t;
76
 
77
#define REGFLAG_DISP 0x100
78
 
79
DECLARE_AS_EVAL_CB(tlcs870c1_eval_cb)
80
{
81
  tlcs870c1_eval_cb_data_t *p_tlcs870c1_eval_cb_data = (tlcs870c1_eval_cb_data_t*)p_data;
82
  size_t z;
83
  static const char AdrRegs[][3] =
84
  {
85
    "DE", "HL", "IX", "IY", "SP", "C", "PC", "A"
86
  };
87
 
88
  for (z = 0; z < as_array_size(AdrRegs); z++)
89
    if (!as_strcasecmp(p_arg->str.p_str, AdrRegs[z]))
90
    {
91
      if ((p_tlcs870c1_eval_cb_data->reg_flag & (1 << z))
92
       || !as_eval_cb_data_stack_plain_add(p_data->p_stack))
93
      {
94
        WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
95
        return e_eval_fail;
96
      }
97
      p_tlcs870c1_eval_cb_data->reg_flag |= 1 << z;
98
      as_tempres_set_int(p_res, 0);
99
      return e_eval_ok;
100
    }
101
  return e_eval_none;
102
}
103
 
104
static void DecodeAdr(const tStrComp *pArg, Byte Erl, Boolean IsDest)
105
{
106
  static const char Reg16Names[][3] =
107
  {
108
    "WA", "BC", "DE", "HL", "IX", "IY", "SP"
109
  };
110
  static const int Reg16Cnt = sizeof(Reg16Names) / sizeof(*Reg16Names);
111
 
112
  int z;
113
  LongInt DispAcc;
114
  Boolean OK;
115
 
116
  AdrType = ModNone;
117
  AdrCnt = 0;
118
 
119
  if (strlen(pArg->str.p_str) == 1)
120
  {
121
    for (z = 0; z < Reg8Cnt; z++)
122
      if (as_toupper(*pArg->str.p_str) == Reg8Names[z])
123
      {
124
        AdrType = ModReg8;
125
        OpSize = 0;
126
        AdrMode = z;
127
        goto chk;
128
      }
129
  }
130
 
131
  for (z = 0; z < Reg16Cnt; z++)
132
    if (!as_strcasecmp(pArg->str.p_str, Reg16Names[z]))
133
    {
134
      AdrType = ModReg16;
135
      OpSize = 1;
136
      AdrMode = z;
137
      goto chk;
138
    }
139
 
140
  if (IsIndirect(pArg->str.p_str))
141
  {
142
    tStrComp Arg;
143
    tEvalResult eval_result;
144
    tlcs870c1_eval_cb_data_t tlcs870c1_eval_cb_data;
145
 
146
    StrCompRefRight(&Arg, pArg, 1);
147
    StrCompShorten(&Arg, 1);
148
 
149
    if ((!as_strcasecmp(Arg.str.p_str, "+SP")) && (!IsDest))
150
    {
151
      AdrType = ModMem;
152
      AdrMode = 0xe6;
153
      goto chk;
154
    }
155
    if ((!as_strcasecmp(Arg.str.p_str, "SP-")) && (IsDest))
156
    {
157
      AdrType = ModMem;
158
      AdrMode = 0xe6;
159
      goto chk;
160
    }
161
 
162
    as_eval_cb_data_ini(&tlcs870c1_eval_cb_data.cb_data, tlcs870c1_eval_cb);
163
    tlcs870c1_eval_cb_data.reg_flag = 0;
164
    DispAcc = EvalStrIntExprWithResultAndCallback(&Arg, Int32, &eval_result, &tlcs870c1_eval_cb_data.cb_data);
165
    if (DispAcc || !tlcs870c1_eval_cb_data.reg_flag)
166
      tlcs870c1_eval_cb_data.reg_flag |= REGFLAG_DISP;
167
    if (eval_result.OK)
168
      switch (tlcs870c1_eval_cb_data.reg_flag)
169
      {
170
        case REGFLAG_DISP: /* (nnnn) (nn) */
171
          AdrType = ModMem;
172
          AdrVals[0] = DispAcc & 0xff;
173
          if (DispAcc > 0xff)
174
          {
175
            AdrMode = 0xe1;
176
            AdrCnt = 2;
177
            AdrVals[1] = (DispAcc >> 8) & 0xff;
178
          }
179
          else
180
          {
181
            AdrMode = 0xe0;
182
            AdrCnt = 1;
183
          }
184
          break;
185
        case 0x08: /* (IY) */
186
          AdrType = ModMem;
187
          AdrMode = 0xe5;
188
          break;
189
        case 0x04: /* (IX) */
190
          AdrType = ModMem;
191
          AdrMode = 0xe4;
192
          break;
193
        case 0x02: /* (HL) */
194
          AdrType = ModMem;
195
          AdrMode = 0xe3;
196
          break;
197
        case 0x01: /* (DE) */
198
          AdrType = ModMem;
199
          AdrMode = 0xe2;
200
          break;
201
        case 0xc0: /* (PC+A) */
202
          AdrType = ModMem;
203
          AdrMode = 0x4f;
204
          break;
205
        case REGFLAG_DISP | 0x10: /* (SP+dd) */
206
          if (mFirstPassUnknown(eval_result.Flags))
207
            DispAcc &= 0x7f;
208
          if (ChkRange(DispAcc, -128, 127))
209
          {
210
            AdrType = ModMem;
211
            AdrMode = 0xd6;
212
            AdrCnt = 1;
213
            AdrVals[0] = DispAcc & 0xff;
214
          }
215
          break;
216
        case REGFLAG_DISP | 0x08: /* (IY+dd) */
217
          if (mFirstPassUnknown(eval_result.Flags))
218
            DispAcc &= 0x7f;
219
          if (ChkRange(DispAcc, -128, 127))
220
          {
221
            AdrType = ModMem;
222
            AdrMode = 0xd5;
223
            AdrCnt = 1;
224
            AdrVals[0] = DispAcc & 0xff;
225
          }
226
          break;
227
        case REGFLAG_DISP | 0x04: /* (IX+dd) */
228
          if (mFirstPassUnknown(eval_result.Flags))
229
            DispAcc &= 0x7f;
230
          if (ChkRange(DispAcc, -128, 127))
231
          {
232
            AdrType = ModMem;
233
            AdrMode = 0xd4;
234
            AdrCnt = 1;
235
            AdrVals[0] = DispAcc & 0xff;
236
          }
237
          break;
238
        case REGFLAG_DISP | 0x02: /* (HL+dd) */
239
          if (mFirstPassUnknown(eval_result.Flags))
240
            DispAcc &= 0x7f;
241
          if (ChkRange(DispAcc, -128, 127))
242
          {
243
            AdrType = ModMem;
244
            AdrMode = 0xd7;
245
            AdrCnt = 1;
246
            AdrVals[0] = DispAcc & 0xff;
247
          }
248
          break;
249
        case 0x22:  /* (HL+c) */
250
          AdrType = ModMem;
251
          AdrMode = 0xe7;
252
          break;
253
        default:
254
          WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
255
      }
256
    goto chk;
257
  }
258
  else
259
  {
260
    switch (OpSize)
261
    {
262
      case -1:
263
        WrError(ErrNum_UndefOpSizes);
264
        break;
265
      case 0:
266
        AdrVals[0] = EvalStrIntExpression(pArg, Int8, &OK);
267
        if (OK)
268
        {
269
          AdrType = ModImm;
270
          AdrCnt = 1;
271
        }
272
        break;
273
      case 1:
274
        DispAcc = EvalStrIntExpression(pArg, Int16, &OK);
275
        if (OK)
276
        {
277
          AdrType = ModImm;
278
          AdrCnt = 2;
279
          AdrVals[0] = DispAcc & 0xff;
280
          AdrVals[1] = (DispAcc >> 8) & 0xff;
281
        }
282
        break;
283
    }
284
  }
285
 
286
chk:
287
  if ((AdrType != ModNone) && (!((1<<AdrType) & Erl)))
288
  {
289
    AdrType = ModNone;
290
    AdrCnt = 0;
291
    WrError(ErrNum_InvAddrMode);
292
  }
293
}
294
 
295
static Byte MakeDestMode(Byte AdrMode)
296
{
297
  if ((AdrMode & 0xf0) == 0xe0)
298
    return AdrMode + 0x10;
299
  else
300
    return AdrMode - 0x80;
301
}
302
 
303
static Boolean DecodeSPDisp(const tStrComp *pArg, Byte *pDisp, Boolean *pDispNeg)
304
{
305
  Boolean OK;
306
  LongInt DispAcc;
307
  tSymbolFlags Flags;
308
 
309
  *pDisp = 0;
310
  *pDispNeg = False;
311
 
312
  /* avoid ambiguities - LD SP,SP should be coded as LD rr,rr */
313
 
314
  if (IsIndirect(pArg->str.p_str))
315
    return False;
316
  if (as_strncasecmp(pArg->str.p_str, "SP", 2))
317
    return False;
318
  if (strlen(pArg->str.p_str) < 3)
319
    return False;
320
 
321
  DispAcc = EvalStrIntExpressionOffsWithFlags(pArg, 2, Int16, &OK, &Flags);
322
  if (!OK)
323
    return False;
324
 
325
  if (mFirstPassUnknown(Flags))
326
    DispAcc &= 0xff;
327
  if (ChkRange(DispAcc, -255, 255))
328
  {
329
    *pDispNeg = DispAcc < 0;
330
    *pDisp = *pDispNeg ? -DispAcc : DispAcc;
331
  }
332
  return True; /* return True even if disp is out of range, addressing mode was properly detected */
333
}
334
 
335
static Boolean SplitBit(tStrComp *pArg, Byte *Erg)
336
{
337
  tStrComp BitArg;
338
  char *p;
339
 
340
  p = RQuotPos(pArg->str.p_str, '.');
341
  if (!p)
342
    return False;
343
  StrCompSplitRef(pArg, &BitArg, pArg, p);
344
 
345
  if (strlen(BitArg.str.p_str) != 1) return False;
346
  else if ((*BitArg.str.p_str >= '0') && (*BitArg.str.p_str <= '7'))
347
  {
348
    *Erg = *BitArg.str.p_str - '0';
349
    return True;
350
  }
351
  else if (toupper(*BitArg.str.p_str) == 'A')
352
  {
353
    *Erg = 8;
354
    return True;
355
  }
356
  else
357
    return False;
358
}
359
 
360
static void CodeMem(Byte Entry, Byte Opcode)
361
{
362
  BAsmCode[0] = Entry + AdrMode;
363
  memcpy(BAsmCode + 1, AdrVals, AdrCnt);
364
  BAsmCode[1 + AdrCnt] = Opcode;
365
}
366
 
367
/*!------------------------------------------------------------------------
368
 * \fn     decode_condition(const char *p_cond_str, Word *p_cond_code)
369
 * \brief  parse condition code
370
 * \param  p_cond_str source argument
371
 * \param  p_cond_code machine code if found
372
 * \return True if found
373
 * ------------------------------------------------------------------------ */
374
 
375
static Boolean decode_condition(const char *p_cond_str, Word *p_cond_code)
376
{
377
  int z;
378
 
379
  for (z = 0; Conditions[z].Name; z++)
380
    if (!as_strcasecmp(p_cond_str, Conditions[z].Name))
381
    {
382
      *p_cond_code = Conditions[z].Code;
383
      return True;
384
    }
385
 
386
  return False;
387
}
388
 
389
/*!------------------------------------------------------------------------
390
 * \fn     cond_code_tf(Word cond_code)
391
 * \brief  check if condition is true or false
392
 * \param  cond_code condition code to check
393
 * \return True if yes
394
 * ------------------------------------------------------------------------ */
395
 
396
static Boolean cond_code_tf(Word cond_code)
397
{
398
  return (cond_code == COND_CODE_TRUE)
399
      || (cond_code == 0xdf);
400
}
401
 
402
/*--------------------------------------------------------------------------*/
403
 
404
static void DecodeFixed(Word Code)
405
{
406
  if (ChkArgCnt(0, 0))
407
  {
408
    CodeLen = 0;
409
    if (Hi(Code) != 0)
410
      BAsmCode[CodeLen++] = Hi(Code);
411
    BAsmCode[CodeLen++] = Lo(Code);
412
  }
413
}
414
 
415
static void DecodeLD(Word Code)
416
{
417
  Byte HReg, Bit, HCnt, HMode, HVals[2];
418
  Boolean OK, NegFlag;
419
 
420
  UNUSED(Code);
421
 
422
  if (!ChkArgCnt(2, 2));
423
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
424
  {
425
    BAsmCode[2] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
426
    if (OK)
427
    {
428
      BAsmCode[0] = 0xe8;
429
      BAsmCode[1] = 0xde;
430
      CodeLen = 3;
431
    }
432
  }
433
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "RBS"))
434
  {
435
    BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], UInt1, &OK) << 1;
436
    if (OK)
437
    {
438
      BAsmCode[0] = 0xf9;
439
      CodeLen = 2;
440
    }
441
  }
442
  else if ((!as_strcasecmp(ArgStr[1].str.p_str, "SP")) && (DecodeSPDisp(&ArgStr[2], BAsmCode + 1, &NegFlag)))
443
  {
444
    BAsmCode[0] = NegFlag ? 0x3f : 0x37;
445
    CodeLen = 2;
446
  }
447
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
448
  {
449
    if (!SplitBit(&ArgStr[2], &Bit)) WrError(ErrNum_InvBitPos);
450
    else
451
    {
452
      DecodeAdr(&ArgStr[2], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
453
      switch (AdrType)
454
      {
455
        case ModReg8:
456
          CodeLen = 2;
457
          BAsmCode[0] = 0xe8 | AdrMode;
458
          BAsmCode[1] = 0x58 | Bit;
459
          break;
460
        case ModMem:
461
          if ((Bit < 8) && (AdrMode == 0xe0))
462
          {
463
            CodeLen = 2;
464
            BAsmCode[0] = 0x58 | Bit;
465
            BAsmCode[1] = AdrVals[0];
466
          }
467
          else if (Bit < 8)
468
          {
469
            CodeLen = 2 + AdrCnt;
470
            CodeMem(0x00, 0x58 | Bit);
471
          }
472
          else
473
          {
474
            CodeLen = 2 + AdrCnt;
475
            CodeMem(0x00, 0xfc);
476
          }
477
          break;
478
      }
479
    }
480
  }
481
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "CF"))
482
  {
483
    if (!SplitBit(&ArgStr[1], &Bit)) WrError(ErrNum_InvBitPos);
484
    else
485
    {
486
      DecodeAdr(&ArgStr[1], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
487
      switch (AdrType)
488
      {
489
        case ModReg8:
490
          CodeLen = 2;
491
          BAsmCode[0] = 0xe8 | AdrMode;
492
          BAsmCode[1] = 0xe8 | Bit;
493
          break;
494
        case ModMem:
495
          if (Bit < 8)
496
          {
497
            CodeLen = 2 + AdrCnt;
498
            CodeMem(0x00, 0xe8 | Bit);
499
          }
500
          else
501
          {
502
            CodeLen = 2 + AdrCnt;
503
            CodeMem(0x00, 0xf3);
504
          }
505
          break;
506
      }
507
    }
508
  }
509
  else
510
  {
511
    DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, TRUE);
512
    switch (AdrType)
513
    {
514
      case ModReg8:
515
        HReg = AdrMode;
516
        DecodeAdr(&ArgStr[2], MModReg8 | MModMem | MModImm, FALSE);
517
        switch (AdrType)
518
        {
519
          case ModReg8:
520
            if (HReg == AccReg)
521
            {
522
              CodeLen = 1; /* OK */
523
              BAsmCode[0] = 0x10 | AdrMode;
524
            }
525
            else if (AdrMode == AccReg)
526
            {
527
              CodeLen = 1; /* OK */
528
              BAsmCode[0] = 0x40 | HReg;
529
            }
530
            else
531
            {
532
              CodeLen = 2; /* OK */
533
              BAsmCode[0] = 0xe8 | AdrMode;
534
              BAsmCode[1] = 0x40 | HReg;
535
            }
536
            break;
537
          case ModMem:
538
            if ((HReg == AccReg) && (AdrMode == 0xe3))   /* A,(HL) */
539
            {
540
              CodeLen = 1; /* OK */
541
              BAsmCode[0] = 0x0d;
542
            }
543
            else if ((HReg == AccReg) && (AdrMode == 0xe0)) /* A,(nn) */
544
            {
545
              CodeLen = 2; /* OK */
546
              BAsmCode[0] = 0x0c;
547
              BAsmCode[1] = AdrVals[0];
548
            }
549
            else
550
            {
551
              CodeLen = 2 + AdrCnt; /* OK */
552
              CodeMem(0x00, 0x40 | HReg);
553
            }
554
            break;
555
          case ModImm:
556
            CodeLen = 2; /* OK */
557
            BAsmCode[0] = 0x18 | HReg;
558
            BAsmCode[1] = AdrVals[0];
559
            break;
560
        }
561
        break;
562
      case ModReg16:
563
        HReg = AdrMode;
564
        DecodeAdr(&ArgStr[2], MModReg16 | MModMem | MModImm, FALSE);
565
        switch (AdrType)
566
        {
567
          case ModReg16:
568
            CodeLen = 2; /* OK */
569
            BAsmCode[0] = 0xe8 | AdrMode;
570
            BAsmCode[1] = 0x18 | HReg;
571
            break;
572
          case ModMem:
573
            CodeLen = 2 + AdrCnt; /* OK */
574
            BAsmCode[0] = AdrMode;
575
            memcpy(BAsmCode + 1, AdrVals, AdrCnt);
576
            BAsmCode[1 + AdrCnt] = 0x48 + HReg;
577
            break;
578
          case ModImm:
579
            CodeLen = 3; /* OK */
580
            BAsmCode[0] = 0x48 | HReg;
581
            memcpy(BAsmCode + 1, AdrVals, 2);
582
            break;
583
        }
584
        break;
585
      case ModMem:
586
        memcpy(HVals, AdrVals, AdrCnt);
587
        HCnt = AdrCnt;
588
        HMode = AdrMode;
589
        OpSize = 0;
590
        DecodeAdr(&ArgStr[2], MModReg8 | MModReg16 | MModImm, FALSE);
591
        switch (AdrType)
592
        {
593
          case ModReg8:
594
            if ((HMode == 0xe3) && (AdrMode == AccReg))   /* (HL),A */
595
            {
596
              CodeLen = 1; /* OK */
597
              BAsmCode[0] = 0x0f;
598
            }
599
            else if ((HMode == 0xe0) && (AdrMode == AccReg))
600
            {
601
              CodeLen = 2; /* OK */
602
              BAsmCode[0] = 0x0e;
603
              BAsmCode[1] = AdrVals[0];
604
            }
605
            else
606
            {
607
              CodeLen = 2 + HCnt; /* OK */
608
              BAsmCode[0] = MakeDestMode(HMode);
609
              memcpy(BAsmCode + 1, HVals, HCnt);
610
              BAsmCode[1 + HCnt] = 0x78 | AdrMode;
611
            }
612
            break;
613
          case ModReg16:
614
            CodeLen = 2 + HCnt; /* OK */
615
            BAsmCode[0] = MakeDestMode(HMode);
616
            memcpy(BAsmCode + 1, HVals, HCnt);
617
            BAsmCode[1 + HCnt] = 0x68 | AdrMode;
618
            break;
619
          case ModImm:
620
            if (HMode == 0xe0) /* (nn),nn */
621
            {
622
              CodeLen = 3;
623
              BAsmCode[0] = 0x0a;
624
              BAsmCode[1] = HVals[0];
625
              BAsmCode[2] = AdrVals[0];
626
            }
627
            else
628
            {
629
              CodeLen = 1 + HCnt + 1 + AdrCnt;
630
              BAsmCode[0] = MakeDestMode(HMode);
631
              memcpy(BAsmCode + 1, HVals, HCnt);
632
              BAsmCode[1 + HCnt] = 0xf9;
633
              BAsmCode[2 + HCnt] = AdrVals[0];
634
            }
635
            break;
636
        }
637
        break;
638
    }
639
  }
640
}
641
 
642
static void DecodeLDW(Word Code)
643
{
644
  UNUSED(Code);
645
 
646
  if (ChkArgCnt(2, 2))
647
  {
648
    Boolean OK;
649
    Integer AdrInt = EvalStrIntExpression(&ArgStr[2], Int16, &OK);
650
    if (OK)
651
    {
652
      DecodeAdr(&ArgStr[1], MModReg16 | MModMem, TRUE);
653
      switch (AdrType)
654
      {
655
        case ModReg16:
656
          CodeLen = 3;
657
          BAsmCode[0] = 0x48 | AdrMode;
658
          BAsmCode[1] = AdrInt & 0xff;
659
          BAsmCode[2] = AdrInt >> 8;
660
          break;
661
        case ModMem:
662
          if (AdrMode == 0xe3) /* HL */
663
          {
664
            CodeLen = 3;
665
            BAsmCode[0] = 0x09;
666
            BAsmCode[1] = AdrInt & 0xff;
667
            BAsmCode[2] = AdrInt >> 8;
668
          }
669
          else if (AdrMode != 0xe0) WrError(ErrNum_InvAddrMode);  /* (nn) */
670
          else
671
          {
672
            CodeLen = 3;
673
            BAsmCode[0] = 0x08;
674
            BAsmCode[1] = AdrInt & 0xff;
675
            BAsmCode[2] = AdrInt >> 8;
676
          }
677
          break;
678
      }
679
    }
680
  }
681
}
682
 
683
static void DecodePUSH_POP(Word Code)
684
{
685
  if (!ChkArgCnt(1, 1));
686
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "PSW"))
687
  {
688
    CodeLen = 2;
689
    BAsmCode[0] = 0xe8;
690
    BAsmCode[1] = 0xdc | Code;
691
  }
692
  else
693
  {
694
    DecodeAdr(&ArgStr[1], MModReg16, False);
695
    if (AdrType != ModNone)
696
    {
697
      if (AdrMode < 4)
698
      {
699
        CodeLen = 1;
700
        BAsmCode[0] = (Code << 7) | 0x50 | AdrMode;
701
      }
702
      else
703
      {
704
        CodeLen = 2;
705
        BAsmCode[0] = 0xe8 | AdrMode;
706
        BAsmCode[1] = 0xd8 | Code;
707
      }
708
    }
709
  }
710
}
711
 
712
static void DecodeXCH(Word Code)
713
{
714
  Byte HReg, HCnt;
715
 
716
  UNUSED(Code);
717
 
718
  if (ChkArgCnt(2, 2))
719
  {
720
    DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, FALSE); /* set IsDest FALSE for mirrored MemOp */
721
    switch (AdrType)
722
    {
723
      case ModReg8:
724
        HReg = AdrMode;
725
        DecodeAdr(&ArgStr[2], MModReg8 | MModMem, FALSE);
726
        switch (AdrType)
727
        {
728
          case ModReg8:
729
            CodeLen = 2;
730
            BAsmCode[0] = 0xe8 | AdrMode;
731
            BAsmCode[1] = 0x70 | HReg;
732
            break;
733
          case ModMem:
734
            CodeLen = 2 + AdrCnt;
735
            CodeMem(0x00, 0x70 | HReg);
736
            break;
737
        }
738
        break;
739
      case ModReg16:
740
        HReg = AdrMode;
741
        DecodeAdr(&ArgStr[2], MModReg16 | MModMem, FALSE);
742
        switch (AdrType)
743
        {
744
          case ModReg16:
745
            CodeLen = 2;
746
            BAsmCode[0] = 0xe8 | AdrMode;
747
            BAsmCode[1] = 0x78 | HReg;
748
            break;
749
          case ModMem:
750
            CodeLen = 2 + AdrCnt;
751
            CodeMem(0x00, 0xd8 | HReg);
752
            break;
753
        }
754
        break;
755
      case ModMem:
756
        BAsmCode[0] = AdrMode;
757
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
758
        HCnt = AdrCnt;
759
        DecodeAdr(&ArgStr[2], MModReg8 | MModReg16, FALSE);
760
        switch (AdrType)
761
        {
762
          case ModReg8:
763
            CodeLen = 2 + HCnt;
764
            BAsmCode[1 + HCnt] = 0x70 | AdrMode;
765
            break;
766
          case ModReg16:
767
            CodeLen = 2 + HCnt;
768
            BAsmCode[1 + HCnt] = 0xd8 | AdrMode;
769
            break;
770
        }
771
        break;
772
    }
773
  }
774
}
775
 
776
static void DecodeALU(Word Code)
777
{
778
  Byte HReg, HLen;
779
 
780
  if (!ChkArgCnt(2, 2));
781
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
782
  {
783
    Byte Bit;
784
 
785
    if (Code != 5) WrError(ErrNum_InvAddrMode); /* XOR only */
786
    else if (!SplitBit(&ArgStr[2], &Bit)) WrError(ErrNum_InvBitPos);
787
    else if (Bit >= 8) WrError(ErrNum_InvAddrMode); /* only fixed bit # */
788
    else
789
    {
790
      DecodeAdr(&ArgStr[2], MModReg8 | MModMem, False);
791
      switch (AdrType)
792
      {
793
        case ModReg8:
794
          CodeLen = 2;
795
          BAsmCode[0] = 0xe8 | AdrMode;
796
          BAsmCode[1] = 0x50 | Bit;
797
          break;
798
        case ModMem:
799
          CodeLen = 2 + AdrCnt;
800
          CodeMem(0x00, 0x50 | Bit);
801
          break;
802
      }
803
    }
804
  }
805
  else
806
  {
807
    DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, FALSE); /* (+SP) allowed as dest mem op instead of (SP-) */
808
    switch (AdrType)
809
    {
810
      case ModReg8:
811
        HReg = AdrMode;
812
        DecodeAdr(&ArgStr[2], MModReg8 | MModMem | MModImm, FALSE);
813
        switch (AdrType)
814
        {
815
          case ModReg8:
816
            CodeLen = 2;
817
            BAsmCode[0] = 0xe8 | AdrMode;
818
            BAsmCode[1] = (HReg << 3) | Code;
819
            break;
820
          case ModMem:
821
            CodeLen = 2 + AdrCnt;
822
            CodeMem(0x00, (HReg << 3) | Code);
823
            break;
824
          case ModImm:
825
            if (HReg == AccReg)
826
            {
827
              CodeLen = 2;
828
              BAsmCode[0] = 0x60 | Code;
829
              BAsmCode[1] = AdrVals[0];
830
            }
831
            else
832
            {
833
              CodeLen = 3;
834
              BAsmCode[0] = 0xe8 | HReg;
835
              BAsmCode[1] = 0x60 | Code;
836
              BAsmCode[2] = AdrVals[0];
837
            }
838
            break;
839
        }
840
        break;
841
      case ModReg16:
842
        HReg = AdrMode;
843
        DecodeAdr(&ArgStr[2], MModImm | MModMem | MModReg16, FALSE);
844
        switch (AdrType)
845
        {
846
          case ModImm:
847
            CodeLen = 4;
848
            BAsmCode[0] = 0xe8 | HReg;
849
            BAsmCode[1] = 0x68 | Code;
850
            memcpy(BAsmCode + 2, AdrVals, AdrCnt);
851
            break;
852
          case ModMem:
853
            CodeLen = 2 + AdrCnt;
854
            CodeMem(0x00, 0x80 | (HReg << 3) | Code);
855
            break;
856
          case ModReg16:
857
            CodeLen = 2;
858
            BAsmCode[0] = 0xe8 | AdrMode;
859
            BAsmCode[1] = 0x80 | (HReg << 3) | Code;
860
            break;
861
        }
862
        break;
863
      case ModMem:
864
        if ((0xe0 == AdrMode) && (Code == 7))
865
        {
866
          BAsmCode[0] = Code;
867
          BAsmCode[1] = AdrVals[0];
868
          HLen = 2;
869
        }
870
        else
871
        {
872
          CodeMem(0x00, 0x60 | Code);
873
          HLen = 2 + AdrCnt;
874
        }
875
        OpSize = 0;
876
        DecodeAdr(&ArgStr[2], MModImm, FALSE);
877
        if (AdrType == ModImm)
878
        {
879
          BAsmCode[HLen] = AdrVals[0];
880
          CodeLen = HLen + 1;
881
        }
882
        break;
883
    }
884
  }
885
}
886
 
887
static void DecodeINC_DEC(Word Code)
888
{
889
  if (ChkArgCnt(1, 1))
890
  {
891
    DecodeAdr(&ArgStr[1], MModReg8 | MModReg16 | MModMem, False);
892
    switch (AdrType)
893
    {
894
      case ModReg8:
895
        CodeLen = 1;
896
        BAsmCode[0] = 0x20 | Code | AdrMode;
897
        break;
898
      case ModReg16:
899
        CodeLen = 1;
900
        BAsmCode[0] = 0x30 | Code | AdrMode;
901
        break;
902
      case ModMem:
903
        CodeLen = 2 + AdrCnt;
904
        CodeMem(0x00, 0xf0 | Code);
905
        break;
906
    }
907
  }
908
}
909
 
910
static void DecodeReg(Word Code)
911
{
912
  if (ChkArgCnt(1, 1))
913
  {
914
    DecodeAdr(&ArgStr[1], MModReg8, False);
915
    if (AdrType != ModNone)
916
    {
917
      CodeLen = 1;
918
      BAsmCode[0] = Lo(Code) | AdrMode;
919
      if (Hi(Code))
920
        BAsmCode[CodeLen++] = Hi(Code);
921
    }
922
  }
923
}
924
 
925
static void DecodeReg16(Word Code)
926
{
927
  if (ChkArgCnt(1, 1))
928
  {
929
    DecodeAdr(&ArgStr[1], MModReg16, False);
930
    if (AdrType != ModNone)
931
    {
932
      CodeLen = 1;
933
      BAsmCode[0] = Lo(Code) | AdrMode;
934
      if (Hi(Code))
935
        BAsmCode[CodeLen++] = Hi(Code);
936
    }
937
  }
938
}
939
 
940
static void DecodeMUL(Word Code)
941
{
942
  UNUSED(Code);
943
 
944
  if (ChkArgCnt(2, 2))
945
  {
946
    DecodeAdr(&ArgStr[1], MModReg8, False);
947
    if (AdrType == ModReg8)
948
    {
949
      Byte HReg = AdrMode;
950
      DecodeAdr(&ArgStr[2], MModReg8, False);
951
      if (AdrType == ModReg8)
952
      {
953
        if ((HReg ^ AdrMode) != 1) WrError(ErrNum_InvRegPair);
954
        else
955
        {
956
          CodeLen = 2;
957
          BAsmCode[0] = 0xe8 | (HReg >> 1);
958
          BAsmCode[1] = 0xf2;
959
        }
960
      }
961
    }
962
  }
963
}
964
 
965
static void DecodeDIV(Word Code)
966
{
967
  UNUSED(Code);
968
 
969
  if (ChkArgCnt(2, 2))
970
  {
971
    DecodeAdr(&ArgStr[1], MModReg16, False);
972
    if (AdrType == ModReg16)
973
    {
974
      if ((AdrMode == 1) || (AdrMode > 3)) WrError(ErrNum_InvAddrMode); /* WA DE HL */
975
      else
976
      {
977
        Byte HReg = AdrMode;
978
        DecodeAdr(&ArgStr[2], MModReg8, False);
979
        if (AdrType == ModReg8)
980
        {
981
          if (AdrMode != 2) WrError(ErrNum_InvAddrMode);  /* C */
982
          else
983
          {
984
            CodeLen = 2;
985
            BAsmCode[0] = 0xe8 | HReg;
986
            BAsmCode[1] = 0xf3;
987
          }
988
        }
989
      }
990
    }
991
  }
992
}
993
 
994
static void DecodeNEG(Word Code)
995
{
996
  UNUSED(Code);
997
 
998
  if (!ChkArgCnt(2, 2));
999
  else if (as_strcasecmp(ArgStr[1].str.p_str, "CS")) WrError(ErrNum_InvAddrMode);
1000
  else
1001
  {
1002
    DecodeAdr(&ArgStr[2], MModReg16, False);
1003
    if (AdrType == ModReg16)
1004
    {
1005
      CodeLen = 2;
1006
      BAsmCode[0] = 0xe8 | AdrMode;
1007
      BAsmCode[1] = 0xfa;
1008
    }
1009
  }
1010
}
1011
 
1012
static void DecodeROLD_RORD(Word Code)
1013
{
1014
  if (!ChkArgCnt(2, 2));
1015
  else if (as_strcasecmp(ArgStr[1].str.p_str, "A")) WrError(ErrNum_InvAddrMode);
1016
  else
1017
  {
1018
    DecodeAdr(&ArgStr[2], MModMem, False);
1019
    if (AdrType != ModNone)
1020
    {
1021
      CodeLen = 2 + AdrCnt;
1022
      CodeMem(0x00, Code);
1023
    }
1024
  }
1025
}
1026
 
1027
static void DecodeTEST_CPL_SET_CLR(Word Code)
1028
{
1029
  Byte Bit;
1030
 
1031
  if (!ChkArgCnt(1, 1));
1032
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "CF"))
1033
  {
1034
    switch (Lo(Code))
1035
    {
1036
      case 0xc0:
1037
        BAsmCode[0] = 0xc5;
1038
        CodeLen = 1;
1039
        break;
1040
      case 0xc8:
1041
        BAsmCode[0] = 0xc4;
1042
        CodeLen = 1;
1043
        break;
1044
      case 0xe0:
1045
        BAsmCode[0] = 0xc6;
1046
        CodeLen = 1;
1047
        break;
1048
      default:
1049
        WrError(ErrNum_InvAddrMode);
1050
    }
1051
  }
1052
  else if (!SplitBit(&ArgStr[1], &Bit)) WrError(ErrNum_InvBitPos);
1053
  else
1054
  {
1055
    DecodeAdr(&ArgStr[1], (Bit < 8 ? MModReg8 : 0) | MModMem, False);
1056
    switch (AdrType)
1057
    {
1058
      case ModReg8:
1059
        CodeLen = 2;
1060
        BAsmCode[0] = 0xe8 | AdrMode;
1061
        BAsmCode[1] = Lo(Code) | Bit;
1062
        break;
1063
      case ModMem:
1064
        if ((Bit < 8) && (AdrMode == 0xe0) && (Lo(Code) != 0xe0)) /* no short addr. for CPL */
1065
        {
1066
          CodeLen = 2;
1067
          BAsmCode[0] = Lo(Code) | Bit;
1068
          BAsmCode[1] = AdrVals[0];
1069
        }
1070
        else if (Bit < 8)
1071
        {
1072
          CodeLen = 2 + AdrCnt;
1073
          CodeMem(0x00, Lo(Code) | Bit);
1074
        }
1075
        else
1076
        {
1077
          CodeLen = 2 + AdrCnt;
1078
          CodeMem(0x00, Hi(Code));
1079
        }
1080
        break;
1081
    }
1082
  }
1083
}
1084
 
1085
static void DecodeJRS(Word Code)
1086
{
1087
  UNUSED(Code);
1088
 
1089
  if (ChkArgCnt(2, 2))
1090
  {
1091
    Integer AdrInt;
1092
    Word cond_code;
1093
    Boolean OK;
1094
    tSymbolFlags Flags;
1095
 
1096
    /* only T/F allowed */
1097
    if (!decode_condition(ArgStr[1].str.p_str, &cond_code) || !cond_code_tf(cond_code)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
1098
    else
1099
    {
1100
      AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[2], Int16, &OK, &Flags) - (EProgCounter() + 2);
1101
      if (OK)
1102
      {
1103
        if (((AdrInt < -16) || (AdrInt > 15)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
1104
        else
1105
        {
1106
          CodeLen = 1;
1107
          BAsmCode[0] = 0x80 | ((cond_code - 0xde) << 5) | (AdrInt & 0x1f);
1108
        }
1109
      }
1110
    }
1111
  }
1112
}
1113
 
1114
static void DecodeJR(Word Code)
1115
{
1116
  UNUSED(Code);
1117
 
1118
  if (ChkArgCnt(1, 2))
1119
  {
1120
    Word cond_code;
1121
    Integer AdrInt;
1122
    int Delta;
1123
    Boolean OK;
1124
    tSymbolFlags Flags;
1125
 
1126
    if (ArgCnt == 1)
1127
      cond_code = COND_CODE_TRUE;
1128
    else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
1129
    {
1130
      WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
1131
      return;
1132
    }
1133
 
1134
      Delta = ((ArgCnt == 1) || (!Hi(cond_code))) ? 2 : 3;
1135
 
1136
      AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], Int16, &OK, &Flags) - (EProgCounter() + Delta);
1137
      if (OK)
1138
      {
1139
        if (((AdrInt < -128) || (AdrInt > 127)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
1140
        else
1141
        {
1142
          if (3 == Delta)
1143
            BAsmCode[CodeLen++] = Hi(cond_code);
1144
          BAsmCode[CodeLen++] = (ArgCnt == 1) ?  0xfc : Lo(cond_code);
1145
          BAsmCode[CodeLen++] = AdrInt & 0xff;
1146
        }
1147
      }
1148
  }
1149
}
1150
 
1151
static void DecodeJ(Word Code)
1152
{
1153
  UNUSED(Code);
1154
 
1155
  if (ChkArgCnt(1, 2))
1156
  {
1157
    Word cond_code;
1158
 
1159
    if (ArgCnt == 1)
1160
      cond_code = COND_CODE_TRUE;
1161
    else if (!decode_condition(ArgStr[1].str.p_str, &cond_code))
1162
    {
1163
      WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
1164
      return;
1165
    }
1166
 
1167
    OpSize = 1;
1168
    DecodeAdr(&ArgStr[ArgCnt], MModReg16 | MModMem | MModImm, False);
1169
    switch (AdrType)
1170
    {
1171
      case ModReg16: /* -> JP */
1172
        if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
1173
        else
1174
        {
1175
          CodeLen = 2;
1176
          BAsmCode[0] = 0xe8 | AdrMode;
1177
          BAsmCode[1] = Code;
1178
        }
1179
        break;
1180
      case ModMem: /* -> JP */
1181
        if (cond_code != COND_CODE_TRUE) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
1182
        else
1183
        {
1184
          CodeLen = 2 + AdrCnt;
1185
          CodeMem(0x00, Code);
1186
        }
1187
        break;
1188
      case ModImm:
1189
      {
1190
        Word Adr = ((Word)(AdrVals[1] << 8)) | AdrVals[0];
1191
        Integer Dist = Adr - (EProgCounter() + 2);
1192
        int Delta = ((ArgCnt == 1) || !Hi(cond_code)) ? 2 : 3;
1193
 
1194
        /* TODO: the ArgCnt != 1 check is only necessary to get same
1195
           encoding as previous versions.  Encoding 'J xxx' as 'JRS T,XXX'
1196
           if possible would actually be smarter: */
1197
 
1198
        if ((Dist >= -16) && (Dist < 15) && (ArgCnt != 1) && cond_code_tf(cond_code)) /* JRS T/F */
1199
        {
1200
          CodeLen = 1;
1201
          BAsmCode[0] = 0x80 | ((cond_code - 0xde) << 5) | (Dist & 0x1f);
1202
        }
1203
        else if ((Dist >= -128) && (Dist < 127))
1204
        {
1205
          if (ArgCnt == 1) /* JR dist */
1206
          {
1207
            BAsmCode[CodeLen++] = 0xfc;
1208
            BAsmCode[CodeLen++] = Dist & 0xff;
1209
          }
1210
          else /* JR cc, dist */
1211
          {
1212
            if (3 == Delta)
1213
              BAsmCode[CodeLen++] = Hi(cond_code);
1214
            BAsmCode[CodeLen++] = Lo(cond_code);
1215
            BAsmCode[CodeLen++] = Dist & 0xff;
1216
          }
1217
        }
1218
        else
1219
        {
1220
          if (ArgCnt == 1) /* JP dest */
1221
          {
1222
            BAsmCode[CodeLen++] = 0xfe;
1223
            BAsmCode[CodeLen++] = Lo(Adr);
1224
            BAsmCode[CodeLen++] = Hi(Adr);
1225
          }
1226
          else /* JR !cc, JP dest */
1227
          {
1228
            cond_code ^= 1;
1229
            if (3 == Delta)
1230
              BAsmCode[CodeLen++] = Hi(cond_code);
1231
            BAsmCode[CodeLen++] = Lo(cond_code);
1232
            BAsmCode[CodeLen++] = 3;
1233
            BAsmCode[CodeLen++] = 0xfe;
1234
            BAsmCode[CodeLen++] = Lo(Adr);
1235
            BAsmCode[CodeLen++] = Hi(Adr);
1236
          }
1237
        }
1238
        break;
1239
      }
1240
    }
1241
  }
1242
}
1243
 
1244
static void DecodeJP_CALL(Word Code)
1245
{
1246
  UNUSED(Code);
1247
 
1248
  if (ChkArgCnt(1, 1))
1249
  {
1250
    OpSize = 1;
1251
    DecodeAdr(&ArgStr[1], MModReg16 | MModMem | MModImm, False);
1252
    switch (AdrType)
1253
    {
1254
      case ModReg16:
1255
        CodeLen = 2;
1256
        BAsmCode[0] = 0xe8 | AdrMode;
1257
        BAsmCode[1] = Code;
1258
        break;
1259
      case ModMem:
1260
        CodeLen = 2 + AdrCnt;
1261
        CodeMem(0x00, Code);
1262
        break;
1263
      case ModImm:
1264
        CodeLen = 3;
1265
        BAsmCode[0] = Code;
1266
        memcpy(BAsmCode + 1, AdrVals, AdrCnt);
1267
        break;
1268
    }
1269
  }
1270
}
1271
 
1272
static void DecodeCALLV(Word Code)
1273
{
1274
  UNUSED(Code);
1275
 
1276
  if (ChkArgCnt(1, 1))
1277
  {
1278
    Boolean OK;
1279
    Byte HVal = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
1280
    if (OK)
1281
    {
1282
      CodeLen = 1;
1283
      BAsmCode[0] = 0x70 | (HVal & 15);
1284
    }
1285
  }
1286
}
1287
 
1288
/*--------------------------------------------------------------------------*/
1289
 
1290
static void AddFixed(const char *NName, Word NCode)
1291
{
1292
  AddInstTable(InstTable, NName, NCode, DecodeFixed);
1293
}
1294
 
1295
static void AddCond(const char *NName, Word NCode)
1296
{
1297
  order_array_rsv_end(Conditions, CondRec);
1298
  Conditions[InstrZ].Name = NName;
1299
  Conditions[InstrZ++].Code = NCode;
1300
}
1301
 
1302
static void AddReg(const char *NName, Word NCode)
1303
{
1304
  AddInstTable(InstTable, NName, NCode, DecodeReg);
1305
}
1306
 
1307
static void AddReg16(const char *NName, Word NCode)
1308
{
1309
  AddInstTable(InstTable, NName, NCode, DecodeReg16);
1310
}
1311
 
1312
static void InitFields(void)
1313
{
1314
  InstTable = CreateInstTable(203);
1315
 
1316
  add_null_pseudo(InstTable);
1317
 
1318
  AddInstTable(InstTable, "LD", 0, DecodeLD);
1319
  AddInstTable(InstTable, "LDW", 0, DecodeLDW);
1320
  AddInstTable(InstTable, "PUSH", 0, DecodePUSH_POP);
1321
  AddInstTable(InstTable, "POP", 1, DecodePUSH_POP);
1322
  AddInstTable(InstTable, "XCH", 0, DecodeXCH);
1323
  AddInstTable(InstTable, "INC", 0, DecodeINC_DEC);
1324
  AddInstTable(InstTable, "DEC", 8, DecodeINC_DEC);
1325
  AddInstTable(InstTable, "MUL", 0, DecodeMUL);
1326
  AddInstTable(InstTable, "DIV", 0, DecodeDIV);
1327
  AddInstTable(InstTable, "NEG", 0, DecodeNEG);
1328
  AddInstTable(InstTable, "ROLD", 0xf6, DecodeROLD_RORD);
1329
  AddInstTable(InstTable, "RORD", 0xf7, DecodeROLD_RORD);
1330
  AddInstTable(InstTable, "CLR", 0xfac8, DecodeTEST_CPL_SET_CLR);
1331
  AddInstTable(InstTable, "TEST", 0xfc58, DecodeTEST_CPL_SET_CLR);
1332
  AddInstTable(InstTable, "CPL", 0xfbe0, DecodeTEST_CPL_SET_CLR);
1333
  AddInstTable(InstTable, "SET", 0xf2c0, DecodeTEST_CPL_SET_CLR);
1334
  AddInstTable(InstTable, "JR", 0, DecodeJR);
1335
  AddInstTable(InstTable, "JRS", 0, DecodeJRS);
1336
  AddInstTable(InstTable, "JP", 0xfe, DecodeJP_CALL);
1337
  AddInstTable(InstTable, "J", 0, DecodeJ);
1338
  AddInstTable(InstTable, "CALL", 0xfd, DecodeJP_CALL);
1339
  AddInstTable(InstTable, "CALLV", 0, DecodeCALLV);
1340
 
1341
  AddFixed("DI"  , 0xc83a);
1342
  AddFixed("EI"  , 0xc03a);
1343
  AddFixed("RET" , 0x00fa);
1344
  AddFixed("RETI", 0x00fb);
1345
  AddFixed("RETN", 0xe8fb);
1346
  AddFixed("SWI" , 0x00ff);
1347
  AddFixed("NOP" , 0x0000);
1348
 
1349
  InstrZ = 0;
1350
  AddCond("EQ" , 0x00d8); AddCond("Z"  , 0x00d8);
1351
  AddCond("NE" , 0x00d9); AddCond("NZ" , 0x00d9);
1352
  AddCond("CS" , 0x00da); AddCond("LT" , 0x00da);
1353
  AddCond("CC" , 0x00db); AddCond("GE" , 0x00db);
1354
  AddCond("LE" , 0x00dc); AddCond("GT" , 0x00dd);
1355
  AddCond("M"  , 0xe8d0); AddCond("P"  , 0xe8d1);
1356
  AddCond("SLT", 0xe8d2); AddCond("SGE", 0xe8d3);
1357
  AddCond("SLE", 0xe8d4); AddCond("SGT", 0xe8d5);
1358
  AddCond("VS" , 0xe8d6); AddCond("VC" , 0xe8d7);
1359
  AddCond("T"  , COND_CODE_TRUE); AddCond("F"  , 0x00df);
1360
  AddCond(NULL , 0);
1361
 
1362
  AddReg("DAA" , 0xdae8);  AddReg("DAS" , 0xdbe8);
1363
  AddReg("SHLC", 0xf4e8);  AddReg("SHRC", 0xf5e8);
1364
  AddReg("ROLC", 0xf6e8);  AddReg("RORC", 0xf7e8);
1365
  AddReg("SWAP", 0xffe8);
1366
 
1367
  AddReg16("SHLCA", 0xf0e8); AddReg16("SHRCA", 0xf1e8);
1368
 
1369
  InstrZ = 0;
1370
  AddInstTable(InstTable, "ADDC", InstrZ++, DecodeALU);
1371
  AddInstTable(InstTable, "ADD" , InstrZ++, DecodeALU);
1372
  AddInstTable(InstTable, "SUBB", InstrZ++, DecodeALU);
1373
  AddInstTable(InstTable, "SUB" , InstrZ++, DecodeALU);
1374
  AddInstTable(InstTable, "AND" , InstrZ++, DecodeALU);
1375
  AddInstTable(InstTable, "XOR" , InstrZ++, DecodeALU);
1376
  AddInstTable(InstTable, "OR"  , InstrZ++, DecodeALU);
1377
  AddInstTable(InstTable, "CMP" , InstrZ++, DecodeALU);
1378
 
1379
  AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
1380
}
1381
 
1382
static void DeinitFields(void)
1383
{
1384
  DestroyInstTable(InstTable);
1385
 
1386
  order_array_free(Conditions);
1387
}
1388
 
1389
/*--------------------------------------------------------------------------*/
1390
 
1391
static void MakeCode_870C(void)
1392
{
1393
  OpSize = eSymbolSizeUnknown;
1394
 
1395
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
1396
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
1397
}
1398
 
1399
static Boolean IsDef_870C(void)
1400
{
1401
  return False;
1402
}
1403
 
1404
static void SwitchFrom_870C(void)
1405
{
1406
  DeinitFields();
1407
}
1408
 
1409
static Boolean TrueFnc(void)
1410
{
1411
  return True;
1412
}
1413
 
1414
static void SwitchTo_870C(void)
1415
{
1416
  const TFamilyDescr *FoundDescr;
1417
 
1418
  FoundDescr = FindFamilyByName("TLCS-870/C");
1419
 
1420
  TurnWords = False;
1421
  SetIntConstMode(eIntConstModeIntel);
1422
  SetIsOccupiedFnc = TrueFnc;
1423
 
1424
  PCSymbol = "$";
1425
  HeaderID = FoundDescr->Id;
1426
  NOPCode = 0x00;
1427
  DivideChars = ",";
1428
  HasAttrs = False;
1429
 
1430
  ValidSegs = 1 << SegCode;
1431
  Grans[SegCode] = 1;
1432
  ListGrans[SegCode] = 1;
1433
  SegInits[SegCode] = 0;
1434
  SegLimits[SegCode] = 0xffff;
1435
 
1436
  MakeCode = MakeCode_870C;
1437
  IsDef = IsDef_870C;
1438
  SwitchFrom = SwitchFrom_870C;
1439
  InitFields();
1440
}
1441
 
1442
void code870c_init(void)
1443
{
1444
  CPU870C = AddCPU("TLCS-870/C", SwitchTo_870C);
1445
}