1 /* codemsp.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Codegenerator MSP430 */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12
13 #include <ctype.h>
14 #include <string.h>
15
16 #include "nls.h"
17 #include "endian.h"
18 #include "strutil.h"
19 #include "bpemu.h"
20 #include "chunks.h"
21 #include "errmsg.h"
22 #include "asmdef.h"
23 #include "asmsub.h"
24 #include "asmcode.h"
25 #include "asmpars.h"
26 #include "asmallg.h"
27 #include "asmitree.h"
28 #include "codepseudo.h"
29 #include "codevars.h"
30
31 #define OneOpCount 6
32
33 typedef struct
34 {
35 Boolean MayByte;
36 Word Code;
37 } OneOpOrder;
38
39 typedef enum
40 {
41 eModeReg = 0,
42 eModeRegDisp = 1,
43 eModeIReg = 2,
44 eModeIRegAutoInc = 3,
45 eModeNone = 0xff
46 } tMode;
47
48 #define MModeReg (1 << eModeReg)
49 #define MModeRegDisp (1 << eModeRegDisp)
50 #define MModeIReg (1 << eModeIReg)
51 #define MModeIRegAutoInc (1 << eModeIRegAutoInc)
52 #define MModeAs 15
53 #define MModeAd 3
54
55 typedef enum
56 {
57 eExtModeNo = 0,
58 eExtModeYes = 1
59 } tExtMode;
60
61 typedef enum
62 {
63 eOpSizeB = 0,
64 eOpSizeW = 1,
65 eOpSizeA = 2,
66 eOpSizeCnt,
67 eOpSizeDefault = eOpSizeW
68 } tOpSize;
69
70 #define RegPC 0
71 #define RegSP 1
72 #define RegSR 2
73 #define RegCG1 2
74 #define RegCG2 3
75
76 #define REG_PC 0
77 #define REG_SP 1
78 #define REG_SR 2
79 #define REG_MARK 16 /* internal mark to differentiate PC<->R0, SP<->R1, and SR<->R2 */
80
81 typedef struct
82 {
83 Word Mode, Part, Cnt;
84 LongWord Val;
85 Boolean WasImm, WasAbs;
86 } tAdrParts;
87
88 /* float exp (8bit bias 128) sign mant (impl. norm.)
89 double exp (8bit bias 128) sign mant (impl. norm.) */
90
91 static CPUVar CPUMSP430, CPUMSP430X;
92
93 static OneOpOrder *OneOpOrders;
94
95 static tOpSize OpSize;
96 static Word PCDist, MultPrefix;
97 static IntType AdrIntType, DispIntType;
98 static const IntType OpSizeIntTypes[eOpSizeCnt] = { Int8, Int16, Int20 };
99
100 /*-------------------------------------------------------------------------*/
101
ResetAdr(tAdrParts * pAdrParts)102 static void ResetAdr(tAdrParts *pAdrParts)
103 {
104 pAdrParts->Mode = eModeNone;
105 pAdrParts->Part = 0;
106 pAdrParts->Cnt = 0;
107 pAdrParts->WasImm =
108 pAdrParts->WasAbs = False;
109 }
110
ChkAdr(Byte Mask,tAdrParts * pAdrParts)111 static Boolean ChkAdr(Byte Mask, tAdrParts *pAdrParts)
112 {
113 if ((pAdrParts->Mode != 0xff) && ((Mask & (1 << pAdrParts->Mode)) == 0))
114 {
115 ResetAdr(pAdrParts);
116 WrError(ErrNum_InvAddrMode);
117 return False;
118 }
119 return True;
120 }
121
122 /*!------------------------------------------------------------------------
123 * \fn DecodeRegCore(const char *pArg, Word *pResult)
124 * \brief check whether argument is a CPU register
125 * \param pArg argument to check
126 * \param pResult numeric register value if yes
127 * \return True if yes
128 * ------------------------------------------------------------------------ */
129
DecodeRegCore(const char * pArg,Word * pResult)130 static Boolean DecodeRegCore(const char *pArg, Word *pResult)
131 {
132 if (!as_strcasecmp(pArg, "PC"))
133 {
134 *pResult = REG_MARK | REG_PC; return True;
135 }
136 else if (!as_strcasecmp(pArg,"SP"))
137 {
138 *pResult = REG_MARK | REG_SP; return True;
139 }
140 else if (!as_strcasecmp(pArg, "SR"))
141 {
142 *pResult = REG_MARK | REG_SR; return True;
143 }
144 if ((as_toupper(*pArg) == 'R') && (strlen(pArg) >= 2) && (strlen(pArg) <= 3))
145 {
146 Boolean OK;
147
148 *pResult = ConstLongInt(pArg + 1, &OK, 10);
149 return OK && (*pResult < 16);
150 }
151
152 return False;
153 }
154
155 /*!------------------------------------------------------------------------
156 * \fn DissectReg_MSP(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
157 * \brief dissect register symbols - MSP variant
158 * \param pDest destination buffer
159 * \param DestSize destination buffer size
160 * \param Value numeric register value
161 * \param InpSize register size
162 * ------------------------------------------------------------------------ */
163
DissectReg_MSP(char * pDest,size_t DestSize,tRegInt Value,tSymbolSize InpSize)164 static void DissectReg_MSP(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
165 {
166 switch (InpSize)
167 {
168 case eSymbolSize8Bit:
169 switch (Value)
170 {
171 case REG_MARK | REG_PC:
172 as_snprintf(pDest, DestSize, "PC");
173 break;
174 case REG_MARK | REG_SP:
175 as_snprintf(pDest, DestSize, "SP");
176 break;
177 case REG_MARK | REG_SR:
178 as_snprintf(pDest, DestSize, "SR");
179 break;
180 default:
181 as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
182 }
183 break;
184 default:
185 as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
186 }
187 }
188
189 /*!------------------------------------------------------------------------
190 * \fn DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
191 * \brief check whether argument is a CPU register or register alias
192 * \param pArg argument to check
193 * \param pResult numeric register value if yes
194 * \param MustBeReg excpecting register as arg
195 * \return True if yes
196 * ------------------------------------------------------------------------ */
197
DecodeReg(const tStrComp * pArg,Word * pResult,Boolean MustBeReg)198 static Boolean DecodeReg(const tStrComp *pArg, Word *pResult, Boolean MustBeReg)
199 {
200 tRegDescr RegDescr;
201 tEvalResult EvalResult;
202 tRegEvalResult RegEvalResult;
203
204 if (DecodeRegCore(pArg->Str, pResult))
205 {
206 *pResult &= ~REG_MARK;
207 return True;
208 }
209
210 RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize8Bit, MustBeReg);
211 *pResult = RegDescr.Reg & ~REG_MARK;
212 return (RegEvalResult == eIsReg);
213 }
214
FillAdrPartsImm(tAdrParts * pAdrParts,LongWord Value,Boolean ForceLong)215 static void FillAdrPartsImm(tAdrParts *pAdrParts, LongWord Value, Boolean ForceLong)
216 {
217 ResetAdr(pAdrParts);
218 pAdrParts->WasImm = True;
219 pAdrParts->Val = Value;
220
221 /* assume no usage of constant generators */
222
223 pAdrParts->Part = RegPC;
224
225 /* constant generators allowed at all? */
226
227 if (!ForceLong)
228 {
229 /* special treatment for -1 since it depends on the operand size: */
230
231 if ((Value == 0xffffffff)
232 || ((OpSize == eOpSizeB) && (Value == 0xff))
233 || ((OpSize == eOpSizeW) && (Value == 0xffff))
234 || ((OpSize == eOpSizeA) && (Value == 0xfffff)))
235 {
236 pAdrParts->Cnt = 0;
237 pAdrParts->Part = RegCG2;
238 pAdrParts->Mode = eModeIRegAutoInc;
239 }
240 else switch (Value)
241 {
242 case 0:
243 pAdrParts->Part = RegCG2;
244 pAdrParts->Mode = eModeReg;
245 break;
246 case 1:
247 pAdrParts->Part = RegCG2;
248 pAdrParts->Mode = eModeRegDisp;
249 break;
250 case 2:
251 pAdrParts->Part = RegCG2;
252 pAdrParts->Mode = eModeIReg;
253 break;
254 case 4:
255 pAdrParts->Part = RegCG1;
256 pAdrParts->Mode = eModeIReg;
257 break;
258 case 8:
259 pAdrParts->Part = RegCG1;
260 pAdrParts->Mode = eModeIRegAutoInc;
261 break;
262 default:
263 break;
264 }
265 }
266
267 /* constant generators not used, in one or the other way -> use
268 @PC++ to dispose constant */
269
270 if (pAdrParts->Part == RegPC)
271 {
272 pAdrParts->Cnt = 1;
273 pAdrParts->Mode = eModeIRegAutoInc;
274 }
275 }
276
DecodeAdr(const tStrComp * pArg,tExtMode ExtMode,Byte Mask,Boolean MayImm,tAdrParts * pAdrParts)277 static Boolean DecodeAdr(const tStrComp *pArg, tExtMode ExtMode, Byte Mask, Boolean MayImm, tAdrParts *pAdrParts)
278 {
279 LongWord AdrWord, CurrPC;
280 Word Reg;
281 Boolean OK;
282 char *p;
283 IntType ThisAdrIntType = (ExtMode == eExtModeYes) ? AdrIntType : UInt16;
284 IntType ThisDispIntType = (ExtMode == eExtModeYes) ? DispIntType : Int16;
285 int ArgLen;
286
287 ResetAdr(pAdrParts);
288
289 /* immediate */
290
291 if (*pArg->Str == '#')
292 {
293 if (!MayImm) WrError(ErrNum_InvAddrMode);
294 else
295 {
296 int ForceLong = (pArg->Str[1] == '>') ? 1 : 0;
297
298 AdrWord = EvalStrIntExpressionOffs(pArg, 1 + ForceLong, OpSizeIntTypes[OpSize], &OK);
299 if (OK)
300 {
301 FillAdrPartsImm(pAdrParts, AdrWord, ForceLong);
302 }
303 }
304 return ChkAdr(Mask, pAdrParts);
305 }
306
307 /* absolut */
308
309 if (*pArg->Str == '&')
310 {
311 pAdrParts->Val = EvalStrIntExpressionOffs(pArg, 1, ThisAdrIntType, &OK);
312 if (OK)
313 {
314 pAdrParts->WasAbs = True;
315 pAdrParts->Mode = eModeRegDisp;
316 pAdrParts->Part = RegCG1; /* == 0 with As/Ad=1 */
317 pAdrParts->Cnt = 1;
318 }
319 return ChkAdr(Mask, pAdrParts);
320 }
321
322 /* Register */
323
324 switch (DecodeReg(pArg, &Reg, False))
325 {
326 case eIsReg:
327 if (Reg == RegCG2) WrStrErrorPos(ErrNum_InvReg, pArg);
328 else
329 {
330 pAdrParts->Mode = eModeReg;
331 pAdrParts->Part = Reg;
332 }
333 return ChkAdr(Mask, pAdrParts);
334 case eIsNoReg:
335 break;
336 case eRegAbort:
337 return False;
338 }
339
340 /* Displacement */
341
342 ArgLen = strlen(pArg->Str);
343 if ((*pArg->Str) && (pArg->Str[ArgLen - 1] == ')'))
344 {
345 tStrComp Arg = *pArg;
346
347 StrCompShorten(&Arg, 1);
348 p = RQuotPos(Arg.Str, '(');
349 if (p)
350 {
351 tStrComp RegComp, OffsComp;
352 char Save;
353
354 Save = StrCompSplitRef(&OffsComp, &RegComp, &Arg, p);
355 if (DecodeReg(&RegComp, &Reg, True) == eIsReg)
356 {
357 pAdrParts->Val = EvalStrIntExpression(&OffsComp, ThisDispIntType, &OK);
358 if (OK)
359 {
360 if ((Reg == 2) || (Reg == 3)) WrStrErrorPos(ErrNum_InvReg, &RegComp);
361 else if ((pAdrParts->Val == 0) && ((Mask & 4) != 0))
362 {
363 pAdrParts->Part = Reg;
364 pAdrParts->Mode = eModeIReg;
365 }
366 else
367 {
368 pAdrParts->Part = Reg;
369 pAdrParts->Cnt = 1;
370 pAdrParts->Mode = eModeRegDisp;
371 }
372 }
373 }
374 *p = Save;
375 }
376 pArg->Str[ArgLen - 1] = ')';
377
378 if (pAdrParts->Mode != eModeNone)
379 return ChkAdr(Mask, pAdrParts);
380 }
381
382 /* indirekt mit/ohne Autoinkrement */
383
384 if ((*pArg->Str == '@') || (*pArg->Str == '*'))
385 {
386 Boolean AutoInc = False;
387 tStrComp Arg;
388
389 StrCompRefRight(&Arg, pArg, 1);
390 ArgLen = strlen(Arg.Str);
391 if (Arg.Str[ArgLen - 1] == '+')
392 {
393 AutoInc = True;
394 StrCompShorten(&Arg, 1);
395 }
396 if (DecodeReg(&Arg, &Reg, True) != eIsReg);
397 else if ((Reg == 2) || (Reg == 3)) WrStrErrorPos(ErrNum_InvReg, &Arg);
398 else if (!AutoInc && ((Mask & MModeIReg) == 0))
399 {
400 pAdrParts->Part = Reg;
401 pAdrParts->Val = 0;
402 pAdrParts->Cnt = 1;
403 pAdrParts->Mode = eModeRegDisp;
404 }
405 else
406 {
407 pAdrParts->Part = Reg;
408 pAdrParts->Mode = AutoInc ? eModeIRegAutoInc : eModeIReg;
409 }
410 return ChkAdr(Mask, pAdrParts);
411 }
412
413 /* bleibt PC-relativ aka 'symbolic mode': */
414
415 if (!PCDist)
416 {
417 fprintf(stderr, "internal error: PCDist not set for '%s'\n", OpPart.Str);
418 exit(10);
419 }
420 CurrPC = EProgCounter() + PCDist;
421
422 /* extended instruction (on 430X): use the full 20 bit displacement: */
423
424 if (ExtMode == eExtModeYes)
425 {
426 AdrWord = (EvalStrIntExpression(pArg, UInt20, &OK) - CurrPC) & 0xfffff;
427 }
428
429 /* non-extended instruction on 430X: if the current PC is within the
430 first 64K, bits 16..19 will be cleared after addition, i.e. the
431 target address must also be within the first 64K: */
432
433 else if (MomCPU >= CPUMSP430X)
434 {
435 if (CurrPC <= 0xffff)
436 {
437 AdrWord = (EvalStrIntExpression(pArg, UInt16, &OK) - CurrPC) & 0xffff;
438 }
439 else
440 {
441 AdrWord = (EvalStrIntExpression(pArg, UInt20, &OK) - CurrPC) & 0xfffff;
442 if ((AdrWord > 0x7fff) && (AdrWord < 0xf8000))
443 {
444 WrError(ErrNum_OverRange);
445 OK = False;
446 }
447 }
448 }
449
450 /* non-extended instruction on 430: all within 64K with wraparound */
451
452 else
453 {
454 AdrWord = (EvalStrIntExpression(pArg, UInt16, &OK) - CurrPC) & 0xffff;
455 }
456
457 if (OK)
458 {
459 pAdrParts->Part = RegPC;
460 pAdrParts->Mode = eModeRegDisp;
461 pAdrParts->Cnt = 1;
462 pAdrParts->Val = AdrWord;
463 }
464
465 return ChkAdr(Mask, pAdrParts);
466 }
467
GetBW(void)468 static Word GetBW(void)
469 {
470 return (OpSize == eOpSizeB) || (OpSize == eOpSizeA) ? 0x0040 : 0x0000;
471 }
472
GetAL(void)473 static Word GetAL(void)
474 {
475 return (OpSize == eOpSizeW) || (OpSize == eOpSizeB) ? 0x0040 : 0x0000;
476 }
477
GetMult(const tStrComp * pArg,Boolean * pOK)478 static Word GetMult(const tStrComp *pArg, Boolean *pOK)
479 {
480 Word Result = 0x0000;
481
482 switch (DecodeReg(pArg, &Result, False))
483 {
484 case eIsReg:
485 *pOK = True;
486 return Result | 0x0080;
487 break;
488 case eIsNoReg:
489 break;
490 case eRegAbort:
491 *pOK = False;
492 return 0;
493 }
494
495 if (*pArg->Str == '#')
496 {
497 tSymbolFlags Flags;
498
499 Result = EvalStrIntExpressionOffsWithFlags(pArg, 1, UInt5, pOK, &Flags);
500 if (*pOK)
501 {
502 if (mFirstPassUnknown(Flags))
503 Result = 1;
504 if (!ChkRange(Result, 1, 16))
505 *pOK = False;
506 else
507 Result--;
508 }
509 }
510 else
511 *pOK = False;
512 return Result;
513 }
514
515 /*-------------------------------------------------------------------------*/
516
PutByte(Word Value)517 static void PutByte(Word Value)
518 {
519 if (CodeLen & 1)
520 WAsmCode[CodeLen >> 1] = (Value << 8) | BAsmCode[CodeLen - 1];
521 else
522 BAsmCode[CodeLen] = Value;
523 CodeLen++;
524 }
525
ConstructTwoOp(Word Code,const tAdrParts * pSrcParts,const tAdrParts * pDestParts)526 static void ConstructTwoOp(Word Code, const tAdrParts *pSrcParts, const tAdrParts *pDestParts)
527 {
528 WAsmCode[CodeLen >> 1] = Code | (pSrcParts->Part << 8) | (pDestParts->Mode << 7)
529 | GetBW() | (pSrcParts->Mode << 4) | pDestParts->Part;
530 CodeLen += 2;
531 memcpy(WAsmCode + (CodeLen >> 1), &pSrcParts->Val, pSrcParts->Cnt << 1); CodeLen += pSrcParts->Cnt << 1;
532 memcpy(WAsmCode + (CodeLen >> 1), &pDestParts->Val, pDestParts->Cnt << 1); CodeLen += pDestParts->Cnt << 1;
533 }
534
ConstructTwoOpX(Word Code,const tAdrParts * pSrcParts,const tAdrParts * pDestParts)535 static void ConstructTwoOpX(Word Code, const tAdrParts *pSrcParts, const tAdrParts *pDestParts)
536 {
537 Word Prefix = 0x1800 | GetAL();
538
539 if ((eModeReg != pSrcParts->Mode) || (eModeReg != pDestParts->Mode))
540 {
541 if (pSrcParts->Cnt)
542 Prefix |= ((pSrcParts->Val >> 16) & 15) << 7;
543 if (pDestParts->Cnt)
544 Prefix |= ((pDestParts->Val >> 16) & 15);
545 }
546
547 /* take over multiply prefix for register<->register ops only */
548
549 else
550 {
551 Prefix |= MultPrefix;
552 MultPrefix = 0;
553 }
554 WAsmCode[CodeLen >> 1] = Prefix; CodeLen += 2;
555 ConstructTwoOp(Code, pSrcParts, pDestParts);
556 }
557
DecodeFixed(Word Code)558 static void DecodeFixed(Word Code)
559 {
560 if (!ChkArgCnt(0, 0));
561 else if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
562 else if (OpSize != eOpSizeDefault) WrError(ErrNum_InvOpSize);
563 else
564 {
565 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
566 WAsmCode[0] = Code; CodeLen = 2;
567 }
568 }
569
DecodeTwoOp(Word Code)570 static void DecodeTwoOp(Word Code)
571 {
572 tAdrParts SrcParts, DestParts;
573
574 if (!ChkArgCnt(2, 2));
575 else if (OpSize > eOpSizeW) WrError(ErrNum_InvOpSize);
576 else
577 {
578 PCDist = 2;
579 if (DecodeAdr(&ArgStr[1], eExtModeNo, 15, True, &SrcParts))
580 {
581 PCDist += SrcParts.Cnt << 1;
582 if (DecodeAdr(&ArgStr[2], eExtModeNo, 3, False, &DestParts))
583 {
584 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
585 ConstructTwoOp(Code, &SrcParts, &DestParts);
586 }
587 }
588 }
589 }
590
DecodeTwoOpX(Word Code)591 static void DecodeTwoOpX(Word Code)
592 {
593 tAdrParts SrcParts, DestParts;
594
595 Code &= ~1;
596
597 if (!ChkArgCnt(2, 2))
598 return;
599
600 PCDist = 4;
601 if (DecodeAdr(&ArgStr[1], eExtModeYes, MModeAs, True, &SrcParts))
602 {
603 PCDist += SrcParts.Cnt << 1;
604 if (DecodeAdr(&ArgStr[2], eExtModeYes, MModeAd, False, &DestParts))
605 {
606 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
607 ConstructTwoOpX(Code, &SrcParts, &DestParts);
608 }
609 }
610 }
611
DecodeEmulOneToTwo(Word Code)612 static void DecodeEmulOneToTwo(Word Code)
613 {
614 Byte SrcSpec;
615 tAdrParts SrcParts, DestParts;
616
617 /* separate src spec & opcode */
618
619 SrcSpec = Lo(Code);
620 Code &= 0xff00;
621
622 if (!ChkArgCnt(1, 1))
623 return;
624
625 if (OpSize > eOpSizeW)
626 {
627 WrError(ErrNum_InvOpSize);
628 return;
629 }
630
631 /* Decode operand:
632 - Ad modes always allowed
633 - for Src == Dest, also allow @Rn+: */
634
635 PCDist = 2;
636 if (!DecodeAdr(&ArgStr[1], eExtModeNo, MModeAd | ((SrcSpec == 0xaa) ? MModeIRegAutoInc : 0), False, &DestParts))
637 return;
638
639 /* filter immediate out separately (we get it as d(PC): */
640
641 if (DestParts.WasImm)
642 {
643 WrError(ErrNum_InvAddrMode);
644 return;
645 }
646
647 /* deduce src operand: 0xaa = special value for Src == Dest: */
648
649 if (SrcSpec == 0xaa)
650 {
651 /* default assumption: */
652
653 SrcParts = DestParts;
654
655 /* @Rn+: is transformed to @Rn+,-opsize(Rn): */
656
657 if (SrcParts.Mode == eModeIRegAutoInc)
658 {
659 static const Byte MemLen[3] = { 1, 2, 4 };
660
661 DestParts.Mode = eModeRegDisp;
662 DestParts.Val = (0 - MemLen[OpSize]) & 0xffff;
663 DestParts.Cnt = 1;
664 }
665
666 /* for PC-relative addressing, fix up destination displacement and
667 complain on displacement overflow: */
668
669 else if ((DestParts.Mode == eModeRegDisp) && (DestParts.Part == RegPC))
670 {
671 LongWord NewDist = DestParts.Val - 2;
672
673 if ((NewDist & 0x8000) != (DestParts.Val & 0x8000))
674 {
675 WrError(ErrNum_DistTooBig);
676 return;
677 }
678 DestParts.Val = NewDist;
679 }
680
681 /* transform 0(Rn) as Dest back to @Rn as Src: */
682
683 else if ((SrcParts.Mode == eModeRegDisp) && (DestParts.Val == 0))
684 {
685 SrcParts.Mode = eModeIReg;
686 SrcParts.Cnt = 0;
687 }
688 }
689
690 /* Src == other (constant) value: 0xff means -1: */
691
692 else
693 FillAdrPartsImm(&SrcParts, SrcSpec == 0xff ? 0xffffffff : SrcSpec, False);
694
695 /* assemble like 2-op instruction: */
696
697 ConstructTwoOp(Code, &SrcParts, &DestParts);
698 }
699
DecodeBR(Word Code)700 static void DecodeBR(Word Code)
701 {
702 tAdrParts DstParts, SrcParts;
703
704 PCDist = 2;
705 if (!ChkArgCnt(1, 1));
706 else if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
707 else if (DecodeAdr(&ArgStr[1], eExtModeNo, MModeAs, True, &SrcParts))
708 {
709 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
710 ResetAdr(&DstParts);
711 DstParts.Mode = eModeReg;
712 DstParts.Part = RegPC;
713 ConstructTwoOp(Code, &SrcParts, &DstParts);
714 }
715 }
716
DecodeEmulOneToTwoX(Word Code)717 static void DecodeEmulOneToTwoX(Word Code)
718 {
719 Byte SrcSpec;
720 tAdrParts SrcParts, DestParts;
721
722 /* separate src spec & opcode */
723
724 SrcSpec = Lo(Code);
725 Code &= 0xff00;
726
727 if (!ChkArgCnt(1, 1))
728 return;
729
730 /* Decode operand:
731 - Ad modes always allowed
732 - for Src == Dest, also allow @Rn+: */
733
734 PCDist = 4;
735 if (!DecodeAdr(&ArgStr[1], eExtModeYes, MModeAd | ((SrcSpec == 0xaa) ? MModeIRegAutoInc : 0), False, &DestParts))
736 return;
737
738 /* filter immediate out separately (we get it as d(PC): */
739
740 if (DestParts.WasImm)
741 {
742 WrError(ErrNum_InvAddrMode);
743 return;
744 }
745
746 /* deduce src operand: 0xaa = special value for Src == Dest: */
747
748 if (SrcSpec == 0xaa)
749 {
750 /* default assumption: */
751
752 SrcParts = DestParts;
753
754 /* @Rn+: is transformed to @Rn+,-opsize(Rn): */
755
756 if (SrcParts.Mode == eModeIRegAutoInc)
757 {
758 static const Byte MemLen[3] = { 1, 2, 4 };
759
760 DestParts.Mode = eModeRegDisp;
761 DestParts.Val = (0 - MemLen[OpSize]) & 0xfffff;
762 DestParts.Cnt = 1;
763 }
764
765 /* for PC-relative addressing, fix up destination displacement and
766 complain on displacement overflow: */
767
768 else if ((DestParts.Mode == eModeRegDisp) && (DestParts.Part == RegPC))
769 {
770 LongWord NewDist = DestParts.Val - 2;
771
772 if ((NewDist & 0x8000) != (DestParts.Val & 0x8000))
773 {
774 WrError(ErrNum_DistTooBig);
775 return;
776 }
777 DestParts.Val = NewDist;
778 }
779
780 /* transform 0(Rn) as Dest back to @Rn as Src: */
781
782 else if ((SrcParts.Mode == eModeRegDisp) && (DestParts.Val == 0))
783 {
784 SrcParts.Mode = eModeIReg;
785 SrcParts.Cnt = 0;
786 }
787 }
788
789 /* Src == other (constant) value: 0xff means -1: */
790
791 else
792 FillAdrPartsImm(&SrcParts, SrcSpec == 0xff ? 0xffffffff : SrcSpec, False);
793
794 /* assemble like 2-op instruction: */
795
796 ConstructTwoOpX(Code, &SrcParts, &DestParts);
797 }
798
DecodePOP(Word Code)799 static void DecodePOP(Word Code)
800 {
801 tAdrParts DstParts, SrcParts;
802
803 PCDist = 2;
804 if (ChkArgCnt(1, 1)
805 && DecodeAdr(&ArgStr[1], eExtModeNo, MModeAd, True, &DstParts))
806 {
807 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
808 ResetAdr(&SrcParts);
809 SrcParts.Mode = eModeIRegAutoInc;
810 SrcParts.Part = RegSP;
811 ConstructTwoOp(Code, &SrcParts, &DstParts);
812 }
813 }
814
DecodePOPX(Word Code)815 static void DecodePOPX(Word Code)
816 {
817 tAdrParts DstParts, SrcParts;
818
819 PCDist = 4;
820 if (ChkArgCnt(1, 1)
821 && DecodeAdr(&ArgStr[1], eExtModeYes, MModeAd, True, &DstParts))
822 {
823 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
824 ResetAdr(&SrcParts);
825 SrcParts.Mode = eModeIRegAutoInc;
826 SrcParts.Part = RegSP;
827 ConstructTwoOpX(Code, &SrcParts, &DstParts);
828 }
829 }
830
DecodeOneOp(Word Index)831 static void DecodeOneOp(Word Index)
832 {
833 const OneOpOrder *pOrder = OneOpOrders + Index;
834
835 if (!ChkArgCnt(1, 1));
836 else if (OpSize > eOpSizeW) WrError(ErrNum_InvOpSize);
837 else if ((OpSize == eOpSizeB) && (!pOrder->MayByte)) WrError(ErrNum_InvOpSize);
838 else
839 {
840 tAdrParts AdrParts;
841
842 PCDist = 2;
843 if (DecodeAdr(&ArgStr[1], eExtModeNo, 15, True, &AdrParts))
844 {
845 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
846 WAsmCode[0] = pOrder->Code | GetBW() | (AdrParts.Mode << 4) | AdrParts.Part;
847 memcpy(WAsmCode + 1, &AdrParts.Val, AdrParts.Cnt << 1);
848 CodeLen = (1 + AdrParts.Cnt) << 1;
849 }
850 }
851 }
852
DecodeOneOpX(Word Index)853 static void DecodeOneOpX(Word Index)
854 {
855 const OneOpOrder *pOrder = OneOpOrders + Index;
856
857 if (!ChkArgCnt(1, 1));
858 else if ((OpSize == eOpSizeB) && (!pOrder->MayByte)) WrError(ErrNum_InvOpSize);
859 else
860 {
861 tAdrParts AdrParts;
862
863 PCDist = 4;
864 if (DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts))
865 {
866 /* B/W for 20 bit size is 0 instead of 1 for SXT/SWPB */
867
868 Word ActBW = pOrder->MayByte ? GetBW() : 0;
869
870 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
871 WAsmCode[0] = 0x1800 | GetAL();
872
873 /* put bits 16:19 of operand into bits 0:3 or 7:10 of extension word? */
874
875 if (AdrParts.Cnt)
876 WAsmCode[0] |= (((AdrParts.Val >> 16) & 15) << 7);
877
878 /* repeat only supported for register op */
879
880 if (AdrParts.Mode == eModeReg)
881 {
882 WAsmCode[0] |= MultPrefix;
883 MultPrefix = 0;
884 }
885 WAsmCode[1] = pOrder->Code | ActBW | (AdrParts.Mode << 4) | AdrParts.Part;
886 memcpy(WAsmCode + 2, &AdrParts.Val, AdrParts.Cnt << 1);
887 CodeLen = (2 + AdrParts.Cnt) << 1;
888 }
889 }
890 }
891
DecodeMOVA(Word Code)892 static void DecodeMOVA(Word Code)
893 {
894 tAdrParts AdrParts;
895
896 UNUSED(Code);
897
898 OpSize = eOpSizeA;
899 if (!ChkArgCnt(2, 2));
900 else if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
901 else
902 {
903 PCDist = 2;
904 DecodeAdr(&ArgStr[2], eExtModeYes, 15, False, &AdrParts);
905 if (AdrParts.WasAbs)
906 {
907 if (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg)
908 {
909 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
910 WAsmCode[0] = 0x0060 | (WAsmCode[0] << 8) | ((AdrParts.Val >> 16) & 0x0f);
911 WAsmCode[1] = AdrParts.Val & 0xffff;
912 CodeLen = 4;
913 }
914 }
915 else switch (AdrParts.Mode)
916 {
917 case eModeReg:
918 WAsmCode[0] = AdrParts.Part;
919 DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts);
920 if (AdrParts.WasImm)
921 {
922 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
923 WAsmCode[0] |= ((AdrParts.Val >> 8) & 0x0f00) | 0x0080;
924 WAsmCode[1] = AdrParts.Val & 0xffff;
925 CodeLen = 4;
926 }
927 else if (AdrParts.WasAbs)
928 {
929 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
930 WAsmCode[0] |= ((AdrParts.Val >> 8) & 0x0f00) | 0x0020;
931 WAsmCode[1] = AdrParts.Val & 0xffff;
932 CodeLen = 4;
933 }
934 else switch (AdrParts.Mode)
935 {
936 case eModeReg:
937 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
938 WAsmCode[0] |= (AdrParts.Part << 8) | 0x00c0;
939 CodeLen = 2;
940 break;
941 case eModeIReg:
942 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
943 WAsmCode[0] |= (AdrParts.Part << 8) | 0x0000;
944 CodeLen = 2;
945 break;
946 case eModeIRegAutoInc:
947 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
948 WAsmCode[0] |= (AdrParts.Part << 8) | 0x0010;
949 CodeLen = 2;
950 break;
951 case eModeRegDisp:
952 if (ChkRange(AdrParts.Val, 0, 0xffff))
953 {
954 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
955 WAsmCode[0] |= (AdrParts.Part << 8) | 0x0030;
956 WAsmCode[1] = AdrParts.Val & 0xffff;
957 CodeLen = 4;
958 }
959 break;
960 }
961 break;
962 case eModeRegDisp:
963 if (ChkRange(AdrParts.Val, 0, 0xffff)
964 && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
965 {
966 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
967 WAsmCode[0] = 0x0070 | (WAsmCode[0] << 8) | AdrParts.Part;
968 WAsmCode[1] = AdrParts.Val & 0xffff;
969 CodeLen = 4;
970 }
971 break;
972 }
973 }
974 }
975
DecodeBRA(Word Code)976 static void DecodeBRA(Word Code)
977 {
978 if (ChkArgCnt(1, 1))
979 {
980 IncArgCnt();
981 strcpy(ArgStr[ArgCnt].Str, "PC");
982 DecodeMOVA(Code);
983 }
984 }
985
DecodeCLRA(Word Code)986 static void DecodeCLRA(Word Code)
987 {
988 if (ChkArgCnt(1, 1)
989 && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
990 {
991 WAsmCode[0] |= Code;
992 CodeLen = 2;
993 }
994 }
995
DecodeTSTA(Word Code)996 static void DecodeTSTA(Word Code)
997 {
998 if (ChkArgCnt(1, 1)
999 && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
1000 {
1001 WAsmCode[0] |= Code;
1002 WAsmCode[1] = 0x0000;
1003 CodeLen = 4;
1004 }
1005 }
1006
DecodeDECDA_INCDA(Word Code)1007 static void DecodeDECDA_INCDA(Word Code)
1008 {
1009 if (ChkArgCnt(1, 1)
1010 && (DecodeReg(&ArgStr[1], &WAsmCode[0], True) == eIsReg))
1011 {
1012 WAsmCode[0] |= Code;
1013 WAsmCode[1] = 2;
1014 CodeLen = 4;
1015 }
1016 }
1017
DecodeADDA_SUBA_CMPA(Word Code)1018 static void DecodeADDA_SUBA_CMPA(Word Code)
1019 {
1020 OpSize = eOpSizeA;
1021
1022 if (!ChkArgCnt(2, 2));
1023 else if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
1024 else if (DecodeReg(&ArgStr[2], &WAsmCode[0], False) == eIsReg)
1025 {
1026 tAdrParts AdrParts;
1027
1028 DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts);
1029 if (AdrParts.WasImm)
1030 {
1031 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
1032 WAsmCode[0] |= Code | ((AdrParts.Val >> 8) & 0xf00);
1033 WAsmCode[1] = AdrParts.Val & 0xffff;
1034 CodeLen = 4;
1035 }
1036 else if (eModeReg == AdrParts.Mode)
1037 {
1038 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
1039 WAsmCode[0] |= Code | 0x0040 | (AdrParts.Part << 8);
1040 CodeLen = 2;
1041 }
1042 else
1043 WrError(ErrNum_InvOpSize);
1044 }
1045 }
1046
DecodeRxM(Word Code)1047 static void DecodeRxM(Word Code)
1048 {
1049 if (!ChkArgCnt(2, 2));
1050 else if (OpSize == eOpSizeB) WrError(ErrNum_InvOpSize);
1051 else if (DecodeReg(&ArgStr[2], &WAsmCode[0], True) != eIsReg);
1052 else if (ArgStr[1].Str[0] != '#') WrError(ErrNum_OnlyImmAddr);
1053 else
1054 {
1055 Word Mult;
1056 tSymbolFlags Flags;
1057 Boolean OK;
1058
1059 Mult = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt3, &OK, &Flags);
1060 if (OK)
1061 {
1062 if (mFirstPassUnknown(Flags))
1063 Mult = 1;
1064 if (ChkRange(Mult, 1, 4))
1065 {
1066 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
1067 WAsmCode[0] |= Code | ((Mult - 1) << 10) | (GetAL() >> 2);
1068 CodeLen = 2;
1069 }
1070 }
1071 }
1072 }
1073
DecodeCALLA(Word Code)1074 static void DecodeCALLA(Word Code)
1075 {
1076 tAdrParts AdrParts;
1077
1078 UNUSED(Code);
1079
1080 OpSize = eOpSizeA;
1081 PCDist = 2;
1082 if (!ChkArgCnt(1, 1));
1083 else if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
1084 else if (DecodeAdr(&ArgStr[1], eExtModeYes, 15, True, &AdrParts))
1085 {
1086 if (AdrParts.WasImm)
1087 {
1088 WAsmCode[0] = 0x13b0 | ((AdrParts.Val >> 16) & 15);
1089 WAsmCode[1] = AdrParts.Val & 0xffff;
1090 CodeLen = 4;
1091 }
1092 else if (AdrParts.WasAbs)
1093 {
1094 WAsmCode[0] = 0x1380 | ((AdrParts.Val >> 16) & 15);
1095 WAsmCode[1] = AdrParts.Val & 0xffff;
1096 CodeLen = 4;
1097 }
1098 else if ((AdrParts.Mode == eModeRegDisp) && (AdrParts.Part == RegPC))
1099 {
1100 WAsmCode[0] = 0x1390 | ((AdrParts.Val >> 16) & 15);
1101 WAsmCode[1] = AdrParts.Val & 0xffff;
1102 CodeLen = 4;
1103 }
1104 else if ((AdrParts.Mode == eModeRegDisp) && (((AdrParts.Val & 0xfffff) > 0x7fff) && ((AdrParts.Val & 0xfffff) < 0xf8000))) WrError(ErrNum_OverRange);
1105 else
1106 {
1107 WAsmCode[0] = 0x1340 | (AdrParts.Mode << 4) | (AdrParts.Part);
1108 memcpy(WAsmCode + 1, &AdrParts.Val, AdrParts.Cnt << 1);
1109 CodeLen = (1 + AdrParts.Cnt) << 1;
1110 }
1111 }
1112 }
1113
DecodePUSHM_POPM(Word Code)1114 static void DecodePUSHM_POPM(Word Code)
1115 {
1116 if (!ChkArgCnt(2, 2));
1117 else if (OpSize == 0) WrError(ErrNum_InvOpSize);
1118 else if (DecodeReg(&ArgStr[2], &WAsmCode[0], True) != eIsReg);
1119 else if (ArgStr[1].Str[0] != '#') WrError(ErrNum_OnlyImmAddr);
1120 else
1121 {
1122 Boolean OK;
1123 Word Cnt;
1124 tSymbolFlags Flags;
1125
1126 Cnt = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt5, &OK, &Flags);
1127 if (mFirstPassUnknown(Flags))
1128 Cnt = 1;
1129 if (OK && ChkRange(Cnt, 1, 16))
1130 {
1131 Cnt--;
1132 if (Code & 0x0200)
1133 WAsmCode[0] = (WAsmCode[0] - Cnt) & 15;
1134 WAsmCode[0] |= Code | (Cnt << 4) | (GetAL() << 2);
1135 CodeLen = 2;
1136 }
1137 }
1138 }
1139
DecodeJmp(Word Code)1140 static void DecodeJmp(Word Code)
1141 {
1142 Integer AdrInt;
1143 tSymbolFlags Flags;
1144 Boolean OK;
1145
1146 if (!ChkArgCnt(1, 1));
1147 else if (OpSize != eOpSizeDefault) WrError(ErrNum_InvOpSize);
1148 {
1149 AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags) - (EProgCounter() + 2);
1150 if (OK)
1151 {
1152 if (Odd(AdrInt)) WrError(ErrNum_DistIsOdd);
1153 else if (!mSymbolQuestionable(Flags) && ((AdrInt < -1024) || (AdrInt > 1022))) WrError(ErrNum_JmpDistTooBig);
1154 else
1155 {
1156 if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
1157 WAsmCode[0] = Code | ((AdrInt >> 1) & 0x3ff);
1158 CodeLen = 2;
1159 }
1160 }
1161 }
1162 }
1163
DecodeBYTE(Word Index)1164 static void DecodeBYTE(Word Index)
1165 {
1166 Boolean OK;
1167 int z;
1168 TempResult t;
1169
1170 UNUSED(Index);
1171
1172 if (ChkArgCnt(1, ArgCntMax))
1173 {
1174 z = 1; OK = True;
1175 do
1176 {
1177 KillBlanks(ArgStr[z].Str);
1178 EvalStrExpression(&ArgStr[z], &t);
1179 switch (t.Typ)
1180 {
1181 case TempInt:
1182 if (mFirstPassUnknown(t.Flags)) t.Contents.Int &= 0xff;
1183 if (!RangeCheck(t.Contents.Int, Int8)) WrError(ErrNum_OverRange);
1184 else if (SetMaxCodeLen(CodeLen + 1))
1185 {
1186 WrError(ErrNum_CodeOverflow); OK = False;
1187 }
1188 else PutByte(t.Contents.Int);
1189 break;
1190 case TempString:
1191 {
1192 unsigned l = t.Contents.Ascii.Length;
1193
1194 if (SetMaxCodeLen(l + CodeLen))
1195 {
1196 WrError(ErrNum_CodeOverflow); OK = False;
1197 }
1198 else
1199 {
1200 char *pEnd = t.Contents.Ascii.Contents + l, *p;
1201
1202 TranslateString(t.Contents.Ascii.Contents, l);
1203 for (p = t.Contents.Ascii.Contents; p < pEnd; PutByte(*(p++)));
1204 }
1205 break;
1206 }
1207 case TempFloat:
1208 WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[z]);
1209 /* fall-through */
1210 default:
1211 OK = False;
1212 break;
1213 }
1214 z++;
1215 }
1216 while ((z <= ArgCnt) && (OK));
1217 if (!OK) CodeLen = 0;
1218 }
1219 }
1220
DecodeWORD(Word Index)1221 static void DecodeWORD(Word Index)
1222 {
1223 int z;
1224 Word HVal16;
1225 Boolean OK;
1226
1227 UNUSED(Index);
1228
1229 if (ChkArgCnt(1, ArgCntMax))
1230 {
1231 z = 1; OK = True;
1232 do
1233 {
1234 HVal16 = EvalStrIntExpression(&ArgStr[z], Int16, &OK);
1235 if (OK)
1236 {
1237 WAsmCode[CodeLen >> 1] = HVal16;
1238 CodeLen += 2;
1239 }
1240 z++;
1241 }
1242 while ((z <= ArgCnt) && (OK));
1243 if (!OK) CodeLen = 0;
1244 }
1245 }
1246
DecodeBSS(Word Index)1247 static void DecodeBSS(Word Index)
1248 {
1249 Word HVal16;
1250 Boolean OK;
1251
1252 UNUSED(Index);
1253
1254 if (ChkArgCnt(1, 1))
1255 {
1256 tSymbolFlags Flags;
1257
1258 HVal16 = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &OK, &Flags);
1259 if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
1260 else if (OK)
1261 {
1262 if (!HVal16) WrError(ErrNum_NullResMem);
1263 DontPrint = True; CodeLen = HVal16;
1264 BookKeeping();
1265 }
1266 }
1267 }
1268
DecodeRPT(Word Code)1269 static void DecodeRPT(Word Code)
1270 {
1271 char *pOpPart, *pArgPart1, *pAttrPart;
1272 Boolean OK;
1273
1274 /* fundamentals */
1275
1276 if (!ChkArgCnt(1, ArgCntMax))
1277 return;
1278 if (*AttrPart.Str != '\0')
1279 {
1280 WrError(ErrNum_UseLessAttr);
1281 return;
1282 }
1283
1284 /* multiplier argument */
1285
1286 pOpPart = FirstBlank(ArgStr[1].Str);
1287 if (!pOpPart)
1288 {
1289 WrError(ErrNum_CannotSplitArg);
1290 return;
1291 }
1292 *pOpPart++ = '\0';
1293 MultPrefix = Code | GetMult(&ArgStr[1], &OK);
1294 if (!OK)
1295 return;
1296
1297 /* new OpPart: */
1298
1299 KillPrefBlanks(pOpPart);
1300 pArgPart1 = FirstBlank(pOpPart);
1301 if (!pArgPart1)
1302 {
1303 WrError(ErrNum_CannotSplitArg);
1304 return;
1305 }
1306 *pArgPart1++ = '\0';
1307 strcpy(OpPart.Str, pOpPart);
1308 UpString(OpPart.Str);
1309 KillPrefBlanks(pArgPart1);
1310 strmov(ArgStr[1].Str, pArgPart1);
1311
1312 /* split off new attribute part: */
1313
1314 pAttrPart = strrchr(OpPart.Str, '.');
1315 if (pAttrPart)
1316 {
1317 AttrPart.Pos.Len = strmemcpy(AttrPart.Str, STRINGSIZE, pAttrPart + 1, strlen(pAttrPart + 1));
1318 *pAttrPart = '\0';
1319 }
1320 else
1321 StrCompReset(&AttrPart);
1322
1323 /* prefix 0x0000 is rptc #1 and effectively a NOP prefix: */
1324
1325 MakeCode();
1326 if (MultPrefix)
1327 {
1328 WrError(ErrNum_NotRepeatable);
1329 CodeLen = 0;
1330 }
1331 }
1332
1333 /*-------------------------------------------------------------------------*/
1334
1335 #define AddFixed(NName, NCode) \
1336 AddInstTable(InstTable, NName, NCode, DecodeFixed)
1337
AddTwoOp(const char * NName,Word NCode)1338 static void AddTwoOp(const char *NName, Word NCode)
1339 {
1340 AddInstTable(InstTable, NName, NCode, DecodeTwoOp);
1341 if (MomCPU >= CPUMSP430X)
1342 {
1343 char XName[20];
1344
1345 as_snprintf(XName, sizeof(XName), "%sX", NName);
1346 AddInstTable(InstTable, XName, NCode, DecodeTwoOpX);
1347 }
1348 }
1349
AddEmulOneToTwo(const char * NName,Word NCode)1350 static void AddEmulOneToTwo(const char *NName, Word NCode)
1351 {
1352 AddInstTable(InstTable, NName, NCode, DecodeEmulOneToTwo);
1353 }
1354
AddEmulOneToTwoX(const char * NName,Word NCode)1355 static void AddEmulOneToTwoX(const char *NName, Word NCode)
1356 {
1357 AddInstTable(InstTable, NName, NCode, DecodeEmulOneToTwoX);
1358 }
1359
AddOneOp(const char * NName,Boolean NMay,Boolean AllowX,Word NCode)1360 static void AddOneOp(const char *NName, Boolean NMay, Boolean AllowX, Word NCode)
1361 {
1362 if (InstrZ >= OneOpCount) exit(255);
1363 OneOpOrders[InstrZ].MayByte = NMay;
1364 OneOpOrders[InstrZ].Code = NCode;
1365 AddInstTable(InstTable, NName, InstrZ, DecodeOneOp);
1366 if ((MomCPU >= CPUMSP430X) && AllowX)
1367 {
1368 char XName[20];
1369
1370 as_snprintf(XName, sizeof(XName), "%sX", NName);
1371 AddInstTable(InstTable, XName, InstrZ, DecodeOneOpX);
1372 }
1373 InstrZ++;
1374 }
1375
1376 #define AddJmp(NName, NCode) \
1377 AddInstTable(InstTable, NName, NCode, DecodeJmp)
1378
InitFields(void)1379 static void InitFields(void)
1380 {
1381 InstTable = CreateInstTable(207);
1382 SetDynamicInstTable(InstTable);
1383
1384 AddFixed("RETI", 0x1300);
1385 AddFixed("CLRC", 0xc312);
1386 AddFixed("CLRN", 0xc222);
1387 AddFixed("CLRZ", 0xc322);
1388 AddFixed("DINT", 0xc232);
1389 AddFixed("EINT", 0xd232);
1390 AddFixed("NOP" , NOPCode);
1391 AddFixed("RET" , 0x4130);
1392 AddFixed("SETC", 0xd312);
1393 AddFixed("SETN", 0xd222);
1394 AddFixed("SETZ", 0xd322);
1395
1396 AddTwoOp("MOV" , 0x4000); AddTwoOp("ADD" , 0x5000);
1397 AddTwoOp("ADDC", 0x6000); AddTwoOp("SUBC", 0x7000);
1398 AddTwoOp("SUB" , 0x8000); AddTwoOp("CMP" , 0x9000);
1399 AddTwoOp("DADD", 0xa000); AddTwoOp("BIT" , 0xb000);
1400 AddTwoOp("BIC" , 0xc000); AddTwoOp("BIS" , 0xd000);
1401 AddTwoOp("XOR" , 0xe000); AddTwoOp("AND" , 0xf000);
1402
1403 AddEmulOneToTwo("ADC" , 0x6000); /* ADDC #0, dst */
1404 AddInstTable(InstTable, "BR", 0x4000, DecodeBR); /* MOV dst, PC */
1405 AddEmulOneToTwo("CLR" , 0x4000); /* MOV #0, dst */
1406 AddEmulOneToTwo("DADC", 0xa000); /* DADD #0, dst */
1407 AddEmulOneToTwo("DEC" , 0x8001); /* SUB #1, dst */
1408 AddEmulOneToTwo("DECD", 0x8002); /* SUB #2, dst */
1409 AddEmulOneToTwo("INC" , 0x5001); /* ADD #1, dst */
1410 AddEmulOneToTwo("INCD", 0x5002); /* ADD #2, dst */
1411 AddEmulOneToTwo("INV" , 0xe0ff); /* XOR #-1, dst */
1412 AddInstTable(InstTable, "POP", 0x4000, DecodePOP); /* MOV @SP+,dst */
1413 AddEmulOneToTwo("RLA" , 0x50aa); /* ADD dst, dst */
1414 AddEmulOneToTwo("RLC" , 0x60aa); /* ADDC dst, dst */
1415 AddEmulOneToTwo("SBC" , 0x7000); /* SUBC #0, dst */
1416 AddEmulOneToTwo("TST" , 0x9000); /* CMP #0, dst */
1417
1418 OneOpOrders = (OneOpOrder *) malloc(sizeof(OneOpOrder) * OneOpCount); InstrZ = 0;
1419 AddOneOp("RRC" , True , True , 0x1000); AddOneOp("RRA" , True , True , 0x1100);
1420 AddOneOp("PUSH", True , True , 0x1200); AddOneOp("SWPB", False, True , 0x1080);
1421 AddOneOp("CALL", False, False, 0x1280); AddOneOp("SXT" , False, True , 0x1180);
1422
1423 if (MomCPU >= CPUMSP430X)
1424 {
1425 /* what about RRUX? */
1426
1427 AddInstTable(InstTable, "MOVA", 0x0000, DecodeMOVA);
1428 AddInstTable(InstTable, "ADDA", 0x00a0, DecodeADDA_SUBA_CMPA);
1429 AddInstTable(InstTable, "CMPA", 0x0090, DecodeADDA_SUBA_CMPA);
1430 AddInstTable(InstTable, "SUBA", 0x00b0, DecodeADDA_SUBA_CMPA);
1431
1432 AddInstTable(InstTable, "RRCM", 0x0040, DecodeRxM);
1433 AddInstTable(InstTable, "RRAM", 0x0140, DecodeRxM);
1434 AddInstTable(InstTable, "RLAM", 0x0240, DecodeRxM);
1435 AddInstTable(InstTable, "RRUM", 0x0340, DecodeRxM);
1436
1437 AddInstTable(InstTable, "CALLA", 0x0000, DecodeCALLA);
1438
1439 AddInstTable(InstTable, "PUSHM", 0x1400, DecodePUSHM_POPM);
1440 AddInstTable(InstTable, "POPM", 0x1600, DecodePUSHM_POPM);
1441
1442 AddEmulOneToTwoX("ADCX", 0x6000); /* ADDCX #0, dst */
1443 AddInstTable(InstTable, "BRA", 0x4000, DecodeBRA); /* MOVA dst, PC */
1444 AddFixed("RETA", 0x0110); /* MOVA @SP+,PC */
1445 AddInstTable(InstTable, "CLRA", 0x4300, DecodeCLRA); /* MOV #0,Rdst */
1446 AddEmulOneToTwoX("CLRX", 0x4000); /* MOVX #0, dest */
1447 AddEmulOneToTwoX("DADCX", 0xa000); /* DADDX #0, dst */
1448 AddEmulOneToTwoX("DECX" , 0x8001); /* SUBX #1, dst */
1449 AddInstTable(InstTable, "DECDA", 0x00b0, DecodeDECDA_INCDA); /* SUBA #2,Rdst */
1450 AddEmulOneToTwoX("DECDX", 0x8002); /* SUBX #2, dst */
1451 AddEmulOneToTwoX("INCX" , 0x5001); /* SUBX #1, dst */
1452 AddInstTable(InstTable, "INCDA", 0x00a0, DecodeDECDA_INCDA); /* SUBA #2,Rdst */
1453 AddEmulOneToTwoX("INCDX", 0x5002); /* SUBX #2, dst */
1454 AddEmulOneToTwoX("INVX" , 0xe0ff); /* XORX #-1, dst */
1455 AddEmulOneToTwoX("RLAX" , 0x50aa); /* ADDX dst, dst */
1456 AddEmulOneToTwoX("RLCX" , 0x60aa); /* ADDCX dst, dst */
1457 AddEmulOneToTwoX("SBCX" , 0x7000); /* SUBCX #0, dst */
1458 AddInstTable(InstTable, "TSTA" , 0x0090, DecodeTSTA); /* CMPA #0,Rdst */
1459 AddEmulOneToTwoX("TSTX" , 0x9000); /* CMPX #0, dst */
1460 AddInstTable(InstTable, "POPX", 0x4000, DecodePOPX); /* MOVX @SP+,dst */
1461
1462 AddInstTable(InstTable, "RPTC", 0x0000, DecodeRPT);
1463 AddInstTable(InstTable, "RPTZ", 0x0100, DecodeRPT);
1464 }
1465
1466 AddJmp("JNE" , 0x2000); AddJmp("JNZ" , 0x2000);
1467 AddJmp("JE" , 0x2400); AddJmp("JZ" , 0x2400);
1468 AddJmp("JNC" , 0x2800); AddJmp("JC" , 0x2c00);
1469 AddJmp("JN" , 0x3000); AddJmp("JGE" , 0x3400);
1470 AddJmp("JL" , 0x3800); AddJmp("JMP" , 0x3C00);
1471 AddJmp("JEQ" , 0x2400); AddJmp("JLO" , 0x2800);
1472 AddJmp("JHS" , 0x2c00);
1473
1474 AddInstTable(InstTable, "WORD", 0, DecodeWORD);
1475
1476 AddInstTable(InstTable, "REG", 0, CodeREG);
1477 }
1478
DeinitFields(void)1479 static void DeinitFields(void)
1480 {
1481 free(OneOpOrders);
1482
1483 DestroyInstTable(InstTable);
1484 }
1485
1486 /*-------------------------------------------------------------------------*/
1487
1488 /*!------------------------------------------------------------------------
1489 * \fn InternSymbol_MSP(char *pArg, TempResult *pResult)
1490 * \brief handle built-in (register) symbols for MSP
1491 * \param pArg source argument
1492 * \param pResult result buffer
1493 * ------------------------------------------------------------------------ */
1494
InternSymbol_MSP(char * pArg,TempResult * pResult)1495 static void InternSymbol_MSP(char *pArg, TempResult *pResult)
1496 {
1497 Word RegNum;
1498
1499 if (DecodeRegCore(pArg, &RegNum))
1500 {
1501 pResult->Typ = TempReg;
1502 pResult->DataSize = eSymbolSize8Bit;
1503 pResult->Contents.RegDescr.Reg = RegNum;
1504 pResult->Contents.RegDescr.Dissect = DissectReg_MSP;
1505 }
1506 }
1507
DecodeAttrPart_MSP(void)1508 static Boolean DecodeAttrPart_MSP(void)
1509 {
1510 if (strlen(AttrPart.Str) > 1)
1511 {
1512 WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
1513 return False;
1514 }
1515 switch (as_toupper(*AttrPart.Str))
1516 {
1517 case '\0':
1518 break;
1519 case 'B':
1520 AttrPartOpSize = eSymbolSize8Bit;
1521 break;
1522 case 'W':
1523 AttrPartOpSize = eSymbolSize16Bit;
1524 break;
1525 case 'A':
1526 if (MomCPU >= CPUMSP430X)
1527 {
1528 AttrPartOpSize = eSymbolSize24Bit; /* TODO: should be 20 bits */
1529 break;
1530 }
1531 /* else fall-through */
1532 default:
1533 WrStrErrorPos(ErrNum_UndefAttr, &AttrPart);
1534 return False;
1535 }
1536 return True;
1537 }
1538
MakeCode_MSP(void)1539 static void MakeCode_MSP(void)
1540 {
1541 CodeLen = 0; DontPrint = False; PCDist = 0;
1542
1543 /* to be ignored: */
1544
1545 if (Memo("")) return;
1546
1547 /* process attribute */
1548
1549 switch (AttrPartOpSize)
1550 {
1551 case eSymbolSize24Bit:
1552 OpSize = eOpSizeA;
1553 break;
1554 case eSymbolSize16Bit:
1555 OpSize = eOpSizeW;
1556 break;
1557 case eSymbolSize8Bit:
1558 OpSize = eOpSizeB;
1559 break;
1560 default:
1561 OpSize = eOpSizeDefault;
1562 break;
1563 }
1564
1565 /* insns not requiring word alignment */
1566
1567 if (Memo("BYTE"))
1568 {
1569 DecodeBYTE(0);
1570 return;
1571 }
1572 if (Memo("BSS"))
1573 {
1574 DecodeBSS(0);
1575 return;
1576 }
1577
1578 /* For all other (pseudo) instructions, optionally pad to even */
1579
1580 if (Odd(EProgCounter()))
1581 {
1582 if (DoPadding)
1583 InsertPadding(1, False);
1584 else
1585 WrError(ErrNum_AddrNotAligned);
1586 }
1587
1588 /* all the rest from table */
1589
1590 if (!LookupInstTable(InstTable, OpPart.Str))
1591 WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
1592 }
1593
IsDef_MSP(void)1594 static Boolean IsDef_MSP(void)
1595 {
1596 return Memo("REG");
1597 }
1598
SwitchFrom_MSP(void)1599 static void SwitchFrom_MSP(void)
1600 {
1601 DeinitFields();
1602 ClearONOFF();
1603 }
1604
SwitchTo_MSP(void)1605 static void SwitchTo_MSP(void)
1606 {
1607 TurnWords = False; ConstMode = ConstModeIntel;
1608
1609 PCSymbol = "$"; HeaderID = 0x4a; NOPCode = 0x4303; /* = MOV #0,#0 */
1610 DivideChars = ","; HasAttrs = True; AttrChars = ".";
1611
1612 ValidSegs = 1 << SegCode;
1613 Grans[SegCode] = 1; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
1614 AdrIntType = (MomCPU == CPUMSP430X) ? UInt20 : UInt16;
1615 DispIntType = (MomCPU == CPUMSP430X) ? Int20 : Int16;
1616 SegLimits[SegCode] = IntTypeDefs[AdrIntType].Max;
1617
1618 AddONOFF("PADDING", &DoPadding, DoPaddingName, False);
1619
1620 DecodeAttrPart = DecodeAttrPart_MSP;
1621 MakeCode = MakeCode_MSP;
1622 IsDef = IsDef_MSP;
1623 InternSymbol = InternSymbol_MSP;
1624 DissectReg = DissectReg_MSP;
1625 SwitchFrom = SwitchFrom_MSP; InitFields();
1626
1627 MultPrefix = 0x0000;
1628 }
1629
codemsp_init(void)1630 void codemsp_init(void)
1631 {
1632 CPUMSP430 = AddCPU("MSP430", SwitchTo_MSP);
1633 CPUMSP430X = AddCPU("MSP430X", SwitchTo_MSP);
1634 }
1635