1 /* codemcore.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegenerator MCORE-Familie                                               */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include "nls.h"
16 #include "endian.h"
17 #include "strutil.h"
18 #include "bpemu.h"
19 #include "asmdef.h"
20 #include "asmsub.h"
21 #include "asmpars.h"
22 #include "asmallg.h"
23 #include "codepseudo.h"
24 #include "motpseudo.h"
25 #include "asmitree.h"
26 #include "codevars.h"
27 #include "errmsg.h"
28 
29 #include "codemcore.h"
30 
31 /*--------------------------------------------------------------------------*/
32 /* Variablen */
33 
34 #define REG_SP 0
35 #define REG_LR 15
36 #define REG_MARK 16 /* internal mark to differentiate SP<->R0 and LR<->R15 */
37 
38 #define FixedOrderCnt 7
39 #define OneRegOrderCnt 32
40 #define TwoRegOrderCnt 23
41 #define UImm5OrderCnt 13
42 #define LJmpOrderCnt 4
43 #define CRegCnt 13
44 
45 typedef struct
46 {
47   Word Code;
48   Boolean Priv;
49 } FixedOrder;
50 
51 typedef struct
52 {
53   Word Code;
54   Word Min,Ofs;
55 } ImmOrder;
56 
57 typedef struct
58 {
59   const char *Name;
60   Word Code;
61 } CReg;
62 
63 static CPUVar CPUMCORE;
64 static tSymbolSize OpSize;
65 
66 static FixedOrder *FixedOrders;
67 static FixedOrder *OneRegOrders;
68 static FixedOrder *TwoRegOrders;
69 static ImmOrder *UImm5Orders;
70 static FixedOrder *LJmpOrders;
71 static CReg *CRegs;
72 
73 /*--------------------------------------------------------------------------*/
74 /* Hilfsdekoder */
75 
76 static const Word AllRegMask = 0xffff;
77 
78 /*!------------------------------------------------------------------------
79  * \fn     DecodeRegCore(const char *pArg, Word *pResult)
80  * \brief  check whether argument is a register
81  * \param  pArg argument
82  * \param  pResult register number if it is
83  * \return True if it is
84  * ------------------------------------------------------------------------ */
85 
DecodeRegCore(const char * pArg,Word * pResult)86 static Boolean DecodeRegCore(const char *pArg, Word *pResult)
87 {
88   if (!as_strcasecmp(pArg, "SP"))
89     *pResult = REG_MARK | REG_SP;
90   else if (!as_strcasecmp(pArg, "LR"))
91     *pResult = REG_MARK | REG_LR;
92   else if (as_toupper(*pArg) != 'R')
93     return False;
94   else
95   {
96     char *endptr;
97 
98     *pResult = strtol(pArg + 1, &endptr, 10);
99     if (*endptr || (*pResult > 15))
100       return False;
101   }
102   return True;
103 }
104 
105 /*!------------------------------------------------------------------------
106  * \fn     DissectReg_MCORE(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
107  * \brief  dissect register symbols - M-CORE variant
108  * \param  pDest destination buffer
109  * \param  DestSize destination buffer size
110  * \param  Value numeric register value
111  * \param  InpSize register size
112  * ------------------------------------------------------------------------ */
113 
DissectReg_MCORE(char * pDest,size_t DestSize,tRegInt Value,tSymbolSize InpSize)114 static void DissectReg_MCORE(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
115 {
116   switch (InpSize)
117   {
118     case eSymbolSize32Bit:
119       switch (Value)
120       {
121         case REG_MARK | REG_SP:
122           as_snprintf(pDest, DestSize, "SP");
123           break;
124         case REG_MARK | REG_LR:
125           as_snprintf(pDest, DestSize, "LR");
126           break;
127         default:
128           as_snprintf(pDest, DestSize, "R%u", (unsigned)Value);
129       }
130       break;
131     default:
132       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
133   }
134 }
135 
136 /*!------------------------------------------------------------------------
137  * \fn     DecodeReg(const tStrComp *pArg, Word *pResult, Word Mask, Boolean MustBeReg)
138  * \brief  check whether argument is a CPU register or register alias
139  * \param  pArg argument
140  * \param  pResult register number if it is
141  * \param  Mask bit mask of allowed registers
142  * \param  MustBeReg operand is expected to be a register
143  * \return True if it is an allowed register
144  * ------------------------------------------------------------------------ */
145 
DecodeReg(const tStrComp * pArg,Word * pResult,Word Mask,Boolean MustBeReg)146 static tRegEvalResult DecodeReg(const tStrComp *pArg, Word *pResult, Word Mask, Boolean MustBeReg)
147 {
148   tRegEvalResult RegEvalResult;
149 
150   if (DecodeRegCore(pArg->Str, pResult))
151     RegEvalResult = eIsReg;
152   else
153   {
154     tRegDescr RegDescr;
155     tEvalResult EvalResult;
156 
157     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
158     *pResult = RegDescr.Reg;
159   }
160   *pResult &= ~REG_MARK;
161   if ((RegEvalResult == eIsReg) && !(Mask & (1 << *pResult)))
162   {
163     RegEvalResult = MustBeReg ? eRegAbort : eIsNoReg;
164     WrStrErrorPos(ErrNum_InvReg, pArg);
165   }
166   return RegEvalResult;
167 }
168 
DecodeArgReg(int Index,Word * pErg,Word Mask)169 static Boolean DecodeArgReg(int Index, Word *pErg, Word Mask)
170 {
171   return (DecodeReg(&ArgStr[Index], pErg, Mask, True) == eIsReg);
172 }
173 
DecodeArgIReg(int Index,Word * pErg,Word Mask)174 static Boolean DecodeArgIReg(int Index, Word *pErg, Word Mask)
175 {
176   tStrComp RegComp;
177   const char *pArg = ArgStr[Index].Str;
178   int l = strlen(pArg);
179 
180   if ((l <= 3) || (pArg[0] != '(') || (pArg[l - 1] != ')'))
181   {
182     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[Index]);
183     return False;
184   }
185   StrCompRefRight(&RegComp, &ArgStr[Index], 1);
186   StrCompShorten(&RegComp, 1);
187   return (DecodeReg(&RegComp, pErg, Mask, True) == eIsReg);
188 }
189 
DecodeArgRegPair(int Index,Word * pFrom,Word FromMask,Word * pTo,Word ToMask)190 static Boolean DecodeArgRegPair(int Index, Word *pFrom, Word FromMask, Word *pTo, Word ToMask)
191 {
192   tStrComp FromComp, ToComp;
193   char *pSep = strchr(ArgStr[Index].Str, '-');
194 
195   if (!pSep)
196   {
197     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[Index]);
198     return False;
199   }
200 
201   StrCompSplitRef(&FromComp, &ToComp, &ArgStr[Index], pSep);
202   return (DecodeReg(&FromComp, pFrom, FromMask, True) == eIsReg)
203       && (DecodeReg(&ToComp, pTo, ToMask, True) == eIsReg);
204 }
205 
DecodeCReg(char * Asc,Word * Erg)206 static Boolean DecodeCReg(char *Asc, Word *Erg)
207 {
208   char *endptr;
209   int z;
210 
211   for (z = 0; z < CRegCnt; z++)
212     if (!as_strcasecmp(Asc, CRegs[z].Name))
213     {
214       *Erg = CRegs[z].Code;
215       return True;
216     }
217 
218   if ((as_toupper(*Asc) != 'C') || (as_toupper(Asc[1]) != 'R'))
219     return False;
220   else
221   {
222     *Erg = strtol(Asc + 2, &endptr, 10);
223     return ((*endptr == '\0') && (*Erg <= 31));
224   }
225 }
226 
DecodeArgCReg(int Index,Word * pErg)227 static Boolean DecodeArgCReg(int Index, Word *pErg)
228 {
229   Boolean Result = DecodeCReg(ArgStr[Index].Str, pErg);
230 
231   if (!Result)
232     WrStrErrorPos(ErrNum_InvCtrlReg, &ArgStr[Index]);
233   return Result;
234 }
235 
DecodeAdr(const tStrComp * pArg,Word * Erg)236 static Boolean DecodeAdr(const tStrComp *pArg, Word *Erg)
237 {
238   Word Base = 0xff, Tmp;
239   LongInt DispAcc = 0, DMask = (1 << OpSize) - 1, DMax = 15 << OpSize;
240   Boolean OK, FirstFlag = False;
241   tSymbolFlags Flags;
242   char *Pos;
243   tStrComp Arg, Remainder;
244 
245   if (!IsIndirect(pArg->Str))
246   {
247     WrError(ErrNum_InvAddrMode);
248     return False;
249   }
250 
251   StrCompRefRight(&Arg,pArg, 1);
252   StrCompShorten(&Arg, 1);
253   do
254   {
255     Pos = QuotPos(Arg.Str,',');
256     if (Pos)
257       StrCompSplitRef(&Arg, &Remainder, &Arg, Pos);
258     switch (DecodeReg(&Arg, &Tmp, AllRegMask, False))
259     {
260       case eIsReg:
261         if (Base == 0xff) Base = Tmp;
262         else
263         {
264           WrError(ErrNum_InvAddrMode);
265           return False;
266         }
267         break;
268       case eIsNoReg:
269         DispAcc += EvalStrIntExpressionWithFlags(&Arg, Int32, &OK, &Flags);
270         if (mFirstPassUnknown(Flags)) FirstFlag = True;
271         if (!OK)
272           return False;
273         break;
274       default:
275         return False;
276     }
277     if (Pos)
278       Arg = Remainder;
279   }
280   while (Pos);
281 
282   if (Base == 0xff)
283   {
284     WrError(ErrNum_InvAddrMode);
285     return False;
286   }
287 
288   if (FirstFlag)
289   {
290     DispAcc -= DispAcc & DMask;
291     if (DispAcc < 0) DispAcc = 0;
292     if (DispAcc > DMax) DispAcc = DMax;
293   }
294 
295   if ((DispAcc & DMask) != 0)
296   {
297     WrError(ErrNum_NotAligned);
298     return False;
299   }
300   if (!ChkRange(DispAcc, 0, DMax))
301     return False;
302   *Erg = Base + ((DispAcc >> OpSize) << 4);
303   return True;
304 }
305 
DecodeFixed(Word Index)306 static void DecodeFixed(Word Index)
307 {
308   FixedOrder *Instr = FixedOrders + Index;
309 
310   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
311   else if (ChkArgCnt(0, 0))
312   {
313     if ((Instr->Priv) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
314     WAsmCode[0] = Instr->Code;
315     CodeLen = 2;
316   }
317 }
318 
DecodeOneReg(Word Index)319 static void DecodeOneReg(Word Index)
320 {
321   FixedOrder *Instr = OneRegOrders + Index;
322   Word RegX;
323 
324   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
325   else if (ChkArgCnt(1, 1) && DecodeArgReg(1, &RegX, AllRegMask))
326   {
327     if ((Instr->Priv) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
328     WAsmCode[0] = Instr->Code + RegX;
329     CodeLen = 2;
330   }
331 }
332 
DecodeTwoReg(Word Index)333 static void DecodeTwoReg(Word Index)
334 {
335   FixedOrder *Instr = TwoRegOrders + Index;
336   Word RegX, RegY;
337 
338   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
339   else if (ChkArgCnt(2, 2)
340         && DecodeArgReg(1, &RegX, AllRegMask)
341         && DecodeArgReg(2, &RegY, AllRegMask))
342   {
343     if ((Instr->Priv) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
344     WAsmCode[0] = Instr->Code + (RegY << 4) + RegX;
345     CodeLen = 2;
346   }
347 }
348 
DecodeUImm5(Word Index)349 static void DecodeUImm5(Word Index)
350 {
351   ImmOrder *Instr = UImm5Orders + Index;
352   Word RegX, ImmV;
353   Boolean OK;
354   tSymbolFlags Flags;
355 
356   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
357   else if (ChkArgCnt(2, 2) && DecodeArgReg(1, &RegX, AllRegMask))
358   {
359     ImmV = EvalStrIntExpressionWithFlags(&ArgStr[2], (Instr->Ofs > 0) ? UInt6 : UInt5, &OK, &Flags);
360     if ((Instr->Min > 0) && (ImmV < Instr->Min))
361     {
362       if (mFirstPassUnknown(Flags)) ImmV = Instr->Min;
363       else
364       {
365         WrError(ErrNum_UnderRange); OK = False;
366       }
367     }
368     if ((Instr->Ofs > 0) && ((ImmV < Instr->Ofs) || (ImmV > 31 + Instr->Ofs)))
369     {
370       if (mFirstPassUnknown(Flags)) ImmV = Instr->Ofs;
371       else
372       {
373         WrError((ImmV < Instr->Ofs) ? ErrNum_UnderRange : ErrNum_OverRange);
374         OK = False;
375       }
376     }
377     if (OK)
378     {
379       WAsmCode[0] = Instr->Code + ((ImmV - Instr->Ofs) << 4) + RegX;
380       CodeLen = 2;
381     }
382   }
383 }
384 
DecodeLJmp(Word Index)385 static void DecodeLJmp(Word Index)
386 {
387   FixedOrder *Instr = LJmpOrders + Index;
388   LongInt Dest;
389   Boolean OK;
390   tSymbolFlags Flags;
391 
392   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
393   else if (ChkArgCnt(1, 1))
394   {
395     Dest = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags) - (EProgCounter() + 2);
396     if (OK)
397     {
398       if (!mSymbolQuestionable(Flags) && (Dest & 1)) WrError(ErrNum_DistIsOdd);
399       else if (!mSymbolQuestionable(Flags) && ((Dest > 2046) || (Dest < -2048))) WrError(ErrNum_JmpDistTooBig);
400       else
401       {
402         if ((Instr->Priv) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
403         WAsmCode[0] = Instr->Code + ((Dest >> 1) & 0x7ff);
404         CodeLen = 2;
405       }
406     }
407   }
408 }
409 
DecodeSJmp(Word Index)410 static void DecodeSJmp(Word Index)
411 {
412   LongInt Dest;
413   Boolean OK;
414   tSymbolFlags Flags;
415   int l = 0;
416 
417   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
418   else if (!ChkArgCnt(1, 1));
419   else if ((*ArgStr[1].Str != '[') || (ArgStr[1].Str[l = strlen(ArgStr[1].Str) - 1] != ']')) WrError(ErrNum_InvAddrMode);
420   else
421   {
422     ArgStr[1].Str[l] = '\0';
423     Dest = EvalStrIntExpressionOffsWithFlags(&ArgStr[1], 1, UInt32, &OK, &Flags);
424     if (OK)
425     {
426       if (!mSymbolQuestionable(Flags) && (Dest & 3)) WrError(ErrNum_NotAligned);
427       else
428       {
429         Dest = (Dest - (EProgCounter() + 2)) >> 2;
430         if ((EProgCounter() & 3) < 2) Dest++;
431         if (!mSymbolQuestionable(Flags) && ((Dest < 0) || (Dest > 255))) WrError(ErrNum_JmpDistTooBig);
432         else
433         {
434           WAsmCode[0] = 0x7000 + (Index << 8) + (Dest & 0xff);
435           CodeLen = 2;
436         }
437       }
438     }
439   }
440 }
441 
DecodeBGENI(Word Index)442 static void DecodeBGENI(Word Index)
443 {
444   Word RegX, ImmV;
445   Boolean OK;
446   UNUSED(Index);
447 
448   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
449   else if (ChkArgCnt(2, 2) && DecodeArgReg(1, &RegX, AllRegMask))
450   {
451     ImmV = EvalStrIntExpression(&ArgStr[2], UInt5, &OK);
452     if (OK)
453     {
454       if (ImmV > 6)
455         WAsmCode[0] = 0x3200 + (ImmV << 4) + RegX;
456       else
457         WAsmCode[0] = 0x6000 + (1 << (4 + ImmV)) + RegX;
458       CodeLen = 2;
459     }
460   }
461 }
462 
DecodeBMASKI(Word Index)463 static void DecodeBMASKI(Word Index)
464 {
465   Word RegX, ImmV;
466   Boolean OK;
467   tSymbolFlags Flags;
468 
469   UNUSED(Index);
470 
471   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
472   else if (ChkArgCnt(2, 2) && DecodeArgReg(1, &RegX, AllRegMask))
473   {
474     ImmV = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt6, &OK, &Flags);
475     if (mFirstPassUnknown(Flags) && ((ImmV < 1) || (ImmV > 32))) ImmV = 8;
476     if (OK)
477     {
478       if (ChkRange(ImmV, 1, 32))
479       {
480         ImmV &= 31;
481         if ((ImmV < 1) || (ImmV > 7))
482           WAsmCode[0] = 0x2c00 + (ImmV << 4) + RegX;
483         else
484           WAsmCode[0] = 0x6000 + (((1 << ImmV) - 1) << 4) + RegX;
485         CodeLen = 2;
486       }
487     }
488   }
489 }
490 
DecodeLdSt(Word Index)491 static void DecodeLdSt(Word Index)
492 {
493   Word RegX, RegZ, NSize;
494 
495   if (*AttrPart.Str && (Lo(Index) != 0xff)) WrError(ErrNum_UseLessAttr);
496   else if (!ChkArgCnt(2, 2));
497   else if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize);
498   else
499   {
500     if (Lo(Index) != 0xff) OpSize = (tSymbolSize)Lo(Index);
501     if (DecodeArgReg(1, &RegZ, AllRegMask) && DecodeAdr(&ArgStr[2], &RegX))
502     {
503       NSize = (OpSize == eSymbolSize32Bit) ? 0 : OpSize + 1;
504       WAsmCode[0] = 0x8000 + (NSize << 13) + (Hi(Index) << 12) + (RegZ << 8) + RegX;
505       CodeLen = 2;
506     }
507   }
508 }
509 
DecodeLdStm(Word Index)510 static void DecodeLdStm(Word Index)
511 {
512   Word RegF, RegL, RegI;
513 
514   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
515   else if (ChkArgCnt(2, 2)
516         && DecodeArgIReg(2, &RegI, 0x0001)
517         && DecodeArgRegPair(1, &RegF, 0x7ffe, &RegL, 0x8000))
518   {
519     WAsmCode[0] = 0x0060 + (Index << 4) + RegF;
520     CodeLen = 2;
521   }
522 }
523 
DecodeLdStq(Word Index)524 static void DecodeLdStq(Word Index)
525 {
526   Word RegF, RegL, RegX;
527 
528   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
529   else if (ChkArgCnt(2, 2)
530         && DecodeArgIReg(2, &RegX, 0xff0f)
531         && DecodeArgRegPair(1, &RegF, 0x0010, &RegL, 0x0080))
532   {
533     WAsmCode[0] = 0x0040 + (Index << 4) + RegX;
534     CodeLen = 2;
535   }
536 }
537 
DecodeLoopt(Word Index)538 static void DecodeLoopt(Word Index)
539 {
540   Word RegY;
541   LongInt Dest;
542   Boolean OK;
543   tSymbolFlags Flags;
544   UNUSED(Index);
545 
546   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
547   else if (ChkArgCnt(2, 2) && DecodeArgReg(1, &RegY, AllRegMask))
548   {
549     Dest = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt32, &OK, &Flags) - (EProgCounter() + 2);
550     if (OK)
551     {
552       if (!mSymbolQuestionable(Flags) && (Dest & 1)) WrError(ErrNum_DistIsOdd);
553       else if (!mSymbolQuestionable(Flags) && ((Dest > -2) || (Dest <- 32))) WrError(ErrNum_JmpDistTooBig);
554       else
555       {
556         WAsmCode[0] = 0x0400 + (RegY << 4) + ((Dest >> 1) & 15);
557         CodeLen = 2;
558       }
559     }
560   }
561 }
562 
DecodeLrm(Word Index)563 static void DecodeLrm(Word Index)
564 {
565   LongInt Dest;
566   Word RegZ;
567   Boolean OK;
568   tSymbolFlags Flags;
569   int l = 0;
570   UNUSED(Index);
571 
572   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
573   else if (!ChkArgCnt(2, 2));
574   else if (!DecodeArgReg(1, &RegZ, 0x7ffe));
575   else if ((*ArgStr[2].Str != '[') || (ArgStr[2].Str[l = strlen(ArgStr[2].Str) - 1] != ']')) WrError(ErrNum_InvAddrMode);
576   else
577   {
578     ArgStr[2].Str[l] = '\0';
579     Dest = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], 1, UInt32, &OK, &Flags);
580     if (OK)
581     {
582       if (!mSymbolQuestionable(Flags) && (Dest & 3)) WrError(ErrNum_NotAligned);
583       else
584       {
585         Dest = (Dest - (EProgCounter() + 2)) >> 2;
586         if ((EProgCounter() & 3) < 2) Dest++;
587         if (!mSymbolQuestionable(Flags) && ((Dest < 0) || (Dest > 255))) WrError(ErrNum_JmpDistTooBig);
588         else
589         {
590           WAsmCode[0] = 0x7000 + (RegZ << 8) + (Dest & 0xff);
591           CodeLen = 2;
592         }
593       }
594     }
595   }
596 }
597 
DecodeMcr(Word Index)598 static void DecodeMcr(Word Index)
599 {
600   Word RegX,CRegY;
601 
602   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
603   else if (ChkArgCnt(2, 2)
604         && DecodeArgReg(1, &RegX, AllRegMask)
605         && DecodeArgCReg(2, &CRegY))
606   {
607     if (!SupAllowed) WrError(ErrNum_PrivOrder);
608     WAsmCode[0] = 0x1000 + (Index << 11) + (CRegY << 4) + RegX;
609     CodeLen = 2;
610   }
611 }
612 
DecodeMovi(Word Index)613 static void DecodeMovi(Word Index)
614 {
615   Word RegX, ImmV;
616   Boolean OK;
617   UNUSED(Index);
618 
619   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
620   else if (ChkArgCnt(2, 2) && DecodeArgReg(1, &RegX, AllRegMask))
621   {
622     ImmV = EvalStrIntExpression(&ArgStr[2], UInt7, &OK);
623     if (OK)
624     {
625       WAsmCode[0] = 0x6000 + ((ImmV & 127) << 4) + RegX;
626       CodeLen = 2;
627     }
628   }
629 }
630 
DecodeTrap(Word Index)631 static void DecodeTrap(Word Index)
632 {
633   Word ImmV;
634   Boolean OK;
635   UNUSED(Index);
636 
637   if (*AttrPart.Str) WrError(ErrNum_UseLessAttr);
638   else if (!ChkArgCnt(1, 1));
639   else if (*ArgStr[1].Str != '#') WrError(ErrNum_OnlyImmAddr);
640   else
641   {
642     ImmV = EvalStrIntExpressionOffs(&ArgStr[1], 1, UInt2, &OK);
643     if (OK)
644     {
645       WAsmCode[0] = 0x0008 + ImmV;
646       CodeLen = 2;
647     }
648   }
649 }
650 
651 /*--------------------------------------------------------------------------*/
652 /* Codetabellenverwaltung */
653 
AddFixed(const char * NName,Word NCode,Boolean NPriv)654 static void AddFixed(const char *NName, Word NCode, Boolean NPriv)
655 {
656   if (InstrZ >= FixedOrderCnt) exit(255);
657   FixedOrders[InstrZ].Code = NCode;
658   FixedOrders[InstrZ].Priv = NPriv;
659   AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
660 }
661 
AddOneReg(const char * NName,Word NCode,Boolean NPriv)662 static void AddOneReg(const char *NName, Word NCode, Boolean NPriv)
663 {
664   if (InstrZ >= OneRegOrderCnt) exit(255);
665   OneRegOrders[InstrZ].Code = NCode;
666   OneRegOrders[InstrZ].Priv = NPriv;
667   AddInstTable(InstTable, NName, InstrZ++, DecodeOneReg);
668 }
669 
AddTwoReg(const char * NName,Word NCode,Boolean NPriv)670 static void AddTwoReg(const char *NName, Word NCode, Boolean NPriv)
671 {
672   if (InstrZ >= TwoRegOrderCnt) exit(255);
673   TwoRegOrders[InstrZ].Code = NCode;
674   TwoRegOrders[InstrZ].Priv = NPriv;
675   AddInstTable(InstTable, NName, InstrZ++, DecodeTwoReg);
676 }
677 
AddUImm5(const char * NName,Word NCode,Word NMin,Word NOfs)678 static void AddUImm5(const char *NName, Word NCode, Word NMin, Word NOfs)
679 {
680    if (InstrZ >= UImm5OrderCnt) exit(255);
681    UImm5Orders[InstrZ].Code = NCode;
682    UImm5Orders[InstrZ].Min = NMin;
683    UImm5Orders[InstrZ].Ofs = NOfs;
684    AddInstTable(InstTable, NName, InstrZ++, DecodeUImm5);
685 }
686 
AddLJmp(const char * NName,Word NCode,Boolean NPriv)687 static void AddLJmp(const char *NName, Word NCode, Boolean NPriv)
688 {
689   if (InstrZ >= LJmpOrderCnt) exit(255);
690   LJmpOrders[InstrZ].Code = NCode;
691   LJmpOrders[InstrZ].Priv = NPriv;
692   AddInstTable(InstTable, NName, InstrZ++, DecodeLJmp);
693 }
694 
AddCReg(const char * NName,Word NCode)695 static void AddCReg(const char *NName, Word NCode)
696 {
697   if (InstrZ >= CRegCnt) exit(255);
698   CRegs[InstrZ].Name = NName;
699   CRegs[InstrZ++].Code = NCode;
700 }
701 
InitFields(void)702 static void InitFields(void)
703 {
704   InstTable = CreateInstTable(201);
705 
706   AddInstTable(InstTable, "REG", 0, CodeREG);
707 
708   InstrZ = 0; FixedOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * FixedOrderCnt);
709   AddFixed("BKPT" , 0x0000, False);
710   AddFixed("DOZE" , 0x0006, True );
711   AddFixed("RFI"  , 0x0003, True );
712   AddFixed("RTE"  , 0x0002, True );
713   AddFixed("STOP" , 0x0004, True );
714   AddFixed("SYNC" , 0x0001, False);
715   AddFixed("WAIT" , 0x0005, True );
716 
717   InstrZ = 0; OneRegOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * OneRegOrderCnt);
718   AddOneReg("ABS"   , 0x01e0, False);  AddOneReg("ASRC" , 0x3a00, False);
719   AddOneReg("BREV"  , 0x00f0, False);  AddOneReg("CLRF" , 0x01d0, False);
720   AddOneReg("CLRT"  , 0x01c0, False);  AddOneReg("DECF" , 0x0090, False);
721   AddOneReg("DECGT" , 0x01a0, False);  AddOneReg("DECLT", 0x0180, False);
722   AddOneReg("DECNE" , 0x01b0, False);  AddOneReg("DECT" , 0x0080, False);
723   AddOneReg("DIVS"  , 0x3210, False);  AddOneReg("DIVU" , 0x2c10, False);
724   AddOneReg("FF1"   , 0x00e0, False);  AddOneReg("INCF" , 0x00b0, False);
725   AddOneReg("INCT"  , 0x00a0, False);  AddOneReg("JMP"  , 0x00c0, False);
726   AddOneReg("JSR"   , 0x00d0, False);  AddOneReg("LSLC" , 0x3c00, False);
727   AddOneReg("LSRC"  , 0x3e00, False);  AddOneReg("MVC"  , 0x0020, False);
728   AddOneReg("MVCV"  , 0x0030, False);  AddOneReg("NOT"  , 0x01f0, False);
729   AddOneReg("SEXTB" , 0x0150, False);  AddOneReg("SEXTH", 0x0170, False);
730   AddOneReg("TSTNBZ", 0x0190, False);  AddOneReg("XSR"  , 0x3800, False);
731   AddOneReg("XTRB0" , 0x0130, False);  AddOneReg("XTRB1", 0x0120, False);
732   AddOneReg("XTRB2" , 0x0110, False);  AddOneReg("XTRB3", 0x0100, False);
733   AddOneReg("ZEXTB" , 0x0140, False);  AddOneReg("ZEXTH", 0x0160, False);
734 
735   InstrZ = 0; TwoRegOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * TwoRegOrderCnt);
736   AddTwoReg("ADDC" , 0x0600, False);  AddTwoReg("ADDU" , 0x1c00, False);
737   AddTwoReg("AND"  , 0x1600, False);  AddTwoReg("ANDN" , 0x1f00, False);
738   AddTwoReg("ASR"  , 0x1a00, False);  AddTwoReg("BGENR", 0x1300, False);
739   AddTwoReg("CMPHS", 0x0c00, False);  AddTwoReg("CMPLT", 0x0d00, False);
740   AddTwoReg("CMPNE", 0x0f00, False);  AddTwoReg("IXH"  , 0x1d00, False);
741   AddTwoReg("IXW"  , 0x1500, False);  AddTwoReg("LSL"  , 0x1b00, False);
742   AddTwoReg("LSR"  , 0x0b00, False);  AddTwoReg("MOV"  , 0x1200, False);
743   AddTwoReg("MOVF" , 0x0a00, False);  AddTwoReg("MOVT" , 0x0200, False);
744   AddTwoReg("MULT" , 0x0300, False);  AddTwoReg("OR"   , 0x1e00, False);
745   AddTwoReg("RSUB" , 0x1400, False);  AddTwoReg("SUBC" , 0x0700, False);
746   AddTwoReg("SUBU" , 0x0500, False);  AddTwoReg("TST"  , 0x0e00, False);
747   AddTwoReg("XOR"  , 0x1700, False);
748 
749   InstrZ = 0; UImm5Orders = (ImmOrder *) malloc(sizeof(ImmOrder) * UImm5OrderCnt);
750   AddUImm5("ADDI"  , 0x2000, 0, 1);  AddUImm5("ANDI"  , 0x2e00, 0, 0);
751   AddUImm5("ASRI"  , 0x3a00, 1, 0);  AddUImm5("BCLRI" , 0x3000, 0, 0);
752   AddUImm5("BSETI" , 0x3400, 0, 0);  AddUImm5("BTSTI" , 0x3600, 0, 0);
753   AddUImm5("CMPLTI", 0x2200, 0, 1);  AddUImm5("CMPNEI", 0x2a00, 0, 0);
754   AddUImm5("LSLI"  , 0x3c00, 1, 0);  AddUImm5("LSRI"  , 0x3e00, 1, 0);
755   AddUImm5("ROTLI" , 0x3800, 1, 0);  AddUImm5("RSUBI" , 0x2800, 0, 0);
756   AddUImm5("SUBI"  , 0x2400, 0, 1);
757 
758   InstrZ = 0; LJmpOrders = (FixedOrder *) malloc(sizeof(FixedOrder) * LJmpOrderCnt);
759   AddLJmp("BF"   , 0xe800, False);  AddLJmp("BR"   , 0xf000, False);
760   AddLJmp("BSR"  , 0xf800, False);  AddLJmp("BT"   , 0xe000, False);
761 
762   InstrZ = 0; CRegs = (CReg *) malloc(sizeof(CReg) * CRegCnt);
763   AddCReg("PSR" , 0); AddCReg("VBR" , 1);
764   AddCReg("EPSR", 2); AddCReg("FPSR", 3);
765   AddCReg("EPC" , 4); AddCReg("FPC",  5);
766   AddCReg("SS0",  6); AddCReg("SS1",  7);
767   AddCReg("SS2",  8); AddCReg("SS3",  9);
768   AddCReg("SS4", 10); AddCReg("GCR", 11);
769   AddCReg("GSR", 12);
770 
771   AddInstTable(InstTable, "BGENI" , 0, DecodeBGENI);
772   AddInstTable(InstTable, "BMASKI", 0, DecodeBMASKI);
773   AddInstTable(InstTable, "JMPI"  , 0, DecodeSJmp);
774   AddInstTable(InstTable, "JSRI"  , 0, DecodeSJmp);
775   AddInstTable(InstTable, "LD"    , 0x0ff, DecodeLdSt);
776   AddInstTable(InstTable, "LDB"   , 0x000, DecodeLdSt);
777   AddInstTable(InstTable, "LDH"   , 0x001, DecodeLdSt);
778   AddInstTable(InstTable, "LDW"   , 0x002, DecodeLdSt);
779   AddInstTable(InstTable, "ST"    , 0x1ff, DecodeLdSt);
780   AddInstTable(InstTable, "STB"   , 0x100, DecodeLdSt);
781   AddInstTable(InstTable, "STH"   , 0x101, DecodeLdSt);
782   AddInstTable(InstTable, "STW"   , 0x102, DecodeLdSt);
783   AddInstTable(InstTable, "LDM"   , 0, DecodeLdStm);
784   AddInstTable(InstTable, "STM"   , 1, DecodeLdStm);
785   AddInstTable(InstTable, "LDQ"   , 0, DecodeLdStq);
786   AddInstTable(InstTable, "STQ"   , 1, DecodeLdStq);
787   AddInstTable(InstTable, "LOOPT" , 0, DecodeLoopt);
788   AddInstTable(InstTable, "LRM"   , 0, DecodeLrm);
789   AddInstTable(InstTable, "MFCR"  , 0, DecodeMcr);
790   AddInstTable(InstTable, "MTCR"  , 1, DecodeMcr);
791   AddInstTable(InstTable, "MOVI"  , 0, DecodeMovi);
792   AddInstTable(InstTable, "TRAP"  , 0, DecodeTrap);
793 }
794 
DeinitFields(void)795 static void DeinitFields(void)
796 {
797   DestroyInstTable(InstTable);
798   free(FixedOrders);
799   free(OneRegOrders);
800   free(TwoRegOrders);
801   free(UImm5Orders);
802   free(LJmpOrders);
803   free(CRegs);
804 }
805 
806 /*--------------------------------------------------------------------------*/
807 /* Callbacks */
808 
809 /*!------------------------------------------------------------------------
810  * \fn     InternSymbol_MCORE(char *pArg, TempResult *pResult)
811  * \brief  handle built-in (register) symbols for M-CORE
812  * \param  pArg source argument
813  * \param  pResult buffer for possible result
814  * ------------------------------------------------------------------------ */
815 
InternSymbol_MCORE(char * pArg,TempResult * pResult)816 static void InternSymbol_MCORE(char *pArg, TempResult *pResult)
817 {
818   Word RegNum;
819 
820   if (DecodeRegCore(pArg, &RegNum))
821   {
822     pResult->Typ = TempReg;
823     pResult->DataSize = eSymbolSize32Bit;
824     pResult->Contents.RegDescr.Dissect = DissectReg_MCORE;
825     pResult->Contents.RegDescr.Reg = RegNum;
826   }
827 }
828 
DecodeAttrPart_MCORE(void)829 static Boolean DecodeAttrPart_MCORE(void)
830 {
831   /* operand size identifiers slightly differ from '68K Standard': */
832 
833   switch (as_toupper(*AttrPart.Str))
834   {
835     case 'H': AttrPartOpSize = eSymbolSize16Bit; break;
836     case 'W': AttrPartOpSize = eSymbolSize32Bit; break;
837     case 'L': WrStrErrorPos(ErrNum_UndefAttr, &AttrPart); return False;
838     default:
839       return DecodeMoto16AttrSize(*AttrPart.Str, &AttrPartOpSize, False);
840   }
841   return True;
842 }
843 
MakeCode_MCORE(void)844 static void MakeCode_MCORE(void)
845 {
846   CodeLen = 0;
847 
848   OpSize = (AttrPartOpSize != eSymbolSizeUnknown) ? AttrPartOpSize : eSymbolSize32Bit;
849   DontPrint = False;
850 
851   /* Nullanweisung */
852 
853   if ((*OpPart.Str == '\0') && !*AttrPart.Str && (ArgCnt == 0)) return;
854 
855   /* Pseudoanweisungen */
856 
857   if (DecodeMoto16Pseudo(OpSize,True)) return;
858 
859   /* Befehlszaehler ungerade ? */
860 
861   if (Odd(EProgCounter())) WrError(ErrNum_AddrNotAligned);
862 
863   /* alles aus der Tabelle */
864 
865   if (!LookupInstTable(InstTable, OpPart.Str))
866     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
867 }
868 
IsDef_MCORE(void)869 static Boolean IsDef_MCORE(void)
870 {
871   return Memo("REG");
872 }
873 
SwitchFrom_MCORE(void)874 static void SwitchFrom_MCORE(void)
875 {
876   DeinitFields();
877   ClearONOFF();
878 }
879 
SwitchTo_MCORE(void)880 static void SwitchTo_MCORE(void)
881 {
882   TurnWords = True; ConstMode = ConstModeMoto;
883 
884    PCSymbol = "*"; HeaderID = 0x03; NOPCode = 0x1200; /* ==MOV r0,r0 */
885    DivideChars = ","; HasAttrs = True; AttrChars = ".";
886 
887    ValidSegs = (1 << SegCode);
888    Grans[SegCode] = 1; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
889    SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
890 
891    DecodeAttrPart = DecodeAttrPart_MCORE;
892    MakeCode = MakeCode_MCORE;
893    IsDef = IsDef_MCORE;
894    InternSymbol = InternSymbol_MCORE;
895    DissectReg = DissectReg_MCORE;
896 
897    SwitchFrom = SwitchFrom_MCORE; InitFields();
898    AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName, False);
899    AddMoto16PseudoONOFF();
900 
901    SetFlag(&DoPadding, DoPaddingName, True);
902 }
903 
904 /*--------------------------------------------------------------------------*/
905 /* Initialisierung */
906 
codemcore_init(void)907 void codemcore_init(void)
908 {
909   CPUMCORE = AddCPU("MCORE", SwitchTo_MCORE);
910 }
911