Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* code68k.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* Codegenerator 680x0-Familie                                               */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
#include <string.h>
13
#include <ctype.h>
14
 
15
#include "nls.h"
16
#include "bpemu.h"
17
#include "be_le.h"
18
#include "ieeefloat.h"
19
#include "strutil.h"
20
#include "asmdef.h"
21
#include "asmsub.h"
22
#include "asmpars.h"
23
#include "asmallg.h"
24
#include "onoff_common.h"
25
#include "asmcode.h"
26
#include "motpseudo.h"
27
#include "asmitree.h"
28
#include "codevars.h"
29
#include "errmsg.h"
30
#include "codepseudo.h"
31
 
32
#include "code68k.h"
33
 
34
typedef enum
35
{
36
  e68KGen1a, /* 68008/68000 */
37
  e68KGen1b, /* 68010/68012 */
38
  eColdfire,
39
  eCPU32,
40
  e68KGen2,  /* 68020/68030 */
41
  e68KGen3   /* 68040 */
42
} tFamily;
43
 
44
typedef enum
45
{
46
  eCfISA_None,
47
  eCfISA_A,
48
  eCfISA_APlus,
49
  eCfISA_B,
50
  eCfISA_C
51
} tCfISA;
52
 
53
typedef enum
54
{
55
  eFlagNone = 0,
56
  eFlagLogCCR = 1 << 0,
57
  eFlagIdxScaling = 1 << 1,
58
  eFlagCALLM_RTM = 1 << 2,
59
  eFlagIntFPU = 1 << 3,
60
  eFlagExtFPU = 1 << 4,
61
  eFlagIntPMMU = 1 << 5,
62
  eFlagBranch32 = 1 << 6,
63
  eFlagMAC = 1 << 7,
64
  eFlagEMAC = 1 << 8
65
} tSuppFlags;
66
 
67
#define eSymbolSizeShiftCnt ((tSymbolSize)8)
68
 
69
#ifdef __cplusplus
70
# include "code68k.hpp"
71
#endif
72
 
73
enum
74
{
75
  Std_Variant = 0,
76
  I_Variant = 4,
77
  A_Variant = 8,
78
  VariantMask = 12
79
};
80
 
81
typedef struct
82
{
83
  const char *Name;
84
  Word Code;
85
} tCtReg;
86
 
87
#define MAX_CTREGS_GROUPS 4
88
 
89
typedef struct
90
{
91
  const char *pName;
92
  LongWord AddrSpaceMask;
93
  tFamily Family;
94
  tCfISA CfISA;
95
  tSuppFlags SuppFlags;
96
  const tCtReg *pCtRegs[MAX_CTREGS_GROUPS];
97
} tCPUProps;
98
 
99
typedef struct
100
{
101
  Word Code;
102
  Boolean MustSup;
103
  Word FamilyMask;
104
} FixedOrder;
105
 
106
typedef struct
107
{
108
  Byte Code;
109
  Boolean Dya;
110
  tSuppFlags NeedsSuppFlags;
111
} FPUOp;
112
 
113
typedef struct
114
{
115
  const char *pName;
116
  tSymbolSize Size;
117
  Word Code;
118
} PMMUReg;
119
 
120
#define EMACAvailName  "HASEMAC"
121
 
122
#define REG_SP 15
123
#define REG_FPCTRL 8
124
#define REG_FPCR 4
125
#define REG_FPSR 2
126
#define REG_FPIAR 1
127
 
128
typedef enum
129
{
130
  ModNone = 0,
131
  ModData = 1,
132
  ModAdr = 2,
133
  ModAdrI = 3,
134
  ModPost = 4,
135
  ModPre = 5,
136
  ModDAdrI = 6,
137
  ModAIX = 7,
138
  ModPC = 8,
139
  ModPCIdx = 9,
140
  ModAbs = 10,
141
  ModImm = 11,
142
  ModFPn = 12,
143
  ModFPCR = 13
144
} adrmode_t;
145
 
146
enum
147
{
148
  MModData = 1 << (ModData - 1),
149
  MModAdr = 1 << (ModAdr - 1),
150
  MModAdrI = 1 << (ModAdrI - 1),
151
  MModPost = 1 << (ModPost - 1),
152
  MModPre = 1 << (ModPre - 1),
153
  MModDAdrI = 1 << (ModDAdrI - 1),
154
  MModAIX = 1 << (ModAIX - 1),
155
  MModPC = 1 << (ModPC - 1),
156
  MModPCIdx = 1 << (ModPCIdx - 1),
157
  MModAbs = 1 << (ModAbs - 1),
158
  MModImm = 1 << (ModImm - 1),
159
  MModFPn = 1 << (ModFPn - 1),
160
  MModFPCR = 1 << (ModFPCR - 1)
161
};
162
 
163
typedef struct
164
{
165
  adrmode_t AdrMode;
166
  Word AdrPart;
167
  Word Vals[10];
168
  tSymbolFlags ImmSymFlags;
169
  int Cnt;
170
} tAdrResult;
171
 
172
static tSymbolSize OpSize;
173
static ShortInt RelPos;
174
static Boolean FullPMMU;                /* voller PMMU-Befehlssatz? */
175
 
176
static FixedOrder *FixedOrders;
177
static FPUOp *FPUOps;
178
static PMMUReg *PMMURegs;
179
 
180
static const tCPUProps *pCurrCPUProps;
181
static tSymbolSize NativeFloatSize;
182
 
183
static const Byte FSizeCodes[10] =
184
{
185
  6, 4, 0, 7, 0, 1, 5, 2, 0, 3
186
};
187
 
188
/*-------------------------------------------------------------------------*/
189
/* Unterroutinen */
190
 
191
#define CopyAdrVals(Dest, pAdrResult) memcpy(Dest, (pAdrResult)->Vals, (pAdrResult)->Cnt)
192
 
193
static Boolean CheckFamilyCore(unsigned FamilyMask)
194
{
195
  return !!((FamilyMask >> pCurrCPUProps->Family) & 1);
196
}
197
 
198
static Boolean CheckFamily(unsigned FamilyMask)
199
{
200
  if (CheckFamilyCore(FamilyMask))
201
    return True;
202
  WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
203
  CodeLen = 0;
204
  return False;
205
}
206
 
207
static Boolean CheckISA(unsigned ISAMask)
208
{
209
  if ((ISAMask >> pCurrCPUProps->CfISA) & 1)
210
    return True;
211
  WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
212
  CodeLen = 0;
213
  return False;
214
}
215
 
216
static Boolean CheckNoFamily(unsigned FamilyMask)
217
{
218
  if (!CheckFamilyCore(FamilyMask))
219
    return True;
220
  WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
221
  CodeLen = 0;
222
  return False;
223
}
224
 
225
static void CheckSup(void)
226
{
227
  if (!SupAllowed)
228
    WrStrErrorPos(ErrNum_PrivOrder, &OpPart);
229
}
230
 
231
static Boolean CheckColdSize(void)
232
{
233
  if ((OpSize > eSymbolSize32Bit) || ((pCurrCPUProps->Family == eColdfire) && (OpSize < eSymbolSize32Bit)))
234
  {
235
    WrError(ErrNum_InvOpSize);
236
    return False;
237
  }
238
  else
239
    return True;
240
}
241
 
242
static Boolean CheckFloatSize(void)
243
{
244
  if (!*AttrPart.str.p_str)
245
    OpSize = NativeFloatSize;
246
 
247
  switch (OpSize)
248
  {
249
    case eSymbolSize8Bit:
250
    case eSymbolSize16Bit:
251
    case eSymbolSize32Bit:
252
    case eSymbolSizeFloat32Bit:
253
    case eSymbolSizeFloat64Bit:
254
      return True;
255
    case eSymbolSizeFloat96Bit:
256
    case eSymbolSizeFloatDec96Bit:
257
      if (pCurrCPUProps->Family != eColdfire)
258
        return True;
259
      /* else fall-through */
260
    default:
261
      WrError(ErrNum_InvOpSize);
262
      return False;
263
  }
264
}
265
 
266
static Boolean FloatOpSizeFitsDataReg(tSymbolSize OpSize)
267
{
268
  return (OpSize <= eSymbolSize32Bit) || (OpSize == eSymbolSizeFloat32Bit);
269
}
270
 
271
static Boolean ValReg(char Ch)
272
{
273
  return ((Ch >= '0') && (Ch <= '7'));
274
}
275
 
276
/*-------------------------------------------------------------------------*/
277
/* Register Symbols */
278
 
279
/*!------------------------------------------------------------------------
280
 * \fn     DecodeRegCore(const char *pArg, Word *pResult)
281
 * \brief  check whether argument is a CPU register
282
 * \param  pArg argument to check
283
 * \param  pResult numeric register value if yes
284
 * \return True if yes
285
 * ------------------------------------------------------------------------ */
286
 
287
static Boolean DecodeRegCore(const char *pArg, Word *pResult)
288
{
289
  if (!as_strcasecmp(pArg, "SP"))
290
  {
291
    *pResult = REG_SP | REGSYM_FLAG_ALIAS;
292
    return True;
293
  }
294
 
295
  if (strlen(pArg) != 2)
296
    return False;
297
  if ((*pResult = pArg[1] - '0') > 7)
298
    return False;
299
 
300
  switch (as_toupper(*pArg))
301
  {
302
    case 'D':
303
      return True;
304
    case 'A':
305
      *pResult |= 8;
306
      return True;
307
    default:
308
      return False;
309
  }
310
}
311
 
312
/*!------------------------------------------------------------------------
313
 * \fn     DecodeFPRegCore(const char *pArg, Word *pResult)
314
 * \brief  check whether argument is an FPU register
315
 * \param  pArg argument to check
316
 * \param  pResult numeric register value if yes
317
 * \return True if yes
318
 * ------------------------------------------------------------------------ */
319
 
320
static Boolean DecodeFPRegCore(const char *pArg, Word *pResult)
321
{
322
  if (!as_strcasecmp(pArg, "FPCR"))
323
  {
324
    *pResult = REG_FPCTRL | REG_FPCR;
325
    return True;
326
  }
327
  if (!as_strcasecmp(pArg, "FPSR"))
328
  {
329
    *pResult = REG_FPCTRL | REG_FPSR;
330
    return True;
331
  }
332
  if (!as_strcasecmp(pArg, "FPIAR"))
333
  {
334
    *pResult = REG_FPCTRL | REG_FPIAR;
335
    return True;
336
  }
337
 
338
  if (strlen(pArg) != 3)
339
    return False;
340
  if (as_strncasecmp(pArg, "FP", 2))
341
    return False;
342
  if ((*pResult = pArg[2] - '0') > 7)
343
    return False;
344
  return True;
345
}
346
 
347
/*!------------------------------------------------------------------------
348
 * \fn     DissectReg_68K(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
349
 * \brief  dissect register symbols - 68K variant
350
 * \param  pDest destination buffer
351
 * \param  DestSize destination buffer size
352
 * \param  Value numeric register value
353
 * \param  InpSize register size
354
 * ------------------------------------------------------------------------ */
355
 
356
static void DissectReg_68K(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
357
{
358
  if (InpSize == NativeFloatSize)
359
  {
360
    switch (Value)
361
    {
362
      case REG_FPCTRL | REG_FPCR:
363
        as_snprintf(pDest, DestSize, "FPCR");
364
        break;
365
      case REG_FPCTRL | REG_FPSR:
366
        as_snprintf(pDest, DestSize, "FPSR");
367
        break;
368
      case REG_FPCTRL | REG_FPIAR:
369
        as_snprintf(pDest, DestSize, "FPIAR");
370
        break;
371
      default:
372
        as_snprintf(pDest, DestSize, "FP%u", (unsigned)Value);
373
    }
374
  }
375
  else if (InpSize == eSymbolSize32Bit)
376
  {
377
    switch (Value)
378
    {
379
      case REGSYM_FLAG_ALIAS | REG_SP:
380
        as_snprintf(pDest, DestSize, "SP");
381
        break;
382
      default:
383
        as_snprintf(pDest, DestSize, "%c%u", Value & 8 ? 'A' : 'D', (unsigned)(Value & 7));
384
    }
385
  }
386
  else
387
    as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
388
}
389
 
390
/*!------------------------------------------------------------------------
391
 * \fn     compare_reg_68k(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tRegInt reg2_size)
392
 * \brief  compare two register symbols
393
 * \param  reg1_num 1st register's number
394
 * \param  reg1_size 1st register's data size
395
 * \param  reg2_num 2nd register's number
396
 * \param  reg2_size 2nd register's data size
397
 * \return 0, -1, 1, -2
398
 * ------------------------------------------------------------------------ */
399
 
400
static int compare_reg_68k(tRegInt reg1_num, tSymbolSize reg1_size, tRegInt reg2_num, tSymbolSize reg2_size)
401
{
402
  /* FP and Integer registers in different register files: */
403
 
404
  if (reg1_size != reg2_size)
405
    return -2;
406
 
407
  if (reg1_size == NativeFloatSize)
408
  {
409
    /* only FP data registers have an ordering: */
410
 
411
    if ((reg1_num & REG_FPCTRL) || (reg2_num & REG_FPCTRL))
412
      return (reg1_num == reg2_num) ? 0 : -2;
413
  }
414
  else if (reg1_size == eSymbolSize32Bit)
415
  {
416
    reg1_num &= ~REGSYM_FLAG_ALIAS;
417
    reg2_num &= ~REGSYM_FLAG_ALIAS;
418
  }
419
 
420
  if (reg1_num < reg2_num)
421
    return -1;
422
  else if (reg1_num > reg2_num)
423
    return 1;
424
  else
425
    return 0;
426
}
427
 
428
/*-------------------------------------------------------------------------*/
429
/* Adressparser */
430
 
431
typedef enum
432
{
433
  PC, AReg, Index, indir, Disp, None
434
} CompType;
435
 
436
/* static const char *CompNames[] = { "PC", "AReg", "Index", "indir", "Disp", "None" }; */
437
 
438
typedef struct
439
{
440
  tStrComp Comp;
441
  CompType Art;
442
  Word ANummer, INummer;
443
  Boolean Long;
444
  Word Scale;
445
  ShortInt Size;
446
  LongInt Wert;
447
} AdrComp;
448
 
449
static void ClrAdrVals(tAdrResult *pResult)
450
{
451
  pResult->AdrMode = ModNone;
452
  pResult->Cnt = 0;
453
}
454
 
455
static Boolean ACheckFamily(unsigned FamilyMask, const tStrComp *pAdrComp, tAdrResult *pResult)
456
{
457
  if (CheckFamilyCore(FamilyMask))
458
    return True;
459
  WrStrErrorPos(ErrNum_AddrModeNotSupported, pAdrComp);
460
  ClrAdrVals(pResult);
461
  return False;
462
}
463
 
464
/*!------------------------------------------------------------------------
465
 * \fn     DecodeReg(const tStrComp *pArg, Word *pErg, Boolean MustBeReg)
466
 * \brief  check whether argument is a CPU register or register alias
467
 * \param  pArg argument to check
468
 * \param  pResult numeric register value if yes
469
 * \param  MustBeReg argument is expected to be a register
470
 * \return RegEvalResult
471
 * ------------------------------------------------------------------------ */
472
 
473
static tRegEvalResult DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
474
{
475
  tRegDescr RegDescr;
476
  tEvalResult EvalResult;
477
  tRegEvalResult RegEvalResult;
478
 
479
  if (DecodeRegCore(pArg->str.p_str, pResult))
480
  {
481
    *pResult &= ~REGSYM_FLAG_ALIAS;
482
    return eIsReg;
483
  }
484
 
485
  RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
486
  *pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
487
  return RegEvalResult;
488
}
489
 
490
/*!------------------------------------------------------------------------
491
 * \fn     DecodeFPReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
492
 * \brief  check whether argument is a FPU register or register alias
493
 * \param  pArg argument to check
494
 * \param  pResult numeric register value if yes
495
 * \param  MustBeReg argument is expected to be a register
496
 * \return RegEvalResult
497
 * ------------------------------------------------------------------------ */
498
 
499
static tRegEvalResult DecodeFPReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
500
{
501
  tRegDescr RegDescr;
502
  tEvalResult EvalResult;
503
  tRegEvalResult RegEvalResult;
504
 
505
  if (DecodeFPRegCore(pArg->str.p_str, pResult))
506
  {
507
    *pResult &= ~REGSYM_FLAG_ALIAS;
508
    return eIsReg;
509
  }
510
 
511
  RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, NativeFloatSize, MustBeReg);
512
  *pResult = RegDescr.Reg;
513
  return RegEvalResult;
514
}
515
 
516
/*!------------------------------------------------------------------------
517
 * \fn     DecodeRegOrFPReg(const tStrComp *pArg, Word *pErg, tSymbolSize *pSize, Boolean MustBeReg)
518
 * \brief  check whether argument is an CPU/FPU register or register alias
519
 * \param  pArg argument to check
520
 * \param  pResult numeric register value if yes
521
 * \param  pSize size of register if yes
522
 * \param  MustBeReg argument is expected to be a register
523
 * \return RegEvalResult
524
 * ------------------------------------------------------------------------ */
525
 
526
static tRegEvalResult DecodeRegOrFPReg(const tStrComp *pArg, Word *pResult, tSymbolSize *pSize, Boolean MustBeReg)
527
{
528
  tRegDescr RegDescr;
529
  tEvalResult EvalResult;
530
  tRegEvalResult RegEvalResult;
531
 
532
  if (DecodeRegCore(pArg->str.p_str, pResult))
533
  {
534
    *pResult &= ~REGSYM_FLAG_ALIAS;
535
    *pSize = eSymbolSize32Bit;
536
    return eIsReg;
537
  }
538
  if (DecodeFPRegCore(pArg->str.p_str, pResult))
539
  {
540
    *pSize = NativeFloatSize;
541
    return eIsReg;
542
  }
543
 
544
  RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
545
  *pResult = RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
546
  *pSize = EvalResult.DataSize;
547
  return RegEvalResult;
548
}
549
 
550
static Boolean DecodeRegPair(tStrComp *pArg, Word *Erg1, Word *Erg2)
551
{
552
  char *pSep = strchr(pArg->str.p_str, ':');
553
  tStrComp Left, Right;
554
 
555
  if (!pSep)
556
    return False;
557
  StrCompSplitRef(&Left, &Right, pArg, pSep);
558
  return (DecodeReg(&Left, Erg1, False) == eIsReg)
559
      && (*Erg1 <= 7)
560
      && (DecodeReg(&Right, Erg2, False) == eIsReg)
561
      && (*Erg2 <= 7);
562
}
563
 
564
static Boolean CodeIndRegPair(tStrComp *pArg, Word *Erg1, Word *Erg2)
565
{
566
  char *pSep = strchr(pArg->str.p_str, ':');
567
  tStrComp Left, Right;
568
 
569
  if (!pSep)
570
    return False;
571
  StrCompSplitRef(&Left, &Right, pArg, pSep);
572
 
573
  if (!IsIndirect(Left.str.p_str) || !IsIndirect(Right.str.p_str))
574
    return False;
575
  StrCompShorten(&Left, 1);
576
  StrCompIncRefLeft(&Left, 1);
577
  StrCompShorten(&Right, 1);
578
  StrCompIncRefLeft(&Right, 1);
579
 
580
  return (DecodeReg(&Left, Erg1, False) == eIsReg)
581
      && (DecodeReg(&Right, Erg2, False) == eIsReg);
582
}
583
 
584
static Boolean CodeCache(char *Asc, Word *Erg)
585
{
586
   if (!as_strcasecmp(Asc, "IC"))
587
     *Erg = 2;
588
   else if (!as_strcasecmp(Asc, "DC"))
589
     *Erg = 1;
590
   else if (!as_strcasecmp(Asc, "IC/DC"))
591
     *Erg = 3;
592
   else if (!as_strcasecmp(Asc, "DC/IC"))
593
     *Erg = 3;
594
   else
595
     return False;
596
   return True;
597
}
598
 
599
static Boolean DecodeCtrlReg(char *Asc, Word *Erg)
600
{
601
  int Grp;
602
  String Asc_N;
603
  const tCtReg *pReg;
604
 
605
  strmaxcpy(Asc_N, Asc, STRINGSIZE);
606
  NLS_UpString(Asc_N);
607
  Asc = Asc_N;
608
 
609
  for (Grp = 0; Grp < MAX_CTREGS_GROUPS; Grp++)
610
  {
611
    pReg = pCurrCPUProps->pCtRegs[Grp];
612
    if (!pReg)
613
      return False;
614
    for (; pReg->Name; pReg++)
615
      if (!strcmp(pReg->Name, Asc))
616
      {
617
        *Erg = pReg->Code;
618
        return True;
619
      }
620
  }
621
  return False;
622
}
623
 
624
static Boolean OneField(const tStrComp *pArg, Word *Erg, Boolean Ab1)
625
{
626
  switch (DecodeReg(pArg, Erg, False))
627
  {
628
    case eIsReg:
629
      if (*Erg > 7)
630
        return False;
631
      *Erg |= 0x20;
632
      return True;
633
    case eIsNoReg:
634
    {
635
      Boolean ValOK;
636
 
637
      *Erg = EvalStrIntExpression(pArg, Int8, &ValOK);
638
      if (Ab1 && (*Erg == 32))
639
        *Erg = 0;
640
      return (ValOK && (*Erg < 32));
641
    }
642
    default:
643
      return False;
644
  }
645
}
646
 
647
static Boolean SplitBitField(tStrComp *pArg, Word *Erg)
648
{
649
  char *p;
650
  Word OfsVal;
651
  tStrComp FieldArg, OffsArg, WidthArg;
652
 
653
  p = strchr(pArg->str.p_str, '{');
654
  if (!p)
655
    return False;
656
  StrCompSplitRef(pArg, &FieldArg, pArg, p);
657
  if ((!*FieldArg.str.p_str) || (FieldArg.str.p_str[strlen(FieldArg.str.p_str) - 1] != '}'))
658
    return False;
659
  StrCompShorten(&FieldArg, 1);
660
 
661
  p = strchr(FieldArg.str.p_str, ':');
662
  if (!p)
663
    return False;
664
  StrCompSplitRef(&OffsArg, &WidthArg, &FieldArg, p);
665
  if (!OneField(&OffsArg, &OfsVal, False))
666
    return False;
667
  if (!OneField(&WidthArg, Erg, True))
668
    return False;
669
  *Erg += OfsVal << 6;
670
  return True;
671
}
672
 
673
static Boolean SplitSize(tStrComp *pArg, ShortInt *DispLen, unsigned OpSizeMask)
674
{
675
  ShortInt NewLen = -1;
676
  int ArgLen = strlen(pArg->str.p_str);
677
 
678
  if ((ArgLen > 2) && (pArg->str.p_str[ArgLen - 2] == '.'))
679
  {
680
    switch (as_toupper(pArg->str.p_str[ArgLen - 1]))
681
    {
682
      case 'B':
683
        if (OpSizeMask & 1)
684
          NewLen = 0;
685
        else
686
          goto wrong;
687
        break;
688
      case 'W':
689
        if (OpSizeMask & 2)
690
          NewLen = 1;
691
        else
692
          goto wrong;
693
        break;
694
      case 'L':
695
        if (OpSizeMask & 2)
696
          NewLen = 2;
697
        else
698
          goto wrong;
699
        break;
700
      default:
701
      wrong:
702
        WrError(ErrNum_InvOpSize);
703
        return False;
704
    }
705
    if ((*DispLen != -1) && (*DispLen != NewLen))
706
    {
707
      WrError(ErrNum_ConfOpSizes);
708
      return False;
709
    }
710
    *DispLen = NewLen;
711
    StrCompShorten(pArg, 2);
712
  }
713
 
714
  return True;
715
}
716
 
717
static Boolean ClassComp(AdrComp *C)
718
{
719
  int comp_len = strlen(C->Comp.str.p_str), reg_len;
720
  char save, c_scale, c_size;
721
 
722
  C->Art = None;
723
  C->ANummer = C->INummer = 0;
724
  C->Long = False;
725
  C->Scale = 0;
726
  C->Size = -1;
727
  C->Wert = 0;
728
 
729
  if ((*C->Comp.str.p_str == '[') && (C->Comp.str.p_str[comp_len - 1] == ']'))
730
  {
731
    C->Art = indir;
732
    return True;
733
  }
734
 
735
  if (!as_strcasecmp(C->Comp.str.p_str, "PC"))
736
  {
737
    C->Art = PC;
738
    return True;
739
  }
740
 
741
  /* assume register, splitting off scale & size first: */
742
 
743
  reg_len = comp_len;
744
  c_scale = c_size = '\0';
745
  if ((reg_len > 2) && (C->Comp.str.p_str[reg_len - 2] == '*'))
746
  {
747
    c_scale = C->Comp.str.p_str[reg_len - 1];
748
    reg_len -= 2;
749
  }
750
  if ((reg_len > 2) && (C->Comp.str.p_str[reg_len - 2] == '.'))
751
  {
752
    c_size = C->Comp.str.p_str[reg_len - 1];
753
    reg_len -= 2;
754
  }
755
  save = C->Comp.str.p_str[reg_len];
756
  C->Comp.str.p_str[reg_len] = '\0';
757
  switch (DecodeReg(&C->Comp, &C->ANummer, False))
758
  {
759
    case eRegAbort:
760
      return False;
761
    case eIsReg:
762
      C->Comp.str.p_str[reg_len] = save;
763
      break;
764
    default: /* eIsNoReg */
765
      C->Comp.str.p_str[reg_len] = save;
766
      goto is_disp;
767
  }
768
 
769
  /* OK, we know it's a register, with optional scale & size: */
770
 
771
  if ((C->ANummer > 7) && !c_scale && !c_size)
772
  {
773
    C->Art = AReg;
774
    C->ANummer -= 8;
775
    return True;
776
  }
777
 
778
  if (c_size)
779
  {
780
    switch (as_toupper(c_size))
781
    {
782
      case 'L':
783
        C->Long = True;
784
        break;
785
      case 'W':
786
        C->Long = False;
787
        break;
788
      default:
789
        return False;
790
    }
791
  }
792
  else
793
    C->Long = (pCurrCPUProps->Family == eColdfire);
794
 
795
  if (c_scale)
796
  {
797
    switch (c_scale)
798
    {
799
      case '1':
800
        C->Scale = 0;
801
        break;
802
      case '2':
803
        C->Scale = 1;
804
        break;
805
      case '4':
806
        C->Scale = 2;
807
        break;
808
      case '8':
809
        if (pCurrCPUProps->Family == eColdfire)
810
          return False;
811
        C->Scale = 3;
812
        break;
813
      default:
814
        return False;
815
    }
816
  }
817
  else
818
    C->Scale = 0;
819
  C->INummer = C->ANummer;
820
  C->Art = Index;
821
  return True;
822
 
823
is_disp:
824
  C->Art = Disp;
825
  if ((comp_len >= 2) && (C->Comp.str.p_str[comp_len - 2] == '.'))
826
  {
827
    switch (as_toupper(C->Comp.str.p_str[comp_len - 1]))
828
    {
829
      case 'L':
830
        C->Size = 2;
831
        break;
832
      case 'W':
833
        C->Size = 1;
834
        break;
835
      default:
836
        return False;
837
    }
838
    StrCompShorten(&C->Comp, 2);
839
  }
840
  else
841
    C->Size = -1;
842
  C->Art = Disp;
843
  return True;
844
}
845
 
846
static void SwapAdrComps(AdrComp *pComp1, AdrComp *pComp2)
847
{
848
  AdrComp Tmp;
849
 
850
  Tmp = *pComp1;
851
  *pComp1 = *pComp2;
852
  *pComp2 = Tmp;
853
}
854
 
855
static void AdrCompToIndex(AdrComp *pComp)
856
{
857
  pComp->Art = Index;
858
  pComp->INummer = pComp->ANummer + 8;
859
  pComp->Long = False;
860
  pComp->Scale = 0;
861
}
862
 
863
static Boolean IsShortAdr(LongInt Addr)
864
{
865
  LongWord OrigAddr = (LongWord)Addr, ExtAddr;
866
 
867
  /* Assuming we would code this address as short address... */
868
 
869
  ExtAddr = OrigAddr & 0xffff;
870
  if (ExtAddr & 0x8000)
871
    ExtAddr |= 0xffff0000ul;
872
 
873
  /* ...would this result in the same address on the bus? */
874
 
875
  return (ExtAddr & pCurrCPUProps->AddrSpaceMask) == (OrigAddr & pCurrCPUProps->AddrSpaceMask);
876
}
877
 
878
static Boolean IsDisp8(LongInt Disp)
879
{
880
  return ((Disp >= -128) && (Disp <= 127));
881
}
882
 
883
static Boolean IsDisp16(LongInt Disp)
884
{
885
  return ((Disp >= -32768) && (Disp <= 32767));
886
}
887
 
888
ShortInt GetDispLen(LongInt Disp)
889
{
890
  if (IsDisp8(Disp))
891
    return 0;
892
  else if (IsDisp16(Disp))
893
    return 1;
894
  else
895
    return 2;
896
}
897
 
898
static void ChkEven(LongInt Adr)
899
{
900
  switch (pCurrCPUProps->Family)
901
  {
902
    case e68KGen1a:
903
    case e68KGen1b:
904
    case eColdfire:
905
      if (Odd(Adr))
906
        WrError(ErrNum_AddrNotAligned);
907
      break;
908
    default:
909
      break;
910
  }
911
}
912
 
913
static void DecodeAbs(const tStrComp *pArg, ShortInt Size, tAdrResult *pResult)
914
{
915
  Boolean ValOK;
916
  tSymbolFlags Flags;
917
  LongInt HVal;
918
  Integer HVal16;
919
 
920
  pResult->Cnt = 0;
921
 
922
  HVal = EvalStrIntExpressionWithFlags(pArg, Int32, &ValOK, &Flags);
923
 
924
  if (ValOK)
925
  {
926
    if (!mFirstPassUnknown(Flags) && (OpSize > eSymbolSize8Bit))
927
      ChkEven(HVal);
928
    HVal16 = HVal;
929
 
930
    if (Size == -1)
931
      Size = (IsShortAdr(HVal)) ? 1 : 2;
932
    pResult->AdrMode = ModAbs;
933
 
934
    if (Size == 1)
935
    {
936
      if (!IsShortAdr(HVal))
937
      {
938
        WrError(ErrNum_NoShortAddr);
939
        pResult->AdrMode = ModNone;
940
      }
941
      else
942
      {
943
        pResult->AdrPart = 0x38;
944
        pResult->Vals[0] = HVal16;
945
        pResult->Cnt = 2;
946
      }
947
    }
948
    else
949
    {
950
      pResult->AdrPart = 0x39;
951
      pResult->Vals[0] = HVal >> 16;
952
      pResult->Vals[1] = HVal & 0xffff;
953
      pResult->Cnt = 4;
954
    }
955
  }
956
}
957
 
958
static Byte DecodeAdr(const tStrComp *pArg, Word Erl, tAdrResult *pResult)
959
{
960
  Byte i;
961
  int ArgLen;
962
  char *p;
963
  Word rerg;
964
  Byte lklamm, rklamm, lastrklamm;
965
  Boolean doklamm;
966
 
967
  AdrComp AdrComps[3], OneComp;
968
  Byte CompCnt;
969
  ShortInt OutDispLen = -1;
970
  Boolean PreInd;
971
 
972
  LongInt HVal;
973
  Integer HVal16;
974
  ShortInt HVal8;
975
  as_float_t DVal;
976
  int ret;
977
  Boolean ValOK;
978
  tSymbolFlags Flags;
979
  Word SwapField[6];
980
  String ArgStr;
981
  tStrComp Arg;
982
  String CReg;
983
  tStrComp CRegArg;
984
  const unsigned ExtAddrFamilyMask = (1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32);
985
  IntType DispIntType;
986
  tSymbolSize RegSize;
987
 
988
  /* some insns decode the same arg twice, so we must keep the original string intact. */
989
 
990
  StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
991
  StrCompCopy(&Arg, pArg);
992
  KillPrefBlanksStrComp(&Arg);
993
  KillPostBlanksStrComp(&Arg);
994
  ArgLen = strlen(Arg.str.p_str);
995
  ClrAdrVals(pResult);
996
 
997
  StrCompMkTemp(&CRegArg, CReg, sizeof(CReg));
998
 
999
  /* immediate : */
1000
 
1001
  if (*Arg.str.p_str == '#')
1002
  {
1003
    tStrComp ImmArg;
1004
 
1005
    StrCompRefRight(&ImmArg, &Arg, 1);
1006
    KillPrefBlanksStrComp(&ImmArg);
1007
 
1008
    pResult->AdrMode = ModImm;
1009
    pResult->AdrPart = 0x3c;
1010
    switch (OpSize)
1011
    {
1012
      case eSymbolSize8Bit:
1013
        pResult->Cnt = 2;
1014
        HVal8 = EvalStrIntExpressionWithFlags(&ImmArg, Int8, &ValOK, &pResult->ImmSymFlags);
1015
        if (ValOK)
1016
          pResult->Vals[0] = (Word)((Byte) HVal8);
1017
        break;
1018
      case eSymbolSize16Bit:
1019
        pResult->Cnt = 2;
1020
        HVal16 = EvalStrIntExpressionWithFlags(&ImmArg, Int16, &ValOK, &pResult->ImmSymFlags);
1021
        if (ValOK)
1022
          pResult->Vals[0] = (Word) HVal16;
1023
        break;
1024
      case eSymbolSize32Bit:
1025
        pResult->Cnt = 4;
1026
        HVal = EvalStrIntExpressionWithFlags(&ImmArg, Int32, &ValOK, &pResult->ImmSymFlags);
1027
        if (ValOK)
1028
        {
1029
          pResult->Vals[0] = HVal >> 16;
1030
          pResult->Vals[1] = HVal & 0xffff;
1031
        }
1032
        break;
1033
      case eSymbolSize64Bit:
1034
      {
1035
        LargeInt QVal = EvalStrIntExpressionWithFlags(&ImmArg, LargeIntType, &ValOK, &pResult->ImmSymFlags);
1036
        pResult->Cnt = 8;
1037
        if (ValOK)
1038
        {
1039
#ifdef HAS64
1040
          pResult->Vals[0] = (QVal >> 48) & 0xffff;
1041
          pResult->Vals[1] = (QVal >> 32) & 0xffff;
1042
#else
1043
          pResult->Vals[0] =
1044
          pResult->Vals[1] = (QVal & 0x80000000ul) ? 0xffff : 0x0000;
1045
#endif
1046
          pResult->Vals[2] = (QVal >> 16) & 0xffff;
1047
          pResult->Vals[3] = (QVal      ) & 0xffff;
1048
        }
1049
        break;
1050
      }
1051
      case eSymbolSizeFloat32Bit:
1052
        pResult->Cnt = 4;
1053
        DVal = EvalStrFloatExpression(&ImmArg, &ValOK);
1054
        if (ValOK)
1055
        {
1056
          if ((ret = as_float_2_ieee4(DVal, (Byte *) SwapField, HostBigEndian)) < 0)
1057
          {
1058
            asmerr_check_fp_dispose_result(ret, &ImmArg);
1059
            ValOK = False;
1060
          }
1061
        }
1062
        if (ValOK)
1063
        {
1064
          if (HostBigEndian)
1065
            DWSwap((Byte *) SwapField, 4);
1066
          pResult->Vals[0] = SwapField[1];
1067
          pResult->Vals[1] = SwapField[0];
1068
        }
1069
        break;
1070
      case eSymbolSizeFloat64Bit:
1071
        pResult->Cnt = 8;
1072
        DVal = EvalStrFloatExpression(&ImmArg, &ValOK);
1073
        if (ValOK)
1074
        {
1075
          if ((ret = as_float_2_ieee8(DVal, (Byte *) SwapField, HostBigEndian)) < 0)
1076
          {
1077
            asmerr_check_fp_dispose_result(ret, &ImmArg);
1078
            ValOK = False;
1079
          }
1080
        }
1081
        if (ValOK)
1082
        {
1083
          if (HostBigEndian)
1084
            QWSwap((Byte *) SwapField, 8);
1085
          pResult->Vals[0] = SwapField[3];
1086
          pResult->Vals[1] = SwapField[2];
1087
          pResult->Vals[2] = SwapField[1];
1088
          pResult->Vals[3] = SwapField[0];
1089
        }
1090
        break;
1091
      case eSymbolSizeFloat96Bit:
1092
        pResult->Cnt = 12;
1093
        DVal = EvalStrFloatExpression(&ImmArg, &ValOK);
1094
        if (ValOK)
1095
        {
1096
          if ((ret = as_float_2_ieee10(DVal, (Byte *) SwapField, False)) < 0)
1097
          {
1098
            asmerr_check_fp_dispose_result(ret, &ImmArg);
1099
            ValOK = False;
1100
          }
1101
        }
1102
        if (ValOK)
1103
        {
1104
          if (HostBigEndian)
1105
            WSwap((Byte *) SwapField, 10);
1106
          pResult->Vals[0] = SwapField[4];
1107
          pResult->Vals[1] = 0;
1108
          pResult->Vals[2] = SwapField[3];
1109
          pResult->Vals[3] = SwapField[2];
1110
          pResult->Vals[4] = SwapField[1];
1111
          pResult->Vals[5] = SwapField[0];
1112
        }
1113
        break;
1114
      case eSymbolSizeFloatDec96Bit:
1115
        pResult->Cnt = 12;
1116
        DVal = EvalStrFloatExpression(&ImmArg, &ValOK);
1117
        if (ValOK)
1118
        {
1119
          ConvertMotoFloatDec(DVal, (Byte *) SwapField, False);
1120
          pResult->Vals[0] = SwapField[5];
1121
          pResult->Vals[1] = SwapField[4];
1122
          pResult->Vals[2] = SwapField[3];
1123
          pResult->Vals[3] = SwapField[2];
1124
          pResult->Vals[4] = SwapField[1];
1125
          pResult->Vals[5] = SwapField[0];
1126
        }
1127
        break;
1128
      case eSymbolSizeShiftCnt: /* special arg 1..8 */
1129
        pResult->Cnt = 2;
1130
        HVal8 = EvalStrIntExpressionWithFlags(&ImmArg, UInt4, &ValOK, &pResult->ImmSymFlags);
1131
        if (ValOK)
1132
        {
1133
          if (mFirstPassUnknown(pResult->ImmSymFlags))
1134
           HVal8 = 1;
1135
          ValOK = ChkRange(HVal8, 1, 8);
1136
        }
1137
        if (ValOK)
1138
          pResult->Vals[0] = (Word)((Byte) HVal8);
1139
        break;
1140
      default:
1141
        break;
1142
    }
1143
    goto chk;
1144
  }
1145
 
1146
  /* CPU/FPU-Register direkt: */
1147
 
1148
  switch (DecodeRegOrFPReg(&Arg, &pResult->AdrPart, &RegSize, False))
1149
  {
1150
    case eIsReg:
1151
      pResult->Cnt = 0;
1152
      if (RegSize == NativeFloatSize)
1153
      {
1154
        pResult->AdrMode = (pResult->AdrPart > 7) ? ModFPCR : ModFPn;
1155
        pResult->AdrPart &= 7;
1156
      }
1157
      else
1158
        pResult->AdrMode = (pResult->AdrPart >> 3) ? ModAdr : ModData;
1159
      /* fall-through */
1160
    case eRegAbort:
1161
      goto chk;
1162
    default:
1163
      break;
1164
  }
1165
 
1166
  /* Adressregister indirekt mit Predekrement: */
1167
 
1168
  if ((ArgLen >= 4) && (*Arg.str.p_str == '-') && (Arg.str.p_str[1] == '(') && (Arg.str.p_str[ArgLen - 1] == ')'))
1169
  {
1170
    StrCompCopySub(&CRegArg, &Arg, 2, ArgLen - 3);
1171
    if ((DecodeReg(&CRegArg, &rerg, False) == eIsReg) && (rerg > 7))
1172
    {
1173
      pResult->AdrPart = rerg + 24;
1174
      pResult->Cnt = 0;
1175
      pResult->AdrMode = ModPre;
1176
      goto chk;
1177
    }
1178
  }
1179
 
1180
  /* Adressregister indirekt mit Postinkrement */
1181
 
1182
  if ((ArgLen >= 4) && (*Arg.str.p_str == '(') && (Arg.str.p_str[ArgLen - 2] == ')') && (Arg.str.p_str[ArgLen - 1] == '+'))
1183
  {
1184
    StrCompCopySub(&CRegArg, &Arg, 1, ArgLen - 3);
1185
    if ((DecodeReg(&CRegArg, &rerg, False) == eIsReg) && (rerg > 7))
1186
    {
1187
      pResult->AdrPart = rerg + 16;
1188
      pResult->Cnt = 0;
1189
      pResult->AdrMode = ModPost;
1190
      goto chk;
1191
    }
1192
  }
1193
 
1194
  /* Unterscheidung direkt<->indirekt: */
1195
 
1196
  lklamm = 0;
1197
  rklamm = 0;
1198
  lastrklamm = 0;
1199
  doklamm = True;
1200
  for (p = Arg.str.p_str; *p; p++)
1201
  {
1202
    if (*p == '[')
1203
      doklamm = False;
1204
    if (*p == ']')
1205
      doklamm = True;
1206
    if (doklamm)
1207
    {
1208
      if (*p == '(')
1209
        lklamm++;
1210
      else if (*p == ')')
1211
      {
1212
        rklamm++;
1213
        lastrklamm = p - Arg.str.p_str;
1214
      }
1215
    }
1216
  }
1217
 
1218
  if ((lklamm == 1) && (rklamm == 1) && (lastrklamm == ArgLen - 1))
1219
  {
1220
    tStrComp OutDisp, IndirComps, Remainder;
1221
    char *pCompSplit;
1222
 
1223
    /* aeusseres Displacement abspalten, Klammern loeschen: */
1224
 
1225
    p = strchr(Arg.str.p_str, '(');
1226
    *p = '\0';
1227
    StrCompSplitRef(&OutDisp, &IndirComps, &Arg, p);
1228
    OutDispLen = -1;
1229
    if (!SplitSize(&OutDisp, &OutDispLen, 7))
1230
      return ModNone;
1231
    StrCompShorten(&IndirComps, 1);
1232
 
1233
    /* in Komponenten zerteilen: */
1234
 
1235
    CompCnt = 0;
1236
    do
1237
    {
1238
      doklamm = True;
1239
      pCompSplit = IndirComps.str.p_str;
1240
      do
1241
      {
1242
        if (*pCompSplit == '[')
1243
          doklamm = False;
1244
        else if (*pCompSplit == ']')
1245
          doklamm = True;
1246
        pCompSplit++;
1247
      }
1248
      while (((!doklamm) || (*pCompSplit != ',')) && (*pCompSplit != '\0'));
1249
 
1250
      if (*pCompSplit == '\0')
1251
      {
1252
        AdrComps[CompCnt].Comp = IndirComps;
1253
        pCompSplit = NULL;
1254
      }
1255
      else
1256
      {
1257
        StrCompSplitRef(&AdrComps[CompCnt].Comp, &Remainder, &IndirComps, pCompSplit);
1258
        IndirComps = Remainder;
1259
      }
1260
 
1261
      KillPrefBlanksStrCompRef(&AdrComps[CompCnt].Comp);
1262
      KillPostBlanksStrComp(&AdrComps[CompCnt].Comp);
1263
 
1264
      /* ignore empty component */
1265
 
1266
      if (!AdrComps[CompCnt].Comp.str.p_str[0])
1267
        continue;
1268
      if (!ClassComp(&AdrComps[CompCnt]))
1269
      {
1270
        WrStrErrorPos(ErrNum_InvAddrMode, &AdrComps[CompCnt].Comp);
1271
        return ModNone;
1272
      }
1273
 
1274
      /* Base register position is already occupied and we get another one: */
1275
 
1276
      if ((CompCnt == 1) && ((AdrComps[CompCnt].Art == AReg) || (AdrComps[CompCnt].Art == PC)))
1277
      {
1278
        /* Index register at "base position": just swap comp 0 & 1, so we get (An,Xi) or (PC,Xi): */
1279
 
1280
        if (AdrComps[0].Art == Index)
1281
          SwapAdrComps(&AdrComps[CompCnt], &AdrComps[0]);
1282
 
1283
        /* Address register at "base position" and we add PC: also swap and convert it to index so we get again (PC,Xi): */
1284
 
1285
        else if ((AdrComps[0].Art == AReg) && (AdrComps[CompCnt].Art == PC))
1286
        {
1287
          SwapAdrComps(&AdrComps[CompCnt], &AdrComps[0]);
1288
          AdrCompToIndex(&AdrComps[CompCnt]);
1289
        }
1290
 
1291
        /* Otherwise, convert address to general index register.  Result may require 68020++ modes: */
1292
 
1293
        else
1294
          AdrCompToIndex(&AdrComps[CompCnt]);
1295
 
1296
        CompCnt++;
1297
      }
1298
 
1299
      /* a displacement found inside (...), but outside [...].  Explicit
1300
         sizes must be consistent, implicitly checked by SplitSize(). */
1301
 
1302
      else if (AdrComps[CompCnt].Art == Disp)
1303
      {
1304
        if (*OutDisp.str.p_str)
1305
        {
1306
          WrError(ErrNum_InvAddrMode);
1307
          return ModNone;
1308
        }
1309
        OutDisp = AdrComps[CompCnt].Comp;
1310
        OutDispLen = AdrComps[CompCnt].Size;
1311
      }
1312
 
1313
      /* no second index */
1314
 
1315
      else if ((AdrComps[CompCnt].Art != Index) && (CompCnt != 0))
1316
      {
1317
        WrError(ErrNum_InvAddrMode);
1318
        return ModNone;
1319
      }
1320
 
1321
      else
1322
        CompCnt++;
1323
    }
1324
    while (pCompSplit);
1325
 
1326
    if ((CompCnt > 2) || ((CompCnt > 1) && (AdrComps[0].Art == Index)))
1327
    {
1328
      WrError(ErrNum_InvAddrMode);
1329
      return ModNone;
1330
    }
1331
 
1332
    /* 0. Absolut in Klammern (d) */
1333
 
1334
    if (CompCnt == 0)
1335
    {
1336
      DecodeAbs(&OutDisp, OutDispLen, pResult);
1337
    }
1338
 
1339
    /* 1. Variante (An....), d(An....) */
1340
 
1341
    else if (AdrComps[0].Art == AReg)
1342
    {
1343
 
1344
      /* 1.1. Variante (An), d(An) */
1345
 
1346
      if (CompCnt == 1)
1347
      {
1348
        /* 1.1.1. Variante (An) */
1349
 
1350
        if ((*OutDisp.str.p_str == '\0') && ((MModAdrI & Erl) != 0))
1351
        {
1352
          pResult->AdrPart = 0x10 + AdrComps[0].ANummer;
1353
          pResult->AdrMode = ModAdrI;
1354
          pResult->Cnt = 0;
1355
          goto chk;
1356
        }
1357
 
1358
        /* 1.1.2. Variante d(An) */
1359
 
1360
        else
1361
        {
1362
          /* only try 32-bit displacement if explicitly requested, or 68020++ and no size given */
1363
 
1364
          if (OutDispLen < 0)
1365
            DispIntType = CheckFamilyCore(ExtAddrFamilyMask) ? SInt32 : SInt16;
1366
          else
1367
            DispIntType = (OutDispLen >= 2) ? SInt32 : SInt16;
1368
          HVal = EvalStrIntExpression(&OutDisp, DispIntType, &ValOK);
1369
          if (!ValOK)
1370
            return ModNone;
1371
          if (ValOK && (HVal == 0) && ((MModAdrI & Erl) != 0) && (OutDispLen == -1))
1372
          {
1373
            pResult->AdrPart = 0x10 + AdrComps[0].ANummer;
1374
            pResult->AdrMode = ModAdrI;
1375
            pResult->Cnt = 0;
1376
            goto chk;
1377
          }
1378
          if (OutDispLen == -1)
1379
            OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
1380
          switch (OutDispLen)
1381
          {
1382
            case 1:                   /* d16(An) */
1383
              pResult->AdrPart = 0x28 + AdrComps[0].ANummer;
1384
              pResult->AdrMode = ModDAdrI;
1385
              pResult->Cnt = 2;
1386
              pResult->Vals[0] = HVal & 0xffff;
1387
              goto chk;
1388
            case 2:                   /* d32(An) */
1389
              pResult->AdrPart = 0x30 + AdrComps[0].ANummer;
1390
              pResult->AdrMode = ModAIX;
1391
              pResult->Cnt = 6;
1392
              pResult->Vals[0] = 0x0170;
1393
              pResult->Vals[1] = (HVal >> 16) & 0xffff;
1394
              pResult->Vals[2] = HVal & 0xffff;
1395
              ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1396
              goto chk;
1397
          }
1398
        }
1399
      }
1400
 
1401
      /* 1.2. Variante d(An,Xi) */
1402
 
1403
      else
1404
      {
1405
        pResult->Vals[0] = (AdrComps[1].INummer << 12) + (Ord(AdrComps[1].Long) << 11) + (AdrComps[1].Scale << 9);
1406
        pResult->AdrPart = 0x30 + AdrComps[0].ANummer;
1407
 
1408
        /* only try 32-bit displacement if explicitly requested, or 68020++ and no size given */
1409
 
1410
        if (OutDispLen < 0)
1411
          DispIntType = CheckFamilyCore(ExtAddrFamilyMask) ? SInt32 : SInt8;
1412
        else
1413
          DispIntType = (OutDispLen >= 2) ? SInt32 : (OutDispLen >= 1 ? SInt16 : SInt8);
1414
        HVal = EvalStrIntExpression(&OutDisp, DispIntType, &ValOK);
1415
        if (ValOK)
1416
          switch (OutDispLen)
1417
          {
1418
            case eSymbolSize8Bit:
1419
              if (!IsDisp8(HVal))
1420
              {
1421
                WrError(ErrNum_OverRange);
1422
                ValOK = FALSE;
1423
              }
1424
              break;
1425
            case eSymbolSize16Bit:
1426
              if (!IsDisp16(HVal))
1427
              {
1428
                WrError(ErrNum_OverRange);
1429
                ValOK = FALSE;
1430
              }
1431
              break;
1432
          }
1433
        if (ValOK)
1434
        {
1435
          if (OutDispLen == -1)
1436
            OutDispLen = GetDispLen(HVal);
1437
          switch (OutDispLen)
1438
          {
1439
            case 0:
1440
              pResult->AdrMode = ModAIX;
1441
              pResult->Cnt = 2;
1442
              pResult->Vals[0] += (HVal & 0xff);
1443
              if ((AdrComps[1].Scale != 0) && (!(pCurrCPUProps->SuppFlags & eFlagIdxScaling)))
1444
              {
1445
                WrStrErrorPos(ErrNum_AddrModeNotSupported, &AdrComps[1].Comp);
1446
                ClrAdrVals(pResult);
1447
              }
1448
              goto chk;
1449
            case 1:
1450
              pResult->AdrMode = ModAIX;
1451
              pResult->Cnt = 4;
1452
              pResult->Vals[0] += 0x120;
1453
              pResult->Vals[1] = HVal & 0xffff;
1454
              ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1455
              goto chk;
1456
            case 2:
1457
              pResult->AdrMode = ModAIX;
1458
              pResult->Cnt = 6;
1459
              pResult->Vals[0] += 0x130;
1460
              pResult->Vals[1] = HVal >> 16;
1461
              pResult->Vals[2] = HVal & 0xffff;
1462
              ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1463
              goto chk;
1464
          }
1465
        }
1466
      }
1467
    }
1468
 
1469
    /* 2. Variante d(PC....) */
1470
 
1471
    else if (AdrComps[0].Art == PC)
1472
    {
1473
      /* 2.1. Variante d(PC) */
1474
 
1475
      if (CompCnt == 1)
1476
      {
1477
        HVal = EvalStrIntExpressionWithFlags(&OutDisp, Int32, &ValOK, &Flags) - (EProgCounter() + RelPos);
1478
        if (!ValOK)
1479
          return ModNone;
1480
        if (OutDispLen < 0)
1481
        {
1482
          if (mSymbolQuestionable(Flags) && !CheckFamilyCore(ExtAddrFamilyMask))
1483
            HVal &= 0x7fff;
1484
          OutDispLen = (IsDisp16(HVal)) ? 1 : 2;
1485
        }
1486
        switch (OutDispLen)
1487
        {
1488
          case 1:
1489
            pResult->AdrPart = 0x3a;
1490
            if (!mSymbolQuestionable(Flags) && !IsDisp16(HVal))
1491
            {
1492
              WrError(ErrNum_DistTooBig);
1493
              return ModNone;
1494
            }
1495
            pResult->AdrMode = ModPC;
1496
            pResult->Cnt = 2;
1497
            pResult->Vals[0] = HVal & 0xffff;
1498
            goto chk;
1499
          case 2:
1500
            pResult->AdrPart = 0x3b;
1501
            pResult->AdrMode = ModPCIdx;
1502
            pResult->Cnt = 6;
1503
            pResult->Vals[0] = 0x170;
1504
            pResult->Vals[1] = HVal >> 16;
1505
            pResult->Vals[2] = HVal & 0xffff;
1506
            ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1507
            goto chk;
1508
        }
1509
      }
1510
 
1511
      /* 2.2. Variante d(PC,Xi) */
1512
 
1513
      else
1514
      {
1515
        pResult->Vals[0] = (AdrComps[1].INummer << 12) + (Ord(AdrComps[1].Long) << 11) + (AdrComps[1].Scale << 9);
1516
        HVal = EvalStrIntExpressionWithFlags(&OutDisp, Int32, &ValOK, &Flags) - (EProgCounter() + RelPos);
1517
        if (!ValOK)
1518
          return ModNone;
1519
        if (OutDispLen < 0)
1520
        {
1521
          if (mSymbolQuestionable(Flags) && !CheckFamilyCore(ExtAddrFamilyMask))
1522
            HVal &= 0x7f;
1523
          OutDispLen = GetDispLen(HVal);
1524
        }
1525
        pResult->AdrPart = 0x3b;
1526
        switch (OutDispLen)
1527
        {
1528
          case 0:
1529
            if (!mSymbolQuestionable(Flags) && !IsDisp8(HVal))
1530
            {
1531
              WrError(ErrNum_DistTooBig);
1532
              return ModNone;
1533
            }
1534
            pResult->Vals[0] += (HVal & 0xff);
1535
            pResult->Cnt = 2;
1536
            pResult->AdrMode = ModPCIdx;
1537
            if ((AdrComps[1].Scale != 0) && (!(pCurrCPUProps->SuppFlags & eFlagIdxScaling)))
1538
            {
1539
              WrStrErrorPos(ErrNum_AddrModeNotSupported, &AdrComps[1].Comp);
1540
              ClrAdrVals(pResult);
1541
            }
1542
            goto chk;
1543
          case 1:
1544
            if (!mSymbolQuestionable(Flags) && !IsDisp16(HVal))
1545
            {
1546
              WrError(ErrNum_DistTooBig);
1547
              return ModNone;
1548
            }
1549
            pResult->Vals[0] += 0x120;
1550
            pResult->Cnt = 4;
1551
            pResult->AdrMode = ModPCIdx;
1552
            pResult->Vals[1] = HVal & 0xffff;
1553
            ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1554
            goto chk;
1555
          case 2:
1556
            pResult->Vals[0] += 0x130;
1557
            pResult->Cnt = 6;
1558
            pResult->AdrMode = ModPCIdx;
1559
            pResult->Vals[1] = HVal >> 16;
1560
            pResult->Vals[2] = HVal & 0xffff;
1561
            ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1562
            goto chk;
1563
        }
1564
      }
1565
    }
1566
 
1567
    /* 3. Variante (Xi), d(Xi) */
1568
 
1569
    else if (AdrComps[0].Art == Index)
1570
    {
1571
      pResult->Vals[0] = (AdrComps[0].INummer << 12) + (Ord(AdrComps[0].Long) << 11) + (AdrComps[0].Scale << 9) + 0x180;
1572
      pResult->AdrPart = 0x30;
1573
      if (*OutDisp.str.p_str == '\0')
1574
      {
1575
        pResult->Vals[0] = pResult->Vals[0] + 0x0010;
1576
        pResult->Cnt = 2;
1577
        pResult->AdrMode = ModAIX;
1578
        ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1579
        goto chk;
1580
      }
1581
      else
1582
      {
1583
        HVal = EvalStrIntExpression(&OutDisp, (OutDispLen != 1) ? SInt32 : SInt16, &ValOK);
1584
        if (ValOK)
1585
        {
1586
          if (OutDispLen == -1)
1587
            OutDispLen = IsDisp16(HVal) ? 1 : 2;
1588
          switch (OutDispLen)
1589
          {
1590
            case 0:
1591
            case 1:
1592
              pResult->Vals[0] = pResult->Vals[0] + 0x0020;
1593
              pResult->Vals[1] = HVal & 0xffff;
1594
              pResult->AdrMode = ModAIX;
1595
              pResult->Cnt = 4;
1596
              ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1597
              goto chk;
1598
            case 2:
1599
              pResult->Vals[0] = pResult->Vals[0] + 0x0030;
1600
              pResult->AdrMode = ModAIX;
1601
              pResult->Cnt = 6;
1602
              pResult->Vals[1] = HVal >> 16;
1603
              pResult->Vals[2] = HVal & 0xffff;
1604
              ACheckFamily(ExtAddrFamilyMask, pArg, pResult);
1605
              goto chk;
1606
          }
1607
        }
1608
      }
1609
    }
1610
 
1611
    /* 4. Variante indirekt: */
1612
 
1613
    else if (AdrComps[0].Art == indir)
1614
    {
1615
      /* erst ab 68020 erlaubt */
1616
 
1617
      if (!ACheckFamily((1 << e68KGen3) | (1 << e68KGen2), pArg, pResult))
1618
        return ModNone;
1619
 
1620
      /* Unterscheidung Vor- <---> Nachindizierung: */
1621
 
1622
      if (CompCnt == 2)
1623
      {
1624
        PreInd = False;
1625
        AdrComps[2] = AdrComps[1];
1626
      }
1627
      else
1628
      {
1629
        PreInd = True;
1630
        AdrComps[2].Art = None;
1631
      }
1632
 
1633
      /* indirektes Argument herauskopieren: */
1634
 
1635
      StrCompRefRight(&IndirComps, &AdrComps[0].Comp, 1);
1636
      StrCompShorten(&IndirComps, 1);
1637
 
1638
      /* Felder loeschen: */
1639
 
1640
      for (i = 0; i < 2; AdrComps[i++].Art = None);
1641
 
1642
      /* indirekten Ausdruck auseinanderfieseln: */
1643
 
1644
      do
1645
      {
1646
        /* abschneiden & klassifizieren: */
1647
 
1648
        pCompSplit = strchr(IndirComps.str.p_str, ',');
1649
        if (!pCompSplit)
1650
          OneComp.Comp = IndirComps;
1651
        else
1652
        {
1653
          StrCompSplitRef(&OneComp.Comp, &Remainder, &IndirComps, pCompSplit);
1654
          IndirComps = Remainder;
1655
        }
1656
        KillPrefBlanksStrCompRef(&OneComp.Comp);
1657
        KillPostBlanksStrComp(&OneComp.Comp);
1658
        if (!ClassComp(&OneComp))
1659
        {
1660
          WrError(ErrNum_InvAddrMode);
1661
          return ModNone;
1662
        }
1663
 
1664
        /* passend einsortieren: */
1665
 
1666
        if ((AdrComps[1].Art != None) && (OneComp.Art == AReg))
1667
        {
1668
          OneComp.Art = Index;
1669
          OneComp.INummer = OneComp.ANummer + 8;
1670
          OneComp.Long = False;
1671
          OneComp.Scale = 0;
1672
        }
1673
        switch (OneComp.Art)
1674
        {
1675
          case Disp:
1676
            i = 0;
1677
            break;
1678
          case AReg:
1679
          case PC:
1680
            i = 1;
1681
            break;
1682
          case Index:
1683
            i = 2;
1684
            break;
1685
          default:
1686
            i = 3;
1687
        }
1688
        if ((i >= 3) || AdrComps[i].Art != None)
1689
        {
1690
          WrError(ErrNum_InvAddrMode);
1691
          return ModNone;
1692
        }
1693
        else
1694
          AdrComps[i] = OneComp;
1695
      }
1696
      while (pCompSplit);
1697
 
1698
      /* extension word: 68020 format */
1699
 
1700
      pResult->Vals[0] = 0x100;
1701
 
1702
      /* bit 2 = post-indexed. */
1703
 
1704
      if (!PreInd)
1705
        pResult->Vals[0] |= 0x0004;
1706
 
1707
      /* Set post-indexed also for no index register for compatibility with older versions. */
1708
 
1709
      if (AdrComps[2].Art == None)
1710
        pResult->Vals[0] |= 0x0040 | 0x0004;
1711
      else
1712
        pResult->Vals[0] |= (AdrComps[2].INummer << 12) + (Ord(AdrComps[2].Long) << 11) + (AdrComps[2].Scale << 9);
1713
 
1714
      /* 4.1 Variante d([...PC...]...) */
1715
 
1716
      if (AdrComps[1].Art == PC)
1717
      {
1718
        if (AdrComps[0].Art == None)
1719
        {
1720
          pResult->AdrPart = 0x3b;
1721
          pResult->Vals[0] |= 0x10;
1722
          pResult->AdrMode = ModAIX;
1723
          pResult->Cnt = 2;
1724
        }
1725
        else
1726
        {
1727
          HVal = EvalStrIntExpression(&AdrComps[0].Comp, Int32, &ValOK);
1728
          HVal -= EProgCounter() + RelPos;
1729
          if (!ValOK)
1730
            return ModNone;
1731
          switch (AdrComps[0].Size)
1732
          {
1733
            case -1:
1734
             if (IsDisp16(HVal))
1735
               goto PCIs16;
1736
             else
1737
               goto PCIs32;
1738
            case 1:
1739
              if (!IsDisp16(HVal))
1740
              {
1741
                WrError(ErrNum_DistTooBig);
1742
                return ModNone;
1743
              }
1744
            PCIs16:
1745
              pResult->Vals[1] = HVal & 0xffff;
1746
              pResult->AdrPart = 0x3b;
1747
              pResult->Vals[0] += 0x20;
1748
              pResult->AdrMode = ModAIX;
1749
              pResult->Cnt = 4;
1750
              break;
1751
            case 2:
1752
            PCIs32:
1753
              pResult->Vals[1] = HVal >> 16;
1754
              pResult->Vals[2] = HVal & 0xffff;
1755
              pResult->AdrPart = 0x3b;
1756
              pResult->Vals[0] += 0x30;
1757
              pResult->AdrMode = ModAIX;
1758
              pResult->Cnt = 6;
1759
              break;
1760
          }
1761
        }
1762
      }
1763
 
1764
      /* 4.2 Variante d([...An...]...) */
1765
 
1766
      else
1767
      {
1768
        if (AdrComps[1].Art == None)
1769
        {
1770
          pResult->AdrPart = 0x30;
1771
          pResult->Vals[0] += 0x80;
1772
        }
1773
        else
1774
          pResult->AdrPart = 0x30 + AdrComps[1].ANummer;
1775
 
1776
        if (AdrComps[0].Art == None)
1777
        {
1778
          pResult->AdrMode = ModAIX;
1779
          pResult->Cnt = 2;
1780
          pResult->Vals[0] += 0x10;
1781
        }
1782
        else
1783
        {
1784
          HVal = EvalStrIntExpression(&AdrComps[0].Comp, Int32, &ValOK);
1785
          if (!ValOK)
1786
            return ModNone;
1787
          switch (AdrComps[0].Size)
1788
          {
1789
            case -1:
1790
              if (IsDisp16(HVal))
1791
                goto AnIs16;
1792
              else
1793
                goto AnIs32;
1794
            case 1:
1795
              if (!IsDisp16(HVal))
1796
              {
1797
                WrError(ErrNum_DistTooBig);
1798
                return ModNone;
1799
              }
1800
            AnIs16:
1801
              pResult->Vals[0] += 0x20;
1802
              pResult->Vals[1] = HVal & 0xffff;
1803
              pResult->AdrMode = ModAIX;
1804
              pResult->Cnt = 4;
1805
              break;
1806
            case 2:
1807
            AnIs32:
1808
              pResult->Vals[0] += 0x30;
1809
              pResult->Vals[1] = HVal >> 16;
1810
              pResult->Vals[2] = HVal & 0xffff;
1811
              pResult->AdrMode = ModAIX;
1812
              pResult->Cnt = 6;
1813
              break;
1814
          }
1815
        }
1816
      }
1817
 
1818
      /* aeusseres Displacement: */
1819
 
1820
      if (OutDisp.str.p_str[0])
1821
        HVal = EvalStrIntExpression(&OutDisp, (OutDispLen == 1) ? SInt16 : SInt32, &ValOK);
1822
      else
1823
      {
1824
        HVal = 0;
1825
        ValOK = True;
1826
      }
1827
      if (!ValOK)
1828
      {
1829
        pResult->AdrMode = ModNone;
1830
        pResult->Cnt = 0;
1831
        return ModNone;
1832
      }
1833
      if (OutDispLen == -1)
1834
        OutDispLen = IsDisp16(HVal) ? 1 : 2;
1835
      if (*OutDisp.str.p_str == '\0')
1836
      {
1837
        pResult->Vals[0]++;
1838
        goto chk;
1839
      }
1840
      else
1841
        switch (OutDispLen)
1842
        {
1843
          case 0:
1844
          case 1:
1845
            pResult->Vals[pResult->Cnt >> 1] = HVal & 0xffff;
1846
            pResult->Cnt += 2;
1847
            pResult->Vals[0] += 2;
1848
            break;
1849
          case 2:
1850
            pResult->Vals[(pResult->Cnt >> 1)    ] = HVal >> 16;
1851
            pResult->Vals[(pResult->Cnt >> 1) + 1] = HVal & 0xffff;
1852
            pResult->Cnt += 4;
1853
            pResult->Vals[0] += 3;
1854
            break;
1855
        }
1856
 
1857
      goto chk;
1858
    }
1859
 
1860
  }
1861
 
1862
  /* absolut: */
1863
 
1864
  else
1865
  {
1866
    if (!SplitSize(&Arg, &OutDispLen, 6))
1867
      return ModNone;
1868
    DecodeAbs(&Arg, OutDispLen, pResult);
1869
  }
1870
 
1871
chk:
1872
  if ((pResult->AdrMode > 0) && (!(Erl & (1 << (pResult->AdrMode - 1)))))
1873
  {
1874
    WrStrErrorPos(ErrNum_InvAddrMode, pArg);
1875
    ClrAdrVals(pResult);
1876
  }
1877
  return pResult->AdrMode;
1878
}
1879
 
1880
static Boolean DecodeMACACC(const char *pArg, Word *pResult)
1881
{
1882
  /* interprete ACC like ACC0, independent of MAC or EMAC: */
1883
 
1884
  if (!as_strcasecmp(pArg, "ACC"))
1885
    *pResult = 0;
1886
  else if (!as_strncasecmp(pArg, "ACC", 3) && (strlen(pArg) == 4) && (pArg[3] >= '0') && (pArg[3] <= '3'))
1887
    *pResult = pArg[3] - '0';
1888
  else
1889
    return False;
1890
 
1891
  /* allow ACC1..3 only on EMAC: */
1892
 
1893
  if ((!(pCurrCPUProps->SuppFlags & eFlagEMAC)) && *pResult)
1894
    return False;
1895
  return True;
1896
}
1897
 
1898
static Boolean DecodeMACReg(const char *pArg, Word *pResult)
1899
{
1900
  if (!as_strcasecmp(pArg, "MACSR"))
1901
  {
1902
    *pResult = 4;
1903
    return True;
1904
  }
1905
  if (!as_strcasecmp(pArg, "MASK"))
1906
  {
1907
    *pResult = 6;
1908
    return True;
1909
  }
1910
 
1911
  /* ACCEXT01/23 only on EMAC: */
1912
 
1913
  if (pCurrCPUProps->SuppFlags & eFlagEMAC)
1914
  {
1915
    if (!as_strcasecmp(pArg, "ACCEXT01"))
1916
    {
1917
      *pResult = 5;
1918
      return True;
1919
    }
1920
    if (!as_strcasecmp(pArg, "ACCEXT23"))
1921
    {
1922
      *pResult = 7;
1923
      return True;
1924
    }
1925
  }
1926
  return DecodeMACACC(pArg, pResult);
1927
}
1928
 
1929
static Boolean DecodeRegList(const tStrComp *pArg, Word *Erg)
1930
{
1931
  Word h, h2;
1932
  Byte z;
1933
  char *p, *p2;
1934
  String ArgStr;
1935
  tStrComp Arg, Remainder, From, To;
1936
 
1937
  StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
1938
  StrCompCopy(&Arg, pArg);
1939
 
1940
  *Erg = 0;
1941
  do
1942
  {
1943
    p = strchr(Arg.str.p_str, '/');
1944
    if (p)
1945
      StrCompSplitRef(&Arg, &Remainder, &Arg, p);
1946
    p2 = strchr(Arg.str.p_str, '-');
1947
    if (!p2)
1948
    {
1949
      if (DecodeReg(&Arg, &h, False) != eIsReg)
1950
        return False;
1951
      *Erg |= 1 << h;
1952
    }
1953
    else
1954
    {
1955
      StrCompSplitRef(&From, &To, &Arg, p2);
1956
      if (!*From.str.p_str || !*To.str.p_str)
1957
        return False;
1958
      if ((DecodeReg(&From, &h, False) != eIsReg)
1959
       || (DecodeReg(&To, &h2, False) != eIsReg))
1960
        return False;
1961
      if (h <= h2)
1962
      {
1963
        for (z = h; z <= h2; z++)
1964
          *Erg |= 1 << z;
1965
      }
1966
      else
1967
      {
1968
        for (z = h; z <= 15; z++)
1969
          *Erg |= 1 << z;
1970
        for (z = 0; z <= h2; z++)
1971
          *Erg |= 1 << z;
1972
      }
1973
    }
1974
    if (p)
1975
      Arg = Remainder;
1976
  }
1977
  while (p);
1978
  return True;
1979
}
1980
 
1981
static Boolean DecodeMACScale(const tStrComp *pArg, Word *pResult)
1982
{
1983
  int l = strlen(pArg->str.p_str);
1984
  tStrComp ShiftArg;
1985
  Boolean Left = False, OK;
1986
  Word ShiftCnt;
1987
 
1988
  /* allow empty argument */
1989
 
1990
  if (!l)
1991
  {
1992
    *pResult = 0;
1993
    return True;
1994
  }
1995
  /* left or right? */
1996
 
1997
  if (l < 2)
1998
    return False;
1999
  if (!strncmp(pArg->str.p_str, "<<", 2))
2000
    Left = True;
2001
  else if (!strncmp(pArg->str.p_str, ">>", 2))
2002
    Left = False;
2003
  else
2004
    return False;
2005
 
2006
  /* evaluate shift cnt - empty count counts as one */
2007
 
2008
  StrCompRefRight(&ShiftArg, pArg, 2);
2009
  KillPrefBlanksStrCompRef(&ShiftArg);
2010
  if (!*ShiftArg.str.p_str)
2011
  {
2012
    ShiftCnt = 1;
2013
    OK = True;
2014
  }
2015
  else
2016
    ShiftCnt = EvalStrIntExpression(&ShiftArg, UInt1, &OK);
2017
  if (!OK)
2018
    return False;
2019
 
2020
  /* codify */
2021
 
2022
  if (ShiftCnt)
2023
    *pResult = Left ? 1 : 3;
2024
  else
2025
    *pResult = 0;
2026
  return True;
2027
}
2028
 
2029
static Boolean SplitMACUpperLower(Word *pResult, tStrComp *pArg)
2030
{
2031
  char *pSplit;
2032
  tStrComp HalfComp;
2033
 
2034
  *pResult = 0;
2035
  pSplit = strrchr(pArg->str.p_str, '.');
2036
  if (!pSplit)
2037
  {
2038
    WrStrErrorPos(ErrNum_InvReg, pArg);
2039
    return False;
2040
  }
2041
 
2042
  StrCompSplitRef(pArg, &HalfComp, pArg, pSplit);
2043
  KillPostBlanksStrComp(pArg);
2044
  if (!as_strcasecmp(HalfComp.str.p_str, "L"))
2045
    *pResult = 0;
2046
  else if (!as_strcasecmp(HalfComp.str.p_str, "U"))
2047
    *pResult = 1;
2048
  else
2049
  {
2050
    WrStrErrorPos(ErrNum_InvReg, &HalfComp);
2051
    return False;
2052
  }
2053
  return True;
2054
}
2055
 
2056
static Boolean SplitMACANDMASK(Word *pResult, tStrComp *pArg)
2057
{
2058
  char *pSplit, Save;
2059
  tStrComp MaskComp, AddrComp;
2060
 
2061
  *pResult = 0;
2062
  pSplit = strrchr(pArg->str.p_str, '&');
2063
  if (!pSplit)
2064
    return True;
2065
 
2066
  Save = StrCompSplitRef(&AddrComp, &MaskComp, pArg, pSplit);
2067
  KillPrefBlanksStrCompRef(&MaskComp);
2068
 
2069
  /* if no MASK argument, be sure to revert pArg to original state: */
2070
 
2071
  if (!strcmp(MaskComp.str.p_str, "") || !as_strcasecmp(MaskComp.str.p_str, "MASK"))
2072
  {
2073
    KillPostBlanksStrComp(&AddrComp);
2074
    *pArg = AddrComp;
2075
    *pResult = 1;
2076
  }
2077
  else
2078
    *pSplit = Save;
2079
  return True;
2080
}
2081
 
2082
/*-------------------------------------------------------------------------*/
2083
/* Dekodierroutinen: Integer-Einheit */
2084
 
2085
/* 0=MOVE 1=MOVEA */
2086
 
2087
static void DecodeMOVE(Word Index)
2088
{
2089
  Word MACReg;
2090
  unsigned Variant = Index & VariantMask;
2091
 
2092
  if (!ChkArgCnt(2, 2));
2093
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "USP"))
2094
  {
2095
    if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2096
    else if ((pCurrCPUProps->Family != eColdfire) || CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_B) | (1 << eCfISA_C)))
2097
    {
2098
      tAdrResult AdrResult;
2099
 
2100
      if (DecodeAdr(&ArgStr[2], MModAdr, &AdrResult))
2101
      {
2102
        CodeLen = 2;
2103
        WAsmCode[0] = 0x4e68 | (AdrResult.AdrPart & 7);
2104
        CheckSup();
2105
      }
2106
    }
2107
  }
2108
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "USP"))
2109
  {
2110
    if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2111
    else if ((pCurrCPUProps->Family != eColdfire) || CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_B) | (1 << eCfISA_C)))
2112
    {
2113
      tAdrResult AdrResult;
2114
 
2115
      if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
2116
      {
2117
        CodeLen = 2;
2118
        WAsmCode[0] = 0x4e60 | (AdrResult.AdrPart & 7);
2119
        CheckSup();
2120
      }
2121
    }
2122
  }
2123
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "SR"))
2124
  {
2125
    if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
2126
    else
2127
    {
2128
      tAdrResult AdrResult;
2129
 
2130
      if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
2131
      {
2132
        CodeLen = 2 + AdrResult.Cnt;
2133
        WAsmCode[0] = 0x40c0 | AdrResult.AdrPart;
2134
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2135
        if (pCurrCPUProps->Family != e68KGen1a)
2136
          CheckSup();
2137
      }
2138
    }
2139
  }
2140
  else if (!as_strcasecmp(ArgStr[1].str.p_str, "CCR"))
2141
  {
2142
    if (*AttrPart.str.p_str && (OpSize > eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
2143
    else if (!CheckNoFamily(1 << e68KGen1a));
2144
    else
2145
    {
2146
      tAdrResult AdrResult;
2147
 
2148
      OpSize = eSymbolSize8Bit;
2149
      if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
2150
      {
2151
        CodeLen = 2 + AdrResult.Cnt;
2152
        WAsmCode[0] = 0x42c0 | AdrResult.AdrPart;
2153
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2154
      }
2155
    }
2156
  }
2157
  else if ((pCurrCPUProps->SuppFlags & eFlagMAC) && (DecodeMACReg(ArgStr[1].str.p_str, &MACReg)))
2158
  {
2159
    Word DestMACReg;
2160
 
2161
    if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2162
    else if ((MACReg == 4) && (!as_strcasecmp(ArgStr[2].str.p_str, "CCR")))
2163
    {
2164
      WAsmCode[0] = 0xa9c0;
2165
      CodeLen = 2;
2166
    }
2167
    else if ((MACReg < 4) && DecodeMACReg(ArgStr[2].str.p_str, &DestMACReg) && (DestMACReg < 4) && (pCurrCPUProps->SuppFlags & eFlagEMAC))
2168
    {
2169
      WAsmCode[0] = 0xa110 | (DestMACReg << 9) | (MACReg << 0);
2170
      CodeLen = 2;
2171
    }
2172
    else
2173
    {
2174
      tAdrResult AdrResult;
2175
 
2176
      if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
2177
      {
2178
        CodeLen = 2;
2179
        WAsmCode[0] = 0xa180 | (AdrResult.AdrPart & 15) | (MACReg << 9);
2180
      }
2181
    }
2182
  }
2183
  else if ((pCurrCPUProps->SuppFlags & eFlagMAC) && (DecodeMACReg(ArgStr[2].str.p_str, &MACReg)))
2184
  {
2185
    if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2186
    else
2187
    {
2188
      tAdrResult AdrResult;
2189
 
2190
      if (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModImm, &AdrResult))
2191
      {
2192
        CodeLen = 2 + AdrResult.Cnt;
2193
        WAsmCode[0] = 0xa100 | (AdrResult.AdrPart) | (MACReg << 9);
2194
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2195
      }
2196
    }
2197
  }
2198
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR"))
2199
  {
2200
    if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
2201
    else
2202
    {
2203
      tAdrResult AdrResult;
2204
 
2205
      if (DecodeAdr(&ArgStr[1], MModData | MModImm | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
2206
      {
2207
        CodeLen = 2 + AdrResult.Cnt;
2208
        WAsmCode[0] = 0x46c0 | AdrResult.AdrPart;
2209
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2210
        CheckSup();
2211
      }
2212
    }
2213
  }
2214
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR"))
2215
  {
2216
    if (*AttrPart.str.p_str && (OpSize > eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
2217
    else
2218
    {
2219
      tAdrResult AdrResult;
2220
 
2221
      if (DecodeAdr(&ArgStr[1], MModData | MModImm | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
2222
      {
2223
        CodeLen = 2 + AdrResult.Cnt;
2224
        WAsmCode[0] = 0x44c0 | AdrResult.AdrPart;
2225
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2226
      }
2227
    }
2228
  }
2229
  else
2230
  {
2231
    if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
2232
    else
2233
    {
2234
      tAdrResult AdrResult;
2235
 
2236
      DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs) | MModImm, &AdrResult);
2237
 
2238
      /* Is An as source in byte mode allowed for ColdFire? No corresponding footnote in CFPRM... */
2239
 
2240
      if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit) && (pCurrCPUProps->Family != eColdfire)) WrError(ErrNum_InvOpSize);
2241
      else if (AdrResult.AdrMode != ModNone)
2242
      {
2243
        unsigned SrcAdrNum = AdrResult.AdrMode;
2244
 
2245
        CodeLen = 2 + AdrResult.Cnt;
2246
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2247
        if (OpSize == eSymbolSize8Bit)
2248
          WAsmCode[0] = 0x1000;
2249
        else if (OpSize == eSymbolSize16Bit)
2250
          WAsmCode[0] = 0x3000;
2251
        else
2252
          WAsmCode[0] = 0x2000;
2253
        WAsmCode[0] |= AdrResult.AdrPart;
2254
        DecodeAdr(&ArgStr[2], ((Variant == A_Variant) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs) | MModAdr, &AdrResult);
2255
        if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit))
2256
        {
2257
          CodeLen = 0;
2258
          WrError(ErrNum_InvOpSize);
2259
        }
2260
        else if (AdrResult.AdrMode == ModNone)
2261
          CodeLen = 0;
2262
        else
2263
        {
2264
          Boolean CombinationOK;
2265
 
2266
          /* ColdFire does not allow all combinations of src+dest: */
2267
 
2268
          if (pCurrCPUProps->Family == eColdfire)
2269
            switch (SrcAdrNum)
2270
            {
2271
              case ModData: /* Dn */
2272
              case ModAdr: /* An */
2273
              case ModAdrI: /* (An) */
2274
              case ModPost: /* (An)+ */
2275
              case ModPre: /* -(An) */
2276
                CombinationOK = True;
2277
                break;
2278
              case ModDAdrI: /* (d16,An) */
2279
              case ModPC: /* (d16,PC) */
2280
                CombinationOK = (AdrResult.AdrMode != ModAIX)   /* no (d8,An,Xi) */
2281
                             && (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
2282
                break;
2283
              case ModAIX: /* (d8,An,Xi) */
2284
              case ModPCIdx: /* (d8,PC,Xi) */
2285
              case ModAbs: /* (xxx).W/L */
2286
                CombinationOK = (AdrResult.AdrMode != ModDAdrI)   /* no (d16,An) */
2287
                             && (AdrResult.AdrMode != ModAIX)   /* no (d8,An,Xi) */
2288
                             && (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
2289
                break;
2290
              case ModImm: /* #xxx */
2291
                if (AdrResult.AdrMode == ModDAdrI) /* (d16,An) OK for 8/16 bit starting with ISA B */
2292
                  CombinationOK = (pCurrCPUProps->CfISA >= eCfISA_B) && (OpSize <= eSymbolSize16Bit);
2293
                else
2294
                  CombinationOK = (AdrResult.AdrMode != ModAIX)   /* no (d8,An,Xi) */
2295
                               && (AdrResult.AdrMode != ModAbs); /* no (xxx).W/L */
2296
                break;
2297
              default: /* should not occur */
2298
                CombinationOK = False;
2299
            }
2300
          else
2301
            CombinationOK = True;
2302
          if (!CombinationOK)
2303
          {
2304
            WrError(ErrNum_InvAddrMode);
2305
            CodeLen = 0;
2306
          }
2307
          else
2308
          {
2309
            AdrResult.AdrPart = ((AdrResult.AdrPart & 7) << 3) | (AdrResult.AdrPart >> 3);
2310
            WAsmCode[0] |= AdrResult.AdrPart << 6;
2311
            CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
2312
            CodeLen += AdrResult.Cnt;
2313
          }
2314
        }
2315
      }
2316
    }
2317
  }
2318
}
2319
 
2320
static void DecodeLEA(Word Index)
2321
{
2322
  UNUSED(Index);
2323
 
2324
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2325
  else if (!ChkArgCnt(2, 2));
2326
  else
2327
  {
2328
    tAdrResult AdrResult;
2329
 
2330
    if (DecodeAdr(&ArgStr[2], MModAdr, &AdrResult))
2331
    {
2332
      OpSize = eSymbolSize8Bit;
2333
      WAsmCode[0] = 0x41c0 | ((AdrResult.AdrPart & 7) << 9);
2334
      if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
2335
      {
2336
        WAsmCode[0] |= AdrResult.AdrPart;
2337
        CodeLen = 2 + AdrResult.Cnt;
2338
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2339
      }
2340
    }
2341
  }
2342
}
2343
 
2344
/* 0=ASR 1=ASL 2=LSR 3=LSL 4=ROXR 5=ROXL 6=ROR 7=ROL */
2345
 
2346
static void DecodeShift(Word Index)
2347
{
2348
  Boolean ValOK;
2349
  Byte HVal8;
2350
  Word LFlag = (Index >> 2), Op = Index & 3;
2351
 
2352
  if (!ChkArgCnt(1, 2));
2353
  else if ((*OpPart.str.p_str == 'R') && (!CheckNoFamily(1 << eColdfire)));
2354
  else
2355
  {
2356
    tAdrResult AdrResult;
2357
 
2358
    if (DecodeAdr(&ArgStr[ArgCnt], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult) == ModData)
2359
    {
2360
      if (CheckColdSize())
2361
      {
2362
        WAsmCode[0] = 0xe000 | AdrResult.AdrPart | (Op << 3) | (OpSize << 6) | (LFlag << 8);
2363
        OpSize = eSymbolSizeShiftCnt;
2364
        if (ArgCnt == 2)
2365
          DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult);
2366
        else
2367
        {
2368
          AdrResult.AdrMode = ModImm;
2369
          AdrResult.Vals[0] = 1;
2370
        }
2371
        if ((AdrResult.AdrMode == ModData) || ((AdrResult.AdrMode == ModImm) && (Lo(AdrResult.Vals[0]) >= 1) && (Lo(AdrResult.Vals[0]) <= 8)))
2372
        {
2373
          CodeLen = 2;
2374
          WAsmCode[0] |= (AdrResult.AdrMode == ModData) ? 0x20 | (AdrResult.AdrPart << 9) : ((AdrResult.Vals[0] & 7) << 9);
2375
        }
2376
        else
2377
          WrStrErrorPos(ErrNum_InvShiftArg, &ArgStr[1]);
2378
      }
2379
    }
2380
    else if (AdrResult.AdrMode != ModNone)
2381
    {
2382
      if (pCurrCPUProps->Family == eColdfire) WrError(ErrNum_InvAddrMode);
2383
      else
2384
      {
2385
        if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
2386
        else
2387
        {
2388
          WAsmCode[0] = 0xe0c0 | AdrResult.AdrPart | (Op << 9) | (LFlag << 8);
2389
          CopyAdrVals(WAsmCode + 1, &AdrResult);
2390
          if (2 == ArgCnt)
2391
          {
2392
            HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], !!(*ArgStr[1].str.p_str == '#'), Int8, &ValOK);
2393
          }
2394
          else
2395
          {
2396
            HVal8 = 1;
2397
            ValOK = True;
2398
          }
2399
          if ((ValOK) && (HVal8 == 1))
2400
            CodeLen = 2 + AdrResult.Cnt;
2401
          else
2402
            WrStrErrorPos(ErrNum_Only1, &ArgStr[1]);
2403
        }
2404
      }
2405
    }
2406
  }
2407
}
2408
 
2409
/*!------------------------------------------------------------------------
2410
 * \fn     DecodeADDQSUBQ(Word Index)
2411
 * \brief  Handle ADDQ/SUBQ Instructions
2412
 * \param  Index ADDQ=0 SUBQ=1
2413
 * ------------------------------------------------------------------------ */
2414
 
2415
static void DecodeADDQSUBQ(Word Index)
2416
{
2417
  LongWord ImmVal;
2418
  Boolean ValOK;
2419
  tSymbolFlags Flags;
2420
  tAdrResult AdrResult;
2421
 
2422
  if (!CheckColdSize())
2423
    return;
2424
 
2425
  if (!ChkArgCnt(2, 2))
2426
    return;
2427
 
2428
  if (!DecodeAdr(&ArgStr[2], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2429
    return;
2430
 
2431
  if ((ModAdr == AdrResult.AdrMode) && (eSymbolSize8Bit == OpSize))
2432
  {
2433
    WrError(ErrNum_InvOpSize);
2434
    return;
2435
  }
2436
 
2437
  WAsmCode[0] = 0x5000 | AdrResult.AdrPart | (OpSize << 6) | (Index << 8);
2438
  CopyAdrVals(WAsmCode + 1, &AdrResult);
2439
  ImmVal = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].str.p_str == '#'), UInt32, &ValOK, &Flags);
2440
  if (mFirstPassUnknownOrQuestionable(Flags))
2441
    ImmVal = 1;
2442
  if (ValOK && ((ImmVal < 1) || (ImmVal > 8)))
2443
  {
2444
    WrError(ErrNum_Range18);
2445
    ValOK = False;
2446
  }
2447
  if (ValOK)
2448
  {
2449
    CodeLen = 2 + AdrResult.Cnt;
2450
    WAsmCode[0] |= (ImmVal & 7) << 9;
2451
  }
2452
}
2453
 
2454
/* 0=SUBX 1=ADDX */
2455
 
2456
static void DecodeADDXSUBX(Word Index)
2457
{
2458
  if (CheckColdSize())
2459
  {
2460
    if (ChkArgCnt(2, 2))
2461
    {
2462
      tAdrResult AdrResult;
2463
 
2464
      if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
2465
      {
2466
        WAsmCode[0] = 0x9100 | (OpSize << 6) | (AdrResult.AdrPart & 7) | (Index << 14);
2467
        if (AdrResult.AdrMode == ModPre)
2468
          WAsmCode[0] |= 8;
2469
        if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
2470
        {
2471
          CodeLen = 2;
2472
          WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
2473
        }
2474
      }
2475
    }
2476
  }
2477
}
2478
 
2479
static void DecodeCMPM(Word Index)
2480
{
2481
  UNUSED(Index);
2482
 
2483
  if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
2484
  else if (ChkArgCnt(2, 2)
2485
        && CheckNoFamily(1 << eColdfire))
2486
  {
2487
    tAdrResult AdrResult;
2488
 
2489
    if (DecodeAdr(&ArgStr[1], MModPost, &AdrResult) == ModPost)
2490
    {
2491
      WAsmCode[0] = 0xb108 | (OpSize << 6) | (AdrResult.AdrPart & 7);
2492
      if (DecodeAdr(&ArgStr[2], MModPost, &AdrResult) == ModPost)
2493
      {
2494
        WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
2495
        CodeLen = 2;
2496
      }
2497
    }
2498
  }
2499
}
2500
 
2501
/* 0=SUB 1=CMP 2=ADD +4=..I +8=..A */
2502
 
2503
static void DecodeADDSUBCMP(Word Index)
2504
{
2505
  Word Op = Index & 3, Reg;
2506
  unsigned Variant = Index & VariantMask;
2507
  Word DestMask, SrcMask;
2508
  Boolean OpSizeOK;
2509
 
2510
  if (I_Variant == Variant)
2511
    SrcMask = MModImm;
2512
  else
2513
    SrcMask = MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm;
2514
 
2515
  if (A_Variant == Variant)
2516
    DestMask = MModAdr;
2517
  else
2518
  {
2519
    DestMask = MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
2520
 
2521
    /* Since CMP only reads operands, PC-relative addressing is also
2522
       allowed for the second operand on 68020++ */
2523
 
2524
    if ((as_toupper(*OpPart.str.p_str) == 'C')
2525
     && (pCurrCPUProps->Family > e68KGen1b))
2526
      DestMask |= MModPC | MModPCIdx;
2527
  }
2528
 
2529
  /* ColdFire ISA B ff. allows 8/16 bit operand size of CMP: */
2530
 
2531
  if (OpSize > eSymbolSize32Bit)
2532
    OpSizeOK = False;
2533
  else if (OpSize == eSymbolSize32Bit)
2534
    OpSizeOK = True;
2535
  else
2536
    OpSizeOK = (pCurrCPUProps->Family != eColdfire)
2537
            || ((pCurrCPUProps->CfISA >= eCfISA_B) && (Op == 1));
2538
 
2539
  if (!OpSizeOK) WrError(ErrNum_InvOpSize);
2540
  else
2541
  {
2542
    if (ChkArgCnt(2, 2))
2543
    {
2544
      tAdrResult AdrResult;
2545
 
2546
      switch (DecodeAdr(&ArgStr[2], DestMask, &AdrResult))
2547
      {
2548
        case ModAdr: /* ADDA/SUBA/CMPA ? */
2549
          if (OpSize == eSymbolSize8Bit) WrError(ErrNum_InvOpSize);
2550
          else
2551
          {
2552
            WAsmCode[0] = 0x90c0 | ((AdrResult.AdrPart & 7) << 9) | (Op << 13);
2553
            if (OpSize == eSymbolSize32Bit) WAsmCode[0] |= 0x100;
2554
            if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult))
2555
            {
2556
              WAsmCode[0] |= AdrResult.AdrPart;
2557
              CodeLen = 2 + AdrResult.Cnt;
2558
              CopyAdrVals(WAsmCode + 1, &AdrResult);
2559
            }
2560
          }
2561
          break;
2562
 
2563
        case ModData: /* ADD/SUB/CMP <ea>,Dn ? */
2564
          WAsmCode[0] = 0x9000 | (OpSize << 6) | ((Reg = AdrResult.AdrPart) << 9) | (Op << 13);
2565
          DecodeAdr(&ArgStr[1], SrcMask, &AdrResult);
2566
 
2567
          /* CMP.B An,Dn allowed for Coldfire? */
2568
 
2569
          if ((AdrResult.AdrMode == ModAdr) && (OpSize == eSymbolSize8Bit) && (pCurrCPUProps->Family != eColdfire)) WrError(ErrNum_InvOpSize);
2570
          if (AdrResult.AdrMode != ModNone)
2571
          {
2572
            if ((AdrResult.AdrMode == ModImm) && (Variant == I_Variant))
2573
            {
2574
              if (Op == 1) Op = 8;
2575
              WAsmCode[0] = 0x400 | (OpSize << 6) | (Op << 8) | Reg;
2576
            }
2577
            else
2578
              WAsmCode[0] |= AdrResult.AdrPart;
2579
            CopyAdrVals(WAsmCode + 1, &AdrResult);
2580
            CodeLen = 2 + AdrResult.Cnt;
2581
          }
2582
          break;
2583
 
2584
        case ModNone:
2585
          break;
2586
 
2587
        default: /* CMP/ADD/SUB <ea>, Dn */
2588
          if (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult) == ModImm)        /* ADDI/SUBI/CMPI ? */
2589
          {
2590
            /* we have to set the PC offset before we decode the destination operand.  Luckily,
2591
               this is only needed afterwards for an immediate source operand, so we know the
2592
               # of words ahead: */
2593
 
2594
            if (*ArgStr[1].str.p_str == '#')
2595
              RelPos += (OpSize == eSymbolSize32Bit) ? 4 : 2;
2596
 
2597
            if (Op == 1) Op = 8;
2598
            WAsmCode[0] = 0x400 | (OpSize << 6) | (Op << 8);
2599
            CodeLen = 2 + AdrResult.Cnt;
2600
            CopyAdrVals(WAsmCode + 1, &AdrResult);
2601
            if (DecodeAdr(&ArgStr[2], (pCurrCPUProps->Family == eColdfire) ? (Word)MModData : DestMask, &AdrResult))
2602
            {
2603
              WAsmCode[0] |= AdrResult.AdrPart;
2604
              CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
2605
              CodeLen += AdrResult.Cnt;
2606
            }
2607
            else
2608
              CodeLen = 0;
2609
          }
2610
          else if (AdrResult.AdrMode != ModNone)    /* ADD Dn,<EA> ? */
2611
          {
2612
            if (Op == 1) WrError(ErrNum_InvCmpMode);
2613
            else
2614
            {
2615
              WAsmCode[0] = 0x9100 | (OpSize << 6) | (AdrResult.AdrPart << 9) | (Op << 13);
2616
              if (DecodeAdr(&ArgStr[2], DestMask, &AdrResult))
2617
              {
2618
                CodeLen = 2 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 1, &AdrResult);
2619
                WAsmCode[0] |= AdrResult.AdrPart;
2620
              }
2621
            }
2622
          }
2623
      }
2624
    }
2625
  }
2626
}
2627
 
2628
/* 0=OR 1=AND +4=..I */
2629
 
2630
static void DecodeANDOR(Word Index)
2631
{
2632
  Word Op = Index & 3, Reg;
2633
  char Variant = Index & VariantMask;
2634
  tAdrResult AdrResult;
2635
 
2636
  if (!ChkArgCnt(2, 2));
2637
  else if (CheckColdSize())
2638
  {
2639
    if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR"))     /* AND #...,CCR */
2640
    {
2641
      if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
2642
      else if (!(pCurrCPUProps->SuppFlags & eFlagLogCCR)) WrError(ErrNum_InstructionNotSupported);
2643
      {
2644
        WAsmCode[0] = 0x003c | (Op << 9);
2645
        OpSize = eSymbolSize8Bit;
2646
        if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
2647
        {
2648
          CodeLen = 4;
2649
          WAsmCode[1] = AdrResult.Vals[0];
2650
        }
2651
      }
2652
    }
2653
    else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR")) /* AND #...,SR */
2654
    {
2655
      if (*AttrPart.str.p_str && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
2656
      else if (CheckNoFamily(1 << eColdfire))
2657
      {
2658
        WAsmCode[0] = 0x007c | (Op << 9);
2659
        OpSize = eSymbolSize16Bit;
2660
        if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
2661
        {
2662
          CodeLen = 4;
2663
          WAsmCode[1] = AdrResult.Vals[0];
2664
          CheckSup();
2665
        }
2666
      }
2667
    }
2668
    else
2669
    {
2670
      DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult);
2671
      if (AdrResult.AdrMode == ModData)                 /* AND <EA>,Dn */
2672
      {
2673
        Reg = AdrResult.AdrPart;
2674
        WAsmCode[0] = 0x8000 | (OpSize << 6) | (Reg << 9) | (Op << 14);
2675
        if (DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs) | MModImm, &AdrResult))
2676
        {
2677
          if ((AdrResult.AdrMode == ModImm) && (Variant == I_Variant))
2678
            WAsmCode[0] = (OpSize << 6) | (Op << 9) | Reg;
2679
          else
2680
            WAsmCode[0] |= AdrResult.AdrPart;
2681
          CodeLen = 2 + AdrResult.Cnt;
2682
          CopyAdrVals(WAsmCode + 1, &AdrResult);
2683
        }
2684
      }
2685
      else if (AdrResult.AdrMode != ModNone)                 /* AND ...,<EA> */
2686
      {
2687
        if (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult) == ModImm)                   /* AND #..,<EA> */
2688
        {
2689
          WAsmCode[0] = (OpSize << 6) | (Op << 9);
2690
          CodeLen = 2 + AdrResult.Cnt;
2691
          CopyAdrVals(WAsmCode + 1, &AdrResult);
2692
          if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2693
          {
2694
            WAsmCode[0] |= AdrResult.AdrPart;
2695
            CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
2696
            CodeLen += AdrResult.Cnt;
2697
          }
2698
          else
2699
            CodeLen = 0;
2700
        }
2701
        else if (AdrResult.AdrMode != ModNone)               /* AND Dn,<EA> ? */
2702
        {
2703
          WAsmCode[0] = 0x8100 | (OpSize << 6) | (AdrResult.AdrPart << 9) | (Op << 14);
2704
          if (DecodeAdr(&ArgStr[2], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2705
          {
2706
            CodeLen = 2 + AdrResult.Cnt;
2707
            CopyAdrVals(WAsmCode + 1, &AdrResult);
2708
            WAsmCode[0] |= AdrResult.AdrPart;
2709
          }
2710
        }
2711
      }
2712
    }
2713
  }
2714
}
2715
 
2716
/* 0=EOR 4=EORI */
2717
 
2718
static void DecodeEOR(Word Index)
2719
{
2720
  unsigned Variant = Index | VariantMask;
2721
  tAdrResult AdrResult;
2722
 
2723
  if (!ChkArgCnt(2, 2));
2724
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "CCR"))
2725
  {
2726
    if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
2727
    else if (CheckNoFamily(1 << eColdfire))
2728
    {
2729
      WAsmCode[0] = 0xa3c;
2730
      OpSize = eSymbolSize8Bit;
2731
      if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
2732
      {
2733
        CodeLen = 4;
2734
        WAsmCode[1] = AdrResult.Vals[0];
2735
      }
2736
    }
2737
  }
2738
  else if (!as_strcasecmp(ArgStr[2].str.p_str, "SR"))
2739
  {
2740
    if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
2741
    else if (CheckNoFamily(1 << eColdfire))
2742
    {
2743
      WAsmCode[0] = 0xa7c;
2744
      if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
2745
      {
2746
        CodeLen = 4;
2747
        WAsmCode[1] = AdrResult.Vals[0];
2748
        CheckSup();
2749
      }
2750
    }
2751
  }
2752
  else if (CheckColdSize())
2753
  {
2754
    if (DecodeAdr(&ArgStr[1], ((Variant == I_Variant) ? 0 : MModData) | MModImm, &AdrResult) == ModData)
2755
    {
2756
      WAsmCode[0] = 0xb100 | (AdrResult.AdrPart << 9) | (OpSize << 6);
2757
      if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2758
      {
2759
        CodeLen = 2 + AdrResult.Cnt;
2760
        CopyAdrVals(WAsmCode + 1, &AdrResult);
2761
        WAsmCode[0] |= AdrResult.AdrPart;
2762
      }
2763
    }
2764
    else if (AdrResult.AdrMode == ModImm)
2765
    {
2766
      WAsmCode[0] = 0x0a00 | (OpSize << 6);
2767
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2768
      CodeLen = 2 + AdrResult.Cnt;
2769
      if (DecodeAdr(&ArgStr[2], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
2770
      {
2771
        CopyAdrVals(WAsmCode + (CodeLen >> 1), &AdrResult);
2772
        CodeLen += AdrResult.Cnt;
2773
        WAsmCode[0] |= AdrResult.AdrPart;
2774
      }
2775
      else CodeLen = 0;
2776
    }
2777
  }
2778
}
2779
 
2780
static void DecodePEA(Word Index)
2781
{
2782
  UNUSED(Index);
2783
 
2784
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_UseLessAttr);
2785
  else if (ChkArgCnt(1, 1))
2786
  {
2787
    tAdrResult AdrResult;
2788
 
2789
    OpSize = eSymbolSize8Bit;
2790
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
2791
    {
2792
      CodeLen = 2 + AdrResult.Cnt;
2793
      WAsmCode[0] = 0x4840 | AdrResult.AdrPart;
2794
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2795
    }
2796
  }
2797
}
2798
 
2799
static void DecodeCLRTST(Word IsTST)
2800
{
2801
  if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
2802
  else if (ChkArgCnt(1, 1))
2803
  {
2804
    Word w1 = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
2805
    tAdrResult AdrResult;
2806
 
2807
    switch (pCurrCPUProps->Family)
2808
    {
2809
      case eCPU32:
2810
      case e68KGen2:
2811
      case e68KGen3:
2812
        if (IsTST)
2813
        {
2814
          w1 |= MModPC | MModPCIdx | MModImm;
2815
          if (OpSize != eSymbolSize8Bit)
2816
            w1 |= MModAdr;
2817
        }
2818
        break;
2819
      default:
2820
        break;
2821
    }
2822
    if (DecodeAdr(&ArgStr[1], w1, &AdrResult))
2823
    {
2824
      CodeLen = 2 + AdrResult.Cnt;
2825
      WAsmCode[0] = 0x4200 | (IsTST << 11) | (OpSize << 6) | AdrResult.AdrPart;
2826
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2827
    }
2828
  }
2829
}
2830
 
2831
/* 0=JSR 1=JMP */
2832
 
2833
static void DecodeJSRJMP(Word Index)
2834
{
2835
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
2836
  else if (ChkArgCnt(1, 1))
2837
  {
2838
    tAdrResult AdrResult;
2839
 
2840
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
2841
    {
2842
      CodeLen = 2 + AdrResult.Cnt;
2843
      WAsmCode[0] = 0x4e80 | (Index << 6) | AdrResult.AdrPart;
2844
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2845
    }
2846
  }
2847
}
2848
 
2849
/* 0=TAS 1=NBCD */
2850
 
2851
static void DecodeNBCDTAS(Word Index)
2852
{
2853
  Boolean Allowed;
2854
 
2855
  /* TAS is allowed on ColdFire ISA B ff. ... */
2856
 
2857
  if (pCurrCPUProps->Family != eColdfire)
2858
    Allowed = True;
2859
  else
2860
    Allowed = Index ? False : (pCurrCPUProps->CfISA >= eCfISA_B);
2861
 
2862
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
2863
  else if (!Allowed) WrError(ErrNum_InstructionNotSupported);
2864
  else if (ChkArgCnt(1, 1))
2865
  {
2866
    tAdrResult AdrResult;
2867
 
2868
    OpSize = eSymbolSize8Bit;
2869
 
2870
    /* ...but not on data register: */
2871
 
2872
    if (DecodeAdr(&ArgStr[1], ((pCurrCPUProps->Family == eColdfire) ? 0 : MModData) | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2873
    {
2874
      CodeLen = 2 + AdrResult.Cnt;
2875
      WAsmCode[0] = (Index == 1) ? 0x4800 : 0x4ac0;
2876
      WAsmCode[0] |= AdrResult.AdrPart;
2877
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2878
    }
2879
  }
2880
}
2881
 
2882
/* 0=NEGX 2=NEG 3=NOT */
2883
 
2884
static void DecodeNEGNOT(Word Index)
2885
{
2886
  if (ChkArgCnt(1, 1)
2887
   && CheckColdSize())
2888
  {
2889
    tAdrResult AdrResult;
2890
 
2891
    if (DecodeAdr(&ArgStr[1], (pCurrCPUProps->Family == eColdfire) ? MModData : (MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
2892
    {
2893
      CodeLen = 2 + AdrResult.Cnt;
2894
      WAsmCode[0] = 0x4000 | (Index << 9) | (OpSize << 6) | AdrResult.AdrPart;
2895
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2896
    }
2897
  }
2898
}
2899
 
2900
static void DecodeSWAP(Word Index)
2901
{
2902
  UNUSED(Index);
2903
 
2904
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2905
  else if (ChkArgCnt(1, 1))
2906
  {
2907
    tAdrResult AdrResult;
2908
 
2909
    if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
2910
    {
2911
      CodeLen = 2;
2912
      WAsmCode[0] = 0x4840 | AdrResult.AdrPart;
2913
    }
2914
  }
2915
}
2916
 
2917
static void DecodeUNLK(Word Index)
2918
{
2919
  UNUSED(Index);
2920
 
2921
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
2922
  else if (ChkArgCnt(1, 1))
2923
  {
2924
    tAdrResult AdrResult;
2925
 
2926
    if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
2927
    {
2928
      CodeLen = 2;
2929
      WAsmCode[0] = 0x4e58 | AdrResult.AdrPart;
2930
    }
2931
  }
2932
}
2933
 
2934
static void DecodeEXT(Word Index)
2935
{
2936
  UNUSED(Index);
2937
 
2938
  if (!ChkArgCnt(1, 1));
2939
  else if ((OpSize == eSymbolSize8Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
2940
  else
2941
  {
2942
    tAdrResult AdrResult;
2943
 
2944
    if (DecodeAdr(&ArgStr[1], MModData, &AdrResult) == ModData)
2945
    {
2946
      WAsmCode[0] = 0x4880 | AdrResult.AdrPart | (((Word)OpSize - 1) << 6);
2947
      CodeLen = 2;
2948
    }
2949
  }
2950
}
2951
 
2952
static void DecodeWDDATA(Word Index)
2953
{
2954
  UNUSED(Index);
2955
 
2956
  if (!ChkArgCnt(1, 1));
2957
  else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
2958
  else if (CheckFamily(1 << eColdfire))
2959
  {
2960
    tAdrResult AdrResult;
2961
 
2962
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
2963
    {
2964
      WAsmCode[0] = 0xf400 + (OpSize << 6) + AdrResult.AdrPart;
2965
      CopyAdrVals(WAsmCode + 1, &AdrResult);
2966
      CodeLen = 2 + AdrResult.Cnt;
2967
      CheckSup();
2968
    }
2969
  }
2970
}
2971
 
2972
static void DecodeWDEBUG(Word Index)
2973
{
2974
  UNUSED(Index);
2975
 
2976
  if (ChkArgCnt(1, 1)
2977
   && CheckFamily(1 << eColdfire)
2978
   && CheckColdSize())
2979
  {
2980
    tAdrResult AdrResult;
2981
 
2982
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI, &AdrResult))
2983
    {
2984
      WAsmCode[0] = 0xfbc0 + AdrResult.AdrPart;
2985
      WAsmCode[1] = 0x0003;
2986
      CopyAdrVals(WAsmCode + 2, &AdrResult);
2987
      CodeLen = 4 + AdrResult.Cnt;
2988
      CheckSup();
2989
    }
2990
  }
2991
}
2992
 
2993
static void DecodeFixed(Word Index)
2994
{
2995
  FixedOrder *FixedZ = FixedOrders + Index;
2996
 
2997
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
2998
  else if (ChkArgCnt(0, 0)
2999
        && CheckFamily(FixedZ->FamilyMask))
3000
  {
3001
    CodeLen = 2;
3002
    WAsmCode[0] = FixedZ->Code;
3003
    if (FixedZ->MustSup)
3004
      CheckSup();
3005
  }
3006
}
3007
 
3008
static void DecodeMOVEM(Word Index)
3009
{
3010
  int z;
3011
  UNUSED(Index);
3012
 
3013
  if (!ChkArgCnt(2, 2));
3014
  else if ((OpSize < eSymbolSize16Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3015
  else if ((pCurrCPUProps->Family == eColdfire) && (OpSize == 1)) WrError(ErrNum_InvOpSize);
3016
  else
3017
  {
3018
    tAdrResult AdrResult;
3019
 
3020
    RelPos = 4;
3021
    if (DecodeRegList(&ArgStr[2], WAsmCode + 1))
3022
    {
3023
      if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModPost | MModAIX | MModPC | MModPCIdx | MModAbs), &AdrResult))
3024
      {
3025
        WAsmCode[0] = 0x4c80 | AdrResult.AdrPart | ((OpSize - 1) << 6);
3026
        CodeLen = 4 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 2, &AdrResult);
3027
      }
3028
    }
3029
    else if (DecodeRegList(&ArgStr[1], WAsmCode + 1))
3030
    {
3031
      if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI  | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModPre | MModAIX | MModAbs), &AdrResult))
3032
      {
3033
        WAsmCode[0] = 0x4880 | AdrResult.AdrPart | ((OpSize - 1) << 6);
3034
        CodeLen = 4 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 2, &AdrResult);
3035
        if (AdrResult.AdrMode == ModPre)
3036
        {
3037
          Word Tmp = WAsmCode[1];
3038
 
3039
          WAsmCode[1] = 0;
3040
          for (z = 0; z < 16; z++)
3041
          {
3042
            WAsmCode[1] = (WAsmCode[1] << 1) + (Tmp & 1);
3043
            Tmp >>= 1;
3044
          }
3045
        }
3046
      }
3047
    }
3048
    else WrError(ErrNum_InvRegList);
3049
  }
3050
}
3051
 
3052
static void DecodeMOVEQ(Word Index)
3053
{
3054
  UNUSED(Index);
3055
 
3056
  if (!ChkArgCnt(2, 2));
3057
  else if ((*AttrPart.str.p_str) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3058
  else if (*ArgStr[1].str.p_str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
3059
  else
3060
  {
3061
    tAdrResult AdrResult;
3062
 
3063
    if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
3064
    {
3065
      Boolean OK;
3066
      tSymbolFlags Flags;
3067
      LongWord Value;
3068
 
3069
      WAsmCode[0] = 0x7000 | (AdrResult.AdrPart << 9);
3070
      Value = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, Int32, &OK, &Flags);
3071
      if (mFirstPassUnknown(Flags))
3072
        Value &= 0x7f;
3073
      else if ((Value > 0xff) && (Value < 0xffffff80ul))
3074
        WrStrErrorPos((Value & 0x80000000ul) ? ErrNum_UnderRange : ErrNum_OverRange, &ArgStr[1]);
3075
      else
3076
      {
3077
        if ((Value >= 0x80) && (Value <= 0xff))
3078
        {
3079
          char str[40];
3080
          LargeWord v1 = Value, v2 = Value | 0xffffff00ul;
3081
 
3082
          as_snprintf(str, sizeof(str), "%llx -> %llx", v1, v2);
3083
          WrXErrorPos(ErrNum_SignExtension, str, &ArgStr[1].Pos);
3084
        }
3085
        CodeLen = 2;
3086
        WAsmCode[0] |= Value & 0xff;
3087
      }
3088
    }
3089
  }
3090
}
3091
 
3092
static void DecodeSTOP(Word Index)
3093
{
3094
  Word HVal;
3095
  Boolean ValOK;
3096
  UNUSED(Index);
3097
 
3098
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3099
  else if (!ChkArgCnt(1, 1));
3100
  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
3101
  else
3102
  {
3103
    HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
3104
    if (ValOK)
3105
    {
3106
      CodeLen = 4;
3107
      WAsmCode[0] = 0x4e72;
3108
      WAsmCode[1] = HVal;
3109
      CheckSup();
3110
    }
3111
  }
3112
}
3113
 
3114
static void DecodeLPSTOP(Word Index)
3115
{
3116
  Word HVal;
3117
  Boolean ValOK;
3118
  UNUSED(Index);
3119
 
3120
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3121
  else if (!ChkArgCnt(1, 1));
3122
  else if (!CheckFamily(1 << eCPU32));
3123
  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
3124
  else
3125
  {
3126
    HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
3127
    if (ValOK)
3128
    {
3129
      CodeLen = 6;
3130
      WAsmCode[0] = 0xf800;
3131
      WAsmCode[1] = 0x01c0;
3132
      WAsmCode[2] = HVal;
3133
      CheckSup();
3134
    }
3135
  }
3136
}
3137
 
3138
static void DecodeTRAP(Word Index)
3139
{
3140
  Byte HVal8;
3141
  Boolean ValOK;
3142
  UNUSED(Index);
3143
 
3144
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3145
  else if (!ChkArgCnt(1, 1));
3146
  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
3147
  else
3148
  {
3149
    HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int4, &ValOK);
3150
    if (ValOK)
3151
    {
3152
      CodeLen = 2;
3153
      WAsmCode[0] = 0x4e40 + (HVal8 & 15);
3154
    }
3155
  }
3156
}
3157
 
3158
static void DecodeBKPT(Word Index)
3159
{
3160
  Byte HVal8;
3161
  Boolean ValOK;
3162
  UNUSED(Index);
3163
 
3164
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3165
  else if (!ChkArgCnt(1, 1));
3166
  else if (!CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)));
3167
  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
3168
  else
3169
  {
3170
    HVal8 = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt3, &ValOK);
3171
    if (ValOK)
3172
    {
3173
      CodeLen = 2;
3174
      WAsmCode[0] = 0x4848 + (HVal8 & 7);
3175
    }
3176
  }
3177
  UNUSED(Index);
3178
}
3179
 
3180
static void DecodeRTD(Word Index)
3181
{
3182
  Word HVal;
3183
  Boolean ValOK;
3184
  UNUSED(Index);
3185
 
3186
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3187
  else if (!ChkArgCnt(1, 1));
3188
  else if (!CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)));
3189
  else if (*ArgStr[1].str.p_str != '#') WrError(ErrNum_OnlyImmAddr);
3190
  else
3191
  {
3192
    HVal = EvalStrIntExpressionOffs(&ArgStr[1], 1, Int16, &ValOK);
3193
    if (ValOK)
3194
    {
3195
      CodeLen = 4;
3196
      WAsmCode[0] = 0x4e74;
3197
      WAsmCode[1] = HVal;
3198
    }
3199
  }
3200
}
3201
 
3202
static void DecodeEXG(Word Index)
3203
{
3204
  Word HReg;
3205
  UNUSED(Index);
3206
 
3207
  if ((*AttrPart.str.p_str) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3208
  else if (ChkArgCnt(2, 2)
3209
        && CheckNoFamily(1 << eColdfire))
3210
  {
3211
    tAdrResult AdrResult;
3212
 
3213
    if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult) == ModData)
3214
    {
3215
      WAsmCode[0] = 0xc100 | (AdrResult.AdrPart << 9);
3216
      if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult) == ModData)
3217
      {
3218
        WAsmCode[0] |= 0x40 | AdrResult.AdrPart;
3219
        CodeLen = 2;
3220
      }
3221
      else if (AdrResult.AdrMode == ModAdr)
3222
      {
3223
        WAsmCode[0] |= 0x88 | (AdrResult.AdrPart & 7);
3224
        CodeLen = 2;
3225
      }
3226
    }
3227
    else if (AdrResult.AdrMode == ModAdr)
3228
    {
3229
      WAsmCode[0] = 0xc100;
3230
      HReg = AdrResult.AdrPart & 7;
3231
      if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult) == ModData)
3232
      {
3233
        WAsmCode[0] |= 0x88 | (AdrResult.AdrPart << 9) | HReg;
3234
        CodeLen = 2;
3235
      }
3236
      else
3237
      {
3238
        WAsmCode[0] |= 0x48 | (HReg << 9) | (AdrResult.AdrPart & 7);
3239
        CodeLen = 2;
3240
      }
3241
    }
3242
  }
3243
}
3244
 
3245
static void DecodeMOVE16(Word Index)
3246
{
3247
  Word z, z2, w1, w2;
3248
  UNUSED(Index);
3249
 
3250
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3251
  else if (ChkArgCnt(2, 2)
3252
        && CheckFamily(1 << e68KGen3))
3253
  {
3254
    tAdrResult AdrResult;
3255
 
3256
    if (DecodeAdr(&ArgStr[1], MModPost | MModAdrI | MModAbs, &AdrResult))
3257
    {
3258
      w1 = AdrResult.AdrMode;
3259
      z = AdrResult.AdrPart & 7;
3260
      if ((w1 == ModAbs) && (AdrResult.Cnt == 2))
3261
      {
3262
        AdrResult.Vals[1] = AdrResult.Vals[0];
3263
        AdrResult.Vals[0] = 0 - (AdrResult.Vals[1] >> 15);
3264
      }
3265
      if (DecodeAdr(&ArgStr[2], MModPost | MModAdrI | MModAbs, &AdrResult))
3266
      {
3267
        w2 = AdrResult.AdrMode;
3268
        z2 = AdrResult.AdrPart & 7;
3269
        if ((w2 == ModAbs) && (AdrResult.Cnt == 2))
3270
        {
3271
          AdrResult.Vals[1] = AdrResult.Vals[0];
3272
          AdrResult.Vals[0] = 0 - (AdrResult.Vals[1] >> 15);
3273
        }
3274
        if ((w1 == ModPost) && (w2 == ModPost))
3275
        {
3276
          WAsmCode[0] = 0xf620 + z;
3277
          WAsmCode[1] = 0x8000 + (z2 << 12);
3278
          CodeLen = 4;
3279
        }
3280
        else
3281
        {
3282
          WAsmCode[1] = AdrResult.Vals[0];
3283
          WAsmCode[2] = AdrResult.Vals[1];
3284
          CodeLen = 6;
3285
          if ((w1 == ModPost) && (w2 == ModAbs))
3286
            WAsmCode[0] = 0xf600 + z;
3287
          else if ((w1 == ModAbs) && (w2 == ModPost))
3288
            WAsmCode[0] = 0xf608 + z2;
3289
          else if ((w1 == ModAdrI) && (w2 == ModAbs))
3290
            WAsmCode[0] = 0xf610 + z;
3291
          else if ((w1 == ModAbs) && (w2 == ModAdrI))
3292
            WAsmCode[0] = 0xf618 + z2;
3293
          else
3294
          {
3295
            WrError(ErrNum_InvAddrMode);
3296
            CodeLen = 0;
3297
          }
3298
        }
3299
      }
3300
    }
3301
  }
3302
}
3303
 
3304
static void DecodeCacheAll(Word Index)
3305
{
3306
  Word w1;
3307
 
3308
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3309
  else if (!ChkArgCnt(1, 1));
3310
  else if (!CheckFamily(1 << e68KGen3));
3311
  else if (!CodeCache(ArgStr[1].str.p_str, &w1)) WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
3312
  else
3313
  {
3314
    WAsmCode[0] = 0xf418 + (w1 << 6) + (Index << 5);
3315
    CodeLen = 2;
3316
    CheckSup();
3317
  }
3318
}
3319
 
3320
static void DecodeCache(Word Index)
3321
{
3322
  Word w1;
3323
 
3324
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
3325
  else if (!ChkArgCnt(2, 2));
3326
  else if (!CheckFamily(1 << e68KGen3));
3327
  else if (!CodeCache(ArgStr[1].str.p_str, &w1)) WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[1]);
3328
  else
3329
  {
3330
    tAdrResult AdrResult;
3331
 
3332
    if (DecodeAdr(&ArgStr[2], MModAdrI, &AdrResult))
3333
    {
3334
      WAsmCode[0] = 0xf400 + (w1 << 6) + (Index << 3) + (AdrResult.AdrPart & 7);
3335
      CodeLen = 2;
3336
      CheckSup();
3337
    }
3338
  }
3339
}
3340
 
3341
static void DecodeMUL_DIV(Word Code)
3342
{
3343
  tAdrResult AdrResult;
3344
 
3345
  if (!ChkArgCnt(2, 2));
3346
  else if ((*OpPart.str.p_str == 'D') && !CheckNoFamily(1 << eColdfire));
3347
  else if (OpSize == eSymbolSize16Bit)
3348
  {
3349
    if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
3350
    {
3351
      WAsmCode[0] = 0x80c0 | (AdrResult.AdrPart << 9) | (Code & 0x0100);
3352
      if (!(Code & 1))
3353
        WAsmCode[0] |= 0x4000;
3354
      if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
3355
      {
3356
        WAsmCode[0] |= AdrResult.AdrPart;
3357
        CodeLen = 2 + AdrResult.Cnt; CopyAdrVals(WAsmCode + 1, &AdrResult);
3358
      }
3359
    }
3360
  }
3361
  else if (OpSize == eSymbolSize32Bit)
3362
  {
3363
    Word w1, w2;
3364
    Boolean OK;
3365
 
3366
    if (strchr(ArgStr[2].str.p_str, ':'))
3367
      OK = DecodeRegPair(&ArgStr[2], &w1, &w2);
3368
    else
3369
    {
3370
      OK = DecodeReg(&ArgStr[2], &w1, True) && (w1 < 8);
3371
      w2 = w1;
3372
    }
3373
    if (!OK) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
3374
    else
3375
    {
3376
      WAsmCode[1] = w1 | (w2 << 12) | ((Code & 0x0100) << 3);
3377
      RelPos = 4;
3378
      if (w1 != w2)
3379
        WAsmCode[1] |= 0x400;
3380
      if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
3381
      {
3382
        WAsmCode[0] = 0x4c00 + AdrResult.AdrPart + (Lo(Code) << 6);
3383
        CopyAdrVals(WAsmCode + 2, &AdrResult);
3384
        CodeLen = 4 + AdrResult.Cnt;
3385
        CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32) | ((w1 == w2) ? (1 << eColdfire) : 0));
3386
      }
3387
    }
3388
  }
3389
  else
3390
    WrError(ErrNum_InvOpSize);
3391
}
3392
 
3393
static void DecodeDIVL(Word Index)
3394
{
3395
  Word w1, w2;
3396
 
3397
  if (!*AttrPart.str.p_str)
3398
    OpSize = eSymbolSize32Bit;
3399
  if (!ChkArgCnt(2, 2));
3400
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
3401
  else if (OpSize != eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
3402
  else if (!DecodeRegPair(&ArgStr[2], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
3403
  else
3404
  {
3405
    tAdrResult AdrResult;
3406
 
3407
    RelPos = 4;
3408
    WAsmCode[1] = w1 | (w2 << 12) | (Index << 11);
3409
    if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
3410
    {
3411
      WAsmCode[0] = 0x4c40 + AdrResult.AdrPart;
3412
      CopyAdrVals(WAsmCode + 2, &AdrResult);
3413
      CodeLen = 4 + AdrResult.Cnt;
3414
    }
3415
  }
3416
}
3417
 
3418
static void DecodeASBCD(Word Index)
3419
{
3420
  if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3421
  else if (ChkArgCnt(2, 2)
3422
        && CheckNoFamily(1 << eColdfire))
3423
  {
3424
    tAdrResult AdrResult;
3425
 
3426
    OpSize = eSymbolSize8Bit;
3427
    if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
3428
    {
3429
      WAsmCode[0] = 0x8100 | (AdrResult.AdrPart & 7) | (Index << 14) | ((AdrResult.AdrMode == ModPre) ? 8 : 0);
3430
      if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
3431
      {
3432
        CodeLen = 2;
3433
        WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
3434
      }
3435
    }
3436
  }
3437
}
3438
 
3439
static void DecodeCHK(Word Index)
3440
{
3441
  UNUSED(Index);
3442
 
3443
  if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3444
  else if (ChkArgCnt(2, 2)
3445
        && CheckNoFamily(1 << eColdfire))
3446
  {
3447
    tAdrResult AdrResult;
3448
 
3449
    if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
3450
    {
3451
      WAsmCode[0] = 0x4000 | AdrResult.AdrPart | ((4 - OpSize) << 7);
3452
      CodeLen = 2 + AdrResult.Cnt;
3453
      CopyAdrVals(WAsmCode + 1, &AdrResult);
3454
      if (DecodeAdr(&ArgStr[2], MModData, &AdrResult) == ModData)
3455
        WAsmCode[0] |= WAsmCode[0] | (AdrResult.AdrPart << 9);
3456
      else
3457
        CodeLen = 0;
3458
    }
3459
  }
3460
}
3461
 
3462
static void DecodeLINK(Word Index)
3463
{
3464
  UNUSED(Index);
3465
 
3466
  if (!*AttrPart.str.p_str && (pCurrCPUProps->Family == eColdfire)) OpSize = eSymbolSize16Bit;
3467
  if ((OpSize < 1) || (OpSize > 2)) WrError(ErrNum_InvOpSize);
3468
  else if ((OpSize == eSymbolSize32Bit) && !CheckFamily((1 << eCPU32) | (1 << e68KGen2) | (1 << e68KGen3)));
3469
  else if (ChkArgCnt(2, 2))
3470
  {
3471
    tAdrResult AdrResult;
3472
 
3473
    if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
3474
    {
3475
      WAsmCode[0] = (OpSize == eSymbolSize16Bit) ? 0x4e50 : 0x4808;
3476
      WAsmCode[0] += AdrResult.AdrPart & 7;
3477
      if (DecodeAdr(&ArgStr[2], MModImm, &AdrResult) == ModImm)
3478
      {
3479
        CodeLen = 2 + AdrResult.Cnt;
3480
        memcpy(WAsmCode + 1, AdrResult.Vals, AdrResult.Cnt);
3481
      }
3482
    }
3483
  }
3484
}
3485
 
3486
static void DecodeMOVEP(Word Index)
3487
{
3488
  UNUSED(Index);
3489
 
3490
  if ((OpSize == eSymbolSize8Bit) || (OpSize > eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3491
  else if (ChkArgCnt(2, 2)
3492
        && CheckNoFamily(1 << eColdfire))
3493
  {
3494
    tAdrResult AdrResult;
3495
 
3496
    if (DecodeAdr(&ArgStr[1], MModData | MModDAdrI, &AdrResult) == ModData)
3497
    {
3498
      WAsmCode[0] = 0x188 | ((OpSize - 1) << 6) | (AdrResult.AdrPart << 9);
3499
      if (DecodeAdr(&ArgStr[2], MModDAdrI, &AdrResult) == ModDAdrI)
3500
      {
3501
        WAsmCode[0] |= AdrResult.AdrPart & 7;
3502
        CodeLen = 4;
3503
        WAsmCode[1] = AdrResult.Vals[0];
3504
      }
3505
    }
3506
    else if (AdrResult.AdrMode == ModDAdrI)
3507
    {
3508
      WAsmCode[0] = 0x108 | ((OpSize - 1) << 6) | (AdrResult.AdrPart & 7);
3509
      WAsmCode[1] = AdrResult.Vals[0];
3510
      if (DecodeAdr(&ArgStr[2], MModData, &AdrResult) == ModData)
3511
      {
3512
        WAsmCode[0] |= (AdrResult.AdrPart & 7) << 9;
3513
        CodeLen = 4;
3514
      }
3515
    }
3516
  }
3517
}
3518
 
3519
static void DecodeMOVEC(Word Index)
3520
{
3521
  UNUSED(Index);
3522
 
3523
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3524
  else if (ChkArgCnt(2, 2))
3525
  {
3526
    tAdrResult AdrResult;
3527
 
3528
    if (DecodeCtrlReg(ArgStr[1].str.p_str, WAsmCode + 1))
3529
    {
3530
      if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
3531
      {
3532
        CodeLen = 4;
3533
        WAsmCode[0] = 0x4e7a;
3534
        WAsmCode[1] |= AdrResult.AdrPart << 12;
3535
        CheckSup();
3536
      }
3537
    }
3538
    else if (DecodeCtrlReg(ArgStr[2].str.p_str, WAsmCode + 1))
3539
    {
3540
      if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
3541
      {
3542
        CodeLen = 4;
3543
        WAsmCode[0] = 0x4e7b;
3544
        WAsmCode[1] |= AdrResult.AdrPart << 12; CheckSup();
3545
      }
3546
    }
3547
    else
3548
      WrError(ErrNum_InvCtrlReg);
3549
  }
3550
}
3551
 
3552
static void DecodeMOVES(Word Index)
3553
{
3554
  UNUSED(Index);
3555
 
3556
  if (!ChkArgCnt(2, 2));
3557
  else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
3558
  else if (CheckNoFamily((1 << e68KGen1a) | (1 << eColdfire)))
3559
  {
3560
    tAdrResult AdrResult;
3561
 
3562
    switch (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
3563
    {
3564
      case ModData:
3565
      case ModAdr:
3566
      {
3567
        WAsmCode[1] = 0x800 | (AdrResult.AdrPart << 12);
3568
        if (DecodeAdr(&ArgStr[2], MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
3569
        {
3570
          WAsmCode[0] = 0xe00 | AdrResult.AdrPart | (OpSize << 6);
3571
          CodeLen = 4 + AdrResult.Cnt;
3572
          CopyAdrVals(WAsmCode + 2, &AdrResult);
3573
          CheckSup();
3574
        }
3575
        break;
3576
      }
3577
      case ModNone:
3578
        break;
3579
      default:
3580
      {
3581
        WAsmCode[0] = 0xe00 | AdrResult.AdrPart | (OpSize << 6);
3582
        CodeLen = 4 + AdrResult.Cnt;
3583
        CopyAdrVals(WAsmCode + 2, &AdrResult);
3584
        if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
3585
        {
3586
          WAsmCode[1] = AdrResult.AdrPart << 12;
3587
          CheckSup();
3588
        }
3589
        else
3590
          CodeLen = 0;
3591
      }
3592
    }
3593
  }
3594
}
3595
 
3596
static void DecodeCALLM(Word Index)
3597
{
3598
  UNUSED(Index);
3599
 
3600
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3601
  else if (!(pCurrCPUProps->SuppFlags & eFlagCALLM_RTM)) WrError(ErrNum_InstructionNotSupported);
3602
  else if (ChkArgCnt(2, 2))
3603
  {
3604
    tAdrResult AdrResult;
3605
 
3606
    OpSize = eSymbolSize8Bit;
3607
    if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
3608
    {
3609
      WAsmCode[1] = AdrResult.Vals[0];
3610
      RelPos = 4;
3611
      if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
3612
      {
3613
        WAsmCode[0] = 0x06c0 + AdrResult.AdrPart;
3614
        CopyAdrVals(WAsmCode + 2, &AdrResult);
3615
        CodeLen = 4 + AdrResult.Cnt;
3616
      }
3617
    }
3618
  }
3619
}
3620
 
3621
static void DecodeCAS(Word Index)
3622
{
3623
  UNUSED(Index);
3624
 
3625
  if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
3626
  else if (ChkArgCnt(3, 3)
3627
        && CheckFamily((1 << e68KGen3) | (1 << e68KGen2)))
3628
  {
3629
    tAdrResult AdrResult;
3630
 
3631
    if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
3632
    {
3633
      WAsmCode[1] = AdrResult.AdrPart;
3634
      if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
3635
      {
3636
        RelPos = 4;
3637
        WAsmCode[1] += (((Word)AdrResult.AdrPart) << 6);
3638
        if (DecodeAdr(&ArgStr[3], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
3639
        {
3640
          WAsmCode[0] = 0x08c0 + AdrResult.AdrPart + (((Word)OpSize + 1) << 9);
3641
          CopyAdrVals(WAsmCode + 2, &AdrResult);
3642
          CodeLen = 4 + AdrResult.Cnt;
3643
        }
3644
      }
3645
    }
3646
  }
3647
}
3648
 
3649
static void DecodeCAS2(Word Index)
3650
{
3651
  Word w1, w2;
3652
  UNUSED(Index);
3653
 
3654
  if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
3655
  else if (!ChkArgCnt(3, 3));
3656
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
3657
  else if (!DecodeRegPair(&ArgStr[1], WAsmCode + 1, WAsmCode + 2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[1]);
3658
  else if (!DecodeRegPair(&ArgStr[2], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[2]);
3659
  else
3660
  {
3661
    WAsmCode[1] += (w1 << 6);
3662
    WAsmCode[2] += (w2 << 6);
3663
    if (!CodeIndRegPair(&ArgStr[3], &w1, &w2)) WrStrErrorPos(ErrNum_InvRegPair, &ArgStr[3]);
3664
    else
3665
    {
3666
      WAsmCode[1] += (w1 << 12);
3667
      WAsmCode[2] += (w2 << 12);
3668
      WAsmCode[0] = 0x0cfc + (((Word)OpSize - 1) << 9);
3669
      CodeLen = 6;
3670
    }
3671
  }
3672
}
3673
 
3674
static void DecodeCMPCHK2(Word Index)
3675
{
3676
  if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
3677
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
3678
  else if (ChkArgCnt(2, 2))
3679
  {
3680
    tAdrResult AdrResult;
3681
 
3682
    if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
3683
    {
3684
      RelPos = 4;
3685
      WAsmCode[1] = (((Word)AdrResult.AdrPart) << 12) | (Index << 11);
3686
      if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
3687
      {
3688
        WAsmCode[0] = 0x00c0 + (((Word)OpSize) << 9) + AdrResult.AdrPart;
3689
        CopyAdrVals(WAsmCode + 2, &AdrResult);
3690
        CodeLen = 4 + AdrResult.Cnt;
3691
      }
3692
    }
3693
  }
3694
}
3695
 
3696
static void DecodeEXTB(Word Index)
3697
{
3698
  UNUSED(Index);
3699
 
3700
  if ((OpSize != eSymbolSize32Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3701
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2) | (1 << eCPU32)));
3702
  else if (ChkArgCnt(1, 1))
3703
  {
3704
    tAdrResult AdrResult;
3705
 
3706
    if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
3707
    {
3708
      WAsmCode[0] = 0x49c0 + AdrResult.AdrPart;
3709
      CodeLen = 2;
3710
    }
3711
  }
3712
}
3713
 
3714
static void DecodePACK(Word Index)
3715
{
3716
  if (!ChkArgCnt(3, 3));
3717
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
3718
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3719
  else
3720
  {
3721
    tAdrResult AdrResult;
3722
 
3723
    if (DecodeAdr(&ArgStr[1], MModData | MModPre, &AdrResult))
3724
    {
3725
      WAsmCode[0] = (0x8140 + (Index << 6)) | (AdrResult.AdrPart & 7);
3726
      if (AdrResult.AdrMode == ModPre)
3727
        WAsmCode[0] += 8;
3728
      if (DecodeAdr(&ArgStr[2], 1 << (AdrResult.AdrMode - 1), &AdrResult))
3729
      {
3730
        WAsmCode[0] |= ((AdrResult.AdrPart & 7) << 9);
3731
        if (DecodeAdr(&ArgStr[3], MModImm, &AdrResult))
3732
        {
3733
          WAsmCode[1] = AdrResult.Vals[0];
3734
          CodeLen = 4;
3735
        }
3736
      }
3737
    }
3738
  }
3739
}
3740
 
3741
static void DecodeRTM(Word Index)
3742
{
3743
  UNUSED(Index);
3744
 
3745
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3746
  else if (!(pCurrCPUProps->SuppFlags & eFlagCALLM_RTM)) WrError(ErrNum_InstructionNotSupported);
3747
  else if (ChkArgCnt(1, 1))
3748
  {
3749
    tAdrResult AdrResult;
3750
 
3751
    if (DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
3752
    {
3753
      WAsmCode[0] = 0x06c0 + AdrResult.AdrPart;
3754
      CodeLen = 2;
3755
    }
3756
  }
3757
}
3758
 
3759
static void DecodeTBL(Word Index)
3760
{
3761
  char *p;
3762
  Word w2, Mode;
3763
 
3764
  if (!ChkArgCnt(2, 2));
3765
  else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
3766
  else if (CheckFamily(1 << eCPU32))
3767
  {
3768
    tAdrResult AdrResult;
3769
 
3770
    if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
3771
    {
3772
      Mode = AdrResult.AdrPart;
3773
      p = strchr(ArgStr[1].str.p_str, ':');
3774
      if (!p)
3775
      {
3776
        RelPos = 4;
3777
        if (DecodeAdr(&ArgStr[1], MModAdrI | MModDAdrI | MModAIX| MModAbs | MModPC | MModPCIdx, &AdrResult))
3778
        {
3779
          WAsmCode[0] = 0xf800 | AdrResult.AdrPart;
3780
          WAsmCode[1] = 0x0100 | (OpSize << 6) | (Mode << 12) | (Index << 10);
3781
          memcpy(WAsmCode + 2, AdrResult.Vals, AdrResult.Cnt);
3782
          CodeLen = 4 + AdrResult.Cnt;
3783
        }
3784
      }
3785
      else
3786
      {
3787
        strcpy(ArgStr[3].str.p_str, p + 1);
3788
        *p = '\0';
3789
        if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
3790
        {
3791
          w2 = AdrResult.AdrPart;
3792
          if (DecodeAdr(&ArgStr[3], MModData, &AdrResult))
3793
          {
3794
            WAsmCode[0] = 0xf800 | w2;
3795
            WAsmCode[1] = 0x0000 | (OpSize << 6) | (Mode << 12) | AdrResult.AdrPart;
3796
            if (OpPart.str.p_str[3] == 'S')
3797
              WAsmCode[1] |= 0x0800;
3798
            if (OpPart.str.p_str[strlen(OpPart.str.p_str) - 1] == 'N')
3799
              WAsmCode[1] |= 0x0400;
3800
            CodeLen = 4;
3801
          }
3802
        }
3803
      }
3804
    }
3805
  }
3806
}
3807
 
3808
/* 0=BTST 1=BCHG 2=BCLR 3=BSET */
3809
 
3810
static void DecodeBits(Word Index)
3811
{
3812
  Word Mask, BitNum, BitMax;
3813
  tSymbolSize SaveOpSize;
3814
  unsigned ResCodeLen;
3815
  Boolean BitNumUnknown = False;
3816
  tAdrResult AdrResult;
3817
 
3818
  if (!ChkArgCnt(2, 2))
3819
    return;
3820
 
3821
  WAsmCode[0] = (Index << 6);
3822
  ResCodeLen = 1;
3823
 
3824
  SaveOpSize = OpSize;
3825
  OpSize = eSymbolSize8Bit;
3826
  switch (DecodeAdr(&ArgStr[1], MModData | MModImm, &AdrResult))
3827
  {
3828
    case ModData:
3829
      WAsmCode[0] |= 0x100 | (AdrResult.AdrPart << 9);
3830
      BitNum = 0; /* implicitly suppresses bit pos check */
3831
      break;
3832
    case ModImm:
3833
      WAsmCode[0] |= 0x800;
3834
      WAsmCode[ResCodeLen++] = BitNum = AdrResult.Vals[0];
3835
      BitNumUnknown = mFirstPassUnknown(AdrResult.ImmSymFlags);
3836
      break;
3837
    default:
3838
      return;
3839
  }
3840
 
3841
  OpSize = SaveOpSize;
3842
  if (!*AttrPart.str.p_str)
3843
    OpSize = eSymbolSize8Bit;
3844
 
3845
  Mask = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs;
3846
  if (!Index)
3847
    Mask |= MModPC | MModPCIdx | MModImm;
3848
  RelPos = ResCodeLen << 1;
3849
  DecodeAdr(&ArgStr[2], Mask, &AdrResult);
3850
 
3851
  if (!*AttrPart.str.p_str)
3852
    OpSize = (AdrResult.AdrMode == ModData) ? eSymbolSize32Bit : eSymbolSize8Bit;
3853
  if (!AdrResult.AdrMode)
3854
    return;
3855
  if (((AdrResult.AdrMode == ModData) && (OpSize != eSymbolSize32Bit)) || ((AdrResult.AdrMode != ModData) && (OpSize != eSymbolSize8Bit)))
3856
  {
3857
    WrError(ErrNum_InvOpSize);
3858
    return;
3859
  }
3860
 
3861
  BitMax = (AdrResult.AdrMode == ModData) ? 31 : 7;
3862
  WAsmCode[0] |= AdrResult.AdrPart;
3863
  CopyAdrVals(WAsmCode + ResCodeLen, &AdrResult);
3864
  CodeLen = (ResCodeLen << 1) + AdrResult.Cnt;
3865
  if (!BitNumUnknown && (BitNum > BitMax))
3866
    WrError(ErrNum_BitNumberTruncated);
3867
}
3868
 
3869
/* 0=BFTST 1=BFCHG 2=BFCLR 3=BFSET */
3870
 
3871
static void DecodeFBits(Word Index)
3872
{
3873
  if (!ChkArgCnt(1, 1));
3874
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
3875
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3876
  else if (!SplitBitField(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
3877
  else
3878
  {
3879
    tAdrResult AdrResult;
3880
 
3881
    RelPos = 4;
3882
    OpSize = eSymbolSize8Bit;
3883
    if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModDAdrI | MModAIX | MModAbs | (Memo("BFTST") ? (MModPC | MModPCIdx) : 0), &AdrResult))
3884
    {
3885
      WAsmCode[0] = 0xe8c0 | AdrResult.AdrPart | (Index << 10);
3886
      CopyAdrVals(WAsmCode + 2, &AdrResult);
3887
      CodeLen = 4 + AdrResult.Cnt;
3888
    }
3889
  }
3890
}
3891
 
3892
/* 0=BFEXTU 1=BFEXTS 2=BFFFO */
3893
 
3894
static void DecodeEBits(Word Index)
3895
{
3896
  if (!ChkArgCnt(2, 2));
3897
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
3898
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3899
  else if (!SplitBitField(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
3900
  else
3901
  {
3902
    tAdrResult AdrResult;
3903
 
3904
    RelPos = 4;
3905
    OpSize = eSymbolSize8Bit;
3906
    if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
3907
    {
3908
      LongInt ThisCodeLen = 4 + AdrResult.Cnt;
3909
 
3910
      WAsmCode[0] = 0xe9c0 + AdrResult.AdrPart + (Index << 9); CopyAdrVals(WAsmCode + 2, &AdrResult);
3911
      if (DecodeAdr(&ArgStr[2], MModData, &AdrResult))
3912
      {
3913
        WAsmCode[1] |= AdrResult.AdrPart << 12;
3914
        CodeLen = ThisCodeLen;
3915
      }
3916
    }
3917
  }
3918
}
3919
 
3920
static void DecodeBFINS(Word Index)
3921
{
3922
  UNUSED(Index);
3923
 
3924
  if (!ChkArgCnt(2, 2));
3925
  else if (!CheckFamily((1 << e68KGen3) | (1 << e68KGen2)));
3926
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
3927
  else if (!SplitBitField(&ArgStr[2], WAsmCode + 1)) WrError(ErrNum_InvBitMask);
3928
  else
3929
  {
3930
    tAdrResult AdrResult;
3931
 
3932
    OpSize = eSymbolSize8Bit;
3933
    if (DecodeAdr(&ArgStr[2], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
3934
    {
3935
      LongInt ThisCodeLen = 4 + AdrResult.Cnt;
3936
 
3937
      WAsmCode[0] = 0xefc0 + AdrResult.AdrPart;
3938
      CopyAdrVals(WAsmCode + 2, &AdrResult);
3939
      if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
3940
      {
3941
        WAsmCode[1] |= AdrResult.AdrPart << 12;
3942
        CodeLen = ThisCodeLen;
3943
      }
3944
    }
3945
  }
3946
}
3947
 
3948
/* bedingte Befehle */
3949
 
3950
static void DecodeBcc(Word CondCode)
3951
{
3952
  /* .W, .S, .L, .X erlaubt */
3953
 
3954
  if ((OpSize > eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
3955
 
3956
  /* nur ein Operand erlaubt */
3957
 
3958
  else if (ChkArgCnt(1, 1))
3959
  {
3960
    LongInt HVal;
3961
    Integer HVal16;
3962
    ShortInt HVal8;
3963
    Boolean ValOK, IsBSR = (1 == CondCode);
3964
    tSymbolFlags Flags;
3965
 
3966
    /* Zieladresse ermitteln, zum Programmzaehler relativieren */
3967
 
3968
    HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags);
3969
    HVal = HVal - (EProgCounter() + 2);
3970
 
3971
    /* Bei Automatik Groesse festlegen */
3972
 
3973
    if (!*AttrPart.str.p_str)
3974
    {
3975
      if (IsDisp8(HVal))
3976
      {
3977
        /* BSR with zero displacement cannot be converted to NOP.  Generate a
3978
           16 bit displacement instead. */
3979
 
3980
        if (!HVal && IsBSR)
3981
          OpSize = eSymbolSize32Bit;
3982
 
3983
        /* if the jump target is the address right behind the BSR, keep
3984
           16 bit displacement to avoid oscillating back and forth between
3985
           8 and 16 bits: */
3986
 
3987
        else if ((Flags & eSymbolFlag_NextLabelAfterBSR) && (HVal == 2) && IsBSR)
3988
          OpSize = eSymbolSize32Bit;
3989
        else
3990
          OpSize = eSymbolSizeFloat32Bit;
3991
      }
3992
      else if (IsDisp16(HVal))
3993
        OpSize = eSymbolSize32Bit;
3994
      else
3995
        OpSize = eSymbolSizeFloat96Bit;
3996
    }
3997
 
3998
    if (ValOK)
3999
    {
4000
      /* 16 Bit (.L or .W) ? */
4001
 
4002
      if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
4003
      {
4004
        /* zu weit ? */
4005
 
4006
        HVal16 = HVal;
4007
        if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4008
        else
4009
        {
4010
          /* Code erzeugen */
4011
 
4012
          CodeLen = 4;
4013
          WAsmCode[0] = 0x6000 | (CondCode << 8);
4014
          WAsmCode[1] = HVal16;
4015
        }
4016
      }
4017
 
4018
      /* 8 Bit (.S or .B) ? */
4019
 
4020
      else if ((OpSize == eSymbolSizeFloat32Bit) || (OpSize == eSymbolSize8Bit))
4021
      {
4022
        /* zu weit ? */
4023
 
4024
        HVal8 = HVal;
4025
        if (!IsDisp8(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4026
 
4027
        /* cannot generate short BSR with zero displacement, and BSR cannot
4028
           be replaced with NOP -> error */
4029
 
4030
        else if ((HVal == 0) && IsBSR && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4031
 
4032
        /* Code erzeugen */
4033
 
4034
        else
4035
        {
4036
          CodeLen = 2;
4037
          if ((HVal8 != 0) || IsBSR)
4038
          {
4039
            WAsmCode[0] = 0x6000 | (CondCode << 8) | ((Byte)HVal8);
4040
          }
4041
          else
4042
          {
4043
            WAsmCode[0] = NOPCode;
4044
            if ((!Repass) && *AttrPart.str.p_str)
4045
              WrError(ErrNum_DistNull);
4046
          }
4047
        }
4048
      }
4049
 
4050
      /* 32 Bit ?  Complain about non-supported instructio only if .X
4051
         was requested explicitly: */
4052
 
4053
      else if (!(pCurrCPUProps->SuppFlags & eFlagBranch32)) WrError(*AttrPart.str.p_str ? ErrNum_InstructionNotSupported : ErrNum_JmpDistTooBig);
4054
      else
4055
      {
4056
        CodeLen = 6;
4057
        WAsmCode[0] = 0x60ff | (CondCode << 8);
4058
        WAsmCode[1] = HVal >> 16;
4059
        WAsmCode[2] = HVal & 0xffff;
4060
      }
4061
    }
4062
 
4063
    if ((CodeLen > 0) && IsBSR)
4064
      AfterBSRAddr = EProgCounter() + CodeLen;
4065
  }
4066
}
4067
 
4068
static void DecodeScc(Word CondCode)
4069
{
4070
  if (*AttrPart.str.p_str && (OpSize != eSymbolSize8Bit)) WrError(ErrNum_InvOpSize);
4071
  else if (ArgCnt != 1) WrError(ErrNum_InvOpSize);
4072
  else
4073
  {
4074
    tAdrResult AdrResult;
4075
 
4076
    OpSize = eSymbolSize8Bit;
4077
    if (DecodeAdr(&ArgStr[1], MModData | ((pCurrCPUProps->Family == eColdfire) ? 0 : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs), &AdrResult))
4078
    {
4079
      WAsmCode[0] = 0x50c0 | (CondCode << 8) | AdrResult.AdrPart;
4080
      CodeLen = 2 + AdrResult.Cnt;
4081
      CopyAdrVals(WAsmCode + 1, &AdrResult);
4082
    }
4083
  }
4084
}
4085
 
4086
static void DecodeDBcc(Word CondCode)
4087
{
4088
  if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
4089
  else if (ChkArgCnt(2, 2)
4090
        && CheckNoFamily(1 << eColdfire))
4091
  {
4092
    Boolean ValOK;
4093
    tSymbolFlags Flags;
4094
    LongInt HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags);
4095
    Integer HVal16;
4096
 
4097
    if (ValOK)
4098
    {
4099
      HVal -= (EProgCounter() + 2);
4100
      HVal16 = HVal;
4101
      if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4102
      else
4103
      {
4104
        tAdrResult AdrResult;
4105
 
4106
        CodeLen = 4;
4107
        WAsmCode[0] = 0x50c8 | (CondCode << 8);
4108
        WAsmCode[1] = HVal16;
4109
        if (DecodeAdr(&ArgStr[1], MModData, &AdrResult) == ModData)
4110
          WAsmCode[0] |= AdrResult.AdrPart;
4111
        else
4112
          CodeLen = 0;
4113
      }
4114
    }
4115
  }
4116
}
4117
 
4118
static void DecodeTRAPcc(Word CondCode)
4119
{
4120
  int ExpectArgCnt;
4121
 
4122
  if (!*AttrPart.str.p_str)
4123
    OpSize = eSymbolSize8Bit;
4124
  ExpectArgCnt = (OpSize == eSymbolSize8Bit) ? 0 : 1;
4125
  if (OpSize > 2) WrError(ErrNum_InvOpSize);
4126
  else if (!ChkArgCnt(ExpectArgCnt, ExpectArgCnt));
4127
  else if ((CondCode != 1) && !CheckNoFamily(1 << eColdfire));
4128
  else
4129
  {
4130
    WAsmCode[0] = 0x50f8 + (CondCode << 8);
4131
    if (OpSize == eSymbolSize8Bit)
4132
    {
4133
      WAsmCode[0] += 4;
4134
      CodeLen = 2;
4135
    }
4136
    else
4137
    {
4138
      tAdrResult AdrResult;
4139
 
4140
      if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
4141
      {
4142
        WAsmCode[0] += OpSize + 1;
4143
        CopyAdrVals(WAsmCode + 1, &AdrResult);
4144
        CodeLen = 2 + AdrResult.Cnt;
4145
      }
4146
    }
4147
    CheckFamily((1 << eColdfire) | (1 << eCPU32) | (1 << e68KGen2) | (1 << e68KGen3));
4148
  }
4149
}
4150
 
4151
/*-------------------------------------------------------------------------*/
4152
/* Dekodierroutinen Gleitkommaeinheit */
4153
 
4154
enum { eFMovemTypNone = 0, eFMovemTypDyn = 1, eFMovemTypStatic = 2, eFMovemTypCtrl = 3 };
4155
 
4156
static void DecodeFRegList(const tStrComp *pArg, Byte *pTyp, Byte *pList)
4157
{
4158
  Word hw, Reg, RegFrom, RegTo;
4159
  Byte z;
4160
  char *p, *p2;
4161
  String ArgStr;
4162
  tStrComp Arg, Remainder, From, To;
4163
 
4164
  StrCompMkTemp(&Arg, ArgStr, sizeof(ArgStr));
4165
  StrCompCopy(&Arg, pArg);
4166
 
4167
  *pTyp = eFMovemTypNone;
4168
  if (*Arg.str.p_str == '\0')
4169
    return;
4170
 
4171
  switch (DecodeReg(&Arg, &Reg, False))
4172
  {
4173
    case eIsReg:
4174
      if (Reg & 8)
4175
        return;
4176
      *pTyp = eFMovemTypDyn;
4177
      *pList = Reg << 4;
4178
      return;
4179
    case eRegAbort:
4180
      return;
4181
    default:
4182
      break;
4183
  }
4184
 
4185
  hw = 0;
4186
  do
4187
  {
4188
    p = strchr(Arg.str.p_str, '/');
4189
    if (p)
4190
      StrCompSplitRef(&Arg, &Remainder, &Arg, p);
4191
    p2 = strchr(Arg.str.p_str, '-');
4192
    if (p2)
4193
    {
4194
      StrCompSplitRef(&From, &To, &Arg, p2);
4195
      if (!strlen(To.str.p_str)
4196
       || (DecodeFPReg(&From, &RegFrom, False) != eIsReg)
4197
       || (RegFrom & REG_FPCTRL)
4198
       || (DecodeFPReg(&To, &RegTo, False) != eIsReg)
4199
       || (RegTo & REG_FPCTRL))
4200
        return;
4201
      if (RegFrom <= RegTo)
4202
        for (z = RegFrom; z <= RegTo; z++) hw |= (1 << (7 - z));
4203
      else
4204
      {
4205
        for (z = RegFrom; z <= 7; z++) hw |= (1 << (7 - z));
4206
        for (z = 0; z <= RegTo; z++) hw |= (1 << (7 - z));
4207
      }
4208
    }
4209
    else
4210
    {
4211
      if (DecodeFPReg(&Arg, &Reg, False) != eIsReg)
4212
        return;
4213
      if (Reg & REG_FPCTRL)
4214
        hw |= (Reg & 7) << 8;
4215
      else
4216
        hw |= (1 << (7 - Reg));
4217
    }
4218
    if (p)
4219
      Arg = Remainder;
4220
  }
4221
  while (p);
4222
  if (Hi(hw) == 0)
4223
  {
4224
    *pTyp = eFMovemTypStatic;
4225
    *pList = Lo(hw);
4226
  }
4227
  else if (Lo(hw) == 0)
4228
  {
4229
    *pTyp = eFMovemTypCtrl;
4230
    *pList = Hi(hw);
4231
  }
4232
}
4233
 
4234
static Byte Mirror8(Byte List)
4235
{
4236
  Byte hList;
4237
  int z;
4238
 
4239
  hList = List; List = 0;
4240
  for (z = 0; z < 8; z++)
4241
  {
4242
    List = List << 1;
4243
    if (hList & 1)
4244
      List |= 1;
4245
    hList = hList >> 1;
4246
  }
4247
  return List;
4248
}
4249
 
4250
static void GenerateMovem(Byte Typ, Byte List, tAdrResult *pResult)
4251
{
4252
  if (pResult->AdrMode == ModNone)
4253
    return;
4254
  CodeLen = 4 + pResult->Cnt;
4255
  CopyAdrVals(WAsmCode + 2, pResult);
4256
  WAsmCode[0] = 0xf200 | pResult->AdrPart;
4257
  switch (Typ)
4258
  {
4259
    case eFMovemTypDyn:
4260
    case eFMovemTypStatic:
4261
      WAsmCode[1] |= 0xc000;
4262
      if (Typ == eFMovemTypDyn)
4263
        WAsmCode[1] |= 0x800;
4264
      if (pResult->AdrMode != ModPre)
4265
        WAsmCode[1] |= 0x1000;
4266
      if ((pResult->AdrMode == ModPre) && (Typ == eFMovemTypStatic))
4267
        List = Mirror8(List);
4268
      WAsmCode[1] |= List;
4269
      break;
4270
    case eFMovemTypCtrl:
4271
      WAsmCode[1] |= 0x8000 | (((Word)List) << 10);
4272
      break;
4273
  }
4274
}
4275
 
4276
/*-------------------------------------------------------------------------*/
4277
 
4278
static void DecodeFPUOp(Word Index)
4279
{
4280
  FPUOp *Op = FPUOps + Index;
4281
  tStrComp *pArg2 = &ArgStr[2];
4282
 
4283
  if ((ArgCnt == 1) && (!Op->Dya))
4284
  {
4285
    pArg2 = &ArgStr[1];
4286
    ArgCnt = 2;
4287
  }
4288
 
4289
  if (!CheckFloatSize());
4290
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4291
  else if ((pCurrCPUProps->SuppFlags & Op->NeedsSuppFlags) != Op->NeedsSuppFlags) WrError(ErrNum_InstructionNotSupported);
4292
  else if (ChkArgCnt(2, 2))
4293
  {
4294
    tAdrResult AdrResult;
4295
 
4296
    if (DecodeAdr(pArg2, MModFPn, &AdrResult) == ModFPn)
4297
    {
4298
      Word SrcMask;
4299
 
4300
      WAsmCode[0] = 0xf200;
4301
      WAsmCode[1] = Op->Code | (AdrResult.AdrPart << 7);
4302
      RelPos = 4;
4303
 
4304
      SrcMask = MModAdrI | MModDAdrI | MModPost | MModPre | MModPC | MModFPn;
4305
      if (FloatOpSizeFitsDataReg(OpSize))
4306
        SrcMask |= MModData;
4307
      if (pCurrCPUProps->Family != eColdfire)
4308
        SrcMask |= MModAIX | MModAbs | MModPCIdx | MModImm;
4309
      if (DecodeAdr(&ArgStr[1], SrcMask, &AdrResult) == ModFPn)
4310
      {
4311
        WAsmCode[1] |= AdrResult.AdrPart << 10;
4312
        if (OpSize == NativeFloatSize)
4313
          CodeLen = 4;
4314
        else
4315
          WrError(ErrNum_InvOpSize);
4316
      }
4317
      else if (AdrResult.AdrMode != ModNone)
4318
      {
4319
        CodeLen = 4 + AdrResult.Cnt;
4320
        CopyAdrVals(WAsmCode + 2, &AdrResult);
4321
        WAsmCode[0] |= AdrResult.AdrPart;
4322
        WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
4323
      }
4324
    }
4325
  }
4326
}
4327
 
4328
static void DecodeFSAVE(Word Code)
4329
{
4330
  UNUSED(Code);
4331
 
4332
  if (!ChkArgCnt(1, 1));
4333
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4334
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
4335
  else
4336
  {
4337
    tAdrResult AdrResult;
4338
 
4339
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
4340
    {
4341
      CodeLen = 2 + AdrResult.Cnt;
4342
      WAsmCode[0] = 0xf300 | AdrResult.AdrPart;
4343
      CopyAdrVals(WAsmCode + 1, &AdrResult);
4344
      CheckSup();
4345
    }
4346
  }
4347
}
4348
 
4349
static void DecodeFRESTORE(Word Code)
4350
{
4351
  UNUSED(Code);
4352
 
4353
  if (!ChkArgCnt(1, 1));
4354
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4355
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
4356
  else
4357
  {
4358
    tAdrResult AdrResult;
4359
 
4360
    RelPos = 4;
4361
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPost | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
4362
    {
4363
      CodeLen = 2 + AdrResult.Cnt;
4364
      WAsmCode[0] = 0xf340 | AdrResult.AdrPart;
4365
      CopyAdrVals(WAsmCode + 1, &AdrResult);
4366
      CheckSup();
4367
    }
4368
  }
4369
}
4370
 
4371
static void DecodeFNOP(Word Code)
4372
{
4373
  UNUSED(Code);
4374
 
4375
  if (!ChkArgCnt(0, 0));
4376
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4377
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
4378
  else
4379
  {
4380
    CodeLen = 4;
4381
    WAsmCode[0] = 0xf280;
4382
    WAsmCode[1] = 0;
4383
  }
4384
}
4385
 
4386
/* TODO: does a { } suffix to <dest> as k factor conflict
4387
   with other features, like stringification?  Maybe better
4388
   check whether this is a valid k factor (register (symbol)
4389
   or immediate) and only cut off if yes.  We might not be
4390
   able to use DecodeAdr() for this any more: */
4391
 
4392
static char *split_k(tStrComp *p_arg, tStrComp *p_k)
4393
{
4394
  int l = strlen(p_arg->str.p_str);
4395
  char *p_sep;
4396
 
4397
  if ((l < 2) || (p_arg->str.p_str[l - 1] != '}'))
4398
    return NULL;
4399
  p_sep = RQuotPos(p_arg->str.p_str, '{');
4400
  if (!p_sep)
4401
    return NULL;
4402
 
4403
  StrCompSplitRef(p_arg, p_k, p_arg, p_sep);
4404
  StrCompShorten(p_k, 1);
4405
  KillPostBlanksStrComp(p_arg);
4406
  KillPrefBlanksStrCompRef(p_k);
4407
  return p_sep;
4408
}
4409
 
4410
static void DecodeFMOVE(Word Code)
4411
{
4412
  Word DestMask, SrcMask;
4413
  tAdrResult DestAdrResult, SrcAdrResult;
4414
  tStrComp KArg;
4415
  Boolean op_size_implicit = !*AttrPart.str.p_str;
4416
 
4417
  UNUSED(Code);
4418
 
4419
  if (!ChkArgCnt(2, 2))
4420
    return;
4421
  if (!FPUAvail)
4422
  {
4423
    WrError(ErrNum_FPUNotEnabled);
4424
    return;
4425
  }
4426
  if (!CheckFloatSize())
4427
    return;
4428
 
4429
  /* k-Faktor abspalten */
4430
 
4431
  LineCompReset(&KArg.Pos);
4432
  if (OpSize == eSymbolSizeFloatDec96Bit)
4433
  {
4434
    if (!split_k(&AttrPart, &KArg))
4435
      split_k(&ArgStr[2], &KArg);
4436
  }
4437
 
4438
  DestMask = MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModFPCR | MModFPn;
4439
  if (pCurrCPUProps->Family != eColdfire)
4440
    DestMask |= MModAIX | MModAbs | MModImm;
4441
  if (FloatOpSizeFitsDataReg(OpSize) || op_size_implicit)
4442
    DestMask |= MModData;
4443
  switch (DecodeAdr(&ArgStr[2], DestMask, &DestAdrResult))
4444
  {
4445
    case ModFPn: /* FMOVE.x <ea>/FPm,FPn ? */
4446
    {
4447
      WAsmCode[0] = 0xf200;
4448
      WAsmCode[1] = DestAdrResult.AdrPart << 7;
4449
      RelPos = 4;
4450
      SrcMask = MModAdrI | MModPost | MModPre | MModDAdrI | MModPC | MModFPn;
4451
      if (pCurrCPUProps->Family != eColdfire)
4452
        SrcMask |= MModAIX | MModAbs | MModImm | MModPCIdx;
4453
      if (FloatOpSizeFitsDataReg(OpSize))
4454
        SrcMask |= MModData;
4455
      switch (DecodeAdr(&ArgStr[1], SrcMask, &SrcAdrResult))
4456
      {
4457
        case ModFPn: /* FMOVE.X FPm,FPn ? */
4458
        {
4459
          if (OpSize != NativeFloatSize)
4460
          {
4461
            WrError(ErrNum_InvOpSize);
4462
            return;
4463
          }
4464
          WAsmCode[1] |= SrcAdrResult.AdrPart << 10;
4465
          CodeLen = 4;
4466
          break;
4467
        }
4468
        case ModNone:
4469
          break;
4470
        default: /* FMOVE.x <ea>,FPn ? */
4471
          CodeLen = 4 + SrcAdrResult.Cnt;
4472
          CopyAdrVals(WAsmCode + 2, &SrcAdrResult);
4473
          WAsmCode[0] |= SrcAdrResult.AdrPart;
4474
          WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
4475
      }
4476
      break;
4477
    }
4478
    case ModFPCR: /* FMOVE.L <ea>,FPcr ? */
4479
    {
4480
      if ((OpSize != eSymbolSize32Bit) && !op_size_implicit)
4481
      {
4482
        WrError(ErrNum_InvOpSize);
4483
        return;
4484
      }
4485
      RelPos = 4;
4486
      WAsmCode[0] = 0xf200;
4487
      WAsmCode[1] = 0x8000 | (DestAdrResult.AdrPart << 10);
4488
      SrcMask = MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModPC;
4489
      if (pCurrCPUProps->Family != eColdfire)
4490
        SrcMask |= MModAIX | MModAbs | MModImm | MModPCIdx;
4491
      if (DestAdrResult.AdrPart == REG_FPIAR) /* only for FPIAR */
4492
        SrcMask |= MModAdr;
4493
      if (DecodeAdr(&ArgStr[1], SrcMask, &SrcAdrResult))
4494
      {
4495
        WAsmCode[0] |= SrcAdrResult.AdrPart;
4496
        CodeLen = 4 + SrcAdrResult.Cnt;
4497
        CopyAdrVals(WAsmCode + 2, &SrcAdrResult);
4498
      }
4499
      break;
4500
    }
4501
    case ModNone:
4502
      break;
4503
    default: /* FMOVE.x ????,<ea> ? */
4504
    {
4505
      WAsmCode[0] = 0xf200 | DestAdrResult.AdrPart;
4506
      CodeLen = 4 + DestAdrResult.Cnt;
4507
      CopyAdrVals(WAsmCode + 2, &DestAdrResult);
4508
      switch (DecodeAdr(&ArgStr[1], (DestAdrResult.AdrMode == ModAdr) ? MModFPCR : MModFPn | MModFPCR, &SrcAdrResult))
4509
      {
4510
        case ModFPn:                       /* FMOVE.x FPn,<ea> ? */
4511
        {
4512
          if (DestAdrResult.AdrMode == ModAdr)
4513
          {
4514
            WrError(ErrNum_InvAddrMode);
4515
            CodeLen = 0;
4516
            return;
4517
          }
4518
          WAsmCode[1] = 0x6000 | (((Word)FSizeCodes[OpSize]) << 10) | (SrcAdrResult.AdrPart << 7);
4519
          if (OpSize == eSymbolSizeFloatDec96Bit)
4520
          {
4521
            if (KArg.Pos.Len > 0)
4522
            {
4523
              tAdrResult KResult;
4524
 
4525
              OpSize = eSymbolSize8Bit;
4526
              switch (DecodeAdr(&KArg, MModData | MModImm, &KResult))
4527
              {
4528
                case ModData:
4529
                  WAsmCode[1] |= (KResult.AdrPart << 4) | 0x1000;
4530
                  break;
4531
                case ModImm:
4532
                  WAsmCode[1] |= (KResult.Vals[0] & 127);
4533
                  break;
4534
                default:
4535
                  CodeLen = 0;
4536
              }
4537
            }
4538
            else
4539
              WAsmCode[1] |= 17;
4540
          }
4541
          break;
4542
        }
4543
        case ModFPCR:                  /* FMOVE.L FPcr,<ea> ? */
4544
        {
4545
          if (!op_size_implicit && (OpSize != eSymbolSize32Bit))
4546
          {
4547
            WrError(ErrNum_InvOpSize);
4548
            CodeLen = 0;
4549
            return;
4550
          }
4551
          if ((SrcAdrResult.AdrPart != REG_FPIAR) && (DestAdrResult.AdrMode == ModAdr))
4552
          {
4553
            WrError(ErrNum_InvAddrMode);
4554
            CodeLen = 0;
4555
            return;
4556
          }
4557
          WAsmCode[1] = 0xa000 | (SrcAdrResult.AdrPart << 10);
4558
          break;
4559
        }
4560
        default:
4561
          CodeLen = 0;
4562
      }
4563
    }
4564
  }
4565
}
4566
 
4567
static void DecodeFMOVECR(Word Code)
4568
{
4569
  UNUSED(Code);
4570
 
4571
  if (!ChkArgCnt(2, 2));
4572
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4573
  else if (!CheckNoFamily(1 << eColdfire));
4574
  else if (*AttrPart.str.p_str && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
4575
  else
4576
  {
4577
    tAdrResult AdrResult;
4578
 
4579
    if (DecodeAdr(&ArgStr[2], MModFPn, &AdrResult) == ModFPn)
4580
    {
4581
      WAsmCode[0] = 0xf200;
4582
      WAsmCode[1] = 0x5c00 | (AdrResult.AdrPart << 7);
4583
      OpSize = eSymbolSize8Bit;
4584
      if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult) == ModImm)
4585
      {
4586
        if (AdrResult.Vals[0] > 63) WrError(ErrNum_RomOffs063);
4587
        else
4588
        {
4589
          CodeLen = 4;
4590
          WAsmCode[1] |= AdrResult.Vals[0];
4591
        }
4592
      }
4593
    }
4594
  }
4595
}
4596
 
4597
static void DecodeFTST(Word Code)
4598
{
4599
  UNUSED(Code);
4600
 
4601
  if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4602
  else if (!CheckFloatSize());
4603
  else if (ChkArgCnt(1, 1))
4604
  {
4605
    Word Mask;
4606
    tAdrResult AdrResult;
4607
 
4608
    RelPos = 4;
4609
    Mask = MModAdrI | MModPost | MModPre | MModDAdrI | MModPC | MModFPn;
4610
    if (pCurrCPUProps->Family != eColdfire)
4611
      Mask |= MModAIX | MModPCIdx | MModAbs | MModImm;
4612
    if (FloatOpSizeFitsDataReg(OpSize))
4613
      Mask |= MModData;
4614
    if (DecodeAdr(&ArgStr[1], Mask, &AdrResult) == ModFPn)
4615
    {
4616
      WAsmCode[0] = 0xf200;
4617
      WAsmCode[1] = 0x3a | (AdrResult.AdrPart << 10);
4618
      CodeLen = 4;
4619
    }
4620
    else if (AdrResult.AdrMode != ModNone)
4621
    {
4622
      WAsmCode[0] = 0xf200 | AdrResult.AdrPart;
4623
      WAsmCode[1] = 0x403a | (((Word)FSizeCodes[OpSize]) << 10);
4624
      CodeLen = 4 + AdrResult.Cnt;
4625
      CopyAdrVals(WAsmCode + 2, &AdrResult);
4626
    }
4627
  }
4628
}
4629
 
4630
static void DecodeFSINCOS(Word Code)
4631
{
4632
  UNUSED(Code);
4633
 
4634
  if (!*AttrPart.str.p_str)
4635
    OpSize = NativeFloatSize;
4636
  if (OpSize == 3) WrError(ErrNum_InvOpSize);
4637
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4638
  else if (!CheckNoFamily(1 << eColdfire));
4639
  else if (ChkArgCnt(2, 3))
4640
  {
4641
    tStrComp *pArg2, *pArg3, Arg2, Arg3;
4642
    tAdrResult AdrResult;
4643
 
4644
    if (3 == ArgCnt)
4645
    {
4646
      pArg2 = &ArgStr[2];
4647
      pArg3 = &ArgStr[3];
4648
    }
4649
    else
4650
    {
4651
      char *pKSep = strrchr(ArgStr[2].str.p_str, ':');
4652
 
4653
      if (!pKSep)
4654
      {
4655
        WrError(ErrNum_WrongArgCnt);
4656
        return;
4657
      }
4658
      StrCompSplitRef(&Arg2, &Arg3, &ArgStr[2], pKSep);
4659
      pArg2 = &Arg2;
4660
      pArg3 = &Arg3;
4661
    }
4662
    if (DecodeAdr(pArg2, MModFPn, &AdrResult) == ModFPn)
4663
    {
4664
      WAsmCode[1] = AdrResult.AdrPart | 0x30;
4665
      if (DecodeAdr(pArg3, MModFPn, &AdrResult) == ModFPn)
4666
      {
4667
        WAsmCode[1] |= (AdrResult.AdrPart << 7);
4668
        RelPos = 4;
4669
        switch (DecodeAdr(&ArgStr[1], ((OpSize <= eSymbolSize32Bit) || (OpSize == eSymbolSizeFloat32Bit))
4670
                                     ? MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm | MModFPn
4671
                                     : MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm | MModFPn, &AdrResult))
4672
        {
4673
          case ModFPn:
4674
            WAsmCode[0] = 0xf200;
4675
            WAsmCode[1] |= (AdrResult.AdrPart << 10);
4676
            CodeLen = 4;
4677
            break;
4678
          case ModNone:
4679
            break;
4680
          default:
4681
            WAsmCode[0] = 0xf200 | AdrResult.AdrPart;
4682
            WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
4683
            CodeLen = 4 + AdrResult.Cnt;
4684
            CopyAdrVals(WAsmCode + 2, &AdrResult);
4685
        }
4686
      }
4687
    }
4688
  }
4689
}
4690
 
4691
static void DecodeFDMOVE_FSMOVE(Word Code)
4692
{
4693
  if (!ChkArgCnt(2, 2));
4694
  else if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4695
  else if (CheckFamily((1 << e68KGen3) | (1 << eColdfire)))
4696
  {
4697
    tAdrResult AdrResult;
4698
 
4699
    if (DecodeAdr(&ArgStr[2], MModFPn, &AdrResult) == ModFPn)
4700
    {
4701
      unsigned Mask;
4702
 
4703
      WAsmCode[0] = 0xf200;
4704
      WAsmCode[1] = Code | AdrResult.AdrPart << 7;
4705
      RelPos = 4;
4706
      if (!*AttrPart.str.p_str)
4707
        OpSize = NativeFloatSize;
4708
      Mask = MModFPn | MModAdrI | MModPost | MModPre | MModDAdrI | MModPC;
4709
      if (pCurrCPUProps->Family != eColdfire)
4710
        Mask |= MModAIX | MModAbs | MModPCIdx | MModImm;
4711
      if (FloatOpSizeFitsDataReg(OpSize))
4712
        Mask |= MModData;
4713
      if (DecodeAdr(&ArgStr[1], Mask, &AdrResult) == ModFPn)
4714
      {
4715
        CodeLen = 4;
4716
        WAsmCode[1] |= (AdrResult.AdrPart << 10);
4717
      }
4718
      else if (AdrResult.AdrMode != ModNone)
4719
      {
4720
        CodeLen = 4 + AdrResult.Cnt;
4721
        CopyAdrVals(WAsmCode + 2, &AdrResult);
4722
        WAsmCode[0] |= AdrResult.AdrPart;
4723
        WAsmCode[1] |= 0x4000 | (((Word)FSizeCodes[OpSize]) << 10);
4724
      }
4725
    }
4726
  }
4727
}
4728
 
4729
/*!------------------------------------------------------------------------
4730
 * \fn     DecodeFMOVEM(Word Code)
4731
 * \brief  handle FMOVEM instruction
4732
 * ------------------------------------------------------------------------ */
4733
 
4734
static void DecodeFMOVEM(Word Code)
4735
{
4736
  Byte Typ, List;
4737
  Word Mask;
4738
  tAdrResult AdrResult;
4739
 
4740
  UNUSED(Code);
4741
 
4742
  if (!ChkArgCnt(2, 2))
4743
    return;
4744
  if (!FPUAvail)
4745
  {
4746
    WrError(ErrNum_FPUNotEnabled);
4747
    return;
4748
  }
4749
 
4750
  /* NOTE: An expression of 'Dn' may be the source or destination of a (single)
4751
     control register FMOVEM, but also a dynamic FPn data register list.  This
4752
     makes the decision tree a bit more complex: */
4753
 
4754
  DecodeFRegList(&ArgStr[2], &Typ, &List);
4755
  switch (Typ)
4756
  {
4757
    case eFMovemTypStatic:
4758
    case eFMovemTypCtrl:
4759
      goto fp_list_is_dest;
4760
 
4761
    case eFMovemTypDyn:
4762
    {
4763
      Byte src_typ, src_list;
4764
      DecodeFRegList(&ArgStr[1], &src_typ, &src_list);
4765
      switch (src_typ)
4766
      {
4767
        case eFMovemTypStatic:
4768
        case eFMovemTypCtrl:
4769
          Typ = src_typ;
4770
          List = src_list;
4771
          goto fp_list_is_src;
4772
        case eFMovemTypDyn:
4773
          WrError(ErrNum_InvRegList);
4774
          return;
4775
        default:
4776
          goto fp_list_is_dest;
4777
      }
4778
    }
4779
 
4780
    default: /* eFMovemTypNone */
4781
      DecodeFRegList(&ArgStr[1], &Typ, &List);
4782
      if (Typ == eFMovemTypNone)
4783
      {
4784
        WrError(ErrNum_InvRegList);
4785
        return;
4786
      }
4787
      /* Fall-Thru */
4788
 
4789
    fp_list_is_src:
4790
      if (*AttrPart.str.p_str && (((Typ < eFMovemTypCtrl) && (OpSize != NativeFloatSize)) || ((Typ == eFMovemTypCtrl) && (OpSize != eSymbolSize32Bit)))) WrError(ErrNum_InvOpSize);
4791
      else if ((Typ != eFMovemTypStatic) && (pCurrCPUProps->Family == eColdfire)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
4792
      else
4793
      {
4794
        Mask = MModAdrI | MModDAdrI;
4795
        if (pCurrCPUProps->Family != eColdfire)
4796
          Mask |= MModPre | MModAIX | MModAbs;
4797
        if (Typ == eFMovemTypCtrl)   /* Steuerregister auch Postinkrement */
4798
        {
4799
          Mask |= MModPost;
4800
          if ((List == REG_FPCR) | (List == REG_FPSR) | (List == REG_FPIAR)) /* nur ein Register */
4801
            Mask |= MModData;
4802
          if (List == REG_FPIAR) /* nur FPIAR */
4803
            Mask |= MModAdr;
4804
        }
4805
        if (DecodeAdr(&ArgStr[2], Mask, &AdrResult))
4806
        {
4807
          WAsmCode[1] = 0x2000;
4808
          GenerateMovem(Typ, List, &AdrResult);
4809
        }
4810
      }
4811
      break;
4812
 
4813
    fp_list_is_dest:
4814
      if (*AttrPart.str.p_str
4815
      && (((Typ < eFMovemTypCtrl) && (OpSize != NativeFloatSize))
4816
        || ((Typ == eFMovemTypCtrl) && (OpSize != eSymbolSize32Bit))))
4817
        WrError(ErrNum_InvOpSize);
4818
      else if ((Typ != eFMovemTypStatic) && (pCurrCPUProps->Family == eColdfire))
4819
        WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
4820
      else
4821
      {
4822
        RelPos = 4;
4823
        Mask = MModAdrI | MModDAdrI | MModPC;
4824
        if (pCurrCPUProps->Family != eColdfire)
4825
          Mask |= MModPost | MModAIX | MModPCIdx | MModAbs;
4826
        if (Typ == eFMovemTypCtrl)   /* Steuerregister auch Predekrement */
4827
        {
4828
          Mask |= MModPre;
4829
          if ((List == REG_FPCR) | (List == REG_FPSR) | (List == REG_FPIAR)) /* nur ein Register */
4830
            Mask |= MModData | MModImm;
4831
          if (List == REG_FPIAR) /* nur FPIAR */
4832
            Mask |= MModAdr;
4833
        }
4834
        if (DecodeAdr(&ArgStr[1], Mask, &AdrResult))
4835
        {
4836
          WAsmCode[1] = 0x0000;
4837
          GenerateMovem(Typ, List, &AdrResult);
4838
        }
4839
      }
4840
      break;
4841
  }
4842
}
4843
 
4844
static void DecodeFBcc(Word CondCode)
4845
{
4846
  if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4847
  else
4848
  {
4849
    if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
4850
    else if (ChkArgCnt(1, 1))
4851
    {
4852
      LongInt HVal;
4853
      Integer HVal16;
4854
      Boolean ValOK;
4855
      tSymbolFlags Flags;
4856
 
4857
      HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags) - (EProgCounter() + 2);
4858
      HVal16 = HVal;
4859
 
4860
      if (!*AttrPart.str.p_str)
4861
      {
4862
        OpSize = (IsDisp16(HVal)) ? eSymbolSize32Bit : eSymbolSizeFloat96Bit;
4863
      }
4864
 
4865
      if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
4866
      {
4867
        if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4868
        else
4869
        {
4870
          CodeLen = 4;
4871
          WAsmCode[0] = 0xf280 | CondCode;
4872
          WAsmCode[1] = HVal16;
4873
        }
4874
      }
4875
      else
4876
      {
4877
        CodeLen = 6;
4878
        WAsmCode[0] = 0xf2c0 | CondCode;
4879
        WAsmCode[2] = HVal & 0xffff;
4880
        WAsmCode[1] = HVal >> 16;
4881
        if (IsDisp16(HVal) && (PassNo > 1) && !*AttrPart.str.p_str)
4882
        {
4883
          WrError(ErrNum_ShortJumpPossible);
4884
          WAsmCode[0] ^= 0x40;
4885
          CodeLen -= 2;
4886
          WAsmCode[1] = WAsmCode[2];
4887
          StopfZahl++;
4888
        }
4889
      }
4890
    }
4891
  }
4892
}
4893
 
4894
static void DecodeFDBcc(Word CondCode)
4895
{
4896
  if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4897
  else if (CheckNoFamily(1 << eColdfire))
4898
  {
4899
    if ((OpSize != eSymbolSize16Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
4900
    else if (ChkArgCnt(2, 2))
4901
    {
4902
      tAdrResult AdrResult;
4903
 
4904
      if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
4905
      {
4906
        LongInt HVal;
4907
        Integer HVal16;
4908
        Boolean ValOK;
4909
        tSymbolFlags Flags;
4910
 
4911
        WAsmCode[0] = 0xf248 | AdrResult.AdrPart;
4912
        WAsmCode[1] = CondCode;
4913
        HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags) - (EProgCounter() + 4);
4914
        if (ValOK)
4915
        {
4916
          HVal16 = HVal;
4917
          WAsmCode[2] = HVal16;
4918
          if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
4919
            else CodeLen = 6;
4920
        }
4921
      }
4922
    }
4923
  }
4924
}
4925
 
4926
static void DecodeFScc(Word CondCode)
4927
{
4928
  if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4929
  else if (!CheckNoFamily(1 << eColdfire));
4930
  else if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
4931
  else if (ChkArgCnt(1, 1))
4932
  {
4933
    tAdrResult AdrResult;
4934
 
4935
    OpSize = eSymbolSize8Bit;
4936
    if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
4937
    {
4938
      CodeLen = 4 + AdrResult.Cnt;
4939
      WAsmCode[0] = 0xf240 | AdrResult.AdrPart;
4940
      WAsmCode[1] = CondCode;
4941
      CopyAdrVals(WAsmCode + 2, &AdrResult);
4942
    }
4943
  }
4944
}
4945
 
4946
static void DecodeFTRAPcc(Word CondCode)
4947
{
4948
  if (!FPUAvail) WrError(ErrNum_FPUNotEnabled);
4949
  else if (!CheckNoFamily(1 << eColdfire));
4950
  else
4951
  {
4952
    if (!*AttrPart.str.p_str)
4953
      OpSize = eSymbolSize8Bit;
4954
    if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
4955
    else if (ChkArgCnt(OpSize ? 1 : 0, OpSize ? 1 : 0))
4956
    {
4957
      WAsmCode[0] = 0xf278;
4958
      WAsmCode[1] = CondCode;
4959
      if (OpSize == eSymbolSize8Bit)
4960
      {
4961
        WAsmCode[0] |= 4;
4962
        CodeLen = 4;
4963
      }
4964
      else
4965
      {
4966
        tAdrResult AdrResult;
4967
 
4968
        if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
4969
        {
4970
          WAsmCode[0] |= (OpSize + 1);
4971
          CopyAdrVals(WAsmCode + 2, &AdrResult);
4972
          CodeLen = 4 + AdrResult.Cnt;
4973
        }
4974
      }
4975
    }
4976
  }
4977
}
4978
 
4979
/*-------------------------------------------------------------------------*/
4980
/* Hilfsroutinen MMU: */
4981
 
4982
static Boolean DecodeFC(const tStrComp *pArg, Word *erg)
4983
{
4984
  Boolean OK;
4985
  Word Val;
4986
 
4987
  if (!as_strcasecmp(pArg->str.p_str, "SFC"))
4988
  {
4989
    *erg = 0;
4990
    return True;
4991
  }
4992
 
4993
  if (!as_strcasecmp(pArg->str.p_str, "DFC"))
4994
  {
4995
    *erg = 1;
4996
    return True;
4997
  }
4998
 
4999
  switch (DecodeReg(pArg, erg, False))
5000
  {
5001
    case eIsReg:
5002
      if (*erg < 8)
5003
      {
5004
        *erg += 8;
5005
        return True;
5006
      }
5007
      break;
5008
    case eIsNoReg:
5009
      break;
5010
    default:
5011
      return False;
5012
  }
5013
 
5014
  if (*pArg->str.p_str == '#')
5015
  {
5016
    Val = EvalStrIntExpressionOffs(pArg, 1, Int4, &OK);
5017
    if (OK)
5018
      *erg = Val + 16;
5019
    return OK;
5020
  }
5021
 
5022
  return False;
5023
}
5024
 
5025
static Boolean DecodePMMUReg(char *Asc, Word *erg, tSymbolSize *pSize)
5026
{
5027
  Byte z;
5028
 
5029
  if ((strlen(Asc) == 4) && (!as_strncasecmp(Asc, "BAD", 3)) && ValReg(Asc[3]))
5030
  {
5031
    *pSize = eSymbolSize16Bit;
5032
    *erg = 0x7000 + ((Asc[3] - '0') << 2);
5033
    return True;
5034
  }
5035
  if ((strlen(Asc) == 4) && (!as_strncasecmp(Asc, "BAC", 3)) && ValReg(Asc[3]))
5036
  {
5037
    *pSize = eSymbolSize16Bit;
5038
    *erg = 0x7400 + ((Asc[3] - '0') << 2);
5039
    return True;
5040
  }
5041
 
5042
  for (z = 0; PMMURegs[z].pName; z++)
5043
    if (!as_strcasecmp(Asc, PMMURegs[z].pName))
5044
    {
5045
      *pSize = PMMURegs[z].Size;
5046
      *erg = PMMURegs[z].Code << 10;
5047
      return True;
5048
    }
5049
  return False;
5050
}
5051
 
5052
/*-------------------------------------------------------------------------*/
5053
 
5054
static void DecodePSAVE(Word Code)
5055
{
5056
  UNUSED(Code);
5057
 
5058
  if (!ChkArgCnt(1, 1));
5059
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5060
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5061
  else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5062
  else
5063
  {
5064
    tAdrResult AdrResult;
5065
 
5066
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5067
    {
5068
      CodeLen = 2 + AdrResult.Cnt;
5069
      WAsmCode[0] = 0xf100 | AdrResult.AdrPart;
5070
      CopyAdrVals(WAsmCode + 1, &AdrResult);
5071
      CheckSup();
5072
    }
5073
  }
5074
}
5075
 
5076
static void DecodePRESTORE(Word Code)
5077
{
5078
  UNUSED(Code);
5079
 
5080
  if (!ChkArgCnt(1, 1));
5081
  else if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5082
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5083
  else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5084
  else
5085
  {
5086
    tAdrResult AdrResult;
5087
 
5088
    RelPos = 4;
5089
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs, &AdrResult))
5090
    {
5091
      CodeLen = 2 + AdrResult.Cnt;
5092
      WAsmCode[0] = 0xf140 | AdrResult.AdrPart;
5093
      CopyAdrVals(WAsmCode + 1, &AdrResult);
5094
      CheckSup();
5095
    }
5096
  }
5097
}
5098
 
5099
static void DecodePFLUSHA(Word Code)
5100
{
5101
  UNUSED(Code);
5102
 
5103
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5104
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5105
  else if (ChkArgCnt(0, 0))
5106
  {
5107
    switch (pCurrCPUProps->Family)
5108
    {
5109
      case e68KGen3:
5110
        CodeLen = 2;
5111
        WAsmCode[0] = 0xf518;
5112
        break;
5113
      default:
5114
        CodeLen = 4;
5115
        WAsmCode[0] = 0xf000;
5116
        WAsmCode[1] = 0x2400;
5117
        break;
5118
    }
5119
    CheckSup();
5120
  }
5121
}
5122
 
5123
static void DecodePFLUSHAN(Word Code)
5124
{
5125
  UNUSED(Code);
5126
 
5127
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5128
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5129
  else if (ChkArgCnt(0, 0)
5130
        && CheckFamily(1 << e68KGen3))
5131
  {
5132
    CodeLen = 2;
5133
    WAsmCode[0] = 0xf510;
5134
    CheckSup();
5135
  }
5136
}
5137
 
5138
static void DecodePFLUSH_PFLUSHS(Word Code)
5139
{
5140
  tAdrResult AdrResult;
5141
 
5142
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5143
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5144
  else if (pCurrCPUProps->Family == e68KGen3)
5145
  {
5146
    if (Code) WrError(ErrNum_FullPMMUNotEnabled);
5147
    else if (ChkArgCnt(1, 1))
5148
    {
5149
      if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
5150
      {
5151
        WAsmCode[0] = 0xf508 + (AdrResult.AdrPart & 7);
5152
        CodeLen = 2;
5153
        CheckSup();
5154
      }
5155
    }
5156
  }
5157
  else if (!ChkArgCnt(2, 3));
5158
  else if ((Code) && (!FullPMMU)) WrError(ErrNum_FullPMMUNotEnabled);
5159
  else if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
5160
  else
5161
  {
5162
    OpSize = eSymbolSize8Bit;
5163
    if (DecodeAdr(&ArgStr[2], MModImm, &AdrResult))
5164
    {
5165
      if (AdrResult.Vals[0] > 15) WrError(ErrNum_InvFMask);
5166
      else
5167
      {
5168
        WAsmCode[1] |= (AdrResult.Vals[0] << 5) | 0x3000 | Code;
5169
        WAsmCode[0] = 0xf000;
5170
        CodeLen = 4;
5171
        CheckSup();
5172
        if (ArgCnt == 3)
5173
        {
5174
          WAsmCode[1] |= 0x800;
5175
          if (!DecodeAdr(&ArgStr[3], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5176
            CodeLen = 0;
5177
          else
5178
          {
5179
            WAsmCode[0] |= AdrResult.AdrPart;
5180
            CodeLen += AdrResult.Cnt;
5181
            CopyAdrVals(WAsmCode + 2, &AdrResult);
5182
          }
5183
        }
5184
      }
5185
    }
5186
  }
5187
}
5188
 
5189
static void DecodePFLUSHN(Word Code)
5190
{
5191
  UNUSED(Code);
5192
 
5193
  if (*AttrPart.str.p_str) WrError(ErrNum_UseLessAttr);
5194
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5195
  else if (ChkArgCnt(1, 1)
5196
        && CheckFamily(1 << e68KGen3))
5197
  {
5198
    tAdrResult AdrResult;
5199
 
5200
    if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
5201
    {
5202
      WAsmCode[0] = 0xf500 + (AdrResult.AdrPart & 7);
5203
      CodeLen = 2;
5204
      CheckSup();
5205
    }
5206
  }
5207
}
5208
 
5209
static void DecodePFLUSHR(Word Code)
5210
{
5211
  UNUSED(Code);
5212
 
5213
  if (*AttrPart.str.p_str)
5214
    OpSize = eSymbolSize64Bit;
5215
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5216
  if (OpSize != eSymbolSize64Bit) WrError(ErrNum_InvOpSize);
5217
  else if (!ChkArgCnt(1, 1));
5218
  else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5219
  else
5220
  {
5221
    tAdrResult AdrResult;
5222
 
5223
    RelPos = 4;
5224
    if (DecodeAdr(&ArgStr[1], MModAdrI | MModPre | MModPost | MModDAdrI | MModAIX | MModPC | MModPCIdx | MModAbs | MModImm, &AdrResult))
5225
    {
5226
      WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5227
      WAsmCode[1] = 0xa000;
5228
      CopyAdrVals(WAsmCode + 2, &AdrResult);
5229
      CodeLen = 4 + AdrResult.Cnt; CheckSup();
5230
    }
5231
  }
5232
}
5233
 
5234
static void DecodePLOADR_PLOADW(Word Code)
5235
{
5236
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5237
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5238
  else if (!ChkArgCnt(2, 2));
5239
  else if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
5240
  else
5241
  {
5242
    tAdrResult AdrResult;
5243
 
5244
    if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5245
    {
5246
      WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5247
      WAsmCode[1] |= Code;
5248
      CodeLen = 4 + AdrResult.Cnt;
5249
      CopyAdrVals(WAsmCode + 2, &AdrResult);
5250
      CheckSup();
5251
    }
5252
  }
5253
}
5254
 
5255
static void DecodePMOVE_PMOVEFD(Word Code)
5256
{
5257
  tSymbolSize RegSize;
5258
  unsigned Mask;
5259
  tAdrResult AdrResult;
5260
 
5261
  if (!ChkArgCnt(2, 2));
5262
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5263
  else
5264
  {
5265
    if (DecodePMMUReg(ArgStr[1].str.p_str, WAsmCode + 1, &RegSize))
5266
    {
5267
      WAsmCode[1] |= 0x200;
5268
      if (!*AttrPart.str.p_str)
5269
        OpSize = RegSize;
5270
      if (OpSize != RegSize) WrError(ErrNum_InvOpSize);
5271
      else
5272
      {
5273
        Mask = MModAdrI | MModDAdrI | MModAIX | MModAbs;
5274
        if (FullPMMU)
5275
        {
5276
          Mask *= MModPost | MModPre;
5277
          if (RegSize != eSymbolSize64Bit)
5278
            Mask += MModData | MModAdr;
5279
        }
5280
        if (DecodeAdr(&ArgStr[2], Mask, &AdrResult))
5281
        {
5282
          WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5283
          CodeLen = 4 + AdrResult.Cnt;
5284
          CopyAdrVals(WAsmCode + 2, &AdrResult);
5285
          CheckSup();
5286
        }
5287
      }
5288
    }
5289
    else if (DecodePMMUReg(ArgStr[2].str.p_str, WAsmCode + 1, &RegSize))
5290
    {
5291
      if (!*AttrPart.str.p_str)
5292
        OpSize = RegSize;
5293
      if (OpSize != RegSize) WrError(ErrNum_InvOpSize);
5294
      else
5295
      {
5296
        RelPos = 4;
5297
        Mask = MModAdrI | MModDAdrI | MModAIX | MModAbs;
5298
        if (FullPMMU)
5299
        {
5300
          Mask += MModPost | MModPre | MModPC | MModPCIdx | MModImm;
5301
          if (RegSize != eSymbolSize64Bit)
5302
            Mask += MModData | MModAdr;
5303
        }
5304
        if (DecodeAdr(&ArgStr[1], Mask, &AdrResult))
5305
        {
5306
          WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5307
          CodeLen = 4 + AdrResult.Cnt;
5308
          CopyAdrVals(WAsmCode + 2, &AdrResult);
5309
          WAsmCode[1] += Code;
5310
          CheckSup();
5311
        }
5312
      }
5313
    }
5314
    else
5315
      WrError(ErrNum_InvMMUReg);
5316
  }
5317
}
5318
 
5319
static void DecodePTESTR_PTESTW(Word Code)
5320
{
5321
  tAdrResult AdrResult;
5322
 
5323
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5324
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5325
  else if (pCurrCPUProps->Family == e68KGen3)
5326
  {
5327
    if (ChkArgCnt(1, 1))
5328
    {
5329
      if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
5330
      {
5331
        WAsmCode[0] = 0xf548 + (AdrResult.AdrPart & 7) + (Code << 5);
5332
        CodeLen = 2;
5333
        CheckSup();
5334
      }
5335
    }
5336
  }
5337
  else if (ChkArgCnt(3, 4))
5338
  {
5339
    if (!DecodeFC(&ArgStr[1], WAsmCode + 1)) WrError(ErrNum_InvFCode);
5340
    else
5341
    {
5342
      if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5343
      {
5344
        WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5345
        CodeLen = 4 + AdrResult.Cnt;
5346
        WAsmCode[1] |= 0x8000 | (Code << 9);
5347
        CopyAdrVals(WAsmCode + 2, &AdrResult);
5348
        if (DecodeAdr(&ArgStr[3], MModImm, &AdrResult))
5349
        {
5350
          if (AdrResult.Vals[0] > 7)
5351
          {
5352
            WrError(ErrNum_Level07);
5353
            CodeLen = 0;
5354
          }
5355
          else
5356
          {
5357
            WAsmCode[1] |= AdrResult.Vals[0] << 10;
5358
            if (ArgCnt == 4)
5359
            {
5360
              if (!DecodeAdr(&ArgStr[4], MModAdr, &AdrResult))
5361
                CodeLen = 0;
5362
              else
5363
                WAsmCode[1] |= AdrResult.AdrPart << 5;
5364
              CheckSup();
5365
            }
5366
          }
5367
        }
5368
        else
5369
          CodeLen = 0;
5370
      }
5371
    }
5372
  }
5373
}
5374
 
5375
static void DecodePVALID(Word Code)
5376
{
5377
  UNUSED(Code);
5378
 
5379
  if (!ChkArgCnt(2, 2));
5380
  else if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5381
  else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5382
  else if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
5383
  else
5384
  {
5385
    tAdrResult AdrResult;
5386
 
5387
    if (DecodeAdr(&ArgStr[2], MModAdrI | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5388
    {
5389
      WAsmCode[0] = 0xf000 | AdrResult.AdrPart;
5390
      WAsmCode[1] = 0x2800;
5391
      CodeLen = 4 + AdrResult.Cnt;
5392
      CopyAdrVals(WAsmCode + 1, &AdrResult);
5393
      if (!as_strcasecmp(ArgStr[1].str.p_str, "VAL"));
5394
      else
5395
      {
5396
        if (DecodeAdr(&ArgStr[1], MModAdr, &AdrResult))
5397
          WAsmCode[1] |= 0x400 | (AdrResult.AdrPart & 7);
5398
        else
5399
          CodeLen = 0;
5400
      }
5401
    }
5402
  }
5403
}
5404
 
5405
static void DecodePBcc(Word CondCode)
5406
{
5407
  if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5408
  else
5409
  {
5410
    if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit) && (OpSize != eSymbolSizeFloat96Bit)) WrError(ErrNum_InvOpSize);
5411
    else if (!ChkArgCnt(1, 1));
5412
    else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5413
    else
5414
    {
5415
      LongInt HVal;
5416
      Integer HVal16;
5417
      Boolean ValOK;
5418
      tSymbolFlags Flags;
5419
 
5420
      HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &ValOK, &Flags) - (EProgCounter() + 2);
5421
      HVal16 = HVal;
5422
 
5423
      if (!*AttrPart.str.p_str)
5424
        OpSize = (IsDisp16(HVal)) ? eSymbolSize32Bit : eSymbolSizeFloat96Bit;
5425
 
5426
      if ((OpSize == eSymbolSize32Bit) || (OpSize == eSymbolSize16Bit))
5427
      {
5428
        if (!IsDisp16(HVal) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
5429
        else
5430
        {
5431
          CodeLen = 4;
5432
          WAsmCode[0] = 0xf080 | CondCode;
5433
          WAsmCode[1] = HVal16;
5434
          CheckSup();
5435
        }
5436
      }
5437
      else
5438
      {
5439
        CodeLen = 6;
5440
        WAsmCode[0] = 0xf0c0 | CondCode;
5441
        WAsmCode[2] = HVal & 0xffff;
5442
        WAsmCode[1] = HVal >> 16;
5443
        CheckSup();
5444
      }
5445
    }
5446
  }
5447
}
5448
 
5449
static void DecodePDBcc(Word CondCode)
5450
{
5451
  if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5452
  else
5453
  {
5454
    if ((OpSize != eSymbolSize16Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5455
    else if (!ChkArgCnt(2, 2));
5456
    else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5457
    else
5458
    {
5459
      tAdrResult AdrResult;
5460
 
5461
      if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
5462
      {
5463
        LongInt HVal;
5464
        Integer HVal16;
5465
        Boolean ValOK;
5466
        tSymbolFlags Flags;
5467
 
5468
        WAsmCode[0] = 0xf048 | AdrResult.AdrPart;
5469
        WAsmCode[1] = CondCode;
5470
        HVal = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &ValOK, &Flags) - (EProgCounter() + 4);
5471
        if (ValOK)
5472
        {
5473
          HVal16 = HVal;
5474
          WAsmCode[2] = HVal16;
5475
          if ((!IsDisp16(HVal)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
5476
          else
5477
            CodeLen = 6;
5478
          CheckSup();
5479
        }
5480
      }
5481
    }
5482
  }
5483
}
5484
 
5485
static void DecodePScc(Word CondCode)
5486
{
5487
  if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5488
  else
5489
  {
5490
    if ((OpSize != eSymbolSize8Bit) && *AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5491
    else if (!ChkArgCnt(1, 1));
5492
    else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5493
    else
5494
    {
5495
      tAdrResult AdrResult;
5496
 
5497
      OpSize = eSymbolSize8Bit;
5498
      if (DecodeAdr(&ArgStr[1], MModData | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5499
      {
5500
        CodeLen = 4 + AdrResult.Cnt;
5501
        WAsmCode[0] = 0xf040 | AdrResult.AdrPart;
5502
        WAsmCode[1] = CondCode;
5503
        CopyAdrVals(WAsmCode + 2, &AdrResult);
5504
        CheckSup();
5505
      }
5506
    }
5507
  }
5508
}
5509
 
5510
static void DecodePTRAPcc(Word CondCode)
5511
{
5512
  if (!PMMUAvail) WrError(ErrNum_PMMUNotEnabled);
5513
  else
5514
  {
5515
    if (!*AttrPart.str.p_str)
5516
      OpSize = eSymbolSize8Bit;
5517
    if (OpSize > 2) WrError(ErrNum_InvOpSize);
5518
    else if (!ChkArgCnt(OpSize ? 1 : 0, OpSize ? 1 : 0));
5519
    else if (!FullPMMU) WrError(ErrNum_FullPMMUNotEnabled);
5520
    else
5521
    {
5522
      WAsmCode[0] = 0xf078;
5523
      WAsmCode[1] = CondCode;
5524
      if (OpSize == eSymbolSize8Bit)
5525
      {
5526
        WAsmCode[0] |= 4;
5527
        CodeLen = 4;
5528
        CheckSup();
5529
      }
5530
      else
5531
      {
5532
        tAdrResult AdrResult;
5533
 
5534
        if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
5535
        {
5536
          WAsmCode[0] |= (OpSize + 1);
5537
          CopyAdrVals(WAsmCode + 2, &AdrResult);
5538
          CodeLen = 4 + AdrResult.Cnt;
5539
          CheckSup();
5540
        }
5541
      }
5542
    }
5543
  }
5544
}
5545
 
5546
static void DecodeColdBit(Word Code)
5547
{
5548
  if (!*AttrPart.str.p_str)
5549
    OpSize = eSymbolSize32Bit;
5550
  if (ChkArgCnt(1, 1)
5551
   && CheckColdSize()
5552
   && CheckFamily(1 << eColdfire)
5553
   && CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_C)))
5554
  {
5555
    tAdrResult AdrResult;
5556
 
5557
    if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
5558
    {
5559
      CodeLen = 2;
5560
      WAsmCode[0] = Code | (AdrResult.AdrPart & 7);
5561
    }
5562
  }
5563
}
5564
 
5565
static void DecodeSTLDSR(Word Code)
5566
{
5567
  UNUSED(Code);
5568
 
5569
  if (!*AttrPart.str.p_str)
5570
    OpSize = eSymbolSize16Bit;
5571
  if (OpSize != eSymbolSize16Bit) WrError(ErrNum_InvOpSize);
5572
  else if (ChkArgCnt(1, 1)
5573
        && CheckFamily(1 << eColdfire)
5574
        && CheckISA((1 << eCfISA_APlus) | (1 << eCfISA_C)))
5575
  {
5576
    tAdrResult AdrResult;
5577
 
5578
    if (DecodeAdr(&ArgStr[1], MModImm, &AdrResult))
5579
    {
5580
      CodeLen = 6;
5581
      WAsmCode[0] = 0x40e7;
5582
      WAsmCode[1] = 0x46fc;
5583
      WAsmCode[2] = AdrResult.Vals[0];
5584
    }
5585
  }
5586
}
5587
 
5588
static void DecodeINTOUCH(Word Code)
5589
{
5590
  UNUSED(Code);
5591
 
5592
  if (*AttrPart.str.p_str) WrError(ErrNum_InvOpSize);
5593
  else if (ChkArgCnt(1, 1)
5594
        && CheckFamily(1 << eColdfire)
5595
        && (pCurrCPUProps->CfISA >= eCfISA_B))
5596
  {
5597
    tAdrResult AdrResult;
5598
 
5599
    if (DecodeAdr(&ArgStr[1], MModAdrI, &AdrResult))
5600
    {
5601
      CodeLen = 2;
5602
      WAsmCode[0] = 0xf428 | (AdrResult.AdrPart & 7);
5603
      CheckSup();
5604
    }
5605
  }
5606
}
5607
 
5608
static void DecodeMOV3Q(Word Code)
5609
{
5610
  Boolean OK;
5611
  tSymbolFlags Flags;
5612
  ShortInt Val;
5613
  tAdrResult AdrResult;
5614
 
5615
  UNUSED(Code);
5616
 
5617
  if (!ChkArgCnt(2, 2)
5618
   || !CheckFamily(1 << eColdfire)
5619
   || (pCurrCPUProps->CfISA < eCfISA_B)
5620
   || !CheckColdSize())
5621
    return;
5622
 
5623
  if (!DecodeAdr(&ArgStr[2], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs, &AdrResult))
5624
    return;
5625
 
5626
  if (*ArgStr[1].str.p_str != '#')
5627
  {
5628
    WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
5629
    return;
5630
  }
5631
 
5632
  Val = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, SInt4, &OK, &Flags);
5633
  if (!OK)
5634
    return;
5635
  if (mFirstPassUnknown(Flags))
5636
    Val = 1;
5637
 
5638
  if (Val == -1)
5639
    Val = 0;
5640
  else if (!ChkRange(Val, 1, 7))
5641
    return;
5642
 
5643
  WAsmCode[0] = 0xa140 | ((Val & 7) << 9) | AdrResult.AdrPart;
5644
  CopyAdrVals(WAsmCode + 1, &AdrResult);
5645
  CodeLen = 2 + AdrResult.Cnt;
5646
}
5647
 
5648
static void DecodeMVS_MVZ(Word Code)
5649
{
5650
  Word DestReg;
5651
  tAdrResult AdrResult;
5652
 
5653
  if (!ChkArgCnt(2, 2)
5654
   || !CheckFamily(1 << eColdfire)
5655
   || (pCurrCPUProps->CfISA < eCfISA_B))
5656
    return;
5657
 
5658
  if (!*AttrPart.str.p_str)
5659
    OpSize = eSymbolSize16Bit;
5660
  if (OpSize > eSymbolSize16Bit)
5661
  {
5662
    WrError(ErrNum_InvOpSize);
5663
    return;
5664
  }
5665
 
5666
  if (!DecodeAdr(&ArgStr[2], MModData, &AdrResult))
5667
    return;
5668
  DestReg = AdrResult.AdrPart & 7;
5669
 
5670
  if (DecodeAdr(&ArgStr[1], MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI | MModAIX | MModAbs | MModImm | MModPC | MModPCIdx, &AdrResult))
5671
  {
5672
    WAsmCode[0] = Code | (DestReg << 9) | (OpSize << 6) | AdrResult.AdrPart;
5673
    CopyAdrVals(WAsmCode + 1, &AdrResult);
5674
    CodeLen = 2 + AdrResult.Cnt;
5675
  }
5676
}
5677
 
5678
static void DecodeSATS(Word Code)
5679
{
5680
  tAdrResult AdrResult;
5681
 
5682
  UNUSED(Code);
5683
 
5684
  if (!ChkArgCnt(1, 1)
5685
   || !CheckFamily(1 << eColdfire)
5686
   || (pCurrCPUProps->CfISA < eCfISA_B)
5687
   || !CheckColdSize())
5688
    return;
5689
 
5690
  if (DecodeAdr(&ArgStr[1], MModData, &AdrResult))
5691
  {
5692
    WAsmCode[0] = 0x4c80 | (AdrResult.AdrPart & 7);
5693
    CodeLen = 2;
5694
  }
5695
}
5696
 
5697
static void DecodeMAC_MSAC(Word Code)
5698
{
5699
  Word Rx, Ry, Rw, Ux = 0, Uy = 0, Scale = 0, Mask, AccNum = 0;
5700
  int CurrArg, RemArgCnt;
5701
  Boolean ExplicitLoad = !!(Code & 0x8000);
5702
  tAdrResult AdrResult;
5703
 
5704
  Code &= 0x7fff;
5705
 
5706
  if (!(pCurrCPUProps->SuppFlags & eFlagMAC))
5707
  {
5708
    WrError(ErrNum_InstructionNotSupported);
5709
    return;
5710
  }
5711
 
5712
  if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit))
5713
  {
5714
    WrError(ErrNum_InvOpSize);
5715
    return;
5716
  }
5717
 
5718
  /* 2 args is the absolute minimum.  6 is the maximum (Ry, Rx, scale, <ea>, Rw, ACC) */
5719
 
5720
  if (!ChkArgCnt(2, 6))
5721
    return;
5722
 
5723
  /* Ry and Rx are always present, and are always the first arguments: */
5724
 
5725
  if (OpSize == eSymbolSize16Bit)
5726
  {
5727
    if (!SplitMACUpperLower(&Uy, &ArgStr[1])
5728
     || !SplitMACUpperLower(&Ux, &ArgStr[2]))
5729
      return;
5730
  }
5731
 
5732
  if (!DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
5733
    return;
5734
  Ry = AdrResult.AdrPart & 15;
5735
  if (!DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
5736
    return;
5737
  Rx = AdrResult.AdrPart & 15;
5738
  CurrArg = 3;
5739
 
5740
  /* Is a scale given as next argument? */
5741
 
5742
  if ((ArgCnt >= CurrArg) && DecodeMACScale(&ArgStr[CurrArg], &Scale))
5743
    CurrArg++;
5744
 
5745
  /* We now have between 0 and 3 args left:
5746
 
5747
     1 -> ACCn
5748
     2 -> load, ACC0
5749
     3 -> load, ACCn
5750
     If the 'L' variant (MACL, MSACL) was given, a parallel
5751
     load was specified explicitly and there MUST be the <ea> and Rw arguments: */
5752
 
5753
  RemArgCnt = ArgCnt - CurrArg + 1;
5754
  if ((RemArgCnt > 3)
5755
   || (ExplicitLoad && (RemArgCnt < 2)))
5756
  {
5757
    WrError(ErrNum_WrongArgCnt);
5758
    return;
5759
  }
5760
 
5761
  /* assumed ACC(0) if no accumulator given */
5762
 
5763
  if (Odd(RemArgCnt))
5764
  {
5765
    if (!DecodeMACACC(ArgStr[ArgCnt].str.p_str, &AccNum))
5766
    {
5767
      WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt]);
5768
      return;
5769
    }
5770
  }
5771
 
5772
  /* If parallel load, bit 7 of first word is set for MAC.  This bit is
5773
     used on EMAC to store accumulator # LSB.  To keep things upward-compatible,
5774
     accumulator # LSB is stored inverted on EMAC if a parallel load is present.
5775
     Since MAC only uses accumulator #0, this works for either target: */
5776
 
5777
  if (RemArgCnt >= 2)
5778
    AccNum ^= 1;
5779
 
5780
  /* Common things for variant with and without parallel load: */
5781
 
5782
  WAsmCode[0] = 0xa000 | ((AccNum & 1) << 7);
5783
  WAsmCode[1] = ((OpSize - 1) << 11) | (Scale << 9) | Code | (Ux << 7) | (Uy << 6) | ((AccNum & 2) << 3);
5784
 
5785
  /* With parallel load? */
5786
 
5787
  if (RemArgCnt >= 2)
5788
  {
5789
    tStrComp CurrArgStr;
5790
 
5791
    if (!DecodeAdr(&ArgStr[CurrArg + 1], MModData | MModAdr, &AdrResult))
5792
      return;
5793
    Rw = AdrResult.AdrPart & 15;
5794
 
5795
    StrCompRefRight(&CurrArgStr, &ArgStr[CurrArg], 0);
5796
    if (!SplitMACANDMASK(&Mask, &CurrArgStr))
5797
      return;
5798
    if (!DecodeAdr(&CurrArgStr, MModAdrI | MModPre | MModPost | MModDAdrI, &AdrResult))
5799
      return;
5800
 
5801
    WAsmCode[0] |= ((Rw & 7) << 9) | ((Rw & 8) << 3) | AdrResult.AdrPart;
5802
    WAsmCode[1] |= (Mask << 5) | (Rx << 12) | (Ry << 0);
5803
    CodeLen = 4 + AdrResult.Cnt;
5804
    CopyAdrVals(WAsmCode + 2, &AdrResult);
5805
  }
5806
 
5807
  /* multiply/accumulate only */
5808
 
5809
  else
5810
  {
5811
    WAsmCode[0] |= Ry | ((Rx & 7) << 9) | ((Rx & 8) << 3);
5812
    CodeLen = 4;
5813
  }
5814
}
5815
 
5816
static void DecodeMOVCLR(Word Code)
5817
{
5818
  Word ACCReg;
5819
 
5820
  UNUSED(Code);
5821
 
5822
  if (!ChkArgCnt(2,2));
5823
  else if (*AttrPart.str.p_str && (OpSize != eSymbolSize32Bit)) WrError(ErrNum_InvOpSize);
5824
  else if (!(pCurrCPUProps->SuppFlags & eFlagEMAC)) WrError(ErrNum_InstructionNotSupported);
5825
  else if (!DecodeMACACC(ArgStr[1].str.p_str, &ACCReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
5826
  else
5827
  {
5828
    tAdrResult AdrResult;
5829
 
5830
    if (DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
5831
    {
5832
      WAsmCode[0] = 0xa1c0 | AdrResult.AdrPart | (ACCReg << 9);
5833
      CodeLen = 2;
5834
    }
5835
  }
5836
}
5837
 
5838
static void DecodeMxxAC(Word Code)
5839
{
5840
  Word Rx, Ry, Ux, Uy, Scale = 0, ACCx, ACCw;
5841
  tAdrResult AdrResult;
5842
 
5843
  if (!(pCurrCPUProps->SuppFlags & eFlagEMAC)
5844
    || (pCurrCPUProps->CfISA < eCfISA_B))
5845
  {
5846
    WrError(ErrNum_InstructionNotSupported);
5847
    return;
5848
  }
5849
 
5850
  if ((OpSize != eSymbolSize16Bit) && (OpSize != eSymbolSize32Bit))
5851
  {
5852
    WrError(ErrNum_InvOpSize);
5853
    return;
5854
  }
5855
 
5856
  if (!ChkArgCnt(4, 5))
5857
    return;
5858
 
5859
  if (!DecodeMACACC(ArgStr[ArgCnt - 1].str.p_str, &ACCx))
5860
  {
5861
    WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt - 1]);
5862
    return;
5863
  }
5864
  if (!DecodeMACACC(ArgStr[ArgCnt].str.p_str, &ACCw))
5865
  {
5866
    WrStrErrorPos(ErrNum_InvReg, &ArgStr[ArgCnt]);
5867
    return;
5868
  }
5869
 
5870
  if (5 == ArgCnt)
5871
  {
5872
    if (!DecodeMACScale(&ArgStr[3], &Scale))
5873
    {
5874
      WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[3]);
5875
      return;
5876
    }
5877
  }
5878
 
5879
  if (OpSize == eSymbolSize16Bit)
5880
  {
5881
    if (!SplitMACUpperLower(&Uy, &ArgStr[1])
5882
     || !SplitMACUpperLower(&Ux, &ArgStr[2]))
5883
      return;
5884
  }
5885
  else
5886
    Ux = Uy = 0;
5887
 
5888
  if (!DecodeAdr(&ArgStr[1], MModData | MModAdr, &AdrResult))
5889
    return;
5890
  Ry = AdrResult.AdrPart & 15;
5891
  if (!DecodeAdr(&ArgStr[2], MModData | MModAdr, &AdrResult))
5892
    return;
5893
  Rx = AdrResult.AdrPart & 15;
5894
 
5895
  WAsmCode[0] = 0xa000 | ((Rx & 7) << 9) | ((Rx & 8) << 3) | Ry | ((ACCx & 1) << 7);
5896
  WAsmCode[1] = Code | ((OpSize - 1) << 11) | (Scale << 9) | (Ux << 7) | (Uy << 6) | ((ACCx & 2) << 3) | (ACCw << 2);
5897
  CodeLen = 4;
5898
}
5899
 
5900
static void DecodeCPBCBUSY(Word Code)
5901
{
5902
  if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
5903
  else if (*AttrPart.str.p_str && (OpSize != eSymbolSize16Bit)) WrError(ErrNum_InvOpSize);
5904
  else if (ChkArgCnt(1, 1))
5905
  {
5906
    Boolean OK;
5907
    tSymbolFlags Flags;
5908
    LongInt Dist;
5909
 
5910
    Dist = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags) - (EProgCounter() + 2);
5911
    if (OK)
5912
    {
5913
      if (!mSymbolQuestionable(Flags) && !IsDisp16(Dist)) WrError(ErrNum_JmpDistTooBig);
5914
      else
5915
      {
5916
        WAsmCode[0] = Code;
5917
        WAsmCode[1] = Dist & 0xffff;
5918
        CodeLen = 4;
5919
      }
5920
    }
5921
  }
5922
}
5923
 
5924
static void DecodeCPLDST(Word Code)
5925
{
5926
  if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
5927
  else if (ChkArgCnt(1, 4))
5928
  {
5929
    Boolean OK;
5930
    Word Reg;
5931
    const tStrComp *pEAArg = NULL, *pRnArg = NULL, *pETArg = NULL;
5932
 
5933
    WAsmCode[0] = Code | (OpSize << 6);
5934
 
5935
    /* CMD is always present and i bits 0..8 - immediate marker is optional
5936
       since it is always a constant. */
5937
 
5938
    WAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[ArgCnt], !!(*ArgStr[ArgCnt].str.p_str == '#'), UInt16, &OK);
5939
    if (!OK)
5940
      return;
5941
 
5942
    if (ArgCnt >= 2)
5943
      pEAArg = &ArgStr[1];
5944
    switch (ArgCnt)
5945
    {
5946
      case 4:
5947
        pRnArg = &ArgStr[2];
5948
        pETArg = &ArgStr[3];
5949
        break;
5950
      case 3:
5951
        if (DecodeReg(&ArgStr[2], &Reg, False) == eIsReg)
5952
          pRnArg = &ArgStr[2];
5953
        else
5954
          pETArg = &ArgStr[2];
5955
        break;
5956
     }
5957
 
5958
    if (pRnArg)
5959
    {
5960
      if (DecodeReg(pRnArg, &Reg, True) != eIsReg)
5961
        return;
5962
      WAsmCode[1] |= Reg << 12;
5963
    }
5964
    if (pETArg)
5965
    {
5966
      Word ET;
5967
 
5968
      ET = EvalStrIntExpression(pETArg, UInt3, &OK);
5969
      if (!OK)
5970
        return;
5971
      WAsmCode[1] |= ET << 9;
5972
    }
5973
 
5974
    if (pEAArg)
5975
    {
5976
      tAdrResult AdrResult;
5977
 
5978
      if (!DecodeAdr(pEAArg, MModData | MModAdr | MModAdrI | MModPost | MModPre | MModDAdrI, &AdrResult))
5979
        return;
5980
      WAsmCode[0] |= AdrResult.AdrPart;
5981
      CopyAdrVals(WAsmCode + 2, &AdrResult);
5982
      CodeLen = 4 + AdrResult.Cnt;
5983
    }
5984
    else
5985
      CodeLen = 4;
5986
  }
5987
}
5988
 
5989
static void DecodeCPNOP(Word Code)
5990
{
5991
  if (pCurrCPUProps->CfISA == eCfISA_None) WrError(ErrNum_InstructionNotSupported);
5992
  else if (ChkArgCnt(0, 1))
5993
  {
5994
    WAsmCode[0] = Code | (OpSize << 6);
5995
 
5996
    /* CMD is always present and i bits 0..8 - immediate marker is optional
5997
       since it is always a constant. */
5998
 
5999
    if (ArgCnt > 0)
6000
    {
6001
      Word ET;
6002
      Boolean OK;
6003
 
6004
      ET = EvalStrIntExpression(&ArgStr[1], UInt3, &OK);
6005
      if (!OK)
6006
        return;
6007
      WAsmCode[1] |= ET << 9;
6008
    }
6009
 
6010
    CodeLen = 4;
6011
  }
6012
}
6013
 
6014
/*-------------------------------------------------------------------------*/
6015
/* Dekodierroutinen Pseudoinstruktionen: */
6016
 
6017
static void PutByte(Byte b)
6018
{
6019
  if ((CodeLen & 1) && !HostBigEndian)
6020
  {
6021
    BAsmCode[CodeLen] = BAsmCode[CodeLen - 1];
6022
    BAsmCode[CodeLen - 1] = b;
6023
  }
6024
  else
6025
  {
6026
    BAsmCode[CodeLen] = b;
6027
  }
6028
  CodeLen++;
6029
}
6030
 
6031
static void DecodeSTR(Word Index)
6032
{
6033
  int l, z;
6034
  UNUSED(Index);
6035
 
6036
  if (!ChkArgCnt(1, 1));
6037
  else if (((l = strlen(ArgStr[1].str.p_str)) < 2)
6038
        || (*ArgStr[1].str.p_str != '\'')
6039
        || (ArgStr[1].str.p_str[l - 1] != '\'')) WrStrErrorPos(ErrNum_ExpectString, &ArgStr[1]);
6040
  else
6041
  {
6042
    PutByte(l - 2);
6043
    for (z = 1; z < l - 1; z++)
6044
      PutByte(as_chartrans_xlate(CurrTransTable->p_table, ((usint) ArgStr[1].str.p_str[z]) & 0xff));
6045
  }
6046
}
6047
 
6048
static void assure_pc_even(Word index)
6049
{
6050
  UNUSED(index);
6051
 
6052
  if (Odd(EProgCounter()))
6053
  {
6054
    if (DoPadding)
6055
      InsertPadding(1, False);
6056
    else
6057
      WrError(ErrNum_AddrNotAligned);
6058
  }
6059
}
6060
 
6061
/*-------------------------------------------------------------------------*/
6062
/* Codetabellenverwaltung */
6063
 
6064
static void AddFixed(const char *NName, Word NCode, Boolean NSup, unsigned NMask)
6065
{
6066
  order_array_rsv_end(FixedOrders, FixedOrder);
6067
  FixedOrders[InstrZ].Code = NCode;
6068
  FixedOrders[InstrZ].MustSup = NSup;
6069
  FixedOrders[InstrZ].FamilyMask = NMask;
6070
  AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
6071
}
6072
 
6073
static void AddCond(const char *NName, Byte NCode)
6074
{
6075
  char TmpName[30];
6076
 
6077
  if (NCode >= 2) /* BT is BRA and BF is BSR */
6078
  {
6079
    as_snprintf(TmpName, sizeof(TmpName), "B%s", NName);
6080
    AddInstTable(InstTable, TmpName, NCode, DecodeBcc);
6081
  }
6082
  as_snprintf(TmpName, sizeof(TmpName), "S%s", NName);
6083
  AddInstTable(InstTable, TmpName, NCode, DecodeScc);
6084
  as_snprintf(TmpName, sizeof(TmpName), "DB%s", NName);
6085
  AddInstTable(InstTable, TmpName, NCode, DecodeDBcc);
6086
  as_snprintf(TmpName, sizeof(TmpName), "TRAP%s", NName);
6087
  AddInstTable(InstTable, TmpName, NCode, DecodeTRAPcc);
6088
}
6089
 
6090
static void AddFPUOp(const char *NName, Byte NCode, Boolean NDya, tSuppFlags NeedFlags)
6091
{
6092
  order_array_rsv_end(FPUOps, FPUOp);
6093
  FPUOps[InstrZ].Code = NCode;
6094
  FPUOps[InstrZ].Dya = NDya;
6095
  FPUOps[InstrZ].NeedsSuppFlags = NeedFlags;
6096
  AddInstTable(InstTable, NName, InstrZ++, DecodeFPUOp);
6097
}
6098
 
6099
static void AddFPUCond(const char *NName, Byte NCode)
6100
{
6101
  char TmpName[30];
6102
 
6103
  as_snprintf(TmpName, sizeof(TmpName), "FB%s", NName);
6104
  AddInstTable(InstTable, TmpName, NCode, DecodeFBcc);
6105
  as_snprintf(TmpName, sizeof(TmpName), "FDB%s", NName);
6106
  AddInstTable(InstTable, TmpName, NCode, DecodeFDBcc);
6107
  as_snprintf(TmpName, sizeof(TmpName), "FS%s", NName);
6108
  AddInstTable(InstTable, TmpName, NCode, DecodeFScc);
6109
  as_snprintf(TmpName, sizeof(TmpName), "FTRAP%s", NName);
6110
  AddInstTable(InstTable, TmpName, NCode, DecodeFTRAPcc);
6111
}
6112
 
6113
static void AddPMMUCond(const char *NName)
6114
{
6115
  char TmpName[30];
6116
 
6117
  as_snprintf(TmpName, sizeof(TmpName), "PB%s", NName);
6118
  AddInstTable(InstTable, TmpName, InstrZ, DecodePBcc);
6119
  as_snprintf(TmpName, sizeof(TmpName), "PDB%s", NName);
6120
  AddInstTable(InstTable, TmpName, InstrZ, DecodePDBcc);
6121
  as_snprintf(TmpName, sizeof(TmpName), "PS%s", NName);
6122
  AddInstTable(InstTable, TmpName, InstrZ, DecodePScc);
6123
  as_snprintf(TmpName, sizeof(TmpName), "PTRAP%s", NName);
6124
  AddInstTable(InstTable, TmpName, InstrZ, DecodePTRAPcc);
6125
  InstrZ++;
6126
}
6127
 
6128
static void AddPMMUReg(const char *Name, tSymbolSize Size, Word Code)
6129
{
6130
  order_array_rsv_end(PMMURegs, PMMUReg);
6131
  PMMURegs[InstrZ].pName = Name;
6132
  PMMURegs[InstrZ].Size = Size;
6133
  PMMURegs[InstrZ++].Code = Code;
6134
}
6135
 
6136
static void InitFields(void)
6137
{
6138
  InstTable = CreateInstTable(607);
6139
  SetDynamicInstTable(InstTable);
6140
 
6141
  inst_table_set_prefix_proc(InstTable, assure_pc_even, 0);
6142
 
6143
  AddInstTable(InstTable, "MOVE"   , Std_Variant, DecodeMOVE);
6144
  AddInstTable(InstTable, "MOVEA"  , A_Variant, DecodeMOVE);
6145
  AddInstTable(InstTable, "MOVEI"  , I_Variant, DecodeMOVE);
6146
  AddInstTable(InstTable, "LEA"    , 0, DecodeLEA);
6147
  AddInstTable(InstTable, "ASR"    , 0, DecodeShift);
6148
  AddInstTable(InstTable, "ASL"    , 4, DecodeShift);
6149
  AddInstTable(InstTable, "LSR"    , 1, DecodeShift);
6150
  AddInstTable(InstTable, "LSL"    , 5, DecodeShift);
6151
  AddInstTable(InstTable, "ROXR"   , 2, DecodeShift);
6152
  AddInstTable(InstTable, "ROXL"   , 6, DecodeShift);
6153
  AddInstTable(InstTable, "ROR"    , 3, DecodeShift);
6154
  AddInstTable(InstTable, "ROL"    , 7, DecodeShift);
6155
  AddInstTable(InstTable, "ADDQ"   , 0, DecodeADDQSUBQ);
6156
  AddInstTable(InstTable, "SUBQ"   , 1, DecodeADDQSUBQ);
6157
  AddInstTable(InstTable, "ADDX"   , 1, DecodeADDXSUBX);
6158
  AddInstTable(InstTable, "SUBX"   , 0, DecodeADDXSUBX);
6159
  AddInstTable(InstTable, "CMPM"   , 0, DecodeCMPM);
6160
  AddInstTable(InstTable, "SUB"    , Std_Variant + 0, DecodeADDSUBCMP);
6161
  AddInstTable(InstTable, "CMP"    , Std_Variant + 1, DecodeADDSUBCMP);
6162
  AddInstTable(InstTable, "ADD"    , Std_Variant + 2, DecodeADDSUBCMP);
6163
  AddInstTable(InstTable, "SUBI"   , I_Variant + 0, DecodeADDSUBCMP);
6164
  AddInstTable(InstTable, "CMPI"   , I_Variant + 1, DecodeADDSUBCMP);
6165
  AddInstTable(InstTable, "ADDI"   , I_Variant + 2, DecodeADDSUBCMP);
6166
  AddInstTable(InstTable, "SUBA"   , A_Variant + 0, DecodeADDSUBCMP);
6167
  AddInstTable(InstTable, "CMPA"   , A_Variant + 1, DecodeADDSUBCMP);
6168
  AddInstTable(InstTable, "ADDA"   , A_Variant + 2, DecodeADDSUBCMP);
6169
  AddInstTable(InstTable, "AND"    , Std_Variant + 1, DecodeANDOR);
6170
  AddInstTable(InstTable, "OR"     , Std_Variant + 0, DecodeANDOR);
6171
  AddInstTable(InstTable, "ANDI"   , I_Variant + 1, DecodeANDOR);
6172
  AddInstTable(InstTable, "ORI"    , I_Variant + 0, DecodeANDOR);
6173
  AddInstTable(InstTable, "EOR"    , Std_Variant, DecodeEOR);
6174
  AddInstTable(InstTable, "EORI"   , I_Variant, DecodeEOR);
6175
  AddInstTable(InstTable, "PEA"    , 0, DecodePEA);
6176
  AddInstTable(InstTable, "CLR"    , 0, DecodeCLRTST);
6177
  AddInstTable(InstTable, "TST"    , 1, DecodeCLRTST);
6178
  AddInstTable(InstTable, "JSR"    , 0, DecodeJSRJMP);
6179
  AddInstTable(InstTable, "JMP"    , 1, DecodeJSRJMP);
6180
  AddInstTable(InstTable, "TAS"    , 0, DecodeNBCDTAS);
6181
  AddInstTable(InstTable, "NBCD"   , 1, DecodeNBCDTAS);
6182
  AddInstTable(InstTable, "NEGX"   , 0, DecodeNEGNOT);
6183
  AddInstTable(InstTable, "NEG"    , 2, DecodeNEGNOT);
6184
  AddInstTable(InstTable, "NOT"    , 3, DecodeNEGNOT);
6185
  AddInstTable(InstTable, "SWAP"   , 0, DecodeSWAP);
6186
  AddInstTable(InstTable, "UNLK"   , 0, DecodeUNLK);
6187
  AddInstTable(InstTable, "EXT"    , 0, DecodeEXT);
6188
  AddInstTable(InstTable, "WDDATA" , 0, DecodeWDDATA);
6189
  AddInstTable(InstTable, "WDEBUG" , 0, DecodeWDEBUG);
6190
  AddInstTable(InstTable, "MOVEM"  , 0, DecodeMOVEM);
6191
  AddInstTable(InstTable, "MOVEQ"  , 0, DecodeMOVEQ);
6192
  AddInstTable(InstTable, "STOP"   , 0, DecodeSTOP);
6193
  AddInstTable(InstTable, "LPSTOP" , 0, DecodeLPSTOP);
6194
  AddInstTable(InstTable, "TRAP"   , 0, DecodeTRAP);
6195
  AddInstTable(InstTable, "BKPT"   , 0, DecodeBKPT);
6196
  AddInstTable(InstTable, "RTD"    , 0, DecodeRTD);
6197
  AddInstTable(InstTable, "EXG"    , 0, DecodeEXG);
6198
  AddInstTable(InstTable, "MOVE16" , 0, DecodeMOVE16);
6199
  AddInstTable(InstTable, "MULU"   , 0x0000, DecodeMUL_DIV);
6200
  AddInstTable(InstTable, "MULS"   , 0x0100, DecodeMUL_DIV);
6201
  AddInstTable(InstTable, "DIVU"   , 0x0001, DecodeMUL_DIV);
6202
  AddInstTable(InstTable, "DIVS"   , 0x0101, DecodeMUL_DIV);
6203
  AddInstTable(InstTable, "DIVUL"  , 0, DecodeDIVL);
6204
  AddInstTable(InstTable, "DIVSL"  , 1, DecodeDIVL);
6205
  AddInstTable(InstTable, "ABCD"   , 1, DecodeASBCD);
6206
  AddInstTable(InstTable, "SBCD"   , 0, DecodeASBCD);
6207
  AddInstTable(InstTable, "CHK"    , 0, DecodeCHK);
6208
  AddInstTable(InstTable, "LINK"   , 0, DecodeLINK);
6209
  AddInstTable(InstTable, "MOVEP"  , 0, DecodeMOVEP);
6210
  AddInstTable(InstTable, "MOVEC"  , 0, DecodeMOVEC);
6211
  AddInstTable(InstTable, "MOVES"  , 0, DecodeMOVES);
6212
  AddInstTable(InstTable, "CALLM"  , 0, DecodeCALLM);
6213
  AddInstTable(InstTable, "CAS"    , 0, DecodeCAS);
6214
  AddInstTable(InstTable, "CAS2"   , 0, DecodeCAS2);
6215
  AddInstTable(InstTable, "CMP2"   , 0, DecodeCMPCHK2);
6216
  AddInstTable(InstTable, "CHK2"   , 1, DecodeCMPCHK2);
6217
  AddInstTable(InstTable, "EXTB"   , 0, DecodeEXTB);
6218
  AddInstTable(InstTable, "PACK"   , 0, DecodePACK);
6219
  AddInstTable(InstTable, "UNPK"   , 1, DecodePACK);
6220
  AddInstTable(InstTable, "RTM"    , 0, DecodeRTM);
6221
  AddInstTable(InstTable, "TBLU"   , 0, DecodeTBL);
6222
  AddInstTable(InstTable, "TBLUN"  , 1, DecodeTBL);
6223
  AddInstTable(InstTable, "TBLS"   , 2, DecodeTBL);
6224
  AddInstTable(InstTable, "TBLSN"  , 3, DecodeTBL);
6225
  AddInstTable(InstTable, "BTST"   , 0, DecodeBits);
6226
  AddInstTable(InstTable, "BSET"   , 3, DecodeBits);
6227
  AddInstTable(InstTable, "BCLR"   , 2, DecodeBits);
6228
  AddInstTable(InstTable, "BCHG"   , 1, DecodeBits);
6229
  AddInstTable(InstTable, "BFTST"  , 0, DecodeFBits);
6230
  AddInstTable(InstTable, "BFSET"  , 3, DecodeFBits);
6231
  AddInstTable(InstTable, "BFCLR"  , 2, DecodeFBits);
6232
  AddInstTable(InstTable, "BFCHG"  , 1, DecodeFBits);
6233
  AddInstTable(InstTable, "BFEXTU" , 0, DecodeEBits);
6234
  AddInstTable(InstTable, "BFEXTS" , 1, DecodeEBits);
6235
  AddInstTable(InstTable, "BFFFO"  , 2, DecodeEBits);
6236
  AddInstTable(InstTable, "BFINS"  , 0, DecodeBFINS);
6237
  AddInstTable(InstTable, "CINVA"  , 0, DecodeCacheAll);
6238
  AddInstTable(InstTable, "CPUSHA" , 1, DecodeCacheAll);
6239
  AddInstTable(InstTable, "CINVL"  , 1, DecodeCache);
6240
  AddInstTable(InstTable, "CPUSHL" , 5, DecodeCache);
6241
  AddInstTable(InstTable, "CINVP"  , 2, DecodeCache);
6242
  AddInstTable(InstTable, "CPUSHP" , 6, DecodeCache);
6243
  AddInstTable(InstTable, "STR"    , 0, DecodeSTR);
6244
 
6245
  InstrZ = 0;
6246
  AddFixed("NOP"    , 0x4e71, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
6247
  AddFixed("RESET"  , 0x4e70, True,  (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
6248
  AddFixed("ILLEGAL", 0x4afc, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
6249
  AddFixed("TRAPV"  , 0x4e76, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
6250
  AddFixed("RTE"    , 0x4e73, True , (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
6251
  AddFixed("RTR"    , 0x4e77, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32));
6252
  AddFixed("RTS"    , 0x4e75, False, (1 << e68KGen1a) | (1 << e68KGen1b) | (1 << e68KGen2) | (1 << e68KGen3) | (1 << eCPU32) | (1 << eColdfire));
6253
  AddFixed("BGND"   , 0x4afa, False, (1 << eCPU32));
6254
  AddFixed("HALT"   , 0x4ac8, True , (1 << eColdfire));
6255
  AddFixed("PULSE"  , 0x4acc, True , (1 << eColdfire));
6256
 
6257
  AddCond("T" , 0);  AddCond("F" , 1);  AddCond("HI", 2);  AddCond("LS", 3);
6258
  AddCond("CC", 4);  AddCond("CS", 5);  AddCond("NE", 6);  AddCond("EQ", 7);
6259
  AddCond("VC", 8);  AddCond("VS", 9);  AddCond("PL",10);  AddCond("MI",11);
6260
  AddCond("GE",12);  AddCond("LT",13);  AddCond("GT",14);  AddCond("LE",15);
6261
  AddCond("HS", 4);  AddCond("LO", 5);
6262
  AddInstTable(InstTable, "BRA", 0, DecodeBcc);
6263
  AddInstTable(InstTable, "BSR", 1, DecodeBcc);
6264
  AddInstTable(InstTable, "DBRA", 1, DecodeDBcc);
6265
 
6266
  InstrZ = 0;
6267
  AddFPUOp("FINT"   , 0x01, False, eFlagNone  );  AddFPUOp("FSINH"  , 0x02, False, eFlagExtFPU);
6268
  AddFPUOp("FINTRZ" , 0x03, False, eFlagNone  );  AddFPUOp("FSQRT"  , 0x04, False, eFlagNone  );
6269
  AddFPUOp("FSSQRT" , 0x41, False, eFlagIntFPU);  AddFPUOp("FDSQRT" , 0x45, False, eFlagIntFPU);
6270
  AddFPUOp("FLOGNP1", 0x06, False, eFlagExtFPU);  AddFPUOp("FETOXM1", 0x08, False, eFlagExtFPU);
6271
  AddFPUOp("FTANH"  , 0x09, False, eFlagExtFPU);  AddFPUOp("FATAN"  , 0x0a, False, eFlagExtFPU);
6272
  AddFPUOp("FASIN"  , 0x0c, False, eFlagExtFPU);  AddFPUOp("FATANH" , 0x0d, False, eFlagExtFPU);
6273
  AddFPUOp("FSIN"   , 0x0e, False, eFlagExtFPU);  AddFPUOp("FTAN"   , 0x0f, False, eFlagExtFPU);
6274
  AddFPUOp("FETOX"  , 0x10, False, eFlagExtFPU);  AddFPUOp("FTWOTOX", 0x11, False, eFlagExtFPU);
6275
  AddFPUOp("FTENTOX", 0x12, False, eFlagExtFPU);  AddFPUOp("FLOGN"  , 0x14, False, eFlagExtFPU);
6276
  AddFPUOp("FLOG10" , 0x15, False, eFlagExtFPU);  AddFPUOp("FLOG2"  , 0x16, False, eFlagExtFPU);
6277
  AddFPUOp("FABS"   , 0x18, False, eFlagNone  );  AddFPUOp("FSABS"  , 0x58, False, eFlagIntFPU);
6278
  AddFPUOp("FDABS"  , 0x5c, False, eFlagIntFPU);  AddFPUOp("FCOSH"  , 0x19, False, eFlagExtFPU);
6279
  AddFPUOp("FNEG"   , 0x1a, False, eFlagNone  );  AddFPUOp("FACOS"  , 0x1c, False, eFlagExtFPU);
6280
  AddFPUOp("FCOS"   , 0x1d, False, eFlagExtFPU);  AddFPUOp("FGETEXP", 0x1e, False, eFlagExtFPU);
6281
  AddFPUOp("FGETMAN", 0x1f, False, eFlagExtFPU);  AddFPUOp("FDIV"   , 0x20, True , eFlagNone  );
6282
  AddFPUOp("FSDIV"  , 0x60, False, eFlagIntFPU);  AddFPUOp("FDDIV"  , 0x64, True , eFlagIntFPU);
6283
  AddFPUOp("FMOD"   , 0x21, True , eFlagExtFPU);  AddFPUOp("FADD"   , 0x22, True , eFlagNone  );
6284
  AddFPUOp("FSADD"  , 0x62, True , eFlagIntFPU);  AddFPUOp("FDADD"  , 0x66, True , eFlagIntFPU);
6285
  AddFPUOp("FMUL"   , 0x23, True , eFlagNone  );  AddFPUOp("FSMUL"  , 0x63, True , eFlagIntFPU);
6286
  AddFPUOp("FDMUL"  , 0x67, True , eFlagIntFPU);  AddFPUOp("FSGLDIV", 0x24, True , eFlagExtFPU);
6287
  AddFPUOp("FREM"   , 0x25, True , eFlagExtFPU);  AddFPUOp("FSCALE" , 0x26, True , eFlagExtFPU);
6288
  AddFPUOp("FSGLMUL", 0x27, True , eFlagExtFPU);  AddFPUOp("FSUB"   , 0x28, True , eFlagNone  );
6289
  AddFPUOp("FSSUB"  , 0x68, True , eFlagIntFPU);  AddFPUOp("FDSUB"  , 0x6c, True , eFlagIntFPU);
6290
  AddFPUOp("FCMP"   , 0x38, True , eFlagNone   );
6291
 
6292
  AddInstTable(InstTable, "FSAVE", 0, DecodeFSAVE);
6293
  AddInstTable(InstTable, "FRESTORE", 0, DecodeFRESTORE);
6294
  AddInstTable(InstTable, "FNOP", 0, DecodeFNOP);
6295
  AddInstTable(InstTable, "FMOVE", 0, DecodeFMOVE);
6296
  AddInstTable(InstTable, "FMOVECR", 0, DecodeFMOVECR);
6297
  AddInstTable(InstTable, "FTST", 0, DecodeFTST);
6298
  AddInstTable(InstTable, "FSINCOS", 0, DecodeFSINCOS);
6299
  AddInstTable(InstTable, "FDMOVE", 0x0044, DecodeFDMOVE_FSMOVE);
6300
  AddInstTable(InstTable, "FSMOVE", 0x0040, DecodeFDMOVE_FSMOVE);
6301
  AddInstTable(InstTable, "FMOVEM", 0, DecodeFMOVEM);
6302
 
6303
  AddFPUCond("EQ"  , 0x01); AddFPUCond("NE"  , 0x0e);
6304
  AddFPUCond("GT"  , 0x12); AddFPUCond("NGT" , 0x1d);
6305
  AddFPUCond("GE"  , 0x13); AddFPUCond("NGE" , 0x1c);
6306
  AddFPUCond("LT"  , 0x14); AddFPUCond("NLT" , 0x1b);
6307
  AddFPUCond("LE"  , 0x15); AddFPUCond("NLE" , 0x1a);
6308
  AddFPUCond("GL"  , 0x16); AddFPUCond("NGL" , 0x19);
6309
  AddFPUCond("GLE" , 0x17); AddFPUCond("NGLE", 0x18);
6310
  AddFPUCond("OGT" , 0x02); AddFPUCond("ULE" , 0x0d);
6311
  AddFPUCond("OGE" , 0x03); AddFPUCond("ULT" , 0x0c);
6312
  AddFPUCond("OLT" , 0x04); AddFPUCond("UGE" , 0x0b);
6313
  AddFPUCond("OLE" , 0x05); AddFPUCond("UGT" , 0x0a);
6314
  AddFPUCond("OGL" , 0x06); AddFPUCond("UEQ" , 0x09);
6315
  AddFPUCond("OR"  , 0x07); AddFPUCond("UN"  , 0x08);
6316
  AddFPUCond("F"   , 0x00); AddFPUCond("T"   , 0x0f);
6317
  AddFPUCond("SF"  , 0x10); AddFPUCond("ST"  , 0x1f);
6318
  AddFPUCond("SEQ" , 0x11); AddFPUCond("SNE" , 0x1e);
6319
 
6320
  AddPMMUCond("BS"); AddPMMUCond("BC"); AddPMMUCond("LS"); AddPMMUCond("LC");
6321
  AddPMMUCond("SS"); AddPMMUCond("SC"); AddPMMUCond("AS"); AddPMMUCond("AC");
6322
  AddPMMUCond("WS"); AddPMMUCond("WC"); AddPMMUCond("IS"); AddPMMUCond("IC");
6323
  AddPMMUCond("GS"); AddPMMUCond("GC"); AddPMMUCond("CS"); AddPMMUCond("CC");
6324
 
6325
  AddInstTable(InstTable, "PSAVE", 0, DecodePSAVE);
6326
  AddInstTable(InstTable, "PRESTORE", 0, DecodePRESTORE);
6327
  AddInstTable(InstTable, "PFLUSHA", 0, DecodePFLUSHA);
6328
  AddInstTable(InstTable, "PFLUSHAN", 0, DecodePFLUSHAN);
6329
  AddInstTable(InstTable, "PFLUSH", 0x0000, DecodePFLUSH_PFLUSHS);
6330
  AddInstTable(InstTable, "PFLUSHS", 0x0400, DecodePFLUSH_PFLUSHS);
6331
  AddInstTable(InstTable, "PFLUSHN", 0, DecodePFLUSHN);
6332
  AddInstTable(InstTable, "PFLUSHR", 0, DecodePFLUSHR);
6333
  AddInstTable(InstTable, "PLOADR", 0x2200, DecodePLOADR_PLOADW);
6334
  AddInstTable(InstTable, "PLOADW", 0x2000, DecodePLOADR_PLOADW);
6335
  AddInstTable(InstTable, "PMOVE", 0x0000, DecodePMOVE_PMOVEFD);
6336
  AddInstTable(InstTable, "PMOVEFD", 0x0100, DecodePMOVE_PMOVEFD);
6337
  AddInstTable(InstTable, "PTESTR", 1, DecodePTESTR_PTESTW);
6338
  AddInstTable(InstTable, "PTESTW", 0, DecodePTESTR_PTESTW);
6339
  AddInstTable(InstTable, "PVALID", 0, DecodePVALID);
6340
 
6341
  AddInstTable(InstTable, "BITREV", 0x00c0, DecodeColdBit);
6342
  AddInstTable(InstTable, "BYTEREV", 0x02c0, DecodeColdBit);
6343
  AddInstTable(InstTable, "FF1", 0x04c0, DecodeColdBit);
6344
  AddInstTable(InstTable, "STLDSR", 0x0000, DecodeSTLDSR);
6345
  AddInstTable(InstTable, "INTOUCH", 0x0000, DecodeINTOUCH);
6346
  AddInstTable(InstTable, "MOV3Q", 0x0000, DecodeMOV3Q);
6347
  /* MOVEI? */
6348
  AddInstTable(InstTable, "MVS", 0x7100, DecodeMVS_MVZ);
6349
  AddInstTable(InstTable, "MVZ", 0x7180, DecodeMVS_MVZ);
6350
  AddInstTable(InstTable, "SATS", 0x0000, DecodeSATS);
6351
  AddInstTable(InstTable, "MAC" , 0x0000, DecodeMAC_MSAC);
6352
  AddInstTable(InstTable, "MSAC", 0x0100, DecodeMAC_MSAC);
6353
  AddInstTable(InstTable, "MACL" , 0x8000, DecodeMAC_MSAC);
6354
  AddInstTable(InstTable, "MSACL", 0x8100, DecodeMAC_MSAC);
6355
  AddInstTable(InstTable, "MOVCLR" , 0x0000, DecodeMOVCLR);
6356
  AddInstTable(InstTable, "MAAAC" , 0x0001, DecodeMxxAC);
6357
  AddInstTable(InstTable, "MASAC" , 0x0003, DecodeMxxAC);
6358
  AddInstTable(InstTable, "MSAAC" , 0x0101, DecodeMxxAC);
6359
  AddInstTable(InstTable, "MSSAC" , 0x0103, DecodeMxxAC);
6360
 
6361
  AddInstTable(InstTable, "CP0BCBUSY", 0xfcc0, DecodeCPBCBUSY);
6362
  AddInstTable(InstTable, "CP1BCBUSY", 0xfec0, DecodeCPBCBUSY);
6363
  AddInstTable(InstTable, "CP0LD", 0xfc00, DecodeCPLDST);
6364
  AddInstTable(InstTable, "CP1LD", 0xfe00, DecodeCPLDST);
6365
  AddInstTable(InstTable, "CP0ST", 0xfd00, DecodeCPLDST);
6366
  AddInstTable(InstTable, "CP1ST", 0xff00, DecodeCPLDST);
6367
  AddInstTable(InstTable, "CP0NOP", 0xfc00, DecodeCPNOP);
6368
  AddInstTable(InstTable, "CP1NOP", 0xfe00, DecodeCPNOP);
6369
 
6370
  InstrZ = 0;
6371
  AddPMMUReg("TC"   , eSymbolSize32Bit, 16); AddPMMUReg("DRP"  , eSymbolSize64Bit, 17);
6372
  AddPMMUReg("SRP"  , eSymbolSize64Bit, 18); AddPMMUReg("CRP"  , eSymbolSize64Bit, 19);
6373
  AddPMMUReg("CAL"  , eSymbolSize8Bit, 20);  AddPMMUReg("VAL"  , eSymbolSize8Bit, 21);
6374
  AddPMMUReg("SCC"  , eSymbolSize8Bit, 22);  AddPMMUReg("AC"   , eSymbolSize16Bit, 23);
6375
  AddPMMUReg("PSR"  , eSymbolSize16Bit, 24); AddPMMUReg("PCSR" , eSymbolSize16Bit, 25);
6376
  AddPMMUReg("TT0"  , eSymbolSize32Bit,  2); AddPMMUReg("TT1"  , eSymbolSize32Bit,  3);
6377
  AddPMMUReg("MMUSR", eSymbolSize16Bit, 24); AddPMMUReg(NULL   , eSymbolSizeUnknown, 0);
6378
 
6379
  inst_table_set_prefix_proc(InstTable, NULL, 0);
6380
 
6381
  AddInstTable(InstTable, "REG", 0, CodeREG);
6382
  AddMoto16Pseudo(InstTable, e_moto_pseudo_flags_be);
6383
}
6384
 
6385
static void DeinitFields(void)
6386
{
6387
  DestroyInstTable(InstTable);
6388
  order_array_free(FixedOrders);
6389
  order_array_free(FPUOps);
6390
  order_array_free(PMMURegs);
6391
}
6392
 
6393
/*-------------------------------------------------------------------------*/
6394
 
6395
/*!------------------------------------------------------------------------
6396
 * \fn     InternSymbol_68K(char *pArg, TempResult *pResult)
6397
 * \brief  handle built-in (register) symbols for 68K
6398
 * \param  pArg source argument
6399
 * \param  pResult result buffer
6400
 * ------------------------------------------------------------------------ */
6401
 
6402
static void InternSymbol_68K(char *pArg, TempResult *pResult)
6403
{
6404
  Word RegNum;
6405
 
6406
  if (DecodeRegCore(pArg, &RegNum))
6407
  {
6408
    pResult->Typ = TempReg;
6409
    pResult->DataSize = eSymbolSize32Bit;
6410
    pResult->Contents.RegDescr.Reg = RegNum;
6411
    pResult->Contents.RegDescr.Dissect = DissectReg_68K;
6412
    pResult->Contents.RegDescr.compare = compare_reg_68k;
6413
  }
6414
  else if (DecodeFPRegCore(pArg, &RegNum))
6415
  {
6416
    pResult->Typ = TempReg;
6417
    pResult->DataSize = NativeFloatSize;
6418
    pResult->Contents.RegDescr.Reg = RegNum;
6419
    pResult->Contents.RegDescr.Dissect = DissectReg_68K;
6420
    pResult->Contents.RegDescr.compare = compare_reg_68k;
6421
  }
6422
}
6423
 
6424
static Boolean DecodeAttrPart_68K(void)
6425
{
6426
  return DecodeMoto16AttrSize(*AttrPart.str.p_str, &AttrPartOpSize[0], False);
6427
}
6428
 
6429
static void MakeCode_68K(void)
6430
{
6431
  if (AttrPartOpSize[0] == eSymbolSizeUnknown)
6432
    AttrPartOpSize[0] = ((pCurrCPUProps->Family == eColdfire) ? eSymbolSize32Bit : eSymbolSize16Bit);
6433
  OpSize = AttrPartOpSize[0];
6434
  RelPos = 2;
6435
 
6436
  /* Nullanweisung */
6437
 
6438
  if ((*OpPart.str.p_str == '\0') && !*AttrPart.str.p_str && (ArgCnt == 0))
6439
    return;
6440
 
6441
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
6442
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
6443
}
6444
 
6445
static Boolean IsDef_68K(void)
6446
{
6447
  return Memo("REG");
6448
}
6449
 
6450
static void SwitchTo_68K(void *pUser)
6451
{
6452
  TurnWords = True;
6453
  SetIntConstMode(eIntConstModeMoto);
6454
 
6455
  PCSymbol = "*";
6456
  HeaderID = 0x01;
6457
  NOPCode = 0x4e71;
6458
  DivideChars = ",";
6459
  HasAttrs = True;
6460
  AttrChars = ".";
6461
 
6462
  ValidSegs = (1 << SegCode);
6463
  Grans[SegCode] = 1;
6464
  ListGrans[SegCode] = 2;
6465
  SegInits[SegCode] = 0;
6466
  SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
6467
 
6468
  pCurrCPUProps = (const tCPUProps*)pUser;
6469
 
6470
  DecodeAttrPart = DecodeAttrPart_68K;
6471
  MakeCode = MakeCode_68K;
6472
  IsDef = IsDef_68K;
6473
  DissectReg = DissectReg_68K;
6474
  InternSymbol = InternSymbol_68K;
6475
 
6476
  SwitchFrom = DeinitFields;
6477
  InitFields();
6478
  onoff_fpu_add();
6479
  onoff_pmmu_add();
6480
  onoff_supmode_add();
6481
  if (onoff_test_and_set(e_onoff_reg_fullpmmu))
6482
    SetFlag(&FullPMMU, FullPMMUName, True);
6483
  AddONOFF(FullPMMUName, &FullPMMU  , FullPMMUName  , False);
6484
  AddMoto16PseudoONOFF(True);
6485
 
6486
  SetFlag(&FullPMMU, FullPMMUName, !(pCurrCPUProps->SuppFlags & eFlagIntPMMU));
6487
  NativeFloatSize = (pCurrCPUProps->Family == eColdfire) ? eSymbolSizeFloat64Bit : eSymbolSizeFloat96Bit;
6488
}
6489
 
6490
static const tCtReg CtRegs_40[] =
6491
{
6492
  { "TC"   , 0x003 },
6493
  { "ITT0" , 0x004 },
6494
  { "ITT1" , 0x005 },
6495
  { "DTT0" , 0x006 },
6496
  { "DTT1" , 0x007 },
6497
  { "MMUSR", 0x805 },
6498
  { "URP"  , 0x806 },
6499
  { "SRP"  , 0x807 },
6500
  { "IACR0", 0x004 },
6501
  { "IACR1", 0x005 },
6502
  { "DACR0", 0x006 },
6503
  { "DACR1", 0x007 },
6504
  { NULL   , 0x000 },
6505
},
6506
CtRegs_2030[] =
6507
{
6508
  { "CAAR" , 0x802 },
6509
  { NULL   , 0x000 },
6510
},
6511
CtRegs_2040[] =
6512
{
6513
  { "CACR" , 0x002 },
6514
  { "MSP"  , 0x803 },
6515
  { "ISP"  , 0x804 },
6516
  { NULL   , 0x000 },
6517
},
6518
CtRegs_1040[] =
6519
{
6520
  { "SFC"  , 0x000 },
6521
  { "DFC"  , 0x001 },
6522
  { "USP"  , 0x800 },
6523
  { "VBR"  , 0x801 },
6524
  { NULL   , 0x000 },
6525
};
6526
 
6527
static const tCtReg CtRegs_5202[] =
6528
{
6529
  { "CACR"   , 0x002 },
6530
  { "ACR0"   , 0x004 },
6531
  { "ACR1"   , 0x005 },
6532
  { "VBR"    , 0x801 },
6533
  { "SR"     , 0x80e },
6534
  { "PC"     , 0x80f },
6535
  { NULL     , 0x000 },
6536
};
6537
 
6538
static const tCtReg CtRegs_5202_5204[] =
6539
{
6540
  { "RAMBAR" , 0xc04 },
6541
  { "MBAR"   , 0xc0f },
6542
  { NULL     , 0x000 },
6543
};
6544
 
6545
static const tCtReg CtRegs_5202_5208[] =
6546
{
6547
  { "RGPIOBAR", 0x009},
6548
  { "RAMBAR" , 0xc05 },
6549
  { NULL     , 0x000 },
6550
};
6551
 
6552
static const tCtReg CtRegs_5202_5307[] =
6553
{
6554
  { "ACR2"   , 0x006 },
6555
  { "ACR3"   , 0x007 },
6556
  { "RAMBAR0", 0xc04 },
6557
  { "RAMBAR1", 0xc05 },
6558
  { NULL     , 0x000 },
6559
};
6560
 
6561
static const tCtReg CtRegs_5202_5329[] =
6562
{
6563
  { "RAMBAR" , 0xc05 },
6564
  { NULL     , 0x000 },
6565
};
6566
 
6567
static const tCtReg CtRegs_5202_5407[] =
6568
{
6569
  { "ACR2"   , 0x006 },
6570
  { "ACR3"   , 0x007 },
6571
  { "RAMBAR0", 0xc04 },
6572
  { "RAMBAR1", 0xc05 },
6573
  { "MBAR"   , 0xc0f },
6574
  { NULL     , 0x000 },
6575
};
6576
 
6577
static const tCtReg CtRegs_Cf_CPU[] =
6578
{
6579
  { "D0_LOAD"  , 0x080 },
6580
  { "D1_LOAD"  , 0x081 },
6581
  { "D2_LOAD"  , 0x082 },
6582
  { "D3_LOAD"  , 0x083 },
6583
  { "D4_LOAD"  , 0x084 },
6584
  { "D5_LOAD"  , 0x085 },
6585
  { "D6_LOAD"  , 0x086 },
6586
  { "D7_LOAD"  , 0x087 },
6587
  { "A0_LOAD"  , 0x088 },
6588
  { "A1_LOAD"  , 0x089 },
6589
  { "A2_LOAD"  , 0x08a },
6590
  { "A3_LOAD"  , 0x08b },
6591
  { "A4_LOAD"  , 0x08c },
6592
  { "A5_LOAD"  , 0x08d },
6593
  { "A6_LOAD"  , 0x08e },
6594
  { "A7_LOAD"  , 0x08f },
6595
  { "D0_STORE" , 0x180 },
6596
  { "D1_STORE" , 0x181 },
6597
  { "D2_STORE" , 0x182 },
6598
  { "D3_STORE" , 0x183 },
6599
  { "D4_STORE" , 0x184 },
6600
  { "D5_STORE" , 0x185 },
6601
  { "D6_STORE" , 0x186 },
6602
  { "D7_STORE" , 0x187 },
6603
  { "A0_STORE" , 0x188 },
6604
  { "A1_STORE" , 0x189 },
6605
  { "A2_STORE" , 0x18a },
6606
  { "A3_STORE" , 0x18b },
6607
  { "A4_STORE" , 0x18c },
6608
  { "A5_STORE" , 0x18d },
6609
  { "A6_STORE" , 0x18e },
6610
  { "A7_STORE" , 0x18f },
6611
  { "OTHER_A7" , 0x800 },
6612
  { NULL       , 0x000 },
6613
};
6614
 
6615
static const tCtReg CtRegs_Cf_EMAC[] =
6616
{
6617
  { "MACSR"    , 0x804 },
6618
  { "MASK"     , 0x805 },
6619
  { "ACC0"     , 0x806 },
6620
  { "ACCEXT01" , 0x807 },
6621
  { "ACCEXT23" , 0x808 },
6622
  { "ACC1"     , 0x809 },
6623
  { "ACC2"     , 0x80a },
6624
  { "ACC3"     , 0x80b },
6625
  { NULL       , 0x000 },
6626
};
6627
 
6628
static const tCtReg CtRegs_MCF51[] =
6629
{
6630
  { "VBR"      , 0x801 },
6631
  { "CPUCR"    , 0x802 },
6632
  { NULL       , 0x000 },
6633
};
6634
 
6635
static const tCPUProps CPUProps[] =
6636
{
6637
  /* 68881/68882 may be attached memory-mapped and emulated on pre-68020 devices */
6638
  { "68008",    0x000ffffful, e68KGen1a, eCfISA_None  , eFlagExtFPU | eFlagLogCCR, { NULL } },
6639
  { "68000",    0x00fffffful, e68KGen1a, eCfISA_None  , eFlagExtFPU | eFlagLogCCR, { NULL } },
6640
  { "68010",    0x00fffffful, e68KGen1b, eCfISA_None  , eFlagExtFPU | eFlagLogCCR, { CtRegs_1040 } },
6641
  { "68012",    0x7ffffffful, e68KGen1b, eCfISA_None  , eFlagExtFPU | eFlagLogCCR, { CtRegs_1040 } },
6642
  { "MCF5202",  0xfffffffful, eColdfire, eCfISA_A     , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202 } },
6643
  { "MCF5204",  0xfffffffful, eColdfire, eCfISA_A     , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202, CtRegs_5202_5204 } },
6644
  { "MCF5206",  0xfffffffful, eColdfire, eCfISA_A     , eFlagIntFPU | eFlagIdxScaling, { CtRegs_5202, CtRegs_5202_5204 } },
6645
  { "MCF5208",  0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
6646
  { "MCF52274", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
6647
  { "MCF52277", 0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5208, CtRegs_Cf_CPU, CtRegs_Cf_EMAC } }, /* V2 */
6648
  { "MCF5307",  0xfffffffful, eColdfire, eCfISA_A     , eFlagIntFPU | eFlagIdxScaling | eFlagMAC, { CtRegs_5202, CtRegs_5202_5307 } }, /* V3 */
6649
  { "MCF5329",  0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5329 } }, /* V3 */
6650
  { "MCF5373",  0xfffffffful, eColdfire, eCfISA_APlus , eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5329 } }, /* V3 */
6651
  { "MCF5407",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4 */
6652
  { "MCF5470",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6653
  { "MCF5471",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6654
  { "MCF5472",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6655
  { "MCF5473",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6656
  { "MCF5474",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6657
  { "MCF5475",  0xfffffffful, eColdfire, eCfISA_B     , eFlagBranch32 | eFlagIntFPU | eFlagIdxScaling | eFlagMAC | eFlagEMAC, { CtRegs_5202, CtRegs_5202_5407 } }, /* V4e */
6658
  { "MCF51QM",  0xfffffffful, eColdfire, eCfISA_C     , eFlagBranch32 | eFlagMAC | eFlagIdxScaling | eFlagEMAC, { CtRegs_MCF51 } }, /* V1 */
6659
  { "68332",    0xfffffffful, eCPU32   , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
6660
  { "68340",    0xfffffffful, eCPU32   , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
6661
  { "68360",    0xfffffffful, eCPU32   , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling, { CtRegs_1040 } },
6662
  { "68020",    0xfffffffful, e68KGen2 , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagExtFPU | eFlagCALLM_RTM, { CtRegs_1040, CtRegs_2040, CtRegs_2030 } },
6663
  { "68030",    0xfffffffful, e68KGen2 , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagExtFPU | eFlagIntPMMU, { CtRegs_1040, CtRegs_2040, CtRegs_2030 } },
6664
  /* setting eFlagExtFPU assumes instructions of external FPU are emulated/provided by M68040FPSP! */
6665
  { "68040",    0xfffffffful, e68KGen3 , eCfISA_None  , eFlagBranch32 | eFlagLogCCR | eFlagIdxScaling | eFlagIntPMMU | eFlagExtFPU | eFlagIntFPU, { CtRegs_1040, CtRegs_2040, CtRegs_40 } },
6666
  { NULL   ,    0           , e68KGen1a, eCfISA_None  , eFlagNone, { NULL } },
6667
};
6668
 
6669
void code68k_init(void)
6670
{
6671
  const tCPUProps *pProp;
6672
  for (pProp = CPUProps; pProp->pName; pProp++)
6673
    (void)AddCPUUser(pProp->pName, SwitchTo_68K, (void*)pProp, NULL);
6674
}