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 "codepseudo.h"
22 #include "intpseudo.h"
23 #include "asmitree.h"
24 #include "codevars.h"
25 
26 /*---------------------------------------------------------------------------*/
27 
28 typedef struct
29 {
30   const char *Name;
31   CPUVar MinCPU;
32   Word Code;
33 } FixedOrder;
34 
35 typedef struct
36 {
37   CPUVar MinCPU;
38   Word Code;
39   Byte Add;
40 } AddOrder;
41 
42 #define NO_FWAIT_FLAG 0x2000
43 
44 #define FixedOrderCnt 43
45 #define ReptOrderCnt 7
46 #define ShiftOrderCnt 8
47 #define Reg16OrderCnt 3
48 #define ModRegOrderCnt 4
49 #define StringOrderCnt 14
50 #define RelOrderCnt 36
51 
52 #define SegRegCnt 3
53 static const char SegRegNames[SegRegCnt + 1][3] =
54 {
55   "ES", "CS", "SS", "DS"
56 };
57 static const Byte SegRegPrefixes[SegRegCnt + 1] =
58 {
59   0x26, 0x2e, 0x36, 0x3e
60 };
61 
62 static char ArgSTStr[] = "ST";
63 static const tStrComp ArgST = { { 0, 0 }, ArgSTStr };
64 
65 #define TypeNone (-1)
66 #define TypeReg8 0
67 #define TypeReg16 1
68 #define TypeRegSeg 2
69 #define TypeMem 3
70 #define TypeImm 4
71 #define TypeFReg 5
72 
73 static ShortInt AdrType;
74 static Byte AdrMode;
75 static Byte AdrVals[6];
76 static ShortInt OpSize;
77 static Boolean UnknownFlag;
78 static unsigned ImmAddrSpaceMask;
79 
80 static Boolean NoSegCheck;
81 
82 static Byte Prefixes[6];
83 static Byte PrefixLen;
84 
85 static Byte SegAssumes[SegRegCnt + 1];
86 
87 static CPUVar CPU8086, CPU80186, CPUV30, CPUV35;
88 
89 static FixedOrder *FixedOrders, *StringOrders, *ReptOrders, *ShiftOrders,
90                   *ModRegOrders, *RelOrders;
91 static AddOrder *Reg16Orders;
92 
93 /*------------------------------------------------------------------------------------*/
94 
PutCode(Word Code)95 static void PutCode(Word Code)
96 {
97   if (Hi(Code) != 0)
98     BAsmCode[CodeLen++] = Hi(Code);
99   BAsmCode[CodeLen++] = Lo(Code);
100 }
101 
MoveAdr(int Dest)102 static void MoveAdr(int Dest)
103 {
104   memcpy(BAsmCode + CodeLen + Dest, AdrVals, AdrCnt);
105 }
106 
Sgn(Byte inp)107 static Byte Sgn(Byte inp)
108 {
109   return (inp > 127) ? 0xff : 0;
110 }
111 
AddPrefix(Byte Prefix)112 static void AddPrefix(Byte Prefix)
113 {
114   Prefixes[PrefixLen++] = Prefix;
115 }
116 
AddPrefixes(void)117 static void AddPrefixes(void)
118 {
119   if ((CodeLen != 0) && (PrefixLen != 0))
120   {
121     memmove(BAsmCode + PrefixLen, BAsmCode, CodeLen);
122     memcpy(BAsmCode, Prefixes, PrefixLen);
123     CodeLen += PrefixLen;
124   }
125 }
126 
AbleToSign(Word Arg)127 static Boolean AbleToSign(Word Arg)
128 {
129   return ((Arg <= 0x7f) || (Arg >= 0xff80));
130 }
131 
MinOneIs0(void)132 static Boolean MinOneIs0(void)
133 {
134   if ((UnknownFlag) && (OpSize == -1))
135   {
136     OpSize = 0;
137     return True;
138   }
139   else
140     return False;
141 }
142 
ChkOpSize(ShortInt NewSize)143 static void ChkOpSize(ShortInt NewSize)
144 {
145   if (OpSize == -1)
146     OpSize = NewSize;
147   else if (OpSize != NewSize)
148   {
149     AdrType = TypeNone;
150     WrError(ErrNum_ConfOpSizes);
151   }
152 }
153 
ChkSingleSpace(Byte Seg,Byte EffSeg,Byte MomSegment)154 static void ChkSingleSpace(Byte Seg, Byte EffSeg, Byte MomSegment)
155 {
156   Byte z;
157 
158   /* liegt Operand im zu pruefenden Segment? nein-->vergessen */
159 
160   if (!(MomSegment & (1 << Seg)))
161     return;
162 
163   /* zeigt bish. benutztes Segmentregister auf dieses Segment? ja-->ok */
164 
165   if (EffSeg == Seg)
166     return;
167 
168   /* falls schon ein Override gesetzt wurde, nur warnen */
169 
170   if (PrefixLen > 0)
171     WrError(ErrNum_WrongSegment);
172 
173   /* ansonsten ein passendes Segment suchen und warnen, falls keines da */
174 
175   else
176   {
177     z = 0;
178     while ((z <= SegRegCnt) && (SegAssumes[z] != Seg))
179       z++;
180     if (z > SegRegCnt)
181       WrXError(ErrNum_InAccSegment, SegNames[Seg]);
182     else
183       AddPrefix(SegRegPrefixes[z]);
184   }
185 }
186 
ChkSpaces(ShortInt SegBuffer,Byte MomSegment)187 static void ChkSpaces(ShortInt SegBuffer, Byte MomSegment)
188 {
189   Byte EffSeg;
190 
191   if (NoSegCheck)
192     return;
193 
194   /* in welches Segment geht das benutzte Segmentregister ? */
195 
196   EffSeg = SegAssumes[SegBuffer];
197 
198   /* Zieloperand in Code-/Datensegment ? */
199 
200   ChkSingleSpace(SegCode, EffSeg, MomSegment);
201   ChkSingleSpace(SegXData, EffSeg, MomSegment);
202   ChkSingleSpace(SegData, EffSeg, MomSegment);
203 }
204 
DecodeAdr(const tStrComp * pArg)205 static void DecodeAdr(const tStrComp *pArg)
206 {
207   static const int RegCnt = 8;
208   static const char Reg16Names[8][3] =
209   {
210     "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
211   };
212   static const char Reg8Names[8][3] =
213   {
214     "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
215   };
216   static const Byte RMCodes[8] =
217   {
218     11, 12, 21, 22, 1, 2 , 20, 10
219   };
220 
221   int RegZ, z;
222   Boolean IsImm;
223   ShortInt IndexBuf, BaseBuf;
224   Byte SumBuf;
225   LongInt DispAcc, DispSum;
226   char *pIndirStart, *pIndirEnd, *pSep;
227   ShortInt SegBuffer;
228   Byte MomSegment;
229   ShortInt FoundSize;
230   tStrComp Arg;
231   int ArgLen = strlen(pArg->Str);
232 
233   AdrType = TypeNone; AdrCnt = 0;
234   SegBuffer = -1; MomSegment = 0;
235 
236   for (RegZ = 0; RegZ < RegCnt; RegZ++)
237   {
238     if (!as_strcasecmp(pArg->Str, Reg16Names[RegZ]))
239     {
240       AdrType = TypeReg16; AdrMode = RegZ;
241       ChkOpSize(1);
242       return;
243     }
244     if (!as_strcasecmp(pArg->Str, Reg8Names[RegZ]))
245     {
246       AdrType = TypeReg8; AdrMode = RegZ;
247       ChkOpSize(0);
248       return;
249     }
250   }
251 
252   for (RegZ = 0; RegZ <= SegRegCnt; RegZ++)
253     if (!as_strcasecmp(pArg->Str, SegRegNames[RegZ]))
254     {
255       AdrType = TypeRegSeg; AdrMode = RegZ;
256       ChkOpSize(1);
257       return;
258     }
259 
260   if (FPUAvail)
261   {
262     if (!as_strcasecmp(pArg->Str, "ST"))
263     {
264       AdrType = TypeFReg; AdrMode = 0;
265       ChkOpSize(4);
266       return;
267     }
268 
269     if ((ArgLen > 4) && (!as_strncasecmp(pArg->Str, "ST(", 3)) && (pArg->Str[ArgLen - 1] == ')'))
270     {
271       tStrComp Num;
272       Boolean OK;
273 
274       StrCompRefRight(&Num, pArg, 3);
275       StrCompShorten(&Num, 1);
276       AdrMode = EvalStrIntExpression(&Num, UInt3, &OK);
277       if (OK)
278       {
279         AdrType = TypeFReg;
280         ChkOpSize(4);
281       }
282       return;
283     }
284   }
285 
286   IsImm = True;
287   IndexBuf = 0; BaseBuf = 0;
288   DispAcc = 0; FoundSize = -1;
289   Arg = *pArg;
290   if (!as_strncasecmp(Arg.Str, "WORD PTR", 8))
291   {
292     StrCompIncRefLeft(&Arg, 8);
293     FoundSize = 1;
294     IsImm = False;
295     KillPrefBlanksStrCompRef(&Arg);
296   }
297   else if (!as_strncasecmp(Arg.Str, "BYTE PTR", 8))
298   {
299     StrCompIncRefLeft(&Arg, 8);
300     FoundSize = 0;
301     IsImm = False;
302     KillPrefBlanksStrCompRef(&Arg);
303   }
304   else if (!as_strncasecmp(Arg.Str, "DWORD PTR", 9))
305   {
306     StrCompIncRefLeft(&Arg, 9);
307     FoundSize = 2;
308     IsImm = False;
309     KillPrefBlanksStrCompRef(&Arg);
310   }
311   else if (!as_strncasecmp(Arg.Str, "QWORD PTR", 9))
312   {
313     StrCompIncRefLeft(&Arg, 9);
314     FoundSize = 3;
315     IsImm = False;
316     KillPrefBlanksStrCompRef(&Arg);
317   }
318   else if (!as_strncasecmp(Arg.Str, "TBYTE PTR", 9))
319   {
320     StrCompIncRefLeft(&Arg, 9);
321     FoundSize = 4;
322     IsImm = False;
323     KillPrefBlanksStrCompRef(&Arg);
324   }
325 
326   if ((strlen(Arg.Str) > 2) && (Arg.Str[2] == ':'))
327   {
328     tStrComp Remainder;
329 
330     StrCompSplitRef(&Arg, &Remainder, &Arg, Arg.Str + 2);
331     for (z = 0; z <= SegRegCnt; z++)
332       if (!as_strcasecmp(Arg.Str, SegRegNames[z]))
333       {
334         SegBuffer = z;
335         AddPrefix(SegRegPrefixes[SegBuffer]);
336         break;
337       }
338     if (SegBuffer < 0)
339     {
340       WrStrErrorPos(ErrNum_InvReg, &Arg);
341       return;
342     }
343     Arg = Remainder;
344   }
345 
346   do
347   {
348     pIndirStart = QuotPos(Arg.Str, '[');
349 
350     /* no address expr or outer displacement: */
351 
352     if (!pIndirStart || (pIndirStart != Arg.Str))
353     {
354       tStrComp Remainder;
355       tEvalResult EvalResult;
356 
357       if (pIndirStart)
358         StrCompSplitRef(&Arg, &Remainder, &Arg, pIndirStart);
359       DispAcc += EvalStrIntExpressionWithResult(&Arg, Int16, &EvalResult);
360       if (!EvalResult.OK)
361          return;
362       UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
363       MomSegment |= EvalResult.AddrSpaceMask;
364       if (FoundSize == eSymbolSizeUnknown)
365         FoundSize = EvalResult.DataSize;
366       if (pIndirStart)
367         Arg = Remainder;
368       else
369         break;
370     }
371     else
372       StrCompIncRefLeft(&Arg, 1);
373 
374     /* Arg now points right behind [ */
375 
376     if (pIndirStart)
377     {
378       tStrComp IndirArg, OutRemainder, IndirArgRemainder;
379       Boolean NegFlag, OldNegFlag;
380 
381       IsImm = False;
382 
383       pIndirEnd = RQuotPos(Arg.Str, ']');
384       if (!pIndirEnd)
385       {
386         WrError(ErrNum_BrackErr);
387         return;
388       }
389 
390       StrCompSplitRef(&IndirArg, &OutRemainder, &Arg, pIndirEnd);
391       OldNegFlag = False;
392 
393       do
394       {
395         NegFlag = False;
396         pSep = QuotMultPos(IndirArg.Str, "+-");
397         NegFlag = pSep && (*pSep == '-');
398 
399         if (pSep)
400           StrCompSplitRef(&IndirArg, &IndirArgRemainder, &IndirArg, pSep);
401 
402         if (!as_strcasecmp(IndirArg.Str, "BX"))
403         {
404           if ((OldNegFlag) || (BaseBuf != 0))
405             return;
406           else
407             BaseBuf = 1;
408         }
409         else if (!as_strcasecmp(IndirArg.Str, "BP"))
410         {
411           if ((OldNegFlag) || (BaseBuf != 0))
412             return;
413           else
414             BaseBuf = 2;
415         }
416         else if (!as_strcasecmp(IndirArg.Str, "SI"))
417         {
418           if ((OldNegFlag) || (IndexBuf != 0))
419             return;
420           else
421             IndexBuf = 1;
422         }
423         else if (!as_strcasecmp(IndirArg.Str, "DI"))
424         {
425           if ((OldNegFlag) || (IndexBuf !=0 ))
426             return;
427           else
428             IndexBuf = 2;
429         }
430         else
431         {
432           tEvalResult EvalResult;
433 
434           DispSum = EvalStrIntExpressionWithResult(&IndirArg, Int16, &EvalResult);
435           if (!EvalResult.OK)
436             return;
437           UnknownFlag = UnknownFlag || mFirstPassUnknown(EvalResult.Flags);
438           DispAcc = OldNegFlag ? DispAcc - DispSum : DispAcc + DispSum;
439           MomSegment |= EvalResult.AddrSpaceMask;
440           if (FoundSize == eSymbolSizeUnknown)
441             FoundSize = EvalResult.DataSize;
442         }
443         OldNegFlag = NegFlag;
444         if (pSep)
445           IndirArg = IndirArgRemainder;
446       }
447       while (pSep);
448       Arg = OutRemainder;
449     }
450   }
451   while (*Arg.Str);
452 
453   SumBuf = BaseBuf * 10 + IndexBuf;
454 
455   /* welches Segment effektiv benutzt ? */
456 
457   if (SegBuffer == -1)
458     SegBuffer = (BaseBuf == 2) ? 2 : 3;
459 
460   /* nur Displacement */
461 
462   if (0 == SumBuf)
463   {
464     /* immediate */
465 
466     if (IsImm)
467     {
468       ImmAddrSpaceMask = MomSegment;
469       if (((UnknownFlag) && (OpSize == 0)) || (MinOneIs0()))
470         DispAcc &= 0xff;
471       switch (OpSize)
472       {
473         case -1:
474           WrError(ErrNum_UndefOpSizes);
475           break;
476         case 0:
477           if ((DispAcc <- 128) || (DispAcc > 255)) WrError(ErrNum_OverRange);
478           else
479           {
480             AdrType = TypeImm;
481             AdrVals[0] = DispAcc & 0xff;
482             AdrCnt = 1;
483           }
484           break;
485         case 1:
486           AdrType = TypeImm;
487           AdrVals[0] = Lo(DispAcc);
488           AdrVals[1] = Hi(DispAcc);
489           AdrCnt = 2;
490           break;
491         default:
492           WrError(ErrNum_InvOpSize);
493           break;
494       }
495     }
496 
497     /* absolut */
498 
499     else
500     {
501       AdrType = TypeMem;
502       AdrMode = 0x06;
503       AdrVals[0] = Lo(DispAcc);
504       AdrVals[1] = Hi(DispAcc);
505       AdrCnt = 2;
506       if (FoundSize != -1)
507         ChkOpSize(FoundSize);
508       ChkSpaces(SegBuffer, MomSegment);
509     }
510   }
511 
512   /* kombiniert */
513 
514   else
515   {
516     AdrType = TypeMem;
517     for (z = 0; z < 8; z++)
518       if (SumBuf == RMCodes[z])
519         AdrMode = z;
520     if (DispAcc == 0)
521     {
522       if (SumBuf == 20)
523       {
524         AdrMode += 0x40;
525         AdrVals[0] = 0;
526         AdrCnt = 1;
527       }
528     }
529     else if (AbleToSign(DispAcc))
530     {
531       AdrMode += 0x40;
532       AdrVals[0] = DispAcc & 0xff;
533       AdrCnt = 1;
534     }
535     else
536     {
537       AdrMode += 0x80;
538       AdrVals[0] = Lo(DispAcc);
539       AdrVals[1] = Hi(DispAcc);
540       AdrCnt = 2;
541     }
542     ChkSpaces(SegBuffer, MomSegment);
543     if (FoundSize != -1)
544       ChkOpSize(FoundSize);
545   }
546 }
547 
AddFWait(Word * pCode)548 static void AddFWait(Word *pCode)
549 {
550   if (*pCode & NO_FWAIT_FLAG)
551     *pCode &= ~NO_FWAIT_FLAG;
552   else
553     AddPrefix(0x9b);
554 }
555 
FPUEntry(Word * pCode)556 static Boolean FPUEntry(Word *pCode)
557 {
558   if (!FPUAvail)
559   {
560     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
561     return FALSE;
562   }
563 
564   AddFWait(pCode);
565   return TRUE;
566 }
567 
568 /*---------------------------------------------------------------------------*/
569 
DecodeMOV(Word Index)570 static void DecodeMOV(Word Index)
571 {
572   Byte AdrByte;
573   UNUSED(Index);
574 
575   if (ChkArgCnt(2, 2))
576   {
577     DecodeAdr(&ArgStr[1]);
578     switch (AdrType)
579     {
580       case TypeReg8:
581       case TypeReg16:
582         AdrByte = AdrMode;
583         DecodeAdr(&ArgStr[2]);
584         switch (AdrType)
585         {
586           case TypeReg8:
587           case TypeReg16:
588             BAsmCode[CodeLen++] = 0x8a | OpSize;
589             BAsmCode[CodeLen++] = 0xc0 | (AdrByte << 3) | AdrMode;
590             break;
591           case TypeMem:
592             if ((AdrByte == 0) && (AdrMode == 6))
593             {
594               BAsmCode[CodeLen] = 0xa0 | OpSize;
595               MoveAdr(1);
596               CodeLen += 1 + AdrCnt;
597             }
598             else
599             {
600               BAsmCode[CodeLen++] = 0x8a | OpSize;
601               BAsmCode[CodeLen++] = AdrMode | (AdrByte << 3);
602               MoveAdr(0);
603               CodeLen += AdrCnt;
604             }
605             break;
606           case TypeRegSeg:
607             if (OpSize == 0) WrError(ErrNum_ConfOpSizes);
608             else
609             {
610               BAsmCode[CodeLen++] = 0x8c;
611               BAsmCode[CodeLen++] = 0xc0 | (AdrMode << 3) | AdrByte;
612             }
613             break;
614           case TypeImm:
615             BAsmCode[CodeLen++] = 0xb0 | (OpSize << 3) | AdrByte;
616             MoveAdr(0);
617             CodeLen += AdrCnt;
618             break;
619           default:
620             if (AdrType != TypeNone)
621               WrError(ErrNum_InvAddrMode);
622         }
623         break;
624       case TypeMem:
625          BAsmCode[CodeLen + 1] = AdrMode;
626          MoveAdr(2);
627          AdrByte = AdrCnt;
628          DecodeAdr(&ArgStr[2]);
629          switch (AdrType)
630          {
631            case TypeReg8:
632            case TypeReg16:
633             if ((AdrMode == 0) && (BAsmCode[CodeLen + 1] == 6))
634             {
635               BAsmCode[CodeLen] = 0xa2 | OpSize;
636               memmove(BAsmCode + CodeLen + 1, BAsmCode + CodeLen + 2, AdrByte);
637               CodeLen += 1 + AdrByte;
638             }
639             else
640             {
641               BAsmCode[CodeLen] = 0x88 | OpSize;
642               BAsmCode[CodeLen + 1] |= AdrMode << 3;
643               CodeLen += 2 + AdrByte;
644             }
645             break;
646           case TypeRegSeg:
647             BAsmCode[CodeLen] = 0x8c;
648             BAsmCode[CodeLen + 1] |= AdrMode << 3;
649             CodeLen += 2 + AdrByte;
650             break;
651           case TypeImm:
652             BAsmCode[CodeLen] = 0xc6 | OpSize;
653             MoveAdr(2 + AdrByte);
654             CodeLen += 2 + AdrByte + AdrCnt;
655             break;
656           default:
657             if (AdrType != TypeNone)
658               WrError(ErrNum_InvAddrMode);
659         }
660         break;
661       case TypeRegSeg:
662         BAsmCode[CodeLen + 1] = AdrMode << 3;
663         DecodeAdr(&ArgStr[2]);
664         switch (AdrType)
665         {
666           case TypeReg16:
667             BAsmCode[CodeLen++] = 0x8e;
668             BAsmCode[CodeLen++] |= 0xc0 + AdrMode;
669             break;
670           case TypeMem:
671             BAsmCode[CodeLen] = 0x8e;
672             BAsmCode[CodeLen + 1] |= AdrMode;
673             MoveAdr(2);
674             CodeLen += 2 + AdrCnt;
675             break;
676           default:
677             if (AdrType != TypeNone)
678               WrError(ErrNum_InvAddrMode);
679         }
680         break;
681       default:
682         if (AdrType != TypeNone)
683           WrError(ErrNum_InvAddrMode);
684     }
685   }
686   AddPrefixes();
687 }
688 
DecodeINCDEC(Word Index)689 static void DecodeINCDEC(Word Index)
690 {
691   if (ChkArgCnt(1, 1))
692   {
693     DecodeAdr(&ArgStr[1]);
694     switch (AdrType)
695     {
696       case TypeReg16:
697         BAsmCode[CodeLen] = 0x40 | AdrMode | Index;
698         CodeLen++;
699         break;
700       case TypeReg8:
701         BAsmCode[CodeLen] = 0xfe;
702         BAsmCode[CodeLen + 1] = 0xc0 | AdrMode | Index;
703         CodeLen += 2;
704         break;
705       case TypeMem:
706         MinOneIs0();
707         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
708         else
709         {
710           BAsmCode[CodeLen] = 0xfe | OpSize; /* ANSI :-0 */
711           BAsmCode[CodeLen + 1] = AdrMode | Index;
712           MoveAdr(2);
713           CodeLen += 2 + AdrCnt;
714         }
715         break;
716       default:
717         if (AdrType != TypeNone)
718           WrError(ErrNum_InvAddrMode);
719     }
720   }
721   AddPrefixes();
722 }
723 
DecodeINT(Word Index)724 static void DecodeINT(Word Index)
725 {
726   Boolean OK;
727   UNUSED(Index);
728 
729   if (ChkArgCnt(1, 1))
730   {
731     BAsmCode[CodeLen + 1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
732     if (OK)
733     {
734       if (BAsmCode[1] == 3)
735         BAsmCode[CodeLen++] = 0xcc;
736       else
737       {
738         BAsmCode[CodeLen] = 0xcd;
739         CodeLen += 2;
740       }
741     }
742   }
743   AddPrefixes();
744 }
745 
DecodeINOUT(Word Index)746 static void DecodeINOUT(Word Index)
747 {
748   if (ChkArgCnt(2, 2))
749   {
750     tStrComp *pPortArg = Index ? &ArgStr[1] : &ArgStr[2],
751              *pRegArg = Index ? &ArgStr[2] : &ArgStr[1];
752 
753     DecodeAdr(pRegArg);
754     switch (AdrType)
755     {
756       case TypeReg8:
757       case TypeReg16:
758         if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
759         else if (!as_strcasecmp(pPortArg->Str, "DX"))
760           BAsmCode[CodeLen++] = 0xec | OpSize | Index;
761         else
762         {
763           tEvalResult EvalResult;
764 
765           BAsmCode[CodeLen + 1] = EvalStrIntExpressionWithResult(pPortArg, UInt8, &EvalResult);
766           if (EvalResult.OK)
767           {
768             ChkSpace(SegIO, EvalResult.AddrSpaceMask);
769             BAsmCode[CodeLen] = 0xe4 | OpSize | Index;
770             CodeLen += 2;
771           }
772         }
773         break;
774       default:
775         if (AdrType != TypeNone)
776           WrError(ErrNum_InvAddrMode);
777     }
778   }
779   AddPrefixes();
780 }
781 
DecodeCALLJMP(Word Index)782 static void DecodeCALLJMP(Word Index)
783 {
784   Byte AdrByte;
785   Word AdrWord;
786   Boolean OK;
787 
788   if (ChkArgCnt(1, 1))
789   {
790     char *pAdr = ArgStr[1].Str;
791 
792     if (!strncmp(pAdr, "SHORT ", 6))
793     {
794       AdrByte = 2;
795       pAdr += 6;
796       KillPrefBlanks(pAdr);
797     }
798     else if ((!strncmp(pAdr, "LONG ", 5)) || (!strncmp(pAdr, "NEAR ", 5)))
799     {
800       AdrByte = 1;
801       pAdr +=  5;
802       KillPrefBlanks(pAdr);
803     }
804     else
805       AdrByte = 0;
806     OK = True;
807     if (Index == 0)
808     {
809       if (AdrByte == 2)
810       {
811         WrError(ErrNum_InvAddrMode);
812         OK = False;
813       }
814       else
815         AdrByte = 1;
816     }
817 
818     if (OK)
819     {
820       OpSize = 1;
821       DecodeAdr(&ArgStr[1]);
822       switch (AdrType)
823       {
824         case TypeReg16:
825           BAsmCode[0] = 0xff;
826           BAsmCode[1] = AdrMode | (0xd0 + (Index << 4));
827           CodeLen = 2;
828           break;
829         case TypeMem:
830           BAsmCode[0] = 0xff;
831           BAsmCode[1] = AdrMode | (0x10 + (Index << 4));
832           MoveAdr(2);
833           CodeLen = 2 + AdrCnt;
834           break;
835         case TypeImm:
836           ChkSpace(SegCode, ImmAddrSpaceMask);
837           AdrWord = (((Word) AdrVals[1]) << 8) | AdrVals[0];
838           if ((AdrByte == 2) || ((AdrByte == 0) && (AbleToSign(AdrWord - EProgCounter() - 2))))
839           {
840             AdrWord -= EProgCounter() + 2;
841             if (!AbleToSign(AdrWord)) WrError(ErrNum_DistTooBig);
842             else
843             {
844               BAsmCode[0] = 0xeb;
845               BAsmCode[1] = Lo(AdrWord);
846               CodeLen = 2;
847             }
848           }
849           else
850           {
851             AdrWord -= EProgCounter() + 3;
852             BAsmCode[0] = 0xe8 | Index;
853             BAsmCode[1] = Lo(AdrWord);
854             BAsmCode[2] = Hi(AdrWord);
855             CodeLen = 3;
856             AdrWord++;
857           }
858           break;
859         default:
860          if (AdrType != TypeNone)
861            WrError(ErrNum_InvAddrMode);
862       }
863     }
864   }
865   AddPrefixes();
866 }
867 
DecodePUSHPOP(Word Index)868 static void DecodePUSHPOP(Word Index)
869 {
870   if (ChkArgCnt(1, 1))
871   {
872     OpSize = 1; DecodeAdr(&ArgStr[1]);
873     switch (AdrType)
874     {
875       case TypeReg16:
876         BAsmCode[CodeLen] = 0x50 |  AdrMode | (Index << 3);
877         CodeLen++;
878         break;
879       case TypeRegSeg:
880         BAsmCode[CodeLen] = 0x06 | (AdrMode << 3) | Index;
881         CodeLen++;
882         break;
883       case TypeMem:
884         BAsmCode[CodeLen] = 0x8f;
885         BAsmCode[CodeLen + 1] = AdrMode;
886         if (Index == 0)
887         {
888           BAsmCode[CodeLen] += 0x70;
889           BAsmCode[CodeLen + 1] += 0x30;
890         }
891         MoveAdr(2);
892         CodeLen += 2 + AdrCnt;
893         break;
894       case TypeImm:
895         if (!ChkMinCPU(CPU80186));
896         else if (Index == 1) WrError(ErrNum_InvAddrMode);
897         else
898         {
899           BAsmCode[CodeLen] = 0x68;
900           BAsmCode[CodeLen + 1] = AdrVals[0];
901           if (Sgn(AdrVals[0]) == AdrVals[1])
902           {
903             BAsmCode[CodeLen] += 2;
904             CodeLen += 2;
905           }
906           else
907           {
908             BAsmCode[CodeLen + 2] = AdrVals[1];
909             CodeLen += 3;
910           }
911         }
912         break;
913       default:
914         if (AdrType != TypeNone)
915           WrError(ErrNum_InvAddrMode);
916     }
917   }
918   AddPrefixes();
919 }
920 
DecodeNOTNEG(Word Index)921 static void DecodeNOTNEG(Word Index)
922 {
923   if (ChkArgCnt(1, 1))
924   {
925     DecodeAdr(&ArgStr[1]);
926     MinOneIs0();
927     BAsmCode[CodeLen] = 0xf6 | OpSize;
928     BAsmCode[CodeLen + 1] = 0x10 | Index;
929     switch (AdrType)
930     {
931       case TypeReg8:
932       case TypeReg16:
933         BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
934         CodeLen += 2;
935         break;
936       case TypeMem:
937         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
938         else
939         {
940           BAsmCode[CodeLen + 1] |= AdrMode;
941           MoveAdr(2);
942           CodeLen += 2 + AdrCnt;
943         }
944         break;
945       default:
946         if (AdrType != TypeNone)
947           WrError(ErrNum_InvAddrMode);
948     }
949   }
950   AddPrefixes();
951 }
952 
DecodeRET(Word Index)953 static void DecodeRET(Word Index)
954 {
955   Word AdrWord;
956   Boolean OK;
957 
958   if (!ChkArgCnt(0, 1));
959   else if (ArgCnt == 0)
960     BAsmCode[CodeLen++] = 0xc3 | Index;
961   else
962   {
963     AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
964     if (OK)
965     {
966       BAsmCode[CodeLen++] = 0xc2 | Index;
967       BAsmCode[CodeLen++] = Lo(AdrWord);
968       BAsmCode[CodeLen++] = Hi(AdrWord);
969     }
970   }
971 }
972 
DecodeTEST(Word Index)973 static void DecodeTEST(Word Index)
974 {
975   Byte AdrByte;
976   UNUSED(Index);
977 
978   if (ChkArgCnt(2, 2))
979   {
980     DecodeAdr(&ArgStr[1]);
981     switch (AdrType)
982     {
983       case TypeReg8:
984       case TypeReg16:
985         BAsmCode[CodeLen + 1] = (AdrMode << 3);
986         DecodeAdr(&ArgStr[2]);
987         switch (AdrType)
988         {
989           case TypeReg8:
990           case TypeReg16:
991             BAsmCode[CodeLen + 1] += 0xc0 | AdrMode;
992             BAsmCode[CodeLen] = 0x84 | OpSize;
993             CodeLen += 2;
994             break;
995           case TypeMem:
996             BAsmCode[CodeLen + 1] |= AdrMode;
997             BAsmCode[CodeLen] = 0x84 | OpSize;
998             MoveAdr(2);
999             CodeLen += 2 + AdrCnt;
1000             break;
1001           case TypeImm:
1002             if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
1003             {
1004               BAsmCode[CodeLen] = 0xa8 | OpSize;
1005               MoveAdr(1);
1006               CodeLen += 1 + AdrCnt;
1007             }
1008             else
1009             {
1010               BAsmCode[CodeLen] = OpSize | 0xf6;
1011               BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) | 0xc0;
1012               MoveAdr(2);
1013               CodeLen += 2 + AdrCnt;
1014             }
1015             break;
1016           default:
1017             if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1018         }
1019         break;
1020       case TypeMem:
1021         BAsmCode[CodeLen + 1] = AdrMode;
1022         AdrByte = AdrCnt;
1023         MoveAdr(2);
1024         DecodeAdr(&ArgStr[2]);
1025         switch (AdrType)
1026         {
1027           case TypeReg8:
1028           case TypeReg16:
1029             BAsmCode[CodeLen] = 0x84 | OpSize;
1030             BAsmCode[CodeLen + 1] += (AdrMode << 3);
1031             CodeLen += 2 + AdrByte;
1032             break;
1033           case TypeImm:
1034             BAsmCode[CodeLen] = OpSize | 0xf6;
1035             MoveAdr(2 + AdrByte);
1036             CodeLen += 2 + AdrCnt + AdrByte;
1037             break;
1038           default:
1039             if (AdrType != TypeNone)
1040               WrError(ErrNum_InvAddrMode);
1041         }
1042         break;
1043       default:
1044         if (AdrType != TypeNone)
1045           WrError(ErrNum_InvAddrMode);
1046     }
1047   }
1048   AddPrefixes();
1049 }
1050 
DecodeXCHG(Word Index)1051 static void DecodeXCHG(Word Index)
1052 {
1053   Byte AdrByte;
1054   UNUSED(Index);
1055 
1056   if (ChkArgCnt(2, 2))
1057   {
1058     DecodeAdr(&ArgStr[1]);
1059     switch (AdrType)
1060     {
1061       case TypeReg8:
1062       case TypeReg16:
1063         AdrByte = AdrMode;
1064         DecodeAdr(&ArgStr[2]);
1065         switch (AdrType)
1066         {
1067           case TypeReg8:
1068           case TypeReg16:
1069             if ((OpSize == 1) && ((AdrMode == 0) || (AdrByte == 0)))
1070             {
1071               BAsmCode[CodeLen] = 0x90 | AdrMode | AdrByte;
1072               CodeLen++;
1073             }
1074             else
1075             {
1076               BAsmCode[CodeLen] = 0x86 | OpSize;
1077               BAsmCode[CodeLen+1] = AdrMode | 0xc0 | (AdrByte << 3);
1078               CodeLen += 2;
1079             }
1080             break;
1081           case TypeMem:
1082             BAsmCode[CodeLen] = 0x86 | OpSize;
1083             BAsmCode[CodeLen+1] = AdrMode | (AdrByte << 3);
1084             MoveAdr(2);
1085             CodeLen += AdrCnt + 2;
1086             break;
1087           default:
1088             if (AdrType != TypeNone)
1089               WrError(ErrNum_InvAddrMode);
1090         }
1091         break;
1092       case TypeMem:
1093         BAsmCode[CodeLen + 1] = AdrMode;
1094         MoveAdr(2);
1095         AdrByte = AdrCnt;
1096         DecodeAdr(&ArgStr[2]);
1097         switch (AdrType)
1098         {
1099           case TypeReg8:
1100           case TypeReg16:
1101             BAsmCode[CodeLen] = 0x86 | OpSize;
1102             BAsmCode[CodeLen+1] |= (AdrMode << 3);
1103             CodeLen += AdrByte + 2;
1104             break;
1105           default:
1106             if (AdrType != TypeNone)
1107               WrError(ErrNum_InvAddrMode);
1108         }
1109         break;
1110       default:
1111         if (AdrType != TypeNone)
1112           WrError(ErrNum_InvAddrMode);
1113     }
1114   }
1115   AddPrefixes();
1116 }
1117 
DecodeCALLJMPF(Word Index)1118 static void DecodeCALLJMPF(Word Index)
1119 {
1120   char *p;
1121   Word AdrWord;
1122   Boolean OK;
1123 
1124   if (ChkArgCnt(1, 1))
1125   {
1126     p = QuotPos(ArgStr[1].Str, ':');
1127     if (!p)
1128     {
1129       DecodeAdr(&ArgStr[1]);
1130       switch (AdrType)
1131       {
1132         case TypeMem:
1133           BAsmCode[CodeLen] = 0xff;
1134           BAsmCode[CodeLen + 1] = AdrMode | Hi(Index);
1135           MoveAdr(2);
1136           CodeLen += 2 + AdrCnt;
1137           break;
1138         default:
1139           if (AdrType != TypeNone)
1140             WrError(ErrNum_InvAddrMode);
1141       }
1142     }
1143     else
1144     {
1145       tStrComp SegArg, OffsArg;
1146 
1147       StrCompSplitRef(&SegArg, &OffsArg, &ArgStr[1], p);
1148       AdrWord = EvalStrIntExpression(&SegArg, UInt16, &OK);
1149       if (OK)
1150       {
1151         BAsmCode[CodeLen + 3] = Lo(AdrWord);
1152         BAsmCode[CodeLen + 4] = Hi(AdrWord);
1153         AdrWord = EvalStrIntExpression(&OffsArg, UInt16, &OK);
1154         if (OK)
1155         {
1156           BAsmCode[CodeLen + 1] = Lo(AdrWord);
1157           BAsmCode[CodeLen + 2] = Hi(AdrWord);
1158           BAsmCode[CodeLen] = Lo(Index);
1159           CodeLen += 5;
1160         }
1161       }
1162     }
1163   }
1164   AddPrefixes();
1165 }
1166 
DecodeENTER(Word Index)1167 static void DecodeENTER(Word Index)
1168 {
1169   Word AdrWord;
1170   Boolean OK;
1171   UNUSED(Index);
1172 
1173   if (!ChkArgCnt(2, 2));
1174   else if (ChkMinCPU(CPU80186))
1175   {
1176     AdrWord = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
1177     if (OK)
1178     {
1179       BAsmCode[CodeLen + 1] = Lo(AdrWord);
1180       BAsmCode[CodeLen + 2] = Hi(AdrWord);
1181       BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
1182       if (OK)
1183       {
1184         BAsmCode[CodeLen] = 0xc8;
1185         CodeLen += 4;
1186       }
1187     }
1188   }
1189   AddPrefixes();
1190 }
1191 
DecodeFixed(Word Index)1192 static void DecodeFixed(Word Index)
1193 {
1194   const FixedOrder *pOrder = FixedOrders + Index;
1195 
1196   if (ChkArgCnt(0, 0)
1197    && ChkMinCPU(pOrder->MinCPU))
1198     PutCode(pOrder->Code);
1199   AddPrefixes();
1200 }
1201 
DecodeALU2(Word Index)1202 static void DecodeALU2(Word Index)
1203 {
1204   Byte AdrByte;
1205 
1206   if (ChkArgCnt(2, 2))
1207   {
1208     DecodeAdr(&ArgStr[1]);
1209     switch (AdrType)
1210     {
1211       case TypeReg8:
1212       case TypeReg16:
1213         BAsmCode[CodeLen + 1] = AdrMode << 3;
1214         DecodeAdr(&ArgStr[2]);
1215         switch (AdrType)
1216         {
1217           case TypeReg8:
1218           case TypeReg16:
1219             BAsmCode[CodeLen + 1] |= 0xc0 | AdrMode;
1220             BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
1221             CodeLen += 2;
1222             break;
1223           case TypeMem:
1224             BAsmCode[CodeLen + 1] |= AdrMode;
1225             BAsmCode[CodeLen] = (Index << 3) | 2 | OpSize;
1226             MoveAdr(2);
1227             CodeLen += 2 + AdrCnt;
1228             break;
1229           case TypeImm:
1230             if (((BAsmCode[CodeLen+1] >> 3) & 7) == 0)
1231             {
1232               BAsmCode[CodeLen] = (Index << 3) | 4 | OpSize;
1233               MoveAdr(1);
1234               CodeLen += 1 + AdrCnt;
1235             }
1236             else
1237             {
1238               BAsmCode[CodeLen] = OpSize | 0x80;
1239               if ((OpSize == 1) && (Sgn(AdrVals[0]) == AdrVals[1]))
1240               {
1241                 AdrCnt = 1;
1242                 BAsmCode[CodeLen] |= 2;
1243               }
1244               BAsmCode[CodeLen + 1] = (BAsmCode[CodeLen + 1] >> 3) + 0xc0 + (Index << 3);
1245               MoveAdr(2);
1246               CodeLen += 2 + AdrCnt;
1247             }
1248             break;
1249           default:
1250             if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1251         }
1252         break;
1253       case TypeMem:
1254         BAsmCode[CodeLen + 1] = AdrMode;
1255         AdrByte = AdrCnt;
1256         MoveAdr(2);
1257         DecodeAdr(&ArgStr[2]);
1258         switch (AdrType)
1259         {
1260           case TypeReg8:
1261           case TypeReg16:
1262             BAsmCode[CodeLen] = (Index << 3) | OpSize;
1263             BAsmCode[CodeLen + 1] |= (AdrMode << 3);
1264             CodeLen += 2 + AdrByte;
1265             break;
1266           case TypeImm:
1267             BAsmCode[CodeLen] = OpSize | 0x80;
1268             if ((OpSize == 1) && (Sgn(AdrVals[0]) == AdrVals[1]))
1269             {
1270               AdrCnt = 1;
1271               BAsmCode[CodeLen] += 2;
1272             }
1273             BAsmCode[CodeLen + 1] += (Index << 3);
1274             MoveAdr(2 + AdrByte);
1275             CodeLen += 2 + AdrCnt + AdrByte;
1276             break;
1277           default:
1278             if (AdrType != TypeNone)
1279               WrError(ErrNum_InvAddrMode);
1280         }
1281         break;
1282       default:
1283         if (AdrType != TypeNone)
1284           WrError(ErrNum_InvAddrMode);
1285     }
1286   }
1287   AddPrefixes();
1288 }
1289 
DecodeRel(Word Index)1290 static void DecodeRel(Word Index)
1291 {
1292   const FixedOrder *pOrder = RelOrders + Index;
1293 
1294   if (ChkArgCnt(1, 1)
1295    && ChkMinCPU(pOrder->MinCPU))
1296   {
1297     tEvalResult EvalResult;
1298     Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], Int16, &EvalResult);
1299 
1300     if (EvalResult.OK)
1301     {
1302       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1303       AdrWord -= EProgCounter() + 2;
1304       if (Hi(pOrder->Code) != 0)
1305         AdrWord--;
1306       if ((AdrWord >= 0x80) && (AdrWord < 0xff80) && !mSymbolQuestionable(EvalResult.Flags)) WrError(ErrNum_JmpDistTooBig);
1307       else
1308       {
1309         PutCode(pOrder->Code);
1310         BAsmCode[CodeLen++] = Lo(AdrWord);
1311       }
1312     }
1313   }
1314 }
1315 
DecodeASSUME(void)1316 static void DecodeASSUME(void)
1317 {
1318   Boolean OK;
1319   int z, z2, z3;
1320   char *p;
1321   String SegPart, ValPart;
1322 
1323   if (ChkArgCnt(1, ArgCntMax))
1324   {
1325     z = 1 ; OK = True;
1326     while ((z <= ArgCnt) && (OK))
1327     {
1328       OK = False; p = QuotPos(ArgStr[z].Str, ':');
1329       if (p)
1330       {
1331         *p = '\0';
1332         strmaxcpy(SegPart, ArgStr[z].Str, STRINGSIZE);
1333         strmaxcpy(ValPart, p + 1, STRINGSIZE);
1334       }
1335       else
1336       {
1337         strmaxcpy(SegPart, ArgStr[z].Str, STRINGSIZE);
1338         *ValPart = '\0';
1339       }
1340       z2 = 0;
1341       while ((z2 <= SegRegCnt) && (as_strcasecmp(SegPart, SegRegNames[z2])))
1342         z2++;
1343       if (z2 > SegRegCnt) WrXError(ErrNum_UnknownSegReg, SegPart);
1344       else
1345       {
1346         z3 = 0;
1347         while ((z3 <= PCMax) && (as_strcasecmp(ValPart, SegNames[z3])))
1348           z3++;
1349         if (z3 > PCMax) WrXError(ErrNum_UnknownSegment, ValPart);
1350         else if ((z3 != SegCode) && (z3 != SegData) && (z3 != SegXData) && (z3 != SegNone)) WrError(ErrNum_InvSegment);
1351         else
1352         {
1353           SegAssumes[z2] = z3;
1354           OK = True;
1355         }
1356       }
1357       z++;
1358     }
1359   }
1360 }
1361 
DecodePORT(Word Code)1362 static void DecodePORT(Word Code)
1363 {
1364   UNUSED(Code);
1365 
1366   CodeEquate(SegIO, 0, 0xffff);
1367 }
1368 
DecodeFPUFixed(Word Code)1369 static void DecodeFPUFixed(Word Code)
1370 {
1371   if (!FPUEntry(&Code))
1372     return;
1373 
1374   if (ChkArgCnt(0, 0))
1375   {
1376     PutCode(Code);
1377     AddPrefixes();
1378   }
1379 }
1380 
DecodeFPUSt(Word Code)1381 static void DecodeFPUSt(Word Code)
1382 {
1383   if (!FPUEntry(&Code))
1384     return;
1385 
1386   if (ChkArgCnt(1, 1))
1387   {
1388     DecodeAdr(&ArgStr[1]);
1389     if (AdrType == TypeFReg)
1390     {
1391       PutCode(Code);
1392       BAsmCode[CodeLen-1] |= AdrMode;
1393       AddPrefixes();
1394     }
1395     else if (AdrType != TypeNone)
1396       WrError(ErrNum_InvAddrMode);
1397   }
1398 }
1399 
DecodeFLD(Word Code)1400 static void DecodeFLD(Word Code)
1401 {
1402   if (!FPUEntry(&Code))
1403     return;
1404 
1405   if (ChkArgCnt(1, 1))
1406   {
1407     DecodeAdr(&ArgStr[1]);
1408     switch (AdrType)
1409     {
1410       case TypeFReg:
1411         BAsmCode[CodeLen] = 0xd9;
1412         BAsmCode[CodeLen + 1] = 0xc0 | AdrMode;
1413         CodeLen += 2;
1414         break;
1415       case TypeMem:
1416         if ((OpSize == -1) && (UnknownFlag))
1417           OpSize = 2;
1418         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1419         else if (OpSize < 2) WrError(ErrNum_InvOpSize);
1420         else
1421         {
1422           MoveAdr(2);
1423           BAsmCode[CodeLen + 1] = AdrMode;
1424           switch (OpSize)
1425           {
1426             case 2:
1427               BAsmCode[CodeLen] = 0xd9;
1428               break;
1429             case 3:
1430               BAsmCode[CodeLen] = 0xdd;
1431               break;
1432             case 4:
1433               BAsmCode[CodeLen] = 0xdb;
1434               BAsmCode[CodeLen + 1] += 0x28;
1435               break;
1436           }
1437           CodeLen += 2+AdrCnt;
1438         }
1439         break;
1440       default:
1441         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1442     }
1443   }
1444   AddPrefixes();
1445 }
1446 
DecodeFILD(Word Code)1447 static void DecodeFILD(Word Code)
1448 {
1449   if (!FPUEntry(&Code))
1450     return;
1451 
1452   if (ChkArgCnt(1, 1))
1453   {
1454     DecodeAdr(&ArgStr[1]);
1455     switch (AdrType)
1456     {
1457       case TypeMem:
1458         if ((OpSize  == -1) && (UnknownFlag)) OpSize = 1;
1459         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1460         else if ((OpSize < 1) || (OpSize > 3)) WrError(ErrNum_InvOpSize);
1461         else
1462         {
1463           MoveAdr(2);
1464           BAsmCode[CodeLen + 1] = AdrMode;
1465           switch (OpSize)
1466           {
1467             case 1:
1468               BAsmCode[CodeLen] = 0xdf;
1469               break;
1470             case 2:
1471               BAsmCode[CodeLen] = 0xdb;
1472               break;
1473             case 3:
1474               BAsmCode[CodeLen] = 0xdf;
1475               BAsmCode[CodeLen + 1] |= 0x28;
1476               break;
1477           }
1478           CodeLen += 2 + AdrCnt;
1479         }
1480         break;
1481       default:
1482         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1483     }
1484   }
1485   AddPrefixes();
1486 }
1487 
DecodeFBLD(Word Code)1488 static void DecodeFBLD(Word Code)
1489 {
1490   if (!FPUEntry(&Code))
1491     return;
1492 
1493   if (ChkArgCnt(1, 1))
1494   {
1495     DecodeAdr(&ArgStr[1]);
1496     switch (AdrType)
1497     {
1498       case TypeMem:
1499         if ((OpSize == -1) && (UnknownFlag))
1500           OpSize = 4;
1501         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1502         else if (OpSize != 4) WrError(ErrNum_InvOpSize);
1503         else
1504         {
1505           BAsmCode[CodeLen] = 0xdf;
1506           MoveAdr(2);
1507           BAsmCode[CodeLen+1] = AdrMode+0x20;
1508           CodeLen += 2+AdrCnt;
1509         }
1510         break;
1511       default:
1512         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1513     }
1514   }
1515   AddPrefixes();
1516 }
1517 
DecodeFST_FSTP(Word Code)1518 static void DecodeFST_FSTP(Word Code)
1519 {
1520   if (!FPUEntry(&Code))
1521     return;
1522 
1523   if (ChkArgCnt(1, 1))
1524   {
1525     DecodeAdr(&ArgStr[1]);
1526     switch (AdrType)
1527     {
1528       case TypeFReg:
1529         BAsmCode[CodeLen] = 0xdd;
1530         BAsmCode[CodeLen + 1] = Code | AdrMode;
1531         CodeLen += 2;
1532         break;
1533       case TypeMem:
1534         if ((OpSize == -1) && (UnknownFlag))
1535           OpSize = 2;
1536         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1537         else if ((OpSize < 2) || ((OpSize == 4) && (Code == 0xd0))) WrError(ErrNum_InvOpSize);
1538         else
1539         {
1540           MoveAdr(2);
1541           BAsmCode[CodeLen + 1] = AdrMode | 0x10 | (Code & 8);
1542           switch (OpSize)
1543           {
1544             case 2:
1545               BAsmCode[CodeLen] = 0xd9;
1546               break;
1547             case 3:
1548               BAsmCode[CodeLen] = 0xdd;
1549               break;
1550             case 4:
1551               BAsmCode[CodeLen] = 0xdb;
1552               BAsmCode[CodeLen + 1] |= 0x20;
1553               break;
1554           }
1555           CodeLen += 2 + AdrCnt;
1556         }
1557         break;
1558       default:
1559         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1560     }
1561   }
1562   AddPrefixes();
1563 }
1564 
DecodeFIST_FISTP(Word Code)1565 static void DecodeFIST_FISTP(Word Code)
1566 {
1567   if (!FPUEntry(&Code))
1568     return;
1569 
1570   if (ChkArgCnt(1, 1))
1571   {
1572     DecodeAdr(&ArgStr[1]);
1573     switch (AdrType)
1574     {
1575       case TypeMem:
1576         if ((OpSize == -1) && (UnknownFlag)) OpSize = 1;
1577         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1578         else if ((OpSize < 1) || (OpSize == 4) || ((OpSize == 3) && (Code == 0x10))) WrError(ErrNum_InvOpSize);
1579         else
1580         {
1581           MoveAdr(2);
1582           BAsmCode[CodeLen + 1] = AdrMode | Code;
1583           switch (OpSize)
1584           {
1585             case 1:
1586               BAsmCode[CodeLen] = 0xdf;
1587               break;
1588             case 2:
1589               BAsmCode[CodeLen] = 0xdb;
1590               break;
1591             case 3:
1592               BAsmCode[CodeLen] = 0xdf;
1593               BAsmCode[CodeLen + 1] = 0x20;
1594               break;
1595           }
1596           CodeLen += 2 + AdrCnt;
1597         }
1598         break;
1599       default:
1600         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1601     }
1602   }
1603   AddPrefixes();
1604 }
1605 
DecodeFBSTP(Word Code)1606 static void DecodeFBSTP(Word Code)
1607 {
1608   if (!FPUEntry(&Code))
1609     return;
1610 
1611   if (ChkArgCnt(1, 1))
1612   {
1613     DecodeAdr(&ArgStr[1]);
1614     switch (AdrType)
1615     {
1616       case TypeMem:
1617         if ((OpSize == -1) && (UnknownFlag))
1618           OpSize = 1;
1619         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1620         else if (OpSize != 4) WrError(ErrNum_InvOpSize);
1621         else
1622         {
1623           BAsmCode[CodeLen] = 0xdf;
1624           BAsmCode[CodeLen + 1] = AdrMode | 0x30;
1625           MoveAdr(2);
1626           CodeLen += 2 + AdrCnt;
1627         }
1628         break;
1629       default:
1630         if (AdrType != TypeNone)
1631           WrError(ErrNum_InvAddrMode);
1632     }
1633   }
1634   AddPrefixes();
1635 }
1636 
DecodeFCOM_FCOMP(Word Code)1637 static void DecodeFCOM_FCOMP(Word Code)
1638 {
1639   if (!FPUEntry(&Code))
1640     return;
1641 
1642   if (ChkArgCnt(1, 1))
1643   {
1644     DecodeAdr(&ArgStr[1]);
1645     switch (AdrType)
1646     {
1647       case TypeFReg:
1648         BAsmCode[CodeLen] = 0xd8;
1649         BAsmCode[CodeLen+1] = Code | AdrMode;
1650         CodeLen += 2;
1651         break;
1652       case TypeMem:
1653         if ((OpSize == -1) && (UnknownFlag))
1654           OpSize = 1;
1655         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1656         else if ((OpSize != 2) && (OpSize != 3)) WrError(ErrNum_InvOpSize);
1657         else
1658         {
1659           BAsmCode[CodeLen] = (OpSize == 2) ? 0xd8 : 0xdc;
1660           BAsmCode[CodeLen + 1] = AdrMode | 0x10 | (Code & 8);
1661           MoveAdr(2);
1662           CodeLen += 2 + AdrCnt;
1663         }
1664         break;
1665       default:
1666         if (AdrType != TypeNone)
1667           WrError(ErrNum_InvAddrMode);
1668     }
1669   }
1670   AddPrefixes();
1671 }
1672 
DecodeFICOM_FICOMP(Word Code)1673 static void DecodeFICOM_FICOMP(Word Code)
1674 {
1675   if (!FPUEntry(&Code))
1676     return;
1677 
1678   if (ChkArgCnt(1, 1))
1679   {
1680     DecodeAdr(&ArgStr[1]);
1681     switch (AdrType)
1682     {
1683       case TypeMem:
1684         if ((OpSize == -1) && (UnknownFlag))
1685           OpSize = 1;
1686         if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1687         else if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
1688         else
1689         {
1690           BAsmCode[CodeLen] = (OpSize == 1) ? 0xde  : 0xda;
1691           BAsmCode[CodeLen+1] = AdrMode | Code;
1692           MoveAdr(2);
1693           CodeLen += 2 + AdrCnt;
1694         }
1695         break;
1696       default:
1697         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
1698     }
1699   }
1700   AddPrefixes();
1701 }
1702 
DecodeFADD_FMUL(Word Code)1703 static void DecodeFADD_FMUL(Word Code)
1704 {
1705   if (!FPUEntry(&Code))
1706     return;
1707 
1708   if (ArgCnt == 0)
1709   {
1710     BAsmCode[CodeLen] = 0xde;
1711     BAsmCode[CodeLen + 1] = 0xc1 + Code;
1712     CodeLen += 2;
1713   }
1714   else if (ChkArgCnt(0, 2))
1715   {
1716     const tStrComp *pArg1 = &ArgStr[1],
1717                    *pArg2 = &ArgStr[2];
1718 
1719     if (ArgCnt == 1)
1720     {
1721       pArg2 = &ArgStr[1];
1722       pArg1 = &ArgST;
1723     }
1724 
1725     DecodeAdr(pArg1);
1726     OpSize = -1;
1727     switch (AdrType)
1728     {
1729       case TypeFReg:
1730         if (AdrMode != 0)   /* ST(i) ist Ziel */
1731         {
1732           BAsmCode[CodeLen + 1] = AdrMode;
1733           DecodeAdr(pArg2);
1734           if ((AdrType != TypeFReg) || (AdrMode != 0)) WrError(ErrNum_InvAddrMode);
1735           else
1736           {
1737             BAsmCode[CodeLen] = 0xdc;
1738             BAsmCode[CodeLen + 1] += 0xc0 + Code;
1739             CodeLen += 2;
1740           }
1741         }
1742         else                      /* ST ist Ziel */
1743         {
1744           DecodeAdr(pArg2);
1745           switch (AdrType)
1746           {
1747             case TypeFReg:
1748               BAsmCode[CodeLen] = 0xd8;
1749               BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
1750               CodeLen += 2;
1751               break;
1752             case TypeMem:
1753               if ((OpSize == -1) && (UnknownFlag)) OpSize = 2;
1754               if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1755               else if ((OpSize != 2) && (OpSize != 3)) WrError(ErrNum_InvOpSize);
1756               else
1757               {
1758                 BAsmCode[CodeLen] = (OpSize == 2) ? 0xd8 : 0xdc;
1759                 BAsmCode[CodeLen + 1] = AdrMode + Code;
1760                 MoveAdr(2);
1761                 CodeLen += AdrCnt + 2;
1762               }
1763               break;
1764             default:
1765               if (AdrType != TypeNone)
1766                 WrError(ErrNum_InvAddrMode);
1767           }
1768         }
1769         break;
1770       default:
1771         if (AdrType != TypeNone)
1772           WrError(ErrNum_InvAddrMode);
1773     }
1774   }
1775   AddPrefixes();
1776 }
1777 
DecodeFIADD_FIMUL(Word Code)1778 static void DecodeFIADD_FIMUL(Word Code)
1779 {
1780   const tStrComp *pArg1 = &ArgStr[1],
1781                  *pArg2 = &ArgStr[2];
1782 
1783   if (!FPUEntry(&Code))
1784     return;
1785 
1786   if (ArgCnt == 1)
1787   {
1788     pArg2 = &ArgStr[1];
1789     pArg1 = &ArgST;
1790   }
1791   else if (ChkArgCnt(1, 2))
1792   {
1793     DecodeAdr(pArg1);
1794     switch (AdrType)
1795     {
1796       case TypeFReg:
1797         if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
1798         else
1799         {
1800           OpSize = -1;
1801           DecodeAdr(pArg2);
1802           if ((AdrType != TypeMem) && (AdrType != TypeNone)) WrError(ErrNum_InvAddrMode);
1803           else if (AdrType != TypeNone)
1804           {
1805             if ((OpSize == -1) && (UnknownFlag)) OpSize = 1;
1806             if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1807             else if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
1808             else
1809             {
1810               BAsmCode[CodeLen] = (OpSize == 1) ? 0xde : 0xda;
1811               BAsmCode[CodeLen+1] = AdrMode + Code;
1812               MoveAdr(2);
1813               CodeLen += 2 + AdrCnt;
1814             }
1815           }
1816         }
1817         break;
1818       default:
1819         if (AdrType != TypeNone)
1820           WrError(ErrNum_InvAddrMode);
1821     }
1822   }
1823   AddPrefixes();
1824 }
1825 
DecodeFADDP_FMULP(Word Code)1826 static void DecodeFADDP_FMULP(Word Code)
1827 {
1828   if (!FPUEntry(&Code))
1829     return;
1830 
1831   if (ChkArgCnt(2, 2))
1832   {
1833     DecodeAdr(&ArgStr[2]);
1834     switch (AdrType)
1835     {
1836       case TypeFReg:
1837         if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
1838         else
1839         {
1840           DecodeAdr(&ArgStr[1]);
1841           if ((AdrType != TypeFReg) && (AdrType != TypeNone)) WrError(ErrNum_InvAddrMode);
1842           else if (AdrType != TypeNone)
1843           {
1844             BAsmCode[CodeLen] = 0xde;
1845             BAsmCode[CodeLen + 1] = 0xc0 + AdrMode + Code;
1846             CodeLen += 2;
1847           }
1848         }
1849         break;
1850       default:
1851         if (AdrType != TypeNone)
1852           WrError(ErrNum_InvAddrMode);
1853     }
1854   }
1855   AddPrefixes();
1856 }
1857 
DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)1858 static void DecodeFSUB_FSUBR_FDIV_FDIVR(Word Code)
1859 {
1860   if (!FPUEntry(&Code))
1861     return;
1862 
1863   if (ArgCnt == 0)
1864   {
1865     BAsmCode[CodeLen] = 0xde;
1866     BAsmCode[CodeLen + 1] = 0xe1 + (Code ^ 8);
1867     CodeLen += 2;
1868   }
1869   else if (ChkArgCnt(0, 2))
1870   {
1871     const tStrComp *pArg1 = &ArgStr[1],
1872                    *pArg2 = &ArgStr[2];
1873 
1874     if (ArgCnt == 1)
1875     {
1876       pArg1 = &ArgST;
1877       pArg2 = &ArgStr[1];
1878     }
1879 
1880     DecodeAdr(pArg1);
1881     OpSize = -1;
1882     switch (AdrType)
1883     {
1884       case TypeFReg:
1885         if (AdrMode != 0)   /* ST(i) ist Ziel */
1886         {
1887           BAsmCode[CodeLen + 1] = AdrMode;
1888           DecodeAdr(pArg2);
1889           switch (AdrType)
1890           {
1891             case TypeFReg:
1892               if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
1893               else
1894               {
1895                 BAsmCode[CodeLen] = 0xdc;
1896                 BAsmCode[CodeLen + 1] += 0xe0 + (Code ^ 8);
1897                 CodeLen += 2;
1898               }
1899               break;
1900             default:
1901               if (AdrType != TypeNone)
1902                 WrError(ErrNum_InvAddrMode);
1903           }
1904         }
1905         else               /* ST ist Ziel */
1906         {
1907           DecodeAdr(pArg2);
1908           switch (AdrType)
1909           {
1910             case TypeFReg:
1911               BAsmCode[CodeLen] = 0xd8;
1912               BAsmCode[CodeLen + 1] = 0xe0 + AdrMode + Code;
1913               CodeLen += 2;
1914               break;
1915             case TypeMem:
1916               if ((OpSize == -1) && (UnknownFlag))
1917                 OpSize = 2;
1918               if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1919               else if ((OpSize != 2) && (OpSize != 3)) WrError(ErrNum_InvOpSize);
1920               else
1921               {
1922                 BAsmCode[CodeLen] = (OpSize == 2) ? 0xd8 : 0xdc;
1923                 BAsmCode[CodeLen + 1] = AdrMode + 0x20 + Code;
1924                 MoveAdr(2);
1925                 CodeLen += AdrCnt + 2;
1926               }
1927               break;
1928             default:
1929               if (AdrType != TypeNone)
1930                 WrError(ErrNum_InvAddrMode);
1931           }
1932         }
1933         break;
1934       default:
1935         if (AdrType != TypeNone)
1936           WrError(ErrNum_InvAddrMode);
1937     }
1938   }
1939   AddPrefixes();
1940 }
1941 
DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)1942 static void DecodeFISUB_FISUBR_FIDIV_FIDIVR(Word Code)
1943 {
1944   if (!FPUEntry(&Code))
1945     return;
1946 
1947   if (ChkArgCnt(1, 2))
1948   {
1949     const tStrComp *pArg1 = &ArgStr[1],
1950                    *pArg2 = &ArgStr[2];
1951 
1952     if (ArgCnt == 1)
1953     {
1954       pArg1 = &ArgST;
1955       pArg2 = &ArgStr[1];
1956     }
1957 
1958     DecodeAdr(pArg1);
1959     switch (AdrType)
1960     {
1961       case TypeFReg:
1962         if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
1963         else
1964         {
1965           OpSize = -1;
1966           DecodeAdr(pArg2);
1967           switch (AdrType)
1968           {
1969             case TypeMem:
1970               if ((OpSize == -1) && (UnknownFlag))
1971                 OpSize = 1;
1972               if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
1973               else if ((OpSize != 1) && (OpSize != 2)) WrError(ErrNum_InvOpSize);
1974               else
1975               {
1976                 BAsmCode[CodeLen] = (OpSize == 1) ? 0xde : 0xda;
1977                 BAsmCode[CodeLen + 1] = AdrMode + 0x20 + Code;
1978                 MoveAdr(2);
1979                 CodeLen += 2 + AdrCnt;
1980               }
1981               break;
1982             default:
1983               if (AdrType != TypeNone)
1984                 WrError(ErrNum_InvAddrMode);
1985           }
1986         }
1987         break;
1988       default:
1989         if (AdrType != TypeNone)
1990           WrError(ErrNum_InvAddrMode);
1991     }
1992   }
1993   AddPrefixes();
1994 }
1995 
DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)1996 static void DecodeFSUBP_FSUBRP_FDIVP_FDIVRP(Word Code)
1997 {
1998   if (!FPUEntry(&Code))
1999     return;
2000 
2001   if (ChkArgCnt(2, 2))
2002   {
2003     DecodeAdr(&ArgStr[2]);
2004     switch (AdrType)
2005     {
2006       case TypeFReg:
2007         if (AdrMode != 0) WrError(ErrNum_InvAddrMode);
2008         else
2009         {
2010           DecodeAdr(&ArgStr[1]);
2011           switch (AdrType)
2012           {
2013             case TypeFReg:
2014               BAsmCode[CodeLen] = 0xde;
2015               BAsmCode[CodeLen+1] = 0xe0 + AdrMode + (Code ^ 8);
2016               CodeLen += 2;
2017               break;
2018             default:
2019               if (AdrType != TypeNone)
2020                 WrError(ErrNum_InvAddrMode);
2021           }
2022         }
2023         break;
2024       default:
2025         if (AdrType != TypeNone)
2026           WrError(ErrNum_InvAddrMode);
2027     }
2028   }
2029   AddPrefixes();
2030 }
2031 
DecodeFPU16(Word Code)2032 static void DecodeFPU16(Word Code)
2033 {
2034   if (!FPUEntry(&Code))
2035     return;
2036 
2037   if (ChkArgCnt(1, 1))
2038   {
2039     OpSize = 1;
2040     DecodeAdr(&ArgStr[1]);
2041     switch (AdrType)
2042     {
2043       case TypeMem:
2044         PutCode(Code);
2045         BAsmCode[CodeLen - 1] += AdrMode;
2046         MoveAdr(0);
2047         CodeLen += AdrCnt;
2048         break;
2049       default:
2050         if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
2051     }
2052   }
2053   AddPrefixes();
2054 }
2055 
DecodeFSAVE_FRSTOR(Word Code)2056 static void DecodeFSAVE_FRSTOR(Word Code)
2057 {
2058   if (!FPUEntry(&Code))
2059     return;
2060 
2061   if (ChkArgCnt(1, 1))
2062   {
2063     DecodeAdr(&ArgStr[1]);
2064     switch (AdrType)
2065     {
2066       case TypeMem:
2067         BAsmCode[CodeLen] = 0xdd;
2068         BAsmCode[CodeLen + 1] = AdrMode + Code;
2069         MoveAdr(2);
2070         CodeLen += 2 + AdrCnt;
2071         break;
2072       default:
2073         if (AdrType != TypeNone)
2074           WrError(ErrNum_InvAddrMode);
2075     }
2076   }
2077   AddPrefixes();
2078 }
2079 
DecodeRept(Word Index)2080 static void DecodeRept(Word Index)
2081 {
2082   const FixedOrder *pOrder = ReptOrders + Index;
2083 
2084   if (ChkArgCnt(1, 1)
2085    && ChkMinCPU(pOrder->MinCPU))
2086   {
2087     int z2;
2088 
2089     for (z2 = 0; z2 < StringOrderCnt; z2++)
2090       if (!as_strcasecmp(StringOrders[z2].Name,ArgStr[1].Str))
2091         break;
2092     if (z2 >= StringOrderCnt) WrError(ErrNum_InvArg);
2093     else if (ChkMinCPU(StringOrders[z2].MinCPU))
2094     {
2095       PutCode(pOrder->Code);
2096       PutCode(StringOrders[z2].Code);
2097     }
2098   }
2099   AddPrefixes();
2100 }
2101 
DecodeMul(Word Index)2102 static void DecodeMul(Word Index)
2103 {
2104   Boolean OK;
2105   Word AdrWord;
2106 
2107   if (!ChkArgCnt(1, (1 == Index) ? 3 : 1)) /* IMUL only 2/3 ops */
2108     return;
2109 
2110   switch (ArgCnt)
2111   {
2112     case 1:
2113       DecodeAdr(&ArgStr[1]);
2114       switch (AdrType)
2115       {
2116         case TypeReg8:
2117         case TypeReg16:
2118           BAsmCode[CodeLen] = 0xf6 + OpSize;
2119           BAsmCode[CodeLen + 1] = 0xe0 + (Index << 3) + AdrMode;
2120           CodeLen += 2;
2121           break;
2122         case TypeMem:
2123           MinOneIs0();
2124           if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
2125           else
2126           {
2127             BAsmCode[CodeLen] = 0xf6 + OpSize;
2128             BAsmCode[CodeLen+1] = 0x20 + (Index << 3) + AdrMode;
2129             MoveAdr(2);
2130             CodeLen += 2 + AdrCnt;
2131           }
2132           break;
2133         default:
2134           if (AdrType != TypeNone) WrError(ErrNum_InvAddrMode);
2135       }
2136       break;
2137     case 2:
2138     case 3:
2139       if (ChkMinCPU(CPU80186))
2140       {
2141         tStrComp *pArg1 = &ArgStr[1],
2142                  *pArg2 = (ArgCnt == 2) ? &ArgStr[1] : &ArgStr[2],
2143                  *pArg3 = (ArgCnt == 2) ? &ArgStr[2] : &ArgStr[3];
2144 
2145         BAsmCode[CodeLen] = 0x69;
2146         DecodeAdr(pArg1);
2147         switch (AdrType)
2148         {
2149           case TypeReg16:
2150             BAsmCode[CodeLen + 1] = (AdrMode << 3);
2151             DecodeAdr(pArg2);
2152             if (AdrType == TypeReg16)
2153             {
2154               AdrType = TypeMem;
2155               AdrMode += 0xc0;
2156             }
2157             switch (AdrType)
2158             {
2159               case TypeMem:
2160                 BAsmCode[CodeLen + 1] += AdrMode;
2161                 MoveAdr(2);
2162                 AdrWord = EvalStrIntExpression(pArg3, Int16, &OK);
2163                 if (OK)
2164                 {
2165                   BAsmCode[CodeLen + 2 + AdrCnt] = Lo(AdrWord);
2166                   BAsmCode[CodeLen + 3 + AdrCnt] = Hi(AdrWord);
2167                   CodeLen += 2 + AdrCnt + 2;
2168                   if ((AdrWord >= 0xff80) || (AdrWord < 0x80))
2169                   {
2170                     CodeLen--;
2171                     BAsmCode[CodeLen-AdrCnt - 2 - 1] += 2;
2172                   }
2173                 }
2174                 break;
2175               default:
2176                 if (AdrType != TypeNone)
2177                   WrError(ErrNum_InvAddrMode);
2178             }
2179             break;
2180           default:
2181             if (AdrType != TypeNone)
2182               WrError(ErrNum_InvAddrMode);
2183         }
2184       }
2185       break;
2186   }
2187   AddPrefixes();
2188 }
2189 
DecodeModReg(Word Index)2190 static void DecodeModReg(Word Index)
2191 {
2192   Byte AdrByte;
2193   const FixedOrder *pOrder = ModRegOrders + Index;
2194 
2195   NoSegCheck = Hi(pOrder->Code) != 0;
2196   if (ChkArgCnt(2, 2)
2197    && ChkMinCPU(pOrder->MinCPU))
2198   {
2199     DecodeAdr(&ArgStr[1]);
2200     switch (AdrType)
2201     {
2202       case TypeReg16:
2203         OpSize = Hi(pOrder->Code) ? -1 : 2;
2204         AdrByte = (AdrMode << 3);
2205         DecodeAdr(&ArgStr[2]);
2206         switch (AdrType)
2207         {
2208           case TypeMem:
2209             PutCode(Lo(pOrder->Code));
2210             BAsmCode[CodeLen] = AdrByte + AdrMode;
2211             MoveAdr(1);
2212             CodeLen += 1 + AdrCnt;
2213             break;
2214           default:
2215             if (AdrType != TypeNone)
2216               WrError(ErrNum_InvAddrMode);
2217         }
2218         break;
2219       default:
2220         if (AdrType != TypeNone)
2221           WrError(ErrNum_InvAddrMode);
2222     }
2223   }
2224   AddPrefixes();
2225 }
2226 
DecodeShift(Word Index)2227 static void DecodeShift(Word Index)
2228 {
2229   const FixedOrder *pOrder = ShiftOrders + Index;
2230 
2231   if (ChkArgCnt(2, 2)
2232    && ChkMinCPU(pOrder->MinCPU))
2233   {
2234     DecodeAdr(&ArgStr[1]);
2235     MinOneIs0();
2236     if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
2237     else switch (AdrType)
2238     {
2239       case TypeReg8:
2240       case TypeReg16:
2241       case TypeMem:
2242         BAsmCode[CodeLen] = OpSize;
2243         BAsmCode[CodeLen + 1] = AdrMode + (pOrder->Code << 3);
2244         if (AdrType != TypeMem)
2245           BAsmCode[CodeLen + 1] += 0xc0;
2246         MoveAdr(2);
2247         if (!as_strcasecmp(ArgStr[2].Str, "CL"))
2248         {
2249           BAsmCode[CodeLen] += 0xd2;
2250           CodeLen += 2 + AdrCnt;
2251         }
2252         else
2253         {
2254           Boolean OK;
2255 
2256           BAsmCode[CodeLen + 2 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
2257           if (OK)
2258           {
2259             if (BAsmCode[CodeLen + 2 + AdrCnt] == 1)
2260             {
2261               BAsmCode[CodeLen] += 0xd0;
2262               CodeLen += 2 + AdrCnt;
2263             }
2264             else if (ChkMinCPU(CPU80186))
2265             {
2266               BAsmCode[CodeLen] += 0xc0;
2267               CodeLen += 3 + AdrCnt;
2268             }
2269           }
2270         }
2271         break;
2272       default:
2273         if (AdrType != TypeNone)
2274           WrError(ErrNum_InvAddrMode);
2275     }
2276   }
2277   AddPrefixes();
2278 }
2279 
DecodeROL4_ROR4(Word Code)2280 static void DecodeROL4_ROR4(Word Code)
2281 {
2282   if (ChkArgCnt(1, 1)
2283    && ChkMinCPU(CPUV30))
2284   {
2285     DecodeAdr(&ArgStr[1]);
2286     BAsmCode[CodeLen    ] = 0x0f;
2287     BAsmCode[CodeLen + 1] = Code;
2288     switch (AdrType)
2289     {
2290       case TypeReg8:
2291         BAsmCode[CodeLen+2] = 0xc0 + AdrMode;
2292         CodeLen += 3;
2293         break;
2294       case TypeMem:
2295         BAsmCode[CodeLen+2] = AdrMode;
2296         MoveAdr(3);
2297         CodeLen += 3 + AdrCnt;
2298         break;
2299       default:
2300         if (AdrType != TypeNone)
2301           WrError(ErrNum_InvAddrMode);
2302     }
2303   }
2304   AddPrefixes();
2305 }
2306 
DecodeBit1(Word Index)2307 static void DecodeBit1(Word Index)
2308 {
2309   if (ChkArgCnt(2, 2)
2310    && ChkMinCPU(CPUV30))
2311   {
2312     DecodeAdr(&ArgStr[1]);
2313     if ((AdrType == TypeReg8) || (AdrType == TypeReg16))
2314     {
2315       AdrMode += 0xc0;
2316       AdrType = TypeMem;
2317     }
2318     MinOneIs0();
2319     if (OpSize == -1) WrError(ErrNum_UndefOpSizes);
2320     else switch (AdrType)
2321     {
2322       case TypeMem:
2323         BAsmCode[CodeLen    ] = 0x0f;
2324         BAsmCode[CodeLen + 1] = 0x10 + (Index << 1) + OpSize;
2325         BAsmCode[CodeLen + 2] = AdrMode;
2326         MoveAdr(3);
2327         if (!as_strcasecmp(ArgStr[2].Str, "CL"))
2328           CodeLen += 3 + AdrCnt;
2329         else
2330         {
2331           Boolean OK;
2332 
2333           BAsmCode[CodeLen + 1] += 8;
2334           BAsmCode[CodeLen + 3 + AdrCnt] = EvalStrIntExpression(&ArgStr[2], Int4, &OK);
2335           if (OK)
2336             CodeLen += 4 + AdrCnt;
2337         }
2338         break;
2339       default:
2340         if (AdrType != TypeNone)
2341           WrError(ErrNum_InvAddrMode);
2342     }
2343   }
2344   AddPrefixes();
2345 }
2346 
DecodeINS_EXT(Word Code)2347 static void DecodeINS_EXT(Word Code)
2348 {
2349   if (ChkArgCnt(2, 2)
2350    && ChkMinCPU(CPUV30))
2351   {
2352     DecodeAdr(&ArgStr[1]);
2353     if (AdrType != TypeNone)
2354     {
2355       if (AdrType != TypeReg8) WrError(ErrNum_InvAddrMode);
2356       else
2357       {
2358         BAsmCode[CodeLen    ] = 0x0f;
2359         BAsmCode[CodeLen + 1] = Code;
2360         BAsmCode[CodeLen + 2] = 0xc0 + AdrMode;
2361         DecodeAdr(&ArgStr[2]);
2362         switch (AdrType)
2363         {
2364           case TypeReg8:
2365             BAsmCode[CodeLen + 2] += (AdrMode << 3);
2366             CodeLen += 3;
2367             break;
2368           case TypeImm:
2369             if (AdrVals[0] > 15) WrError(ErrNum_OverRange);
2370             else
2371             {
2372               BAsmCode[CodeLen + 1] += 8;
2373               BAsmCode[CodeLen + 3] = AdrVals[1];
2374               CodeLen += 4;
2375             }
2376             break;
2377           default:
2378             if (AdrType != TypeNone)
2379               WrError(ErrNum_InvAddrMode);
2380         }
2381       }
2382     }
2383   }
2384   AddPrefixes();
2385 }
2386 
DecodeFPO2(Word Code)2387 static void DecodeFPO2(Word Code)
2388 {
2389   UNUSED(Code);
2390 
2391   if (ChkArgCnt(1, 2)
2392    && ChkMinCPU(CPUV30))
2393   {
2394     Byte AdrByte;
2395     Boolean OK;
2396 
2397     AdrByte = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
2398     if (OK)
2399     {
2400       BAsmCode[CodeLen    ] = 0x66 + (AdrByte >> 3);
2401       BAsmCode[CodeLen + 1] = (AdrByte & 7) << 3;
2402       if (ArgCnt == 1)
2403       {
2404         BAsmCode[CodeLen + 1] += 0xc0;
2405         CodeLen += 2;
2406       }
2407       else
2408       {
2409         DecodeAdr(&ArgStr[2]);
2410         switch (AdrType)
2411         {
2412           case TypeReg8:
2413             BAsmCode[CodeLen + 1] += 0xc0 + AdrMode;
2414             CodeLen += 2;
2415             break;
2416           case TypeMem:
2417             BAsmCode[CodeLen + 1] += AdrMode;
2418             MoveAdr(2);
2419             CodeLen += 2 + AdrCnt;
2420             break;
2421           default:
2422             if (AdrType != TypeNone)
2423               WrError(ErrNum_InvAddrMode);
2424         }
2425       }
2426     }
2427   }
2428   AddPrefixes();
2429 }
2430 
DecodeBTCLR(Word Code)2431 static void DecodeBTCLR(Word Code)
2432 {
2433   UNUSED(Code);
2434 
2435   if (ChkArgCnt(3, 3)
2436    && ChkMinCPU(CPUV35))
2437   {
2438     Boolean OK;
2439 
2440     BAsmCode[CodeLen  ] = 0x0f;
2441     BAsmCode[CodeLen + 1] = 0x9c;
2442     BAsmCode[CodeLen + 2] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
2443     if (OK)
2444     {
2445       BAsmCode[CodeLen + 3] = EvalStrIntExpression(&ArgStr[2], UInt3, &OK);
2446       if (OK)
2447       {
2448         Word AdrWord;
2449         tSymbolFlags Flags;
2450 
2451         AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[3], Int16, &OK, & Flags) - (EProgCounter() + 5);
2452         if (OK)
2453         {
2454           if (!mSymbolQuestionable(Flags) && ((AdrWord > 0x7f) && (AdrWord < 0xff80))) WrError(ErrNum_DistTooBig);
2455           else
2456           {
2457             BAsmCode[CodeLen + 4] = Lo(AdrWord);
2458             CodeLen += 5;
2459           }
2460         }
2461       }
2462     }
2463   }
2464   AddPrefixes();
2465 }
2466 
DecodeReg16(Word Index)2467 static void DecodeReg16(Word Index)
2468 {
2469   const AddOrder *pOrder = Reg16Orders + Index;
2470 
2471   if (ChkArgCnt(1, 1))
2472   {
2473     DecodeAdr(&ArgStr[1]);
2474     switch (AdrType)
2475     {
2476       case TypeReg16:
2477         PutCode(pOrder->Code);
2478         BAsmCode[CodeLen++] = pOrder->Add + AdrMode;
2479         break;
2480       default:
2481         if (AdrType != TypeNone)
2482           WrError(ErrNum_InvAddrMode);
2483     }
2484   }
2485   AddPrefixes();
2486 }
2487 
DecodeString(Word Index)2488 static void DecodeString(Word Index)
2489 {
2490   const FixedOrder *pOrder = StringOrders + Index;
2491 
2492   if (ChkArgCnt(0, 0)
2493    && ChkMinCPU(pOrder->MinCPU))
2494     PutCode(pOrder->Code);
2495   AddPrefixes();
2496 }
2497 
2498 /*---------------------------------------------------------------------------*/
2499 
AddFPU(const char * NName,Word NCode,InstProc NProc)2500 static void AddFPU(const char *NName, Word NCode, InstProc NProc)
2501 {
2502   char Instr[30];
2503 
2504   AddInstTable(InstTable, NName, NCode, NProc);
2505   as_snprintf(Instr, sizeof(Instr), "%cN%s", *NName, NName + 1);
2506   AddInstTable(InstTable, Instr, NCode | NO_FWAIT_FLAG, NProc);
2507 }
2508 
AddFixed(const char * NName,CPUVar NMin,Word NCode)2509 static void AddFixed(const char *NName, CPUVar NMin, Word NCode)
2510 {
2511   if (InstrZ >= FixedOrderCnt) exit(255);
2512   FixedOrders[InstrZ].Code = NCode;
2513   FixedOrders[InstrZ].MinCPU = NMin;
2514   AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
2515 }
2516 
AddFPUFixed(const char * NName,Word NCode)2517 static void AddFPUFixed(const char *NName, Word NCode)
2518 {
2519   AddFPU(NName, NCode, DecodeFPUFixed);
2520 }
2521 
AddFPUSt(const char * NName,Word NCode)2522 static void AddFPUSt(const char *NName, Word NCode)
2523 {
2524   AddFPU(NName, NCode, DecodeFPUSt);
2525 }
2526 
AddFPU16(const char * NName,Word NCode)2527 static void AddFPU16(const char *NName, Word NCode)
2528 {
2529   AddFPU(NName, NCode, DecodeFPU16);
2530 }
2531 
AddString(const char * NName,CPUVar NMin,Word NCode)2532 static void AddString(const char *NName, CPUVar NMin, Word NCode)
2533 {
2534   if (InstrZ >= StringOrderCnt) exit(255);
2535   StringOrders[InstrZ].Name = NName;
2536   StringOrders[InstrZ].MinCPU = NMin;
2537   StringOrders[InstrZ].Code = NCode;
2538   AddInstTable(InstTable, NName, InstrZ++, DecodeString);
2539 }
2540 
AddRept(const char * NName,CPUVar NMin,Word NCode)2541 static void AddRept(const char *NName, CPUVar NMin, Word NCode)
2542 {
2543   if (InstrZ >= ReptOrderCnt) exit(255);
2544   ReptOrders[InstrZ].Code = NCode;
2545   ReptOrders[InstrZ].MinCPU = NMin;
2546   AddInstTable(InstTable, NName, InstrZ++, DecodeRept);
2547 }
2548 
AddRel(const char * NName,CPUVar NMin,Word NCode)2549 static void AddRel(const char *NName, CPUVar NMin, Word NCode)
2550 {
2551   if (InstrZ >= RelOrderCnt) exit(255);
2552   RelOrders[InstrZ].MinCPU = NMin;
2553   RelOrders[InstrZ].Code = NCode;
2554   AddInstTable(InstTable, NName, InstrZ++, DecodeRel);
2555 }
2556 
AddModReg(const char * NName,CPUVar NMin,Word NCode)2557 static void AddModReg(const char *NName, CPUVar NMin, Word NCode)
2558 {
2559   if (InstrZ >= ModRegOrderCnt) exit(255);
2560   ModRegOrders[InstrZ].MinCPU = NMin;
2561   ModRegOrders[InstrZ].Code = NCode;
2562   AddInstTable(InstTable, NName, InstrZ++, DecodeModReg);
2563 }
2564 
AddShift(const char * NName,CPUVar NMin,Word NCode)2565 static void AddShift(const char *NName, CPUVar NMin, Word NCode)
2566 {
2567   if (InstrZ >= ShiftOrderCnt) exit(255);
2568   ShiftOrders[InstrZ].MinCPU = NMin;
2569   ShiftOrders[InstrZ].Code = NCode;
2570   AddInstTable(InstTable, NName, InstrZ++, DecodeShift);
2571 }
2572 
AddReg16(const char * NName,CPUVar NMin,Word NCode,Byte NAdd)2573 static void AddReg16(const char *NName, CPUVar NMin, Word NCode, Byte NAdd)
2574 {
2575   if (InstrZ >= Reg16OrderCnt) exit(255);
2576   Reg16Orders[InstrZ].MinCPU = NMin;
2577   Reg16Orders[InstrZ].Code = NCode;
2578   Reg16Orders[InstrZ].Add = NAdd;
2579   AddInstTable(InstTable, NName, InstrZ++, DecodeReg16);
2580 }
2581 
InitFields(void)2582 static void InitFields(void)
2583 {
2584   InstTable = CreateInstTable(403);
2585   SetDynamicInstTable(InstTable);
2586 
2587   AddInstTable(InstTable, "MOV"  , 0, DecodeMOV);
2588   AddInstTable(InstTable, "INC"  , 0, DecodeINCDEC);
2589   AddInstTable(InstTable, "DEC"  , 8, DecodeINCDEC);
2590   AddInstTable(InstTable, "INT"  , 0, DecodeINT);
2591   AddInstTable(InstTable, "IN"   , 0, DecodeINOUT);
2592   AddInstTable(InstTable, "OUT"  , 2, DecodeINOUT);
2593   AddInstTable(InstTable, "CALL" , 0, DecodeCALLJMP);
2594   AddInstTable(InstTable, "JMP"  , 1, DecodeCALLJMP);
2595   AddInstTable(InstTable, "PUSH" , 0, DecodePUSHPOP);
2596   AddInstTable(InstTable, "POP"  , 1, DecodePUSHPOP);
2597   AddInstTable(InstTable, "NOT"  , 0, DecodeNOTNEG);
2598   AddInstTable(InstTable, "NEG"  , 8, DecodeNOTNEG);
2599   AddInstTable(InstTable, "RET"  , 0, DecodeRET);
2600   AddInstTable(InstTable, "RETF" , 8, DecodeRET);
2601   AddInstTable(InstTable, "TEST" , 0, DecodeTEST);
2602   AddInstTable(InstTable, "XCHG" , 0, DecodeXCHG);
2603   AddInstTable(InstTable, "CALLF", 0x189a, DecodeCALLJMPF);
2604   AddInstTable(InstTable, "JMPF" , 0x28ea, DecodeCALLJMPF);
2605   AddInstTable(InstTable, "ENTER", 0, DecodeENTER);
2606   AddInstTable(InstTable, "PORT", 0, DecodePORT);
2607   AddInstTable(InstTable, "ROL4", 0x28, DecodeROL4_ROR4);
2608   AddInstTable(InstTable, "ROR4", 0x2a, DecodeROL4_ROR4);
2609   AddInstTable(InstTable, "INS", 0x31, DecodeINS_EXT);
2610   AddInstTable(InstTable, "EXT", 0x33, DecodeINS_EXT);
2611   AddInstTable(InstTable, "FPO2", 0, DecodeFPO2);
2612   AddInstTable(InstTable, "BTCLR", 0, DecodeBTCLR);
2613   AddFPU("FLD", 0, DecodeFLD);
2614   AddFPU("FILD", 0, DecodeFILD);
2615   AddFPU("FBLD", 0, DecodeFBLD);
2616   AddFPU("FST", 0xd0, DecodeFST_FSTP);
2617   AddFPU("FSTP", 0xd8, DecodeFST_FSTP);
2618   AddFPU("FIST", 0x10, DecodeFIST_FISTP);
2619   AddFPU("FISTP", 0x18, DecodeFIST_FISTP);
2620   AddFPU("FBSTP", 0, DecodeFBSTP);
2621   AddFPU("FCOM", 0xd0, DecodeFCOM_FCOMP);
2622   AddFPU("FCOMP", 0xd8, DecodeFCOM_FCOMP);
2623   AddFPU("FICOM", 0x10, DecodeFICOM_FICOMP);
2624   AddFPU("FICOMP", 0x18, DecodeFICOM_FICOMP);
2625   AddFPU("FADD", 0, DecodeFADD_FMUL);
2626   AddFPU("FMUL", 8, DecodeFADD_FMUL);
2627   AddFPU("FIADD", 0, DecodeFIADD_FIMUL);
2628   AddFPU("FIMUL", 8, DecodeFIADD_FIMUL);
2629   AddFPU("FADDP", 0, DecodeFADDP_FMULP);
2630   AddFPU("FMULP", 8, DecodeFADDP_FMULP);
2631   AddFPU("FDIV" , 16, DecodeFSUB_FSUBR_FDIV_FDIVR);
2632   AddFPU("FDIVR", 24, DecodeFSUB_FSUBR_FDIV_FDIVR);
2633   AddFPU("FSUB" ,  0, DecodeFSUB_FSUBR_FDIV_FDIVR);
2634   AddFPU("FSUBR",  8, DecodeFSUB_FSUBR_FDIV_FDIVR);
2635   AddFPU("FIDIV" , 16, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
2636   AddFPU("FIDIVR", 24, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
2637   AddFPU("FISUB" ,  0, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
2638   AddFPU("FISUBR",  8, DecodeFISUB_FISUBR_FIDIV_FIDIVR);
2639   AddFPU("FDIVP" , 16, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
2640   AddFPU("FDIVRP", 24, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
2641   AddFPU("FSUBP" ,  0, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
2642   AddFPU("FSUBRP",  8, DecodeFSUBP_FSUBRP_FDIVP_FDIVRP);
2643   AddFPU("FSAVE" , 0x30, DecodeFSAVE_FRSTOR);
2644   AddFPU("FRSTOR" , 0x20, DecodeFSAVE_FRSTOR);
2645 
2646   FixedOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * FixedOrderCnt); InstrZ = 0;
2647   AddFixed("AAA",   CPU8086,  0x0037);  AddFixed("AAS",   CPU8086,  0x003f);
2648   AddFixed("AAM",   CPU8086,  0xd40a);  AddFixed("AAD",   CPU8086,  0xd50a);
2649   AddFixed("CBW",   CPU8086,  0x0098);  AddFixed("CLC",   CPU8086,  0x00f8);
2650   AddFixed("CLD",   CPU8086,  0x00fc);  AddFixed("CLI",   CPU8086,  0x00fa);
2651   AddFixed("CMC",   CPU8086,  0x00f5);  AddFixed("CWD",   CPU8086,  0x0099);
2652   AddFixed("DAA",   CPU8086,  0x0027);  AddFixed("DAS",   CPU8086,  0x002f);
2653   AddFixed("HLT",   CPU8086,  0x00f4);  AddFixed("INTO",  CPU8086,  0x00ce);
2654   AddFixed("IRET",  CPU8086,  0x00cf);  AddFixed("LAHF",  CPU8086,  0x009f);
2655   AddFixed("LOCK",  CPU8086,  0x00f0);  AddFixed("NOP",   CPU8086,  0x0090);
2656   AddFixed("POPF",  CPU8086,  0x009d);  AddFixed("PUSHF", CPU8086,  0x009c);
2657   AddFixed("SAHF",  CPU8086,  0x009e);  AddFixed("STC",   CPU8086,  0x00f9);
2658   AddFixed("STD",   CPU8086,  0x00fd);  AddFixed("STI",   CPU8086,  0x00fb);
2659   AddFixed("WAIT",  CPU8086,  0x009b);  AddFixed("XLAT",  CPU8086,  0x00d7);
2660   AddFixed("LEAVE", CPU80186, 0x00c9);  AddFixed("PUSHA", CPU80186, 0x0060);
2661   AddFixed("POPA",  CPU80186, 0x0061);  AddFixed("ADD4S", CPUV30,   0x0f20);
2662   AddFixed("SUB4S", CPUV30,   0x0f22);  AddFixed("CMP4S", CPUV30,   0x0f26);
2663   AddFixed("STOP",  CPUV35,   0x0f9e);  AddFixed("RETRBI",CPUV35,   0x0f91);
2664   AddFixed("FINT",  CPUV35,   0x0f92);  AddFixed("MOVSPA",CPUV35,   0x0f25);
2665   AddFixed("SEGES", CPU8086,  0x0026);  AddFixed("SEGCS", CPU8086,  0x002e);
2666   AddFixed("SEGSS", CPU8086,  0x0036);  AddFixed("SEGDS", CPU8086,  0x003e);
2667   AddFixed("FWAIT", CPU8086,  0x009b);
2668 
2669   AddFPUFixed("FCOMPP", 0xded9); AddFPUFixed("FTST",   0xd9e4);
2670   AddFPUFixed("FXAM",   0xd9e5); AddFPUFixed("FLDZ",   0xd9ee);
2671   AddFPUFixed("FLD1",   0xd9e8); AddFPUFixed("FLDPI",  0xd9eb);
2672   AddFPUFixed("FLDL2T", 0xd9e9); AddFPUFixed("FLDL2E", 0xd9ea);
2673   AddFPUFixed("FLDLG2", 0xd9ec); AddFPUFixed("FLDLN2", 0xd9ed);
2674   AddFPUFixed("FSQRT",  0xd9fa); AddFPUFixed("FSCALE", 0xd9fd);
2675   AddFPUFixed("FPREM",  0xd9f8); AddFPUFixed("FRNDINT",0xd9fc);
2676   AddFPUFixed("FXTRACT",0xd9f4); AddFPUFixed("FABS",   0xd9e1);
2677   AddFPUFixed("FCHS",   0xd9e0); AddFPUFixed("FPTAN",  0xd9f2);
2678   AddFPUFixed("FPATAN", 0xd9f3); AddFPUFixed("F2XM1",  0xd9f0);
2679   AddFPUFixed("FYL2X",  0xd9f1); AddFPUFixed("FYL2XP1",0xd9f9);
2680   AddFPUFixed("FINIT",  0xdbe3); AddFPUFixed("FENI",   0xdbe0);
2681   AddFPUFixed("FDISI",  0xdbe1); AddFPUFixed("FCLEX",  0xdbe2);
2682   AddFPUFixed("FINCSTP",0xd9f7); AddFPUFixed("FDECSTP",0xd9f6);
2683   AddFPUFixed("FNOP",   0xd9d0);
2684 
2685   AddFPUSt("FXCH",  0xd9c8);
2686   AddFPUSt("FFREE", 0xddc0);
2687 
2688   AddFPU16("FLDCW",  0xd928);
2689   AddFPU16("FSTCW",  0xd938);
2690   AddFPU16("FSTSW",  0xdd38);
2691   AddFPU16("FSTENV", 0xd930);
2692   AddFPU16("FLDENV", 0xd920);
2693 
2694   StringOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * StringOrderCnt); InstrZ = 0;
2695   AddString("CMPSB", CPU8086,  0x00a6);
2696   AddString("CMPSW", CPU8086,  0x00a7);
2697   AddString("LODSB", CPU8086,  0x00ac);
2698   AddString("LODSW", CPU8086,  0x00ad);
2699   AddString("MOVSB", CPU8086,  0x00a4);
2700   AddString("MOVSW", CPU8086,  0x00a5);
2701   AddString("SCASB", CPU8086,  0x00ae);
2702   AddString("SCASW", CPU8086,  0x00af);
2703   AddString("STOSB", CPU8086,  0x00aa);
2704   AddString("STOSW", CPU8086,  0x00ab);
2705   AddString("INSB",  CPU80186, 0x006c);
2706   AddString("INSW",  CPU80186, 0x006d);
2707   AddString("OUTSB", CPU80186, 0x006e);
2708   AddString("OUTSW", CPU80186, 0x006f);
2709 
2710   ReptOrders = (FixedOrder *) malloc(sizeof(*ReptOrders) * ReptOrderCnt); InstrZ = 0;
2711   AddRept("REP",   CPU8086,  0x00f3);
2712   AddRept("REPE",  CPU8086,  0x00f3);
2713   AddRept("REPZ",  CPU8086,  0x00f3);
2714   AddRept("REPNE", CPU8086,  0x00f2);
2715   AddRept("REPNZ", CPU8086,  0x00f2);
2716   AddRept("REPC",  CPUV30,   0x0065);
2717   AddRept("REPNC", CPUV30,   0x0064);
2718 
2719   RelOrders = (FixedOrder *) malloc(sizeof(*RelOrders) * RelOrderCnt); InstrZ = 0;
2720   AddRel("JA",    CPU8086, 0x0077); AddRel("JNBE",  CPU8086, 0x0077);
2721   AddRel("JAE",   CPU8086, 0x0073); AddRel("JNB",   CPU8086, 0x0073);
2722   AddRel("JB",    CPU8086, 0x0072); AddRel("JNAE",  CPU8086, 0x0072);
2723   AddRel("JBE",   CPU8086, 0x0076); AddRel("JNA",   CPU8086, 0x0076);
2724   AddRel("JC",    CPU8086, 0x0072); AddRel("JCXZ",  CPU8086, 0x00e3);
2725   AddRel("JE",    CPU8086, 0x0074); AddRel("JZ",    CPU8086, 0x0074);
2726   AddRel("JG",    CPU8086, 0x007f); AddRel("JNLE",  CPU8086, 0x007f);
2727   AddRel("JGE",   CPU8086, 0x007d); AddRel("JNL",   CPU8086, 0x007d);
2728   AddRel("JL",    CPU8086, 0x007c); AddRel("JNGE",  CPU8086, 0x007c);
2729   AddRel("JLE",   CPU8086, 0x007e); AddRel("JNG",   CPU8086, 0x007e);
2730   AddRel("JNC",   CPU8086, 0x0073); AddRel("JNE",   CPU8086, 0x0075);
2731   AddRel("JNZ",   CPU8086, 0x0075); AddRel("JNO",   CPU8086, 0x0071);
2732   AddRel("JNS",   CPU8086, 0x0079); AddRel("JNP",   CPU8086, 0x007b);
2733   AddRel("JPO",   CPU8086, 0x007b); AddRel("JO",    CPU8086, 0x0070);
2734   AddRel("JP",    CPU8086, 0x007a); AddRel("JPE",   CPU8086, 0x007a);
2735   AddRel("JS",    CPU8086, 0x0078); AddRel("LOOP",  CPU8086, 0x00e2);
2736   AddRel("LOOPE", CPU8086, 0x00e1); AddRel("LOOPZ", CPU8086, 0x00e1);
2737   AddRel("LOOPNE",CPU8086, 0x00e0); AddRel("LOOPNZ",CPU8086, 0x00e0);
2738 
2739   ModRegOrders = (FixedOrder *) malloc(sizeof(*ModRegOrders) * ModRegOrderCnt); InstrZ = 0;
2740   AddModReg("LDS",   CPU8086,  0x00c5);
2741   AddModReg("LEA",   CPU8086,  0x018d);
2742   AddModReg("LES",   CPU8086,  0x00c4);
2743   AddModReg("BOUND", CPU80186, 0x0062);
2744 
2745   ShiftOrders = (FixedOrder *) malloc(sizeof(*ShiftOrders) * ShiftOrderCnt); InstrZ = 0;
2746   AddShift("SHL",   CPU8086, 4); AddShift("SAL",   CPU8086, 4);
2747   AddShift("SHR",   CPU8086, 5); AddShift("SAR",   CPU8086, 7);
2748   AddShift("ROL",   CPU8086, 0); AddShift("ROR",   CPU8086, 1);
2749   AddShift("RCL",   CPU8086, 2); AddShift("RCR",   CPU8086, 3);
2750 
2751   Reg16Orders = (AddOrder *) malloc(sizeof(AddOrder) * Reg16OrderCnt); InstrZ = 0;
2752   AddReg16("BRKCS" , CPUV35, 0x0f2d, 0xc0);
2753   AddReg16("TSKSW" , CPUV35, 0x0f94, 0xf8);
2754   AddReg16("MOVSPB", CPUV35, 0x0f95, 0xf8);
2755 
2756   InstrZ = 0;
2757   AddInstTable(InstTable, "ADD", InstrZ++, DecodeALU2);
2758   AddInstTable(InstTable, "OR" , InstrZ++, DecodeALU2);
2759   AddInstTable(InstTable, "ADC", InstrZ++, DecodeALU2);
2760   AddInstTable(InstTable, "SBB", InstrZ++, DecodeALU2);
2761   AddInstTable(InstTable, "AND", InstrZ++, DecodeALU2);
2762   AddInstTable(InstTable, "SUB", InstrZ++, DecodeALU2);
2763   AddInstTable(InstTable, "XOR", InstrZ++, DecodeALU2);
2764   AddInstTable(InstTable, "CMP", InstrZ++, DecodeALU2);
2765 
2766   InstrZ = 0;
2767   AddInstTable(InstTable, "MUL" , InstrZ++, DecodeMul);
2768   AddInstTable(InstTable, "IMUL", InstrZ++, DecodeMul);
2769   AddInstTable(InstTable, "DIV" , InstrZ++, DecodeMul);
2770   AddInstTable(InstTable, "IDIV", InstrZ++, DecodeMul);
2771 
2772   InstrZ = 0;
2773   AddInstTable(InstTable, "TEST1", InstrZ++, DecodeBit1);
2774   AddInstTable(InstTable, "CLR1" , InstrZ++, DecodeBit1);
2775   AddInstTable(InstTable, "SET1" , InstrZ++, DecodeBit1);
2776   AddInstTable(InstTable, "NOT1" , InstrZ++, DecodeBit1);
2777 }
2778 
DeinitFields(void)2779 static void DeinitFields(void)
2780 {
2781   DestroyInstTable(InstTable);
2782   free(FixedOrders);
2783   free(ReptOrders);
2784   free(ShiftOrders);
2785   free(StringOrders);
2786   free(ModRegOrders);
2787   free(Reg16Orders);
2788   free(RelOrders);
2789 }
2790 
MakeCode_86(void)2791 static void MakeCode_86(void)
2792 {
2793   CodeLen = 0;
2794   DontPrint = False;
2795   OpSize = -1;
2796   PrefixLen = 0;
2797   NoSegCheck = False;
2798   UnknownFlag = False;
2799 
2800   /* zu ignorierendes */
2801 
2802   if (Memo(""))
2803     return;
2804 
2805   /* Pseudoanweisungen */
2806 
2807   if (DecodeIntelPseudo(False))
2808     return;
2809 
2810   /* vermischtes */
2811 
2812   if (!LookupInstTable(InstTable, OpPart.Str))
2813     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
2814 }
2815 
InitCode_86(void)2816 static void InitCode_86(void)
2817 {
2818   SegAssumes[0] = SegNone; /* ASSUME ES:NOTHING */
2819   SegAssumes[1] = SegCode; /* ASSUME CS:CODE */
2820   SegAssumes[2] = SegNone; /* ASSUME SS:NOTHING */
2821   SegAssumes[3] = SegData; /* ASSUME DS:DATA */
2822 }
2823 
IsDef_86(void)2824 static Boolean IsDef_86(void)
2825 {
2826   return (Memo("PORT"));
2827 }
2828 
SwitchFrom_86(void)2829 static void SwitchFrom_86(void)
2830 {
2831   DeinitFields();
2832   ClearONOFF();
2833 }
2834 
SwitchTo_86(void)2835 static void SwitchTo_86(void)
2836 {
2837   TurnWords = False; ConstMode = ConstModeIntel;
2838 
2839   PCSymbol = "$"; HeaderID = 0x42; NOPCode = 0x90;
2840   DivideChars = ","; HasAttrs = False;
2841 
2842   ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegXData) | (1 << SegIO);
2843   Grans[SegCode ] = 1; ListGrans[SegCode ] = 1; SegInits[SegCode ] = 0;
2844   SegLimits[SegCode ] = 0xffff;
2845   Grans[SegData ] = 1; ListGrans[SegData ] = 1; SegInits[SegData ] = 0;
2846   SegLimits[SegData ] = 0xffff;
2847   Grans[SegXData] = 1; ListGrans[SegXData] = 1; SegInits[SegXData] = 0;
2848   SegLimits[SegXData] = 0xffff;
2849   Grans[SegIO   ] = 1; ListGrans[SegIO   ] = 1; SegInits[SegIO   ] = 0;
2850   SegLimits[SegIO   ] = 0xffff;
2851 
2852   pASSUMEOverride = DecodeASSUME;
2853 
2854   MakeCode = MakeCode_86; IsDef = IsDef_86;
2855   SwitchFrom = SwitchFrom_86; InitFields();
2856   AddONOFF("FPU",&FPUAvail,FPUAvailName,False);
2857 }
2858 
code86_init(void)2859 void code86_init(void)
2860 {
2861   CPU8086  = AddCPU("8086" ,SwitchTo_86);
2862   CPU80186 = AddCPU("80186",SwitchTo_86);
2863   CPUV30   = AddCPU("V30"  ,SwitchTo_86);
2864   CPUV35   = AddCPU("V35"  ,SwitchTo_86);
2865 
2866   AddInitPassProc(InitCode_86);
2867 }
2868