1 /* code960.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* Makroassembler AS                                                         */
6 /*                                                                           */
7 /* Codegenerator i960-Familie                                                */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include <string.h>
13 #include <ctype.h>
14 
15 #include "endian.h"
16 #include "strutil.h"
17 #include "bpemu.h"
18 #include "asmdef.h"
19 #include "asmsub.h"
20 #include "asmpars.h"
21 #include "asmallg.h"
22 #include "asmitree.h"
23 #include "codevars.h"
24 #include "intpseudo.h"
25 #include "headids.h"
26 #include "errmsg.h"
27 
28 #include "code960.h"
29 
30 /*--------------------------------------------------------------------------*/
31 
32 enum
33 {
34   ModNone = -1,
35   ModReg = 0,
36   ModFReg = 1,
37   ModImm = 2
38 };
39 
40 #define MModReg (1 << ModReg)
41 #define MModFReg (1 << ModFReg)
42 #define MModImm (1 << ModImm)
43 
44 #define FixedOrderCnt 13
45 #define RegOrderCnt 116
46 #define CobrOrderCnt 24
47 #define CtrlOrderCnt 11
48 #define MemOrderCnt 20
49 #define SpecRegCnt 4
50 
51 typedef enum
52 {
53   NoneOp, IntOp, LongOp, QuadOp, SingleOp, DoubleOp, ExtOp, OpCnt
54 } OpType;
55 
56 static LongWord OpMasks[OpCnt] =
57 {
58   0xffffffff, 0, 1, 3, 0, 1, 3
59 };
60 
61 typedef struct
62 {
63   LongWord Code;
64 } FixedOrder;
65 
66 typedef struct
67 {
68   LongWord Code;
69   Boolean HasSrc;
70 } CobrOrder;
71 
72 typedef struct
73 {
74   LongWord Code;
75   OpType Src1Type, Src2Type, DestType;
76   Boolean Imm1, Imm2, Privileged;
77 } RegOrder;
78 
79 typedef struct
80 {
81   LongWord Code;
82   OpType Type;
83   ShortInt RegPos;
84 } MemOrder;
85 
86 typedef struct
87 {
88   char Name[4];
89   LongWord Code;
90 } SpecReg;
91 
92 #define REG_MARK 32
93 
94 static FixedOrder *FixedOrders;
95 static RegOrder *RegOrders;
96 static CobrOrder *CobrOrders;
97 static FixedOrder *CtrlOrders;
98 static MemOrder *MemOrders;
99 static const SpecReg SpecRegs[SpecRegCnt] =
100 {
101   { "FP" , 31 },
102   { "PFP",  0 },
103   { "SP" ,  1 },
104   { "RIP",  2 }
105 };
106 
107 static CPUVar CPU80960;
108 
109 /*--------------------------------------------------------------------------*/
110 
ChkAdr(int AMode,Byte Mask,LongWord * Erg,LongWord * Mode)111 static Boolean ChkAdr(int AMode, Byte Mask, LongWord *Erg, LongWord *Mode)
112 {
113   UNUSED(Erg);
114 
115   if (!(Mask & (1 << AMode)))
116   {
117     WrError(ErrNum_InvAddrMode);
118     return False;
119   }
120   else
121   {
122     *Mode = (AMode != ModReg);
123     return True;
124   }
125 }
126 
127 /*!------------------------------------------------------------------------
128  * \fn     DecodeIRegCore(const char *pArg, LongWord *pResult)
129  * \brief  check whether argument is a CPU register
130  * \param  pArg source argument
131  * \param  pResult register # if yes
132  * \return True if yes
133  * ------------------------------------------------------------------------ */
134 
DecodeIRegCore(const char * pArg,LongWord * pResult)135 static Boolean DecodeIRegCore(const char *pArg, LongWord *pResult)
136 {
137   int z;
138   LongWord Offs;
139 
140   for (z = 0; z < SpecRegCnt; z++)
141    if (!as_strcasecmp(pArg, SpecRegs[z].Name))
142    {
143      *pResult = REG_MARK | SpecRegs[z].Code;
144      return True;
145    }
146 
147   switch (as_toupper(*pArg))
148   {
149     case 'G':
150       Offs = 16;
151       goto eval;
152     case 'R':
153       Offs = 0;
154       goto eval;
155     default:
156       return False;
157     eval:
158     {
159       char *pEnd;
160 
161       *pResult = strtoul(pArg + 1, &pEnd, 10);
162       if (!*pEnd && (*pResult <= 15))
163       {
164         *pResult += Offs;
165         return True;
166       }
167     }
168   }
169 
170   return False;
171 }
172 
173 /*!------------------------------------------------------------------------
174  * \fn     DecodeFPRegCore(const char *pArg, LongWord *pResult)
175  * \brief  check whether argument is an FPU register
176  * \param  pArg source argument
177  * \param  pResult register # if yes
178  * \return True if yes
179  * ------------------------------------------------------------------------ */
180 
DecodeFPRegCore(const char * pArg,LongWord * pResult)181 static Boolean DecodeFPRegCore(const char *pArg, LongWord *pResult)
182 {
183   if (!as_strncasecmp(pArg, "FP", 2))
184   {
185     char *pEnd;
186 
187     *pResult = strtoul(pArg + 2, &pEnd, 10);
188     if (!*pEnd && (*pResult <= 3))
189       return True;
190   }
191 
192   return False;
193 }
194 
195 /*!------------------------------------------------------------------------
196  * \fn     DissectReg_960(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
197  * \brief  dissect register symbols - i960 variant
198  * \param  pDest destination buffer
199  * \param  DestSize destination buffer size
200  * \param  Value numeric register value
201  * \param  InpSize register size
202  * ------------------------------------------------------------------------ */
203 
DissectReg_960(char * pDest,size_t DestSize,tRegInt Value,tSymbolSize InpSize)204 static void DissectReg_960(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize)
205 {
206   switch (InpSize)
207   {
208     case eSymbolSize32Bit:
209     {
210       int z;
211 
212       for (z = 0; z < SpecRegCnt; z++)
213         if (Value == (REG_MARK | SpecRegs[z].Code))
214         {
215           as_snprintf(pDest, DestSize, "%s", SpecRegs[z].Name);
216           return;
217         }
218       as_snprintf(pDest, DestSize, "%c%u", Value & 16 ? 'G' : 'R', (unsigned)(Value & 15));
219       break;
220     }
221     case eSymbolSizeFloat64Bit:
222       as_snprintf(pDest, DestSize, "FP%u", (unsigned)Value);
223       break;
224     default:
225       as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value);
226   }
227 }
228 
229 /*!------------------------------------------------------------------------
230  * \fn     DecodeIReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
231  * \brief  check whether argument is a CPU register or register alias
232  * \param  pArg source argument
233  * \param  pResult register # if yes
234  * \param  MustBeReg True if register is expected
235  * \return reg eval result
236  * ------------------------------------------------------------------------ */
237 
DecodeIReg(const tStrComp * pArg,LongWord * pResult,Boolean MustBeReg)238 static tRegEvalResult DecodeIReg(const tStrComp *pArg, LongWord *pResult, Boolean MustBeReg)
239 {
240   if (DecodeIRegCore(pArg->Str, pResult))
241   {
242     *pResult &= ~REG_MARK;
243     return eIsReg;
244   }
245   else
246   {
247     tRegDescr RegDescr;
248     tEvalResult EvalResult;
249     tRegEvalResult RegEvalResult;
250 
251     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSize32Bit, MustBeReg);
252     if (eIsReg == RegEvalResult)
253       *pResult = RegDescr.Reg & ~REG_MARK;
254     return RegEvalResult;
255   }
256 }
257 
258 /*!------------------------------------------------------------------------
259  * \fn     DecodeIOrFPReg(const tStrComp *pArg, LongWord *pResult, tSymbolSize *pSize, Boolean MustBeReg)
260  * \brief  check whether argument is a CPU/FPU register or register alias
261  * \param  pArg source argument
262  * \param  pResult register # if yes
263  * \param  pSize returns register size/type
264  * \param  MustBeReg True if register is expected
265  * \return reg eval result
266  * ------------------------------------------------------------------------ */
267 
DecodeIOrFPReg(const tStrComp * pArg,LongWord * pResult,tSymbolSize * pSize,Boolean MustBeReg)268 static tRegEvalResult DecodeIOrFPReg(const tStrComp *pArg, LongWord *pResult, tSymbolSize *pSize, Boolean MustBeReg)
269 {
270   if (DecodeIRegCore(pArg->Str, pResult))
271   {
272     *pResult &= ~REG_MARK;
273     *pSize = eSymbolSize32Bit;
274     return eIsReg;
275   }
276   else if (DecodeFPRegCore(pArg->Str, pResult))
277   {
278     *pSize = eSymbolSizeFloat64Bit;
279     return eIsReg;
280   }
281   else
282   {
283     tRegDescr RegDescr;
284     tEvalResult EvalResult;
285     tRegEvalResult RegEvalResult;
286 
287     RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg);
288     if (eIsReg == RegEvalResult)
289     {
290       *pResult = RegDescr.Reg & ~REG_MARK;
291       *pSize = EvalResult.DataSize;
292     }
293     return RegEvalResult;
294   }
295 }
296 
DecodeAdr(const tStrComp * pArg,Byte Mask,OpType Type,LongWord * Erg,LongWord * Mode)297 static Boolean DecodeAdr(const tStrComp *pArg, Byte Mask, OpType Type, LongWord *Erg, LongWord *Mode)
298 {
299   Double FVal;
300   tEvalResult EvalResult;
301   tSymbolSize DataSize;
302 
303   *Mode = ModNone;
304   *Erg = 0;
305 
306   switch (DecodeIOrFPReg(pArg, Erg, &DataSize, False))
307   {
308     case eIsReg:
309       switch (DataSize)
310       {
311         case eSymbolSize32Bit:
312           if ((*Erg) & OpMasks[Type])
313           {
314             WrStrErrorPos(ErrNum_InvRegPair, pArg);
315             return False;
316           }
317           else
318             return ChkAdr(ModReg, Mask, Erg, Mode);
319           break;
320         case eSymbolSizeFloat64Bit:
321           return ChkAdr(ModFReg, Mask, Erg, Mode);
322         default:
323           break;
324       }
325       break;
326     case eRegAbort:
327       return False;
328     case eIsNoReg:
329       break;
330   }
331 
332   if (Type != IntOp)
333   {
334     FVal = EvalStrFloatExpressionWithResult(pArg, Float64, &EvalResult);
335     if (EvalResult.OK)
336     {
337       if (mFirstPassUnknown(EvalResult.Flags))
338         FVal = 0.0;
339       if (FVal == 0.0)
340         *Erg = 16;
341       else if (FVal == 1.0)
342         *Erg = 22;
343       else
344       {
345         WrError(ErrNum_OverRange);
346         EvalResult.OK = False;
347       }
348       if (EvalResult.OK)
349         return ChkAdr(ModImm, Mask, Erg, Mode);
350     }
351   }
352   else
353   {
354     *Erg = EvalStrIntExpressionWithResult(pArg, UInt5, &EvalResult);
355     if (EvalResult.OK)
356       return ChkAdr(ModImm, Mask, Erg, Mode);
357   }
358   return False;
359 }
360 
361 #define NOREG 33
362 #define IPREG 32
363 
AddrError(tErrorNum Num)364 static int AddrError(tErrorNum Num)
365 {
366   WrError(Num);
367   return -1;
368 }
369 
DecodeMem(const tStrComp * pArg,LongWord * Erg,LongWord * Ext)370 static int DecodeMem(const tStrComp *pArg, LongWord *Erg, LongWord *Ext)
371 {
372   LongInt DispAcc;
373   LongWord Base, Index, Scale, Mode;
374   Boolean Done;
375   int ArgLen, Scale2;
376   char *p, *p2, *end;
377   Boolean OK;
378   tStrComp Arg = *pArg, RegArg, ScaleArg;
379 
380   Base = Index = NOREG;
381   Scale = 0;
382 
383   /* Register abhobeln */
384 
385   Done = FALSE;
386   do
387   {
388     ArgLen = strlen(Arg.Str);
389     if (ArgLen == 0)
390       Done = True;
391     else switch (Arg.Str[ArgLen - 1])
392     {
393       case ']':
394         if (Index != NOREG) return AddrError(ErrNum_InvAddrMode);
395         for (p = Arg.Str + ArgLen - 1; p >= Arg.Str; p--)
396           if (*p == '[')
397             break;
398         if (p < Arg.Str) return AddrError(ErrNum_BrackErr);
399         StrCompShorten(&Arg, 1);
400         StrCompSplitRef(&Arg, &RegArg, &Arg, p);
401         p2 = strchr(RegArg.Str, '*');
402         if (p2)
403         {
404           StrCompSplitRef(&RegArg, &ScaleArg, &RegArg, p2);
405           Scale2 = strtol(ScaleArg.Str, &end, 10);
406           if (*end != '\0') return AddrError(ErrNum_InvAddrMode);
407           for (Scale = 0; Scale < 5; Scale++, Scale2 = Scale2 >> 1)
408             if (Odd(Scale2))
409               break;
410           if (Scale2 != 1) return AddrError(ErrNum_InvAddrMode);
411         }
412         if (DecodeIReg(&RegArg, &Index, True) != eIsReg)
413           return -1;
414 
415         break;
416       case ')':
417         if (Base != NOREG) return AddrError(ErrNum_InvAddrMode);
418         for (p = Arg.Str + ArgLen - 1; p >= Arg.Str; p--)
419           if (*p == '(')
420             break;
421         if (p < Arg.Str) return AddrError(ErrNum_BrackErr);
422         StrCompShorten(&Arg, 1);
423         StrCompSplitRef(&Arg, &RegArg, &Arg, p);
424         if (!as_strcasecmp(RegArg.Str, "IP"))
425           Base = IPREG;
426         else if (DecodeIReg(&RegArg, &Base, True) != eIsReg)
427           return -1;
428         break;
429       default:
430         Done = True;
431     }
432   }
433   while (!Done);
434 
435   DispAcc = EvalStrIntExpression(&Arg, Int32, &OK);
436 
437   if (Base == IPREG)
438   {
439     DispAcc -= EProgCounter() + 8;
440     if (Index != NOREG) return AddrError(ErrNum_InvAddrMode);
441     else
442     {
443       *Erg = (5 << 10);
444       *Ext = DispAcc;
445       return 1;
446     }
447   }
448   else if ((Index == NOREG) && (DispAcc >= 0) && (DispAcc <= 4095))
449   {
450     *Erg = DispAcc;
451     if (Base != NOREG)
452       *Erg += 0x2000 + (Base << 14);
453     return 0;
454   }
455   else
456   {
457     Mode = (Ord(DispAcc != 0) << 3) + 4 + (Ord(Index != NOREG) << 1) + Ord(Base != NOREG);
458     if ((Mode & 9) == 0)
459       Mode += 8;
460     if (Mode == 5)
461       Mode--;
462     *Erg = (Mode << 10);
463     if (Base != NOREG)
464       *Erg += Base << 14;
465     if (Index != NOREG)
466       *Erg += Index + (Scale << 7);
467     if (Mode < 8) return 0;
468     else
469     {
470       *Ext = DispAcc;
471       return 1;
472     }
473   }
474 }
475 
476 /*--------------------------------------------------------------------------*/
477 
DecodeFixed(Word Index)478 static void DecodeFixed(Word Index)
479 {
480   FixedOrder *Op = FixedOrders + Index;
481 
482   if (ChkArgCnt(0, 0))
483   {
484     DAsmCode[0] = Op->Code;
485     CodeLen = 4;
486   }
487 }
488 
DecodeReg(Word Index)489 static void DecodeReg(Word Index)
490 {
491   RegOrder *Op = RegOrders + Index;
492   LongWord DReg = 0, DMode = 0;
493   LongWord S1Reg = 0, S1Mode = 0;
494   LongWord S2Reg = 0, S2Mode = 0;
495   unsigned NumArgs = 1 + Ord(Op->Src2Type != NoneOp) + Ord(Op->DestType != NoneOp), ActArgCnt;
496   tStrComp *pDestArg = NULL;
497 
498   /* if destination required, but too few args, assume the last op is also destination */
499 
500   ActArgCnt = ArgCnt;
501   if (Op->DestType != NoneOp)
502   {
503     if (ArgCnt == 1 + Ord(Op->Src2Type != NoneOp))
504       ActArgCnt++;
505     pDestArg = &ArgStr[ArgCnt];
506   }
507 
508   if (!ChkArgCntExt(ActArgCnt, NumArgs, NumArgs));
509   else if (((Op->DestType >= SingleOp) || (Op->Src1Type >= SingleOp)) && (!FPUAvail)) WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
510   else if (((Op->DestType == NoneOp) || (DecodeAdr(pDestArg, MModReg | (Op->DestType >= SingleOp ? MModFReg : 0), Op->DestType, &DReg, &DMode)))
511         && (DecodeAdr(&ArgStr[1], MModReg | (Op->Src1Type >= SingleOp ? MModFReg : 0) | (Op->Imm1 ? MModImm : 0 ), Op->Src1Type, &S1Reg, &S1Mode))
512         && ((Op->Src2Type == NoneOp) || (DecodeAdr(&ArgStr[2], MModReg | (Op->Src2Type >= SingleOp ? MModFReg : 0) | (Op->Imm2 ? MModImm : 0), Op->Src2Type, &S2Reg, &S2Mode))))
513   {
514     DAsmCode[0] = ((Op->Code & 0xff0) << 20)
515                 + ((Op->Code & 0xf) << 7)
516                 + (S1Reg)
517                 + (S2Reg << 14)
518                 + (DReg << 19)
519                 + (S1Mode << 11)
520                 + (S2Mode << 12)
521                 + (DMode << 13);
522     CodeLen = 4;
523     if ((Op->Privileged) && (!SupAllowed)) WrError(ErrNum_PrivOrder);
524   }
525 }
526 
DecodeCobr(Word Index)527 static void DecodeCobr(Word Index)
528 {
529   CobrOrder *Op = CobrOrders + Index;
530   LongWord S1Reg, S1Mode;
531   LongWord S2Reg = 0, S2Mode = 0;
532   LongInt AdrInt;
533   Boolean OK;
534   tSymbolFlags Flags;
535   unsigned NumArgs = 1 + 2 * Ord(Op->HasSrc);
536 
537   if (!ChkArgCnt(NumArgs, NumArgs));
538   else if ((DecodeAdr(&ArgStr[1], MModReg | (Op->HasSrc ? MModImm : 0), IntOp, &S1Reg, &S1Mode))
539         && ((!Op->HasSrc) || (DecodeAdr(&ArgStr[2], MModReg, IntOp, &S2Reg, &S2Mode))))
540   {
541     OK = True;
542     Flags = eSymbolFlag_None;
543     AdrInt = (Op->HasSrc) ? EvalStrIntExpressionWithFlags(&ArgStr[3], UInt32, &OK, &Flags) - EProgCounter() : 0;
544     if (mFirstPassUnknown(Flags))
545       AdrInt &= (~3);
546     if (OK)
547     {
548       if (AdrInt & 3) WrError(ErrNum_NotAligned);
549       else if (!mSymbolQuestionable(Flags) && ((AdrInt < -4096) || (AdrInt > 4090))) WrError(ErrNum_JmpDistTooBig);
550       else
551       {
552         DAsmCode[0] = (Op->Code << 24)
553                     + (S1Reg << 19)
554                     + (S2Reg << 14)
555                     + (S1Mode << 13)
556                     + (AdrInt & 0x1ffc);
557         CodeLen = 4;
558       }
559     }
560   }
561 }
562 
DecodeCtrl(Word Index)563 static void DecodeCtrl(Word Index)
564 {
565   FixedOrder *Op = CtrlOrders + Index;
566   LongInt AdrInt;
567   tSymbolFlags Flags;
568   Boolean OK;
569 
570   if (ChkArgCnt(1, 1))
571   {
572     AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags) - EProgCounter();
573     if (mFirstPassUnknown(Flags)) AdrInt &= (~3);
574     if (OK)
575     {
576       if (AdrInt & 3) WrError(ErrNum_NotAligned);
577       else if (!mSymbolQuestionable(Flags) && ((AdrInt < -8388608) || (AdrInt > 8388604))) WrError(ErrNum_JmpDistTooBig);
578       else
579       {
580         DAsmCode[0] = (Op->Code << 24) + (AdrInt & 0xfffffc);
581         CodeLen = 4;
582       }
583     }
584   }
585 }
586 
DecodeMemO(Word Index)587 static void DecodeMemO(Word Index)
588 {
589   MemOrder *Op = MemOrders + Index;
590   LongWord Reg = 0, Mem = 0;
591   int MemType;
592   ShortInt MemPos = (Op->RegPos > 0) ? 3 - Op->RegPos : 1;
593   unsigned NumArgs = 1 + Ord(Op->RegPos > 0);
594 
595   if (!ChkArgCnt(NumArgs, NumArgs));
596   else if ((Op->RegPos > 0) && (DecodeIReg(&ArgStr[Op->RegPos], &Reg, True) != eIsReg));
597   else if (Reg & OpMasks[Op->Type]) WrStrErrorPos(ErrNum_InvReg, &ArgStr[Op->RegPos]);
598   else if ((MemType = DecodeMem(&ArgStr[MemPos], &Mem,DAsmCode + 1)) >= 0)
599   {
600     DAsmCode[0] = (Op->Code << 24) + (Reg << 19) + Mem;
601     CodeLen = (1 + MemType) << 2;
602   }
603 }
604 
DecodeWORD(Word Code)605 static void DecodeWORD(Word Code)
606 {
607   Boolean OK;
608   int z;
609 
610   UNUSED(Code);
611 
612   if (ChkArgCnt(1, ArgCntMax))
613   {
614     OK = True;
615     z = 1;
616     while ((z <= ArgCnt) && (OK))
617     {
618       DAsmCode[z - 1] = EvalStrIntExpression(&ArgStr[z], Int32, &OK);
619       z++;
620     }
621     if (OK)
622       CodeLen = 4 * ArgCnt;
623   }
624 }
625 
DecodeSPACE(Word Code)626 static void DecodeSPACE(Word Code)
627 {
628   Boolean OK;
629   LongWord Size;
630   tSymbolFlags Flags;
631 
632   UNUSED(Code);
633 
634   if (ChkArgCnt(1, 1))
635   {
636     Size = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags);
637     if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
638     if (OK && !mFirstPassUnknown(Flags))
639     {
640       DontPrint = True;
641       if (!Size) WrError(ErrNum_NullResMem);
642       CodeLen = Size;
643       BookKeeping();
644     }
645   }
646 }
647 
648 /*--------------------------------------------------------------------------*/
649 
MakeCode_960(void)650 static void MakeCode_960(void)
651 {
652   CodeLen = 0;
653   DontPrint = False;
654 
655   /* Nullanweisung */
656 
657   if (Memo(""))
658     return;
659 
660   /* Pseudoanweisungen */
661 
662   if (DecodeIntelPseudo(False))
663     return;
664 
665   /* Befehlszaehler nicht ausgerichtet? */
666 
667   if (EProgCounter() & 3)
668     WrError(ErrNum_AddrNotAligned);
669 
670   /* CPU-Anweisungen */
671 
672   if (!LookupInstTable(InstTable, OpPart.Str))
673     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
674 }
675 
676 /*--------------------------------------------------------------------------*/
677 
AddFixed(const char * NName,LongWord NCode)678 static void AddFixed(const char *NName, LongWord NCode)
679 {
680   if (InstrZ >= FixedOrderCnt) exit(255);
681   FixedOrders[InstrZ].Code = NCode;
682   AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
683 }
684 
AddReg(const char * NName,LongWord NCode,OpType NSrc1,OpType NSrc2,OpType NDest,Boolean NImm1,Boolean NImm2,Boolean NPriv)685 static void AddReg(const char *NName, LongWord NCode,
686                    OpType NSrc1, OpType NSrc2, OpType NDest,
687                    Boolean NImm1, Boolean NImm2, Boolean NPriv)
688 {
689   if (InstrZ >= RegOrderCnt) exit(255);
690   RegOrders[InstrZ].Code = NCode;
691   RegOrders[InstrZ].Src1Type = NSrc1;
692   RegOrders[InstrZ].Src2Type = NSrc2;
693   RegOrders[InstrZ].DestType = NDest;
694   RegOrders[InstrZ].Imm1 = NImm1;
695   RegOrders[InstrZ].Imm2 = NImm2;
696   RegOrders[InstrZ].Privileged = NPriv;
697   AddInstTable(InstTable, NName, InstrZ++, DecodeReg);
698 }
699 
AddCobr(const char * NName,LongWord NCode,Boolean NHas)700 static void AddCobr(const char *NName, LongWord NCode, Boolean NHas)
701 {
702   if (InstrZ >= CobrOrderCnt) exit(255);
703   CobrOrders[InstrZ].Code = NCode;
704   CobrOrders[InstrZ].HasSrc = NHas;
705   AddInstTable(InstTable, NName, InstrZ++, DecodeCobr);
706 }
707 
AddCtrl(const char * NName,LongWord NCode)708 static void AddCtrl(const char *NName, LongWord NCode)
709 {
710   if (InstrZ >= CtrlOrderCnt) exit(255);
711   CtrlOrders[InstrZ].Code = NCode;
712   AddInstTable(InstTable, NName, InstrZ++, DecodeCtrl);
713 }
714 
AddMem(const char * NName,LongWord NCode,OpType NType,int NPos)715 static void AddMem(const char *NName, LongWord NCode, OpType NType, int NPos)
716 {
717   if (InstrZ >= MemOrderCnt) exit(255);
718   MemOrders[InstrZ].Code = NCode;
719   MemOrders[InstrZ].Type = NType;
720   MemOrders[InstrZ].RegPos = NPos;
721   AddInstTable(InstTable, NName, InstrZ++, DecodeMemO);
722 }
723 
InitFields(void)724 static void InitFields(void)
725 {
726   InstTable = CreateInstTable(301);
727 
728   FixedOrders = (FixedOrder*) malloc(sizeof(FixedOrder)*FixedOrderCnt); InstrZ = 0;
729   AddFixed("FLUSHREG", 0x66000680);
730   AddFixed("FMARK"   , 0x66000600);
731   AddFixed("MARK"    , 0x66000580);
732   AddFixed("RET"     , 0x0a000000);
733   AddFixed("SYNCF"   , 0x66000780);
734   AddFixed("FAULTNO" , 0x18000000);
735   AddFixed("FAULTG"  , 0x19000000);
736   AddFixed("FAULTE"  , 0x1a000000);
737   AddFixed("FAULTGE" , 0x1b000000);
738   AddFixed("FAULTL"  , 0x1c000000);
739   AddFixed("FAULTNE" , 0x1d000000);
740   AddFixed("FAULTLE" , 0x1e000000);
741   AddFixed("FAULTO"  , 0x1f000000);
742 
743   RegOrders = (RegOrder*) malloc(sizeof(RegOrder)*RegOrderCnt); InstrZ = 0;
744       /*  Name       OpCode Src1Type  Src2Type  DestType  Imm1   Imm2 */
745   AddReg("ADDC"    , 0x5b0, IntOp   , IntOp   , IntOp   , True , True , False);
746   AddReg("ADDI"    , 0x591, IntOp   , IntOp   , IntOp   , True , True , False);
747   AddReg("ADDO"    , 0x590, IntOp   , IntOp   , IntOp   , True , True , False);
748   AddReg("ADDR"    , 0x78f, SingleOp, SingleOp, SingleOp, True , True , False);
749   AddReg("ADDRL"   , 0x79f, DoubleOp, DoubleOp, DoubleOp, True , True , False);
750   AddReg("ALTERBIT", 0x58f, IntOp   , IntOp   , IntOp   , True , True , False);
751   AddReg("AND"     , 0x581, IntOp   , IntOp   , IntOp   , True , True , False);
752   AddReg("ANDNOT"  , 0x582, IntOp   , IntOp   , IntOp   , True , True , False);
753   AddReg("ATADD"   , 0x612, IntOp   , IntOp   , IntOp   , True , True , False);
754   AddReg("ATANR"   , 0x680, SingleOp, SingleOp, SingleOp, True , True , False);
755   AddReg("ATANRL"  , 0x690, DoubleOp, DoubleOp, DoubleOp, True , True , False);
756   AddReg("ATMOD"   , 0x610, IntOp   , IntOp   , IntOp   , True , True , False);
757   AddReg("CALLS"   , 0x660, IntOp   , NoneOp  , NoneOp  , True , False, False);
758   AddReg("CHKBIT"  , 0x5ae, IntOp   , IntOp   , NoneOp  , True , True , False);
759   AddReg("CLASSR"  , 0x68f, SingleOp, NoneOp  , NoneOp  , True , False, False);
760   AddReg("CLASSRL" , 0x69f, DoubleOp, NoneOp  , NoneOp  , True , False, False);
761   AddReg("CLRBIT"  , 0x58c, IntOp   , IntOp   , IntOp   , True , True , False);
762   AddReg("CMPDECI" , 0x5a7, IntOp   , IntOp   , IntOp   , True , False, False);
763   AddReg("CMPDECO" , 0x5a6, IntOp   , IntOp   , IntOp   , True , False, False);
764   AddReg("CMPI"    , 0x5a1, IntOp   , IntOp   , NoneOp  , True , True , False);
765   AddReg("CMPO"    , 0x5a0, IntOp   , IntOp   , NoneOp  , True , True , False);
766   AddReg("CMPINCI" , 0x5a5, IntOp   , IntOp   , IntOp   , True , False, False);
767   AddReg("CMPINCO" , 0x5a4, IntOp   , IntOp   , IntOp   , True , False, False);
768   AddReg("CMPOR"   , 0x684, SingleOp, SingleOp, NoneOp  , True , True , False);
769   AddReg("CMPORL"  , 0x694, DoubleOp, DoubleOp, NoneOp  , True , True , False);
770   AddReg("CMPR"    , 0x685, SingleOp, SingleOp, NoneOp  , True , True , False);
771   AddReg("CMPRL"   , 0x695, DoubleOp, DoubleOp, NoneOp  , True , True , False);
772   AddReg("CONCMPI" , 0x5a3, IntOp   , IntOp   , NoneOp  , True , True , False);
773   AddReg("CONCMPO" , 0x5a2, IntOp   , IntOp   , NoneOp  , True , True , False);
774   AddReg("COSR"    , 0x68d, SingleOp, NoneOp  , SingleOp, True , False, False);
775   AddReg("COSRL"   , 0x69d, DoubleOp, NoneOp  , DoubleOp, True , False, False);
776   AddReg("CPYSRE"  , 0x6e2, SingleOp, SingleOp, SingleOp, True , True , False);
777   AddReg("CPYRSRE" , 0x6e3, SingleOp, SingleOp, SingleOp, True , True , False);
778   AddReg("CVTIR"   , 0x674, IntOp,    NoneOp  , SingleOp, True , False, False);
779   AddReg("CVTILR"  , 0x675, LongOp,   NoneOp  , DoubleOp, True , False, False);
780   AddReg("CVTRI"   , 0x6c0, SingleOp, NoneOp  , IntOp   , True , False, False);
781   AddReg("CVTRIL"  , 0x6c1, SingleOp, NoneOp  , LongOp  , True , False, False);
782   AddReg("CVTZRI"  , 0x6c2, IntOp   , NoneOp  , IntOp   , True , False, False);
783   AddReg("CVTZRIL" , 0x6c2, LongOp  , NoneOp  , LongOp  , True , False, False);
784       /*  Name       OpCode Src1Type  Src2Type  DestType  Imm1   Imm2 */
785   AddReg("DADDC"   , 0x642, IntOp   , IntOp   , IntOp   , False, False, False);
786   AddReg("DIVI"    , 0x74b, IntOp   , IntOp   , IntOp   , True , True , False);
787   AddReg("DIVO"    , 0x70b, IntOp   , IntOp   , IntOp   , True , True , False);
788   AddReg("DIVR"    , 0x78b, SingleOp, SingleOp, SingleOp, True , True , False);
789   AddReg("DIVRL"   , 0x79b, DoubleOp, DoubleOp, DoubleOp, True , True , False);
790   AddReg("DMOVT"   , 0x644, IntOp   , NoneOp  , IntOp   , False, False, False);
791   AddReg("DSUBC"   , 0x643, IntOp   , IntOp   , IntOp   , False, False, False);
792   AddReg("EDIV"    , 0x671, IntOp   , LongOp  , LongOp  , True , True , False);
793   AddReg("EMUL"    , 0x670, IntOp   , IntOp   , LongOp  , True , True , False);
794   AddReg("EXPR"    , 0x689, SingleOp, NoneOp  , SingleOp, True , False, False);
795   AddReg("EXPRL"   , 0x699, DoubleOp, NoneOp  , DoubleOp, True , False, False);
796   AddReg("EXTRACT" , 0x651, IntOp   , IntOp   , IntOp   , True , True , False);
797   AddReg("LOGBNR"  , 0x68a, SingleOp, NoneOp  , SingleOp, True , False, False);
798   AddReg("LOGBNRL" , 0x69a, DoubleOp, NoneOp  , DoubleOp, True , False, False);
799   AddReg("LOGEPR"  , 0x681, SingleOp, SingleOp, SingleOp, True , True , False);
800   AddReg("LOGEPRL" , 0x691, DoubleOp, DoubleOp, DoubleOp, True , True , False);
801   AddReg("LOGR"    , 0x682, SingleOp, SingleOp, SingleOp, True , True , False);
802   AddReg("LOGRL"   , 0x692, DoubleOp, DoubleOp, DoubleOp, True , True , False);
803   AddReg("MODAC"   , 0x645, IntOp   , IntOp   , IntOp   , True , True , False);
804   AddReg("MODI"    , 0x749, IntOp   , IntOp   , IntOp   , True , True , False);
805   AddReg("MODIFY"  , 0x650, IntOp   , IntOp   , IntOp   , True , True , False);
806   AddReg("MODPC"   , 0x655, IntOp   , IntOp   , IntOp   , True , True , True );
807   AddReg("MODTC"   , 0x654, IntOp   , IntOp   , IntOp   , True , True , False);
808   AddReg("MOV"     , 0x5cc, IntOp   , NoneOp  , IntOp   , True , False, False);
809   AddReg("MOVL"    , 0x5dc, LongOp  , NoneOp  , LongOp  , True , False, False);
810   AddReg("MOVT"    , 0x5ec, QuadOp  , NoneOp  , QuadOp  , True , False, False);
811   AddReg("MOVQ"    , 0x5fc, QuadOp  , NoneOp  , QuadOp  , True , False, False);
812   AddReg("MOVR"    , 0x6c9, SingleOp, NoneOp  , SingleOp, True , False, False);
813   AddReg("MOVRL"   , 0x6d9, DoubleOp, NoneOp  , DoubleOp, True , False, False);
814   AddReg("MOVRE"   , 0x6e1, ExtOp   , NoneOp  , ExtOp   , True , False, False);
815   AddReg("MULI"    , 0x741, IntOp   , IntOp   , IntOp   , True , True , False);
816   AddReg("MULO"    , 0x701, IntOp   , IntOp   , IntOp   , True , True , False);
817   AddReg("MULR"    , 0x78c, SingleOp, SingleOp, SingleOp, True , True , False);
818   AddReg("MULRL"   , 0x79c, DoubleOp, DoubleOp, DoubleOp, True , True , False);
819   AddReg("NAND"    , 0x58e, IntOp   , IntOp   , IntOp   , True , True , False);
820   AddReg("NOR"     , 0x588, IntOp   , IntOp   , IntOp   , True , True , False);
821   AddReg("NOT"     , 0x58a, IntOp   , NoneOp  , IntOp   , True , False, False);
822   AddReg("NOTAND"  , 0x584, IntOp   , IntOp   , IntOp   , True , True , False);
823   AddReg("NOTBIT"  , 0x580, IntOp   , IntOp   , IntOp   , True , True , False);
824   AddReg("NOTOR"   , 0x58d, IntOp   , IntOp   , IntOp   , True , True , False);
825   AddReg("OR"      , 0x587, IntOp   , IntOp   , IntOp   , True , True , False);
826   AddReg("ORNOT"   , 0x58b, IntOp   , IntOp   , IntOp   , True , True , False);
827       /*  Name       OpCode TwoSrc HDest  Float     Imm1   Imm2 */
828   AddReg("REMI"    , 0x748, IntOp   , IntOp   , IntOp   , True , True , False);
829   AddReg("REMO"    , 0x708, IntOp   , IntOp   , IntOp   , True , True , False);
830   AddReg("REMR"    , 0x683, SingleOp, SingleOp, SingleOp, True , True , False);
831   AddReg("REMRL"   , 0x693, DoubleOp, DoubleOp, DoubleOp, True , True , False);
832   AddReg("ROTATE"  , 0x59d, IntOp   , IntOp   , IntOp   , True , True , False);
833   AddReg("ROUNDR"  , 0x68b, SingleOp, NoneOp  , SingleOp, True , False, False);
834   AddReg("ROUNDRL" , 0x69b, DoubleOp, NoneOp  , DoubleOp, True , False, False);
835   AddReg("SCALER"  , 0x677, IntOp   , SingleOp, SingleOp, True , True , False);
836   AddReg("SCALERL" , 0x676, IntOp   , DoubleOp, DoubleOp, True , True , False);
837   AddReg("SCANBIT" , 0x641, IntOp   , NoneOp  , IntOp   , True , False, False);
838   AddReg("SCANBYTE", 0x5ac, IntOp   , NoneOp  , IntOp   , True , False, False);
839   AddReg("SETBIT"  , 0x583, IntOp   , IntOp   , IntOp   , True , True , False);
840   AddReg("SHLO"    , 0x59c, IntOp   , IntOp   , IntOp   , True , True , False);
841   AddReg("SHRO"    , 0x598, IntOp   , IntOp   , IntOp   , True , True , False);
842   AddReg("SHLI"    , 0x59e, IntOp   , IntOp   , IntOp   , True , True , False);
843   AddReg("SHRI"    , 0x59B, IntOp   , IntOp   , IntOp   , True , True , False);
844   AddReg("SHRDI"   , 0x59a, IntOp   , IntOp   , IntOp   , True , True , False);
845   AddReg("SINR"    , 0x68c, SingleOp, NoneOp  , SingleOp, True , False, False);
846   AddReg("SINRL"   , 0x69c, DoubleOp, NoneOp  , DoubleOp, True , False, False);
847   AddReg("SPANBIT" , 0x640, IntOp   , NoneOp  , IntOp   , True , False, False);
848   AddReg("SQRTR"   , 0x688, SingleOp, NoneOp  , SingleOp, True , False, False);
849   AddReg("SQRTRL"  , 0x698, DoubleOp, NoneOp  , DoubleOp, True , False, False);
850   AddReg("SUBC"    , 0x5b2, IntOp   , IntOp   , IntOp   , True , True , False);
851   AddReg("SUBI"    , 0x593, IntOp   , IntOp   , IntOp   , True , True , False);
852   AddReg("SUBO"    , 0x592, IntOp   , IntOp   , IntOp   , True , True , False);
853   AddReg("SUBR"    , 0x78d, SingleOp, SingleOp, SingleOp, True , True , False);
854   AddReg("SUBRL"   , 0x79d, DoubleOp, DoubleOp, DoubleOp, True , True , False);
855   AddReg("SYNLD"   , 0x615, IntOp   , NoneOp  , IntOp   , False, False, False);
856   AddReg("SYNMOV"  , 0x600, IntOp   , NoneOp  , IntOp   , False, False, False);
857   AddReg("SYNMOVL" , 0x601, IntOp   , NoneOp  , IntOp   , False, False, False);
858   AddReg("SYNMOVQ" , 0x602, IntOp   , NoneOp  , IntOp   , False, False, False);
859   AddReg("TANR"    , 0x68e, SingleOp, NoneOp  , SingleOp, True , False, False);
860   AddReg("TANRL"   , 0x69e, DoubleOp, NoneOp  , DoubleOp, True , False, False);
861   AddReg("XOR"     , 0x589, IntOp   , IntOp   , IntOp   , True , True , False);
862   AddReg("XNOR"    , 0x589, IntOp   , IntOp   , IntOp   , True , True , False);
863 
864   CobrOrders = (CobrOrder*) malloc(sizeof(CobrOrder)*CobrOrderCnt); InstrZ = 0;
865   AddCobr("BBC"    , 0x30, True ); AddCobr("BBS"    , 0x37, True );
866   AddCobr("CMPIBE" , 0x3a, True ); AddCobr("CMPOBE" , 0x32, True );
867   AddCobr("CMPIBNE", 0x3d, True ); AddCobr("CMPOBNE", 0x35, True );
868   AddCobr("CMPIBL" , 0x3c, True ); AddCobr("CMPOBL" , 0x34, True );
869   AddCobr("CMPIBLE", 0x3e, True ); AddCobr("CMPOBLE", 0x36, True );
870   AddCobr("CMPIBG" , 0x39, True ); AddCobr("CMPOBG" , 0x31, True );
871   AddCobr("CMPIBGE", 0x3b, True ); AddCobr("CMPOBGE", 0x33, True );
872   AddCobr("CMPIBO" , 0x3f, True ); AddCobr("CMPIBNO", 0x38, True );
873   AddCobr("TESTE"  , 0x22, False); AddCobr("TESTNE" , 0x25, False);
874   AddCobr("TESTL"  , 0x24, False); AddCobr("TESTLE" , 0x26, False);
875   AddCobr("TESTG"  , 0x21, False); AddCobr("TESTGE" , 0x23, False);
876   AddCobr("TESTO"  , 0x27, False); AddCobr("TESTNO" , 0x27, False);
877 
878   CtrlOrders = (FixedOrder*) malloc(sizeof(FixedOrder)*CtrlOrderCnt); InstrZ = 0;
879   AddCtrl("B"   , 0x08); AddCtrl("CALL", 0x09);
880   AddCtrl("BAL" , 0x0b); AddCtrl("BNO" , 0x19);
881   AddCtrl("BG"  , 0x11); AddCtrl("BE"  , 0x12);
882   AddCtrl("BGE" , 0x13); AddCtrl("BL"  , 0x14);
883   AddCtrl("BNE" , 0x15); AddCtrl("BLE" , 0x16);
884   AddCtrl("BO"  , 0x17);
885 
886   MemOrders = (MemOrder*) malloc(sizeof(MemOrder)*MemOrderCnt); InstrZ = 0;
887   AddMem("LDOB" , 0x80, IntOp   , 2);
888   AddMem("STOB" , 0x82, IntOp   , 1);
889   AddMem("BX"   , 0x84, IntOp   , 0);
890   AddMem("BALX" , 0x85, IntOp   , 2);
891   AddMem("CALLX", 0x86, IntOp   , 0);
892   AddMem("LDOS" , 0x88, IntOp   , 2);
893   AddMem("STOS" , 0x8a, IntOp   , 1);
894   AddMem("LDA"  , 0x8c, IntOp   , 2);
895   AddMem("LD"   , 0x90, IntOp   , 2);
896   AddMem("ST"   , 0x92, IntOp   , 1);
897   AddMem("LDL"  , 0x98, LongOp  , 2);
898   AddMem("STL"  , 0x9a, LongOp  , 1);
899   AddMem("LDT"  , 0xa0, QuadOp  , 2);
900   AddMem("STT"  , 0xa2, QuadOp  , 1);
901   AddMem("LDQ"  , 0xb0, QuadOp  , 2);
902   AddMem("STQ"  , 0xb2, QuadOp  , 1);
903   AddMem("LDIB" , 0xc0, IntOp   , 2);
904   AddMem("STIB" , 0xc2, IntOp   , 1);
905   AddMem("LDIS" , 0xc8, IntOp   , 2);
906   AddMem("STIS" , 0xca, IntOp   , 1);
907 
908   AddInstTable(InstTable, "WORD", 0, DecodeWORD);
909   AddInstTable(InstTable, "SPACE", 0, DecodeSPACE);
910   AddInstTable(InstTable, "REG", 0, CodeREG);
911 }
912 
DeinitFields(void)913 static void DeinitFields(void)
914 {
915   DestroyInstTable(InstTable);
916   free(FixedOrders);
917   free(RegOrders);
918   free(CobrOrders);
919   free(CtrlOrders);
920 }
921 
922 /*--------------------------------------------------------------------------*/
923 
IsDef_960(void)924 static Boolean IsDef_960(void)
925 {
926   return Memo("REG");
927 }
928 
InitPass_960(void)929 static void InitPass_960(void)
930 {
931   SetFlag(&FPUAvail, FPUAvailName, False);
932 }
933 
SwitchFrom_960(void)934 static void SwitchFrom_960(void)
935 {
936   DeinitFields();
937   ClearONOFF();
938 }
939 
940 /*!------------------------------------------------------------------------
941  * \fn     InternSymbol_960(char *pArg, TempResult *pResult)
942  * \brief  handle built-in symbols on i960
943  * \param  pArg source argument
944  * \param  pResult result buffer
945  * ------------------------------------------------------------------------ */
946 
InternSymbol_960(char * pArg,TempResult * pResult)947 static void InternSymbol_960(char *pArg, TempResult *pResult)
948 {
949   LongWord Reg;
950 
951   if (DecodeIRegCore(pArg, &Reg))
952   {
953     pResult->Typ = TempReg;
954     pResult->DataSize = eSymbolSize32Bit;
955     pResult->Contents.RegDescr.Reg = Reg;
956     pResult->Contents.RegDescr.Dissect = DissectReg_960;
957   }
958   else if (DecodeFPRegCore(pArg, &Reg))
959   {
960     pResult->Typ = TempReg;
961     pResult->DataSize = eSymbolSizeFloat64Bit;
962     pResult->Contents.RegDescr.Reg = Reg;
963     pResult->Contents.RegDescr.Dissect = DissectReg_960;
964   }
965 }
966 
SwitchTo_960(void)967 static void SwitchTo_960(void)
968 {
969   PFamilyDescr FoundId;
970 
971   TurnWords = False;
972   ConstMode = ConstModeIntel;
973 
974   FoundId = FindFamilyByName("i960");
975   if (!FoundId)
976     exit(255);
977   PCSymbol = "$";
978   HeaderID = FoundId->Id;
979   NOPCode = 0x000000000;
980   DivideChars = ",";
981   HasAttrs = False;
982 
983   ValidSegs=(1 << SegCode);
984   Grans[SegCode] = 1;
985   ListGrans[SegCode] = 4;
986   SegInits[SegCode] = 0;
987   SegLimits[SegCode] = (LargeWord)IntTypeDefs[UInt32].Max;
988 
989   MakeCode = MakeCode_960;
990   IsDef = IsDef_960;
991   InternSymbol = InternSymbol_960;
992   DissectReg = DissectReg_960;
993   SwitchFrom=SwitchFrom_960;
994   AddONOFF("FPU"     , &FPUAvail  , FPUAvailName  , False);
995   AddONOFF("SUPMODE" , &SupAllowed, SupAllowedName, False);
996 
997   InitFields();
998 }
999 
code960_init(void)1000 void code960_init(void)
1001 {
1002   CPU80960 = AddCPU("80960", SwitchTo_960);
1003 
1004   AddInitPassProc(InitPass_960);
1005 }
1006