Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* code86.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* Codegenerator 8086/V-Serie                                                */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
#include <string.h>
13
 
14
#include "bpemu.h"
15
#include "strutil.h"
16
#include "errmsg.h"
17
#include "asmdef.h"
18
#include "asmsub.h"
19
#include "asmpars.h"
20
#include "asmallg.h"
21
#include "onoff_common.h"
22
#include "codepseudo.h"
23
#include "intpseudo.h"
24
#include "asmitree.h"
25
#include "asmcode.h"
26
#include "symbolsize.h"
27
#include "codevars.h"
28
#include "nlmessages.h"
29
#include "as.rsc"
30
#include "code86.h"
31
 
32
/*---------------------------------------------------------------------------*/
33
 
34
typedef struct
35
{
36
  const char *Name;
37
  Byte core_mask;
38
  Word Code;
39
} FixedOrder;
40
 
41
typedef struct
42
{
43
  const char *Name;
44
  Byte core_mask;
45
  Word Code;
46
  Boolean no_seg_check;
47
} ModRegOrder;
48
 
49
typedef struct
50
{
51
  CPUVar MinCPU;
52
  Word Code;
53
  Byte Add;
54
} AddOrder;
55
 
56
#define NO_FWAIT_FLAG 0x2000
57
 
58
static char ArgSTStr[] = "ST";
59
static const tStrComp ArgST = { { 0, 0 }, { 0, ArgSTStr, 0 } };
60
 
61
typedef enum
62
{
63
  TypeNone = -1,
64
  TypeReg8 = 0,
65
  TypeReg16 = 1,
66
  TypeRegSeg = 2,
67
  TypeMem = 3,
68
  TypeImm = 4,
69
  TypeFReg = 5
70
} tAdrType;
71
 
72
#define MTypeReg8 (1 << TypeReg8)
73
#define MTypeReg16 (1 << TypeReg16)
74
#define MTypeRegSeg (1 << TypeRegSeg)
75
#define MTypeMem (1 << TypeMem)
76
#define MTypeImm (1 << TypeImm)
77
#define MTypeFReg (1 << TypeFReg)
78
 
79
static tAdrType AdrType;
80
static Byte AdrMode;
81
static Byte AdrVals[6];
82
static tSymbolSize OpSize;
83
static Boolean UnknownFlag;
84
static unsigned ImmAddrSpaceMask;
85
 
86
static Boolean NoSegCheck;
87
 
88
static Byte Prefixes[6];
89
static Byte PrefixLen;
90
 
91
enum
92
{
93
  e_core_86    = 1 << 0, /* 8086/8088 */
94
  e_core_186   = 1 << 1, /* 80186/80188 */
95
  e_core_v30   = 1 << 2, /* V20/30/40/50 */
96
  e_core_v33   = 1 << 3, /* V33/V53 */
97
  e_core_v35   = 1 << 4, /* V25/V35 */
98
  e_core_v55   = 1 << 5, /* V55 */
99
  e_core_v55pi = 1 << 6, /* V55PI */
100
  e_core_v55sc = 1 << 7, /* V55SC */
101
 
102
  e_core_all_v55 = e_core_v55 | e_core_v55pi | e_core_v55sc,
103
  e_core_all_v35 = e_core_v35 | e_core_all_v55,
104
  e_core_all_v = e_core_v30 | e_core_v33 | e_core_all_v35,
105
  e_core_all_186 = e_core_all_v | e_core_186,
106
  e_core_all = e_core_all_186 | e_core_86
107
};
108
 
109
typedef struct
110
{
111
  const char name[6];
112
  Byte core;
113
} cpu_props_t;
114
 
115
static const cpu_props_t *p_curr_cpu_props;
116
 
117
static FixedOrder *FixedOrders, *StringOrders, *ReptOrders, *ShiftOrders,
118
                  *RelOrders, *BrkOrders, *Imm16Orders;
119
static AddOrder *Reg16Orders;
120
static ModRegOrder *ModRegOrders;
121
static unsigned StringOrderCnt;
122
 
123
/*------------------------------------------------------------------------------------*/
124
 
125
/*!------------------------------------------------------------------------
126
 * Register Symbols
127
 * ------------------------------------------------------------------------ */
128
 
129
#define SEGREG_NUMOFFSET 8
130
 
131
static const char reg8_names[][3] =
132
{
133
  "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
134
};
135
static const char reg16_names[][3] =
136
{
137
  "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
138
};
139
static const char seg_reg_names[][4] =
140
{
141
  "ES", "CS", "SS", "DS",
142
  "DS3", "DS2" /* V55 specific */
143
};
144
 
145
/*!------------------------------------------------------------------------
146
 * \fn     decode_reg8_core(const char *p_arg, Byte *p_ret)
147
 * \brief  check whether argument is an 8 bit register's name
148
 * \param  p_arg source argument
149
 * \param  p_ret returns register # if so
150
 * \return True if argument is a 8 bit register
151
 * ------------------------------------------------------------------------ */
152
 
153
static Boolean decode_reg8_core(const char *p_arg, Byte *p_ret)
154
{
155
  for (*p_ret = 0; *p_ret < as_array_size(reg8_names); (*p_ret)++)
156
    if (!as_strcasecmp(p_arg, reg8_names[*p_ret]))
157
      return True;
158
  return False;
159
}
160
 
161
/*!------------------------------------------------------------------------
162
 * \fn     decode_reg16_core(const char *p_arg, Byte *p_ret)
163
 * \brief  check whether argument is a 16 bit register's name
164
 * \param  p_arg source argument
165
 * \param  p_ret returns register # if so
166
 * \return True if argument is a 16 bit register
167
 * ------------------------------------------------------------------------ */
168
 
169
static Boolean decode_reg16_core(const char *p_arg, Byte *p_ret)
170
{
171
  for (*p_ret = 0; *p_ret < as_array_size(reg16_names); (*p_ret)++)
172
    if (!as_strcasecmp(p_arg, reg16_names[*p_ret]))
173
      return True;
174
  return False;
175
}
176
 
177
/*!------------------------------------------------------------------------
178
 * \fn     decode_seg_reg_core(const char *p_arg, Byte *p_ret)
179
 * \brief  check whether argument is a segment register's name
180
 * \param  p_arg source argument
181
 * \param  p_ret returns register # if so
182
 * \return True if argument is a segment register
183
 * ------------------------------------------------------------------------ */
184
 
185
static Boolean decode_seg_reg_core(const char *p_arg, Byte *p_ret)
186
{
187
  int reg_z, reg_cnt = as_array_size(seg_reg_names);
188
 
189
  /* DS2/DS3 only allowed on V55.  These names should be allowed as
190
     ordinary symbol names on other targets: */
191
 
192
  if (!(p_curr_cpu_props->core & e_core_all_v55))
193
    reg_cnt -= 2;
194
  for (reg_z = 0; reg_z < reg_cnt; reg_z++)
195
    if (!as_strcasecmp(p_arg, seg_reg_names[reg_z]))
196
    {
197
      *p_ret = reg_z;
198
      return True;
199
    }
200
  return False;
201
}
202
 
203
/*!------------------------------------------------------------------------
204
 * \fn     decode_reg_core(const char *p_arg, tRegInt *p_ret, tSymbolSize *p_size)
205
 * \brief  check whether argument is a register's name
206
 * \param  p_arg source argument
207
 * \param  p_ret returns register # if so
208
 * \param  p_size returns register size if so
209
 * \return True if argument is a register
210
 * ------------------------------------------------------------------------ */
211
 
212
static Boolean decode_reg_core(const char *p_arg, tRegInt *p_ret, tSymbolSize *p_size)
213
{
214
  Byte reg_num;
215
 
216
  if (decode_reg8_core(p_arg, &reg_num))
217
  {
218
    *p_ret = reg_num;
219
    *p_size = eSymbolSize8Bit;
220
    return True;
221
  }
222
  else if (decode_reg16_core(p_arg, &reg_num))
223
  {
224
    *p_ret = reg_num;
225
    *p_size = eSymbolSize16Bit;
226
    return True;
227
  }
228
  else if (decode_seg_reg_core(p_arg, &reg_num))
229
  {
230
    *p_ret = reg_num + SEGREG_NUMOFFSET;
231
    *p_size = eSymbolSize16Bit;
232
    return True;
233
  }
234
  else
235
    return False;
236
}
237
 
238
/*!------------------------------------------------------------------------
239
 * \fn     dissect_reg_86(char *p_dest, size_t dest_size, tRegInt reg_num, tSymbolSize reg_size)
240
 * \brief  dissect register symbols - x86 variant
241
 * \param  p_dest destination buffer
242
 * \param  dest_size destination buffer size
243
 * \param  reg_num numeric register value
244
 * \param  reg_size register size
245
 * ------------------------------------------------------------------------ */
246
 
247
static void dissect_reg_86(char *p_dest, size_t dest_size, tRegInt reg_num, tSymbolSize reg_size)
248
{
249
  switch (reg_size)
250
  {
251
    case eSymbolSize8Bit:
252
      if (reg_num >= as_array_size(reg8_names))
253
        goto unknown;
254
      strmaxcpy(p_dest, reg8_names[reg_num], dest_size);
255
      break;
256
    case eSymbolSize16Bit:
257
      if (reg_num < as_array_size(reg16_names))
258
        strmaxcpy(p_dest, reg16_names[reg_num], dest_size);
259
      else if (reg_num < SEGREG_NUMOFFSET + as_array_size(seg_reg_names))
260
        strmaxcpy(p_dest, seg_reg_names[reg_num - as_array_size(reg16_names)], dest_size);
261
      else
262
        goto unknown;
263
      break;
264
    default:
265
    unknown:
266
      as_snprintf(p_dest, dest_size, "%d-%u", (int)reg_size, (unsigned)reg_num);
267
  }
268
}
269
 
270
/*!------------------------------------------------------------------------
271
 * \fn     decode_reg(const tStrComp *p_arg, Byte *p_reg_num, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
272
 * \brief  check whether argument is a CPU register or user-defined register alias
273
 * \param  p_arg argument
274
 * \param  p_reg_num resulting register # if yes
275
 * \param  p_size resulting register size if yes
276
 * \param  req_size requested register size
277
 * \param  must_be_reg expecting register or maybe not?
278
 * \return reg eval result
279
 * ------------------------------------------------------------------------ */
280
 
281
static Boolean chk_reg_size(tSymbolSize req_size, tSymbolSize act_size)
282
{
283
  return (req_size == eSymbolSizeUnknown)
284
      || (req_size == act_size);
285
}
286
 
287
static tRegEvalResult decode_reg(const tStrComp *p_arg, Byte *p_reg_num, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
288
{
289
  tRegDescr reg_descr;
290
  tEvalResult eval_result;
291
  tRegEvalResult reg_eval_result;
292
 
293
  if (decode_reg_core(p_arg->str.p_str, &reg_descr.Reg, &eval_result.DataSize))
294
    reg_eval_result = eIsReg;
295
  else
296
    reg_eval_result = EvalStrRegExpressionAsOperand(p_arg, &reg_descr, &eval_result, eSymbolSizeUnknown, must_be_reg);
297
 
298
  if (reg_eval_result == eIsReg)
299
  {
300
    if (!chk_reg_size(req_size, eval_result.DataSize))
301
    {
302
      WrStrErrorPos(ErrNum_InvOpSize, p_arg);
303
      reg_eval_result = must_be_reg ? eIsNoReg : eRegAbort;
304
    }
305
  }
306
 
307
  *p_reg_num = reg_descr.Reg;
308
  if (p_size) *p_size = eval_result.DataSize;
309
  return reg_eval_result;
310
}
311
 
312
/*!------------------------------------------------------------------------
313
 * \fn     decode_seg_reg(const tStrComp *p_arg, Byte *p_reg_num)
314
 * \brief  check whether argument is a CPU segment register or user-defined register alias
315
 * \param  p_arg source argument
316
 * \param  p_reg_num resulting segment register # if yes
317
 * \return True if it is
318
 * ------------------------------------------------------------------------ */
319
 
320
static Boolean decode_seg_reg(const tStrComp *p_arg, Byte *p_reg_num)
321
{
322
  switch (decode_reg(p_arg, p_reg_num, NULL, eSymbolSize16Bit, True))
323
  {
324
    case eIsReg:
325
      if (*p_reg_num < SEGREG_NUMOFFSET)
326
        return False;
327
      *p_reg_num -= SEGREG_NUMOFFSET;
328
      return True;
329
    default:
330
      return False;
331
  }
332
}
333
 
334
/*!------------------------------------------------------------------------
335
 * Address Expression parser
336
 * ------------------------------------------------------------------------ */
337
 
338
static const Byte SegRegPrefixes[6] =
339
{
340
  0x26, 0x2e, 0x36, 0x3e,
341
  0xd6, 0x63
342
};
343
static Byte SegAssumes[6];
344
 
345
/*!------------------------------------------------------------------------
346
 * \fn     copy_adr_vals(int Dest)
347
 * \brief  copy addressing mode extension bytes
348
 * \param  Dest where to copy relative to current instruction end
349
 * ------------------------------------------------------------------------ */
350
 
351
static void copy_adr_vals(int Dest)
352
{
353
  memcpy(BAsmCode + CodeLen + Dest, AdrVals, AdrCnt);
354
}
355
 
356
/*!------------------------------------------------------------------------
357
 * \fn     append_adr_vals(void)
358
 * \brief  append addressing mode extension bytes
359
 * ------------------------------------------------------------------------ */
360
 
361
static void append_adr_vals(void)
362
{
363
  copy_adr_vals(0);
364
  CodeLen += AdrCnt;
365
}
366
 
367
/*!------------------------------------------------------------------------
368
 * \fn     Sgn(Byte inp)
369
 * \brief  get value of upper byte after sign extension
370
 * \param  inp value that will be extended
371
 * \return 0 or 0xff
372
 * ------------------------------------------------------------------------ */
373
 
374
static Byte Sgn(Byte inp)
375
{
376
  return (inp > 127) ? 0xff : 0;
377
}
378
 
379
/*!------------------------------------------------------------------------
380
 * \fn     AddPrefix(Byte Prefix)
381
 * \brief  store new prefix
382
 * \param  Prefix prefix byte to store
383
 * ------------------------------------------------------------------------ */
384
 
385
static void AddPrefix(Byte Prefix)
386
{
387
  Prefixes[PrefixLen++] = Prefix;
388
}
389
 
390
/*!------------------------------------------------------------------------
391
 * \fn     AddPrefixes(void)
392
 * \brief  prepend stored prefixes
393
 * ------------------------------------------------------------------------ */
394
 
395
static void AddPrefixes(void)
396
{
397
  if ((CodeLen != 0) && (PrefixLen != 0))
398
  {
399
    memmove(BAsmCode + PrefixLen, BAsmCode, CodeLen);
400
    memcpy(BAsmCode, Prefixes, PrefixLen);
401
    CodeLen += PrefixLen;
402
  }
403
}
404
 
405
/*!------------------------------------------------------------------------
406
 * \fn     AbleToSign(Word Arg)
407
 * \brief  can argument be written as 8-bit vlaue that will be sign extended?
408
 * \param  Arg value to check
409
 * \return True if yes
410
 * ------------------------------------------------------------------------ */
411
 
412
static Boolean AbleToSign(Word Arg)
413
{
414
  return ((Arg <= 0x7f) || (Arg >= 0xff80));
415
}
416
 
417
/*!------------------------------------------------------------------------
418
 * \fn     MinOneIs0(void)
419
 * \brief  optionally set operand size to 8 bits if not yet set
420
 * \return True if operand size was set
421
 * ------------------------------------------------------------------------ */
422
 
423
static Boolean MinOneIs0(void)
424
{
425
  if (UnknownFlag && (OpSize == eSymbolSizeUnknown))
426
  {
427
    OpSize = eSymbolSize8Bit;
428
    return True;
429
  }
430
  else
431
    return False;
432
}
433
 
434
/*!------------------------------------------------------------------------
435
 * \fn     ChkOpSize(tSymbolSize NewSize)
436
 * \brief  check, match and optionally set operand size
437
 * \param  NewSize operand size of operand
438
 * ------------------------------------------------------------------------ */
439
 
440
static void ChkOpSize(tSymbolSize NewSize)
441
{
442
  if (OpSize == eSymbolSizeUnknown)
443
    OpSize = NewSize;
444
  else if (OpSize != NewSize)
445
  {
446
    AdrType = TypeNone;
447
    WrError(ErrNum_ConfOpSizes);
448
  }
449
}
450
 
451
/*!------------------------------------------------------------------------
452
 * \fn     ChkSpaces(ShortInt SegBuffer, Byte MomSegment, const tStrComp *p_arg)
453
 * \brief  check for matching address space of memory argument
454
 * \param  SegBuffer index into segment assume table
455
 * \param  MomSegment current segment being used
456
 * \param  p_arg source argument for error reporting
457
 * ------------------------------------------------------------------------ */
458
 
459
static void ChkSingleSpace(Byte Seg, Byte EffSeg, Byte MomSegment, const tStrComp *p_arg)
460
{
461
  Byte z;
462
 
463
  /* liegt Operand im zu pruefenden Segment? nein-->vergessen */
464
 
465
  if (!(MomSegment & (1 << Seg)))
466
    return;
467
 
468
  /* zeigt bish. benutztes Segmentregister auf dieses Segment? ja-->ok */
469
 
470
  if (EffSeg == Seg)
471
    return;
472
 
473
  /* falls schon ein Override gesetzt wurde, nur warnen */
474
 
475
  if (PrefixLen > 0)
476
    WrStrErrorPos(ErrNum_WrongSegment, p_arg);
477
 
478
  /* ansonsten ein passendes Segment suchen und warnen, falls keines da */
479
 
480
  else
481
  {
482
    z = 0;
483
    while ((z < as_array_size(SegAssumes)) && (SegAssumes[z] != Seg))
484
      z++;
485
    if (z >= as_array_size(SegAssumes))
486
      WrXErrorPos(ErrNum_InAccSegment, seg_reg_names[Seg], &p_arg->Pos);
487
    else
488
      AddPrefix(SegRegPrefixes[z]);
489
  }
490
}
491
 
492
static void ChkSpaces(ShortInt SegBuffer, Byte MomSegment, const tStrComp *p_arg)
493
{
494
  Byte EffSeg;
495
 
496
  if (NoSegCheck)
497
    return;
498
 
499
  /* in welches Segment geht das benutzte Segmentregister ? */
500
 
501
  EffSeg = SegAssumes[SegBuffer];
502
 
503
  /* Zieloperand in Code-/Datensegment ? */
504
 
505
  ChkSingleSpace(SegCode, EffSeg, MomSegment, p_arg);
506
  ChkSingleSpace(SegXData, EffSeg, MomSegment, p_arg);
507
  ChkSingleSpace(SegData, EffSeg, MomSegment, p_arg);
508
}
509
 
510
/*!------------------------------------------------------------------------
511
 * \fn     DecodeAdr(const tStrComp *pArg, unsigned type_mask)
512
 * \brief  parse addressing mode argument
513
 * \param  pArg source argument
514
 * \param  type_mask bit mask of allowed addressing modes
515
 * \return resulting addressing mode
516
 * ------------------------------------------------------------------------ */
517
 
518
typedef struct
519
{
520
  as_eval_cb_data_t cb_data;
521
  ShortInt IndexBuf, BaseBuf;
522
} x86_eval_cb_data_t;
523
 
524
#define DBG_CB 0
525
 
526
DECLARE_AS_EVAL_CB(x86_eval_cb)
527
{
528
  x86_eval_cb_data_t *p_x86_eval_cb_data = (x86_eval_cb_data_t*)p_data;
529
  ShortInt *p_buf, buf_val;
530
  Byte reg_num;
531
  tSymbolSize reg_size;
532
 
533
#if DBG_CB
534
  printf("x86 eval callback: ");
535
  DumpStrComp("arg", p_arg);
536
#endif
537
 
538
  /* CPU register? */
539
 
540
  switch (decode_reg(p_arg, &reg_num, &reg_size, eSymbolSizeUnknown, False))
541
  {
542
    case eIsReg:
543
      if (reg_size != eSymbolSize16Bit)
544
      {
545
        WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
546
        return e_eval_fail;
547
      }
548
      break;
549
    case eRegAbort:
550
      return e_eval_fail;
551
    default:
552
      return e_eval_none;
553
  }
554
 
555
#if DBG_CB
556
  as_dump_eval_cb_data_stack(p_data->p_stack);
557
#endif
558
 
559
  /* Register allowed for addressing? */
560
 
561
  switch (reg_num)
562
  {
563
    case 3:
564
    case 5:
565
      p_buf = &p_x86_eval_cb_data->BaseBuf;
566
      buf_val = reg_num / 2;
567
      break;
568
    case 6:
569
    case 7:
570
      p_buf = &p_x86_eval_cb_data->IndexBuf;
571
      buf_val = reg_num - 5;
572
      break;
573
    default:
574
      WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
575
      return e_eval_fail;
576
  }
577
 
578
  /* Simple additive component in expression? */
579
 
580
  if (!as_eval_cb_data_stack_plain_add(p_data->p_stack))
581
  {
582
    WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
583
    return e_eval_fail;
584
  }
585
 
586
  /* We already have a base/index register ? */
587
 
588
  if (*p_buf)
589
  {
590
    WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
591
    return e_eval_fail;
592
  }
593
 
594
  /* Occupy slot and signal component as zero to parser */
595
 
596
  *p_buf = buf_val;
597
  as_tempres_set_int(p_res, 0);
598
  return e_eval_ok;
599
}
600
 
601
static tAdrType DecodeAdr(const tStrComp *pArg, unsigned type_mask)
602
{
603
  static const Byte RMCodes[8] =
604
  {
605
    11, 12, 21, 22, 1, 2 , 20, 10
606
  };
607
 
608
  int z;
609
  Boolean IsImm;
610
  Byte SumBuf;
611
  LongInt DispAcc, DispSum;
612
  char *pIndirStart, *pIndirEnd;
613
  ShortInt SegBuffer;
614
  Byte MomSegment;
615
  x86_eval_cb_data_t x86_eval_cb_data;
616
  tSymbolSize FoundSize;
617
  tStrComp Arg;
618
  int ArgLen = strlen(pArg->str.p_str);
619
 
620
  AdrType = TypeNone; AdrCnt = 0;
621
  SegBuffer = -1; MomSegment = 0;
622
 
623
  /* A somewhat dirty hack to avoid
624
   *
625
   * 'addr[reg]'
626
   *
627
   * being parsed as symbol with section: */
628
 
629
  if (!strchr(pArg->str.p_str, '['))
630
  {
631
    switch (decode_reg(pArg, &AdrMode, &FoundSize, eSymbolSizeUnknown, False))
632
    {
633
      case eRegAbort:
634
        return AdrType;
635
      case eIsReg:
636
        if (FoundSize == eSymbolSize8Bit)
637
          AdrType = TypeReg8;
638
        else if (AdrMode >= SEGREG_NUMOFFSET)
639
        {
640
          AdrMode -= SEGREG_NUMOFFSET;
641
          AdrType = TypeRegSeg;
642
        }
643
        else
644
          AdrType = TypeReg16;
645
        ChkOpSize(FoundSize);
646
        goto chk_type;
647
      default:
648
        break;
649
    }
650
  }
651
 
652
  if (FPUAvail)
653
  {
654
    if (!as_strcasecmp(pArg->str.p_str, "ST"))
655
    {
656
      AdrType = TypeFReg; AdrMode = 0;
657
      ChkOpSize(eSymbolSize80Bit);
658
      goto chk_type;
659
    }
660
 
661
    if ((ArgLen > 4) && (!as_strncasecmp(pArg->str.p_str, "ST(", 3)) && (pArg->str.p_str[ArgLen - 1] == ')'))
662
    {
663
      tStrComp Num;
664
      Boolean OK;
665
 
666
      StrCompRefRight(&Num, pArg, 3);
667
      StrCompShorten(&Num, 1);
668
      AdrMode = EvalStrIntExpression(&Num, UInt3, &OK);
669
      if (OK)
670
      {
671
        AdrType = TypeFReg;
672
        ChkOpSize(eSymbolSize80Bit);
673
      }
674
      goto chk_type;
675
    }
676
  }
677
 
678
  IsImm = True;
679
  as_eval_cb_data_ini(&x86_eval_cb_data.cb_data, x86_eval_cb);
680
  x86_eval_cb_data.IndexBuf =
681
  x86_eval_cb_data.BaseBuf = 0;
682
  DispAcc = 0; FoundSize = eSymbolSizeUnknown;
683
  StrCompRefRight(&Arg, pArg, 0);
684
  if (!as_strncasecmp(Arg.str.p_str, "WORD PTR", 8))
685
  {
686
    StrCompIncRefLeft(&Arg, 8);
687
    FoundSize = eSymbolSize16Bit;
688
    IsImm = False;
689
    KillPrefBlanksStrCompRef(&Arg);
690
  }
691
  else if (!as_strncasecmp(Arg.str.p_str, "BYTE PTR", 8))
692
  {
693
    StrCompIncRefLeft(&Arg, 8);
694
    FoundSize = eSymbolSize8Bit;
695
    IsImm = False;
696
    KillPrefBlanksStrCompRef(&Arg);
697
  }
698
  else if (!as_strncasecmp(Arg.str.p_str, "DWORD PTR", 9))
699
  {
700
    StrCompIncRefLeft(&Arg, 9);
701
    FoundSize = eSymbolSize32Bit;
702
    IsImm = False;
703
    KillPrefBlanksStrCompRef(&Arg);
704
  }
705
  else if (!as_strncasecmp(Arg.str.p_str, "QWORD PTR", 9))
706
  {
707
    StrCompIncRefLeft(&Arg, 9);
708
    FoundSize = eSymbolSize64Bit;
709
    IsImm = False;
710
    KillPrefBlanksStrCompRef(&Arg);
711
  }
712
  else if (!as_strncasecmp(Arg.str.p_str, "TBYTE PTR", 9))
713
  {
714
    StrCompIncRefLeft(&Arg, 9);
715
    FoundSize = eSymbolSize80Bit;
716
    IsImm = False;
717
    KillPrefBlanksStrCompRef(&Arg);
718
  }
719
 
720
  if ((strlen(Arg.str.p_str) > 2) && (Arg.str.p_str[2] == ':'))
721
  {
722
    tStrComp Remainder;
723
    Byte seg_reg;
724
 
725
    StrCompSplitRef(&Arg, &Remainder, &Arg, Arg.str.p_str + 2);
726
    if (decode_seg_reg(&Arg, &seg_reg))
727
    {
728
      SegBuffer = seg_reg;
729
      AddPrefix(SegRegPrefixes[SegBuffer]);
730
    }
731
    if (SegBuffer < 0)
732
    {
733
      WrStrErrorPos(ErrNum_UnknownSegReg, &Arg);
734
      goto chk_type;
735
    }
736
    Arg = Remainder;
737
  }
738
 
739
  do
740
  {
741
    tEvalResult EvalResult;
742
 
743
    pIndirStart = QuotPos(Arg.str.p_str, '[');
744
 
745
    /* no address expr or outer displacement: */
746
 
747
    if (!pIndirStart || (pIndirStart != Arg.str.p_str))
748
    {
749
      tStrComp Remainder;
750
 
751
      if (pIndirStart)
752
        StrCompSplitRef(&Arg, &Remainder, &Arg, pIndirStart);
753
      DispAcc += EvalStrIntExpressionWithResult(&Arg, Int16, &EvalResult);
754
      if (!EvalResult.OK)
755
         goto chk_type;
756
      UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
757
      MomSegment |= EvalResult.AddrSpaceMask;
758
      if (FoundSize == eSymbolSizeUnknown)
759
        FoundSize = EvalResult.DataSize;
760
      if (pIndirStart)
761
        Arg = Remainder;
762
      else
763
        break;
764
    }
765
    else
766
      StrCompIncRefLeft(&Arg, 1);
767
 
768
    /* Arg now points right behind [ */
769
 
770
    if (pIndirStart)
771
    {
772
      tStrComp IndirArg, OutRemainder;
773
 
774
      IsImm = False;
775
 
776
      pIndirEnd = RQuotPos(Arg.str.p_str, ']');
777
      if (!pIndirEnd)
778
      {
779
        WrStrErrorPos(ErrNum_BrackErr, &Arg);
780
        goto chk_type;
781
      }
782
 
783
      StrCompSplitRef(&IndirArg, &OutRemainder, &Arg, pIndirEnd);
784
 
785
      DispSum = EvalStrIntExprWithResultAndCallback(&IndirArg, Int16, &EvalResult, &x86_eval_cb_data.cb_data);
786
      if (!EvalResult.OK)
787
        goto chk_type;
788
      UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
789
      DispAcc += DispSum;
790
      MomSegment |= EvalResult.AddrSpaceMask;
791
      if (FoundSize == eSymbolSizeUnknown)
792
        FoundSize = EvalResult.DataSize;
793
      Arg = OutRemainder;
794
    }
795
  }
796
  while (*Arg.str.p_str);
797
 
798
  SumBuf = x86_eval_cb_data.BaseBuf * 10 + x86_eval_cb_data.IndexBuf;
799
 
800
  /* welches Segment effektiv benutzt ? */
801
 
802
  if (SegBuffer == -1)
803
    SegBuffer = (x86_eval_cb_data.BaseBuf == 2) ? 2 : 3;
804
 
805
  /* nur Displacement */
806
 
807
  if (0 == SumBuf)
808
  {
809
    /* immediate */
810
 
811
    if (IsImm)
812
    {
813
      ImmAddrSpaceMask = MomSegment;
814
      if ((UnknownFlag && (OpSize == eSymbolSize8Bit)) || (MinOneIs0()))
815
        DispAcc &= 0xff;
816
      switch (OpSize)
817
      {
818
        case eSymbolSizeUnknown:
819
          WrStrErrorPos(ErrNum_UndefOpSizes, &Arg);
820
          break;
821
        case eSymbolSize8Bit:
822
          if ((DispAcc <- 128) || (DispAcc > 255)) WrStrErrorPos(ErrNum_OverRange, &Arg);
823
          else
824
          {
825
            AdrType = TypeImm;
826
            AdrVals[0] = DispAcc & 0xff;
827
            AdrCnt = 1;
828
          }
829
          break;
830
        case eSymbolSize16Bit:
831
          AdrType = TypeImm;
832
          AdrVals[0] = Lo(DispAcc);
833
          AdrVals[1] = Hi(DispAcc);
834
          AdrCnt = 2;
835
          break;
836
        default:
837
          WrStrErrorPos(ErrNum_InvOpSize, &Arg);
838
          break;
839
      }
840
    }
841
 
842
    /* absolut */
843
 
844
    else
845
    {
846
      AdrType = TypeMem;
847
      AdrMode = 0x06;
848
      AdrVals[0] = Lo(DispAcc);
849
      AdrVals[1] = Hi(DispAcc);
850
      AdrCnt = 2;
851
      if (FoundSize != -1)
852
        ChkOpSize(FoundSize);
853
      ChkSpaces(SegBuffer, MomSegment, &Arg);
854
    }
855
  }
856
 
857
  /* kombiniert */
858
 
859
  else
860
  {
861
    AdrType = TypeMem;
862
    for (z = 0; z < 8; z++)
863
      if (SumBuf == RMCodes[z])
864
        AdrMode = z;
865
    if (DispAcc == 0)
866
    {
867
      if (SumBuf == 20)
868
      {
869
        AdrMode += 0x40;
870
        AdrVals[0] = 0;
871
        AdrCnt = 1;
872
      }
873
    }
874
    else if (AbleToSign(DispAcc))
875
    {
876
      AdrMode += 0x40;
877
      AdrVals[0] = DispAcc & 0xff;
878
      AdrCnt = 1;
879
    }
880
    else
881
    {
882
      AdrMode += 0x80;
883
      AdrVals[0] = Lo(DispAcc);
884
      AdrVals[1] = Hi(DispAcc);
885
      AdrCnt = 2;
886
    }
887
    ChkSpaces(SegBuffer, MomSegment, &Arg);
888
    if (FoundSize != -1)
889
      ChkOpSize(FoundSize);
890
  }
891
 
892
chk_type:
893
  if ((AdrType != TypeNone) && !((type_mask >> AdrType) & 1))
894
  {
895
    WrStrErrorPos(ErrNum_InvAddrMode, pArg);
896
    AdrType = TypeNone;
897
    AdrCnt = 0;
898
  }
899
  return AdrType;
900
}
901
 
902
/*!------------------------------------------------------------------------
903
 * Code Helpers
904
 * ------------------------------------------------------------------------ */
905
 
906
/*!------------------------------------------------------------------------
907
 * \fn     PutCode(Word Code)
908
 * \brief  append 1- or 2-byte machine code to instruction stream
909
 * \param  Code machine code to append
910
 * ------------------------------------------------------------------------ */
911
 
912
static void PutCode(Word Code)
913
{
914
  if (Hi(Code) != 0)
915
    BAsmCode[CodeLen++] = Hi(Code);
916
  BAsmCode[CodeLen++] = Lo(Code);
917
}
918
 
919
/*!------------------------------------------------------------------------
920
 * \fn     AddFWait(Word *pCode)
921
 * \brief  add FPU instruction entry code
922
 * \param  pCode machine code of instruction
923
 * ------------------------------------------------------------------------ */
924
 
925
static void AddFWait(Word *pCode)
926
{
927
  if (*pCode & NO_FWAIT_FLAG)
928
    *pCode &= ~NO_FWAIT_FLAG;
929
  else
930
    AddPrefix(0x9b);
931
}
932
 
933
/*!------------------------------------------------------------------------
934
 * \fn     FPUEntry(Word *pCode)
935
 * \brief  check for FPU availibility and add FPU instruction entry code
936
 * \param  pCode machine code of instruction
937
 * ------------------------------------------------------------------------ */
938
 
939
static Boolean FPUEntry(Word *pCode)
940
{
941
  if (!FPUAvail)
942
  {
943
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
944
    return FALSE;
945
  }
946
 
947
  AddFWait(pCode);
948
  return TRUE;
949
}
950
 
951
/*!------------------------------------------------------------------------
952
 * \fn     check_core_mask(Byte instr_core_mask)
953
 * \brief  check whether current CPU supports core requirments
954
 * \param  instr_core_mask mask of allowed core types
955
 * \return True if OK
956
 * ------------------------------------------------------------------------ */
957
 
958
static Boolean check_core_mask(Byte instr_core_mask)
959
{
960
  const char *p_cpu_name;
961
 
962
  if (p_curr_cpu_props->core & instr_core_mask)
963
    return True;
964
 
965
  switch (instr_core_mask)
966
  {
967
    case e_core_all_v35:
968
      p_cpu_name = "V25/V35";
969
      goto write_min;
970
    case e_core_all_v:
971
      p_cpu_name = "V20/V30";
972
      goto write_min;
973
    case e_core_all_186:
974
      p_cpu_name = "80186/80188";
975
      goto write_min;
976
    default:
977
      WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
978
      break;
979
    write_min:
980
    {
981
      char str[100];
982
 
983
      as_snprintf(str, sizeof(str), getmessage(Num_ErrMsgMinCPUSupported), p_cpu_name);
984
      WrXErrorPos(ErrNum_InstructionNotSupported, str, &OpPart.Pos);
985
      break;
986
    }
987
  }
988
  return False;
989
}
990
 
991
/*---------------------------------------------------------------------------*/
992
 
993
/*!------------------------------------------------------------------------
994
 * \fn     decode_mod_reg_core(Word code, Boolean no_seg_check, int start_index)
995
 * \brief  decode/append mod/reg instruction
996
 * \param  code instruction's machine code
997
 * \param  no_seg_check
998
 * \param  start_index position of first argument
999
 * ------------------------------------------------------------------------ */
1000
 
1001
static void decode_mod_reg_core(Word code, Boolean no_seg_check, int start_index)
1002
{
1003
  switch (DecodeAdr(&ArgStr[start_index], MTypeReg16))
1004
  {
1005
    case TypeReg16:
1006
    {
1007
      Byte reg = (AdrMode << 3);
1008
      OpSize = no_seg_check ? eSymbolSizeUnknown : eSymbolSize32Bit;
1009
      switch (DecodeAdr(&ArgStr[start_index + 1], MTypeMem))
1010
      {
1011
        case TypeMem:
1012
          PutCode(code);
1013
          BAsmCode[CodeLen] = reg + AdrMode;
1014
          copy_adr_vals(1);
1015
          CodeLen += 1 + AdrCnt;
1016
          break;
1017
        default:
1018
          break;
1019
      }
1020
      break;
1021
    }
1022
    default:
1023
      break;
1024
  }
1025
  AddPrefixes();
1026
}
1027
 
1028
/*!------------------------------------------------------------------------
1029
 * \fn     append_rel(const tStrComp *p_arg)
1030
 * \brief  append relative displacement to instruction
1031
 * \param  p_arg source argument of branch target
1032
 * ------------------------------------------------------------------------ */
1033
 
1034
static void append_rel(const tStrComp *p_arg)
1035
{
1036
  tEvalResult eval_result;
1037
  Word adr_word = EvalStrIntExpressionWithResult(p_arg, Int16, &eval_result);
1038
 
1039
  if (eval_result.OK)
1040
  {
1041
    ChkSpace(SegCode, eval_result.AddrSpaceMask);
1042
    adr_word -= EProgCounter() + CodeLen + 1;
1043
    if ((adr_word >= 0x80) && (adr_word < 0xff80) && !mSymbolQuestionable(eval_result.Flags))
1044
    {
1045
      WrStrErrorPos(ErrNum_JmpDistTooBig, p_arg);
1046
      CodeLen = 0;
1047
    }
1048
    else
1049
      BAsmCode[CodeLen++] = Lo(adr_word);
1050
  }
1051
  else
1052
    CodeLen = 0;
1053
}
1054
 
1055
/*!------------------------------------------------------------------------
1056
 * \fn     DecodeMOV(Word Index)
1057
 * \brief  handle MOV instruction
1058
 * ------------------------------------------------------------------------ */
1059
 
1060
static void DecodeMOV(Word Index)
1061
{
1062
  Byte AdrByte;
1063
  UNUSED(Index);
1064
 
1065
  if (ChkArgCnt(2, 3))
1066
  {
1067
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeRegSeg))
1068
    {
1069
      case TypeReg8:
1070
      case TypeReg16:
1071
        if (!ChkArgCnt(2, 2))
1072
          return;
1073
        AdrByte = AdrMode;
1074
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeRegSeg | MTypeImm))
1075
        {
1076
          case TypeReg8:
1077
          case TypeReg16:
1078
            BAsmCode[CodeLen++] = 0x8a | OpSize;
1079
            BAsmCode[CodeLen++] = 0xc0 | (AdrByte << 3) | AdrMode;
1080
            break;
1081
          case TypeMem:
1082
            if ((AdrByte == 0) && (AdrMode == 6))
1083
            {
1084
              BAsmCode[CodeLen] = 0xa0 | OpSize;
1085
              copy_adr_vals(1);
1086
              CodeLen += 1 + AdrCnt;
1087
            }
1088
            else
1089
            {
1090
              BAsmCode[CodeLen++] = 0x8a | OpSize;
1091
              BAsmCode[CodeLen++] = AdrMode | (AdrByte << 3);
1092
              copy_adr_vals(0);
1093
              CodeLen += AdrCnt;
1094
            }
1095
            break;
1096
          case TypeRegSeg:
1097
            if (OpSize == eSymbolSize8Bit) WrError(ErrNum_ConfOpSizes);
1098
            else
1099
            {
1100
              if (AdrMode >= 4) /* V55 DS2/DS3 */
1101
                AdrMode += 2;
1102
              BAsmCode[CodeLen++] = 0x8c;
1103
              BAsmCode[CodeLen++] = 0xc0 | (AdrMode << 3) | AdrByte;
1104
            }
1105
            break;
1106
          case TypeImm:
1107
            BAsmCode[CodeLen++] = 0xb0 | (OpSize << 3) | AdrByte;
1108
            copy_adr_vals(0);
1109
            CodeLen += AdrCnt;
1110
            break;
1111
          default:
1112
            break;
1113
        }
1114
        break;
1115
      case TypeMem:
1116
        if (!ChkArgCnt(2, 2))
1117
          return;
1118
         BAsmCode[CodeLen + 1] = AdrMode;
1119
         copy_adr_vals(2);
1120
         AdrByte = AdrCnt;
1121
         switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeRegSeg | MTypeImm))
1122
         {
1123
           case TypeReg8:
1124
           case TypeReg16:
1125
            if ((AdrMode == 0) && (BAsmCode[CodeLen + 1] == 6))
1126
            {
1127
              BAsmCode[CodeLen] = 0xa2 | OpSize;
1128
              memmove(BAsmCode + CodeLen + 1, BAsmCode + CodeLen + 2, AdrByte);
1129
              CodeLen += 1 + AdrByte;
1130
            }
1131
            else
1132
            {
1133
              BAsmCode[CodeLen] = 0x88 | OpSize;
1134
              BAsmCode[CodeLen + 1] |= AdrMode << 3;
1135
              CodeLen += 2 + AdrByte;
1136
            }
1137
            break;
1138
          case TypeRegSeg:
1139
            if (AdrMode >= 4) /* V55 DS2/DS3 */
1140
              AdrMode += 2;
1141
            BAsmCode[CodeLen] = 0x8c;
1142
            BAsmCode[CodeLen + 1] |= AdrMode << 3;
1143
            CodeLen += 2 + AdrByte;
1144
            break;
1145
          case TypeImm:
1146
            BAsmCode[CodeLen] = 0xc6 | OpSize;
1147
            copy_adr_vals(2 + AdrByte);
1148
            CodeLen += 2 + AdrByte + AdrCnt;
1149
            break;
1150
          default:
1151
            break;
1152
        }
1153
        break;
1154
      case TypeRegSeg:
1155
        if (3 == ArgCnt) /* Alias for LDS, LES... */
1156
        {
1157
          switch (AdrMode)
1158
          {
1159
            case 0: /* LES reg,ea <-> MOV ES,reg,ea */
1160
              decode_mod_reg_core(0x00c4, True, 2);
1161
              break;
1162
            case 3: /* LDS reg,ea <-> MOV DS,reg,ea */
1163
              decode_mod_reg_core(0x00c5, False, 2);
1164
              break;
1165
            case 4: /* LDS3 reg,ea <-> MOV DS3,reg,ea */
1166
              decode_mod_reg_core(0x0f36, False, 2);
1167
              break;
1168
            case 5: /* LDS2 reg,ea <-> MOV DS2,reg,ea */
1169
              decode_mod_reg_core(0x0f3e, False, 2);
1170
              break;
1171
            default:
1172
              WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
1173
          }
1174
        }
1175
        else /* ordinary MOV <segreg>,r/m */
1176
        {
1177
          if (AdrMode >= 4) /* V55 DS2/DS3 */
1178
            AdrMode += 2;
1179
          BAsmCode[CodeLen + 1] = AdrMode << 3;
1180
          switch (DecodeAdr(&ArgStr[2], MTypeReg16 | MTypeMem))
1181
          {
1182
            case TypeReg16:
1183
              BAsmCode[CodeLen++] = 0x8e;
1184
              BAsmCode[CodeLen++] |= 0xc0 + AdrMode;
1185
              break;
1186
            case TypeMem:
1187
              BAsmCode[CodeLen] = 0x8e;
1188
              BAsmCode[CodeLen + 1] |= AdrMode;
1189
              copy_adr_vals(2);
1190
              CodeLen += 2 + AdrCnt;
1191
              break;
1192
            default:
1193
              break;
1194
          }
1195
        }
1196
        break;
1197
      default:
1198
        break;
1199
    }
1200
  }
1201
  AddPrefixes();
1202
}
1203
 
1204
/*!------------------------------------------------------------------------
1205
 * \fn     DecodeINCDEC(Word Index)
1206
 * \brief  handle INC/DEC instructions
1207
 * \param  Index machine code
1208
 * ------------------------------------------------------------------------ */
1209
 
1210
static void DecodeINCDEC(Word Index)
1211
{
1212
  if (ChkArgCnt(1, 1))
1213
  {
1214
    switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeReg8 | MTypeMem))
1215
    {
1216
      case TypeReg16:
1217
        BAsmCode[CodeLen] = 0x40 | AdrMode | Index;
1218
        CodeLen++;
1219
        break;
1220
      case TypeReg8:
1221
        BAsmCode[CodeLen] = 0xfe;
1222
        BAsmCode[CodeLen + 1] = 0xc0 | AdrMode | Index;
1223
        CodeLen += 2;
1224
        break;
1225
      case TypeMem:
1226
        MinOneIs0();
1227
        if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
1228
        else
1229
        {
1230
          BAsmCode[CodeLen] = 0xfe | OpSize; /* ANSI :-0 */
1231
          BAsmCode[CodeLen + 1] = AdrMode | Index;
1232
          copy_adr_vals(2);
1233
          CodeLen += 2 + AdrCnt;
1234
        }
1235
        break;
1236
      default:
1237
        break;
1238
    }
1239
  }
1240
  AddPrefixes();
1241
}
1242
 
1243
/*!------------------------------------------------------------------------
1244
 * \fn     DecodeINOUT(Word Index)
1245
 * \brief  handle IN/OUT instructions
1246
 * \param  Index machine code
1247
 * ------------------------------------------------------------------------ */
1248
 
1249
static void DecodeINT(Word Index)
1250
{
1251
  Boolean OK;
1252
  UNUSED(Index);
1253
 
1254
  if (ChkArgCnt(1, 1))
1255
  {
1256
    BAsmCode[CodeLen + 1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
1257
    if (OK)
1258
    {
1259
      if (BAsmCode[1] == 3)
1260
        BAsmCode[CodeLen++] = 0xcc;
1261
      else
1262
      {
1263
        BAsmCode[CodeLen] = 0xcd;
1264
        CodeLen += 2;
1265
      }
1266
    }
1267
  }
1268
  AddPrefixes();
1269
}
1270
 
1271
/*!------------------------------------------------------------------------
1272
 * \fn     DecodeBrk(Word Index)
1273
 * \brief  Decode BRKxx instructions
1274
 * \param  Index instruction table index
1275
 * ------------------------------------------------------------------------ */
1276
 
1277
static void DecodeBrk(Word Index)
1278
{
1279
  Boolean OK;
1280
  const FixedOrder *p_order = &BrkOrders[Index];
1281
 
1282
  if (ChkArgCnt(1, 1) && check_core_mask(p_order->core_mask))
1283
  {
1284
    PutCode(p_order->Code);
1285
    BAsmCode[CodeLen] = EvalStrIntExpression(&ArgStr[1], UInt8, &OK);
1286
    if (OK)
1287
    {
1288
      CodeLen++;
1289
      AddPrefixes();
1290
    }
1291
    else
1292
      CodeLen = 0;
1293
  }
1294
  AddPrefixes();
1295
}
1296
 
1297
/*!------------------------------------------------------------------------
1298
 * \fn     DecodeINOUT(Word Index)
1299
 * \brief  handle IN/OUT (intra-segment) instructions
1300
 * \param  Index machine code
1301
 * ------------------------------------------------------------------------ */
1302
 
1303
static void DecodeINOUT(Word Index)
1304
{
1305
  if (ChkArgCnt(2, 2))
1306
  {
1307
    tStrComp *pPortArg = Index ? &ArgStr[1] : &ArgStr[2],
1308
             *pRegArg = Index ? &ArgStr[2] : &ArgStr[1];
1309
 
1310
    switch (DecodeAdr(pRegArg, MTypeReg8 | MTypeReg16))
1311
    {
1312
      case TypeReg8:
1313
      case TypeReg16:
1314
        if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pRegArg);
1315
        else if (!as_strcasecmp(pPortArg->str.p_str, "DX"))
1316
          BAsmCode[CodeLen++] = 0xec | OpSize | Index;
1317
        else
1318
        {
1319
          tEvalResult EvalResult;
1320
 
1321
          BAsmCode[CodeLen + 1] = EvalStrIntExpressionWithResult(pPortArg, UInt8, &EvalResult);
1322
          if (EvalResult.OK)
1323
          {
1324
            ChkSpace(SegIO, EvalResult.AddrSpaceMask);
1325
            BAsmCode[CodeLen] = 0xe4 | OpSize | Index;
1326
            CodeLen += 2;
1327
          }
1328
        }
1329
        break;
1330
      default:
1331
        break;
1332
    }
1333
  }
1334
  AddPrefixes();
1335
}
1336
 
1337
/*!------------------------------------------------------------------------
1338
 * \fn     DecodeCALLJMP(Word Index)
1339
 * \brief  handle CALL/JMP (intra-segment) instructions
1340
 * \param  Index machine code
1341
 * ------------------------------------------------------------------------ */
1342
 
1343
static void DecodeCALLJMP(Word Index)
1344
{
1345
  Byte AdrByte;
1346
  Word AdrWord;
1347
  Boolean OK;
1348
 
1349
  if (ChkArgCnt(1, 1))
1350
  {
1351
    char *pAdr = ArgStr[1].str.p_str;
1352
 
1353
    if (!strncmp(pAdr, "SHORT ", 6))
1354
    {
1355
      AdrByte = 2;
1356
      pAdr += 6;
1357
      KillPrefBlanks(pAdr);
1358
    }
1359
    else if ((!strncmp(pAdr, "LONG ", 5)) || (!strncmp(pAdr, "NEAR ", 5)))
1360
    {
1361
      AdrByte = 1;
1362
      pAdr +=  5;
1363
      KillPrefBlanks(pAdr);
1364
    }
1365
    else
1366
      AdrByte = 0;
1367
    OK = True;
1368
    if (Index == 0)
1369
    {
1370
      if (AdrByte == 2)
1371
      {
1372
        WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1373
        OK = False;
1374
      }
1375
      else
1376
        AdrByte = 1;
1377
    }
1378
 
1379
    if (OK)
1380
    {
1381
      OpSize = eSymbolSize16Bit;
1382
      switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeMem | MTypeImm))
1383
      {
1384
        case TypeReg16:
1385
          BAsmCode[0] = 0xff;
1386
          BAsmCode[1] = AdrMode | (0xd0 + (Index << 4));
1387
          CodeLen = 2;
1388
          break;
1389
        case TypeMem:
1390
          BAsmCode[0] = 0xff;
1391
          BAsmCode[1] = AdrMode | (0x10 + (Index << 4));
1392
          copy_adr_vals(2);
1393
          CodeLen = 2 + AdrCnt;
1394
          break;
1395
        case TypeImm:
1396
          ChkSpace(SegCode, ImmAddrSpaceMask);
1397
          AdrWord = (((Word) AdrVals[1]) << 8) | AdrVals[0];
1398
          if ((AdrByte == 2) || ((AdrByte == 0) && (AbleToSign(AdrWord - EProgCounter() - 2))))
1399
          {
1400
            AdrWord -= EProgCounter() + 2;
1401
            if (!AbleToSign(AdrWord)) WrStrErrorPos(ErrNum_DistTooBig, &ArgStr[1]);
1402
            else
1403
            {
1404
              BAsmCode[0] = 0xeb;
1405
              BAsmCode[1] = Lo(AdrWord);
1406
              CodeLen = 2;
1407
            }
1408
          }
1409
          else
1410
          {
1411
            AdrWord -= EProgCounter() + 3;
1412
            BAsmCode[0] = 0xe8 | Index;
1413
            BAsmCode[1] = Lo(AdrWord);
1414
            BAsmCode[2] = Hi(AdrWord);
1415
            CodeLen = 3;
1416
            AdrWord++;
1417
          }
1418
          break;
1419
        default:
1420
          break;
1421
      }
1422
    }
1423
  }
1424
  AddPrefixes();
1425
}
1426
 
1427
/*!------------------------------------------------------------------------
1428
 * \fn     DecodePUSHPOP(Word Index)
1429
 * \brief  handle PUSH/POP instructions
1430
 * \param  Index machine code
1431
 * ------------------------------------------------------------------------ */
1432
 
1433
static void DecodePUSHPOP(Word Index)
1434
{
1435
  if (ChkArgCnt(1, 1))
1436
  {
1437
    OpSize = eSymbolSize16Bit;
1438
    switch (DecodeAdr(&ArgStr[1], MTypeReg16 | MTypeMem | MTypeRegSeg | ((Index == 1) ? 0 : MTypeImm)))
1439
    {
1440
      case TypeReg16:
1441
        BAsmCode[CodeLen] = 0x50 |  AdrMode | (Index << 3);
1442
        CodeLen++;
1443
        break;
1444
      case TypeRegSeg:
1445
        if (AdrMode >= 4) /* V55 DS2/DS3 */
1446
        {
1447
          BAsmCode[CodeLen++] = 0x0f;
1448
          BAsmCode[CodeLen++] = 0x76 | ((AdrMode & 1) << 3) | Index;
1449
        }
1450
        else
1451
        {
1452
          BAsmCode[CodeLen] = 0x06 | (AdrMode << 3) | Index;
1453
          CodeLen++;
1454
        }
1455
        break;
1456
      case TypeMem:
1457
        BAsmCode[CodeLen] = 0x8f;
1458
        BAsmCode[CodeLen + 1] = AdrMode;
1459
        if (Index == 0)
1460
        {
1461
          BAsmCode[CodeLen] += 0x70;
1462
          BAsmCode[CodeLen + 1] += 0x30;
1463
        }
1464
        copy_adr_vals(2);
1465
        CodeLen += 2 + AdrCnt;
1466
        break;
1467
      case TypeImm:
1468
        if (check_core_mask(e_core_all_186))
1469
        {
1470
          BAsmCode[CodeLen] = 0x68;
1471
          BAsmCode[CodeLen + 1] = AdrVals[0];
1472
          if (Sgn(AdrVals[0]) == AdrVals[1])
1473
          {
1474
            BAsmCode[CodeLen] += 2;
1475
            CodeLen += 2;
1476
          }
1477
          else
1478
          {
1479
            BAsmCode[CodeLen + 2] = AdrVals[1];
1480
            CodeLen += 3;
1481
          }
1482
        }
1483
        break;
1484
      default:
1485
        break;
1486
    }
1487
  }
1488
  AddPrefixes();
1489
}
1490
 
1491
/*!------------------------------------------------------------------------
1492
 * \fn     DecodeNOTNEG(Word Index)
1493
 * \brief  handle NOT/NEG instructions
1494
 * \param  Index machine code
1495
 * ------------------------------------------------------------------------ */
1496
 
1497
static void DecodeNOTNEG(Word Index)
1498
{
1499
  if (ChkArgCnt(1, 1))
1500
  {
1501
    DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem);
1502
    MinOneIs0();
1503
    BAsmCode[CodeLen] = 0xf6 | OpSize;
1504
    BAsmCode[CodeLen + 1] = 0x10 | Index;
1505
    switch (AdrType)
1506
    {
1507
      case TypeReg8:
1508
      case TypeReg16:
1509
        BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
1510
        CodeLen += 2;
1511
        break;
1512
      case TypeMem:
1513
        if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
1514
        else
1515
        {
1516
          BAsmCode[CodeLen + 1] |= AdrMode;
1517
          copy_adr_vals(2);
1518
          CodeLen += 2 + AdrCnt;
1519
        }
1520
        break;
1521
      default:
1522
        break;
1523
    }
1524
  }
1525
  AddPrefixes();
1526
}
1527
 
1528
/*!------------------------------------------------------------------------
1529
 * \fn     DecodeRET(Word Index)
1530
 * \brief  handle RET instruction
1531
 * ------------------------------------------------------------------------ */
1532
 
1533
static void DecodeRET(Word Index)
1534
{
1535
  Word AdrWord;
1536
  Boolean OK;
1537
 
1538
  if (!ChkArgCnt(0, 1));
1539
  else if (ArgCnt == 0)
1540
    BAsmCode[CodeLen++] = 0xc3 | Index;
1541
  else
1542
  {
1543
    AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
1544
    if (OK)
1545
    {
1546
      BAsmCode[CodeLen++] = 0xc2 | Index;
1547
      BAsmCode[CodeLen++] = Lo(AdrWord);
1548
      BAsmCode[CodeLen++] = Hi(AdrWord);
1549
    }
1550
  }
1551
}
1552
 
1553
/*!------------------------------------------------------------------------
1554
 * \fn     DecodeTEST(Word Index)
1555
 * \brief  handle TEST instruction
1556
 * ------------------------------------------------------------------------ */
1557
 
1558
static void DecodeTEST(Word Index)
1559
{
1560
  Byte AdrByte;
1561
  UNUSED(Index);
1562
 
1563
  if (ChkArgCnt(2, 2))
1564
  {
1565
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
1566
    {
1567
      case TypeReg8:
1568
      case TypeReg16:
1569
        BAsmCode[CodeLen + 1] = (AdrMode << 3);
1570
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeImm))
1571
        {
1572
          case TypeReg8:
1573
          case TypeReg16:
1574
            BAsmCode[CodeLen + 1] += 0xc0 | AdrMode;
1575
            BAsmCode[CodeLen] = 0x84 | OpSize;
1576
            CodeLen += 2;
1577
            break;
1578
          case TypeMem:
1579
            BAsmCode[CodeLen + 1] |= AdrMode;
1580
            BAsmCode[CodeLen] = 0x84 | OpSize;
1581
            copy_adr_vals(2);
1582
            CodeLen += 2 + AdrCnt;
1583
            break;
1584
          case TypeImm:
1585
            if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
1586
            {
1587
              BAsmCode[CodeLen] = 0xa8 | OpSize;
1588
              copy_adr_vals(1);
1589
              CodeLen += 1 + AdrCnt;
1590
            }
1591
            else
1592
            {
1593
              BAsmCode[CodeLen] = OpSize | 0xf6;
1594
              BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) | 0xc0;
1595
              copy_adr_vals(2);
1596
              CodeLen += 2 + AdrCnt;
1597
            }
1598
            break;
1599
          default:
1600
            break;;
1601
        }
1602
        break;
1603
      case TypeMem:
1604
        BAsmCode[CodeLen + 1] = AdrMode;
1605
        AdrByte = AdrCnt;
1606
        copy_adr_vals(2);
1607
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeImm))
1608
        {
1609
          case TypeReg8:
1610
          case TypeReg16:
1611
            BAsmCode[CodeLen] = 0x84 | OpSize;
1612
            BAsmCode[CodeLen + 1] += (AdrMode << 3);
1613
            CodeLen += 2 + AdrByte;
1614
            break;
1615
          case TypeImm:
1616
            BAsmCode[CodeLen] = OpSize | 0xf6;
1617
            copy_adr_vals(2 + AdrByte);
1618
            CodeLen += 2 + AdrCnt + AdrByte;
1619
            break;
1620
          default:
1621
            break;
1622
        }
1623
        break;
1624
      default:
1625
        break;
1626
    }
1627
  }
1628
  AddPrefixes();
1629
}
1630
 
1631
/*!------------------------------------------------------------------------
1632
 * \fn     DecodeXCHG(Word Index)
1633
 * \brief  handle XCHG instruction
1634
 * ------------------------------------------------------------------------ */
1635
 
1636
static void DecodeXCHG(Word Index)
1637
{
1638
  Byte AdrByte;
1639
  UNUSED(Index);
1640
 
1641
  if (ChkArgCnt(2, 2))
1642
  {
1643
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
1644
    {
1645
      case TypeReg8:
1646
      case TypeReg16:
1647
        AdrByte = AdrMode;
1648
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem))
1649
        {
1650
          case TypeReg8:
1651
          case TypeReg16:
1652
            if ((OpSize == eSymbolSize16Bit) && ((AdrMode == 0) || (AdrByte == 0)))
1653
            {
1654
              BAsmCode[CodeLen] = 0x90 | AdrMode | AdrByte;
1655
              CodeLen++;
1656
            }
1657
            else
1658
            {
1659
              BAsmCode[CodeLen] = 0x86 | OpSize;
1660
              BAsmCode[CodeLen+1] = AdrMode | 0xc0 | (AdrByte << 3);
1661
              CodeLen += 2;
1662
            }
1663
            break;
1664
          case TypeMem:
1665
            BAsmCode[CodeLen] = 0x86 | OpSize;
1666
            BAsmCode[CodeLen+1] = AdrMode | (AdrByte << 3);
1667
            copy_adr_vals(2);
1668
            CodeLen += AdrCnt + 2;
1669
            break;
1670
          default:
1671
            break;
1672
        }
1673
        break;
1674
      case TypeMem:
1675
        BAsmCode[CodeLen + 1] = AdrMode;
1676
        copy_adr_vals(2);
1677
        AdrByte = AdrCnt;
1678
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16))
1679
        {
1680
          case TypeReg8:
1681
          case TypeReg16:
1682
            BAsmCode[CodeLen] = 0x86 | OpSize;
1683
            BAsmCode[CodeLen+1] |= (AdrMode << 3);
1684
            CodeLen += AdrByte + 2;
1685
            break;
1686
          default:
1687
            break;
1688
        }
1689
        break;
1690
      default:
1691
        break;
1692
    }
1693
  }
1694
  AddPrefixes();
1695
}
1696
 
1697
/*!------------------------------------------------------------------------
1698
 * \fn     DecodeCALLJMPF(Word Index)
1699
 * \brief  handle CALLF/JMPF (inter-segment) instructions
1700
 * \param  Index machine code
1701
 * ------------------------------------------------------------------------ */
1702
 
1703
static void DecodeCALLJMPF(Word Index)
1704
{
1705
  char *p;
1706
  Word AdrWord;
1707
  Boolean OK;
1708
 
1709
  if (ChkArgCnt(1, 1))
1710
  {
1711
    p = QuotPos(ArgStr[1].str.p_str, ':');
1712
    if (!p)
1713
    {
1714
      switch (DecodeAdr(&ArgStr[1], MTypeMem))
1715
      {
1716
        case TypeMem:
1717
          BAsmCode[CodeLen] = 0xff;
1718
          BAsmCode[CodeLen + 1] = AdrMode | Hi(Index);
1719
          copy_adr_vals(2);
1720
          CodeLen += 2 + AdrCnt;
1721
          break;
1722
        default:
1723
          break;
1724
      }
1725
    }
1726
    else
1727
    {
1728
      tStrComp SegArg, OffsArg;
1729
 
1730
      StrCompSplitRef(&SegArg, &OffsArg, &ArgStr[1], p);
1731
      AdrWord = EvalStrIntExpression(&SegArg, UInt16, &OK);
1732
      if (OK)
1733
      {
1734
        BAsmCode[CodeLen + 3] = Lo(AdrWord);
1735
        BAsmCode[CodeLen + 4] = Hi(AdrWord);
1736
        AdrWord = EvalStrIntExpression(&OffsArg, UInt16, &OK);
1737
        if (OK)
1738
        {
1739
          BAsmCode[CodeLen + 1] = Lo(AdrWord);
1740
          BAsmCode[CodeLen + 2] = Hi(AdrWord);
1741
          BAsmCode[CodeLen] = Lo(Index);
1742
          CodeLen += 5;
1743
        }
1744
      }
1745
    }
1746
  }
1747
  AddPrefixes();
1748
}
1749
 
1750
/*!------------------------------------------------------------------------
1751
 * \fn     DecodeENTER(Word Index)
1752
 * \brief  handle ENTER instruction
1753
 * ------------------------------------------------------------------------ */
1754
 
1755
static void DecodeENTER(Word Index)
1756
{
1757
  Word AdrWord;
1758
  Boolean OK;
1759
  UNUSED(Index);
1760
 
1761
  if (!ChkArgCnt(2, 2));
1762
  else if (check_core_mask(e_core_all_186))
1763
  {
1764
    AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
1765
    if (OK)
1766
    {
1767
      BAsmCode[CodeLen + 1] = Lo(AdrWord);
1768
      BAsmCode[CodeLen + 2] = Hi(AdrWord);
1769
      BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
1770
      if (OK)
1771
      {
1772
        BAsmCode[CodeLen] = 0xc8;
1773
        CodeLen += 4;
1774
      }
1775
    }
1776
  }
1777
  AddPrefixes();
1778
}
1779
 
1780
/*!------------------------------------------------------------------------
1781
 * \fn     DecodeFixed(Word Index)
1782
 * \brief  handle instructions without argument
1783
 * \param  Index index into instruction table
1784
 * ------------------------------------------------------------------------ */
1785
 
1786
static void DecodeFixed(Word Index)
1787
{
1788
  const FixedOrder *pOrder = FixedOrders + Index;
1789
 
1790
  if (ChkArgCnt(0, 0)
1791
   && check_core_mask(pOrder->core_mask))
1792
    PutCode(pOrder->Code);
1793
  AddPrefixes();
1794
}
1795
 
1796
/*!------------------------------------------------------------------------
1797
 * \fn     DecodeALU2(Word Index)
1798
 * \brief  handle ALU instructions with two arguments
1799
 * \param  Index index into instruction table
1800
 * ------------------------------------------------------------------------ */
1801
 
1802
static void DecodeALU2(Word Index)
1803
{
1804
  Byte AdrByte;
1805
 
1806
  if (ChkArgCnt(2, 2))
1807
  {
1808
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
1809
    {
1810
      case TypeReg8:
1811
      case TypeReg16:
1812
        BAsmCode[CodeLen + 1] = AdrMode << 3;
1813
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeMem | MTypeImm))
1814
        {
1815
          case TypeReg8:
1816
          case TypeReg16:
1817
            BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
1818
            BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
1819
            CodeLen += 2;
1820
            break;
1821
          case TypeMem:
1822
            BAsmCode[CodeLen + 1] |= AdrMode;
1823
            BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
1824
            copy_adr_vals(2);
1825
            CodeLen += 2 + AdrCnt;
1826
            break;
1827
          case TypeImm:
1828
            if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
1829
            {
1830
              BAsmCode[CodeLen] = (Index << 3) | 4 | OpSize;
1831
              copy_adr_vals(1);
1832
              CodeLen += 1 + AdrCnt;
1833
            }
1834
            else
1835
            {
1836
              BAsmCode[CodeLen] = OpSize | 0x80;
1837
              if ((OpSize == eSymbolSize16Bit) && (Sgn(AdrVals[0]) == AdrVals[1]))
1838
              {
1839
                AdrCnt = 1;
1840
                BAsmCode[CodeLen] |= 2;
1841
              }
1842
              BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) + 0xc0 + (Index << 3);
1843
              copy_adr_vals(2);
1844
              CodeLen += 2 + AdrCnt;
1845
            }
1846
            break;
1847
          default:
1848
            break;
1849
        }
1850
        break;
1851
      case TypeMem:
1852
        BAsmCode[CodeLen + 1] = AdrMode;
1853
        AdrByte = AdrCnt;
1854
        copy_adr_vals(2);
1855
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeReg16 | MTypeImm))
1856
        {
1857
          case TypeReg8:
1858
          case TypeReg16:
1859
            BAsmCode[CodeLen] = (Index << 3) | OpSize;
1860
            BAsmCode[CodeLen + 1] |= (AdrMode << 3);
1861
            CodeLen += 2 + AdrByte;
1862
            break;
1863
          case TypeImm:
1864
            BAsmCode[CodeLen] = OpSize | 0x80;
1865
            if ((OpSize == eSymbolSize16Bit) && (Sgn(AdrVals[0]) == AdrVals[1]))
1866
            {
1867
              AdrCnt = 1;
1868
              BAsmCode[CodeLen] += 2;
1869
            }
1870
            BAsmCode[CodeLen + 1] += (Index << 3);
1871
            copy_adr_vals(2 + AdrByte);
1872
            CodeLen += 2 + AdrCnt + AdrByte;
1873
            break;
1874
          default:
1875
            break;
1876
        }
1877
        break;
1878
      default:
1879
        break;
1880
    }
1881
  }
1882
  AddPrefixes();
1883
}
1884
 
1885
/*!------------------------------------------------------------------------
1886
 * \fn     DecodeRel(Word Index)
1887
 * \brief  handle relative branches
1888
 * \param  Index index into instruction table
1889
 * ------------------------------------------------------------------------ */
1890
 
1891
static void DecodeRel(Word Index)
1892
{
1893
  const FixedOrder *pOrder = RelOrders + Index;
1894
 
1895
  if (ChkArgCnt(1, 1)
1896
   && check_core_mask(pOrder->core_mask))
1897
  {
1898
    PutCode(pOrder->Code);
1899
    append_rel(&ArgStr[1]);
1900
  }
1901
}
1902
 
1903
/*!------------------------------------------------------------------------
1904
 * \fn     DecodeASSUME(void)
1905
 * \brief  handle ASSUME instruction
1906
 * ------------------------------------------------------------------------ */
1907
 
1908
static void DecodeASSUME(void)
1909
{
1910
  Boolean OK;
1911
  int z, z3;
1912
  char *p, empty_str[1] = "";
1913
 
1914
  if (ChkArgCnt(1, ArgCntMax))
1915
  {
1916
    z = 1 ; OK = True;
1917
    while ((z <= ArgCnt) && (OK))
1918
    {
1919
      Byte seg_reg;
1920
      tStrComp seg_arg, val_arg;
1921
 
1922
      OK = False;
1923
      p = QuotPos(ArgStr[z].str.p_str, ':');
1924
      if (p)
1925
        StrCompSplitRef(&seg_arg, &val_arg, &ArgStr[z], p);
1926
      else
1927
      {
1928
        StrCompRefRight(&seg_arg, &ArgStr[z], 0);
1929
        StrCompMkTemp(&val_arg, empty_str, sizeof(empty_str));
1930
      }
1931
      if (!decode_seg_reg(&seg_arg, &seg_reg)) WrStrErrorPos(ErrNum_UnknownSegReg, &seg_arg);
1932
      else
1933
      {
1934
        z3 = addrspace_lookup(val_arg.str.p_str);
1935
        if (z3 >= SegCount) WrStrErrorPos(ErrNum_UnknownSegment, &val_arg);
1936
        else if ((z3 != SegCode) && (z3 != SegData) && (z3 != SegXData) && (z3 != SegNone)) WrStrErrorPos(ErrNum_InvSegment, &val_arg);
1937
        else
1938
        {
1939
          SegAssumes[seg_reg] = z3;
1940
          OK = True;
1941
        }
1942
      }
1943
      z++;
1944
    }
1945
  }
1946
}
1947
 
1948
/*!------------------------------------------------------------------------
1949
 * \fn     DecodePORT(Word Code)
1950
 * \brief  handle PORT instruction
1951
 * ------------------------------------------------------------------------ */
1952
 
1953
static void DecodePORT(Word Code)
1954
{
1955
  UNUSED(Code);
1956
 
1957
  CodeEquate(SegIO, 0, 0xffff);
1958
}
1959
 
1960
/*!------------------------------------------------------------------------
1961
 * \fn     DecodeFPUFixed(Word Code)
1962
 * \brief  handle FPU instructions with no arguments
1963
 * \param  Code machine code
1964
 * ------------------------------------------------------------------------ */
1965
 
1966
static void DecodeFPUFixed(Word Code)
1967
{
1968
  if (!FPUEntry(&Code))
1969
    return;
1970
 
1971
  if (ChkArgCnt(0, 0))
1972
  {
1973
    PutCode(Code);
1974
    AddPrefixes();
1975
  }
1976
}
1977
 
1978
/*!------------------------------------------------------------------------
1979
 * \fn     DecodeFPUSt(Word Code)
1980
 * \brief  handle FPU instructions with one register argument
1981
 * \param  Code machine code
1982
 * ------------------------------------------------------------------------ */
1983
 
1984
static void DecodeFPUSt(Word Code)
1985
{
1986
  if (!FPUEntry(&Code))
1987
    return;
1988
 
1989
  if (ChkArgCnt(1, 1))
1990
  {
1991
    if (DecodeAdr(&ArgStr[1], MTypeFReg) == TypeFReg)
1992
    {
1993
      PutCode(Code);
1994
      BAsmCode[CodeLen-1] |= AdrMode;
1995
      AddPrefixes();
1996
    }
1997
  }
1998
}
1999
 
2000
/*!------------------------------------------------------------------------
2001
 * \fn     DecodeFLD(Word Code)
2002
 * \brief  handle FLD instruction
2003
 * \param  Code machine code
2004
 * ------------------------------------------------------------------------ */
2005
 
2006
static void DecodeFLD(Word Code)
2007
{
2008
  if (!FPUEntry(&Code))
2009
    return;
2010
 
2011
  if (ChkArgCnt(1, 1))
2012
  {
2013
    switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
2014
    {
2015
      case TypeFReg:
2016
        BAsmCode[CodeLen++] = 0xd9;
2017
        BAsmCode[CodeLen++] = 0xc0 | AdrMode;
2018
        break;
2019
      case TypeMem:
2020
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2021
          OpSize = eSymbolSize32Bit;
2022
        switch (OpSize)
2023
        {
2024
          case eSymbolSize32Bit:
2025
            BAsmCode[CodeLen++] = 0xd9;
2026
            BAsmCode[CodeLen++] = AdrMode;
2027
            break;
2028
          case eSymbolSize64Bit:
2029
            BAsmCode[CodeLen++] = 0xdd;
2030
            BAsmCode[CodeLen++] = AdrMode;
2031
            break;
2032
          case eSymbolSize80Bit:
2033
            BAsmCode[CodeLen++] = 0xdb;
2034
            BAsmCode[CodeLen++] = AdrMode | 0x28;
2035
            break;
2036
          case eSymbolSizeUnknown:
2037
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2038
            CodeLen = 0;
2039
            break;
2040
          default:
2041
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2042
            CodeLen = 0;
2043
            break;
2044
        }
2045
        if (CodeLen)
2046
          append_adr_vals();
2047
        break;
2048
      default:
2049
        break;
2050
    }
2051
  }
2052
  AddPrefixes();
2053
}
2054
 
2055
/*!------------------------------------------------------------------------
2056
 * \fn     DecodeFILD(Word Code)
2057
 * \brief  handle FILD instruction
2058
 * \param  Code machine code
2059
 * ------------------------------------------------------------------------ */
2060
 
2061
static void DecodeFILD(Word Code)
2062
{
2063
  if (!FPUEntry(&Code))
2064
    return;
2065
 
2066
  if (ChkArgCnt(1, 1))
2067
  {
2068
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2069
    {
2070
      case TypeMem:
2071
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2072
          OpSize = eSymbolSize16Bit;
2073
        switch (OpSize)
2074
        {
2075
          case eSymbolSize16Bit:
2076
            BAsmCode[CodeLen++] = 0xdf;
2077
            BAsmCode[CodeLen++] = AdrMode;
2078
            break;
2079
          case eSymbolSize32Bit:
2080
            BAsmCode[CodeLen++] = 0xdb;
2081
            BAsmCode[CodeLen++] = AdrMode;
2082
            break;
2083
          case eSymbolSize64Bit:
2084
            BAsmCode[CodeLen++] = 0xdf;
2085
            BAsmCode[CodeLen++] = AdrMode | 0x28;
2086
            break;
2087
          case eSymbolSizeUnknown:
2088
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2089
            CodeLen = 0;
2090
            break;
2091
          default:
2092
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2093
            CodeLen = 0;
2094
            break;
2095
        }
2096
        if (CodeLen)
2097
          append_adr_vals();
2098
        break;
2099
      default:
2100
        break;
2101
    }
2102
  }
2103
  AddPrefixes();
2104
}
2105
 
2106
/*!------------------------------------------------------------------------
2107
 * \fn     DecodeFBLD(Word Code)
2108
 * \brief  handle FBLD instruction
2109
 * \param  Code machine code
2110
 * ------------------------------------------------------------------------ */
2111
 
2112
static void DecodeFBLD(Word Code)
2113
{
2114
  if (!FPUEntry(&Code))
2115
    return;
2116
 
2117
  if (ChkArgCnt(1, 1))
2118
  {
2119
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2120
    {
2121
      case TypeMem:
2122
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2123
          OpSize = eSymbolSize80Bit;
2124
        switch (OpSize)
2125
        {
2126
          case eSymbolSizeUnknown:
2127
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2128
            CodeLen = 0;
2129
            break;
2130
          case eSymbolSize80Bit:
2131
            BAsmCode[CodeLen++] = 0xdf;
2132
            BAsmCode[CodeLen++] = AdrMode + 0x20;
2133
            break;
2134
          default:
2135
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2136
            CodeLen = 0;
2137
            break;
2138
        }
2139
        if (CodeLen > 0)
2140
          append_adr_vals();
2141
        break;
2142
      default:
2143
        break;
2144
    }
2145
  }
2146
  AddPrefixes();
2147
}
2148
 
2149
/*!------------------------------------------------------------------------
2150
 * \fn     DecodeFST_FSTP(Word Code)
2151
 * \brief  handle FST(P) instructions
2152
 * \param  Code machine code
2153
 * ------------------------------------------------------------------------ */
2154
 
2155
static void DecodeFST_FSTP(Word Code)
2156
{
2157
  if (!FPUEntry(&Code))
2158
    return;
2159
 
2160
  if (ChkArgCnt(1, 1))
2161
  {
2162
    switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
2163
    {
2164
      case TypeFReg:
2165
        BAsmCode[CodeLen++] = 0xdd;
2166
        BAsmCode[CodeLen++] = Code | AdrMode;
2167
        break;
2168
      case TypeMem:
2169
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2170
          OpSize = eSymbolSize32Bit;
2171
        switch (OpSize)
2172
        {
2173
          case eSymbolSize32Bit:
2174
            BAsmCode[CodeLen++] = 0xd9;
2175
            BAsmCode[CodeLen++] = 0x00;
2176
            break;
2177
          case eSymbolSize64Bit:
2178
            BAsmCode[CodeLen++] = 0xdd;
2179
            BAsmCode[CodeLen++] = 0x00;
2180
            break;
2181
          case eSymbolSize80Bit:
2182
            if (Code == 0xd0)
2183
              goto invalid;
2184
            BAsmCode[CodeLen++] = 0xdb;
2185
            BAsmCode[CodeLen++] = 0x20;
2186
            break;
2187
          case eSymbolSizeUnknown:
2188
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2189
            CodeLen = 0;
2190
            break;
2191
          invalid:
2192
          default:
2193
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2194
            CodeLen = 0;
2195
            break;
2196
        }
2197
        if (CodeLen > 0)
2198
        {
2199
          BAsmCode[CodeLen - 1] |= AdrMode | 0x10 | (Code & 8);
2200
          append_adr_vals();
2201
        }
2202
        break;
2203
      default:
2204
        break;
2205
    }
2206
  }
2207
  AddPrefixes();
2208
}
2209
 
2210
/*!------------------------------------------------------------------------
2211
 * \fn     DecodeFIST_FISTP(Word Code)
2212
 * \brief  handle FIST(P) instructions
2213
 * \param  Code machine code
2214
 * ------------------------------------------------------------------------ */
2215
 
2216
static void DecodeFIST_FISTP(Word Code)
2217
{
2218
  if (!FPUEntry(&Code))
2219
    return;
2220
 
2221
  if (ChkArgCnt(1, 1))
2222
  {
2223
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2224
    {
2225
      case TypeMem:
2226
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2227
          OpSize = eSymbolSize16Bit;
2228
        switch (OpSize)
2229
        {
2230
          case eSymbolSize16Bit:
2231
            BAsmCode[CodeLen++] = 0xdf;
2232
            BAsmCode[CodeLen++] = 0x00;
2233
            break;
2234
          case eSymbolSize32Bit:
2235
            BAsmCode[CodeLen++] = 0xdb;
2236
            BAsmCode[CodeLen++] = 0x00;
2237
            break;
2238
          case eSymbolSize64Bit:
2239
            if (Code == 0x10)
2240
              goto invalid;
2241
            BAsmCode[CodeLen++] = 0xdf;
2242
            BAsmCode[CodeLen++] = 0x20;
2243
            break;
2244
          case eSymbolSizeUnknown:
2245
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2246
            break;
2247
          invalid:
2248
          default:
2249
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2250
            CodeLen = 0;
2251
            break;
2252
        }
2253
        if (CodeLen > 0)
2254
        {
2255
          BAsmCode[CodeLen - 1] |= AdrMode | Code;
2256
          append_adr_vals();
2257
        }
2258
        break;
2259
      default:
2260
        break;
2261
    }
2262
  }
2263
  AddPrefixes();
2264
}
2265
 
2266
/*!------------------------------------------------------------------------
2267
 * \fn     DecodeFBSTP(Word Code)
2268
 * \brief  handle FBSTP instruction
2269
 * \param  Code machine code
2270
 * ------------------------------------------------------------------------ */
2271
 
2272
static void DecodeFBSTP(Word Code)
2273
{
2274
  if (!FPUEntry(&Code))
2275
    return;
2276
 
2277
  if (ChkArgCnt(1, 1))
2278
  {
2279
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2280
    {
2281
      case TypeMem:
2282
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2283
          OpSize = eSymbolSize16Bit;
2284
        switch (OpSize)
2285
        {
2286
          case eSymbolSizeUnknown:
2287
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2288
            break;
2289
          case eSymbolSize80Bit:
2290
            BAsmCode[CodeLen] = 0xdf;
2291
            BAsmCode[CodeLen + 1] = AdrMode | 0x30;
2292
            copy_adr_vals(2);
2293
            CodeLen += 2 + AdrCnt;
2294
            break;
2295
          default:
2296
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2297
        }
2298
        break;
2299
      default:
2300
        break;
2301
    }
2302
  }
2303
  AddPrefixes();
2304
}
2305
 
2306
/*!------------------------------------------------------------------------
2307
 * \fn     DecodeFCOM_FCOMP(Word Code)
2308
 * \brief  handle FCOM(P) instructions
2309
 * \param  Code machine code
2310
 * ------------------------------------------------------------------------ */
2311
 
2312
static void DecodeFCOM_FCOMP(Word Code)
2313
{
2314
  if (!FPUEntry(&Code))
2315
    return;
2316
 
2317
  if (ChkArgCnt(1, 1))
2318
  {
2319
    switch (DecodeAdr(&ArgStr[1], MTypeFReg | MTypeMem))
2320
    {
2321
      case TypeFReg:
2322
        BAsmCode[CodeLen] = 0xd8;
2323
        BAsmCode[CodeLen+1] = Code | AdrMode;
2324
        CodeLen += 2;
2325
        break;
2326
      case TypeMem:
2327
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2328
          OpSize = eSymbolSize16Bit;
2329
        switch (OpSize)
2330
        {
2331
          case eSymbolSize32Bit:
2332
            BAsmCode[CodeLen++] = 0xd8;
2333
            break;
2334
          case eSymbolSize64Bit:
2335
            BAsmCode[CodeLen++] = 0xdc;
2336
            break;
2337
          case eSymbolSizeUnknown:
2338
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2339
            CodeLen = 0;
2340
            break;
2341
          default:
2342
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2343
            CodeLen = 0;
2344
            break;
2345
        }
2346
        if (CodeLen > 0)
2347
        {
2348
          BAsmCode[CodeLen++] = AdrMode | 0x10 | (Code & 8);
2349
          append_adr_vals();
2350
        }
2351
        break;
2352
      default:
2353
        break;
2354
    }
2355
  }
2356
  AddPrefixes();
2357
}
2358
 
2359
/*!------------------------------------------------------------------------
2360
 * \fn     DecodeFICOM_FICOMP(Word Code)
2361
 * \brief  handle FICOM(P) instructions
2362
 * \param  Code machine code
2363
 * ------------------------------------------------------------------------ */
2364
 
2365
static void DecodeFICOM_FICOMP(Word Code)
2366
{
2367
  if (!FPUEntry(&Code))
2368
    return;
2369
 
2370
  if (ChkArgCnt(1, 1))
2371
  {
2372
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2373
    {
2374
      case TypeMem:
2375
        if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2376
          OpSize = eSymbolSize16Bit;
2377
        switch (OpSize)
2378
        {
2379
          case eSymbolSize16Bit:
2380
            BAsmCode[CodeLen++] = 0xde;
2381
            break;
2382
          case eSymbolSize32Bit:
2383
            BAsmCode[CodeLen++] = 0xda;
2384
            break;
2385
          case eSymbolSizeUnknown:
2386
            WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2387
            CodeLen = 0;
2388
            break;
2389
          default:
2390
            WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2391
            CodeLen = 0;
2392
            break;
2393
        }
2394
        if (CodeLen > 0)
2395
        {
2396
          BAsmCode[CodeLen++] = AdrMode | Code;
2397
          append_adr_vals();
2398
        }
2399
        break;
2400
      default:
2401
        break;
2402
    }
2403
  }
2404
  AddPrefixes();
2405
}
2406
 
2407
/*!------------------------------------------------------------------------
2408
 * \fn     DecodeFADD_FMUL(Word Code)
2409
 * \brief  handle FADD/FMUL instructions
2410
 * \param  Code machine code
2411
 * ------------------------------------------------------------------------ */
2412
 
2413
static void DecodeFADD_FMUL(Word Code)
2414
{
2415
  if (!FPUEntry(&Code))
2416
    return;
2417
 
2418
  if (ArgCnt == 0)
2419
  {
2420
    BAsmCode[CodeLen] = 0xde;
2421
    BAsmCode[CodeLen + 1] = 0xc1 + Code;
2422
    CodeLen += 2;
2423
  }
2424
  else if (ChkArgCnt(0, 2))
2425
  {
2426
    const tStrComp *pArg1 = &ArgStr[1],
2427
                   *pArg2 = &ArgStr[2];
2428
 
2429
    if (ArgCnt == 1)
2430
    {
2431
      pArg2 = &ArgStr[1];
2432
      pArg1 = &ArgST;
2433
    }
2434
 
2435
    switch (DecodeAdr(pArg1, MTypeFReg))
2436
    {
2437
      case TypeFReg:
2438
        OpSize = eSymbolSizeUnknown;
2439
        if (AdrMode != 0)   /* ST(i) ist Ziel */
2440
        {
2441
          BAsmCode[CodeLen + 1] = AdrMode;
2442
          switch (DecodeAdr(pArg2, MTypeFReg))
2443
          {
2444
            case TypeFReg:
2445
              BAsmCode[CodeLen] = 0xdc;
2446
              BAsmCode[CodeLen + 1] += 0xc0 + Code;
2447
              CodeLen += 2;
2448
              break;
2449
            default:
2450
              break;
2451
          }
2452
        }
2453
        else                      /* ST ist Ziel */
2454
        {
2455
          switch (DecodeAdr(pArg2, MTypeFReg | MTypeMem))
2456
          {
2457
            case TypeFReg:
2458
              BAsmCode[CodeLen] = 0xd8;
2459
              BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
2460
              CodeLen += 2;
2461
              break;
2462
            case TypeMem:
2463
              if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2464
                OpSize = eSymbolSize32Bit;
2465
              switch (OpSize)
2466
              {
2467
                case eSymbolSize32Bit:
2468
                  BAsmCode[CodeLen++] = 0xd8;
2469
                  break;
2470
                case eSymbolSize64Bit:
2471
                  BAsmCode[CodeLen++] = 0xdc;
2472
                  break;
2473
                case eSymbolSizeUnknown:
2474
                  WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2475
                  CodeLen = 0;
2476
                  break;
2477
                default:
2478
                  WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]);
2479
                  CodeLen = 0;
2480
                  break;
2481
              }
2482
              if (CodeLen > 0)
2483
              {
2484
                BAsmCode[CodeLen++] = AdrMode + Code;
2485
                append_adr_vals();
2486
              }
2487
              break;
2488
            default:
2489
              break;
2490
          }
2491
        }
2492
        break;
2493
      default:
2494
        break;
2495
    }
2496
  }
2497
  AddPrefixes();
2498
}
2499
 
2500
/*!------------------------------------------------------------------------
2501
 * \fn     DecodeFIADD_FIMUL(Word Code)
2502
 * \brief  decode FIADD/FIMUL instructions
2503
 * \param  Code machine code
2504
 * ------------------------------------------------------------------------ */
2505
 
2506
static void DecodeFIADD_FIMUL(Word Code)
2507
{
2508
  const tStrComp *pArg1 = &ArgStr[1],
2509
                 *pArg2 = &ArgStr[2];
2510
 
2511
  if (!FPUEntry(&Code))
2512
    return;
2513
 
2514
  if (ArgCnt == 1)
2515
  {
2516
    pArg2 = &ArgStr[1];
2517
    pArg1 = &ArgST;
2518
  }
2519
  if (ChkArgCnt(1, 2))
2520
  {
2521
    switch (DecodeAdr(pArg1, MTypeFReg))
2522
    {
2523
      case TypeFReg:
2524
        if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
2525
        else
2526
        {
2527
          OpSize = eSymbolSizeUnknown;
2528
          switch (DecodeAdr(pArg2, MTypeMem))
2529
          {
2530
            case TypeMem:
2531
              if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2532
                OpSize = eSymbolSize16Bit;
2533
              switch (OpSize)
2534
              {
2535
                case eSymbolSize16Bit:
2536
                  BAsmCode[CodeLen++] = 0xde;
2537
                  break;
2538
                case eSymbolSize32Bit:
2539
                  BAsmCode[CodeLen++] = 0xda;
2540
                  break;
2541
                case eSymbolSizeUnknown:
2542
                  WrStrErrorPos(ErrNum_UndefOpSizes, pArg1);
2543
                  CodeLen = 0;
2544
                  break;
2545
                default:
2546
                  WrStrErrorPos(ErrNum_InvOpSize, pArg1);
2547
                  CodeLen = 0;
2548
                  break;
2549
              }
2550
              if (CodeLen > 0)
2551
              {
2552
                BAsmCode[CodeLen++] = AdrMode + Code;
2553
                append_adr_vals();
2554
              }
2555
              break;
2556
            default:
2557
              break;
2558
          }
2559
        }
2560
        break;
2561
      default:
2562
        break;
2563
    }
2564
  }
2565
  AddPrefixes();
2566
}
2567
 
2568
/*!------------------------------------------------------------------------
2569
 * \fn     DecodeFADDP_FMULP(Word Code)
2570
 * \brief  handle FADDP/FMULP instructions
2571
 * \param  Code machine code
2572
 * ------------------------------------------------------------------------ */
2573
 
2574
static void DecodeFADDP_FMULP(Word Code)
2575
{
2576
  if (!FPUEntry(&Code))
2577
    return;
2578
 
2579
  if (ChkArgCnt(2, 2))
2580
  {
2581
    switch (DecodeAdr(&ArgStr[2], MTypeFReg))
2582
    {
2583
      case TypeFReg:
2584
        if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
2585
        else
2586
        {
2587
          switch (DecodeAdr(&ArgStr[1], MTypeFReg))
2588
          {
2589
            case TypeFReg:
2590
              BAsmCode[CodeLen] = 0xde;
2591
              BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
2592
              CodeLen += 2;
2593
            default:
2594
              break;
2595
          }
2596
        }
2597
        break;
2598
      default:
2599
        break;
2600
    }
2601
  }
2602
  AddPrefixes();
2603
}
2604
 
2605
/*!------------------------------------------------------------------------
2606
 * \fn     DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)
2607
 * \brief  handle FSUB(R)/FDIV(R) instructions
2608
 * \param  Code machine code
2609
 * ------------------------------------------------------------------------ */
2610
 
2611
static void DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)
2612
{
2613
  if (!FPUEntry(&Code))
2614
    return;
2615
 
2616
  if (ArgCnt == 0)
2617
  {
2618
    BAsmCode[CodeLen] = 0xde;
2619
    BAsmCode[CodeLen + 1] = 0xe1 + (Code ^ 8);
2620
    CodeLen += 2;
2621
  }
2622
  else if (ChkArgCnt(0, 2))
2623
  {
2624
    const tStrComp *pArg1 = &ArgStr[1],
2625
                   *pArg2 = &ArgStr[2];
2626
 
2627
    if (ArgCnt == 1)
2628
    {
2629
      pArg1 = &ArgST;
2630
      pArg2 = &ArgStr[1];
2631
    }
2632
 
2633
    switch (DecodeAdr(pArg1, MTypeFReg))
2634
    {
2635
      case TypeFReg:
2636
        OpSize = eSymbolSizeUnknown;
2637
        if (AdrMode != 0)   /* ST(i) ist Ziel */
2638
        {
2639
          BAsmCode[CodeLen + 1] = AdrMode;
2640
          switch (DecodeAdr(pArg2, MTypeFReg))
2641
          {
2642
            case TypeFReg:
2643
              if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg2);
2644
              else
2645
              {
2646
                BAsmCode[CodeLen] = 0xdc;
2647
                BAsmCode[CodeLen + 1] += 0xe0 + (Code ^ 8);
2648
                CodeLen += 2;
2649
              }
2650
              break;
2651
            default:
2652
              break;
2653
          }
2654
        }
2655
        else  /* ST ist Ziel */
2656
        {
2657
          switch (DecodeAdr(pArg2, MTypeFReg | MTypeMem))
2658
          {
2659
            case TypeFReg:
2660
              BAsmCode[CodeLen] = 0xd8;
2661
              BAsmCode[CodeLen + 1] = 0xe0 + AdrMode + Code;
2662
              CodeLen += 2;
2663
              break;
2664
            case TypeMem:
2665
              if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2666
                OpSize = eSymbolSize32Bit;
2667
              switch (OpSize)
2668
              {
2669
                case eSymbolSize32Bit:
2670
                  BAsmCode[CodeLen++] = 0xd8;
2671
                  break;
2672
                case eSymbolSize64Bit:
2673
                  BAsmCode[CodeLen++] = 0xdc;
2674
                  break;
2675
                case eSymbolSizeUnknown:
2676
                  WrStrErrorPos(ErrNum_UndefOpSizes, pArg2);
2677
                  CodeLen = 0;
2678
                  break;
2679
                default:
2680
                  WrStrErrorPos(ErrNum_InvOpSize, pArg2);
2681
                  CodeLen = 0;
2682
                  break;
2683
              }
2684
              if (CodeLen > 0)
2685
              {
2686
                BAsmCode[CodeLen++] = AdrMode + 0x20 + Code;
2687
                append_adr_vals();
2688
              }
2689
              break;
2690
            default:
2691
              break;
2692
          }
2693
        }
2694
        break;
2695
      default:
2696
        break;
2697
    }
2698
  }
2699
  AddPrefixes();
2700
}
2701
 
2702
/*!------------------------------------------------------------------------
2703
 * \fn     DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)
2704
 * \brief  handle FISUB(R)/FIDIV(R) instructions
2705
 * \param  Code machine code
2706
 * ------------------------------------------------------------------------ */
2707
 
2708
static void DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)
2709
{
2710
  if (!FPUEntry(&Code))
2711
    return;
2712
 
2713
  if (ChkArgCnt(1, 2))
2714
  {
2715
    const tStrComp *pArg1 = &ArgStr[1],
2716
                   *pArg2 = &ArgStr[2];
2717
 
2718
    if (ArgCnt == 1)
2719
    {
2720
      pArg1 = &ArgST;
2721
      pArg2 = &ArgStr[1];
2722
    }
2723
 
2724
    switch (DecodeAdr(pArg1, MTypeFReg))
2725
    {
2726
      case TypeFReg:
2727
        if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, pArg1);
2728
        else
2729
        {
2730
          OpSize = eSymbolSizeUnknown;
2731
          switch (DecodeAdr(pArg2, MTypeMem))
2732
          {
2733
            case TypeMem:
2734
              if ((OpSize == eSymbolSizeUnknown) && UnknownFlag)
2735
                OpSize = eSymbolSize16Bit;
2736
              switch (OpSize)
2737
              {
2738
                case eSymbolSize16Bit:
2739
                  BAsmCode[CodeLen++] = 0xde;
2740
                  break;
2741
                case eSymbolSize32Bit:
2742
                  BAsmCode[CodeLen++] = 0xda;
2743
                  break;
2744
                case eSymbolSizeUnknown:
2745
                  WrStrErrorPos(ErrNum_UndefOpSizes, pArg2);
2746
                  CodeLen = 0;
2747
                  break;
2748
                default:
2749
                  WrStrErrorPos(ErrNum_InvOpSize, pArg2);
2750
                  CodeLen = 0;
2751
                  break;
2752
              }
2753
              if (CodeLen > 0)
2754
              {
2755
                BAsmCode[CodeLen++] = AdrMode + 0x20 + Code;
2756
                append_adr_vals();
2757
              }
2758
              break;
2759
            default:
2760
              break;
2761
          }
2762
        }
2763
        break;
2764
      default:
2765
        break;
2766
    }
2767
  }
2768
  AddPrefixes();
2769
}
2770
 
2771
/*!------------------------------------------------------------------------
2772
 * \fn     DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)
2773
 * \brief  handle FSUB(R)P/FDIV(R)P instructions
2774
 * \param  Code machine code
2775
 * ------------------------------------------------------------------------ */
2776
 
2777
static void DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)
2778
{
2779
  if (!FPUEntry(&Code))
2780
    return;
2781
 
2782
  if (ChkArgCnt(2, 2))
2783
  {
2784
    switch (DecodeAdr(&ArgStr[2], MTypeFReg))
2785
    {
2786
      case TypeFReg:
2787
        if (AdrMode != 0) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
2788
        else
2789
        {
2790
          switch (DecodeAdr(&ArgStr[1], MTypeFReg))
2791
          {
2792
            case TypeFReg:
2793
              BAsmCode[CodeLen] = 0xde;
2794
              BAsmCode[CodeLen+1] = 0xe0 + AdrMode + (Code ^ 8);
2795
              CodeLen += 2;
2796
              break;
2797
            default:
2798
              break;
2799
          }
2800
        }
2801
        break;
2802
      default:
2803
        break;
2804
    }
2805
  }
2806
  AddPrefixes();
2807
}
2808
 
2809
/*!------------------------------------------------------------------------
2810
 * \fn     DecodeFPU16(Word Code)
2811
 * \brief  handle FPU instructions with one 16 bit memory argument
2812
 * \param  Code machine code
2813
 * ------------------------------------------------------------------------ */
2814
 
2815
static void DecodeFPU16(Word Code)
2816
{
2817
  if (!FPUEntry(&Code))
2818
    return;
2819
 
2820
  if (ChkArgCnt(1, 1))
2821
  {
2822
    OpSize = eSymbolSize16Bit;
2823
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2824
    {
2825
      case TypeMem:
2826
        PutCode(Code);
2827
        BAsmCode[CodeLen - 1] += AdrMode;
2828
        copy_adr_vals(0);
2829
        CodeLen += AdrCnt;
2830
        break;
2831
      default:
2832
        break;
2833
    }
2834
  }
2835
  AddPrefixes();
2836
}
2837
 
2838
/*!------------------------------------------------------------------------
2839
 * \fn     DecodeFSAVE_FRSTOR(Word Code)
2840
 * \brief  handle FSAVE/FRSTOR instructions
2841
 * \param  Code machine code
2842
 * ------------------------------------------------------------------------ */
2843
 
2844
static void DecodeFSAVE_FRSTOR(Word Code)
2845
{
2846
  if (!FPUEntry(&Code))
2847
    return;
2848
 
2849
  if (ChkArgCnt(1, 1))
2850
  {
2851
    switch (DecodeAdr(&ArgStr[1], MTypeMem))
2852
    {
2853
      case TypeMem:
2854
        BAsmCode[CodeLen] = 0xdd;
2855
        BAsmCode[CodeLen + 1] = AdrMode + Code;
2856
        copy_adr_vals(2);
2857
        CodeLen += 2 + AdrCnt;
2858
        break;
2859
      default:
2860
        break;
2861
    }
2862
  }
2863
  AddPrefixes();
2864
}
2865
 
2866
/*!------------------------------------------------------------------------
2867
 * \fn     DecodeRept(Word Index)
2868
 * \brief  handle repetition instructions
2869
 * \param  Index index into instruction table
2870
 * ------------------------------------------------------------------------ */
2871
 
2872
static void DecodeRept(Word Index)
2873
{
2874
  const FixedOrder *pOrder = ReptOrders + Index;
2875
 
2876
  if (ChkArgCnt(1, 1)
2877
   && check_core_mask(pOrder->core_mask))
2878
  {
2879
    unsigned z2;
2880
 
2881
    for (z2 = 0; z2 < StringOrderCnt; z2++)
2882
      if (!as_strcasecmp(StringOrders[z2].Name, ArgStr[1].str.p_str))
2883
        break;
2884
    if (z2 >= StringOrderCnt) WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
2885
    else if (check_core_mask(StringOrders[z2].core_mask))
2886
    {
2887
      PutCode(pOrder->Code);
2888
      PutCode(StringOrders[z2].Code);
2889
    }
2890
  }
2891
  AddPrefixes();
2892
}
2893
 
2894
/*!------------------------------------------------------------------------
2895
 * \fn     DecodeMul(Word Index)
2896
 * \brief  handle multiplication instructions
2897
 * \param  Index machine code
2898
 * ------------------------------------------------------------------------ */
2899
 
2900
static void DecodeMul(Word Index)
2901
{
2902
  Boolean OK;
2903
  Word AdrWord;
2904
 
2905
  if (!ChkArgCnt(1, (1 == Index) ? 3 : 1)) /* IMUL only 2/3 ops */
2906
    return;
2907
 
2908
  switch (ArgCnt)
2909
  {
2910
    case 1:
2911
      switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
2912
      {
2913
        case TypeReg8:
2914
        case TypeReg16:
2915
          BAsmCode[CodeLen] = 0xf6 + OpSize;
2916
          BAsmCode[CodeLen + 1] = 0xe0 + (Index << 3) + AdrMode;
2917
          CodeLen += 2;
2918
          break;
2919
        case TypeMem:
2920
          MinOneIs0();
2921
          if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
2922
          else
2923
          {
2924
            BAsmCode[CodeLen] = 0xf6 + OpSize;
2925
            BAsmCode[CodeLen+1] = 0x20 + (Index << 3) + AdrMode;
2926
            copy_adr_vals(2);
2927
            CodeLen += 2 + AdrCnt;
2928
          }
2929
          break;
2930
        default:
2931
          break;
2932
      }
2933
      break;
2934
    case 2:
2935
    case 3:
2936
      if (check_core_mask(e_core_all_186))
2937
      {
2938
        tStrComp *pArg1 = &ArgStr[1],
2939
                 *pArg2 = (ArgCnt == 2) ? &ArgStr[1] : &ArgStr[2],
2940
                 *pArg3 = (ArgCnt == 2) ? &ArgStr[2] : &ArgStr[3];
2941
 
2942
        BAsmCode[CodeLen] = 0x69;
2943
        switch (DecodeAdr(pArg1, MTypeReg16))
2944
        {
2945
          case TypeReg16:
2946
            BAsmCode[CodeLen + 1] = (AdrMode << 3);
2947
            switch (DecodeAdr(pArg2, MTypeReg16 | MTypeMem))
2948
            {
2949
              case TypeReg16:
2950
                AdrMode += 0xc0;
2951
                /* FALL-THRU */
2952
              case TypeMem:
2953
                BAsmCode[CodeLen + 1] += AdrMode;
2954
                copy_adr_vals(2);
2955
                AdrWord = EvalStrIntExpression(pArg3, Int16, &OK);
2956
                if (OK)
2957
                {
2958
                  BAsmCode[CodeLen + 2 + AdrCnt] = Lo(AdrWord);
2959
                  BAsmCode[CodeLen + 3 + AdrCnt] = Hi(AdrWord);
2960
                  CodeLen += 2 + AdrCnt + 2;
2961
                  if ((AdrWord >= 0xff80) || (AdrWord < 0x80))
2962
                  {
2963
                    CodeLen--;
2964
                    BAsmCode[CodeLen-AdrCnt - 2 - 1] += 2;
2965
                  }
2966
                }
2967
                break;
2968
              default:
2969
                break;
2970
            }
2971
            break;
2972
          default:
2973
            break;
2974
        }
2975
      }
2976
      break;
2977
  }
2978
  AddPrefixes();
2979
}
2980
 
2981
/*!------------------------------------------------------------------------
2982
 * \fn     DecodeModReg(Word Index)
2983
 * \brief  handle instructions with one mod/reg argument
2984
 * \param  Index index into instruction table
2985
 * ------------------------------------------------------------------------ */
2986
 
2987
static void DecodeModReg(Word Index)
2988
{
2989
  const ModRegOrder *pOrder = ModRegOrders + Index;
2990
 
2991
  NoSegCheck = pOrder->no_seg_check;
2992
  if (ChkArgCnt(2, 2)
2993
   && check_core_mask(pOrder->core_mask))
2994
    decode_mod_reg_core(pOrder->Code, pOrder->no_seg_check, 1);
2995
}
2996
 
2997
/*!------------------------------------------------------------------------
2998
 * \fn     DecodeShift(Word Index)
2999
 * \brief  handle shift instructions
3000
 * \param  Index index into instruction table
3001
 * ------------------------------------------------------------------------ */
3002
 
3003
static void DecodeShift(Word Index)
3004
{
3005
  const FixedOrder *pOrder = ShiftOrders + Index;
3006
 
3007
  if (ChkArgCnt(2, 2)
3008
   && check_core_mask(pOrder->core_mask))
3009
  {
3010
    DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem);
3011
    MinOneIs0();
3012
    if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
3013
    else switch (AdrType)
3014
    {
3015
      case TypeReg8:
3016
      case TypeReg16:
3017
      case TypeMem:
3018
        BAsmCode[CodeLen] = OpSize;
3019
        /* work around issue on VAX */
3020
        BAsmCode[CodeLen + 1] = pOrder->Code;
3021
        BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] << 3) | AdrMode;
3022
        if (AdrType != TypeMem)
3023
          BAsmCode[CodeLen + 1] += 0xc0;
3024
        copy_adr_vals(2);
3025
        if (!as_strcasecmp(ArgStr[2].str.p_str, "CL"))
3026
        {
3027
          BAsmCode[CodeLen] += 0xd2;
3028
          CodeLen += 2 + AdrCnt;
3029
        }
3030
        else
3031
        {
3032
          Boolean OK;
3033
 
3034
          BAsmCode[CodeLen + 2 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
3035
          if (OK)
3036
          {
3037
            if (BAsmCode[CodeLen + 2 + AdrCnt] == 1)
3038
            {
3039
              BAsmCode[CodeLen] += 0xd0;
3040
              CodeLen += 2 + AdrCnt;
3041
            }
3042
            else if (check_core_mask(e_core_all_186))
3043
            {
3044
              BAsmCode[CodeLen] += 0xc0;
3045
              CodeLen += 3 + AdrCnt;
3046
            }
3047
          }
3048
        }
3049
        break;
3050
      default:
3051
        break;
3052
    }
3053
  }
3054
  AddPrefixes();
3055
}
3056
 
3057
/*!------------------------------------------------------------------------
3058
 * \fn     DecodeROL4_ROR4(Word Code)
3059
 * \brief  handle V20 ROL4/ROR4 instructions
3060
 * \param  Code machine code
3061
 * ------------------------------------------------------------------------ */
3062
 
3063
static void DecodeROL4_ROR4(Word Code)
3064
{
3065
  if (ChkArgCnt(1, 1)
3066
   && check_core_mask(e_core_all_v))
3067
  {
3068
    BAsmCode[CodeLen    ] = 0x0f;
3069
    BAsmCode[CodeLen + 1] = Code;
3070
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeMem))
3071
    {
3072
      case TypeReg8:
3073
        /* TODO: convert mode */
3074
        BAsmCode[CodeLen + 2] = 0xc0 + AdrMode;
3075
        CodeLen += 3;
3076
        break;
3077
      case TypeMem:
3078
        BAsmCode[CodeLen + 2] = AdrMode;
3079
        copy_adr_vals(3);
3080
        CodeLen += 3 + AdrCnt;
3081
        break;
3082
      default:
3083
        break;
3084
    }
3085
  }
3086
  AddPrefixes();
3087
}
3088
 
3089
/*!------------------------------------------------------------------------
3090
 * \fn     DecodeBit1(Word Index)
3091
 * \brief  Handle V30-specific bit instructions (NOT1, CLR1, SET1, TEST1)
3092
 * \param  Index machine code index
3093
 * ------------------------------------------------------------------------ */
3094
 
3095
static void DecodeBit1(Word Index)
3096
{
3097
  int min_arg_cnt = (Index == 0) ? 2 : 1;
3098
  if (!check_core_mask(e_core_all_v))
3099
    return;
3100
 
3101
  switch (ArgCnt)
3102
  {
3103
    case 2:
3104
      switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
3105
      {
3106
        case TypeReg8:
3107
        case TypeReg16:
3108
          AdrMode += 0xc0;
3109
          /* FALL-THRU */
3110
        case TypeMem:
3111
          MinOneIs0();
3112
          if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
3113
          else
3114
          {
3115
            BAsmCode[CodeLen    ] = 0x0f;
3116
            BAsmCode[CodeLen + 1] = 0x10 + (Index << 1) + OpSize;
3117
            BAsmCode[CodeLen + 2] = AdrMode;
3118
            copy_adr_vals(3);
3119
            if (!as_strcasecmp(ArgStr[2].str.p_str, "CL"))
3120
              CodeLen += 3 + AdrCnt;
3121
            else
3122
            {
3123
              Boolean OK;
3124
 
3125
              BAsmCode[CodeLen + 1] += 8;
3126
              BAsmCode[CodeLen + 3 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int4, &OK);
3127
              if (OK)
3128
                CodeLen += 4 + AdrCnt;
3129
            }
3130
          }
3131
          break;
3132
        default:
3133
          break;
3134
      }
3135
      break;
3136
 
3137
    case 1:
3138
      if (min_arg_cnt > 1)
3139
        goto bad_arg_cnt;
3140
      if (as_strcasecmp(ArgStr[1].str.p_str, "CY")) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
3141
      BAsmCode[CodeLen++] = Index == 3 ? 0xf5 : (Index + 0xf7);
3142
      break;
3143
 
3144
    bad_arg_cnt:
3145
    default:
3146
      (void)ChkArgCnt(min_arg_cnt, 2);
3147
  }
3148
  AddPrefixes();
3149
}
3150
 
3151
/*!------------------------------------------------------------------------
3152
 * \fn     DecodeBSCH(Word Index)
3153
 * \brief  Handle V55-specific BSCH instruction
3154
 * \param  code machine code
3155
 * ------------------------------------------------------------------------ */
3156
 
3157
static void DecodeBSCH(Word code)
3158
{
3159
  if (check_core_mask(e_core_all_v55) && ChkArgCnt(1, 1))
3160
    switch (DecodeAdr(&ArgStr[1], MTypeReg8 | MTypeReg16 | MTypeMem))
3161
    {
3162
      case TypeReg8:
3163
      case TypeReg16:
3164
        AdrMode += 0xc0;
3165
        /* FALL-THRU */
3166
      case TypeMem:
3167
        MinOneIs0();
3168
        if (OpSize == eSymbolSizeUnknown) WrStrErrorPos(ErrNum_UndefOpSizes, &ArgStr[1]);
3169
        PutCode(code + OpSize);
3170
        BAsmCode[CodeLen++] = AdrMode;
3171
        copy_adr_vals(3);
3172
        break;
3173
      default:
3174
        break;
3175
    }
3176
  AddPrefixes();
3177
}
3178
 
3179
/*!------------------------------------------------------------------------
3180
 * \fn     DecodeRSTWDT(Word code)
3181
 * \brief  handle RSTWDT instruction
3182
 * \param  code machine code
3183
 * ------------------------------------------------------------------------ */
3184
 
3185
static void DecodeRSTWDT(Word code)
3186
{
3187
  if (check_core_mask(e_core_all_v55)
3188
   && ChkArgCnt(2, 2))
3189
  {
3190
    Boolean ok;
3191
 
3192
    BAsmCode[2] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
3193
    if (ok)
3194
      BAsmCode[3] = EvalStrIntExpression(&ArgStr[2], Int8, &ok);
3195
    if (ok)
3196
    {
3197
      PutCode(code);
3198
      CodeLen += 2;
3199
    }
3200
  }
3201
}
3202
 
3203
/*!------------------------------------------------------------------------
3204
 * \fn     DecodeBTCLRL(Word code)
3205
 * \brief  handle BTCLRL instruction
3206
 * \param  code machine code
3207
 * ------------------------------------------------------------------------ */
3208
 
3209
static void DecodeBTCLRL(Word code)
3210
{
3211
  if (check_core_mask(e_core_all_v55)
3212
   && ChkArgCnt(3, 3))
3213
  {
3214
    Boolean ok;
3215
 
3216
    PutCode(code);
3217
    BAsmCode[CodeLen++] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
3218
    if (ok)
3219
      BAsmCode[CodeLen++] = EvalStrIntExpression(&ArgStr[2], Int8, &ok);
3220
    if (ok)
3221
      append_rel(&ArgStr[3]);
3222
  }
3223
}
3224
 
3225
/*!------------------------------------------------------------------------
3226
 * \fn     DecodeINS_EXT(Word Code)
3227
 * \brief  Handle V30-specific bit field instructions (INS, EXT)
3228
 * ------------------------------------------------------------------------ */
3229
 
3230
static void DecodeINS_EXT(Word Code)
3231
{
3232
  if (ChkArgCnt(2, 2)
3233
   && check_core_mask(e_core_all_v))
3234
  {
3235
    if (DecodeAdr(&ArgStr[1], MTypeReg8) == TypeReg8)
3236
    {
3237
      BAsmCode[CodeLen    ] = 0x0f;
3238
      BAsmCode[CodeLen + 1] = Code;
3239
      BAsmCode[CodeLen + 2] = 0xc0 + AdrMode;
3240
      switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeImm))
3241
      {
3242
        case TypeReg8:
3243
          BAsmCode[CodeLen + 2] += (AdrMode << 3);
3244
          CodeLen += 3;
3245
          break;
3246
        case TypeImm:
3247
          if (AdrVals[0] > 15) WrStrErrorPos(ErrNum_OverRange, &ArgStr[2]);
3248
          else
3249
          {
3250
            BAsmCode[CodeLen + 1] += 8;
3251
            BAsmCode[CodeLen + 3] = AdrVals[0];
3252
            CodeLen += 4;
3253
          }
3254
          break;
3255
        default:
3256
          break;
3257
      }
3258
    }
3259
  }
3260
  AddPrefixes();
3261
}
3262
 
3263
/*!------------------------------------------------------------------------
3264
 * \fn     DecodeFPO2(Word Code)
3265
 * \brief  handle FPO2 instruction
3266
 * ------------------------------------------------------------------------ */
3267
 
3268
static void DecodeFPO2(Word Code)
3269
{
3270
  UNUSED(Code);
3271
 
3272
  if (ChkArgCnt(1, 2)
3273
   && check_core_mask(e_core_all_v))
3274
  {
3275
    Byte AdrByte;
3276
    Boolean OK;
3277
 
3278
    AdrByte = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
3279
    if (OK)
3280
    {
3281
      BAsmCode[CodeLen    ] = 0x66 + (AdrByte >> 3);
3282
      BAsmCode[CodeLen + 1] = (AdrByte & 7) << 3;
3283
      if (ArgCnt == 1)
3284
      {
3285
        BAsmCode[CodeLen + 1] += 0xc0;
3286
        CodeLen += 2;
3287
      }
3288
      else
3289
      {
3290
        switch (DecodeAdr(&ArgStr[2], MTypeReg8 | MTypeMem))
3291
        {
3292
          case TypeReg8:
3293
            BAsmCode[CodeLen + 1] += 0xc0 + AdrMode;
3294
            CodeLen += 2;
3295
            break;
3296
          case TypeMem:
3297
            BAsmCode[CodeLen + 1] += AdrMode;
3298
            copy_adr_vals(2);
3299
            CodeLen += 2 + AdrCnt;
3300
            break;
3301
          default:
3302
            break;
3303
        }
3304
      }
3305
    }
3306
  }
3307
  AddPrefixes();
3308
}
3309
 
3310
/*!------------------------------------------------------------------------
3311
 * \fn     DecodeBTCLR(Word Code)
3312
 * \brief  handle BTCLR instruction
3313
 * ------------------------------------------------------------------------ */
3314
 
3315
static void DecodeBTCLR(Word Code)
3316
{
3317
  UNUSED(Code);
3318
 
3319
  if (ChkArgCnt(3, 3)
3320
   && check_core_mask(e_core_all_v35))
3321
  {
3322
    Boolean OK;
3323
 
3324
    BAsmCode[CodeLen  ] = 0x0f;
3325
    BAsmCode[CodeLen + 1] = 0x9c;
3326
    BAsmCode[CodeLen + 2] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
3327
    if (OK)
3328
    {
3329
      BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
3330
      if (OK)
3331
      {
3332
        Word AdrWord;
3333
        tSymbolFlags Flags;
3334
 
3335
        AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[3], Int16, &OK, & Flags) - (EProgCounter() + 5);
3336
        if (OK)
3337
        {
3338
          if (!mSymbolQuestionable(Flags) && ((AdrWord > 0x7f) && (AdrWord < 0xff80))) WrStrErrorPos(ErrNum_DistTooBig, &ArgStr[3]);
3339
          else
3340
          {
3341
            BAsmCode[CodeLen + 4] = Lo(AdrWord);
3342
            CodeLen += 5;
3343
          }
3344
        }
3345
      }
3346
    }
3347
  }
3348
  AddPrefixes();
3349
}
3350
 
3351
/*!------------------------------------------------------------------------
3352
 * \fn     DecodeReg16(Word Index)
3353
 * \brief  handle instructions with one 16 bit register argument
3354
 * \param  Index index into list of instructions
3355
 * ------------------------------------------------------------------------ */
3356
 
3357
static void DecodeReg16(Word Index)
3358
{
3359
  const AddOrder *pOrder = Reg16Orders + Index;
3360
 
3361
  if (ChkArgCnt(1, 1))
3362
  {
3363
    switch (DecodeAdr(&ArgStr[1], MTypeReg16))
3364
    {
3365
      case TypeReg16:
3366
        PutCode(pOrder->Code);
3367
        BAsmCode[CodeLen++] = pOrder->Add + AdrMode;
3368
        break;
3369
      default:
3370
        break;
3371
    }
3372
  }
3373
  AddPrefixes();
3374
}
3375
 
3376
/*!------------------------------------------------------------------------
3377
 * \fn     DecodeImm16(Word index)
3378
 * \brief  handle instructions with one immediate 16 bit argument
3379
 * \param  index index into instruction table
3380
 * ------------------------------------------------------------------------ */
3381
 
3382
static void DecodeImm16(Word index)
3383
{
3384
  const FixedOrder *p_order = &Imm16Orders[index];
3385
 
3386
  if (ChkArgCnt(1, 1)
3387
   && check_core_mask(p_order->core_mask))
3388
  {
3389
    Word arg;
3390
    Boolean ok;
3391
 
3392
    PutCode(p_order->Code);
3393
    arg = EvalStrIntExpression(&ArgStr[1], Int16, &ok);
3394
    if (ok)
3395
    {
3396
      BAsmCode[CodeLen++] = Lo(arg);
3397
      BAsmCode[CodeLen++] = Hi(arg);
3398
    }
3399
    else
3400
      CodeLen = 0;
3401
  }
3402
}
3403
 
3404
/*!------------------------------------------------------------------------
3405
 * \fn     DecodeString(Word Index)
3406
 * \brief  handle string instructions
3407
 * \param  Index index into instruction table
3408
 * ------------------------------------------------------------------------ */
3409
 
3410
static void DecodeString(Word Index)
3411
{
3412
  const FixedOrder *pOrder = StringOrders + Index;
3413
 
3414
  if (ChkArgCnt(0, 0)
3415
   && check_core_mask(pOrder->core_mask))
3416
    PutCode(pOrder->Code);
3417
  AddPrefixes();
3418
}
3419
 
3420
/*---------------------------------------------------------------------------*/
3421
 
3422
/*!------------------------------------------------------------------------
3423
 * \fn     InitFields(void)
3424
 * \brief  create/initialize dynamic instruction and hash tables
3425
 * ------------------------------------------------------------------------ */
3426
 
3427
static void AddFPU(const char *NName, Word NCode, InstProc NProc)
3428
{
3429
  char Instr[30];
3430
 
3431
  AddInstTable(InstTable, NName, NCode, NProc);
3432
  as_snprintf(Instr, sizeof(Instr), "%cN%s", *NName, NName + 1);
3433
  AddInstTable(InstTable, Instr, NCode | NO_FWAIT_FLAG, NProc);
3434
}
3435
 
3436
static void AddFixed(const char *NName, Byte core_mask, Word NCode)
3437
{
3438
  order_array_rsv_end(FixedOrders, FixedOrder);
3439
  FixedOrders[InstrZ].core_mask = core_mask;
3440
  FixedOrders[InstrZ].Code = NCode;
3441
  AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
3442
}
3443
 
3444
static void AddBrk(const char *NName, Byte core_mask, Word NCode)
3445
{
3446
  order_array_rsv_end(BrkOrders, FixedOrder);
3447
  BrkOrders[InstrZ].core_mask = core_mask;
3448
  BrkOrders[InstrZ].Code = NCode;
3449
  AddInstTable(InstTable, NName, InstrZ++, DecodeBrk);
3450
}
3451
 
3452
static void AddFPUFixed(const char *NName, Word NCode)
3453
{
3454
  AddFPU(NName, NCode, DecodeFPUFixed);
3455
}
3456
 
3457
static void AddFPUSt(const char *NName, Word NCode)
3458
{
3459
  AddFPU(NName, NCode, DecodeFPUSt);
3460
}
3461
 
3462
static void AddFPU16(const char *NName, Word NCode)
3463
{
3464
  AddFPU(NName, NCode, DecodeFPU16);
3465
}
3466
 
3467
static void AddString(const char *NName, Byte core_mask, Word NCode)
3468
{
3469
  order_array_rsv_end(StringOrders, FixedOrder);
3470
  StringOrders[InstrZ].Name = NName;
3471
  StringOrders[InstrZ].core_mask = core_mask;
3472
  StringOrders[InstrZ].Code = NCode;
3473
  AddInstTable(InstTable, NName, InstrZ++, DecodeString);
3474
}
3475
 
3476
static void AddRept(const char *NName, Byte core_mask, Word NCode)
3477
{
3478
  order_array_rsv_end(ReptOrders, FixedOrder);
3479
  ReptOrders[InstrZ].Code = NCode;
3480
  ReptOrders[InstrZ].core_mask = core_mask;
3481
  AddInstTable(InstTable, NName, InstrZ++, DecodeRept);
3482
}
3483
 
3484
static void AddRel(const char *NName, Byte core_mask, Word NCode)
3485
{
3486
  order_array_rsv_end(RelOrders, FixedOrder);
3487
  RelOrders[InstrZ].core_mask = core_mask;
3488
  RelOrders[InstrZ].Code = NCode;
3489
  AddInstTable(InstTable, NName, InstrZ++, DecodeRel);
3490
}
3491
 
3492
static void AddModReg(const char *NName, Byte core_mask, Word NCode, Boolean no_seg_check)
3493
{
3494
  order_array_rsv_end(ModRegOrders, ModRegOrder);
3495
  ModRegOrders[InstrZ].core_mask = core_mask;
3496
  ModRegOrders[InstrZ].Code = NCode;
3497
  ModRegOrders[InstrZ].no_seg_check = no_seg_check;
3498
  AddInstTable(InstTable, NName, InstrZ++, DecodeModReg);
3499
}
3500
 
3501
static void AddShift(const char *NName, Byte core_mask, Word NCode)
3502
{
3503
  order_array_rsv_end(ShiftOrders, FixedOrder);
3504
  ShiftOrders[InstrZ].core_mask = core_mask;
3505
  ShiftOrders[InstrZ].Code = NCode;
3506
  AddInstTable(InstTable, NName, InstrZ++, DecodeShift);
3507
}
3508
 
3509
static void AddReg16(const char *NName, CPUVar NMin, Word NCode, Byte NAdd)
3510
{
3511
  order_array_rsv_end(Reg16Orders, AddOrder);
3512
  Reg16Orders[InstrZ].MinCPU = NMin;
3513
  Reg16Orders[InstrZ].Code = NCode;
3514
  Reg16Orders[InstrZ].Add = NAdd;
3515
  AddInstTable(InstTable, NName, InstrZ++, DecodeReg16);
3516
}
3517
 
3518
static void AddImm16(const char *NName, Byte core_mask, Word code)
3519
{
3520
  order_array_rsv_end(Imm16Orders, FixedOrder);
3521
  Imm16Orders[InstrZ].core_mask = core_mask;
3522
  Imm16Orders[InstrZ].Code = code;
3523
  AddInstTable(InstTable, NName, InstrZ++, DecodeImm16);
3524
}
3525
 
3526
static void InitFields(void)
3527
{
3528
  InstTable = CreateInstTable(403);
3529
  SetDynamicInstTable(InstTable);
3530
 
3531
  add_null_pseudo(InstTable);
3532
 
3533
  AddInstTable(InstTable, "MOV"  , 0, DecodeMOV);
3534
  AddInstTable(InstTable, "INC"  , 0, DecodeINCDEC);
3535
  AddInstTable(InstTable, "DEC"  , 8, DecodeINCDEC);
3536
  AddInstTable(InstTable, "INT"  , 0, DecodeINT);
3537
  AddInstTable(InstTable, "IN"   , 0, DecodeINOUT);
3538
  AddInstTable(InstTable, "OUT"  , 2, DecodeINOUT);
3539
  AddInstTable(InstTable, "CALL" , 0, DecodeCALLJMP);
3540
  AddInstTable(InstTable, "JMP"  , 1, DecodeCALLJMP);
3541
  AddInstTable(InstTable, "PUSH" , 0, DecodePUSHPOP);
3542
  AddInstTable(InstTable, "POP"  , 1, DecodePUSHPOP);
3543
  AddInstTable(InstTable, "NOT"  , 0, DecodeNOTNEG);
3544
  AddInstTable(InstTable, "NEG"  , 8, DecodeNOTNEG);
3545
  AddInstTable(InstTable, "RET"  , 0, DecodeRET);
3546
  AddInstTable(InstTable, "RETF" , 8, DecodeRET);
3547
  AddInstTable(InstTable, "TEST" , 0, DecodeTEST);
3548
  AddInstTable(InstTable, "XCHG" , 0, DecodeXCHG);
3549
  AddInstTable(InstTable, "CALLF", 0x189a, DecodeCALLJMPF);
3550
  AddInstTable(InstTable, "JMPF" , 0x28ea, DecodeCALLJMPF);
3551
  AddInstTable(InstTable, "ENTER", 0, DecodeENTER);
3552
  AddInstTable(InstTable, "PORT", 0, DecodePORT);
3553
  AddInstTable(InstTable, "ROL4", 0x28, DecodeROL4_ROR4);
3554
  AddInstTable(InstTable, "ROR4", 0x2a, DecodeROL4_ROR4);
3555
  AddInstTable(InstTable, "INS", 0x31, DecodeINS_EXT);
3556
  AddInstTable(InstTable, "EXT", 0x33, DecodeINS_EXT);
3557
  AddInstTable(InstTable, "FPO2", 0, DecodeFPO2);
3558
  AddInstTable(InstTable, "BTCLR", 0, DecodeBTCLR);
3559
  AddFPU("FLD", 0, DecodeFLD);
3560
  AddFPU("FILD", 0, DecodeFILD);
3561
  AddFPU("FBLD", 0, DecodeFBLD);
3562
  AddFPU("FST", 0xd0, DecodeFST_FSTP);
3563
  AddFPU("FSTP", 0xd8, DecodeFST_FSTP);
3564
  AddFPU("FIST", 0x10, DecodeFIST_FISTP);
3565
  AddFPU("FISTP", 0x18, DecodeFIST_FISTP);
3566
  AddFPU("FBSTP", 0, DecodeFBSTP);
3567
  AddFPU("FCOM", 0xd0, DecodeFCOM_FCOMP);
3568
  AddFPU("FCOMP", 0xd8, DecodeFCOM_FCOMP);
3569
  AddFPU("FICOM", 0x10, DecodeFICOM_FICOMP);
3570
  AddFPU("FICOMP", 0x18, DecodeFICOM_FICOMP);
3571
  AddFPU("FADD", 0, DecodeFADD_FMUL);
3572
  AddFPU("FMUL", 8, DecodeFADD_FMUL);
3573
  AddFPU("FIADD", 0, DecodeFIADD_FIMUL);
3574
  AddFPU("FIMUL", 8, DecodeFIADD_FIMUL);
3575
  AddFPU("FADDP", 0, DecodeFADDP_FMULP);
3576
  AddFPU("FMULP", 8, DecodeFADDP_FMULP);
3577
  AddFPU("FDIV" , 16, DecodeFSUB_FSUBR_FDIV_FDIVR);
3578
  AddFPU("FDIVR", 24, DecodeFSUB_FSUBR_FDIV_FDIVR);
3579
  AddFPU("FSUB" ,  0, DecodeFSUB_FSUBR_FDIV_FDIVR);
3580
  AddFPU("FSUBR",  8, DecodeFSUB_FSUBR_FDIV_FDIVR);
3581
  AddFPU("FIDIV" , 16, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
3582
  AddFPU("FIDIVR", 24, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
3583
  AddFPU("FISUB" ,  0, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
3584
  AddFPU("FISUBR",  8, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
3585
  AddFPU("FDIVP" , 16, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
3586
  AddFPU("FDIVRP", 24, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
3587
  AddFPU("FSUBP" ,  0, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
3588
  AddFPU("FSUBRP",  8, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
3589
  AddFPU("FSAVE" , 0x30, DecodeFSAVE_FRSTOR);
3590
  AddFPU("FRSTOR" , 0x20, DecodeFSAVE_FRSTOR);
3591
 
3592
  InstrZ = 0;
3593
  AddFixed("AAA",   e_core_all,     0x0037);  AddFixed("AAS",   e_core_all,     0x003f);
3594
  AddFixed("AAM",   e_core_all,     0xd40a);  AddFixed("AAD",   e_core_all,     0xd50a);
3595
  AddFixed("CBW",   e_core_all,     0x0098);  AddFixed("CLC",   e_core_all,     0x00f8);
3596
  AddFixed("CLD",   e_core_all,     0x00fc);  AddFixed("CLI",   e_core_all,     0x00fa);
3597
  AddFixed("CMC",   e_core_all,     0x00f5);  AddFixed("CWD",   e_core_all,     0x0099);
3598
  AddFixed("DAA",   e_core_all,     0x0027);  AddFixed("DAS",   e_core_all,     0x002f);
3599
  AddFixed("HLT",   e_core_all,     0x00f4);  AddFixed("INTO",  e_core_all,     0x00ce);
3600
  AddFixed("IRET",  e_core_all,     0x00cf);  AddFixed("LAHF",  e_core_all,     0x009f);
3601
  AddFixed("LOCK",  e_core_all,     0x00f0);  AddFixed("NOP",   e_core_all,     0x0090);
3602
  AddFixed("POPF",  e_core_all,     0x009d);  AddFixed("PUSHF", e_core_all,     0x009c);
3603
  AddFixed("SAHF",  e_core_all,     0x009e);  AddFixed("STC",   e_core_all,     0x00f9);
3604
  AddFixed("STD",   e_core_all,     0x00fd);  AddFixed("STI",   e_core_all,     0x00fb);
3605
  AddFixed("WAIT",  e_core_all,     0x009b);  AddFixed("XLAT",  e_core_all,     0x00d7);
3606
  AddFixed("LEAVE", e_core_all_186, 0x00c9);  AddFixed("PUSHA", e_core_all_186, 0x0060);
3607
  AddFixed("POPA",  e_core_all_186, 0x0061);  AddFixed("ADD4S", e_core_all_v,   0x0f20);
3608
  AddFixed("SUB4S", e_core_all_v,   0x0f22);  AddFixed("CMP4S", e_core_all_v,   0x0f26);
3609
  AddFixed("STOP",  e_core_all_v35, 0x0f9e);  AddFixed("RETRBI",e_core_all_v35, 0x0f91);
3610
  AddFixed("FINT",  e_core_all_v35, 0x0f92);  AddFixed("MOVSPA",e_core_all_v35, 0x0f25);
3611
  AddFixed("SEGES", e_core_all,     0x0026);  AddFixed("SEGCS", e_core_all,     0x002e);
3612
  AddFixed("SEGSS", e_core_all,     0x0036);  AddFixed("SEGDS", e_core_all,     0x003e);
3613
  AddFixed("SEGDS2",e_core_all_v55, 0x0063);  AddFixed("SEGDS3",e_core_all_v55, 0x00d6);
3614
  AddFixed("FWAIT", e_core_all,     0x009b);  AddFixed("IDLE",  e_core_v55sc,   0x0f9f);
3615
  AddFixed("ALBIT", e_core_v55pi,   0x0f9a);  AddFixed("COLTRP",e_core_v55pi,   0x0f9b);
3616
  AddFixed("MHENC", e_core_v55pi,   0x0f93);  AddFixed("MRENC", e_core_v55pi,   0x0f97);
3617
  AddFixed("SCHEOL",e_core_v55pi,   0x0f78);  AddFixed("GETBIT",e_core_v55pi,   0x0f79);
3618
  AddFixed("MHDEC", e_core_v55pi,   0x0f7c);  AddFixed("MRDEC", e_core_v55pi,   0x0f7d);
3619
  AddFixed("CNVTRP",e_core_v55pi,   0x0f7a);  AddFixed("IRAM",  e_core_all_v55, 0x00f1);
3620
 
3621
  InstrZ = 0;
3622
  AddBrk("BRKEM", e_core_v30, 0x0fff);
3623
  AddBrk("BRKXA", e_core_v33, 0x0fe0);
3624
  AddBrk("RETXA", e_core_v33, 0x0ff0);
3625
  AddBrk("BRKS",  e_core_v35, 0x00f1);
3626
  AddBrk("BRKN",  e_core_v35, 0x0063);
3627
 
3628
  AddFPUFixed("FCOMPP", 0xded9); AddFPUFixed("FTST",   0xd9e4);
3629
  AddFPUFixed("FXAM",   0xd9e5); AddFPUFixed("FLDZ",   0xd9ee);
3630
  AddFPUFixed("FLD1",   0xd9e8); AddFPUFixed("FLDPI",  0xd9eb);
3631
  AddFPUFixed("FLDL2T", 0xd9e9); AddFPUFixed("FLDL2E", 0xd9ea);
3632
  AddFPUFixed("FLDLG2", 0xd9ec); AddFPUFixed("FLDLN2", 0xd9ed);
3633
  AddFPUFixed("FSQRT",  0xd9fa); AddFPUFixed("FSCALE", 0xd9fd);
3634
  AddFPUFixed("FPREM",  0xd9f8); AddFPUFixed("FRNDINT",0xd9fc);
3635
  AddFPUFixed("FXTRACT",0xd9f4); AddFPUFixed("FABS",   0xd9e1);
3636
  AddFPUFixed("FCHS",   0xd9e0); AddFPUFixed("FPTAN",  0xd9f2);
3637
  AddFPUFixed("FPATAN", 0xd9f3); AddFPUFixed("F2XM1",  0xd9f0);
3638
  AddFPUFixed("FYL2X",  0xd9f1); AddFPUFixed("FYL2XP1",0xd9f9);
3639
  AddFPUFixed("FINIT",  0xdbe3); AddFPUFixed("FENI",   0xdbe0);
3640
  AddFPUFixed("FDISI",  0xdbe1); AddFPUFixed("FCLEX",  0xdbe2);
3641
  AddFPUFixed("FINCSTP",0xd9f7); AddFPUFixed("FDECSTP",0xd9f6);
3642
  AddFPUFixed("FNOP",   0xd9d0);
3643
 
3644
  AddFPUSt("FXCH",  0xd9c8);
3645
  AddFPUSt("FFREE", 0xddc0);
3646
 
3647
  AddFPU16("FLDCW",  0xd928);
3648
  AddFPU16("FSTCW",  0xd938);
3649
  AddFPU16("FSTSW",  0xdd38);
3650
  AddFPU16("FSTENV", 0xd930);
3651
  AddFPU16("FLDENV", 0xd920);
3652
 
3653
  InstrZ = 0;
3654
  AddString("CMPSB", e_core_all,     0x00a6);
3655
  AddString("CMPSW", e_core_all,     0x00a7);
3656
  AddString("LODSB", e_core_all,     0x00ac);
3657
  AddString("LODSW", e_core_all,     0x00ad);
3658
  AddString("MOVSB", e_core_all,     0x00a4);
3659
  AddString("MOVSW", e_core_all,     0x00a5);
3660
  AddString("SCASB", e_core_all,     0x00ae);
3661
  AddString("SCASW", e_core_all,     0x00af);
3662
  AddString("STOSB", e_core_all,     0x00aa);
3663
  AddString("STOSW", e_core_all,     0x00ab);
3664
  AddString("INSB",  e_core_all_186, 0x006c);
3665
  AddString("INSW",  e_core_all_186, 0x006d);
3666
  AddString("OUTSB", e_core_all_186, 0x006e);
3667
  AddString("OUTSW", e_core_all_186, 0x006f);
3668
  StringOrderCnt = InstrZ;
3669
 
3670
  InstrZ = 0;
3671
  AddRept("REP",   e_core_all,   0x00f3);
3672
  AddRept("REPE",  e_core_all,   0x00f3);
3673
  AddRept("REPZ",  e_core_all,   0x00f3);
3674
  AddRept("REPNE", e_core_all,   0x00f2);
3675
  AddRept("REPNZ", e_core_all,   0x00f2);
3676
  AddRept("REPC",  e_core_all_v, 0x0065);
3677
  AddRept("REPNC", e_core_all_v, 0x0064);
3678
 
3679
  InstrZ = 0;
3680
  AddRel("JA",    e_core_all, 0x0077); AddRel("JNBE",  e_core_all, 0x0077);
3681
  AddRel("JAE",   e_core_all, 0x0073); AddRel("JNB",   e_core_all, 0x0073);
3682
  AddRel("JB",    e_core_all, 0x0072); AddRel("JNAE",  e_core_all, 0x0072);
3683
  AddRel("JBE",   e_core_all, 0x0076); AddRel("JNA",   e_core_all, 0x0076);
3684
  AddRel("JC",    e_core_all, 0x0072); AddRel("JCXZ",  e_core_all, 0x00e3);
3685
  AddRel("JE",    e_core_all, 0x0074); AddRel("JZ",    e_core_all, 0x0074);
3686
  AddRel("JG",    e_core_all, 0x007f); AddRel("JNLE",  e_core_all, 0x007f);
3687
  AddRel("JGE",   e_core_all, 0x007d); AddRel("JNL",   e_core_all, 0x007d);
3688
  AddRel("JL",    e_core_all, 0x007c); AddRel("JNGE",  e_core_all, 0x007c);
3689
  AddRel("JLE",   e_core_all, 0x007e); AddRel("JNG",   e_core_all, 0x007e);
3690
  AddRel("JNC",   e_core_all, 0x0073); AddRel("JNE",   e_core_all, 0x0075);
3691
  AddRel("JNZ",   e_core_all, 0x0075); AddRel("JNO",   e_core_all, 0x0071);
3692
  AddRel("JNS",   e_core_all, 0x0079); AddRel("JNP",   e_core_all, 0x007b);
3693
  AddRel("JPO",   e_core_all, 0x007b); AddRel("JO",    e_core_all, 0x0070);
3694
  AddRel("JP",    e_core_all, 0x007a); AddRel("JPE",   e_core_all, 0x007a);
3695
  AddRel("JS",    e_core_all, 0x0078); AddRel("LOOP",  e_core_all, 0x00e2);
3696
  AddRel("LOOPE", e_core_all, 0x00e1); AddRel("LOOPZ", e_core_all, 0x00e1);
3697
  AddRel("LOOPNE",e_core_all, 0x00e0); AddRel("LOOPNZ",e_core_all, 0x00e0);
3698
 
3699
  InstrZ = 0;
3700
  AddModReg("LDS",   e_core_all,     0x00c5, False);
3701
  AddModReg("LEA",   e_core_all,     0x008d, True );
3702
  AddModReg("LES",   e_core_all,     0x00c4, False);
3703
  AddModReg("BOUND", e_core_all_186, 0x0062, False);
3704
  AddModReg("LDS3",  e_core_all,     0x0f36, False);
3705
  AddModReg("LDS2",  e_core_all,     0x0f3e, False);
3706
 
3707
  InstrZ = 0;
3708
  AddShift("SHL",   e_core_all, 4); AddShift("SAL",   e_core_all, 4);
3709
  AddShift("SHR",   e_core_all, 5); AddShift("SAR",   e_core_all, 7);
3710
  AddShift("ROL",   e_core_all, 0); AddShift("ROR",   e_core_all, 1);
3711
  AddShift("RCL",   e_core_all, 2); AddShift("RCR",   e_core_all, 3);
3712
 
3713
  InstrZ = 0;
3714
  AddReg16("BRKCS" , e_core_all_v35, 0x0f2d, 0xc0);
3715
  AddReg16("TSKSW" , e_core_all_v35, 0x0f94, 0xf8);
3716
  AddReg16("MOVSPB", e_core_all_v35, 0x0f95, 0xf8);
3717
 
3718
  InstrZ = 0;
3719
  AddInstTable(InstTable, "ADD", InstrZ++, DecodeALU2);
3720
  AddInstTable(InstTable, "OR" , InstrZ++, DecodeALU2);
3721
  AddInstTable(InstTable, "ADC", InstrZ++, DecodeALU2);
3722
  AddInstTable(InstTable, "SBB", InstrZ++, DecodeALU2);
3723
  AddInstTable(InstTable, "AND", InstrZ++, DecodeALU2);
3724
  AddInstTable(InstTable, "SUB", InstrZ++, DecodeALU2);
3725
  AddInstTable(InstTable, "XOR", InstrZ++, DecodeALU2);
3726
  AddInstTable(InstTable, "CMP", InstrZ++, DecodeALU2);
3727
 
3728
  InstrZ = 0;
3729
  AddInstTable(InstTable, "MUL" , InstrZ++, DecodeMul);
3730
  AddInstTable(InstTable, "IMUL", InstrZ++, DecodeMul);
3731
  AddInstTable(InstTable, "DIV" , InstrZ++, DecodeMul);
3732
  AddInstTable(InstTable, "IDIV", InstrZ++, DecodeMul);
3733
 
3734
  InstrZ = 0;
3735
  AddInstTable(InstTable, "TEST1", InstrZ++, DecodeBit1);
3736
  AddInstTable(InstTable, "CLR1" , InstrZ++, DecodeBit1);
3737
  AddInstTable(InstTable, "SET1" , InstrZ++, DecodeBit1);
3738
  AddInstTable(InstTable, "NOT1" , InstrZ++, DecodeBit1);
3739
 
3740
  AddInstTable(InstTable, "BSCH" , 0x0f3c, DecodeBSCH);
3741
  AddInstTable(InstTable, "RSTWDT", 0x0f96, DecodeRSTWDT);
3742
  AddInstTable(InstTable, "BTCLRL", 0x0f9d, DecodeBTCLRL);
3743
 
3744
  InstrZ = 0;
3745
  AddImm16("QHOUT",  e_core_all_v55, 0x0fe0);
3746
  AddImm16("QOUT",   e_core_all_v55, 0x0fe1);
3747
  AddImm16("QTIN",   e_core_all_v55, 0x0fe2);
3748
 
3749
  AddInstTable(InstTable, "REG" , 0, CodeREG);
3750
  AddIntelPseudo(InstTable, eIntPseudoFlag_LittleEndian);
3751
}
3752
 
3753
/*!------------------------------------------------------------------------
3754
 * \fn     DeinitFields(void)
3755
 * \brief  dispose instructions fields after switch from target
3756
 * ------------------------------------------------------------------------ */
3757
 
3758
static void DeinitFields(void)
3759
{
3760
  DestroyInstTable(InstTable);
3761
  order_array_free(FixedOrders);
3762
  order_array_free(BrkOrders);
3763
  order_array_free(ReptOrders);
3764
  order_array_free(ShiftOrders);
3765
  order_array_free(StringOrders);
3766
  order_array_free(ModRegOrders);
3767
  order_array_free(Reg16Orders);
3768
  order_array_free(RelOrders);
3769
  order_array_free(Imm16Orders);
3770
}
3771
 
3772
/*!------------------------------------------------------------------------
3773
 * \fn     MakeCode_86(void)
3774
 * \brief  parse/encode one instruction
3775
 * ------------------------------------------------------------------------ */
3776
 
3777
static void MakeCode_86(void)
3778
{
3779
  OpSize = eSymbolSizeUnknown;
3780
  PrefixLen = 0;
3781
  NoSegCheck = False;
3782
  UnknownFlag = False;
3783
 
3784
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
3785
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
3786
}
3787
 
3788
/*!------------------------------------------------------------------------
3789
 * \fn     InitCode_86(void)
3790
 * \brief  y86-specific initializations prior to pass
3791
 * ------------------------------------------------------------------------ */
3792
 
3793
static void InitCode_86(void)
3794
{
3795
  SegAssumes[0] = SegNone; /* ASSUME ES:NOTHING */
3796
  SegAssumes[1] = SegCode; /* ASSUME CS:CODE */
3797
  SegAssumes[2] = SegNone; /* ASSUME SS:NOTHING */
3798
  SegAssumes[3] = SegData; /* ASSUME DS:DATA */
3799
}
3800
 
3801
/*!------------------------------------------------------------------------
3802
 * \fn     IsDef_86(void)
3803
 * \brief  does instruction consume label field?
3804
 * \return True if yes
3805
 * ------------------------------------------------------------------------ */
3806
 
3807
static Boolean IsDef_86(void)
3808
{
3809
  return Memo("PORT")
3810
      || Memo("REG");
3811
}
3812
 
3813
/*!------------------------------------------------------------------------
3814
 * \fn     intern_symbol_86(char *p_arg, TempResult *p_result)
3815
 * \brief  parse for built-in symbols
3816
 * \param  p_arg source argument
3817
 * \param  p_result possible result
3818
 * ------------------------------------------------------------------------ */
3819
 
3820
static void intern_symbol_86(char *p_arg, TempResult *p_result)
3821
{
3822
  if (decode_reg_core(p_arg, &p_result->Contents.RegDescr.Reg, &p_result->DataSize))
3823
  {
3824
    p_result->Typ = TempReg;
3825
    p_result->Contents.RegDescr.Dissect = dissect_reg_86;
3826
    p_result->Contents.RegDescr.compare = NULL;
3827
  }
3828
}
3829
 
3830
/*!------------------------------------------------------------------------
3831
 * \fn     SwitchTo_86(void *p_user)
3832
 * \brief  switch to x86 target
3833
 * \param  p_user * to properties of specific variant
3834
 * ------------------------------------------------------------------------ */
3835
 
3836
static void SwitchTo_86(void *p_user)
3837
{
3838
  p_curr_cpu_props = (const cpu_props_t*)p_user;
3839
 
3840
  TurnWords = False; SetIntConstMode(eIntConstModeIntel);
3841
 
3842
  PCSymbol = "$"; HeaderID = 0x42; NOPCode = 0x90;
3843
  DivideChars = ","; HasAttrs = False;
3844
 
3845
  ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegXData) | (1 << SegIO);
3846
  Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
3847
  SegLimits[SegCode ] = 0xffff;
3848
  Grans[SegData ] = 1; ListGrans[SegData ] = 1; SegInits[SegData ] = 0;
3849
  SegLimits[SegData ] = 0xffff;
3850
  Grans[SegXData] = 1; ListGrans[SegXData] = 1; SegInits[SegXData] = 0;
3851
  SegLimits[SegXData] = 0xffff;
3852
  Grans[SegIO   ] = 1; ListGrans[SegIO   ] = 1; SegInits[SegIO   ] = 0;
3853
  SegLimits[SegIO   ] = 0xffff;
3854
 
3855
  pASSUMEOverride = DecodeASSUME;
3856
 
3857
  MakeCode = MakeCode_86; IsDef = IsDef_86;
3858
  SwitchFrom = DeinitFields; InitFields();
3859
  InternSymbol = intern_symbol_86;
3860
  DissectReg = dissect_reg_86;
3861
  onoff_fpu_add();
3862
}
3863
 
3864
/*!------------------------------------------------------------------------
3865
 * \fn     code86_init(void)
3866
 * \brief  register x86 target
3867
 * ------------------------------------------------------------------------ */
3868
 
3869
static const cpu_props_t cpu_props[] =
3870
{
3871
  { "8088"   , e_core_86    },
3872
  { "8086"   , e_core_86    },
3873
  { "80188"  , e_core_186   },
3874
  { "80186"  , e_core_186   },
3875
  { "V20"    , e_core_v30   },
3876
  { "V25"    , e_core_v35   },
3877
  { "V30"    , e_core_v30   },
3878
  { "V33"    , e_core_v33   },
3879
  { "V35"    , e_core_v35   },
3880
  { "V40"    , e_core_v30   },
3881
  { "V50"    , e_core_v30   },
3882
  { "V53"    , e_core_v33   },
3883
  { "V55"    , e_core_v55   },
3884
  { "V55SC"  , e_core_v55sc },
3885
  { "V55PI"  , e_core_v55pi },
3886
  { ""       , e_core_86    }
3887
};
3888
 
3889
void code86_init(void)
3890
{
3891
  const cpu_props_t *p_prop;
3892
  for (p_prop = cpu_props; p_prop->name[0]; p_prop++)
3893
    (void)AddCPUUser(p_prop->name, SwitchTo_86, (void*)p_prop, NULL);
3894
 
3895
  AddInitPassProc(InitCode_86);
3896
}