1 /* codeh16.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Code Generator Hitachi H16                                                */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 
13 #include <string.h>
14 #include <ctype.h>
15 
16 #include "bpemu.h"
17 #include "strutil.h"
18 #include "chunks.h"
19 #include "headids.h"
20 #include "asmdef.h"
21 #include "asmsub.h"
22 #include "asmpars.h"
23 #include "asmallg.h"
24 #include "asmitree.h"
25 #include "asmstructs.h"
26 #include "codepseudo.h"
27 #include "motpseudo.h"
28 #include "codevars.h"
29 #include "errmsg.h"
30 #include "nls.h"
31 
32 #include "codeh16.h"
33 
34 /*---------------------------------------------------------------------------*/
35 
36 static CPUVar CPU641016;
37 static tSymbolSize OpSize;
38 static tStrComp FormatPart;
39 
40 #define REG_SP 15
41 #define REG_MARK 16
42 
43 typedef enum
44 {
45   eAdrModeNone = -1,
46   eAdrModeReg = 0,
47   eAdrModeIReg = 1,
48   eAdrModePost = 2,
49   eAdrModePre = 3,
50   eAdrModeImm = 4,
51   eAdrModeAbs = 5,
52   eAdrModeIRegScale = 6,
53   eAdrModeIdxScale = 7,
54   eAdrModePCIdxScale = 8,
55   eAdrModePCRel = 9,
56   eAdrModeDoubleIndir = 10
57 } tAdrMode;
58 
59 #define MModeReg (1 << eAdrModeReg)
60 #define MModeIReg (1 << eAdrModeIReg)
61 #define MModePost (1 << eAdrModePost)
62 #define MModePre (1 << eAdrModePre)
63 #define MModeImm (1 << eAdrModeImm)
64 #define MModeAbs (1 << eAdrModeAbs)
65 #define MModeIRegScale (1 << eAdrModeIRegScale)
66 #define MModeIdxScale (1 << eAdrModeIdxScale)
67 #define MModePCIdxScale (1 << eAdrModePCIdxScale)
68 #define MModePCRel (1 << eAdrModePCRel)
69 #define MModeDoubleIndir (1 << eAdrModeDoubleIndir)
70 #define MModeAll (MModeReg | MModeIReg | MModePost | MModePre | MModeImm | MModeAbs | MModeIRegScale | MModeIdxScale | MModePCIdxScale | MModePCRel | MModeDoubleIndir)
71 
72 typedef enum
73 {
74   eFormatNone,
75   eFormatG,
76   eFormatQ,
77   eFormatR,
78   eFormatRQ,
79   eFormatF  /* no source-side format; used for MOV->MOVF conversion */
80 } tFormat;
81 
82 #ifdef __cplusplus
83 # include "codeh16.hpp"
84 #endif
85 
86 typedef struct
87 {
88   tAdrMode Mode;
89   unsigned Cnt;
90   Byte Vals[10];
91 } tAdrVals;
92 
93 #define NOREG 255
94 #define PCREG 254
95 #define NormalReg(Reg) ((Reg) <= 15)
96 #define DefIndexRegSize eSymbolSize32Bit /* correct? */
97 
98 #define PREFIX_CRn 0x70
99 #define PREFIX_PRn 0x74
100 
101 #define eSymbolSize5Bit ((tSymbolSize)-2)  /* for shift cnt/bit pos arg */
102 #define eSymbolSize4Bit ((tSymbolSize)-3)  /* for bit pos arg */
103 #define eSymbolSize3Bit ((tSymbolSize)-4)  /* for bit pos arg */
104 
105 typedef struct
106 {
107   LongInt OuterDisp, InnerDisp;
108   Boolean OuterDispPresent, InnerDispPresent;
109   tSymbolSize OuterDispSize, InnerDispSize;
110   Byte BaseReg, IndexReg, InnerReg;
111   ShortInt BaseRegIncr, IndexRegSize;
112   Byte IndexRegScale;
113   Byte RegPrefix;
114 } tAdrComps;
115 
116 /*---------------------------------------------------------------------------*/
117 
118 /*!------------------------------------------------------------------------
119  * \fn     SetOpSize(tSymbolSize NewOpSize)
120  * \brief  set (instruction) operand size; complain if size mismatch
121  * \param  NewOpSize size to set
122  * \return True if setting/confirmation succeeded
123  * ------------------------------------------------------------------------ */
124 
SetOpSize(tSymbolSize NewOpSize)125 static Boolean SetOpSize(tSymbolSize NewOpSize)
126 {
127   if ((OpSize != eSymbolSizeUnknown) && (NewOpSize != OpSize))
128   {
129     WrError(ErrNum_ConfOpSizes);
130     return False;
131   }
132   OpSize = NewOpSize;
133   return True;
134 }
135 
136 /*!------------------------------------------------------------------------
137  * \fn     ChkOpSize(tSymbolSize DefaultSize, Word Mask)
138  * \brief  possibly set & check instruction operand size
139  * \param  DefaultSize size to set if size is unknown so far
140  * \param  Mask bit mask of allowed sizes (8/16/32 -> bit 0/1/2)
141  * \return True if operand size is OK
142  * ------------------------------------------------------------------------ */
143 
ChkOpSize(tSymbolSize DefaultSize,Word Mask)144 static Boolean ChkOpSize(tSymbolSize DefaultSize, Word Mask)
145 {
146   if (OpSize == eSymbolSizeUnknown)
147     OpSize = DefaultSize;
148   if (!((Mask >> OpSize) & 1))
149   {
150     WrError(ErrNum_InvOpSize);
151     return False;
152   }
153   return True;
154 }
155 
156 /*!------------------------------------------------------------------------
157  * \fn     DecodeFormat(unsigned FormatMask)
158  * \brief  decode instruction's format to internal enum
159  * \param  FormatMask bit mask of allowed formats
160  * \return resulting format or FormatNone if unknown/disallowed
161  * ------------------------------------------------------------------------ */
162 
DecodeFormat(unsigned FormatMask)163 static tFormat DecodeFormat(unsigned FormatMask)
164 {
165   static const char Formats[][3] = { "G", "Q", "R", "RQ", "" };
166   tFormat Result;
167 
168   FormatMask >>= 1;
169   for (Result = (tFormat)0; *Formats[Result]; Result++, FormatMask >>= 1)
170     if ((FormatMask & 1) && !as_strcasecmp(FormatPart.Str, Formats[Result]))
171       return Result + 1;
172   return eFormatNone;
173 }
174 
175 /*!------------------------------------------------------------------------
176  * \fn     ChkEmptyFormat(void)
177  * \brief  check whether no format spec was given and complain if there is one
178  * \return True if no format spec was given
179  * ------------------------------------------------------------------------ */
180 
ChkEmptyFormat(void)181 static Boolean ChkEmptyFormat(void)
182 {
183   if (*FormatPart.Str)
184   {
185     WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
186     return False;
187   }
188   return True;
189 }
190 
191 /*!------------------------------------------------------------------------
192  * \fn     ResetAdrVals(tAdrVals *pAdrVals)
193  * \brief  reset tAdrVals structure to initial state
194  * \param  pAdrVals struct to reset
195  * ------------------------------------------------------------------------ */
196 
ResetAdrVals(tAdrVals * pAdrVals)197 static void ResetAdrVals(tAdrVals *pAdrVals)
198 {
199   pAdrVals->Mode = eAdrModeNone;
200   pAdrVals->Cnt = 0;
201 }
202 
203 /*!------------------------------------------------------------------------
204  * \fn     AppendAdrVals(tAdrVals *pAdrVals, Byte Value)
205  * \brief  append another byte to tAdrVals' expansion byte list; check for overflow
206  * \param  pAdrVals AdrVals to extend
207  * \param  Value new value to append
208  * ------------------------------------------------------------------------ */
209 
AppendAdrVals(tAdrVals * pAdrVals,Byte Value)210 static void AppendAdrVals(tAdrVals *pAdrVals, Byte Value)
211 {
212   if (pAdrVals->Cnt >= (sizeof(pAdrVals->Vals) / sizeof(*pAdrVals->Vals)))
213   {
214     WrError(ErrNum_CodeOverflow);
215     return;
216   }
217   pAdrVals->Vals[pAdrVals->Cnt++] = Value;
218 }
219 
220 /*!------------------------------------------------------------------------
221  * \fn     AppendRegPrefix(tAdrVals *pAdrVals, Byte RegPrefix)
222  * \brief  append register prefix to tAdrVals if not a global bank register
223  * \param  pAdrVals AdrVals to extend
224  * \param  RegPrefix register prefix (0x70/0x74 or 0x00 for no prefix)
225  * ------------------------------------------------------------------------ */
226 
AppendRegPrefix(tAdrVals * pAdrVals,Byte RegPrefix)227 static void AppendRegPrefix(tAdrVals *pAdrVals, Byte RegPrefix)
228 {
229   if (RegPrefix)
230     AppendAdrVals(pAdrVals, RegPrefix);
231 }
232 
233 /*!------------------------------------------------------------------------
234  * \fn     AppendBySize(Byte *pDest, LongInt Value, tSymbolSize OpSize)
235  * \brief  append an integer value to byte array, BE order
236  * \param  pDest where to write
237  * \param  Value integer value to append
238  * \param  OpSize operand size of value (3/4/5/8/16/32 bits)
239  * \return # of bytes appended
240  * ------------------------------------------------------------------------ */
241 
GetH16SymbolSizeBytes(tSymbolSize Size)242 static unsigned GetH16SymbolSizeBytes(tSymbolSize Size)
243 {
244   return (Size <= eSymbolSize5Bit) ? 1 : GetSymbolSizeBytes(Size);
245 }
246 
AppendBySize(Byte * pDest,LongInt Value,tSymbolSize OpSize)247 static unsigned AppendBySize(Byte *pDest, LongInt Value, tSymbolSize OpSize)
248 {
249   int z;
250   unsigned Cnt = GetH16SymbolSizeBytes(OpSize);
251 
252   for (z = Cnt - 1; z >= 0; z--)
253   {
254     pDest[z] = Value & 0xff;
255     Value >>= 8;
256   }
257   return Cnt;
258 }
259 
260 /*!------------------------------------------------------------------------
261  * \fn     AppendToAdrValsBySize(tAdrVals *pAdrVals, LongInt Value, tSymbolSize OpSize)
262  * \brief  append an integer value to tAdrVals
263  * \param  pAdrVals AdrVals to extend
264  * \param  Value integer value to append
265  * \param  OpSize operand size of value (3/4/5/8/16/32 bits)
266  * ------------------------------------------------------------------------ */
267 
AppendToAdrValsBySize(tAdrVals * pAdrVals,LongInt Value,tSymbolSize OpSize)268 static void AppendToAdrValsBySize(tAdrVals *pAdrVals, LongInt Value, tSymbolSize OpSize)
269 {
270   unsigned Cnt = GetH16SymbolSizeBytes(OpSize);
271 
272   if ((pAdrVals->Cnt + Cnt) > (sizeof(pAdrVals->Vals) / sizeof(*pAdrVals->Vals)))
273   {
274     WrError(ErrNum_CodeOverflow);
275     return;
276   }
277   AppendBySize(pAdrVals->Vals + pAdrVals->Cnt, Value, OpSize);
278   pAdrVals->Cnt += Cnt;
279 }
280 
281 /*!------------------------------------------------------------------------
282  * \fn     ResetAdrComps(tAdrComps *pComps)
283  * \brief  reset indirect address parser context to empty state
284  * \param  pComps context to reset
285  * ------------------------------------------------------------------------ */
286 
ResetAdrComps(tAdrComps * pComps)287 static void ResetAdrComps(tAdrComps *pComps)
288 {
289   pComps->OuterDisp = pComps->InnerDisp = 0;
290   pComps->OuterDispPresent = pComps->InnerDispPresent = False;
291   pComps->OuterDispSize = pComps->InnerDispSize = eSymbolSizeUnknown;
292   pComps->BaseReg = pComps->IndexReg = pComps->InnerReg = NOREG;
293   pComps->IndexRegScale = pComps->BaseRegIncr = 0;
294   pComps->IndexRegSize = DefIndexRegSize;
295   pComps->RegPrefix = 0x00;
296 }
297 
298 /*!------------------------------------------------------------------------
299  * \fn     SplitOpSize(tStrComp *pArg, tSymbolSize *pSize)
300  * \brief  split off explicit size spec from argument
301  * \param  pArg argument to treat
302  * \param  pSize resulting size if suffix was present
303  * \return True if a suffix was split off
304  * ------------------------------------------------------------------------ */
305 
SplitOpSize(tStrComp * pArg,tSymbolSize * pSize)306 static Boolean SplitOpSize(tStrComp *pArg, tSymbolSize *pSize)
307 {
308   static const char Suffixes[][4] = { ".B", ":8", ".W", ":16", ".L", ":32" };
309   int l = strlen(pArg->Str), l2;
310   unsigned z;
311 
312   for (z = 0; z < sizeof(Suffixes) / sizeof(*Suffixes); z++)
313   {
314     l2 = strlen(Suffixes[z]);
315     if ((l > l2) && !as_strcasecmp(pArg->Str + l - l2, Suffixes[z]))
316     {
317       StrCompShorten(pArg, l2);
318       *pSize = (tSymbolSize)(z / 2);
319       return True;
320     }
321   }
322   return False;
323 }
324 
325 /*!------------------------------------------------------------------------
326  * \fn     SplitScale(tStrComp *pArg, Byte *pScale)
327  * \brief  split off scaling option from (register) argument
328  * \param  pArg argument to treat
329  * \param  pScale resulting scale if suffix was present
330  * \return True if a suffix was split off
331  * ------------------------------------------------------------------------ */
332 
333 static const char ScaleSuffixes[][3] = { "*1", "*2", "*4", "*8" };
334 
SplitScale(tStrComp * pArg,Byte * pScale)335 static char SplitScale(tStrComp *pArg, Byte *pScale)
336 {
337   int l = strlen(pArg->Str);
338   unsigned z;
339 
340   if (l >= 2)
341     for (z = 0; z < sizeof(ScaleSuffixes) / sizeof(*ScaleSuffixes); z++)
342       if (!as_strcasecmp(pArg->Str + l - 2, ScaleSuffixes[z]))
343       {
344         StrCompShorten(pArg, 2);
345         *pScale = z;
346         return *ScaleSuffixes[z];
347       }
348   return '\0';
349 }
350 
351 /*!------------------------------------------------------------------------
352  * \fn     AppendScale(tStrComp *pArg, Byte Scale)
353  * \brief  append scaling option to (register) argument
354  * \param  pArg argument to augment by scaling
355  * \param  Scale Scale to append
356  * ------------------------------------------------------------------------ */
357 
AppendScale(tStrComp * pArg,Byte Scale)358 static void AppendScale(tStrComp *pArg, Byte Scale)
359 {
360   strcat(pArg->Str, ScaleSuffixes[Scale]);
361   pArg->Pos.Len += 2;
362 }
363 
364 /*!------------------------------------------------------------------------
365  * \fn     DecodeRegCore(const char *pArg, Byte *pResult, Byte *pPrefix)
366  * \brief  check whether argument is a register and return register # if yes
367  * \param  pArg argument to check
368  * \param  pResult register # if argument is a valid (general) register
369  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
370  * \return True if argument is a register
371  * ------------------------------------------------------------------------ */
372 
DecodeRegCore(const char * pArg,Byte * pResult,Byte * pPrefix)373 static Boolean DecodeRegCore(const char *pArg, Byte *pResult, Byte *pPrefix)
374 {
375   Boolean OK;
376 
377   if (!as_strcasecmp(pArg, "SP"))
378   {
379     *pResult = REG_MARK | REG_SP;
380     *pPrefix = 0x00;
381     return True;
382   }
383 
384   if ((strlen(pArg) > 1)
385    && (as_toupper(*pArg) == 'R'))
386     *pPrefix = 0x00;
387   else if ((strlen(pArg) > 2)
388    && (as_toupper(*pArg) == 'C')
389    && (as_toupper(pArg[1]) == 'R'))
390     *pPrefix = PREFIX_CRn;
391   else if ((strlen(pArg) > 2)
392    && (as_toupper(*pArg) == 'P')
393    && (as_toupper(pArg[1]) == 'R'))
394     *pPrefix = PREFIX_PRn;
395   else
396     return False;
397 
398   *pResult = ConstLongInt(pArg + 1 + !!*pPrefix, &OK, 10);
399   return (OK && (*pResult <= 15));
400 }
401 
402 /*!------------------------------------------------------------------------
403  * \fn     DissectReg_H16(char *pDest, size_t DestSize, tRegInt Reg, tSymbolSize Size)
404  * \brief  dissect register symbols - H16 variant
405  * \param  pDest destination buffer
406  * \param  DestSize size of destination buffer
407  * \param  Reg register number
408  * \param  Size register size
409  * ------------------------------------------------------------------------ */
410 
DissectReg_H16(char * pDest,size_t DestSize,tRegInt Reg,tSymbolSize Size)411 static void DissectReg_H16(char *pDest, size_t DestSize, tRegInt Reg, tSymbolSize Size)
412 {
413   switch (Size)
414   {
415     case eSymbolSize32Bit:
416       if (Reg == (REG_MARK | REG_SP))
417         as_snprintf(pDest, DestSize, "SP");
418       else
419       {
420         if (Hi(Reg) == PREFIX_CRn)
421           as_snprintf(pDest, DestSize, "CR");
422         else if (Hi(Reg) == PREFIX_PRn)
423           as_snprintf(pDest, DestSize, "PR");
424         else if (!Hi(Reg))
425           as_snprintf(pDest, DestSize, "R");
426         else
427           as_snprintf(pDest, DestSize, "%u-", Hi(Reg));
428         as_snprcatf(pDest, DestSize, "%u", Lo(Reg));
429       }
430       break;
431     default:
432       as_snprintf(pDest, DestSize, "%d-%u", Size, Reg);
433   }
434 }
435 
436 /*!------------------------------------------------------------------------
437  * \fn     DecodeReg(const tStrComp *pArg, Byte *pReg, Byte *pPrefix, Boolean AllowPrefix, Boolean MustBeReg)
438  * \brief  check whether argument is CPU register or register alias
439  * \param  pArg source argument
440  * \param  pReg register number
441  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
442  * \param  AllowPrefix allow previous/current bank registers
443  * \param  MustBeReg argument must be register
444  * \return True if argument is a register
445  * ------------------------------------------------------------------------ */
446 
DecodeReg(const tStrComp * pArg,Byte * pReg,Byte * pPrefix,Boolean AllowPrefix,Boolean MustBeReg)447 static tRegEvalResult DecodeReg(const tStrComp *pArg, Byte *pReg, Byte *pPrefix, Boolean AllowPrefix, Boolean MustBeReg)
448 {
449   tRegDescr RegDescr;
450   tEvalResult EvalResult;
451   tRegEvalResult RegEvalResult;
452 
453   if (DecodeRegCore(pArg->Str, pReg, pPrefix))
454     RegEvalResult = eIsReg;
455   else
456   {
457     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
458     *pPrefix = Hi(RegDescr.Reg);
459     *pReg = Lo(RegDescr.Reg);
460   }
461 
462   if (RegEvalResult == eIsReg)
463   {
464     if (!AllowPrefix && *pPrefix)
465     {
466       WrStrErrorPos(ErrNum_InvReg, pArg);
467       RegEvalResult = MustBeReg ? eIsNoReg : eRegAbort;
468     }
469   }
470   *pReg &= ~REG_MARK;
471   return RegEvalResult;
472 }
473 
474 /*!------------------------------------------------------------------------
475  * \fn     DecodeRegList(Word *pDest, int StartIdx, int StopIdx)
476  * \brief  parse a register list
477  * \param  pDest destination buffer for register bit field
478  * \param  StartIdx index of first argument of list
479  * \param  StopIdx index of last argument of list
480  * \return True if parsing succeeded
481  * ------------------------------------------------------------------------ */
482 
DecodeRegList(Word * pDest,int StartIdx,int StopIdx)483 static Boolean DecodeRegList(Word *pDest, int StartIdx, int StopIdx)
484 {
485   int Index;
486   char *pSep;
487   Byte RegStart, RegStop, Prefix;
488   Word Mask;
489 
490   *pDest = 0;
491   for (Index = StartIdx; Index <= StopIdx; Index++)
492   {
493     pSep = strchr(ArgStr[Index].Str, '-');
494     if (pSep)
495     {
496       tStrComp StartComp, StopComp;
497 
498       StrCompSplitRef(&StartComp, &StopComp, &ArgStr[Index], pSep);
499       KillPostBlanksStrComp(&StartComp);
500       KillPrefBlanksStrCompRef(&StopComp);
501       if (!DecodeReg(&StartComp, &RegStart, &Prefix, False, True))
502         return False;
503       if (!DecodeReg(&StopComp, &RegStop, &Prefix, False, True))
504         return False;
505       if (RegStart > RegStop)
506       {
507         Prefix = RegStart;
508         RegStart = RegStop;
509         RegStop = Prefix;
510       }
511       Mask = ((1ul << (RegStop + 1)) - 1) & ~((1ul << (RegStart)) - 1);
512     }
513     else
514     {
515       if (!DecodeReg(&ArgStr[Index], &RegStart, &Prefix, False, True))
516         return False;
517       Mask = 1ul << RegStart;
518     }
519     if (*pDest & Mask)
520     {
521       WrStrErrorPos(ErrNum_DoubleReg, &ArgStr[Index]);
522       return False;
523     }
524     *pDest |= Mask;
525   }
526   return True;
527 }
528 
529 /*!------------------------------------------------------------------------
530  * \fn     DecodeRegWithSize(const tStrComp *pArg, Byte *pReg, tSymbolSize *pSize, Byte *pPrefix, Boolean MustBeReg)
531  * \brief  check whether argument is register with possible size spec
532  * \param  pArg argument to check
533  * \param  pReg returns register # if argument is a register
534  * \param  pSize returns size spec if argument is a register (may be SizeUnknown)
535  * \param  pPrefix prefix for previous/current bank registers; 0 for global bank registers
536  * \param  MustBeReg argument must be register
537  * \return RegEval result
538  * ------------------------------------------------------------------------ */
539 
DecodeRegWithSize(const tStrComp * pArg,Byte * pReg,tSymbolSize * pSize,Byte * pPrefix,Boolean MustBeReg)540 static tRegEvalResult DecodeRegWithSize(const tStrComp *pArg, Byte *pReg, tSymbolSize *pSize, Byte *pPrefix, Boolean MustBeReg)
541 {
542   String Str;
543   tStrComp Copy;
544 
545   StrCompMkTemp(&Copy, Str);
546   StrCompCopy(&Copy, pArg);
547   if (!SplitOpSize(&Copy, pSize))
548     *pSize = eSymbolSizeUnknown;
549   return DecodeReg(&Copy, pReg, pPrefix, True, MustBeReg);
550 }
551 
552 /*!------------------------------------------------------------------------
553  * \fn     CheckSup(const tStrComp *pArg)
554  * \brief  check whether supervisor mode is enabled and warn if not
555  * \param  pArg possible argument to print if sup mode is not enabled
556  * \return True (only a warning, no error)
557  * ------------------------------------------------------------------------ */
558 
CheckSup(const tStrComp * pArg)559 static Boolean CheckSup(const tStrComp *pArg)
560 {
561   if (!SupAllowed)
562     WrStrErrorPos(ErrNum_PrivOrder, pArg);
563   return True;
564 }
565 
566 /*!------------------------------------------------------------------------
567  * \fn     DecodeCReg(const tStrComp *pArg, Byte *pResult)
568  * \brief  check whether argument id a control register
569  * \param  pArg argument to check
570  * \param  pResult control register # if argument is a control register
571  * \return True if argument is a control register
572  * ------------------------------------------------------------------------ */
573 
574 typedef struct
575 {
576   const char *pName;
577   Byte Code;
578   tSymbolSize Size;
579 } tCReg;
580 
581 static const tCReg CRegs[] =
582 {
583   { "CCR"  , 0x20, eSymbolSize8Bit  },
584   { "VBNR" , 0x01, eSymbolSize8Bit  },
585   { "CBNR" , 0x40, eSymbolSize32Bit },
586   { "BSP"  , 0x41, eSymbolSize32Bit },
587   { "BMR"  , 0x80, eSymbolSize8Bit  },
588   { "GBNR" , 0x81, eSymbolSize8Bit  },
589   { "SR"   , 0xa0, eSymbolSize16Bit },
590   { "EBR"  , 0xc0, eSymbolSize32Bit },
591   { "RBR"  , 0xc1, eSymbolSize32Bit },
592   { "USP"  , 0xc2, eSymbolSize32Bit },
593   { "IBR"  , 0xc3, eSymbolSize32Bit },
594   { NULL   , 0x00, eSymbolSizeUnknown },
595 };
596 
DecodeCReg(const tStrComp * pArg,Byte * pResult)597 static Boolean DecodeCReg(const tStrComp *pArg, Byte *pResult)
598 {
599   const tCReg *pReg;
600 
601   for (pReg = CRegs; pReg->pName; pReg++)
602     if (!as_strcasecmp(pArg->Str, pReg->pName))
603     {
604       if ((pReg->Code & 0x80) && !CheckSup(pArg))
605         return False;
606       if (!SetOpSize(pReg->Size))
607         return False;
608       *pResult = pReg->Code;
609       return True;
610     }
611   WrStrErrorPos(ErrNum_InvCtrlReg, pArg);
612   return False;
613 }
614 
615 /*!------------------------------------------------------------------------
616  * \fn     DeduceSize(LongInt Value)
617  * \brief  deduce minimum operand size needed to represent value, assuming sign-extension
618  * \param  Value value to judge
619  * \return resulting minimum size
620  * ------------------------------------------------------------------------ */
621 
DeduceSize(LongInt Value)622 static tSymbolSize DeduceSize(LongInt Value)
623 {
624   if ((Value >= -128) && (Value <= 127))
625     return eSymbolSize8Bit;
626   if ((Value >= -32768) && (Value <= 32767))
627     return eSymbolSize16Bit;
628   return eSymbolSize32Bit;
629 }
630 
631 /*!------------------------------------------------------------------------
632  * \fn     DeduceSize8_32(LongInt Value)
633  * \brief  similar to DeduceSize, but excluding 16 bits
634  * \param  Value value to judge
635  * \return resulting minimum size
636  * ------------------------------------------------------------------------ */
637 
DeduceSize8_32(LongInt Value)638 static tSymbolSize DeduceSize8_32(LongInt Value)
639 {
640   if ((Value >= -128) && (Value <= 127))
641     return eSymbolSize8Bit;
642   return eSymbolSize32Bit;
643 }
644 
645 /*!------------------------------------------------------------------------
646  * \fn     ChkSize(LongInt Value, tSymbolSize OpSize)
647  * \brief  check whether given value can be represented with given size, assuming sign extension
648  * \param  Value value to judge
649  * \param  OpSize proposed operand size
650  * \return True if value can be represented with this size
651  * ------------------------------------------------------------------------ */
652 
ChkSize(LongInt Value,tSymbolSize OpSize)653 static Boolean ChkSize(LongInt Value, tSymbolSize OpSize)
654 {
655   switch (OpSize)
656   {
657     case eSymbolSize8Bit: return ChkRange(Value, -128, 127);
658     case eSymbolSize16Bit: return ChkRange(Value, -32768, 32767);
659     default: return True;
660   }
661 }
662 
663 /*!------------------------------------------------------------------------
664  * \fn     DeduceSize16M(LongInt Value)
665  * \brief  deduce minimum size to represent memory address, assuming sign-extension
666  * \param  Value address to judge
667  * \return minimum operand size (8/16/32)
668  * ------------------------------------------------------------------------ */
669 
DeduceSize16M(LongInt Value)670 static tSymbolSize DeduceSize16M(LongInt Value)
671 {
672   LongWord TmpVal;
673 
674   TmpVal = Value & 0xff;
675   if (TmpVal & 0x80) TmpVal |= 0xffffff00;
676   if ((TmpVal & 0xffffff) == ((LongWord)Value & 0xffffff))
677     return eSymbolSize8Bit;
678 
679   TmpVal = Value & 0xffff;
680   if (TmpVal & 0x8000) TmpVal |= 0xff0000;
681   if ((TmpVal & 0xffffff) == ((LongWord)Value & 0xffffff))
682     return eSymbolSize16Bit;
683 
684   return eSymbolSize32Bit;
685 }
686 
687 /*!------------------------------------------------------------------------
688  * \fn     ChkSize16M(LongInt Value, tSymbolSize OpSize)
689  * \brief  check whether given memory address can be represented with given size, assuming sign extension
690  * \param  Value address to judge
691  * \param  OpSize proposed operand size
692  * \return True if value can be represented with this size
693  * ------------------------------------------------------------------------ */
694 
ChkSize16M(LongInt Value,tSymbolSize OpSize)695 static Boolean ChkSize16M(LongInt Value, tSymbolSize OpSize)
696 {
697   LongWord TmpVal;
698   Boolean OK;
699 
700   switch (OpSize)
701   {
702     case eSymbolSize8Bit:
703       TmpVal = Value & 0xff;
704       if (TmpVal & 0x80) TmpVal |= 0xffffff00;
705       break;
706     case eSymbolSize16Bit:
707       TmpVal = Value & 0xffff;
708       if (TmpVal & 0x8000) TmpVal |= 0xff0000;
709       break;
710     default:
711       TmpVal = Value;
712   }
713   OK = (Value & 0xffffff) == (TmpVal & 0xffffff);
714   if (!OK)
715     WrError(ErrNum_OverRange);
716   return OK;
717 }
718 
719 /*!------------------------------------------------------------------------
720  * \fn     DeduceSizePCRel(LongInt AbsAddr, LongInt DispAddr)
721  * \brief  deduce minimum size to represent memory address as distance, assuming PC-relative addressing
722  * \param  AbsAddr absolute memory addess in question
723  * \param  DispAddr address of PC-relative displacement in code
724  * \return minimum displacement size (8/16/32)
725  * ------------------------------------------------------------------------ */
726 
DeduceSizePCRel(LongInt AbsAddr,LongInt DispAddr)727 static tSymbolSize DeduceSizePCRel(LongInt AbsAddr, LongInt DispAddr)
728 {
729   LongInt PCValue, Dist;
730 
731   PCValue = DispAddr + 1;
732   Dist = PCValue - AbsAddr;
733   if ((Dist >= -128) && (Dist <= 127))
734     return eSymbolSize8Bit;
735   PCValue = DispAddr + 2;
736   Dist = PCValue - AbsAddr;
737   if ((Dist >= -32768) && (Dist <= 32767))
738     return eSymbolSize16Bit;
739   return eSymbolSize32Bit;
740 }
741 
742 /*!------------------------------------------------------------------------
743  * \fn     ChkSizePCRelDisplacement(LongInt *pAbsAddr, tSymbolSize SymbolSize, LongInt DispAddr)
744  * \brief  check whether given address can be represented with given size, assuming PC-relative addressing
745  * \param  pAbsAddr (in) absolute memory addess in question (out) resulting displacement
746  * \param  SymbolSize proposed displacement size
747  * \param  DispAddr address of PC-relative displacement in code
748  * \return True if value can be represented with this size and displacement was computed
749  * ------------------------------------------------------------------------ */
750 
ChkSizePCRelDisplacement(LongInt * pAbsAddr,tSymbolSize SymbolSize,LongInt DispAddr)751 static Boolean ChkSizePCRelDisplacement(LongInt *pAbsAddr, tSymbolSize SymbolSize, LongInt DispAddr)
752 {
753   switch (SymbolSize)
754   {
755     case eSymbolSize8Bit:
756       *pAbsAddr -= DispAddr + 1;
757       return ChkRange(*pAbsAddr, -128, 127);
758     case eSymbolSize16Bit:
759       *pAbsAddr -= DispAddr + 2;
760       return ChkRange(*pAbsAddr, -32768, 32767);
761     case eSymbolSize32Bit:
762       *pAbsAddr -= DispAddr + 4;
763       return True;
764     default:
765       return False;
766   }
767 }
768 
769 /*!------------------------------------------------------------------------
770  * \fn     ChkSizePCRelBranch(const tStrComp *pArg, LongInt *pAbsAddr, tSymbolSize SymbolSize, tSymbolFlags Flags, LongInt DispAddr)
771  * \brief  same as ChkSizePCRel(), but use error messages appropriate for branches
772  * \param  pAbsAddr (in) destination address of branch  (out) resulting displacement
773  * \param  SymbolSize proposed displacement size
774  * \param  Flags symbol flags returned along with pAbsAddr
775  * \param  DispAddr address of PC-relative displacement in code
776  * \return True if displacement can be represented with this size and was computed
777  * ------------------------------------------------------------------------ */
778 
ChkSizePCRelBranch(const tStrComp * pArg,LongInt * pAbsAddr,tSymbolSize SymbolSize,tSymbolFlags Flags,LongInt DispAddr)779 static Boolean ChkSizePCRelBranch(const tStrComp *pArg, LongInt *pAbsAddr, tSymbolSize SymbolSize, tSymbolFlags Flags, LongInt DispAddr)
780 {
781   Boolean OK;
782 
783   switch (SymbolSize)
784   {
785     case eSymbolSize8Bit:
786       *pAbsAddr -= DispAddr + 1;
787       OK = mSymbolQuestionable(Flags) || RangeCheck(*pAbsAddr, SInt8);
788       break;
789     case eSymbolSize16Bit:
790       *pAbsAddr -= DispAddr + 2;
791       OK = mSymbolQuestionable(Flags) || RangeCheck(*pAbsAddr, SInt16);
792       break;
793     case eSymbolSize32Bit:
794       *pAbsAddr -= DispAddr + 4;
795       OK = True;
796       break;
797     default:
798       OK = False;
799   }
800   if (!OK)
801     WrStrErrorPos(ErrNum_JmpDistTooBig, pArg);
802   return OK;
803 }
804 
805 /*!------------------------------------------------------------------------
806  * \fn     SetRegPrefix(Byte *pDest, Byte Src, const tStrComp *pArg)
807  * \brief  set (new) previous/current bank register prefix
808  * \param  pDest current prefix
809  * \param  Src new prefix to set/confirm
810  * \param  pArg argument to print in error msg if bank mismatch
811  * \return True if register bank was set or confirmed
812  * ------------------------------------------------------------------------ */
813 
SetRegPrefix(Byte * pDest,Byte Src,const tStrComp * pArg)814 static Boolean SetRegPrefix(Byte *pDest, Byte Src, const tStrComp *pArg)
815 {
816   if (*pDest && (*pDest != Src))
817   {
818     WrStrErrorPos(ErrNum_RegBankMismatch, pArg);
819     return False;
820   }
821   *pDest = Src;
822   return True;
823 }
824 
825 /*!------------------------------------------------------------------------
826  * \fn     EvalArg(const tStrComp *pArg, int Offset, tSymbolSize OpSize, Boolean *pOK)
827  * \brief  evaluate integer expression accoring to operand size
828  * \param  pArg argument to evaluate
829  * \param  Offset offset into argument where expression begins
830  * \param  OpSize operand size to use
831  * \param  pOK returns True if evaluation succeeded
832  * \return result of evaluation
833  * ------------------------------------------------------------------------ */
834 
EvalArg(const tStrComp * pArg,int Offset,tSymbolSize OpSize,Boolean * pOK)835 static LongInt EvalArg(const tStrComp *pArg, int Offset, tSymbolSize OpSize, Boolean *pOK)
836 {
837   switch ((int)OpSize)
838   {
839     case eSymbolSize8Bit:
840       return EvalStrIntExpressionOffs(pArg, Offset, Int8, pOK);
841     case eSymbolSize16Bit:
842       return EvalStrIntExpressionOffs(pArg, Offset, Int16, pOK);
843     case eSymbolSize32Bit:
844       return EvalStrIntExpressionOffs(pArg, Offset, Int32, pOK);
845     case eSymbolSize5Bit:
846       return EvalStrIntExpressionOffs(pArg, Offset, UInt5, pOK);
847     case eSymbolSize4Bit:
848       return EvalStrIntExpressionOffs(pArg, Offset, UInt4, pOK);
849     case eSymbolSize3Bit:
850       return EvalStrIntExpressionOffs(pArg, Offset, UInt3, pOK);
851     default:
852       *pOK = False;
853       return 0;
854   }
855 }
856 
857 /*!------------------------------------------------------------------------
858  * \fn     ValidBaseRegSize(tSymbolSize Size)
859  * \brief  check whether operand size is appropriate for base reg in indirect expression
860  * \param  Size operand size to check
861  * \return True if OK
862  * ------------------------------------------------------------------------ */
863 
ValidBaseRegSize(tSymbolSize Size)864 static Boolean ValidBaseRegSize(tSymbolSize Size)
865 {
866   return (Size == eSymbolSizeUnknown) /* no size given: regarded as 32 bits */
867       || (Size == eSymbolSize32Bit);
868 }
869 
870 /*!------------------------------------------------------------------------
871  * \fn     ValidIndexRegSize(tSymbolSize Size)
872  * \brief  check whether operand size is appropriate for indirect reg in indirect expression
873  * \param  Size operand size to check
874  * \return True if OK
875  * ------------------------------------------------------------------------ */
876 
ValidIndexRegSize(tSymbolSize Size)877 static Boolean ValidIndexRegSize(tSymbolSize Size)
878 {
879   return (Size == eSymbolSizeUnknown) /* no size given: regarded as default index reg size */
880       || (Size == eSymbolSize16Bit)
881       || (Size == eSymbolSize32Bit);
882 }
883 
884 /*!------------------------------------------------------------------------
885  * \fn     ClassComp(tStrComp *pArg, tAdrComps *pComps)
886  * \brief  classify/parse argument of indirect address expression
887  * \param  pComps indirect address evaluation context to update/augment
888  * \param  pArg argument to parse
889  * \return True if parsing and context update succeeded
890  * ------------------------------------------------------------------------ */
891 
892 static Boolean ClassCompList(tAdrComps *pComps, tStrComp *pArg);
893 
ClassComp(tStrComp * pArg,tAdrComps * pComps)894 static Boolean ClassComp(tStrComp *pArg, tAdrComps *pComps)
895 {
896   tSymbolSize OpSize;
897   Byte Reg, Scale, Prefix;
898   char Save;
899   LongInt Value;
900   Boolean OK;
901 
902   KillPrefBlanksStrCompRef(pArg);
903   KillPostBlanksStrComp(pArg);
904 
905   if (!as_strcasecmp(pArg->Str, "PC"))
906   {
907     if (pComps->BaseReg == NOREG)
908     {
909       pComps->BaseReg = PCREG;
910       pComps->BaseRegIncr = 0;
911       return True;
912     }
913     else if (pComps->IndexReg == NOREG)
914     {
915       pComps->IndexReg = pComps->BaseReg;
916       pComps->IndexRegScale = 0;
917       pComps->IndexRegSize = eSymbolSize32Bit;
918       pComps->BaseReg = PCREG;
919       pComps->BaseRegIncr = 0;
920       return True;
921     }
922     else
923       return False;
924   }
925   if (*pArg->Str == '@')
926   {
927     tAdrComps InnerComps;
928     tStrComp InnerList;
929 
930     if (pComps->InnerReg != NOREG)
931       return False;
932 
933     StrCompRefRight(&InnerList, pArg, 1);
934     if (!ClassCompList(&InnerComps, &InnerList))
935       return False;
936     if (!InnerComps.InnerDispPresent
937       && (InnerComps.InnerReg == NOREG)
938       && (InnerComps.IndexReg == NOREG)
939       && (InnerComps.BaseReg != NOREG)
940       && !InnerComps.BaseRegIncr)
941     {
942       pComps->InnerReg = InnerComps.BaseReg;
943       pComps->InnerDispPresent = InnerComps.OuterDispPresent;
944       pComps->InnerDisp = InnerComps.OuterDisp;
945       pComps->InnerDispSize = InnerComps.OuterDispSize;
946     }
947 
948     return True;
949   }
950   switch (DecodeRegWithSize(pArg, &Reg, &OpSize, &Prefix, False))
951   {
952     case eIsReg:
953       if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
954         return False;
955       if ((pComps->BaseReg == NOREG) && (OpSize == eSymbolSizeUnknown))
956       {
957         pComps->BaseReg = Reg;
958         pComps->BaseRegIncr = 0;
959         return True;
960       }
961       else if ((pComps->IndexReg == NOREG) && ValidIndexRegSize(OpSize))
962       {
963         pComps->IndexReg = Reg;
964         pComps->IndexRegScale = 0;
965         if (OpSize != eSymbolSizeUnknown)
966           pComps->IndexRegSize = OpSize;
967         return True;
968       }
969       else
970         return False;
971       break;
972     case eIsNoReg:
973       break;
974     case eRegAbort:
975       return False;
976   }
977   if (*pArg->Str == '-')
978   {
979     tStrComp RegComp;
980 
981     StrCompRefRight(&RegComp, pArg, 1);
982     switch (DecodeReg(&RegComp, &Reg, &Prefix, True, False))
983     {
984       case eIsReg:
985         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
986           return False;
987         if (pComps->BaseReg == NOREG)
988         {
989           pComps->BaseReg = Reg;
990           pComps->BaseRegIncr = -1;
991           return True;
992         }
993         else
994           return False;
995       case eRegAbort:
996         return False;
997       case eIsNoReg:
998         break;
999     }
1000   }
1001   if (pArg->Str[pArg->Pos.Len - 1] == '+')
1002   {
1003     pArg->Str[pArg->Pos.Len - 1] = '\0';
1004     switch (DecodeReg(pArg, &Reg, &Prefix, True, False))
1005     {
1006       case eIsReg:
1007         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
1008           return False;
1009         if (pComps->BaseReg == NOREG)
1010         {
1011           pComps->BaseReg = Reg;
1012           pComps->BaseRegIncr = +1;
1013           return True;
1014         }
1015         else
1016           return False;
1017       case eRegAbort:
1018         return False;
1019       case eIsNoReg:
1020         pArg->Str[pArg->Pos.Len - 1] = '+';
1021         break;
1022     }
1023   }
1024   Save = SplitScale(pArg, &Scale);
1025   if (Save)
1026   {
1027     switch (DecodeRegWithSize(pArg, &Reg, &OpSize, &Prefix, False))
1028     {
1029       case eIsReg:
1030         if (!SetRegPrefix(&pComps->RegPrefix, Prefix, pArg))
1031           return False;
1032         if ((pComps->IndexReg == NOREG) && ValidIndexRegSize(OpSize))
1033         {
1034           pComps->IndexReg = Reg;
1035           pComps->IndexRegScale = Scale;
1036           if (OpSize != eSymbolSizeUnknown)
1037             pComps->IndexRegSize = OpSize;
1038         }
1039         else if (pComps->BaseReg == NOREG)
1040         {
1041           if ((Scale == 0) && ValidBaseRegSize(OpSize))
1042             pComps->BaseReg = Reg;
1043           else if ((Scale != 0) && (pComps->IndexRegScale == 0) && (pComps->IndexRegSize == eSymbolSize32Bit))
1044           {
1045             pComps->BaseReg = pComps->IndexReg;
1046             pComps->IndexReg = Reg;
1047             pComps->IndexRegScale = Scale;
1048             pComps->IndexRegSize = (OpSize == eSymbolSizeUnknown) ? DefIndexRegSize : OpSize;
1049           }
1050           else
1051             return False;
1052         }
1053         else
1054           return False;
1055         return True;
1056       case eIsNoReg:
1057         AppendScale(pArg, Scale);
1058         break;
1059       case eRegAbort:
1060         return False;
1061     }
1062   }
1063 
1064   if (!SplitOpSize(pArg, &OpSize))
1065     OpSize = eSymbolSizeUnknown;
1066   Value = EvalArg(pArg, 0, eSymbolSize32Bit, &OK);
1067   if (!OK)
1068     return False;
1069   pComps->OuterDispPresent = True;
1070   if (OpSize > pComps->OuterDispSize)
1071     pComps->OuterDispSize = OpSize;
1072   pComps->OuterDisp += Value;
1073   return True;
1074 }
1075 
1076 /*!------------------------------------------------------------------------
1077  * \fn     ClassCompList(tAdrComps *pComps, tStrComp *pArg)
1078  * \brief  classify/parse argument list of indirect address expression
1079  * \param  pComps indirect address evaluation context to fill
1080  * \param  pArg address expression argument
1081  * \return True if parsing succeeded
1082  * ------------------------------------------------------------------------ */
1083 
ClassCompList(tAdrComps * pComps,tStrComp * pArg)1084 static Boolean ClassCompList(tAdrComps *pComps, tStrComp *pArg)
1085 {
1086   ResetAdrComps(pComps);
1087 
1088   if (IsIndirect(pArg->Str))
1089   {
1090     char *pSplit;
1091     tStrComp Remainder;
1092 
1093     StrCompIncRefLeft(pArg, 1);
1094     StrCompShorten(pArg, 1);
1095     do
1096     {
1097       pSplit = QuotPos(pArg->Str, ',');
1098       if (pSplit)
1099         StrCompSplitRef(pArg, &Remainder, pArg, pSplit);
1100       if (!ClassComp(pArg, pComps))
1101       {
1102         WrStrErrorPos(ErrNum_InvAddrMode, pArg);
1103         return False;
1104       }
1105       if (pSplit)
1106         *pArg = Remainder;
1107     }
1108     while (pSplit);
1109   }
1110   else
1111   {
1112     if (!ClassComp(pArg, pComps))
1113     {
1114       WrStrErrorPos(ErrNum_InvAddrMode, pArg);
1115       return False;
1116     }
1117   }
1118   return True;
1119 }
1120 
1121 /*!------------------------------------------------------------------------
1122  * \fn     DecodeAdr(const tStrComp *pArg, unsigned Mask, tAdrVals *pAdrVals, LongInt EAAddr)
1123  * \brief  parse address expression
1124  * \param  pArg expression to parse
1125  * \param  Mask bit mask of allowed addressing modes
1126  * \param  pAdrVals returns parsed addressing mode
1127  * \param  EAAddr position of associared EA byte in code (needed for PC-relative addressing)
1128  * \return True if parsing succeeded
1129  * ------------------------------------------------------------------------ */
1130 
DecodeAdr(const tStrComp * pArg,unsigned Mask,tAdrVals * pAdrVals,LongInt EAAddr)1131 static Boolean DecodeAdr(const tStrComp *pArg, unsigned Mask, tAdrVals *pAdrVals, LongInt EAAddr)
1132 {
1133   Byte Reg, Prefix;
1134   tStrComp Arg;
1135 
1136   ResetAdrVals(pAdrVals);
1137 
1138   Arg = *pArg;
1139   while (True)
1140   {
1141     if (!as_strncasecmp(Arg.Str, "<CRn>", 5)
1142      || !as_strncasecmp(Arg.Str, "<PRn>", 5))
1143     {
1144       AppendAdrVals(pAdrVals, (toupper(Arg.Str[1]) == 'C') ? PREFIX_CRn : PREFIX_PRn);
1145       StrCompIncRefLeft(&Arg, 5);
1146       KillPrefBlanksStrCompRef(&Arg);
1147     }
1148     else
1149       break;
1150   }
1151 
1152   switch (DecodeReg(&Arg, &Reg, &Prefix, True, False))
1153   {
1154     case eIsReg:
1155       pAdrVals->Mode = eAdrModeReg;
1156       AppendRegPrefix(pAdrVals, Prefix);
1157       AppendAdrVals(pAdrVals, 0x40 | Reg);
1158       goto Check;
1159     case eIsNoReg:
1160       break;
1161     case eRegAbort:
1162       return False;
1163   }
1164 
1165   if (*Arg.Str == '#')
1166   {
1167     tSymbolSize ImmOpSize;
1168     LongInt ArgVal;
1169     Boolean OK;
1170 
1171     if (!SplitOpSize(&Arg, &ImmOpSize))
1172       ImmOpSize = OpSize;
1173     ArgVal = EvalArg(&Arg, 1, ImmOpSize, &OK);
1174     if (OK)
1175     {
1176       AppendAdrVals(pAdrVals, 0x70 | (ImmOpSize + 1));
1177       AppendToAdrValsBySize(pAdrVals, ArgVal, ImmOpSize);
1178       pAdrVals->Mode = eAdrModeImm;
1179     }
1180     goto Check;
1181   }
1182 
1183   if (*Arg.Str == '@')
1184   {
1185     tStrComp IndirComp;
1186     tAdrComps Comps;
1187 
1188     StrCompRefRight(&IndirComp, &Arg, 1);
1189     if (!ClassCompList(&Comps, &IndirComp))
1190       return False;
1191 
1192     /* only base register, no indirection, and optional displacement: */
1193 
1194     if (!Comps.InnerDispPresent
1195      && (Comps.InnerReg == NOREG)
1196      && (Comps.IndexReg == NOREG)
1197      && NormalReg(Comps.BaseReg)
1198      && !Comps.BaseRegIncr)
1199     {
1200       if (Comps.OuterDispPresent)
1201       {
1202         if (Comps.OuterDispSize == eSymbolSizeUnknown)
1203           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
1204         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
1205           goto Check;
1206         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1207         AppendAdrVals(pAdrVals, ((Comps.OuterDispSize + 1) << 4) | Comps.BaseReg);
1208         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1209       }
1210       else
1211         AppendAdrVals(pAdrVals, 0x00 | Comps.BaseReg);
1212       pAdrVals->Mode = eAdrModeIReg;
1213       goto Check;
1214     }
1215 
1216     /* postinc/predec */
1217 
1218     if (!Comps.InnerDispPresent
1219      && !Comps.OuterDispPresent
1220      && (Comps.InnerReg == NOREG)
1221      && (Comps.IndexReg == NOREG)
1222      && NormalReg(Comps.BaseReg)
1223      && Comps.BaseRegIncr)
1224     {
1225       if (Comps.BaseRegIncr > 0)
1226       {
1227         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1228         AppendAdrVals(pAdrVals, 0x50 | Comps.BaseReg);
1229         pAdrVals->Mode = eAdrModePost;
1230       }
1231       else
1232       {
1233         AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1234         AppendAdrVals(pAdrVals, 0x60 | Comps.BaseReg);
1235         pAdrVals->Mode = eAdrModePre;
1236       }
1237       goto Check;
1238     }
1239 
1240     /* absolute */
1241 
1242     if (!Comps.InnerDispPresent
1243      && Comps.OuterDispPresent
1244      && (Comps.InnerReg == NOREG)
1245      && (Comps.IndexReg == NOREG)
1246      && (Comps.BaseReg == NOREG))
1247     {
1248       if (Comps.OuterDispSize == eSymbolSizeUnknown)
1249         Comps.OuterDispSize = DeduceSize16M(Comps.OuterDisp);
1250       if (!ChkSize16M(Comps.OuterDisp, Comps.OuterDispSize))
1251         goto Check;
1252       AppendAdrVals(pAdrVals, 0x74 | (Comps.OuterDispSize + 1));
1253       AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1254       pAdrVals->Mode = eAdrModeAbs;
1255       goto Check;
1256     }
1257 
1258     /* register indirect with scale */
1259 
1260     if (!Comps.InnerDispPresent
1261      && (Comps.InnerReg == NOREG)
1262      && (Comps.BaseReg == NOREG)
1263      && NormalReg(Comps.IndexReg)
1264      && (Comps.IndexRegSize == eSymbolSize32Bit))
1265     {
1266       Byte EAVal = 0x78;
1267 
1268       if (Comps.OuterDispPresent)
1269       {
1270         if (Comps.OuterDispSize == eSymbolSizeUnknown)
1271           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
1272         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
1273           goto Check;
1274         EAVal |= (1 + Comps.OuterDispSize);
1275       }
1276       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1277       AppendAdrVals(pAdrVals, EAVal);
1278       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
1279       if (Comps.OuterDispPresent)
1280         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1281       pAdrVals->Mode = eAdrModeIRegScale;
1282       goto Check;
1283     }
1284 
1285     /* register indirect with (scaled) index */
1286 
1287     if (!Comps.InnerDispPresent
1288      && (Comps.InnerReg == NOREG)
1289      && NormalReg(Comps.BaseReg)
1290      && NormalReg(Comps.IndexReg))
1291     {
1292       Byte Exp1Val = ((Comps.IndexRegSize - 1) << 6) | Comps.BaseReg;
1293 
1294       if (Comps.OuterDispPresent)
1295       {
1296         if (Comps.OuterDispSize == eSymbolSizeUnknown)
1297           Comps.OuterDispSize = DeduceSize(Comps.OuterDisp);
1298         if (!ChkSize(Comps.OuterDisp, Comps.OuterDispSize))
1299           goto Check;
1300         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
1301       }
1302       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1303       AppendAdrVals(pAdrVals, 0x7c);
1304       AppendAdrVals(pAdrVals, Exp1Val);
1305       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
1306       if (Comps.OuterDispPresent)
1307         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1308       pAdrVals->Mode = eAdrModeIdxScale;
1309       goto Check;
1310     }
1311 
1312     /* PC-relative with (scaled) index */
1313 
1314     if (!Comps.InnerDispPresent
1315      && (Comps.InnerReg == NOREG)
1316      && (Comps.BaseReg == PCREG)
1317      && NormalReg(Comps.IndexReg))
1318     {
1319       Byte Exp1Val = ((Comps.IndexRegSize - 1) << 6);
1320 
1321       if (Comps.OuterDispPresent)
1322       {
1323         if (Comps.OuterDispSize == eSymbolSizeUnknown)
1324           Comps.OuterDispSize = DeduceSizePCRel(Comps.OuterDisp, EAAddr + 3);
1325         if (!ChkSizePCRelDisplacement(&Comps.OuterDisp, Comps.OuterDispSize, EAAddr + 3))
1326           goto Check;
1327         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
1328       }
1329       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1330       AppendAdrVals(pAdrVals, 0x7d);
1331       AppendAdrVals(pAdrVals, Exp1Val);
1332       AppendAdrVals(pAdrVals, (Comps.IndexRegScale << 4) | Comps.IndexReg);
1333       if (Comps.OuterDispPresent)
1334         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1335       pAdrVals->Mode = eAdrModePCIdxScale;
1336       goto Check;
1337     }
1338 
1339     /* PC-relative */
1340 
1341     if (!Comps.InnerDispPresent
1342      && (Comps.InnerReg == NOREG)
1343      && (Comps.BaseReg == PCREG)
1344      && (Comps.IndexReg == NOREG))
1345     {
1346       Byte Exp1Val = 0x80;
1347 
1348       if (Comps.OuterDispPresent)
1349       {
1350         if (Comps.OuterDispSize == eSymbolSizeUnknown)
1351           Comps.OuterDispSize = DeduceSizePCRel(Comps.OuterDisp, EAAddr + 2);
1352         if (!ChkSizePCRelDisplacement(&Comps.OuterDisp, Comps.OuterDispSize, EAAddr + 2))
1353           goto Check;
1354         Exp1Val |= (1 + Comps.OuterDispSize) << 4;
1355       }
1356       AppendRegPrefix(pAdrVals, Comps.RegPrefix); /* should never occur, no Rn in expression */
1357       AppendAdrVals(pAdrVals, 0x7d);
1358       AppendAdrVals(pAdrVals, Exp1Val);
1359       if (Comps.OuterDispPresent)
1360         AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1361       pAdrVals->Mode = eAdrModePCRel;
1362       goto Check;
1363     }
1364 
1365     /* Register double indirect */
1366 
1367     if (NormalReg(Comps.InnerReg)
1368      && (Comps.BaseReg == NOREG)
1369      && (Comps.IndexReg == NOREG))
1370     {
1371       /* no disp not allowed -> convert zero-disp to 8 bits */
1372 
1373       if (Comps.OuterDispSize == eSymbolSizeUnknown)
1374         Comps.OuterDispSize = DeduceSize8_32(Comps.OuterDisp);
1375       if (Comps.InnerDispSize == eSymbolSizeUnknown)
1376         Comps.InnerDispSize = DeduceSize8_32(Comps.InnerDisp);
1377       AppendRegPrefix(pAdrVals, Comps.RegPrefix);
1378       AppendAdrVals(pAdrVals, 0x7e);
1379       AppendAdrVals(pAdrVals, Comps.InnerReg | ((Comps.InnerDispSize + 1) << 4) | ((Comps.OuterDispSize + 1) << 6));
1380       AppendToAdrValsBySize(pAdrVals, Comps.InnerDisp, Comps.InnerDispSize);
1381       AppendToAdrValsBySize(pAdrVals, Comps.OuterDisp, Comps.OuterDispSize);
1382       pAdrVals->Mode = eAdrModeDoubleIndir;
1383       goto Check;
1384     }
1385 
1386     WrStrErrorPos(ErrNum_InvAddrMode, &Arg);
1387   }
1388 
1389   /* None of this.  Should we treat it as absolute? */
1390 
1391   WrStrErrorPos(ErrNum_InvAddrMode, pArg);
1392 
1393 Check:
1394   if ((pAdrVals->Mode != eAdrModeNone)
1395    && !((Mask >> pAdrVals->Mode) & 1))
1396   {
1397     WrStrErrorPos(ErrNum_InvAddrMode, pArg);
1398     ResetAdrVals(pAdrVals);
1399     return False;
1400   }
1401   return True;
1402 }
1403 
1404 /*!------------------------------------------------------------------------
1405  * \fn     GlobalBankReg(const tAdrVals *pAdrVals)
1406  * \brief  check whether parsed address expression is a global bank register
1407  * \param  pAdrVals parsed expression
1408  * \return True if it is a global bank register
1409  * ------------------------------------------------------------------------ */
1410 
GlobalBankReg(const tAdrVals * pAdrVals)1411 static Boolean GlobalBankReg(const tAdrVals *pAdrVals)
1412 {
1413   return (pAdrVals->Mode == eAdrModeReg)
1414       && (pAdrVals->Cnt == 1);
1415 }
1416 
1417 /*!------------------------------------------------------------------------
1418  * \fn     ImmValS8(const tAdrVals *pAdrVals)
1419  * \brief  check whether parsed address expression is an immediate value representable as 8 bits,
1420            assuming sign extension
1421  * \param  pAdrVals parsed expression
1422  * \return True if immediate & value range OK
1423  * ------------------------------------------------------------------------ */
1424 
ImmValS8(const tAdrVals * pAdrVals)1425 static Boolean ImmValS8(const tAdrVals *pAdrVals)
1426 {
1427   Byte Sign;
1428   unsigned z;
1429 
1430   if ((pAdrVals->Mode != eAdrModeImm)
1431    || (pAdrVals->Cnt < 1))
1432     return False;
1433 
1434   Sign = (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0x80) ? 0xff: 0x00;
1435   for (z = 1; z < pAdrVals->Cnt - 1; z++)
1436     if (pAdrVals->Vals[z] != Sign)
1437       return False;
1438 
1439   return True;
1440 }
1441 
1442 /*!------------------------------------------------------------------------
1443  * \fn     ImmValS4(const tAdrVals *pAdrVals)
1444  * \brief  check whether parsed address expression is an immediate value representable as 4 bits,
1445            assuming sign extension
1446  * \param  pAdrVals parsed expression
1447  * \return True if immediate & value range OK
1448  * ------------------------------------------------------------------------ */
1449 
ImmValS4(const tAdrVals * pAdrVals)1450 static Boolean ImmValS4(const tAdrVals *pAdrVals)
1451 {
1452   Byte Sign;
1453 
1454   if (!ImmValS8(pAdrVals))
1455     return False;
1456 
1457   Sign = (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0x08) ? 0xf0: 0x00;
1458   return (pAdrVals->Vals[pAdrVals->Cnt - 1] & 0xf0) == Sign;
1459 }
1460 
1461 /*!------------------------------------------------------------------------
1462  * \fn     AppendAdrValsToCode(const tAdrVals *pAdrVals)
1463  * \brief  append parsed address expression to instruction's code
1464  * \param  pAdrVals parsed expression
1465  * ------------------------------------------------------------------------ */
1466 
AppendAdrValsToCode(const tAdrVals * pAdrVals)1467 static void AppendAdrValsToCode(const tAdrVals *pAdrVals)
1468 {
1469   memcpy(&BAsmCode[CodeLen], pAdrVals->Vals, pAdrVals->Cnt);
1470   CodeLen += pAdrVals->Cnt;
1471 }
1472 
1473 /*!------------------------------------------------------------------------
1474  * \fn     AppendAdrValPair(tAdrVals *pSrcAdrVals, const tAdrVals *pDestAdrVals)
1475  * \brief  append source & destination address expression to instruction's code
1476  * \param  pSrcAdrVals parsed source address expression
1477  * \param  pDestAdrVals parsed destination address expression
1478  * ------------------------------------------------------------------------ */
1479 
AppendAdrValPair(tAdrVals * pSrcAdrVals,const tAdrVals * pDestAdrVals)1480 static void AppendAdrValPair(tAdrVals *pSrcAdrVals, const tAdrVals *pDestAdrVals)
1481 {
1482   Byte *pEASrc = &BAsmCode[CodeLen];
1483 
1484   AppendAdrValsToCode(pSrcAdrVals);
1485   if (pDestAdrVals->Vals[0] == 0x40) /* EA=0x40 -> R0 -> accumulator mode */
1486     *pEASrc |= 0x80;
1487   else
1488     AppendAdrValsToCode(pDestAdrVals);
1489 }
1490 
1491 /*--------------------------------------------------------------------------*/
1492 /* Bit Symbol Handling */
1493 
1494 /*
1495  * Compact representation of bits and bit fields in symbol table:
1496  * bits 0..2/3/4: (start) bit position
1497  * bits 3/4/5...26/27/28: register address
1498  * bits 30/31: register size (0/1/2 for 8/16/32 bits)
1499  */
1500 
1501 /*!------------------------------------------------------------------------
1502  * \fn     EvalBitPosition(const char *pBitArg, Boolean *pOK, tSymbolSize OpSize)
1503  * \brief  evaluate constant bit position, with bit range depending on operand size
1504  * \param  pBitArg bit position argument
1505  * \param  pOK returns True if OK
1506  * \param  OpSize operand size (0,1,2 -> 8,16,32 bits)
1507  * \return bit position as number
1508  * ------------------------------------------------------------------------ */
1509 
EvalBitPosition(const tStrComp * pBitArg,Boolean * pOK,tSymbolSize OpSize)1510 static Byte EvalBitPosition(const tStrComp *pBitArg, Boolean *pOK, tSymbolSize OpSize)
1511 {
1512   int Offset = !!(*pBitArg->Str == '#');
1513 
1514   switch (OpSize)
1515   {
1516     case eSymbolSize8Bit:
1517       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt3, pOK);
1518     case eSymbolSize16Bit:
1519       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt4, pOK);
1520     case eSymbolSize32Bit:
1521       return EvalStrIntExpressionOffs(pBitArg, Offset, UInt5, pOK);
1522     default:
1523       WrError(ErrNum_InvOpSize);
1524       *pOK = False;
1525       return 0;
1526   }
1527 }
1528 
1529 /*!------------------------------------------------------------------------
1530  * \fn     AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address)
1531  * \brief  build the compact internal representation of a bit field symbol
1532  * \param  BitPos bit position in word
1533  * \param  Width width of bit field
1534  * \param  OpSize operand size (8/16/32 bit)
1535  * \param  Address register address
1536  * \return compact representation
1537  * ------------------------------------------------------------------------ */
1538 
AssembleBitSymbol(Byte BitPos,tSymbolSize OpSize,LongWord Address)1539 static LongWord AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address)
1540 {
1541   int AddrShift = 3 + OpSize;
1542 
1543   return BitPos
1544        | ((Address & 0xfffffful) << AddrShift)
1545        | ((LongWord)OpSize << 30);
1546 }
1547 
1548 /*!------------------------------------------------------------------------
1549  * \fn     DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize)
1550  * \brief  transform compact represenation of bit (field) symbol into components
1551  * \param  BitSymbol compact storage
1552  * \param  pAddress (I/O) register address
1553  * \param  pBitPos (start) bit position
1554  * \param  pOpSize returns register size (0/1/2 for 8/16/32 bits)
1555  * \return constant True
1556  * ------------------------------------------------------------------------ */
1557 
DissectBitSymbol(LongWord BitSymbol,LongWord * pAddress,Byte * pBitPos,tSymbolSize * pOpSize)1558 static Boolean DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize)
1559 {
1560   *pOpSize = (tSymbolSize)((BitSymbol >> 30) & 3);
1561   switch (*pOpSize)
1562   {
1563     case eSymbolSize8Bit:
1564       *pAddress = (BitSymbol >> 3) & 0xfffffful;
1565       *pBitPos = BitSymbol & 7;
1566       break;
1567     case eSymbolSize16Bit:
1568       *pAddress = (BitSymbol >> 4) & 0xfffffful;
1569       *pBitPos = BitSymbol & 15;
1570       break;
1571     case eSymbolSize32Bit:
1572       *pAddress = (BitSymbol >> 5) & 0xfffffful;
1573       *pBitPos = BitSymbol & 31;
1574       break;
1575     default:
1576       *pAddress = 0;
1577       *pBitPos = 0;
1578   }
1579   return True;
1580 }
1581 
1582 /*!------------------------------------------------------------------------
1583  * \fn     DissectBit_H16(char *pDest, size_t DestSize, LargeWord Inp)
1584  * \brief  dissect compact storage of bit (field) into readable form for listing
1585  * \param  pDest destination for ASCII representation
1586  * \param  DestSize destination buffer size
1587  * \param  Inp compact storage
1588  * ------------------------------------------------------------------------ */
1589 
DissectBit_H16(char * pDest,size_t DestSize,LargeWord Inp)1590 static void DissectBit_H16(char *pDest, size_t DestSize, LargeWord Inp)
1591 {
1592   Byte BitPos;
1593   LongWord Address;
1594   tSymbolSize OpSize;
1595   char Attribute;
1596 
1597   DissectBitSymbol(Inp, &Address, &BitPos, &OpSize);
1598   Attribute = "bwl"[OpSize];
1599 
1600   as_snprintf(pDest, DestSize, "$%lx(%c).%u", (unsigned long)Address, Attribute, (unsigned)BitPos);
1601 }
1602 
1603 /*!------------------------------------------------------------------------
1604  * \fn     ExpandH16Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
1605  * \brief  expands bit definition when a structure is instantiated
1606  * \param  pVarName desired symbol name
1607  * \param  pStructElem element definition
1608  * \param  Base base address of instantiated structure
1609  * ------------------------------------------------------------------------ */
1610 
ExpandH16Bit(const tStrComp * pVarName,const struct sStructElem * pStructElem,LargeWord Base)1611 static void ExpandH16Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base)
1612 {
1613   tSymbolSize OpSize = (pStructElem->OpSize < 0) ? eSymbolSize8Bit : pStructElem->OpSize;
1614   LongWord Address = Base + pStructElem->Offset;
1615 
1616   if (!ChkRange(Address, 0, 0xfffffful)
1617    || !ChkRange(pStructElem->BitPos, 0, (8 << OpSize) - 1))
1618     return;
1619 
1620   PushLocHandle(-1);
1621   EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, OpSize, Address), SegBData, False);
1622   PopLocHandle();
1623   /* TODO: MakeUseList? */
1624 }
1625 
1626 /*!------------------------------------------------------------------------
1627  * \fn     DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, tSymbolSize OpSize)
1628  * \brief  encode a bit symbol, address & bit position separated
1629  * \param  pResult resulting encoded bit
1630  * \param  pRegArg register argument
1631  * \param  pBitArg bit argument
1632  * \param  OpSize register size (0/1/2 = 8/16/32 bit)
1633  * \return True if success
1634  * ------------------------------------------------------------------------ */
1635 
DecodeBitArg2(LongWord * pResult,const tStrComp * pRegArg,const tStrComp * pBitArg,tSymbolSize OpSize)1636 static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg, tSymbolSize OpSize)
1637 {
1638   Boolean OK;
1639   LongWord Addr;
1640   Byte BitPos;
1641 
1642   BitPos = EvalBitPosition(pBitArg, &OK, OpSize);
1643   if (!OK)
1644     return False;
1645 
1646   Addr = EvalStrIntExpressionOffs(pRegArg, !!(*pRegArg->Str == '@'), UInt24, &OK);
1647   if (!OK)
1648     return False;
1649 
1650   *pResult = AssembleBitSymbol(BitPos, OpSize, Addr);
1651 
1652   return True;
1653 }
1654 
1655 /*!------------------------------------------------------------------------
1656  * \fn     DecodeBitArg(LongWord *pResult, int Start, int Stop)
1657  * \brief  encode a bit symbol from instruction argument(s)
1658  * \param  pResult resulting encoded bit
1659  * \param  Start first argument
1660  * \param  Stop last argument
1661  * \param  OpSize register size (0/1/2 = 8/16/32 bit)
1662  * \return True if success
1663  * ------------------------------------------------------------------------ */
1664 
DecodeBitArg(LongWord * pResult,int Start,int Stop,tSymbolSize OpSize)1665 static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop, tSymbolSize OpSize)
1666 {
1667   *pResult = 0;
1668 
1669   /* Just one argument -> parse as bit argument */
1670 
1671   if (Start == Stop)
1672   {
1673     tEvalResult EvalResult;
1674 
1675     *pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], UInt32, &EvalResult);
1676     if (EvalResult.OK)
1677       ChkSpace(SegBData, EvalResult.AddrSpaceMask);
1678     return EvalResult.OK;
1679   }
1680 
1681   /* Register & bit position are given as separate arguments:
1682      use same argument positions as for machine instructions */
1683 
1684   else if (Stop == Start + 1)
1685     return DecodeBitArg2(pResult, &ArgStr[Stop], &ArgStr[Start], OpSize);
1686 
1687   /* other # of arguments not allowed */
1688 
1689   else
1690   {
1691     WrError(ErrNum_WrongArgCnt);
1692     return False;
1693   }
1694 }
1695 
1696 /*!------------------------------------------------------------------------
1697  * \fn     DecodeStringReg(Word Code)
1698  * \brief  decode register argument for string instruction
1699  * \param  pComp argument to parse
1700  * \param  Mask bit mask of allowed addressing modes
1701  * \param  pResult returns (global) register number
1702  * ------------------------------------------------------------------------ */
1703 
DecodeStringReg(tStrComp * pComp,unsigned Mask,Byte * pResult)1704 static Boolean DecodeStringReg(tStrComp *pComp, unsigned Mask, Byte *pResult)
1705 {
1706   tAdrVals AdrVals;
1707 
1708   if (!DecodeAdr(pComp, Mask, &AdrVals, EProgCounter() + 2))
1709     return False;
1710   switch (AdrVals.Mode)
1711   {
1712     case eAdrModeReg:
1713       if (!GlobalBankReg(&AdrVals))
1714       {
1715         WrStrErrorPos(ErrNum_InvReg, pComp);
1716         return False;
1717       }
1718       break;
1719     case eAdrModeIReg:
1720       if (AdrVals.Cnt != 1)
1721       {
1722         WrStrErrorPos(ErrNum_InvAddrMode, pComp);
1723         return False;
1724       }
1725       break;
1726     case eAdrModePost:
1727     case eAdrModePre:
1728       break;
1729     default:
1730       return False;
1731   }
1732   *pResult = AdrVals.Vals[0] & 15;
1733   return True;
1734 }
1735 
1736 /*!------------------------------------------------------------------------
1737  * \fn     ExtractDisp(const Byte *pVals, Byte SizeCode)
1738  * \brief  extract variable-length signed value
1739  * \param  pVals storage of value
1740  * \param  SizeCode # of bytes used (0..3 for 0/1/2/4 bytes)
1741  * \return effective value
1742  * ------------------------------------------------------------------------ */
1743 
ExtractDisp(const Byte * pVals,Byte SizeCode)1744 static LongInt ExtractDisp(const Byte *pVals, Byte SizeCode)
1745 {
1746   LongInt Result = 0;
1747 
1748   switch (SizeCode)
1749   {
1750     case 3:
1751       Result = (Result << 8) | (*pVals++);
1752       Result = (Result << 8) | (*pVals++);
1753       Result = (Result << 8) | (*pVals++);
1754       Result = (Result << 8) | (*pVals++);
1755       break;
1756     case 2:
1757       Result = (Result << 8) | (*pVals++);
1758       Result = (Result << 8) | (*pVals++);
1759       if (Result & 0x8000ul)
1760         Result -= 0x10000ul;
1761       break;
1762     case 1:
1763       Result = (Result << 8) | (*pVals++);
1764       if (Result & 0x80ul)
1765         Result -= 0x100;
1766       break;
1767     default:
1768       Result = 0;
1769   }
1770   return Result;
1771 }
1772 
1773 /*!------------------------------------------------------------------------
1774  * \fn     PCDistOK(const tAdrVals *pAdrVals, int Delta)
1775  * \brief  if expression is PC-relative, check whether change of distance does not change displacement size
1776  * \param  pAdrVals parsed address expression
1777  * \param  Delta displacement change
1778  * ------------------------------------------------------------------------ */
1779 
PCDistOK(tAdrVals * pAdrVals,int Delta)1780 static Boolean PCDistOK(tAdrVals *pAdrVals, int Delta)
1781 {
1782   Byte DispSizeCode;
1783   LongInt NewDisp;
1784   int DispOffs;
1785   tSymbolSize DispSize;
1786 
1787   /* only relevant for EA values that use PC-relative addressing: */
1788 
1789   if (pAdrVals->Vals[0] != 0x7d)
1790     return True;
1791   DispOffs = (pAdrVals->Vals[1] & 0x80) ? 2 : 3;
1792 
1793   /* extract displacement size Sd */
1794 
1795   DispSizeCode = (pAdrVals->Vals[1] >> 4) & 3;
1796   DispSize = (tSymbolSize)(DispSizeCode - 1);
1797 
1798   /* compute new displacement after correction */
1799 
1800   NewDisp = ExtractDisp(pAdrVals->Vals + DispOffs, DispSizeCode) + Delta;
1801 
1802   /* still fits size? */
1803 
1804   if (DeduceSize(NewDisp) != DispSize)
1805     return False;
1806 
1807   AppendBySize(pAdrVals->Vals + DispOffs, NewDisp, DispSize);
1808   return True;
1809 }
1810 
1811 /*!------------------------------------------------------------------------
1812  * \fn     NegSignedValOK(tAdrVals *pAdrVals)
1813  * \brief  tests whether negated (8 bit) immediate value still fits size
1814  * \param  pAdrVals parsed address expression
1815  * \return True if successfully inverted
1816  * ------------------------------------------------------------------------ */
1817 
NegSigned8ValOK(tAdrVals * pAdrVals)1818 static Boolean NegSigned8ValOK(tAdrVals *pAdrVals)
1819 {
1820   Byte DispSizeCode;
1821   LongInt Value;
1822   tSymbolSize DispSize;
1823 
1824   /* only treats immediate argument: */
1825 
1826   if (pAdrVals->Mode != eAdrModeImm)
1827     return False;
1828 
1829   DispSizeCode = pAdrVals->Vals[0] & 3;
1830   if (!DispSizeCode)
1831     return False;
1832   DispSize = (tSymbolSize)(DispSizeCode - 1);
1833 
1834   /* extract immediate value */
1835 
1836   Value = ExtractDisp(pAdrVals->Vals + 1, DispSizeCode) * (-1);
1837 
1838   /* still fits size? */
1839 
1840   if (DeduceSize(Value) > eSymbolSize8Bit)
1841     return False;
1842 
1843   AppendBySize(pAdrVals->Vals + 1, Value, DispSize);
1844   return True;
1845 }
1846 
1847 /*---------------------------------------------------------------------------*/
1848 
1849 /*!------------------------------------------------------------------------
1850  * \fn     DecodeMOV_ADD_SUB_CMP(Word Code)
1851  * \brief  instruction parser for MOV, ADD, CMP and SUB
1852  * \param  Code specific instruction code
1853  * ------------------------------------------------------------------------ */
1854 
DecodeMOV_ADD_SUB_CMP(Word Code)1855 static void DecodeMOV_ADD_SUB_CMP(Word Code)
1856 {
1857   tAdrVals SrcAdrVals, DestAdrVals;
1858   tFormat Format;
1859   unsigned DestMask;
1860   Boolean IsSUB = (Code == 0x04),
1861           IsCMP = (Code == 0x08);
1862 
1863   if (!ChkOpSize(eSymbolSize16Bit, 7))
1864     return;
1865 
1866   /* Immediate is allowed as destination for CMP since the result is
1867      anyway discarded: */
1868 
1869   DestMask = MModeAll;
1870   if (!IsCMP)
1871     DestMask &= ~MModeImm;
1872 
1873   if (ChkArgCnt(2, 2)
1874    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
1875    && DecodeAdr(&ArgStr[2], DestMask, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
1876   {
1877     /* TODO: auto-convert SUB:Q n,<ea> to ADD:q -n,<ea>? */
1878 
1879     if (!*FormatPart.Str)
1880     {
1881       /* R format (all instructions) */
1882 
1883       if (GlobalBankReg(&SrcAdrVals) && GlobalBankReg(&DestAdrVals))
1884         Format = eFormatR;
1885 
1886       /* MOV R0,<ea> -> MOVF <ea> if PC-relative distance size does not change. */
1887 
1888       else if (GlobalBankReg(&SrcAdrVals) && (SrcAdrVals.Vals[0] == 0x40) && PCDistOK(&DestAdrVals, SrcAdrVals.Cnt))
1889         Format = eFormatF;
1890       else if (ImmValS4(&SrcAdrVals) && GlobalBankReg(&DestAdrVals))
1891         Format = eFormatRQ;
1892 
1893       /* SUB:Q #n,<ea> does not exist.  Convert to ADD:Q #-n,<ea> if possible..
1894          TODO: should not do this at all if immediate size >= 16 bit was forced.  */
1895 
1896       else if (ImmValS8(&SrcAdrVals) && (!IsSUB || NegSigned8ValOK(&SrcAdrVals)))
1897       {
1898         if (IsSUB)
1899         {
1900           Code = 0x00;
1901           IsSUB = False;
1902         }
1903         Format = eFormatQ;
1904       }
1905       else
1906         Format = eFormatG;
1907     }
1908     else if (!(Format = DecodeFormat((1 << eFormatG) | (1 << eFormatQ) | (1 << eFormatR) | (1 << eFormatRQ))))
1909     {
1910       WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
1911       return;
1912     }
1913     switch (Format)
1914     {
1915       case eFormatG:
1916         BAsmCode[CodeLen++] = 0x00 | Code | OpSize;
1917         AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
1918         break;
1919       case eFormatR:
1920         if (!GlobalBankReg(&SrcAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1921         else if (!GlobalBankReg(&DestAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
1922         else
1923         {
1924           BAsmCode[CodeLen++] = 0x20 | Code | OpSize;
1925           BAsmCode[CodeLen++] = ((SrcAdrVals.Vals[0] & 15) << 4) | (DestAdrVals.Vals[0] & 15);
1926         }
1927         break;
1928       case eFormatRQ:
1929         if (SrcAdrVals.Mode != eAdrModeImm) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1930         else if (!ImmValS4(&SrcAdrVals)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
1931         else if (!GlobalBankReg(&DestAdrVals)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[2]);
1932         else
1933         {
1934           BAsmCode[CodeLen++] = 0x30 | Code | OpSize;
1935           BAsmCode[CodeLen++] = ((DestAdrVals.Vals[0] & 15) << 4) | (SrcAdrVals.Vals[SrcAdrVals.Cnt - 1] & 15);
1936         }
1937         break;
1938       case eFormatQ:
1939         if (IsSUB) WrStrErrorPos(ErrNum_InvAddrMode, &AttrPart);
1940         else if (SrcAdrVals.Mode != eAdrModeImm) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1941         else if (!ImmValS8(&SrcAdrVals)) WrStrErrorPos(ErrNum_OverRange, &ArgStr[1]);
1942         else
1943         {
1944           BAsmCode[CodeLen++] = 0x10 | Code | OpSize;
1945           BAsmCode[CodeLen++] = SrcAdrVals.Vals[SrcAdrVals.Cnt - 1];
1946           AppendAdrValsToCode(&DestAdrVals);
1947         }
1948         break;
1949       case eFormatF:
1950         if (!GlobalBankReg(&SrcAdrVals) || (SrcAdrVals.Vals[0] != 0x40)) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1951         else
1952         {
1953           BAsmCode[CodeLen++] = 0x5c | OpSize;
1954           AppendAdrValsToCode(&DestAdrVals);
1955         }
1956         break;
1957       default:
1958         break;
1959     }
1960   }
1961 }
1962 
1963 /*!------------------------------------------------------------------------
1964  * \fn     DecodeSignExt(Word Code)
1965  * \brief  instruction parser for MOVS, ADDS, CMPS and SUBS
1966  * \param  Code specific instruction code
1967  * ------------------------------------------------------------------------ */
1968 
DecodeSignExt(Word Code)1969 static void DecodeSignExt(Word Code)
1970 {
1971   tSymbolSize SrcOpSize;
1972   tAdrVals SrcAdrVals, DestAdrVals;
1973   Boolean IsCMPS = (Code == 0x48);
1974   unsigned DestMask;
1975 
1976   /* Immediate is allowed as destination for CMPS since the result is
1977      anyway discarded: */
1978 
1979   DestMask = MModeAll;
1980   if (!IsCMPS)
1981     DestMask &= ~MModeImm;
1982 
1983   if (!ChkEmptyFormat()
1984    || !ChkOpSize(eSymbolSize16Bit, 7)
1985    || !ChkArgCnt(2, 2)
1986    || !DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1))
1987     return;
1988   SrcOpSize = OpSize;
1989   OpSize = eSymbolSize32Bit;
1990   if (DecodeAdr(&ArgStr[2], DestMask, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
1991   {
1992     BAsmCode[CodeLen++] = Code | SrcOpSize;
1993     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
1994   }
1995 }
1996 
1997 /*!------------------------------------------------------------------------
1998  * \fn     DecodeTwo(Word Code)
1999  * \brief  instruction parser for generic two-operand instructions
2000  * \param  Code specific instruction code
2001  * ------------------------------------------------------------------------ */
2002 
DecodeTwo(Word Code)2003 static void DecodeTwo(Word Code)
2004 {
2005   tAdrVals SrcAdrVals, DestAdrVals;
2006   Boolean Only8 = (Code & 3) == 3;
2007 
2008   if (ChkEmptyFormat()
2009    && ChkOpSize(Only8 ? eSymbolSize8Bit : eSymbolSize16Bit, Only8 ? 1 : 7)
2010    && ChkArgCnt(2, 2)
2011    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
2012    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2013   {
2014     BAsmCode[CodeLen++] = Code | OpSize;
2015     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2016   }
2017 }
2018 
2019 /*!------------------------------------------------------------------------
2020  * \fn     DecodeOne(Word Code)
2021  * \brief  instruction parser for generic one-operand instructions
2022  * \param  Code specific instruction code
2023  * ------------------------------------------------------------------------ */
2024 
DecodeOne(Word Code)2025 static void DecodeOne(Word Code)
2026 {
2027   tAdrVals AdrVals;
2028   Boolean Only8 = !!(Code & 3);
2029   unsigned Mask;
2030 
2031   Mask = MModeAll;
2032   if (Code != 0x58) /* TST */
2033     Mask &= ~MModeImm;
2034 
2035   if (ChkEmptyFormat()
2036    && ChkOpSize(Only8 ? eSymbolSize8Bit : eSymbolSize16Bit, Only8 ? 1 : 7)
2037    && ChkArgCnt(1, 1)
2038    && DecodeAdr(&ArgStr[1], Mask, &AdrVals, EProgCounter() + 1))
2039   {
2040     BAsmCode[CodeLen++] = Code | OpSize;
2041     AppendAdrValsToCode(&AdrVals);
2042   }
2043 }
2044 
2045 /*!------------------------------------------------------------------------
2046  * \fn     DecodeMUL_DIV(Word Code)
2047  * \brief  instruction parser for multiply and divide instructions
2048  * \param  Code specific instruction code
2049  * ------------------------------------------------------------------------ */
2050 
DecodeMUL_DIV(Word Code)2051 static void DecodeMUL_DIV(Word Code)
2052 {
2053   tAdrVals SrcAdrVals, DestAdrVals;
2054 
2055   if (!ChkEmptyFormat()
2056    || !ChkOpSize(eSymbolSize16Bit, 3)
2057    || !ChkArgCnt(2, 2)
2058    || !DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 2))
2059     return;
2060   OpSize++;
2061   if (!DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 2 + SrcAdrVals.Cnt))
2062     return;
2063   OpSize--;
2064 
2065   BAsmCode[CodeLen++] = 0xee | (Code & 0x01);
2066   BAsmCode[CodeLen++] = (Code & 0x70) | (OpSize << 4);
2067   AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2068 }
2069 
2070 /*!------------------------------------------------------------------------
2071  * \fn     DecodeEXT(Word Code)
2072  * \brief  instruction parser for EXTS/EXTU
2073  * \param  Code specific instruction code
2074  * ------------------------------------------------------------------------ */
2075 
DecodeEXT(Word Code)2076 static void DecodeEXT(Word Code)
2077 {
2078   Byte Reg, Prefix;
2079 
2080   if (ChkEmptyFormat()
2081    && ChkOpSize(eSymbolSize16Bit, 7)
2082    && ChkArgCnt(1, 1))
2083   {
2084     if (DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
2085     {
2086       OpSize = (OpSize == eSymbolSize8Bit) ? eSymbolSize32Bit : (OpSize - 1);
2087       BAsmCode[CodeLen++] = Code | OpSize;
2088       BAsmCode[CodeLen++] = Reg;
2089     }
2090   }
2091 }
2092 
2093 /*!------------------------------------------------------------------------
2094  * \fn     DecodeCInstr(Word Code)
2095  * \brief  instruction decoder for control-register related instructions
2096  * \param  Code specific instruction code
2097  * ------------------------------------------------------------------------ */
2098 
DecodeCInstr(Word Code)2099 static void DecodeCInstr(Word Code)
2100 {
2101   Byte CReg;
2102   unsigned Mask = MModeAll;
2103   int CIdx = 2, EAIdx = 1;
2104   tAdrVals AdrVals;
2105 
2106   if (0xfc == Code) /* STC */
2107   {
2108     CIdx = 1;
2109     EAIdx = 2;
2110     Mask &= ~MModeImm;
2111   }
2112 
2113   if (ChkEmptyFormat()
2114    && ChkArgCnt(2, 2)
2115    && DecodeCReg(&ArgStr[CIdx], &CReg)
2116    && DecodeAdr(&ArgStr[EAIdx], Mask, &AdrVals, EProgCounter() + 2))
2117   {
2118     BAsmCode[CodeLen++] = Code;
2119     BAsmCode[CodeLen++] = CReg;
2120     AppendAdrValsToCode(&AdrVals);
2121   }
2122 }
2123 
2124 /*!------------------------------------------------------------------------
2125  * \fn     DecodeBranch(Word Code)
2126  * \brief  instruction decoder for non-generic branch instructions
2127  * \param  Code specific instruction code
2128  * ------------------------------------------------------------------------ */
2129 
DecodeBranch(Word Code)2130 static void DecodeBranch(Word Code)
2131 {
2132   LongInt Addr;
2133   Boolean OK;
2134   tSymbolFlags Flags;
2135 
2136   if (!ChkEmptyFormat()
2137    || !ChkArgCnt(1, 1))
2138     return;
2139 
2140   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].Str == '@'), UInt24, &OK, &Flags);
2141   if (!OK)
2142     return;
2143 
2144   if (OpSize == eSymbolSizeUnknown)
2145     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 1);
2146   if (!ChkSizePCRelBranch(&ArgStr[1], &Addr, OpSize, Flags, EProgCounter() + 1))
2147     return;
2148 
2149   BAsmCode[CodeLen++] = Code | OpSize;
2150   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
2151 }
2152 
2153 /*!------------------------------------------------------------------------
2154  * \fn     DecodeBranchGen(Word Code)
2155  * \brief  instruction decoder for generic branch instructions
2156  * \param  Code specific instruction code
2157  * ------------------------------------------------------------------------ */
2158 
DecodeBranchGen(Word Code)2159 static void DecodeBranchGen(Word Code)
2160 {
2161   LongInt Addr;
2162   Boolean OK;
2163   tSymbolFlags Flags;
2164   tFormat Format;
2165 
2166   if (!ChkArgCnt(1, 1))
2167     return;
2168 
2169   if (!*FormatPart.Str)
2170   {
2171     if (Code == 7)
2172     {
2173       DecodeBranch(0xa0);
2174       return;
2175     }
2176     if (Code == 6)
2177     {
2178       DecodeBranch(0xb0);
2179       return;
2180     }
2181   }
2182   else
2183   {
2184     Format = DecodeFormat(1 << eFormatG);
2185     if (!Format)
2186     {
2187       WrStrErrorPos(ErrNum_InvFormat, &FormatPart);
2188       return;
2189     }
2190   }
2191 
2192   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], !!(*ArgStr[1].Str == '@'), UInt24, &OK, &Flags);
2193   if (!OK)
2194     return;
2195 
2196   if (OpSize == eSymbolSizeUnknown)
2197     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 2);
2198   if (!ChkSizePCRelBranch(&ArgStr[1], &Addr, OpSize, Flags, EProgCounter() + 2))
2199     return;
2200 
2201   BAsmCode[CodeLen++] = 0xa4 | OpSize;
2202   BAsmCode[CodeLen++] = Code;
2203   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
2204 }
2205 
2206 /*!------------------------------------------------------------------------
2207  * \fn     DecodeFixed(Word Code)
2208  * \brief  instruction decoder for instructions without argument
2209  * \param  Code specific instruction code
2210  * ------------------------------------------------------------------------ */
2211 
DecodeFixed(Word Code)2212 static void DecodeFixed(Word Code)
2213 {
2214   if (ChkEmptyFormat()
2215    && (!(Code & 0x8000) || CheckSup(&OpPart))
2216    && ChkArgCnt(0, 0))
2217     BAsmCode[CodeLen++] = Lo(Code);
2218 }
2219 
2220 /*!------------------------------------------------------------------------
2221  * \fn     Decode(Word Code)
2222  * \brief  instruction decoder for shift & rotate instructions
2223  * \param  Code specific instruction code
2224  * ------------------------------------------------------------------------ */
2225 
DecodeShift(Word Code)2226 static void DecodeShift(Word Code)
2227 {
2228   tAdrVals ShiftAdrVals, OpAdrVals;
2229   tSymbolSize SaveOpSize;
2230 
2231   if (!ChkEmptyFormat()
2232    || !ChkOpSize(eSymbolSize16Bit, 7)
2233    || !ChkArgCnt(2, 2)
2234    || !DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &OpAdrVals, EProgCounter() + 2))
2235     return;
2236   SaveOpSize = OpSize;
2237 
2238   OpSize = eSymbolSize5Bit;
2239   (void)DecodeAdr(&ArgStr[1], MModeImm | MModeReg, &ShiftAdrVals, EProgCounter() + 1);
2240   switch (ShiftAdrVals.Mode)
2241   {
2242     case eAdrModeReg:
2243       if (ShiftAdrVals.Cnt > 1) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
2244       else
2245       {
2246         BAsmCode[CodeLen++] = 0x60 | SaveOpSize;
2247         BAsmCode[CodeLen++] = Code | (ShiftAdrVals.Vals[0] & 15);
2248         goto common;
2249       }
2250       break;
2251     case eAdrModeImm:
2252       BAsmCode[CodeLen++] = 0x64 | SaveOpSize;
2253       BAsmCode[CodeLen++] = Code | (ShiftAdrVals.Vals[1] & 31);
2254       goto common;
2255     default:
2256       break;
2257     common:
2258       AppendAdrValsToCode(&OpAdrVals);
2259   }
2260 }
2261 
2262 /*!------------------------------------------------------------------------
2263  * \fn     DecodeSET(Word Code)
2264  * \brief  instruction decoder for SET/cc instructions
2265  * \param  Code specific instruction code
2266  * ------------------------------------------------------------------------ */
2267 
DecodeSET(Word Code)2268 static void DecodeSET(Word Code)
2269 {
2270   tAdrVals AdrVals;
2271 
2272   if (ChkEmptyFormat()
2273    && ChkOpSize(eSymbolSize8Bit, 1)
2274    && ChkArgCnt(1, 1)
2275    && DecodeAdr(&ArgStr[1], MModeAll - MModeImm, &AdrVals, EProgCounter() + 2))
2276   {
2277     BAsmCode[CodeLen++] = 0xb7;
2278     BAsmCode[CodeLen++] = Code;
2279     AppendAdrValsToCode(&AdrVals);
2280   }
2281 }
2282 
2283 /*!------------------------------------------------------------------------
2284  * \fn     DecodeTRAP(Word Code)
2285  * \brief  instruction decoder for TRAP/cc instructions
2286  * \param  Code specific instruction code
2287  * ------------------------------------------------------------------------ */
2288 
DecodeTRAP(Word Code)2289 static void DecodeTRAP(Word Code)
2290 {
2291   if (ChkEmptyFormat()
2292    && ChkArgCnt(0, 0))
2293   {
2294     BAsmCode[CodeLen++] = 0xf3;
2295     BAsmCode[CodeLen++] = Code;
2296   }
2297 }
2298 
2299 /*!------------------------------------------------------------------------
2300  * \fn     DecodeSCB(Word Code)
2301  * \brief  instruction decoder for SCB/cc instructions
2302  * \param  Code specific instruction code
2303  * ------------------------------------------------------------------------ */
2304 
DecodeSCB(Word Code)2305 static void DecodeSCB(Word Code)
2306 {
2307   LongInt Addr;
2308   Boolean OK;
2309   tSymbolFlags Flags;
2310   Byte Reg, Prefix;
2311 
2312   if (!ChkEmptyFormat()
2313    || !ChkArgCnt(2, 2))
2314     return;
2315 
2316   if (!DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
2317     return;
2318 
2319   Addr = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], !!(*ArgStr[1].Str == '@'), UInt24, &OK, &Flags);
2320   if (!OK)
2321     return;
2322 
2323   if (OpSize == eSymbolSizeUnknown)
2324     OpSize = DeduceSizePCRel(Addr, EProgCounter() + 2);
2325   if (!ChkSizePCRelBranch(&ArgStr[2], &Addr, OpSize, Flags, EProgCounter() + 2))
2326     return;
2327 
2328   BAsmCode[CodeLen++] = 0xb4 | OpSize;
2329   BAsmCode[CodeLen++] = (Reg << 4) | Code;
2330   CodeLen += AppendBySize(BAsmCode + CodeLen, Addr, OpSize);
2331 }
2332 
2333 /*!------------------------------------------------------------------------
2334  * \fn     DecodeJMP_JSR(Word Code)
2335  * \brief  instruction decoder for JMP and JSR instructions
2336  * \param  Code specific instruction code
2337  * ------------------------------------------------------------------------ */
2338 
DecodeJMP_JSR(Word Code)2339 static void DecodeJMP_JSR(Word Code)
2340 {
2341   tAdrVals Arg;
2342 
2343   if (ChkEmptyFormat()
2344    && ChkArgCnt(1, 1)
2345    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModeImm, &Arg, EProgCounter() + 1))
2346   {
2347     BAsmCode[CodeLen++] = Code;
2348     AppendAdrValsToCode(&Arg);
2349   }
2350 }
2351 
2352 /*!------------------------------------------------------------------------
2353  * \fn     DecodeSWAP(Word Code)
2354  * \brief  instruction decoder for SWAP instruction
2355  * \param  Code specific instruction code
2356  * ------------------------------------------------------------------------ */
2357 
DecodeSWAP(Word Code)2358 static void DecodeSWAP(Word Code)
2359 {
2360   tAdrVals Arg;
2361 
2362   if (ChkEmptyFormat()
2363    && ChkOpSize(eSymbolSize16Bit, 3)
2364    && ChkArgCnt(1, 1)
2365    && DecodeAdr(&ArgStr[1], MModeAll - MModeImm, &Arg, EProgCounter() + 1))
2366   {
2367     BAsmCode[CodeLen++] = Code | OpSize;
2368     AppendAdrValsToCode(&Arg);
2369   }
2370 }
2371 
2372 /*!------------------------------------------------------------------------
2373  * \fn     DecodeXCH(Word Code)
2374  * \brief  instruction decoder for XCH instruction
2375  * \param  Code specific instruction code
2376  * ------------------------------------------------------------------------ */
2377 
DecodeXCH(Word Code)2378 static void DecodeXCH(Word Code)
2379 {
2380   Byte RegX, RegY, PrefixX, PrefixY;
2381 
2382   if (ChkEmptyFormat()
2383    && ChkOpSize(eSymbolSize32Bit, 4)
2384    && ChkArgCnt(2, 2))
2385   {
2386     if (DecodeReg(&ArgStr[1], &RegX, &PrefixX, False, True)
2387      && DecodeReg(&ArgStr[2], &RegY, &PrefixY, False, True))
2388     {
2389       BAsmCode[CodeLen++] = Code;
2390       BAsmCode[CodeLen++] = (RegX << 4) | RegY;
2391     }
2392   }
2393 }
2394 
2395 /*!------------------------------------------------------------------------
2396  * \fn     DecodeLINK(Word Code)
2397  * \brief  instruction decoder for LINK instruction
2398  * \param  Code specific instruction code
2399  * ------------------------------------------------------------------------ */
2400 
DecodeLINK(Word Code)2401 static void DecodeLINK(Word Code)
2402 {
2403   Byte Reg, Prefix;
2404 
2405   if (!ChkEmptyFormat()
2406    || !ChkArgCnt(2, 2))
2407     return;
2408   if (!DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True));
2409   else if (*ArgStr[2].Str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[2]);
2410   else
2411   {
2412     Boolean OK;
2413     LongInt Val = EvalArg(&ArgStr[2], 1, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize, &OK);
2414 
2415     if (OK)
2416     {
2417       if (OpSize == eSymbolSizeUnknown)
2418         OpSize = DeduceSize(Val);
2419       BAsmCode[CodeLen++] = Code | OpSize;
2420       BAsmCode[CodeLen++] = Reg;
2421       CodeLen += AppendBySize(BAsmCode + CodeLen, Val, OpSize);
2422     }
2423   }
2424 }
2425 
2426 /*!------------------------------------------------------------------------
2427  * \fn     DecodeUNLK(Word Code)
2428  * \brief  instruction decoder for UNLK instruction
2429  * \param  Code specific instruction code
2430  * ------------------------------------------------------------------------ */
2431 
DecodeUNLK(Word Code)2432 static void DecodeUNLK(Word Code)
2433 {
2434   Byte Reg, Prefix;
2435 
2436   if (!ChkEmptyFormat()
2437    || !ChkArgCnt(1, 1))
2438     return;
2439   if (DecodeReg(&ArgStr[1], &Reg, &Prefix, False, True))
2440   {
2441     BAsmCode[CodeLen++] = Code;
2442     BAsmCode[CodeLen++] = Reg;
2443   }
2444 }
2445 
2446 /*!------------------------------------------------------------------------
2447  * \fn     DecodeTRAPA(Word Code)
2448  * \brief  instruction decoder for TRAPA instruction
2449  * \param  Code specific instruction code
2450  * ------------------------------------------------------------------------ */
2451 
DecodeTRAPA(Word Code)2452 static void DecodeTRAPA(Word Code)
2453 {
2454   if (!ChkEmptyFormat()
2455    || !ChkArgCnt(1, 1))
2456     return;
2457   if (*ArgStr[1].Str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
2458   else
2459   {
2460     Boolean OK;
2461     Byte Val = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt4, &OK);
2462 
2463     if (OK)
2464     {
2465       BAsmCode[CodeLen++] = Code;
2466       BAsmCode[CodeLen++] = Val;
2467     }
2468   }
2469 }
2470 
2471 /*!------------------------------------------------------------------------
2472  * \fn     DecodeRTD(Word Code)
2473  * \brief  instruction decoder for RTD instruction
2474  * \param  Code specific instruction code
2475  * ------------------------------------------------------------------------ */
2476 
DecodeRTD(Word Code)2477 static void DecodeRTD(Word Code)
2478 {
2479   if (!ChkEmptyFormat()
2480    || !ChkArgCnt(1, 1))
2481     return;
2482   else if (*ArgStr[1].Str != '#') WrStrErrorPos(ErrNum_OnlyImmAddr, &ArgStr[1]);
2483   else
2484   {
2485     Boolean OK;
2486     LongInt Val = EvalArg(&ArgStr[1], 1, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize, &OK);
2487 
2488     if (OK)
2489     {
2490       if (OpSize == eSymbolSizeUnknown)
2491         OpSize = DeduceSize(Val);
2492       BAsmCode[CodeLen++] = Code | OpSize;
2493       CodeLen += AppendBySize(BAsmCode + CodeLen, Val, OpSize);
2494     }
2495   }
2496 }
2497 
2498 /*!------------------------------------------------------------------------
2499  * \fn     DecodeLDM_STM(Word Code)
2500  * \brief  instruction decoder for LDM and STM instructions
2501  * \param  Code specific instruction code
2502  * ------------------------------------------------------------------------ */
2503 
DecodeLDM_STM(Word Code)2504 static void DecodeLDM_STM(Word Code)
2505 {
2506   Word RegList;
2507   tAdrVals AdrVals;
2508   Boolean IsLDM = !!(Code == 0x74);
2509 
2510   if (ChkEmptyFormat()
2511    && ChkOpSize(eSymbolSize16Bit, 7)
2512    && ChkArgCnt(2, ArgCntMax)
2513    && DecodeRegList(&RegList, 1 + IsLDM, ArgCnt - 1 + IsLDM)
2514    && DecodeAdr(&ArgStr[IsLDM ? 1 : ArgCnt], MModeAll - MModeImm - MModeReg, &AdrVals, EProgCounter() + 1))
2515   {
2516     BAsmCode[CodeLen++] = Code | OpSize;
2517     AppendAdrValsToCode(&AdrVals);
2518     BAsmCode[CodeLen++] = Hi(RegList);
2519     BAsmCode[CodeLen++] = Lo(RegList);
2520   }
2521 }
2522 
2523 /*!------------------------------------------------------------------------
2524  * \fn     DecodeCGBN(Word Code)
2525  * \brief  instruction decoder for CGBN instruction
2526  * \param  Code specific instruction code
2527  * ------------------------------------------------------------------------ */
2528 
DecodeCGBN(Word Code)2529 static void DecodeCGBN(Word Code)
2530 {
2531   tAdrVals AdrVals;
2532 
2533   if (ChkEmptyFormat()
2534    && CheckSup(&OpPart)
2535    && ChkOpSize(eSymbolSize8Bit, 1)
2536    && ChkArgCnt(1, ArgCntMax)
2537    && DecodeAdr(&ArgStr[1], MModeReg | MModeImm, &AdrVals, EProgCounter() + 1))
2538   {
2539     Word RegList = 0;
2540 
2541     if (ArgCnt >= 2)
2542     {
2543       if (!DecodeRegList(&RegList, 2, ArgCnt))
2544         return;
2545     }
2546     BAsmCode[CodeLen++] = Code | ((AdrVals.Mode == eAdrModeImm) ? 2 : 0) | !!RegList;
2547     BAsmCode[CodeLen++] = (AdrVals.Mode == eAdrModeImm) ? AdrVals.Vals[1] : (AdrVals.Vals[0] & 0x0f);
2548     if (RegList)
2549     {
2550       BAsmCode[CodeLen++] = Hi(RegList);
2551       BAsmCode[CodeLen++] = Lo(RegList);
2552     }
2553   }
2554 }
2555 
2556 /*!------------------------------------------------------------------------
2557  * \fn     DecodePGBN(Word Code)
2558  * \brief  instruction decoder for PGBN instruction
2559  * \param  Code specific instruction code
2560  * ------------------------------------------------------------------------ */
2561 
DecodePGBN(Word Code)2562 static void DecodePGBN(Word Code)
2563 {
2564   if (ChkEmptyFormat()
2565    && CheckSup(&OpPart)
2566    && ChkOpSize(eSymbolSize8Bit, 1)
2567    && ChkArgCnt(0, ArgCntMax))
2568   {
2569     Word RegList = 0;
2570 
2571     if (ArgCnt >= 1)
2572     {
2573       if (!DecodeRegList(&RegList, 1, ArgCnt))
2574         return;
2575     }
2576     BAsmCode[CodeLen++] = Code | !!RegList;
2577     if (RegList)
2578     {
2579       BAsmCode[CodeLen++] = Hi(RegList);
2580       BAsmCode[CodeLen++] = Lo(RegList);
2581     }
2582   }
2583 }
2584 
2585 /*!------------------------------------------------------------------------
2586  * \fn     DecodeMOVFP(Word Code)
2587  * \brief  instruction decoder for MOVFP instruction
2588  * \param  Code specific instruction code
2589  * ------------------------------------------------------------------------ */
2590 
DecodeMOVFP(Word Code)2591 static void DecodeMOVFP(Word Code)
2592 {
2593   tAdrVals SrcAdrVals, DestAdrVals;
2594 
2595   if (ChkEmptyFormat()
2596    && ChkOpSize(eSymbolSize16Bit, 6)
2597    && ChkArgCnt(2, 2)
2598    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 1)
2599    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2600   {
2601     BAsmCode[CodeLen++] = Code | (OpSize - 1);
2602     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2603   }
2604 }
2605 
2606 /*!------------------------------------------------------------------------
2607  * \fn     DecodeMOVFPE(Word Code)
2608  * \brief  instruction decoder for MOVFPE instruction
2609  * \param  Code specific instruction code
2610  * ------------------------------------------------------------------------ */
2611 
DecodeMOVFPE(Word Code)2612 static void DecodeMOVFPE(Word Code)
2613 {
2614   tAdrVals SrcAdrVals, DestAdrVals;
2615 
2616   if (ChkEmptyFormat()
2617    && ChkOpSize(eSymbolSize16Bit, 7)
2618    && ChkArgCnt(2, 2)
2619    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 1)
2620    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2621   {
2622     BAsmCode[CodeLen++] = Code | OpSize;
2623     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2624   }
2625 }
2626 
2627 /*!------------------------------------------------------------------------
2628  * \fn     DecodeMOVTP(Word Code)
2629  * \brief  instruction decoder for MOVTP instruction
2630  * \param  Code specific instruction code
2631  * ------------------------------------------------------------------------ */
2632 
DecodeMOVTP(Word Code)2633 static void DecodeMOVTP(Word Code)
2634 {
2635   tAdrVals SrcAdrVals, DestAdrVals;
2636 
2637   if (ChkEmptyFormat()
2638    && ChkOpSize(eSymbolSize16Bit, 6)
2639    && ChkArgCnt(2, 2)
2640    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
2641    && DecodeAdr(&ArgStr[2], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2642   {
2643     BAsmCode[CodeLen++] = Code | (OpSize - 1);
2644     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2645   }
2646 }
2647 
2648 /*!------------------------------------------------------------------------
2649  * \fn     DecodeMOVTPE(Word Code)
2650  * \brief  instruction decoder for MOVTPE instruction
2651  * \param  Code specific instruction code
2652  * ------------------------------------------------------------------------ */
2653 
DecodeMOVTPE(Word Code)2654 static void DecodeMOVTPE(Word Code)
2655 {
2656   tAdrVals SrcAdrVals, DestAdrVals;
2657 
2658   if (ChkEmptyFormat()
2659    && ChkOpSize(eSymbolSize16Bit, 7)
2660    && ChkArgCnt(2, 2)
2661    && DecodeAdr(&ArgStr[1], MModeAll, &SrcAdrVals, EProgCounter() + 1)
2662    && DecodeAdr(&ArgStr[2], MModeAll - MModeReg - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2663   {
2664     BAsmCode[CodeLen++] = Code | OpSize;
2665     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2666   }
2667 }
2668 
2669 /*!------------------------------------------------------------------------
2670  * \fn     DecodeMOVA(Word Code)
2671  * \brief  instruction decoder for MOVA instruction
2672  * \param  Code specific instruction code
2673  * ------------------------------------------------------------------------ */
2674 
DecodeMOVA(Word Code)2675 static void DecodeMOVA(Word Code)
2676 {
2677   tAdrVals SrcAdrVals, DestAdrVals;
2678 
2679   if (ChkEmptyFormat()
2680    && ChkOpSize(eSymbolSize32Bit, 4)
2681    && ChkArgCnt(2, 2)
2682    && DecodeAdr(&ArgStr[1], MModeAll - MModeReg - MModeImm, &SrcAdrVals, EProgCounter() + 1)
2683    && DecodeAdr(&ArgStr[2], MModeAll - MModeImm, &DestAdrVals, EProgCounter() + 1 + SrcAdrVals.Cnt))
2684   {
2685     BAsmCode[CodeLen++] = Code;
2686     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2687   }
2688 }
2689 
2690 /*!------------------------------------------------------------------------
2691  * \fn     DecodeString(Word Code)
2692  * \brief  decode string instruction
2693  * \param  Code specific instruction code
2694  * ------------------------------------------------------------------------ */
2695 
DecodeString(Word Code)2696 static void DecodeString(Word Code)
2697 {
2698   int ExpectArgCnt = (Code & 0x80) ? 4 : 3;
2699   unsigned SrcMask, DestMask = MModeReg | ((Code & 0x40) ? MModePre : MModePost);
2700   Byte SrcReg, DestReg, CntReg, FinalReg, Prefix;
2701 
2702   SrcMask = MModeReg;
2703   if (Code & 0x30) /* SCMP/SMOV */
2704     SrcMask |= (Code & 0x40) ? MModePre : MModePost;
2705   else if (Code & 0x80) /* SSCH */
2706     SrcMask |= MModeIReg;
2707 
2708   if (ChkEmptyFormat()
2709    && ChkOpSize(eSymbolSize16Bit, 3)
2710    && ChkArgCnt(ExpectArgCnt, ExpectArgCnt)
2711    && DecodeStringReg(&ArgStr[1], SrcMask, &SrcReg)
2712    && DecodeStringReg(&ArgStr[2], DestMask, &DestReg))
2713   {
2714     if (DecodeReg(&ArgStr[3], &CntReg, &Prefix, False, True))
2715     {
2716       if (4 == ExpectArgCnt)
2717       {
2718         if (!DecodeReg(&ArgStr[4], &FinalReg, &Prefix, False, True))
2719           return;
2720       }
2721       BAsmCode[CodeLen++] = 0x94 | OpSize;
2722       BAsmCode[CodeLen++] = Code | CntReg;
2723       BAsmCode[CodeLen++] = (SrcReg << 4) | DestReg;
2724       if (4 == ExpectArgCnt)
2725         BAsmCode[CodeLen++] = (FinalReg << 4) | Hi(Code);
2726     }
2727   }
2728 }
2729 
2730 /*!------------------------------------------------------------------------
2731  * \fn     DecodeBField(Word Code)
2732  * \brief  decode bit field instruction
2733  * \param  Code specific instruction code
2734  * ------------------------------------------------------------------------ */
2735 
DecodeBField(Word Code)2736 static void DecodeBField(Word Code)
2737 {
2738   tAdrVals SrcAdrVals, DestAdrVals;
2739   Byte PosReg, CntReg;
2740 
2741   if (OpSize != eSymbolSizeUnknown) WrError (ErrNum_InvOpSize);
2742   else if (ChkEmptyFormat()
2743         && ChkArgCnt(4, 4)
2744         && DecodeStringReg(&ArgStr[1], MModeReg, &PosReg)
2745         && DecodeStringReg(&ArgStr[2], MModeReg, &CntReg)
2746         && DecodeAdr(&ArgStr[3], MModeAll - MModePre - MModePost - MModeImm, &SrcAdrVals, EProgCounter() + 2)
2747         && DecodeAdr(&ArgStr[4], MModeAll - MModePre - MModePost - MModeImm, &DestAdrVals, EProgCounter() + 2 + SrcAdrVals.Cnt))
2748   {
2749     BAsmCode[CodeLen++] = Code;
2750     BAsmCode[CodeLen++] = (PosReg << 4) | CntReg;
2751     AppendAdrValPair(&SrcAdrVals, &DestAdrVals);
2752   }
2753 }
2754 
2755 /*!------------------------------------------------------------------------
2756  * \fn     DecodeBFMOV(Word Code)
2757  * \brief  decode bit field move instruction which is different from other bit field instructions
2758  * \param  Code specific instruction code
2759  * ------------------------------------------------------------------------ */
2760 
DecodeBFMOV(Word Code)2761 static void DecodeBFMOV(Word Code)
2762 {
2763   Byte XReg, BReg, YReg, OReg, SReg, DReg;
2764 
2765   if (OpSize != eSymbolSizeUnknown) WrError (ErrNum_InvOpSize);
2766   else if (ChkEmptyFormat()
2767         && ChkArgCnt(6, 6)
2768         && DecodeStringReg(&ArgStr[1], MModeReg, &XReg)
2769         && DecodeStringReg(&ArgStr[2], MModeReg, &BReg)
2770         && DecodeStringReg(&ArgStr[3], MModeReg, &YReg)
2771         && DecodeStringReg(&ArgStr[4], MModeReg, &OReg)
2772         && DecodeStringReg(&ArgStr[5], MModeReg | MModeIReg , &SReg)
2773         && DecodeStringReg(&ArgStr[6], MModeReg | MModeIReg , &DReg))
2774   {
2775     BAsmCode[CodeLen++] = Code;
2776     BAsmCode[CodeLen++] = (XReg << 4) | BReg;
2777     BAsmCode[CodeLen++] = (YReg << 4) | OReg;
2778     BAsmCode[CodeLen++] = (SReg << 4) | DReg;
2779   }
2780 }
2781 
2782 /*!------------------------------------------------------------------------
2783  * \fn     DecodeBit(Word Code)
2784  * \brief  decode CPU bit handling instruction
2785  * \param  Code specific instruction code
2786  * ------------------------------------------------------------------------ */
2787 
DecodeBit(Word Code)2788 static void DecodeBit(Word Code)
2789 {
2790   tSymbolSize ThisOpSize;
2791 
2792   if (!ChkEmptyFormat()
2793    || !ChkArgCnt(1, 2))
2794     return;
2795 
2796   /* bit "object": */
2797 
2798   if (1 == ArgCnt)
2799   {
2800     LongWord BitArg, Address;
2801     Byte ImmPos;
2802 
2803     if (DecodeBitArg(&BitArg, 1, 1, OpSize)
2804      && DissectBitSymbol(BitArg, &Address, &ImmPos, &ThisOpSize)
2805      && SetOpSize(ThisOpSize))
2806     {
2807       tSymbolSize AddressSize = DeduceSize16M(Address);
2808 
2809       /* SetOpSize() has set OpSize to 0..2 or confirmed it, no need to check for invalid size */
2810 
2811       BAsmCode[CodeLen++] = 0x6c | OpSize;
2812       BAsmCode[CodeLen++] = Code | ImmPos;
2813       BAsmCode[CodeLen++] = 0x74 | (AddressSize + 1);
2814       CodeLen += AppendBySize(BAsmCode + CodeLen, Address, AddressSize);
2815     }
2816   }
2817 
2818   /* bit + <ea> */
2819 
2820   else
2821   {
2822     tAdrVals EAAdrVals, BitAdrVals;
2823     unsigned Mask = MModeAll - ((Code == 0x60) ? 0 : MModeImm);
2824 
2825     if (ChkOpSize(eSymbolSize16Bit, 7)
2826      && DecodeAdr(&ArgStr[2], Mask, &EAAdrVals, EProgCounter() + 2))
2827     {
2828       ThisOpSize = OpSize;
2829       OpSize = eSymbolSize3Bit + OpSize;
2830       if (DecodeAdr(&ArgStr[1], MModeImm | MModeReg, &BitAdrVals, EProgCounter() + 1))
2831       {
2832         switch (BitAdrVals.Mode)
2833         {
2834           case eAdrModeReg:
2835             if (!GlobalBankReg(&BitAdrVals))
2836             {
2837               WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
2838               return;
2839             }
2840             BAsmCode[CodeLen++] = 0x64 | ThisOpSize;
2841             BAsmCode[CodeLen++] = Code | (BitAdrVals.Vals[0] & 15);
2842             break;
2843           case eAdrModeImm:
2844             BAsmCode[CodeLen++] = 0x6c | ThisOpSize;
2845             BAsmCode[CodeLen++] = Code | BitAdrVals.Vals[1];
2846             break;
2847           default:
2848             return;
2849         }
2850         AppendAdrValsToCode(&EAAdrVals);
2851       }
2852     }
2853   }
2854 }
2855 
2856 /*!------------------------------------------------------------------------
2857  * \fn     DecodeBIT(Word Code)
2858  * \brief  decode bit declaration instruction
2859  * ------------------------------------------------------------------------ */
2860 
DecodeBIT(Word Code)2861 static void DecodeBIT(Word Code)
2862 {
2863   LongWord BitSpec;
2864 
2865   UNUSED(Code);
2866 
2867   /* if in structure definition, add special element to structure */
2868 
2869   if (ActPC == StructSeg)
2870   {
2871     Boolean OK;
2872     Byte BitPos;
2873     PStructElem pElement;
2874 
2875     if (!ChkArgCnt(2, 2))
2876       return;
2877     BitPos = EvalBitPosition(&ArgStr[1], &OK, (OpSize == eSymbolSizeUnknown) ? eSymbolSize32Bit : OpSize);
2878     if (!OK)
2879       return;
2880     pElement = CreateStructElem(LabPart.Str);
2881     pElement->pRefElemName = as_strdup(ArgStr[2].Str);
2882     /* undefined op size -> take over from ref elem */
2883     pElement->OpSize = OpSize;
2884     pElement->BitPos = BitPos;
2885     pElement->ExpandFnc = ExpandH16Bit;
2886     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
2887   }
2888   else
2889   {
2890     if (!ChkOpSize(eSymbolSize16Bit, 7))
2891       return;
2892 
2893     if (DecodeBitArg(&BitSpec, 1, ArgCnt, OpSize))
2894     {
2895       *ListLine = '=';
2896       DissectBit_H16(ListLine + 1, STRINGSIZE - 3, BitSpec);
2897       PushLocHandle(-1);
2898       EnterIntSymbol(&LabPart, BitSpec, SegBData, False);
2899       PopLocHandle();
2900       /* TODO: MakeUseList? */
2901     }
2902   }
2903 }
2904 
2905 /*---------------------------------------------------------------------------*/
2906 
2907 /*!------------------------------------------------------------------------
2908  * \fn     AddCondition(const char *pName, Word Code)
2909  * \brief  register condition to instruction hash table
2910  * \param  pName name of condition
2911  * \param  Code binary coding of condition
2912  * ------------------------------------------------------------------------ */
2913 
AddCondition(const char * pName,Word Code)2914 static void AddCondition(const char *pName, Word Code)
2915 {
2916   char Name[20];
2917 
2918   as_snprintf(Name, sizeof(Name), "B%s", pName);
2919   AddInstTable(InstTable, Name, Code, DecodeBranchGen);
2920   as_snprintf(Name, sizeof(Name), "SET/%s", pName);
2921   AddInstTable(InstTable, Name, Code, DecodeSET);
2922   as_snprintf(Name, sizeof(Name), "TRAP/%s", pName);
2923   AddInstTable(InstTable, Name, Code, DecodeTRAP);
2924   as_snprintf(Name, sizeof(Name), "SCB/%s", pName);
2925   AddInstTable(InstTable, Name, Code, DecodeSCB);
2926   as_snprintf(Name, sizeof(Name), "SCMP/%s/F", pName);
2927   AddInstTable(InstTable, Name, 0x00a0 | (Code << 8), DecodeString);
2928   as_snprintf(Name, sizeof(Name), "SCMP/%s/B", pName);
2929   AddInstTable(InstTable, Name, 0x00d0 | (Code << 8), DecodeString);
2930   as_snprintf(Name, sizeof(Name), "SSCH/%s/F", pName);
2931   AddInstTable(InstTable, Name, 0x0080 | (Code << 8), DecodeString);
2932   as_snprintf(Name, sizeof(Name), "SSCH/%s/B", pName);
2933   /* per-instr. description gives 000 for both SSCH variants, taken from Figure 16-9: */
2934   AddInstTable(InstTable, Name, 0x00c0 | (Code << 8), DecodeString);
2935 }
2936 
2937 /*!------------------------------------------------------------------------
2938  * \fn     InitFields(void)
2939  * \brief  build up instruction hash table
2940  * ------------------------------------------------------------------------ */
2941 
InitFields(void)2942 static void InitFields(void)
2943 {
2944   InstTable = CreateInstTable(307);
2945   SetDynamicInstTable(InstTable);
2946 
2947   AddInstTable(InstTable, "MOV", 0x0c, DecodeMOV_ADD_SUB_CMP);
2948   AddInstTable(InstTable, "ADD", 0x00, DecodeMOV_ADD_SUB_CMP);
2949   AddInstTable(InstTable, "SUB", 0x04, DecodeMOV_ADD_SUB_CMP);
2950   AddInstTable(InstTable, "CMP", 0x08, DecodeMOV_ADD_SUB_CMP);
2951 
2952   AddInstTable(InstTable, "MOVS", 0x4c, DecodeSignExt);
2953   AddInstTable(InstTable, "ADDS", 0x40, DecodeSignExt);
2954   AddInstTable(InstTable, "SUBS", 0x44, DecodeSignExt);
2955   AddInstTable(InstTable, "CMPS", 0x48, DecodeSignExt);
2956 
2957   AddInstTable(InstTable, "ADDX", 0x50, DecodeTwo);
2958   AddInstTable(InstTable, "SUBX", 0x54, DecodeTwo);
2959   AddInstTable(InstTable, "AND" , 0x80, DecodeTwo);
2960   AddInstTable(InstTable, "OR"  , 0x88, DecodeTwo);
2961   AddInstTable(InstTable, "XOR" , 0x84, DecodeTwo);
2962   AddInstTable(InstTable, "DADD", 0x83, DecodeTwo);
2963   AddInstTable(InstTable, "DSUB", 0x87, DecodeTwo);
2964 
2965   AddInstTable(InstTable, "MULXS" , 0x00, DecodeMUL_DIV);
2966   AddInstTable(InstTable, "MULXU" , 0x40, DecodeMUL_DIV);
2967   AddInstTable(InstTable, "DIVXS" , 0x01, DecodeMUL_DIV);
2968   AddInstTable(InstTable, "DIVXU" , 0x41, DecodeMUL_DIV);
2969 
2970   AddInstTable(InstTable, "NEG"  , 0x8c, DecodeOne);
2971   AddInstTable(InstTable, "NEGX" , 0x9c, DecodeOne);
2972   AddInstTable(InstTable, "NOT"  , 0x90, DecodeOne);
2973   AddInstTable(InstTable, "TST"  , 0x58, DecodeOne);
2974   AddInstTable(InstTable, "CLR"  , 0x14, DecodeOne);
2975   AddInstTable(InstTable, "DNEG" , 0xaf, DecodeOne);
2976   AddInstTable(InstTable, "TAS"  , 0xee, DecodeOne);
2977   AddInstTable(InstTable, "MOVF" , 0x5c, DecodeOne);
2978 
2979   AddInstTable(InstTable, "EXTS" , 0xbc, DecodeEXT);
2980   AddInstTable(InstTable, "EXTU" , 0xac, DecodeEXT);
2981 
2982   AddInstTable(InstTable, "ANDC" , 0xf8, DecodeCInstr);
2983   AddInstTable(InstTable, "ORC"  , 0xf9, DecodeCInstr);
2984   AddInstTable(InstTable, "XORC" , 0xfa, DecodeCInstr);
2985   AddInstTable(InstTable, "LDC"  , 0xfb, DecodeCInstr);
2986   AddInstTable(InstTable, "STC"  , 0xfc, DecodeCInstr);
2987 
2988   AddInstTable(InstTable, "BRA"  , 0x98, DecodeBranch);
2989   AddInstTable(InstTable, "BSR"  , 0xa8, DecodeBranch);
2990   AddCondition("CC" , 0x04);
2991   AddCondition("HS" , 0x04);
2992   AddCondition("CS" , 0x05);
2993   AddCondition("LO" , 0x05);
2994   AddCondition("NE" , 0x06);
2995   AddCondition("EQ" , 0x07);
2996   AddCondition("GE" , 0x0c);
2997   AddCondition("LT" , 0x0d);
2998   AddCondition("GT" , 0x0e);
2999   AddCondition("LE" , 0x0f);
3000   AddCondition("HI" , 0x02);
3001   AddCondition("LS" , 0x03);
3002   AddCondition("PL" , 0x0a);
3003   AddCondition("MI" , 0x0b);
3004   AddCondition("VC" , 0x08);
3005   AddCondition("VS" , 0x09);
3006   AddCondition("T"  , 0x00);
3007   AddCondition("F"  , 0x01);
3008 
3009   AddInstTable(InstTable, "RTS"  , 0x00bb, DecodeFixed);
3010   AddInstTable(InstTable, "RESET", 0x80f0, DecodeFixed);
3011   AddInstTable(InstTable, "RTE"  , 0x80f1, DecodeFixed);
3012   AddInstTable(InstTable, "RTR"  , 0x00f4, DecodeFixed);
3013   AddInstTable(InstTable, "SLEEP", 0x80f5, DecodeFixed);
3014   AddInstTable(InstTable, "NOP"  , 0x00ff, DecodeFixed);
3015   AddInstTable(InstTable, "DCBN" , 0x00fe, DecodeFixed);
3016   AddInstTable(InstTable, "ICBN" , 0x00fd, DecodeFixed);
3017 
3018   AddInstTable(InstTable, "SHAR"  , 0 << 5, DecodeShift);
3019   AddInstTable(InstTable, "SHLR"  , 1 << 5, DecodeShift);
3020   AddInstTable(InstTable, "ROTR"  , 2 << 5, DecodeShift);
3021   AddInstTable(InstTable, "ROTXR" , 3 << 5, DecodeShift);
3022   AddInstTable(InstTable, "SHAL"  , 4 << 5, DecodeShift);
3023   AddInstTable(InstTable, "SHLL"  , 5 << 5, DecodeShift);
3024   AddInstTable(InstTable, "ROTL"  , 6 << 5, DecodeShift);
3025   AddInstTable(InstTable, "ROTXL" , 7 << 5, DecodeShift);
3026 
3027   AddInstTable(InstTable, "JMP" , 0x9b, DecodeJMP_JSR);
3028   AddInstTable(InstTable, "JSR" , 0xab, DecodeJMP_JSR);
3029   AddInstTable(InstTable, "SWAP", 0xea, DecodeSWAP);
3030   AddInstTable(InstTable, "XCH" , 0xb3, DecodeXCH);
3031 
3032   AddInstTable(InstTable, "LINK", 0xd0, DecodeLINK);
3033   AddInstTable(InstTable, "UNLK", 0xd3, DecodeUNLK);
3034   AddInstTable(InstTable, "TRAPA",0xf2, DecodeTRAPA);
3035   AddInstTable(InstTable, "RTD" , 0xb8, DecodeRTD);
3036 
3037   AddInstTable(InstTable, "LDM" , 0x74, DecodeLDM_STM);
3038   AddInstTable(InstTable, "STM" , 0x70, DecodeLDM_STM);
3039   AddInstTable(InstTable, "CGBN", 0xe4, DecodeCGBN);
3040   AddInstTable(InstTable, "PGBN", 0xe8, DecodePGBN);
3041 
3042   AddInstTable(InstTable, "MOVFP",0xe2, DecodeMOVFP);
3043   AddInstTable(InstTable, "MOVFPE",0x7c, DecodeMOVFPE);
3044   AddInstTable(InstTable, "MOVTP",0xe0, DecodeMOVTP);
3045   AddInstTable(InstTable, "MOVTPE",0x78, DecodeMOVTPE);
3046   AddInstTable(InstTable, "MOVA", 0xbf, DecodeMOVA);
3047 
3048   AddInstTable(InstTable, "SMOV/F", 0x0020, DecodeString);
3049   AddInstTable(InstTable, "SMOV/B", 0x0050, DecodeString);
3050   AddInstTable(InstTable, "SSTR/F", 0x0000, DecodeString);
3051   AddInstTable(InstTable, "SSTR/B", 0x0040, DecodeString);
3052 
3053   AddInstTable(InstTable, "BFEXT", 0xd4, DecodeBField);
3054   AddInstTable(InstTable, "BFINS", 0xd5, DecodeBField);
3055   AddInstTable(InstTable, "BFSCH", 0xd6, DecodeBField);
3056   AddInstTable(InstTable, "BFMOV", 0xd7, DecodeBFMOV);
3057 
3058   AddInstTable(InstTable, "BCLR", 0x40, DecodeBit);
3059   AddInstTable(InstTable, "BNOT", 0x20, DecodeBit);
3060   AddInstTable(InstTable, "BSET", 0x00, DecodeBit);
3061   AddInstTable(InstTable, "BTST", 0x60, DecodeBit);
3062 
3063   AddInstTable(InstTable, "BIT", 0, DecodeBIT);
3064   AddInstTable(InstTable, "REG", 0, CodeREG);
3065 }
3066 
3067 /*!------------------------------------------------------------------------
3068  * \fn     DeinitFields(void)
3069  * \brief  tear down instruction hash table
3070  * ------------------------------------------------------------------------ */
3071 
DeinitFields(void)3072 static void DeinitFields(void)
3073 {
3074   DestroyInstTable(InstTable);
3075 }
3076 
3077 /*---------------------------------------------------------------------------*/
3078 
3079 /*!------------------------------------------------------------------------
3080  * \fn     MakeCode_H16(void)
3081  * \brief  general entry point to parse machine instructions
3082  * ------------------------------------------------------------------------ */
3083 
DecodeAttrPart_H16(void)3084 static Boolean DecodeAttrPart_H16(void)
3085 {
3086   tStrComp SizePart;
3087   char *p;
3088   static char EmptyStr[] = "";
3089 
3090   /* split off format and operand size */
3091 
3092   switch (AttrSplit)
3093   {
3094     case '.':
3095       p = strchr(AttrPart.Str, ':');
3096       if (p)
3097         StrCompSplitRef(&SizePart, &FormatPart, &AttrPart, p);
3098       else
3099       {
3100         StrCompRefRight(&SizePart, &AttrPart, 0);
3101         StrCompMkTemp(&FormatPart, EmptyStr);
3102       }
3103       break;
3104     case ':':
3105       p = strchr(AttrPart.Str, '.');
3106       if (p)
3107         StrCompSplitRef(&FormatPart, &SizePart, &AttrPart, p);
3108       else
3109       {
3110         StrCompRefRight(&FormatPart, &AttrPart, 0);
3111         StrCompMkTemp(&SizePart, EmptyStr);
3112       }
3113       break;
3114     default:
3115       StrCompMkTemp(&FormatPart, EmptyStr);
3116       StrCompMkTemp(&SizePart, EmptyStr);
3117       break;
3118   }
3119 
3120   /* process operand size part of attribute */
3121 
3122   if (*SizePart.Str)
3123   {
3124     if (!DecodeMoto16AttrSizeStr(&SizePart, &AttrPartOpSize, False))
3125       return False;
3126   }
3127   return True;
3128 }
3129 
MakeCode_H16(void)3130 static void MakeCode_H16(void)
3131 {
3132   CodeLen = 0; DontPrint = False;
3133 
3134   /* zu ignorierendes */
3135 
3136   if (Memo("")) return;
3137 
3138   OpSize = AttrPartOpSize;
3139   if (DecodeMoto16Pseudo(OpSize, True))
3140     return;
3141 
3142   if (!LookupInstTable(InstTable, OpPart.Str))
3143     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
3144 }
3145 
3146 /*!------------------------------------------------------------------------
3147  * \fn     SwitchFrom_H16(void)
3148  * \brief  cleanups to do after switching to other target
3149  * ------------------------------------------------------------------------ */
3150 
SwitchFrom_H16(void)3151 static void SwitchFrom_H16(void)
3152 {
3153   DeinitFields();
3154   ClearONOFF();
3155 }
3156 
3157 /*!------------------------------------------------------------------------
3158  * \fn     IsDef_H16(void)
3159  * \brief  instruction that uses up label field?
3160  * \return true if label field shall not be stored as label
3161  * ------------------------------------------------------------------------ */
3162 
IsDef_H16(void)3163 static Boolean IsDef_H16(void)
3164 {
3165   return Memo("BIT") || Memo("REG");
3166 }
3167 
3168 /*!------------------------------------------------------------------------
3169  * \fn     InternSymbol_H16(char *pArg, TempResult *pResult)
3170  * \brief  handle built-in symbols on H16
3171  * \param  pArg source argument
3172  * \param  pResult result buffer
3173  * ------------------------------------------------------------------------ */
3174 
InternSymbol_H16(char * pArg,TempResult * pResult)3175 static void InternSymbol_H16(char *pArg, TempResult *pResult)
3176 {
3177   Byte Reg, Prefix;
3178 
3179   if (DecodeRegCore(pArg, &Reg, &Prefix))
3180   {
3181     pResult->Typ = TempReg;
3182     pResult->DataSize = eSymbolSize32Bit;
3183     pResult->Contents.RegDescr.Reg = ((Word)Prefix) << 8 | Reg;
3184     pResult->Contents.RegDescr.Dissect = DissectReg_H16;
3185   }
3186 }
3187 
3188 /*!------------------------------------------------------------------------
3189  * \fn     SwitchTo_H16(void)
3190  * \brief  things to do when switching to H16 as target
3191  * ------------------------------------------------------------------------ */
3192 
SwitchTo_H16(void)3193 static void SwitchTo_H16(void)
3194 {
3195   const PFamilyDescr pDescr = FindFamilyByName("H16");
3196 
3197   TurnWords = False;
3198   ConstMode = ConstModeMoto;
3199 
3200   PCSymbol = "*";
3201   HeaderID = pDescr->Id;
3202   NOPCode = 0xff;
3203   DivideChars = ",";
3204   HasAttrs = True;
3205   AttrChars = ".:";
3206 
3207   ValidSegs = (1 << SegCode);
3208   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
3209   SegLimits[SegCode] = 0xffffff;
3210 
3211   DecodeAttrPart = DecodeAttrPart_H16;
3212   MakeCode = MakeCode_H16;
3213   IsDef = IsDef_H16;
3214   SwitchFrom = SwitchFrom_H16;
3215   DissectBit = DissectBit_H16;
3216   DissectReg = DissectReg_H16;
3217   InternSymbol = InternSymbol_H16;
3218   InitFields();
3219 
3220   AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName, False);
3221   AddMoto16PseudoONOFF();
3222 
3223   /* H16 code is byte-oriented, so no padding by default */
3224 
3225   SetFlag(&DoPadding, DoPaddingName, False);
3226 }
3227 
3228 /*!------------------------------------------------------------------------
3229  * \fn     codeh16_init(void)
3230  * \brief  register H16 to upper layers as target
3231  * ------------------------------------------------------------------------ */
3232 
codeh16_init(void)3233 void codeh16_init(void)
3234 {
3235   CPU641016 = AddCPU("HD641016", SwitchTo_H16);
3236 }
3237