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