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