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