Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* codez8000.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS-Portierung */ |
||
6 | /* */ |
||
7 | /* Codegenerator Zilog Z8000 */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "stdinc.h" |
||
12 | #include <string.h> |
||
13 | #include <stdarg.h> |
||
14 | #include <ctype.h> |
||
15 | |||
16 | #include "cpulist.h" |
||
17 | #include "headids.h" |
||
18 | #include "strutil.h" |
||
19 | #include "intformat.h" |
||
20 | #include "bpemu.h" |
||
21 | #include "asmdef.h" |
||
22 | #include "asmsub.h" |
||
23 | #include "asmpars.h" |
||
24 | #include "asmallg.h" |
||
25 | #include "onoff_common.h" |
||
26 | #include "asmitree.h" |
||
27 | #include "asmstructs.h" |
||
28 | #include "codepseudo.h" |
||
29 | #include "codevars.h" |
||
30 | #include "intpseudo.h" |
||
31 | #include "operator.h" |
||
32 | |||
33 | #include "codez8000.h" |
||
34 | |||
35 | typedef enum |
||
36 | { |
||
37 | eCoreNone = 0, |
||
38 | eCoreZ8001 = 1, |
||
39 | eCoreZ8003 = 2 |
||
40 | } tCore; |
||
41 | |||
42 | typedef struct |
||
43 | { |
||
44 | const char *pName; |
||
45 | tCore Core; |
||
46 | Boolean SuppSegmented; |
||
47 | } tCPUProps; |
||
48 | |||
49 | typedef enum eAdrMode |
||
50 | { |
||
51 | eModNone = 0, |
||
52 | eModReg = 1, |
||
53 | eModIReg = 2, |
||
54 | eModDirect = 3, |
||
55 | eModIndexed = 4, |
||
56 | eModBaseAddress = 5, |
||
57 | eModBaseIndexed = 6, |
||
58 | eModImm = 7, |
||
59 | eModCtl = 8 |
||
60 | } tAdrMode; |
||
61 | |||
62 | #define MModReg (1 << eModReg) |
||
63 | #define MModIReg (1 << eModIReg) |
||
64 | #define MModDirect (1 << eModDirect) |
||
65 | #define MModIndexed (1 << eModIndexed) |
||
66 | #define MModBaseAddress (1 << eModBaseAddress) |
||
67 | #define MModBaseIndexed (1 << eModBaseIndexed) |
||
68 | #define MModImm (1 << eModImm) |
||
69 | #define MModCtl (1 << eModCtl) |
||
70 | |||
71 | #define MModIO (1 << 15) |
||
72 | |||
73 | #define MModNoImm (MModReg | MModIReg | MModDirect | MModIndexed | MModBaseAddress | MModBaseIndexed) |
||
74 | #define MModAll (MModNoImm | MModImm) |
||
75 | |||
76 | #define eSymbolSize4Bit ((tSymbolSize)-2) |
||
77 | #define eSymbolSize3Bit ((tSymbolSize)-3) |
||
78 | |||
79 | typedef struct |
||
80 | { |
||
81 | tAdrMode Mode; |
||
82 | unsigned Cnt; |
||
83 | Word Val, Vals[3]; |
||
84 | } tAdrVals; |
||
85 | |||
86 | typedef struct |
||
87 | { |
||
88 | Word Code; |
||
89 | Boolean Privileged; |
||
90 | } FixedOrder; |
||
91 | |||
92 | typedef enum |
||
93 | { |
||
94 | ePrivileged = 1 << 0, |
||
95 | eSegMode = 1 << 1, |
||
96 | eNonSegMode = 1 << 2 |
||
97 | } tCtlFlags; |
||
98 | |||
99 | typedef struct |
||
100 | { |
||
101 | const char *pName; |
||
102 | Word Code; |
||
103 | tCtlFlags Flags; |
||
104 | tSymbolSize Size; |
||
105 | } tCtlReg; |
||
106 | |||
107 | typedef struct |
||
108 | { |
||
109 | const char *pName; |
||
110 | Word Code; |
||
111 | } tCondition; |
||
112 | |||
113 | /* Auto-optimization of LD #imm4,Rn -> LDK disabled for the moment, |
||
114 | until we find a syntax to control it: */ |
||
115 | |||
116 | #define OPT_LD_LDK 0 |
||
117 | |||
118 | static const tCPUProps *pCurrCPUProps; |
||
119 | |||
120 | static FixedOrder *FixedOrders; |
||
121 | static tCtlReg *CtlRegs; |
||
122 | static tCondition *Conditions; |
||
123 | static int CtlRegCnt; |
||
124 | |||
125 | static tSymbolSize OpSize; |
||
126 | static ShortInt ImmOpSize; |
||
127 | static IntType MemIntType; |
||
128 | |||
129 | static LongInt AMDSyntax; |
||
130 | |||
131 | #ifdef __cplusplus |
||
132 | #include "codez8000.hpp" |
||
133 | #endif |
||
134 | |||
135 | /*--------------------------------------------------------------------------*/ |
||
136 | /* Helper Functions */ |
||
137 | |||
138 | /*!------------------------------------------------------------------------ |
||
139 | * \fn CheckSup(Boolean Required) |
||
140 | * \brief check whether supervisor mode requirement and complain if violated |
||
141 | * \param Required is supervisor mode required? |
||
142 | * \return False if violated |
||
143 | * ------------------------------------------------------------------------ */ |
||
144 | |||
145 | static Boolean CheckSup(Boolean Required) |
||
146 | { |
||
147 | if (!SupAllowed && Required) |
||
148 | { |
||
149 | WrStrErrorPos(ErrNum_PrivOrder, &OpPart); |
||
150 | return False; |
||
151 | } |
||
152 | return True; |
||
153 | } |
||
154 | |||
155 | /*!------------------------------------------------------------------------ |
||
156 | * \fn Segmented(void) |
||
157 | * \brief operating in segmented mode? |
||
158 | * \return True if yes |
||
159 | * ------------------------------------------------------------------------ */ |
||
160 | |||
161 | static Boolean Segmented(void) |
||
162 | { |
||
163 | return pCurrCPUProps->SuppSegmented; |
||
164 | } |
||
165 | |||
166 | /*!------------------------------------------------------------------------ |
||
167 | * \fn AddrRegSize(void) |
||
168 | * \brief return size of address register |
||
169 | * \return 16 or 32 bit |
||
170 | * ------------------------------------------------------------------------ */ |
||
171 | |||
172 | static tSymbolSize AddrRegSize(void) |
||
173 | { |
||
174 | return Segmented() ? eSymbolSize32Bit : eSymbolSize16Bit; |
||
175 | } |
||
176 | |||
177 | /*!------------------------------------------------------------------------ |
||
178 | * \fn GetSegment(LongWord Address) |
||
179 | * \brief extract segment from (linear) address |
||
180 | * \param Address (linear) address |
||
181 | * \return segment |
||
182 | * ------------------------------------------------------------------------ */ |
||
183 | |||
184 | static Word GetSegment(LongWord Address) |
||
185 | { |
||
186 | return (Address >> 16) & 0x7f; |
||
187 | } |
||
188 | |||
189 | /*--------------------------------------------------------------------------*/ |
||
190 | /* Register Handling */ |
||
191 | |||
192 | /*!------------------------------------------------------------------------ |
||
193 | * \fn DecodeRegCore(const char *pArg, Word *pValue, tSymbolSize *pSize) |
||
194 | * \brief check whether argument describes a CPU (general purpose) register |
||
195 | * \param pArg source argument |
||
196 | * \param pValue register number if yes |
||
197 | * \param pSize register size if yes |
||
198 | * \return True if it is |
||
199 | * ------------------------------------------------------------------------ */ |
||
200 | |||
201 | static Boolean DecodeRegCore(const char *pArg, Word *pValue, tSymbolSize *pSize) |
||
202 | { |
||
203 | Word Offset = 0, MaskVal, MaxVal; |
||
204 | |||
205 | if (as_toupper(*pArg) != 'R') |
||
206 | return False; |
||
207 | pArg++; |
||
208 | |||
209 | switch (as_toupper(*pArg)) |
||
210 | { |
||
211 | case 'H': |
||
212 | *pSize = eSymbolSize8Bit; |
||
213 | MaskVal = 0; MaxVal = 7; |
||
214 | pArg++; |
||
215 | goto Num; |
||
216 | case 'L': |
||
217 | *pSize = eSymbolSize8Bit; |
||
218 | Offset = 8; |
||
219 | MaskVal = 0; MaxVal = 15; |
||
220 | pArg++; |
||
221 | goto Num; |
||
222 | case 'R': |
||
223 | *pSize = eSymbolSize32Bit; |
||
224 | MaskVal = 1; MaxVal = 15; |
||
225 | pArg++; |
||
226 | goto Num; |
||
227 | case 'Q': |
||
228 | *pSize = eSymbolSize64Bit; |
||
229 | MaskVal = 3; MaxVal = 15; |
||
230 | pArg++; |
||
231 | goto Num; |
||
232 | default: |
||
233 | *pSize = eSymbolSize16Bit; |
||
234 | MaskVal = 0; MaxVal = 15; |
||
235 | /* fall-thru */ |
||
236 | Num: |
||
237 | { |
||
238 | char *pEnd; |
||
239 | |||
240 | *pValue = strtoul(pArg, &pEnd, 10) + Offset; |
||
241 | return !*pEnd && (*pValue <= MaxVal) && !(*pValue & MaskVal); |
||
242 | } |
||
243 | } |
||
244 | } |
||
245 | |||
246 | /*!------------------------------------------------------------------------ |
||
247 | * \fn DissectReg_Z8000(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize) |
||
248 | * \brief dissect register symbols - Z8000 variant |
||
249 | * \param pDest destination buffer |
||
250 | * \param DestSize destination buffer size |
||
251 | * \param Value numeric register value |
||
252 | * \param InpSize register size |
||
253 | * ------------------------------------------------------------------------ */ |
||
254 | |||
255 | static void DissectReg_Z8000(char *pDest, size_t DestSize, tRegInt Value, tSymbolSize InpSize) |
||
256 | { |
||
257 | switch (InpSize) |
||
258 | { |
||
259 | case eSymbolSize8Bit: |
||
260 | as_snprintf(pDest, DestSize, "R%c%u", "HL"[(Value >> 3) & 1], (unsigned)(Value & 7)); |
||
261 | break; |
||
262 | case eSymbolSize16Bit: |
||
263 | as_snprintf(pDest, DestSize, "R%u", (unsigned)Value); |
||
264 | break; |
||
265 | case eSymbolSize32Bit: |
||
266 | as_snprintf(pDest, DestSize, "RR%u", (unsigned)Value); |
||
267 | break; |
||
268 | case eSymbolSize64Bit: |
||
269 | as_snprintf(pDest, DestSize, "RQ%u", (unsigned)Value); |
||
270 | break; |
||
271 | default: |
||
272 | as_snprintf(pDest, DestSize, "%d-%u", (int)InpSize, (unsigned)Value); |
||
273 | } |
||
274 | } |
||
275 | |||
276 | /*!------------------------------------------------------------------------ |
||
277 | * \fn ChkRegOverlap(Word FirstReg, int FirstSize, ...) |
||
278 | * \brief check for register overlap |
||
279 | * \param FirstReg first register # |
||
280 | * \param FirstSize first register size |
||
281 | * \param ... further num/size pairs |
||
282 | * \return -1 if no overlap, otherwise index of first conflicting register |
||
283 | * ------------------------------------------------------------------------ */ |
||
284 | |||
285 | static int ChkRegOverlap(Word FirstReg, int FirstSize, ...) |
||
286 | { |
||
287 | LongWord RegUse = 0, ThisUse; |
||
288 | int Index = 0; |
||
289 | va_list ap; |
||
290 | |||
291 | va_start(ap, FirstSize); |
||
292 | while (True) |
||
293 | { |
||
294 | switch (FirstSize) |
||
295 | { |
||
296 | case eSymbolSize8Bit: |
||
297 | ThisUse = ((FirstReg & 8) ? 2ul : 1ul) << ((FirstReg & 7) * 2); |
||
298 | break; |
||
299 | case eSymbolSize16Bit: |
||
300 | ThisUse = 3ul << (FirstReg * 2); |
||
301 | break; |
||
302 | case eSymbolSize32Bit: |
||
303 | ThisUse = 15ul << (FirstReg * 2); |
||
304 | break; |
||
305 | default: |
||
306 | va_end(ap); |
||
307 | return Index; |
||
308 | } |
||
309 | if (RegUse & ThisUse) |
||
310 | { |
||
311 | va_end(ap); |
||
312 | return Index; |
||
313 | } |
||
314 | RegUse |= ThisUse; |
||
315 | Index++; |
||
316 | FirstReg = va_arg(ap, unsigned); |
||
317 | FirstSize = va_arg(ap, int); |
||
318 | if (FirstSize == eSymbolSizeUnknown) |
||
319 | break; |
||
320 | } |
||
321 | va_end(ap); |
||
322 | return -1; |
||
323 | } |
||
324 | |||
325 | /*--------------------------------------------------------------------------*/ |
||
326 | /* Address Parsing */ |
||
327 | |||
328 | /*!------------------------------------------------------------------------ |
||
329 | * \fn DecodeReg(const tStrComp *pArg, Word *pValue, tSymbolSize *pSize, tChkRegSize ChkRegSize, Boolean MustBeReg) |
||
330 | * \brief check whether argument is a CPU register or user-defined register alias |
||
331 | * \param pArg argument |
||
332 | * \param pValue resulting register # if yes |
||
333 | * \param pSize resulting register size if yes |
||
334 | * \param ChkReqSize optional check callback for register size |
||
335 | * \param MustBeReg expecting register or maybe not? |
||
336 | * \return reg eval result |
||
337 | * ------------------------------------------------------------------------ */ |
||
338 | |||
339 | typedef Boolean (*tChkRegSize)(const tStrComp *pArg, tSymbolSize ActSize); |
||
340 | |||
341 | static Boolean ChkRegSize_Idx(const tStrComp *pArg, tSymbolSize ActSize) |
||
342 | { |
||
343 | if (ActSize != eSymbolSize16Bit) |
||
344 | { |
||
345 | WrStrErrorPos(ErrNum_IndexRegMustBe16Bit, pArg); |
||
346 | return False; |
||
347 | } |
||
348 | return True; |
||
349 | } |
||
350 | |||
351 | static Boolean ChkRegSize_8To32(const tStrComp *pArg, tSymbolSize ActSize) |
||
352 | { |
||
353 | if (ActSize > eSymbolSize32Bit) |
||
354 | { |
||
355 | WrStrErrorPos(ErrNum_InvOpSize, pArg); |
||
356 | return False; |
||
357 | } |
||
358 | return True; |
||
359 | } |
||
360 | |||
361 | static Boolean ChkRegSize_IOAddr(const tStrComp *pArg, tSymbolSize ActSize) |
||
362 | { |
||
363 | if (ActSize != eSymbolSize16Bit) |
||
364 | { |
||
365 | WrStrErrorPos(ErrNum_IOAddrRegMustBe16Bit, pArg); |
||
366 | return False; |
||
367 | } |
||
368 | return True; |
||
369 | } |
||
370 | |||
371 | static Boolean ChkRegSize_MemAddr(const tStrComp *pArg, tSymbolSize ActSize) |
||
372 | { |
||
373 | if (Segmented()) |
||
374 | { |
||
375 | if (ActSize != eSymbolSize32Bit) |
||
376 | { |
||
377 | WrStrErrorPos(ErrNum_SegAddrRegMustBe32Bit, pArg); |
||
378 | return False; |
||
379 | } |
||
380 | } |
||
381 | else |
||
382 | { |
||
383 | if (ActSize != eSymbolSize16Bit) |
||
384 | { |
||
385 | WrStrErrorPos(ErrNum_NonSegAddrRegMustBe16Bit, pArg); |
||
386 | return False; |
||
387 | } |
||
388 | } |
||
389 | return True; |
||
390 | } |
||
391 | |||
392 | static tRegEvalResult DecodeReg(const tStrComp *pArg, Word *pValue, tSymbolSize *pSize, tChkRegSize ChkRegSize, Boolean MustBeReg) |
||
393 | { |
||
394 | tEvalResult EvalResult; |
||
395 | tRegEvalResult RegEvalResult; |
||
396 | |||
397 | if (DecodeRegCore(pArg->str.p_str, pValue, &EvalResult.DataSize)) |
||
398 | RegEvalResult = eIsReg; |
||
399 | else |
||
400 | { |
||
401 | tRegDescr RegDescr; |
||
402 | |||
403 | RegEvalResult = EvalStrRegExpressionAsOperand(pArg, &RegDescr, &EvalResult, eSymbolSizeUnknown, MustBeReg); |
||
404 | if (eIsReg == RegEvalResult) |
||
405 | *pValue = RegDescr.Reg; |
||
406 | } |
||
407 | |||
408 | if ((RegEvalResult == eIsReg) |
||
409 | && ChkRegSize |
||
410 | && !ChkRegSize(pArg, EvalResult.DataSize)) |
||
411 | RegEvalResult = MustBeReg ? eIsNoReg : eRegAbort; |
||
412 | |||
413 | if (pSize) *pSize = EvalResult.DataSize; |
||
414 | return RegEvalResult; |
||
415 | } |
||
416 | |||
417 | /*!------------------------------------------------------------------------ |
||
418 | * \fn ClearAdrVals(tAdrVals *pAdrVals) |
||
419 | * \brief clear address expression result buffer |
||
420 | * \param pAdrVals buffer to clear |
||
421 | * ------------------------------------------------------------------------ */ |
||
422 | |||
423 | static void ClearAdrVals(tAdrVals *pAdrVals) |
||
424 | { |
||
425 | pAdrVals->Mode = eModNone; |
||
426 | pAdrVals->Cnt = 0; |
||
427 | pAdrVals->Val = 0; |
||
428 | } |
||
429 | |||
430 | /*!------------------------------------------------------------------------ |
||
431 | * \fn SetOpSize(tSymbolSize Size, const tStrComp *pArg) |
||
432 | * \brief set (new) operand size of instruction |
||
433 | * \param Size size to set |
||
434 | * \param pArg source argument size was deduced from |
||
435 | * \return True if no conflict |
||
436 | * ------------------------------------------------------------------------ */ |
||
437 | |||
438 | static Boolean SetOpSize(tSymbolSize Size, const tStrComp *pArg) |
||
439 | { |
||
440 | if (OpSize == eSymbolSizeUnknown) |
||
441 | OpSize = Size; |
||
442 | else if ((Size != eSymbolSizeUnknown) && (Size != OpSize)) |
||
443 | { |
||
444 | WrStrErrorPos(ErrNum_ConfOpSizes, pArg); |
||
445 | return False; |
||
446 | } |
||
447 | return True; |
||
448 | } |
||
449 | |||
450 | /*!------------------------------------------------------------------------ |
||
451 | * \fn GetImmIntType(tSymbolSize Size) |
||
452 | * \brief retrieve immediate int type fitting to operand size |
||
453 | * \param Size operand size |
||
454 | * \return int type |
||
455 | * ------------------------------------------------------------------------ */ |
||
456 | |||
457 | static IntType GetImmIntType(tSymbolSize Size) |
||
458 | { |
||
459 | switch ((int)Size) |
||
460 | { |
||
461 | case eSymbolSize3Bit: |
||
462 | return UInt3; |
||
463 | case eSymbolSize4Bit: |
||
464 | return UInt4; |
||
465 | case eSymbolSize8Bit: |
||
466 | return Int8; |
||
467 | case eSymbolSize16Bit: |
||
468 | return Int16; |
||
469 | case eSymbolSize32Bit: |
||
470 | return Int32; |
||
471 | default: |
||
472 | return IntTypeCnt; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | /*!------------------------------------------------------------------------ |
||
477 | * \fn DecodeAddrPartNum(const tStrComp *pArg, LongInt Disp, tEvalResult *pEvalResult, Boolean IsDirect, Boolean IsIO, Boolean *pForceShortt, Boolean *pIsDirect) |
||
478 | * \brief decode address part, for direct/immediate or indexed mode |
||
479 | * \param pArg source argument |
||
480 | * \param Disp displacement to add to value |
||
481 | * \param pAdrVals binary coding of addressing mode |
||
482 | * \param IsDirect force treatment as direct address mode |
||
483 | * \param IsIO I/O space instead of memory space |
||
484 | * \param pForceShort short coding required? |
||
485 | * \param pIsDirect classified as direct addressing? |
||
486 | * \return True if success |
||
487 | * ------------------------------------------------------------------------ */ |
||
488 | |||
489 | typedef struct |
||
490 | { |
||
491 | as_quoted_iterator_cb_data_t data; |
||
492 | int nest; |
||
493 | char *p_split_pos; |
||
494 | } split_cb_data_t; |
||
495 | |||
496 | static int split_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data) |
||
497 | { |
||
498 | split_cb_data_t *p_data = (split_cb_data_t*)p_cb_data; |
||
499 | |||
500 | switch (*p_pos) |
||
501 | { |
||
502 | case '(': |
||
503 | p_data->nest++; |
||
504 | break; |
||
505 | case ')': |
||
506 | p_data->nest--; |
||
507 | break; |
||
508 | case '>': |
||
509 | if (!p_data->nest && (p_pos[1] == '>')) |
||
510 | p_data->p_split_pos = (char*)p_pos; |
||
511 | break; |
||
512 | default: |
||
513 | if (p_data->p_split_pos) |
||
514 | { |
||
515 | if (as_isspace(*p_pos)); /* delay decision to to next non-blank */ |
||
516 | else if (as_isalnum(*p_pos) || (*p_pos == '(')) |
||
517 | return -1; /* found */ |
||
518 | else |
||
519 | p_data->p_split_pos = NULL; |
||
520 | } |
||
521 | break; |
||
522 | } |
||
523 | return 0; |
||
524 | } |
||
525 | |||
526 | static LongWord DecodeAddrPartNum(const tStrComp *pArg, LongInt Disp, tEvalResult *pEvalResult, Boolean IsDirect, Boolean IsIO, Boolean *pForceShort, Boolean *pIsDirect) |
||
527 | { |
||
528 | tStrComp CopyComp; |
||
529 | String Copy; |
||
530 | Boolean HasSeg = False; |
||
531 | LongWord Result, SegNum = 0; |
||
532 | IntType ThisIntType; |
||
533 | |||
534 | StrCompMkTemp(&CopyComp, Copy, sizeof(Copy)); |
||
535 | StrCompCopy(&CopyComp, pArg); |
||
536 | *pForceShort = False; |
||
537 | |||
538 | /* deal with |....| and <<seg>>offs only in segmented mode: */ |
||
539 | |||
540 | if (!IsIO && Segmented()) |
||
541 | { |
||
542 | int Len = strlen(CopyComp.str.p_str); |
||
543 | |||
544 | if ((Len >= 2) && (CopyComp.str.p_str[0] == '|') && (CopyComp.str.p_str[Len - 1] == '|')) |
||
545 | { |
||
546 | StrCompShorten(&CopyComp, 1); |
||
547 | StrCompCutLeft(&CopyComp, 1); |
||
548 | KillPrefBlanksStrComp(&CopyComp); |
||
549 | KillPostBlanksStrComp(&CopyComp); |
||
550 | *pForceShort = True; |
||
551 | IsDirect = True; |
||
552 | Len -= 2; |
||
553 | } |
||
554 | if (!strncmp(CopyComp.str.p_str, "<<", 2)) |
||
555 | { |
||
556 | split_cb_data_t split_data; |
||
557 | |||
558 | split_data.data.callback_before = False; |
||
559 | split_data.data.qualify_quote = QualifyQuote; |
||
560 | split_data.p_split_pos = NULL; |
||
561 | split_data.nest = 0; |
||
562 | |||
563 | as_iterate_str_quoted(CopyComp.str.p_str + 2, split_cb, &split_data.data); |
||
564 | |||
565 | if (split_data.p_split_pos) |
||
566 | { |
||
567 | tStrComp SegArg; |
||
568 | |||
569 | StrCompSplitRef(&SegArg, &CopyComp, &CopyComp, split_data.p_split_pos); |
||
570 | StrCompIncRefLeft(&CopyComp, 1); |
||
571 | SegNum = EvalStrIntExpressionOffsWithResult(&SegArg, 2, UInt7, pEvalResult); |
||
572 | if (!pEvalResult->OK) |
||
573 | return 0; |
||
574 | HasSeg = True; |
||
575 | IsDirect = True; |
||
576 | } |
||
577 | } |
||
578 | } |
||
579 | |||
580 | /* If we know it's direct, right away limit to the correct address range. Otherwise, it might |
||
581 | be immediate up to 32 bits: */ |
||
582 | |||
583 | if (IsDirect) |
||
584 | ThisIntType = (IsIO || HasSeg) ? UInt16 : MemIntType; |
||
585 | else |
||
586 | ThisIntType = Int32; |
||
587 | Result = EvalStrIntExpressionWithResult(&CopyComp, ThisIntType, pEvalResult) + Disp; |
||
588 | |||
589 | /* For AMD syntax, treat as direct if no untyped constant */ |
||
590 | |||
591 | if (AMDSyntax && !IsDirect && pEvalResult->AddrSpaceMask) |
||
592 | IsDirect = True; |
||
593 | |||
594 | /* for forwards, truncate to allowed range */ |
||
595 | |||
596 | if (IsDirect) |
||
597 | ThisIntType = (IsIO || HasSeg) ? UInt16 : MemIntType; |
||
598 | else |
||
599 | ThisIntType = GetImmIntType(OpSize); |
||
600 | if (mFirstPassUnknown(pEvalResult->Flags) && (ThisIntType < IntTypeCnt)) |
||
601 | Result &= IntTypeDefs[(int)ThisIntType].Mask; |
||
602 | |||
603 | if (IsDirect) |
||
604 | { |
||
605 | Result |= (SegNum << 16); |
||
606 | if (pEvalResult->OK |
||
607 | && !mFirstPassUnknownOrQuestionable(pEvalResult->Flags) |
||
608 | && *pForceShort |
||
609 | && (Result & 0x00ff00ul)) |
||
610 | { |
||
611 | WrStrErrorPos(ErrNum_NoShortAddr, pArg); |
||
612 | pEvalResult->OK = False; |
||
613 | } |
||
614 | } |
||
615 | if (pIsDirect) |
||
616 | *pIsDirect = IsDirect; |
||
617 | return Result; |
||
618 | } |
||
619 | |||
620 | /*!------------------------------------------------------------------------ |
||
621 | * \fn FillAbsAddr(tAdrVals *pAdrVals, LongWord Address, Boolean IsDirect, Boolean IsIO, Boolean ForceShort, Boolean *pIsDirect) |
||
622 | * \brief pack absolute addess into instruction extension word(s) |
||
623 | * \param pAdrVals destination buffer |
||
624 | * \param Address address to pack |
||
625 | * \param IsDirect force treatment as direct address mode |
||
626 | * \param IsIO I/O (16b) or memory (23/16b) address? |
||
627 | * \param ForceShort force short encoding |
||
628 | * \param pIsDirect classified as direct addressing? |
||
629 | * ------------------------------------------------------------------------ */ |
||
630 | |||
631 | static void FillAbsAddr(tAdrVals *pAdrVals, LongWord Address, Boolean IsIO, Boolean ForceShort) |
||
632 | { |
||
633 | Word Offset = Address & 0xffff; |
||
634 | |||
635 | if (Segmented() && !IsIO) |
||
636 | { |
||
637 | pAdrVals->Vals[pAdrVals->Cnt++] = (Address >> 8) & 0x7f00; |
||
638 | if ((Offset <= 0xff) && ForceShort) |
||
639 | pAdrVals->Vals[pAdrVals->Cnt - 1] |= Offset; |
||
640 | else |
||
641 | { |
||
642 | pAdrVals->Vals[pAdrVals->Cnt - 1] |= 0x8000; |
||
643 | pAdrVals->Vals[pAdrVals->Cnt++] = Offset; |
||
644 | } |
||
645 | } |
||
646 | else |
||
647 | pAdrVals->Vals[pAdrVals->Cnt++] = Offset; |
||
648 | } |
||
649 | |||
650 | /*!------------------------------------------------------------------------ |
||
651 | * \fn FillImmVal(tAdrVals *pAdrVals, LongWord Value, tSymbolSize OpSize) |
||
652 | * \brief fill address values from immediate value |
||
653 | * \param pAdrVals dest buffer |
||
654 | * \param Value value to fill in |
||
655 | * \param OpSize used operand size |
||
656 | * ------------------------------------------------------------------------ */ |
||
657 | |||
658 | static void FillImmVal(tAdrVals *pAdrVals, LongWord Value, tSymbolSize OpSize) |
||
659 | { |
||
660 | switch ((int)OpSize) |
||
661 | { |
||
662 | case eSymbolSize3Bit: |
||
663 | pAdrVals->Val = Value & 7; |
||
664 | break; |
||
665 | case eSymbolSize4Bit: |
||
666 | pAdrVals->Val = Value & 15; |
||
667 | break; |
||
668 | case eSymbolSize8Bit: |
||
669 | pAdrVals->Vals[pAdrVals->Cnt++] = (Value & 0xff) | ((Value & 0xff) << 8); |
||
670 | break; |
||
671 | case eSymbolSize16Bit: |
||
672 | pAdrVals->Vals[pAdrVals->Cnt++] = Value & 0xffff; |
||
673 | break; |
||
674 | case eSymbolSize32Bit: |
||
675 | pAdrVals->Vals[pAdrVals->Cnt++] = (Value >> 16) & 0xffff; |
||
676 | pAdrVals->Vals[pAdrVals->Cnt++] = Value & 0xffff; |
||
677 | break; |
||
678 | default: |
||
679 | break; |
||
680 | } |
||
681 | } |
||
682 | |||
683 | /*!------------------------------------------------------------------------ |
||
684 | * \fn DecodeAddrPart(const tStrComp *pArg, LongInt Disp, tAdrVals *pAdrVals, Boolean IsDirect, Boolean IsIO, Boolean *pIsDirect) |
||
685 | * \brief decode address part, for direct/immediate or indexed mode |
||
686 | * \param pArg source argument |
||
687 | * \param Disp displacement to add to value |
||
688 | * \param pAdrVals binary coding of addressing mode |
||
689 | * \param IsDirect force treatment as direct address mode |
||
690 | * \param IsIO I/O space instead of memory space |
||
691 | * \param pIsDirect classified as direct addressing? |
||
692 | * \return True if success |
||
693 | * ------------------------------------------------------------------------ */ |
||
694 | |||
695 | static Boolean DecodeAddrPart(const tStrComp *pArg, LongInt Disp, tAdrVals *pAdrVals, Boolean IsDirect, Boolean IsIO, Boolean *pIsDirect) |
||
696 | { |
||
697 | LongWord Address; |
||
698 | tEvalResult EvalResult; |
||
699 | Boolean ForceLong; |
||
700 | |||
701 | Address = DecodeAddrPartNum(pArg, Disp, &EvalResult, IsDirect, IsIO, &ForceLong, pIsDirect); |
||
702 | if (EvalResult.OK) |
||
703 | { |
||
704 | ChkSpace(IsIO ? SegIO : SegCode, EvalResult.AddrSpaceMask); |
||
705 | if (!pIsDirect || *pIsDirect) |
||
706 | FillAbsAddr(pAdrVals, Address, IsIO, ForceLong); |
||
707 | else |
||
708 | FillImmVal(pAdrVals, Address, OpSize); |
||
709 | return True; |
||
710 | } |
||
711 | else |
||
712 | return False; |
||
713 | } |
||
714 | |||
715 | /*!------------------------------------------------------------------------ |
||
716 | * \fn DecodeAdr(const tStrComp *pArg, unsigned ModeMask, tAdrVals *pAdrVals) |
||
717 | * \brief decode address expression |
||
718 | * \param pArg source argument |
||
719 | * \param ModeMask bit mask of allowed addressing modes |
||
720 | * \param pAdrVals binary coding of addressing mode |
||
721 | * \return decoded mode |
||
722 | * ------------------------------------------------------------------------ */ |
||
723 | |||
724 | /* This is necessary to find the split position when a short address is used as |
||
725 | base, i.e. |addr|(rn). | is also the OR operator, and I don't want to get |
||
726 | false positives on other targets on stuff like (...)|(...): */ |
||
727 | |||
728 | static int ShortQualifier(const char *pArg, int NextNonBlankPos, int SplitPos) |
||
729 | { |
||
730 | int FirstNonBlankPos; |
||
731 | |||
732 | for (FirstNonBlankPos = 0; FirstNonBlankPos < NextNonBlankPos; FirstNonBlankPos++) |
||
733 | if (!as_isspace(pArg[FirstNonBlankPos])) |
||
734 | break; |
||
735 | return ((FirstNonBlankPos < NextNonBlankPos) && (pArg[FirstNonBlankPos] == '|') && (pArg[NextNonBlankPos] == '|')) ? SplitPos : -1; |
||
736 | } |
||
737 | |||
738 | static tAdrMode DecodeAdr(const tStrComp *pArg, unsigned ModeMask, tAdrVals *pAdrVals) |
||
739 | { |
||
740 | tSymbolSize ArgSize; |
||
741 | int ArgLen, SplitPos, z; |
||
742 | Boolean IsIO = !!(ModeMask & MModIO); |
||
743 | tChkRegSize ChkRegSize_Addr = IsIO ? ChkRegSize_IOAddr : ChkRegSize_MemAddr, ChkRegSizeForIOIndir; |
||
744 | Boolean IsDirect; |
||
745 | |||
746 | ClearAdrVals(pAdrVals); |
||
747 | |||
748 | /* immediate */ |
||
749 | |||
750 | if (*pArg->str.p_str == '#') |
||
751 | { |
||
752 | LongWord Result; |
||
753 | Boolean OK; |
||
754 | |||
755 | if (ImmOpSize == eSymbolSizeUnknown) |
||
756 | ImmOpSize = OpSize; |
||
757 | switch (ImmOpSize) |
||
758 | { |
||
759 | case eSymbolSize3Bit: |
||
760 | pAdrVals->Val = EvalStrIntExpressionOffs(pArg, 1, UInt3, &OK); |
||
761 | break; |
||
762 | case eSymbolSize4Bit: |
||
763 | pAdrVals->Val = EvalStrIntExpressionOffs(pArg, 1, UInt4, &OK); |
||
764 | break; |
||
765 | case eSymbolSize8Bit: |
||
766 | Result = EvalStrIntExpressionOffs(pArg, 1, Int8, &OK); |
||
767 | if (OK) |
||
768 | pAdrVals->Vals[pAdrVals->Cnt++] = (Result & 0xff) | ((Result & 0xff) << 8); |
||
769 | break; |
||
770 | case eSymbolSize16Bit: |
||
771 | Result = EvalStrIntExpressionOffs(pArg, 1, Int16, &OK); |
||
772 | if (OK) |
||
773 | pAdrVals->Vals[pAdrVals->Cnt++] = Result & 0xffff; |
||
774 | break; |
||
775 | case eSymbolSize32Bit: |
||
776 | Result = EvalStrIntExpressionOffs(pArg, 1, Int32, &OK); |
||
777 | if (OK) |
||
778 | { |
||
779 | pAdrVals->Vals[pAdrVals->Cnt++] = (Result >> 16) & 0xffff; |
||
780 | pAdrVals->Vals[pAdrVals->Cnt++] = Result & 0xffff; |
||
781 | } |
||
782 | break; |
||
783 | default: |
||
784 | WrStrErrorPos(ErrNum_UndefOpSizes, pArg); |
||
785 | return pAdrVals->Mode; |
||
786 | } |
||
787 | if (OK) |
||
788 | { |
||
789 | /* Immediate: is the same coding as indirect, however with register field = 0. |
||
790 | This why register 0 is not allowed for indirect mode. |
||
791 | As an exception, immediate value is placed in pAdrVals->Val for bit number: */ |
||
792 | |||
793 | pAdrVals->Mode = eModImm; |
||
794 | if (OpSize == eSymbolSizeUnknown) |
||
795 | OpSize = (tSymbolSize)ImmOpSize; |
||
796 | } |
||
797 | goto chk; |
||
798 | } |
||
799 | |||
800 | /* Register (R): For AMD syntax, Rn is equivalent to Rn^ resp. @Rn, if I/O ports |
||
801 | are addressed indirectly: */ |
||
802 | |||
803 | ChkRegSizeForIOIndir = (AMDSyntax && !(ModeMask & MModReg) && (ModeMask & MModIReg) && IsIO) ? ChkRegSize_Addr : NULL; |
||
804 | switch (DecodeReg(pArg, &pAdrVals->Val, &ArgSize, ChkRegSizeForIOIndir, False)) |
||
805 | { |
||
806 | case eRegAbort: |
||
807 | return pAdrVals->Mode; |
||
808 | case eIsReg: |
||
809 | { |
||
810 | if (ChkRegSizeForIOIndir) |
||
811 | pAdrVals->Mode = eModIReg; |
||
812 | else |
||
813 | { |
||
814 | if (!SetOpSize(ArgSize, pArg)) |
||
815 | return pAdrVals->Mode; |
||
816 | pAdrVals->Mode = eModReg; |
||
817 | } |
||
818 | goto chk; |
||
819 | } |
||
820 | default: |
||
821 | break; |
||
822 | } |
||
823 | |||
824 | /* control register */ |
||
825 | |||
826 | for (z = 0; z < CtlRegCnt; z++) |
||
827 | if (!as_strcasecmp(pArg->str.p_str, CtlRegs[z].pName)) |
||
828 | { |
||
829 | if (!(CtlRegs[z].Flags & (Segmented() ? eSegMode : eNonSegMode))) |
||
830 | { |
||
831 | WrStrErrorPos(ErrNum_InvCtrlReg, pArg); |
||
832 | return pAdrVals->Mode; |
||
833 | } |
||
834 | if (!SetOpSize(CtlRegs[z].Size, pArg)) |
||
835 | return pAdrVals->Mode; |
||
836 | if (!CheckSup(!!(CtlRegs[z].Flags & ePrivileged))) |
||
837 | return pAdrVals->Mode; |
||
838 | pAdrVals->Val = CtlRegs[z].Code; |
||
839 | pAdrVals->Mode = eModCtl; |
||
840 | goto chk; |
||
841 | } |
||
842 | |||
843 | /* Register indirect (IR): */ |
||
844 | |||
845 | if (*pArg->str.p_str == '@') |
||
846 | { |
||
847 | tStrComp RegComp; |
||
848 | |||
849 | StrCompRefRight(&RegComp, pArg, 1); |
||
850 | if (eIsReg == DecodeReg(&RegComp, &pAdrVals->Val, &ArgSize, ChkRegSize_Addr, True)) |
||
851 | { |
||
852 | if (!pAdrVals->Val) WrStrErrorPos(ErrNum_InvAddrMode, &RegComp); |
||
853 | else |
||
854 | pAdrVals->Mode = eModIReg; |
||
855 | } |
||
856 | goto chk; |
||
857 | } |
||
858 | if (AMDSyntax |
||
859 | && ((ArgLen = strlen(pArg->str.p_str)) > 1) |
||
860 | && (pArg->str.p_str[ArgLen - 1] == '^')) |
||
861 | { |
||
862 | String Reg; |
||
863 | tStrComp RegComp; |
||
864 | |||
865 | StrCompMkTemp(&RegComp, Reg, sizeof(Reg)); |
||
866 | StrCompCopySub(&RegComp, pArg, 0, ArgLen - 1); |
||
867 | switch (DecodeReg(&RegComp, &pAdrVals->Val, &ArgSize, ChkRegSize_Addr, False)) |
||
868 | { |
||
869 | case eRegAbort: |
||
870 | return pAdrVals->Mode; |
||
871 | case eIsReg: |
||
872 | if (!pAdrVals->Val) WrStrErrorPos(ErrNum_InvAddrMode, &RegComp); |
||
873 | else |
||
874 | pAdrVals->Mode = eModIReg; |
||
875 | goto chk; |
||
876 | default: |
||
877 | break; |
||
878 | } |
||
879 | } |
||
880 | |||
881 | /* Indexed, base... */ |
||
882 | |||
883 | SplitPos = FindDispBaseSplitWithQualifier(pArg->str.p_str, &ArgLen, ShortQualifier, "()"); |
||
884 | if (SplitPos > 0) |
||
885 | { |
||
886 | String OutStr, InStr; |
||
887 | tStrComp OutArg, InArg; |
||
888 | |||
889 | /* copy out base + index components */ |
||
890 | |||
891 | StrCompMkTemp(&OutArg, OutStr, sizeof(OutStr)); |
||
892 | StrCompMkTemp(&InArg, InStr, sizeof(InStr)); |
||
893 | StrCompCopySub(&OutArg, pArg, 0, SplitPos); |
||
894 | KillPostBlanksStrComp(&OutArg); |
||
895 | StrCompCopySub(&InArg, pArg, SplitPos + 1, ArgLen - SplitPos - 2); |
||
896 | switch (DecodeReg(&OutArg, &pAdrVals->Val, &ArgSize, ChkRegSize_Addr, False)) |
||
897 | { |
||
898 | case eIsReg: /* [R]Rx(...) */ |
||
899 | if (!pAdrVals->Val) WrStrErrorPos(ErrNum_InvAddrMode, &OutArg); |
||
900 | else if (*InArg.str.p_str == '#') |
||
901 | { |
||
902 | Boolean OK; |
||
903 | |||
904 | pAdrVals->Vals[pAdrVals->Cnt++] = EvalStrIntExpressionOffs(&InArg, 1, Int16, &OK); |
||
905 | if (OK) |
||
906 | pAdrVals->Mode = eModBaseAddress; |
||
907 | } |
||
908 | else if (DecodeReg(&InArg, &pAdrVals->Vals[pAdrVals->Cnt], &ArgSize, ChkRegSize_Idx, True) == eIsReg) |
||
909 | { |
||
910 | pAdrVals->Vals[pAdrVals->Cnt] <<= 8; |
||
911 | pAdrVals->Cnt++; |
||
912 | pAdrVals->Mode = eModBaseIndexed; |
||
913 | } |
||
914 | goto chk; |
||
915 | case eIsNoReg: /* abs(...) */ |
||
916 | { |
||
917 | switch (DecodeReg(&InArg, &pAdrVals->Val, &ArgSize, ChkRegSize_Idx, False)) |
||
918 | { |
||
919 | case eIsReg: /* abs(Rx) */ |
||
920 | if (DecodeAddrPart(&OutArg, 0, pAdrVals, True, IsIO, NULL)) |
||
921 | pAdrVals->Mode = eModIndexed; |
||
922 | break; |
||
923 | case eIsNoReg: /* abs/imm(delta) -> direct/imm*/ |
||
924 | { |
||
925 | Boolean OK; |
||
926 | LongInt Disp = EvalStrIntExpression(&InArg, Int16, &OK); |
||
927 | |||
928 | if (OK && DecodeAddrPart(&OutArg, Disp, pAdrVals, !AMDSyntax || !(ModeMask & MModImm), IsIO, &IsDirect)) |
||
929 | goto DirectOrImmediate; |
||
930 | break; |
||
931 | } |
||
932 | default: |
||
933 | return pAdrVals->Mode; |
||
934 | } |
||
935 | goto chk; |
||
936 | } |
||
937 | case eRegAbort: |
||
938 | return pAdrVals->Mode; |
||
939 | } |
||
940 | } |
||
941 | |||
942 | /* Absolute: is the same coding as indexed, however with index register field = 0. |
||
943 | This is why register 0 is not allowed for indexed mode. */ |
||
944 | |||
945 | if (DecodeAddrPart(pArg, 0, pAdrVals, !AMDSyntax || !(ModeMask & MModImm), IsIO, &IsDirect)) |
||
946 | { |
||
947 | DirectOrImmediate: |
||
948 | if (IsDirect) |
||
949 | { |
||
950 | pAdrVals->Val = 0; |
||
951 | pAdrVals->Mode = eModDirect; |
||
952 | } |
||
953 | else |
||
954 | pAdrVals->Mode = eModImm; |
||
955 | } |
||
956 | |||
957 | chk: |
||
958 | if ((pAdrVals->Mode != eModNone) & !((ModeMask >> pAdrVals->Mode) & 1)) |
||
959 | { |
||
960 | WrStrErrorPos(ErrNum_InvAddrMode, pArg); |
||
961 | ClearAdrVals(pAdrVals); |
||
962 | } |
||
963 | return pAdrVals->Mode; |
||
964 | } |
||
965 | |||
966 | /*--------------------------------------------------------------------------*/ |
||
967 | /* Bit Symbol Handling */ |
||
968 | |||
969 | /* |
||
970 | * Compact representation of bits in symbol table: |
||
971 | * bits 0...2/3: bit position |
||
972 | * bits 3/4...25/26: address in memory space (7+16 bits) |
||
973 | * bit 28: operand size (0/1 for 8/16 bits) |
||
974 | * bit 29: force short address in segmented mode |
||
975 | */ |
||
976 | |||
977 | /*!------------------------------------------------------------------------ |
||
978 | * \fn AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address, Boolean ForceShort) |
||
979 | * \brief build the compact internal representation of a bit symbol |
||
980 | * \param BitPos bit position in word |
||
981 | * \param OpSize operand size (8/16) |
||
982 | * \param Address memory address |
||
983 | * \param ForceShort force short address in segmented mode |
||
984 | * \return compact representation |
||
985 | * ------------------------------------------------------------------------ */ |
||
986 | |||
987 | static LongWord AssembleBitSymbol(Byte BitPos, tSymbolSize OpSize, LongWord Address, Boolean ForceShort) |
||
988 | { |
||
989 | LongWord CodeOpSize = (OpSize == eSymbolSize16Bit) ? 1 : 0; |
||
990 | int AddrShift = CodeOpSize + 3; |
||
991 | |||
992 | return BitPos |
||
993 | | ((Address & 0x7fffff) << AddrShift) |
||
994 | | (CodeOpSize << 28) |
||
995 | | ((!!ForceShort) << 29); |
||
996 | } |
||
997 | |||
998 | /*!------------------------------------------------------------------------ |
||
999 | * \fn EvalBitPosition(const char *pBitArg, Boolean *pOK, ShortInt OpSize) |
||
1000 | * \brief evaluate constant bit position, with bit range depending on operand size |
||
1001 | * \param pBitArg bit position argument |
||
1002 | * \param pOK returns True if OK |
||
1003 | * \param OpSize operand size (0,1,2 -> 8,16,32 bits) |
||
1004 | * \return bit position as number |
||
1005 | * ------------------------------------------------------------------------ */ |
||
1006 | |||
1007 | static Byte EvalBitPosition(const tStrComp *pBitArg, Boolean *pOK, tSymbolSize OpSize) |
||
1008 | { |
||
1009 | IntType Type; |
||
1010 | |||
1011 | switch (OpSize) |
||
1012 | { |
||
1013 | case eSymbolSize8Bit: |
||
1014 | Type = UInt3; |
||
1015 | goto common; |
||
1016 | case eSymbolSize16Bit: |
||
1017 | Type = UInt4; |
||
1018 | goto common; |
||
1019 | default: |
||
1020 | WrStrErrorPos(ErrNum_InvOpSize, pBitArg); |
||
1021 | *pOK = False; |
||
1022 | return 0; |
||
1023 | common: |
||
1024 | return EvalStrIntExpressionOffs(pBitArg, !!(*pBitArg->str.p_str == '#'), Type, pOK); |
||
1025 | } |
||
1026 | } |
||
1027 | |||
1028 | /*!------------------------------------------------------------------------ |
||
1029 | * \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pMemArg, const tStrComp *pBitArg, tSymbolSize OpSize) |
||
1030 | * \brief encode a bit symbol, address & bit position separated |
||
1031 | * \param pResult resulting encoded bit |
||
1032 | * \param pMemArg register argument |
||
1033 | * \param pBitArg bit argument |
||
1034 | * \param OpSize register size (0/1 = 8/16 bit) |
||
1035 | * \return True if success |
||
1036 | * ------------------------------------------------------------------------ */ |
||
1037 | |||
1038 | static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pMemArg, const tStrComp *pBitArg, tSymbolSize OpSize) |
||
1039 | { |
||
1040 | tEvalResult EvalResult; |
||
1041 | LongWord Addr; |
||
1042 | Byte BitPos; |
||
1043 | Boolean ForceShort; |
||
1044 | |||
1045 | BitPos = EvalBitPosition(pBitArg, &EvalResult.OK, OpSize); |
||
1046 | if (!EvalResult.OK) |
||
1047 | return False; |
||
1048 | |||
1049 | Addr = DecodeAddrPartNum(pMemArg, 0, &EvalResult, True, False, &ForceShort, NULL); |
||
1050 | if (!EvalResult.OK) |
||
1051 | return False; |
||
1052 | |||
1053 | *pResult = AssembleBitSymbol(BitPos, OpSize, Addr, ForceShort); |
||
1054 | |||
1055 | return True; |
||
1056 | } |
||
1057 | |||
1058 | /*!------------------------------------------------------------------------ |
||
1059 | * \fn DecodeBitArg(LongWord *pResult, int Start, int Stop, tSymbolSize OpSize) |
||
1060 | * \brief encode a bit symbol from instruction argument(s) |
||
1061 | * \param pResult resulting encoded bit |
||
1062 | * \param Start first argument |
||
1063 | * \param Stop last argument |
||
1064 | * \param OpSize register size (0/1 = 8/16 bit) |
||
1065 | * \return True if success |
||
1066 | * ------------------------------------------------------------------------ */ |
||
1067 | |||
1068 | static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop, tSymbolSize OpSize) |
||
1069 | { |
||
1070 | *pResult = 0; |
||
1071 | |||
1072 | /* Just one argument -> parse as bit argument */ |
||
1073 | |||
1074 | if (Start == Stop) |
||
1075 | { |
||
1076 | tEvalResult EvalResult; |
||
1077 | |||
1078 | *pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], UInt32, &EvalResult); |
||
1079 | if (EvalResult.OK) |
||
1080 | ChkSpace(SegBData, EvalResult.AddrSpaceMask); |
||
1081 | return EvalResult.OK; |
||
1082 | } |
||
1083 | |||
1084 | /* register & bit position are given as separate arguments */ |
||
1085 | |||
1086 | else if (Stop == Start + 1) |
||
1087 | return DecodeBitArg2(pResult, &ArgStr[Start], &ArgStr[Stop], OpSize); |
||
1088 | |||
1089 | /* other # of arguments not allowed */ |
||
1090 | |||
1091 | else |
||
1092 | { |
||
1093 | WrError(ErrNum_WrongArgCnt); |
||
1094 | return False; |
||
1095 | } |
||
1096 | } |
||
1097 | |||
1098 | /*!------------------------------------------------------------------------ |
||
1099 | * \fn DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize, Boolean *pForceShort) |
||
1100 | * \brief transform compact represenation of bit symbol into components |
||
1101 | * \param BitSymbol compact storage |
||
1102 | * \param pAddress (I/O) register address |
||
1103 | * \param pBitPos (start) bit position |
||
1104 | * \param pOpSize returns register size (0/1 for 8/16 bits) |
||
1105 | * \param pForceShort returns force of short address in segmented mode |
||
1106 | * \return constant True |
||
1107 | * ------------------------------------------------------------------------ */ |
||
1108 | |||
1109 | static Boolean DissectBitSymbol(LongWord BitSymbol, LongWord *pAddress, Byte *pBitPos, tSymbolSize *pOpSize, Boolean *pForceShort) |
||
1110 | { |
||
1111 | *pForceShort = ((BitSymbol >> 29) & 1); |
||
1112 | *pOpSize = (tSymbolSize)((BitSymbol >> 28) & 1); |
||
1113 | switch (*pOpSize) |
||
1114 | { |
||
1115 | case eSymbolSize8Bit: |
||
1116 | *pAddress = (BitSymbol >> 3) & 0x7ffffful; |
||
1117 | *pBitPos = BitSymbol & 7; |
||
1118 | break; |
||
1119 | case eSymbolSize16Bit: |
||
1120 | *pAddress = (BitSymbol >> 4) & 0x7ffffful; |
||
1121 | *pBitPos = BitSymbol & 15; |
||
1122 | break; |
||
1123 | default: |
||
1124 | break; |
||
1125 | } |
||
1126 | return True; |
||
1127 | } |
||
1128 | |||
1129 | /*!------------------------------------------------------------------------ |
||
1130 | * \fn DissectBit_Z8000(char *pDest, size_t DestSize, LargeWord Inp) |
||
1131 | * \brief dissect compact storage of bit into readable form for listing |
||
1132 | * \param pDest destination for ASCII representation |
||
1133 | * \param DestSize destination buffer size |
||
1134 | * \param Inp compact storage |
||
1135 | * ------------------------------------------------------------------------ */ |
||
1136 | |||
1137 | static void DissectBit_Z8000(char *pDest, size_t DestSize, LargeWord Inp) |
||
1138 | { |
||
1139 | Byte BitPos; |
||
1140 | LongWord Address; |
||
1141 | tSymbolSize OpSize; |
||
1142 | Boolean ForceShort; |
||
1143 | char Attribute; |
||
1144 | |||
1145 | DissectBitSymbol(Inp, &Address, &BitPos, &OpSize, &ForceShort); |
||
1146 | Attribute = "bw"[OpSize]; |
||
1147 | if (HexStartCharacter == 'A') |
||
1148 | Attribute = as_toupper(Attribute); |
||
1149 | as_snprintf(pDest, DestSize, "%s%~.*u%s%s(%c).%u", |
||
1150 | ForceShort ? "|" : "", |
||
1151 | ListRadixBase, (unsigned)Address, GetIntConstIntelSuffix(ListRadixBase), |
||
1152 | ForceShort ? "|" : "", |
||
1153 | Attribute, (unsigned)BitPos); |
||
1154 | } |
||
1155 | |||
1156 | /*!------------------------------------------------------------------------ |
||
1157 | * \fn ExpandZ8000Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base) |
||
1158 | * \brief expands bit definition when a structure is instantiated |
||
1159 | * \param pVarName desired symbol name |
||
1160 | * \param pStructElem element definition |
||
1161 | * \param Base base address of instantiated structure |
||
1162 | * ------------------------------------------------------------------------ */ |
||
1163 | |||
1164 | static void ExpandZ8000Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base) |
||
1165 | { |
||
1166 | LongWord Address = Base + pStructElem->Offset; |
||
1167 | |||
1168 | if (pInnermostNamedStruct) |
||
1169 | { |
||
1170 | PStructElem pElem = CloneStructElem(pVarName, pStructElem); |
||
1171 | |||
1172 | if (!pElem) |
||
1173 | return; |
||
1174 | pElem->Offset = Address; |
||
1175 | AddStructElem(pInnermostNamedStruct->StructRec, pElem); |
||
1176 | } |
||
1177 | else |
||
1178 | { |
||
1179 | tSymbolSize OpSize = (pStructElem->OpSize == eSymbolSizeUnknown) ? eSymbolSize8Bit : pStructElem->OpSize; |
||
1180 | |||
1181 | if (!ChkRange(Address, 0, 0x7fffff) |
||
1182 | || !ChkRange(pStructElem->BitPos, 0, (8 << OpSize) - 1)) |
||
1183 | return; |
||
1184 | |||
1185 | PushLocHandle(-1); |
||
1186 | EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, OpSize, Address, False), SegBData, False); |
||
1187 | PopLocHandle(); |
||
1188 | /* TODO: MakeUseList? */ |
||
1189 | } |
||
1190 | } |
||
1191 | |||
1192 | /*!------------------------------------------------------------------------ |
||
1193 | * \fn SetOpSizeFromCode(Word Code) |
||
1194 | * \brief set operand size of instruction from insn name |
||
1195 | * \param Code contains size in MSB |
||
1196 | * ------------------------------------------------------------------------ */ |
||
1197 | |||
1198 | static Boolean SetOpSizeFromCode(Word Code) |
||
1199 | { |
||
1200 | Byte Size = Hi(Code); |
||
1201 | |||
1202 | return SetOpSize((Size == 0xff) ? eSymbolSizeUnknown : (tSymbolSize)Size, &OpPart); |
||
1203 | } |
||
1204 | |||
1205 | /*!------------------------------------------------------------------------ |
||
1206 | * \fn AppendCode(Word Code) |
||
1207 | * \brief append instruction word |
||
1208 | * \param pVals code word to append |
||
1209 | * ------------------------------------------------------------------------ */ |
||
1210 | |||
1211 | static void AppendCode(Word Code) |
||
1212 | { |
||
1213 | WAsmCode[CodeLen >> 1] = Code; |
||
1214 | CodeLen += 2; |
||
1215 | } |
||
1216 | |||
1217 | /*!------------------------------------------------------------------------ |
||
1218 | * \fn AppendAdrVals(const tAdrVals *pVals) |
||
1219 | * \brief append address argument(s) |
||
1220 | * \param pVals values to append |
||
1221 | * ------------------------------------------------------------------------ */ |
||
1222 | |||
1223 | static void AppendAdrVals(const tAdrVals *pVals) |
||
1224 | { |
||
1225 | memcpy(&WAsmCode[CodeLen >> 1], pVals->Vals, pVals->Cnt << 1); |
||
1226 | CodeLen += pVals->Cnt << 1; |
||
1227 | } |
||
1228 | |||
1229 | /*!------------------------------------------------------------------------ |
||
1230 | * \fn DecodeCondition(const tStrComp *pArg, Word *pCondition) |
||
1231 | * \brief decode condition argument |
||
1232 | * \param pArg source argument (NULL for non-present condition) |
||
1233 | * \param pCondition result buffer |
||
1234 | * \return True if found |
||
1235 | * ------------------------------------------------------------------------ */ |
||
1236 | |||
1237 | static Boolean DecodeCondition(const tStrComp *pArg, Word *pCondition) |
||
1238 | { |
||
1239 | int z; |
||
1240 | |||
1241 | for (z = 0; Conditions[z].pName; z++) |
||
1242 | if (!as_strcasecmp(pArg ? pArg->str.p_str : "", Conditions[z].pName)) |
||
1243 | { |
||
1244 | *pCondition = Conditions[z].Code; |
||
1245 | return True; |
||
1246 | } |
||
1247 | WrStrErrorPos(ErrNum_UndefCond, pArg); |
||
1248 | return False; |
||
1249 | } |
||
1250 | |||
1251 | /*!------------------------------------------------------------------------ |
||
1252 | * \fn DecodeImm1_16(const tStrComp *pArg, tEvalResult *pEvalResult) |
||
1253 | * \brief decode immediate argument from 1..16 and return as 0..15 |
||
1254 | * \param pArg source argument |
||
1255 | * \param pEvalResult evaluation result |
||
1256 | * \return value |
||
1257 | * ------------------------------------------------------------------------ */ |
||
1258 | |||
1259 | static Word DecodeImm1_16(const tStrComp *pArg, tEvalResult *pEvalResult) |
||
1260 | { |
||
1261 | Word Result; |
||
1262 | |||
1263 | Result = EvalStrIntExpressionOffsWithResult(pArg, !!(*pArg->str.p_str == '#'), UInt5, pEvalResult); |
||
1264 | if (pEvalResult->OK) |
||
1265 | { |
||
1266 | if (mFirstPassUnknownOrQuestionable(pEvalResult->Flags)) |
||
1267 | Result = 1; |
||
1268 | else |
||
1269 | pEvalResult->OK = ChkRange(Result, 1, 16); |
||
1270 | Result--; |
||
1271 | } |
||
1272 | return Result; |
||
1273 | } |
||
1274 | |||
1275 | /*--------------------------------------------------------------------------*/ |
||
1276 | /* Instruction Decoders */ |
||
1277 | |||
1278 | /*!------------------------------------------------------------------------ |
||
1279 | * \fn DecodeFixed(Word Index) |
||
1280 | * \brief decode instruction without arguments |
||
1281 | * \param Index machine code of instruction |
||
1282 | * ------------------------------------------------------------------------ */ |
||
1283 | |||
1284 | static void DecodeFixed(Word Index) |
||
1285 | { |
||
1286 | const FixedOrder *pOrder = FixedOrders + Index; |
||
1287 | |||
1288 | if (ChkArgCnt(0, 0) |
||
1289 | && CheckSup(pOrder->Privileged)) |
||
1290 | { |
||
1291 | CodeLen = 2; |
||
1292 | WAsmCode[0] = pOrder->Code; |
||
1293 | } |
||
1294 | } |
||
1295 | |||
1296 | /*!------------------------------------------------------------------------ |
||
1297 | * \fn DecodeLD(Word Code) |
||
1298 | * \brief decode LD/LDB/LDL instruction |
||
1299 | * \param Code instruction type |
||
1300 | * ------------------------------------------------------------------------ */ |
||
1301 | |||
1302 | static void DecodeLD(Word Code) |
||
1303 | { |
||
1304 | tAdrVals DestAdrVals; |
||
1305 | |||
1306 | if (!SetOpSizeFromCode(Code) |
||
1307 | || !ChkArgCnt(2, 2)) |
||
1308 | return; |
||
1309 | |||
1310 | switch (DecodeAdr(&ArgStr[1], MModNoImm, &DestAdrVals)) |
||
1311 | { |
||
1312 | case eModReg: |
||
1313 | { |
||
1314 | tAdrVals SrcAdrVals; |
||
1315 | |||
1316 | switch (DecodeAdr(&ArgStr[2], MModAll, &SrcAdrVals)) |
||
1317 | { |
||
1318 | case eModReg: |
||
1319 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x9400 : (0xa000 | (OpSize << 8))) |
||
1320 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1321 | break; |
||
1322 | case eModIReg: |
||
1323 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1400 : (0x2000 | (OpSize << 8))) |
||
1324 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1325 | break; |
||
1326 | case eModDirect: |
||
1327 | case eModIndexed: |
||
1328 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x5400 : (0x6000 | (OpSize << 8))) |
||
1329 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1330 | AppendAdrVals(&SrcAdrVals); |
||
1331 | break; |
||
1332 | case eModBaseAddress: |
||
1333 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x3500 : (0x3000 | (OpSize << 8))) |
||
1334 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1335 | AppendAdrVals(&SrcAdrVals); |
||
1336 | break; |
||
1337 | case eModBaseIndexed: |
||
1338 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x7500 : (0x7000 | (OpSize << 8))) |
||
1339 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1340 | AppendAdrVals(&SrcAdrVals); |
||
1341 | break; |
||
1342 | case eModImm: |
||
1343 | if (OpSize == eSymbolSize8Bit) |
||
1344 | AppendCode(0xc000 | (DestAdrVals.Val << 8) | (SrcAdrVals.Vals[0] & 0xff)); |
||
1345 | #if OPT_LD_LDK |
||
1346 | else if ((OpSize == eSymbolSize16Bit) && (SrcAdrVals.Vals[0] < 16)) |
||
1347 | AppendCode(0xbd00 | (DestAdrVals.Val << 4) | (SrcAdrVals.Vals[0] & 0x0f)); |
||
1348 | #endif |
||
1349 | else |
||
1350 | { |
||
1351 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1400 : (0x2000 | (OpSize << 8))) |
||
1352 | | DestAdrVals.Val); |
||
1353 | AppendAdrVals(&SrcAdrVals); |
||
1354 | } |
||
1355 | break; |
||
1356 | default: |
||
1357 | break; |
||
1358 | } |
||
1359 | break; |
||
1360 | } |
||
1361 | case eModIReg: |
||
1362 | { |
||
1363 | tAdrVals SrcAdrVals; |
||
1364 | |||
1365 | ImmOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
1366 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm, &SrcAdrVals)) |
||
1367 | { |
||
1368 | case eModReg: |
||
1369 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1d00 : (0x2e00 | (OpSize << 8))) |
||
1370 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1371 | break; |
||
1372 | case eModImm: |
||
1373 | if (OpSize > eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &OpPart); |
||
1374 | else |
||
1375 | { |
||
1376 | AppendCode(0x0c05 | (OpSize << 8) | (DestAdrVals.Val << 4)); |
||
1377 | AppendAdrVals(&SrcAdrVals); |
||
1378 | } |
||
1379 | break; |
||
1380 | default: |
||
1381 | break; |
||
1382 | } |
||
1383 | break; |
||
1384 | } |
||
1385 | case eModDirect: |
||
1386 | case eModIndexed: |
||
1387 | { |
||
1388 | tAdrVals SrcAdrVals; |
||
1389 | |||
1390 | ImmOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
1391 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm, &SrcAdrVals)) |
||
1392 | { |
||
1393 | case eModReg: |
||
1394 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x5d00 : (0x6e00 | (OpSize << 8))) |
||
1395 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1396 | AppendAdrVals(&DestAdrVals); |
||
1397 | break; |
||
1398 | case eModImm: |
||
1399 | if (OpSize > eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &OpPart); |
||
1400 | else |
||
1401 | { |
||
1402 | AppendCode(0x4c05 | (OpSize << 8) | (DestAdrVals.Val << 4)); |
||
1403 | AppendAdrVals(&DestAdrVals); |
||
1404 | AppendAdrVals(&SrcAdrVals); |
||
1405 | } |
||
1406 | break; |
||
1407 | default: |
||
1408 | break; |
||
1409 | } |
||
1410 | break; |
||
1411 | } |
||
1412 | case eModBaseAddress: |
||
1413 | { |
||
1414 | tAdrVals SrcAdrVals; |
||
1415 | |||
1416 | if (DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals) == eModReg) |
||
1417 | { |
||
1418 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x3700 : (0x3200 | (OpSize << 8))) |
||
1419 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1420 | AppendAdrVals(&DestAdrVals); |
||
1421 | } |
||
1422 | break; |
||
1423 | } |
||
1424 | case eModBaseIndexed: |
||
1425 | { |
||
1426 | tAdrVals SrcAdrVals; |
||
1427 | |||
1428 | if (DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals) == eModReg) |
||
1429 | { |
||
1430 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x7700 : (0x7200 | (OpSize << 8))) |
||
1431 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1432 | AppendAdrVals(&DestAdrVals); |
||
1433 | } |
||
1434 | break; |
||
1435 | } |
||
1436 | default: |
||
1437 | break; |
||
1438 | } |
||
1439 | } |
||
1440 | |||
1441 | /*!------------------------------------------------------------------------ |
||
1442 | * \fn DecodeLDA(Word Code) |
||
1443 | * \brief decode LDA instruction |
||
1444 | * ------------------------------------------------------------------------ */ |
||
1445 | |||
1446 | static void DecodeLDA(Word Code) |
||
1447 | { |
||
1448 | tAdrVals DestAdrVals, SrcAdrVals; |
||
1449 | |||
1450 | UNUSED(Code); |
||
1451 | |||
1452 | SetOpSize(AddrRegSize(), &OpPart); |
||
1453 | if (ChkArgCnt(2, 2) |
||
1454 | && DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals)) |
||
1455 | switch (DecodeAdr(&ArgStr[2], MModDirect | MModIndexed | MModBaseAddress | MModBaseIndexed, &SrcAdrVals)) |
||
1456 | { |
||
1457 | case eModDirect: |
||
1458 | case eModIndexed: |
||
1459 | AppendCode(0x7600 | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1460 | AppendAdrVals(&SrcAdrVals); |
||
1461 | break; |
||
1462 | case eModBaseAddress: |
||
1463 | AppendCode(0x3400 | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1464 | AppendAdrVals(&SrcAdrVals); |
||
1465 | break; |
||
1466 | case eModBaseIndexed: |
||
1467 | AppendCode(0x7400 | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1468 | AppendAdrVals(&SrcAdrVals); |
||
1469 | break; |
||
1470 | default: |
||
1471 | break; |
||
1472 | } |
||
1473 | } |
||
1474 | |||
1475 | /*!------------------------------------------------------------------------ |
||
1476 | * \fn DecodeLDAR(Word Code) |
||
1477 | * \brief decode LDAR instruction |
||
1478 | * ------------------------------------------------------------------------ */ |
||
1479 | |||
1480 | static void DecodeLDAR(Word Code) |
||
1481 | { |
||
1482 | tAdrVals DestAdrVals; |
||
1483 | |||
1484 | SetOpSize(AddrRegSize(), &OpPart); |
||
1485 | if (ChkArgCnt(2, 2) |
||
1486 | && DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals)) |
||
1487 | { |
||
1488 | tEvalResult EvalResult; |
||
1489 | LongWord Addr = EvalStrIntExpressionWithResult(&ArgStr[2], MemIntType, &EvalResult); |
||
1490 | if (EvalResult.OK) |
||
1491 | { |
||
1492 | Word Delta; |
||
1493 | |||
1494 | if (!mFirstPassUnknownOrQuestionable(EvalResult.Flags) && (GetSegment(Addr) != GetSegment(EProgCounter()))) |
||
1495 | WrStrErrorPos(ErrNum_InAccSegment, &ArgStr[2]); |
||
1496 | |||
1497 | Delta = (Addr & 0xffff) - ((EProgCounter() + 4) & 0xffff); |
||
1498 | AppendCode(Code | DestAdrVals.Val); |
||
1499 | AppendCode(Delta); |
||
1500 | } |
||
1501 | } |
||
1502 | } |
||
1503 | |||
1504 | /*!------------------------------------------------------------------------ |
||
1505 | * \fn DecodeLDCTL(Word Code) |
||
1506 | * \brief decode LDCTL(B) instruction |
||
1507 | * ------------------------------------------------------------------------ */ |
||
1508 | |||
1509 | static void DecodeLDCTL(Word Code) |
||
1510 | { |
||
1511 | tAdrVals DestAdrVals; |
||
1512 | |||
1513 | UNUSED(Code); |
||
1514 | if (SetOpSizeFromCode(Code) |
||
1515 | && ChkArgCnt(2, 2) |
||
1516 | && CheckSup(True)) |
||
1517 | switch (DecodeAdr(&ArgStr[1], MModReg | MModCtl, &DestAdrVals)) |
||
1518 | { |
||
1519 | case eModReg: |
||
1520 | { |
||
1521 | tAdrVals SrcAdrVals; |
||
1522 | |||
1523 | if (DecodeAdr(&ArgStr[2], MModCtl, &SrcAdrVals)) |
||
1524 | AppendCode((OpSize ? 0x7d00 : 0x8c00) | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1525 | break; |
||
1526 | } |
||
1527 | case eModCtl: |
||
1528 | { |
||
1529 | tAdrVals SrcAdrVals; |
||
1530 | |||
1531 | if (DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals)) |
||
1532 | AppendCode((OpSize ? 0x7d08 : 0x8c08) | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1533 | break; |
||
1534 | } |
||
1535 | default: |
||
1536 | break; |
||
1537 | } |
||
1538 | } |
||
1539 | |||
1540 | /*!------------------------------------------------------------------------ |
||
1541 | * \fn DecodeLDR(Word Code) |
||
1542 | * \brief decode LDR[L|B] |
||
1543 | * \param Code machine code |
||
1544 | * ------------------------------------------------------------------------ */ |
||
1545 | |||
1546 | static void DecodeLDR(Word Code) |
||
1547 | { |
||
1548 | Word Reg; |
||
1549 | tSymbolSize RegSize; |
||
1550 | int RegArgIndex = 1; |
||
1551 | |||
1552 | if (SetOpSizeFromCode(Code) |
||
1553 | && ChkArgCnt(2, 2)) |
||
1554 | switch (DecodeReg(&ArgStr[RegArgIndex], &Reg, &RegSize, ChkRegSize_8To32, False)) |
||
1555 | { |
||
1556 | case eIsNoReg: |
||
1557 | RegArgIndex = 2; |
||
1558 | if (DecodeReg(&ArgStr[RegArgIndex], &Reg, &RegSize, ChkRegSize_8To32, True) != eIsReg) |
||
1559 | return; |
||
1560 | Code |= 2; |
||
1561 | /* fall-thru */ |
||
1562 | case eIsReg: |
||
1563 | { |
||
1564 | tEvalResult EvalResult; |
||
1565 | LongWord Addr; |
||
1566 | |||
1567 | if (!SetOpSize(RegSize, &ArgStr[RegArgIndex])) |
||
1568 | return; |
||
1569 | if (OpSize > eSymbolSize32Bit) |
||
1570 | { |
||
1571 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[RegArgIndex]); |
||
1572 | return; |
||
1573 | } |
||
1574 | |||
1575 | Addr = EvalStrIntExpressionWithResult(&ArgStr[3 - RegArgIndex], MemIntType, &EvalResult); |
||
1576 | if (EvalResult.OK) |
||
1577 | { |
||
1578 | Word Delta; |
||
1579 | |||
1580 | if (!mFirstPassUnknownOrQuestionable(EvalResult.Flags) && (GetSegment(Addr) != GetSegment(EProgCounter()))) |
||
1581 | WrStrErrorPos(ErrNum_InAccSegment, &ArgStr[2]); |
||
1582 | |||
1583 | Delta = (Addr & 0xffff) - ((EProgCounter() + 4) & 0xffff); |
||
1584 | AppendCode(((Lo(Code) | ((OpSize == eSymbolSize32Bit) ? 0x5 : OpSize)) << 8) | Reg); |
||
1585 | AppendCode(Delta); |
||
1586 | } |
||
1587 | break; |
||
1588 | } |
||
1589 | case eRegAbort: |
||
1590 | break; |
||
1591 | } |
||
1592 | } |
||
1593 | |||
1594 | /*!------------------------------------------------------------------------ |
||
1595 | * \fn DecodeADD(Word Code) |
||
1596 | * \brief decode ADD/ADDB/ADDL instruction |
||
1597 | * \param Code instruction type |
||
1598 | * ------------------------------------------------------------------------ */ |
||
1599 | |||
1600 | static void DecodeADD(Word Code) |
||
1601 | { |
||
1602 | tAdrVals DestAdrVals; |
||
1603 | |||
1604 | if (!SetOpSizeFromCode(Code) |
||
1605 | || !ChkArgCnt(2, 2)) |
||
1606 | return; |
||
1607 | |||
1608 | if (DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals) == eModReg) |
||
1609 | { |
||
1610 | tAdrVals SrcAdrVals; |
||
1611 | |||
1612 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModDirect | MModIndexed, &SrcAdrVals)) |
||
1613 | { |
||
1614 | case eModReg: |
||
1615 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x9600 : (0x8000 | (OpSize << 8))) |
||
1616 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1617 | break; |
||
1618 | case eModIReg: |
||
1619 | case eModImm: |
||
1620 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1600 : (0x0000 | (OpSize << 8))) |
||
1621 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1622 | AppendAdrVals(&SrcAdrVals); |
||
1623 | break; |
||
1624 | case eModDirect: |
||
1625 | case eModIndexed: |
||
1626 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x5600 : (0x4000 | (OpSize << 8))) |
||
1627 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1628 | AppendAdrVals(&SrcAdrVals); |
||
1629 | break; |
||
1630 | default: |
||
1631 | break; |
||
1632 | } |
||
1633 | } |
||
1634 | } |
||
1635 | |||
1636 | /*!------------------------------------------------------------------------ |
||
1637 | * \fn DecodeSUB(Word Code) |
||
1638 | * \brief decode SUB/SUBB/SUBL instruction |
||
1639 | * \param Code instruction type |
||
1640 | * ------------------------------------------------------------------------ */ |
||
1641 | |||
1642 | static void DecodeSUB(Word Code) |
||
1643 | { |
||
1644 | tAdrVals DestAdrVals; |
||
1645 | |||
1646 | if (!SetOpSizeFromCode(Code) |
||
1647 | || !ChkArgCnt(2, 2)) |
||
1648 | return; |
||
1649 | |||
1650 | if (DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals) == eModReg) |
||
1651 | { |
||
1652 | tAdrVals SrcAdrVals; |
||
1653 | |||
1654 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModDirect | MModIndexed, &SrcAdrVals)) |
||
1655 | { |
||
1656 | case eModReg: |
||
1657 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x9200 : (0x8200 | (OpSize << 8))) |
||
1658 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1659 | break; |
||
1660 | case eModIReg: |
||
1661 | case eModImm: |
||
1662 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1200 : (0x0200 | (OpSize << 8))) |
||
1663 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1664 | AppendAdrVals(&SrcAdrVals); |
||
1665 | break; |
||
1666 | case eModDirect: |
||
1667 | case eModIndexed: |
||
1668 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x5200 : (0x4200 | (OpSize << 8))) |
||
1669 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1670 | AppendAdrVals(&SrcAdrVals); |
||
1671 | break; |
||
1672 | default: |
||
1673 | break; |
||
1674 | } |
||
1675 | } |
||
1676 | } |
||
1677 | |||
1678 | /*!------------------------------------------------------------------------ |
||
1679 | * \fn DecodeCP(Word Code) |
||
1680 | * \brief decode CP/CPB/CPL instruction |
||
1681 | * \param Code instruction type |
||
1682 | * ------------------------------------------------------------------------ */ |
||
1683 | |||
1684 | static void DecodeCP(Word Code) |
||
1685 | { |
||
1686 | tAdrVals DestAdrVals; |
||
1687 | |||
1688 | if (!SetOpSizeFromCode(Code) |
||
1689 | || !ChkArgCnt(2, 2)) |
||
1690 | return; |
||
1691 | |||
1692 | switch (DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &DestAdrVals)) |
||
1693 | { |
||
1694 | case eModReg: |
||
1695 | { |
||
1696 | tAdrVals SrcAdrVals; |
||
1697 | |||
1698 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModDirect | MModIndexed, &SrcAdrVals)) |
||
1699 | { |
||
1700 | case eModReg: |
||
1701 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x9000 : (0x8a00 | (OpSize << 8))) |
||
1702 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1703 | break; |
||
1704 | case eModIReg: |
||
1705 | case eModImm: |
||
1706 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x1000 : (0x0a00 | (OpSize << 8))) |
||
1707 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1708 | AppendAdrVals(&SrcAdrVals); |
||
1709 | break; |
||
1710 | case eModDirect: |
||
1711 | case eModIndexed: |
||
1712 | AppendCode(((OpSize == eSymbolSize32Bit) ? 0x5000 : (0x4a00 | (OpSize << 8))) |
||
1713 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1714 | AppendAdrVals(&SrcAdrVals); |
||
1715 | break; |
||
1716 | default: |
||
1717 | break; |
||
1718 | } |
||
1719 | break; |
||
1720 | } |
||
1721 | case eModIReg: |
||
1722 | { |
||
1723 | tAdrVals SrcAdrVals; |
||
1724 | |||
1725 | ImmOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
1726 | if (OpSize == eSymbolSize32Bit) WrStrErrorPos(ErrNum_InvOpSize, &OpPart); |
||
1727 | else if (eModImm == DecodeAdr(&ArgStr[2], MModImm, &SrcAdrVals)) |
||
1728 | { |
||
1729 | AppendCode(0x0c01 | (DestAdrVals.Val << 4) | (OpSize << 8)); |
||
1730 | AppendAdrVals(&SrcAdrVals); |
||
1731 | } |
||
1732 | break; |
||
1733 | } |
||
1734 | case eModDirect: |
||
1735 | case eModIndexed: |
||
1736 | { |
||
1737 | tAdrVals SrcAdrVals; |
||
1738 | |||
1739 | ImmOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
1740 | if (OpSize == eSymbolSize32Bit) WrStrErrorPos(ErrNum_InvOpSize, &OpPart); |
||
1741 | else if (eModImm == DecodeAdr(&ArgStr[2], MModImm, &SrcAdrVals)) |
||
1742 | { |
||
1743 | AppendCode(0x4c01 | (DestAdrVals.Val << 4) | (OpSize << 8)); |
||
1744 | AppendAdrVals(&DestAdrVals); |
||
1745 | AppendAdrVals(&SrcAdrVals); |
||
1746 | } |
||
1747 | break; |
||
1748 | } |
||
1749 | default: |
||
1750 | break; |
||
1751 | } |
||
1752 | } |
||
1753 | |||
1754 | /*!------------------------------------------------------------------------ |
||
1755 | * \fn DecodeADC_SBC(Word Code) |
||
1756 | * \brief decode ADC/SBC instructions |
||
1757 | * \param Code instruction type |
||
1758 | * ------------------------------------------------------------------------ */ |
||
1759 | |||
1760 | static void DecodeADC_SBC(Word Code) |
||
1761 | { |
||
1762 | tAdrVals DestAdrVals, SrcAdrVals; |
||
1763 | |||
1764 | if (!SetOpSizeFromCode(Code) |
||
1765 | || !ChkArgCnt(2, 2)) |
||
1766 | return; |
||
1767 | |||
1768 | if ((DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals) == eModReg) |
||
1769 | && (DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals) == eModReg)) |
||
1770 | { |
||
1771 | if (OpSize > eSymbolSize16Bit) WrError(ErrNum_InvOpSize); |
||
1772 | else |
||
1773 | AppendCode(0x8000 | (((Code & 0xfe) | OpSize) << 8) |
||
1774 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1775 | } |
||
1776 | } |
||
1777 | |||
1778 | /*!------------------------------------------------------------------------ |
||
1779 | * \fn DecodeAND_OR_XOR(Word Code) |
||
1780 | * \brief decode AND/OR/XOR instructions |
||
1781 | * \param Code instruction type |
||
1782 | * ------------------------------------------------------------------------ */ |
||
1783 | |||
1784 | static void DecodeAND_OR_XOR(Word Code) |
||
1785 | { |
||
1786 | tAdrVals DestAdrVals; |
||
1787 | |||
1788 | if (!SetOpSizeFromCode(Code) |
||
1789 | || !ChkArgCnt(2, 2)) |
||
1790 | return; |
||
1791 | |||
1792 | if (DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals) == eModReg) |
||
1793 | { |
||
1794 | tAdrVals SrcAdrVals; |
||
1795 | |||
1796 | if (OpSize > eSymbolSize16Bit) WrError(ErrNum_InvOpSize); |
||
1797 | else switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModDirect | MModIndexed, &SrcAdrVals)) |
||
1798 | { |
||
1799 | case eModReg: |
||
1800 | AppendCode(0x8000 | (((Code & 0xfe) | OpSize) << 8) |
||
1801 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1802 | break; |
||
1803 | case eModIReg: |
||
1804 | case eModImm: |
||
1805 | AppendCode(0x0000 | (((Code & 0xfe) | OpSize) << 8) |
||
1806 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1807 | AppendAdrVals(&SrcAdrVals); |
||
1808 | break; |
||
1809 | case eModDirect: |
||
1810 | case eModIndexed: |
||
1811 | AppendCode(0x4000 | (((Code & 0xfe) | OpSize) << 8) |
||
1812 | | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
1813 | AppendAdrVals(&SrcAdrVals); |
||
1814 | break; |
||
1815 | default: |
||
1816 | break; |
||
1817 | } |
||
1818 | } |
||
1819 | } |
||
1820 | |||
1821 | /*!------------------------------------------------------------------------ |
||
1822 | * \fn DecodeINC_DEC(Word Code) |
||
1823 | * \brief decode increment/decrement instructions |
||
1824 | * \param Code instruction type |
||
1825 | * ------------------------------------------------------------------------ */ |
||
1826 | |||
1827 | static void DecodeINC_DEC(Word Code) |
||
1828 | { |
||
1829 | tAdrVals AdrVals; |
||
1830 | |||
1831 | if (SetOpSizeFromCode(Code) |
||
1832 | && ChkArgCnt(1, 2) |
||
1833 | && DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &AdrVals)) |
||
1834 | { |
||
1835 | if (OpSize == eSymbolSizeUnknown) |
||
1836 | OpSize = eSymbolSize16Bit; |
||
1837 | if (OpSize > eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
1838 | else |
||
1839 | { |
||
1840 | tEvalResult EvalResult; |
||
1841 | Word ImmVal = 0; |
||
1842 | |||
1843 | if (2 == ArgCnt) |
||
1844 | ImmVal = DecodeImm1_16(&ArgStr[2], &EvalResult); |
||
1845 | else |
||
1846 | EvalResult.OK = True; |
||
1847 | |||
1848 | if (EvalResult.OK) |
||
1849 | switch (AdrVals.Mode) |
||
1850 | { |
||
1851 | case eModReg: |
||
1852 | AppendCode(0x8000 | ((Code | OpSize) << 8) | (AdrVals.Val << 4) | ImmVal); |
||
1853 | break; |
||
1854 | case eModIReg: |
||
1855 | AppendCode(0x0000 | ((Code | OpSize) << 8) | (AdrVals.Val << 4) | ImmVal); |
||
1856 | break; |
||
1857 | case eModDirect: |
||
1858 | case eModIndexed: |
||
1859 | AppendCode(0x4000 | ((Code | OpSize) << 8) | (AdrVals.Val << 4) | ImmVal); |
||
1860 | AppendAdrVals(&AdrVals); |
||
1861 | break; |
||
1862 | default: |
||
1863 | break; |
||
1864 | } |
||
1865 | } |
||
1866 | } |
||
1867 | } |
||
1868 | |||
1869 | /*!------------------------------------------------------------------------ |
||
1870 | * \fn DecodeBitOp(Word Code) |
||
1871 | * \brief decode bit set/reset/test instructions |
||
1872 | * \param Code instruction type |
||
1873 | * ------------------------------------------------------------------------ */ |
||
1874 | |||
1875 | static void DecodeBitOp(Word Code) |
||
1876 | { |
||
1877 | tAdrVals DestAdrVals, SrcAdrVals; |
||
1878 | tSymbolSize DestOpSize; |
||
1879 | |||
1880 | if (!SetOpSizeFromCode(Code)) |
||
1881 | return; |
||
1882 | |||
1883 | switch (ArgCnt) |
||
1884 | { |
||
1885 | case 1: |
||
1886 | { |
||
1887 | LongWord PacketBit; |
||
1888 | |||
1889 | if (DecodeBitArg(&PacketBit, 1, 1, OpSize)) |
||
1890 | { |
||
1891 | LongWord Address; |
||
1892 | Byte BitPos; |
||
1893 | Boolean ForceShort; |
||
1894 | |||
1895 | if (DissectBitSymbol(PacketBit, &Address, &BitPos, &DestOpSize, &ForceShort) |
||
1896 | && SetOpSize(DestOpSize, &ArgStr[1])) |
||
1897 | { |
||
1898 | ClearAdrVals(&SrcAdrVals); |
||
1899 | SrcAdrVals.Val = BitPos; |
||
1900 | ClearAdrVals(&DestAdrVals); |
||
1901 | FillAbsAddr(&DestAdrVals, Address, False, ForceShort); |
||
1902 | goto Abs2Imm; /* yeah! */ |
||
1903 | } |
||
1904 | } |
||
1905 | break; |
||
1906 | } |
||
1907 | case 2: |
||
1908 | if (DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &DestAdrVals)) |
||
1909 | { |
||
1910 | DestOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
1911 | |||
1912 | switch (DestOpSize) |
||
1913 | { |
||
1914 | case eSymbolSize8Bit: |
||
1915 | ImmOpSize = eSymbolSize3Bit; break; |
||
1916 | case eSymbolSize16Bit: |
||
1917 | ImmOpSize = eSymbolSize4Bit; break; |
||
1918 | default: |
||
1919 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); return; |
||
1920 | } |
||
1921 | OpSize = eSymbolSizeUnknown; |
||
1922 | |||
1923 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm, &SrcAdrVals)) |
||
1924 | { |
||
1925 | case eModImm: |
||
1926 | switch (DestAdrVals.Mode) |
||
1927 | { |
||
1928 | case eModReg: |
||
1929 | AppendCode(0x8000 | (((Code & 0xfe) | DestOpSize) << 8) |
||
1930 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1931 | break; |
||
1932 | case eModIReg: |
||
1933 | AppendCode(0x0000 | (((Code & 0xfe) | DestOpSize) << 8) |
||
1934 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1935 | break; |
||
1936 | case eModDirect: |
||
1937 | case eModIndexed: |
||
1938 | Abs2Imm: |
||
1939 | AppendCode(0x4000 | (((Code & 0xfe) | DestOpSize) << 8) |
||
1940 | | (DestAdrVals.Val << 4) | SrcAdrVals.Val); |
||
1941 | AppendAdrVals(&DestAdrVals); |
||
1942 | break; |
||
1943 | default: |
||
1944 | break; |
||
1945 | } |
||
1946 | break; |
||
1947 | case eModReg: |
||
1948 | switch (DestAdrVals.Mode) |
||
1949 | { |
||
1950 | case eModReg: |
||
1951 | if (OpSize != eSymbolSize16Bit) WrStrErrorPos (ErrNum_InvOpSize, &ArgStr[2]); |
||
1952 | else |
||
1953 | { |
||
1954 | AppendCode(0x0000 | (((Code & 0xfe) | DestOpSize) << 8) | SrcAdrVals.Val); |
||
1955 | AppendCode(DestAdrVals.Val << 8); |
||
1956 | } |
||
1957 | break; |
||
1958 | case eModNone: |
||
1959 | break; |
||
1960 | default: |
||
1961 | WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]); |
||
1962 | } |
||
1963 | break; |
||
1964 | default: |
||
1965 | break; |
||
1966 | } |
||
1967 | } |
||
1968 | break; |
||
1969 | default: |
||
1970 | (void)ChkArgCnt(1, 2); |
||
1971 | } |
||
1972 | } |
||
1973 | |||
1974 | /*!------------------------------------------------------------------------ |
||
1975 | * \fn DecodeCALL_JP(Word Code) |
||
1976 | * \brief decode jump/call instructions |
||
1977 | * \param instruction code |
||
1978 | * ------------------------------------------------------------------------ */ |
||
1979 | |||
1980 | static void DecodeCALL_JP(Word Code) |
||
1981 | { |
||
1982 | tAdrVals AdrVals; |
||
1983 | Boolean IsCALL = Code & 1; |
||
1984 | |||
1985 | if (ChkArgCnt(1, 2 - IsCALL)) |
||
1986 | { |
||
1987 | Word Condition; |
||
1988 | |||
1989 | if (IsCALL) |
||
1990 | Condition = 0; |
||
1991 | else if (!DecodeCondition((ArgCnt == 2) ? &ArgStr[1] : NULL, &Condition)) |
||
1992 | return; |
||
1993 | |||
1994 | switch (DecodeAdr(&ArgStr[ArgCnt], MModIReg | MModDirect | MModIndexed, &AdrVals)) |
||
1995 | { |
||
1996 | case eModIReg: |
||
1997 | AppendCode(0x0000 | (Code << 8) | (AdrVals.Val << 4) | Condition); |
||
1998 | break; |
||
1999 | case eModDirect: |
||
2000 | case eModIndexed: |
||
2001 | AppendCode(0x4000 | (Code << 8) | (AdrVals.Val << 4) | Condition); |
||
2002 | AppendAdrVals(&AdrVals); |
||
2003 | break; |
||
2004 | default: |
||
2005 | break; |
||
2006 | } |
||
2007 | } |
||
2008 | } |
||
2009 | |||
2010 | /*!------------------------------------------------------------------------ |
||
2011 | * \fn DecodeBranch(Word CodeWord MaxDist, Boolean Inverse, const tStrComp *pArg) |
||
2012 | * \brief relative branch core decode |
||
2013 | * \param Code instruction code (upper bits) |
||
2014 | * \param MaxDist maximum positive distance (in bytes, e.g. even value) |
||
2015 | * \param Inverse Displacement is subtraced and not added by CPU |
||
2016 | * \param pArg source argument |
||
2017 | * ------------------------------------------------------------------------ */ |
||
2018 | |||
2019 | static void DecodeBranch(Word Code, Word MaxDist, Boolean Inverse, const tStrComp *pArg) |
||
2020 | { |
||
2021 | tEvalResult EvalResult; |
||
2022 | LongWord Addr = EvalStrIntExpressionWithResult(pArg, MemIntType, &EvalResult); |
||
2023 | |||
2024 | if (EvalResult.OK) |
||
2025 | { |
||
2026 | Word Delta; |
||
2027 | |||
2028 | /* considering wraparound in segment makes things a bit more complicated: */ |
||
2029 | |||
2030 | if (!mFirstPassUnknownOrQuestionable(EvalResult.Flags) && (GetSegment(Addr) != GetSegment(EProgCounter()))) |
||
2031 | WrStrErrorPos(ErrNum_InAccSegment, pArg); |
||
2032 | |||
2033 | Delta = (Addr & 0xffff) - ((EProgCounter() + 2) & 0xffff); |
||
2034 | if (Inverse) |
||
2035 | Delta = (~Delta) + 1; |
||
2036 | if ((Delta & 1) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags)) WrStrErrorPos(ErrNum_AddrMustBeEven, pArg); |
||
2037 | else if ((Delta > MaxDist) && (Delta < (0xfffe - MaxDist)) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags)) WrStrErrorPos(ErrNum_JmpDistTooBig, pArg); |
||
2038 | else |
||
2039 | AppendCode(Code | ((Delta >> 1) & (MaxDist + 1))); |
||
2040 | } |
||
2041 | } |
||
2042 | |||
2043 | /*!------------------------------------------------------------------------ |
||
2044 | * \fn DecodeCALR(Word Code) |
||
2045 | * \brief decode CALR instruction |
||
2046 | * \param Code instruction code (upper bits) |
||
2047 | * ------------------------------------------------------------------------ */ |
||
2048 | |||
2049 | static void DecodeCALR(Word Code) |
||
2050 | { |
||
2051 | if (ChkArgCnt(1, 1)) |
||
2052 | DecodeBranch(Code, 4094, True, &ArgStr[1]); |
||
2053 | } |
||
2054 | |||
2055 | /*!------------------------------------------------------------------------ |
||
2056 | * \fn DecodeJR(Word Code) |
||
2057 | * \brief decode JR instruction |
||
2058 | * \param Code instruction code (upper bits) |
||
2059 | * ------------------------------------------------------------------------ */ |
||
2060 | |||
2061 | static void DecodeJR(Word Code) |
||
2062 | { |
||
2063 | Word Condition; |
||
2064 | |||
2065 | if (ChkArgCnt(1, 2) |
||
2066 | && DecodeCondition(ArgCnt == 2 ? &ArgStr[1] : NULL, &Condition)) |
||
2067 | DecodeBranch(Code | (Condition << 8), 254, False, &ArgStr[ArgCnt]); |
||
2068 | } |
||
2069 | |||
2070 | /*!------------------------------------------------------------------------ |
||
2071 | * \fn DecodeDJNZ(Word Code) |
||
2072 | * \brief decode DJNZ instructions |
||
2073 | * \param size spec |
||
2074 | * ------------------------------------------------------------------------ */ |
||
2075 | |||
2076 | static void DecodeDJNZ(Word Code) |
||
2077 | { |
||
2078 | tAdrVals AdrVals; |
||
2079 | |||
2080 | if (SetOpSizeFromCode(Code) |
||
2081 | && ChkArgCnt(2, 2) |
||
2082 | && DecodeAdr(&ArgStr[1], MModReg, &AdrVals)) |
||
2083 | { |
||
2084 | if (OpSize > eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2085 | else |
||
2086 | { |
||
2087 | tEvalResult EvalResult; |
||
2088 | LongWord Addr = EvalStrIntExpressionWithResult(&ArgStr[2], MemIntType, &EvalResult); |
||
2089 | |||
2090 | if (EvalResult.OK) |
||
2091 | { |
||
2092 | Word Delta; |
||
2093 | |||
2094 | /* considering wraparound in segment makes things a bit more complicated: */ |
||
2095 | |||
2096 | if (!mFirstPassUnknownOrQuestionable(EvalResult.Flags) && (GetSegment(Addr) != GetSegment(EProgCounter()))) |
||
2097 | WrStrErrorPos(ErrNum_InAccSegment, &ArgStr[2]); |
||
2098 | |||
2099 | Delta = (Addr & 0xffff) - ((EProgCounter() + 2) & 0xffff); |
||
2100 | if ((Delta & 1) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags)) WrStrErrorPos(ErrNum_AddrMustBeEven, &ArgStr[2]); |
||
2101 | else if ((Delta > 0) && (Delta < 0xff02) && !mFirstPassUnknownOrQuestionable(EvalResult.Flags)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[2]); |
||
2102 | else |
||
2103 | { |
||
2104 | Delta = (0x10000lu - Delta) >> 1; |
||
2105 | AppendCode(0xf000 | (AdrVals.Val << 8) | (OpSize << 7) | (Delta & 0x7f)); |
||
2106 | } |
||
2107 | } |
||
2108 | } |
||
2109 | } |
||
2110 | } |
||
2111 | |||
2112 | /*!------------------------------------------------------------------------ |
||
2113 | * \fn DecodeCLR_COM_NEG_TSET(Word Code) |
||
2114 | * \brief decode CLR/COM/NEG/TSET instructions |
||
2115 | * \param Code machine code + size spec |
||
2116 | * ------------------------------------------------------------------------ */ |
||
2117 | |||
2118 | static void DecodeCLR_COM_NEG_TSET(Word Code) |
||
2119 | { |
||
2120 | tAdrVals AdrVals; |
||
2121 | |||
2122 | if (SetOpSizeFromCode(Code) |
||
2123 | && ChkArgCnt(1,1) |
||
2124 | && DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &AdrVals)) |
||
2125 | { |
||
2126 | if (OpSize == eSymbolSizeUnknown) |
||
2127 | OpSize = eSymbolSize16Bit; |
||
2128 | if (OpSize > eSymbolSize16Bit) WrError(ErrNum_InvOpSize); |
||
2129 | else |
||
2130 | { |
||
2131 | Code = ((Code >> 4) & 0x0f) | (((Code & 0x0e) | OpSize) << 8); |
||
2132 | switch (AdrVals.Mode) |
||
2133 | { |
||
2134 | case eModReg: |
||
2135 | AppendCode(0x8000 | Code | (AdrVals.Val << 4)); |
||
2136 | break; |
||
2137 | case eModIReg: |
||
2138 | AppendCode(0x0000 | Code | (AdrVals.Val << 4)); |
||
2139 | break; |
||
2140 | case eModDirect: |
||
2141 | case eModIndexed: |
||
2142 | AppendCode(0x4000 | Code | (AdrVals.Val << 4)); |
||
2143 | AppendAdrVals(&AdrVals); |
||
2144 | break; |
||
2145 | default: |
||
2146 | break; |
||
2147 | } |
||
2148 | } |
||
2149 | } |
||
2150 | } |
||
2151 | |||
2152 | /*!------------------------------------------------------------------------ |
||
2153 | * \fn DecodeTEST(Word Code) |
||
2154 | * \brief decode TEST instruction |
||
2155 | * \param Code machine code + size spec |
||
2156 | * ------------------------------------------------------------------------ */ |
||
2157 | |||
2158 | static void DecodeTEST(Word Code) |
||
2159 | { |
||
2160 | tAdrVals AdrVals; |
||
2161 | |||
2162 | if (SetOpSizeFromCode(Code) |
||
2163 | && ChkArgCnt(1, 1) |
||
2164 | && DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &AdrVals)) |
||
2165 | { |
||
2166 | if (OpSize == eSymbolSizeUnknown) |
||
2167 | OpSize = eSymbolSize16Bit; |
||
2168 | if (OpSize > eSymbolSize32Bit) WrError(ErrNum_InvOpSize); |
||
2169 | else |
||
2170 | { |
||
2171 | Code = (Lo(Code) | ((OpSize == eSymbolSize32Bit) ? 0x10 : OpSize)) << 8 | ((OpSize == eSymbolSize32Bit) ? 8 : 4); |
||
2172 | switch (AdrVals.Mode) |
||
2173 | { |
||
2174 | case eModReg: |
||
2175 | AppendCode(0x8000 | Code | (AdrVals.Val << 4)); |
||
2176 | break; |
||
2177 | case eModIReg: |
||
2178 | AppendCode(0x0000 | Code | (AdrVals.Val << 4)); |
||
2179 | break; |
||
2180 | case eModDirect: |
||
2181 | case eModIndexed: |
||
2182 | AppendCode(0x4000 | Code | (AdrVals.Val << 4)); |
||
2183 | AppendAdrVals(&AdrVals); |
||
2184 | break; |
||
2185 | default: |
||
2186 | break; |
||
2187 | } |
||
2188 | } |
||
2189 | } |
||
2190 | } |
||
2191 | |||
2192 | /*!------------------------------------------------------------------------ |
||
2193 | * \fn DecodeEX(Word Code) |
||
2194 | * \brief decode EX instruction |
||
2195 | * \param Code machine code + size spec |
||
2196 | * ------------------------------------------------------------------------ */ |
||
2197 | |||
2198 | static void DecodeEX(Word Code) |
||
2199 | { |
||
2200 | tAdrVals SrcAdrVals, DestAdrVals; |
||
2201 | |||
2202 | if (SetOpSizeFromCode(Code) |
||
2203 | && ChkArgCnt(2, 2) |
||
2204 | && DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &DestAdrVals) |
||
2205 | && DecodeAdr(&ArgStr[2], MModReg | ((DestAdrVals.Mode == eModReg) ? (MModIReg | MModDirect | MModIndexed) : 0), &SrcAdrVals)) |
||
2206 | { |
||
2207 | if (OpSize == eSymbolSizeUnknown) |
||
2208 | OpSize = eSymbolSize16Bit; |
||
2209 | if (OpSize > eSymbolSize16Bit) WrError(ErrNum_InvOpSize); |
||
2210 | else |
||
2211 | { |
||
2212 | if (DestAdrVals.Mode != eModReg) |
||
2213 | { |
||
2214 | tAdrVals Swap; |
||
2215 | Swap = SrcAdrVals; |
||
2216 | SrcAdrVals = DestAdrVals; |
||
2217 | DestAdrVals = Swap; |
||
2218 | } |
||
2219 | Code = (Lo(Code) | OpSize) << 8; |
||
2220 | switch (SrcAdrVals.Mode) |
||
2221 | { |
||
2222 | case eModReg: |
||
2223 | AppendCode(0x8000 | Code | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2224 | break; |
||
2225 | case eModIReg: |
||
2226 | AppendCode(0x0000 | Code | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2227 | break; |
||
2228 | case eModDirect: |
||
2229 | case eModIndexed: |
||
2230 | AppendCode(0x4000 | Code | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2231 | AppendAdrVals(&SrcAdrVals); |
||
2232 | break; |
||
2233 | default: |
||
2234 | break; |
||
2235 | } |
||
2236 | } |
||
2237 | } |
||
2238 | } |
||
2239 | |||
2240 | /*!------------------------------------------------------------------------ |
||
2241 | * \fn DecodeEXTS(Word Code) |
||
2242 | * \brief decode EXTS instruction |
||
2243 | * \param Code machine code + size spec |
||
2244 | * ------------------------------------------------------------------------ */ |
||
2245 | |||
2246 | static void DecodeEXTS(Word Code) |
||
2247 | { |
||
2248 | if (SetOpSizeFromCode(Code) |
||
2249 | && ChkArgCnt(1, 1)) |
||
2250 | { |
||
2251 | tAdrVals AdrVals; |
||
2252 | |||
2253 | if (OpSize != eSymbolSizeUnknown) |
||
2254 | OpSize++; |
||
2255 | if (DecodeAdr(&ArgStr[1], MModReg, &AdrVals)) |
||
2256 | { |
||
2257 | Code = (Lo(Code) << 8) | 0x8000 | (AdrVals.Val << 4); |
||
2258 | switch (OpSize) |
||
2259 | { |
||
2260 | case eSymbolSize16Bit: |
||
2261 | AppendCode(Code | 0x0000); |
||
2262 | break; |
||
2263 | case eSymbolSize32Bit: |
||
2264 | AppendCode(Code | 0x000a); |
||
2265 | break; |
||
2266 | case eSymbolSize64Bit: |
||
2267 | AppendCode(Code | 0x0007); |
||
2268 | break; |
||
2269 | default: |
||
2270 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2271 | } |
||
2272 | } |
||
2273 | } |
||
2274 | } |
||
2275 | |||
2276 | /*!------------------------------------------------------------------------ |
||
2277 | * \fn DecodeMULT_DIV(Word Code) |
||
2278 | * \brief decode multiply/divide instructions |
||
2279 | * \param Code instruction code |
||
2280 | * ------------------------------------------------------------------------ */ |
||
2281 | |||
2282 | static void DecodeMULT_DIV(Word Code) |
||
2283 | { |
||
2284 | if (SetOpSizeFromCode(Code) |
||
2285 | && ChkArgCnt(2, 2)) |
||
2286 | { |
||
2287 | tAdrVals DestAdrVals; |
||
2288 | |||
2289 | if (OpSize != eSymbolSizeUnknown) |
||
2290 | OpSize++; |
||
2291 | if (DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals) == eModReg) |
||
2292 | { |
||
2293 | tAdrVals SrcAdrVals; |
||
2294 | |||
2295 | if ((OpSize < eSymbolSize32Bit) || (OpSize > eSymbolSize64Bit)) |
||
2296 | { |
||
2297 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2298 | return; |
||
2299 | } |
||
2300 | |||
2301 | OpSize--; |
||
2302 | switch (DecodeAdr(&ArgStr[2], MModReg | MModImm | MModIReg | MModDirect | MModIndexed, &SrcAdrVals)) |
||
2303 | { |
||
2304 | case eModReg: |
||
2305 | AppendCode(0x8000 | ((Code | (OpSize & 1)) << 8) | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2306 | break; |
||
2307 | case eModImm: |
||
2308 | case eModIReg: |
||
2309 | AppendCode(0x0000 | ((Code | (OpSize & 1)) << 8) | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2310 | AppendAdrVals(&SrcAdrVals); |
||
2311 | break; |
||
2312 | case eModDirect: |
||
2313 | case eModIndexed: |
||
2314 | AppendCode(0x4000 | ((Code | (OpSize & 1)) << 8) | (SrcAdrVals.Val << 4) | DestAdrVals.Val); |
||
2315 | AppendAdrVals(&SrcAdrVals); |
||
2316 | break; |
||
2317 | default: |
||
2318 | break; |
||
2319 | } |
||
2320 | } |
||
2321 | } |
||
2322 | } |
||
2323 | |||
2324 | /*!------------------------------------------------------------------------ |
||
2325 | * \fn DecodeDAB(Word Code) |
||
2326 | * \brief decode DAB instruction |
||
2327 | * \param Code instruction code |
||
2328 | * ------------------------------------------------------------------------ */ |
||
2329 | |||
2330 | static void DecodeDAB(Word Code) |
||
2331 | { |
||
2332 | tAdrVals AdrVals; |
||
2333 | |||
2334 | SetOpSize(eSymbolSize8Bit, &OpPart); |
||
2335 | if (ChkArgCnt(1,1) && DecodeAdr(&ArgStr[1], MModReg, &AdrVals)) |
||
2336 | AppendCode(Code | (AdrVals.Val << 4)); |
||
2337 | } |
||
2338 | |||
2339 | /*!------------------------------------------------------------------------ |
||
2340 | * \fn DecodeFLG(Word Code) |
||
2341 | * \brief decode flag set/reset/complement instructions |
||
2342 | * \param machine code |
||
2343 | * ------------------------------------------------------------------------ */ |
||
2344 | |||
2345 | static void DecodeFLG(Word Code) |
||
2346 | { |
||
2347 | if (ChkArgCnt(1, ArgCntMax)) |
||
2348 | { |
||
2349 | int z; |
||
2350 | Word Num; |
||
2351 | static const char FlagNames[] = "PSZCV"; |
||
2352 | |||
2353 | for (z = 1; z <= ArgCnt; z++) |
||
2354 | { |
||
2355 | if (!as_strcasecmp(ArgStr[z].str.p_str, "P/V")) |
||
2356 | Num = 1 << 0; |
||
2357 | else if (!as_strcasecmp(ArgStr[z].str.p_str, "ZR")) |
||
2358 | Num = 1 << 2; |
||
2359 | else if (!as_strcasecmp(ArgStr[z].str.p_str, "CY")) |
||
2360 | Num = 1 << 3; |
||
2361 | else if (1 == strlen(ArgStr[z].str.p_str)) |
||
2362 | { |
||
2363 | const char *pPos = strchr(FlagNames, as_toupper(*ArgStr[z].str.p_str)); |
||
2364 | Num = pPos ? (1 << ((pPos - FlagNames) % 4)) : 0; |
||
2365 | } |
||
2366 | else |
||
2367 | Num = 0; |
||
2368 | |||
2369 | if (!Num) |
||
2370 | { |
||
2371 | WrStrErrorPos(ErrNum_UnknownFlag, &ArgStr[z]); |
||
2372 | return; |
||
2373 | } |
||
2374 | else if (Code & (Num << 4)) |
||
2375 | { |
||
2376 | WrStrErrorPos(ErrNum_DuplicateFlag, &ArgStr[z]); |
||
2377 | return; |
||
2378 | } |
||
2379 | else |
||
2380 | Code |= Num << 4; |
||
2381 | } |
||
2382 | AppendCode(Code); |
||
2383 | } |
||
2384 | } |
||
2385 | |||
2386 | /*!------------------------------------------------------------------------ |
||
2387 | * \fn DecodeDI_EI(Word Code) |
||
2388 | * \brief decode interrupt enable/disable instructions |
||
2389 | * \param Code machine code |
||
2390 | * ------------------------------------------------------------------------ */ |
||
2391 | |||
2392 | static void DecodeDI_EI(Word Code) |
||
2393 | { |
||
2394 | if (ChkArgCnt(1, ArgCntMax) |
||
2395 | && CheckSup(True)) |
||
2396 | { |
||
2397 | int z; |
||
2398 | Word Num; |
||
2399 | |||
2400 | Code |= 3; |
||
2401 | for (z = 1; z <= ArgCnt; z++) |
||
2402 | { |
||
2403 | if (!as_strcasecmp(ArgStr[z].str.p_str, "VI")) |
||
2404 | Num = 1 << 1; |
||
2405 | else if (!as_strcasecmp(ArgStr[z].str.p_str, "NVI")) |
||
2406 | Num = 1 << 0; |
||
2407 | else |
||
2408 | Num = 0; |
||
2409 | |||
2410 | if (!Num) |
||
2411 | { |
||
2412 | WrStrErrorPos(ErrNum_UnknownInt, &ArgStr[z]); |
||
2413 | return; |
||
2414 | } |
||
2415 | else if (!(Code & Num)) |
||
2416 | { |
||
2417 | WrStrErrorPos(ErrNum_DuplicateInt, &ArgStr[z]); |
||
2418 | return; |
||
2419 | } |
||
2420 | else |
||
2421 | Code &= ~Num; |
||
2422 | } |
||
2423 | AppendCode(Code); |
||
2424 | } |
||
2425 | } |
||
2426 | |||
2427 | /*!------------------------------------------------------------------------ |
||
2428 | * \fn DecodeIN_SIN_OUT_SOUT(Word Code) |
||
2429 | * \brief decode IN/SIN/OUT/SOUT |
||
2430 | * \param Code machine code |
||
2431 | * ------------------------------------------------------------------------ */ |
||
2432 | |||
2433 | static void DecodeIN_SIN_OUT_SOUT(Word Code) |
||
2434 | { |
||
2435 | tAdrVals RegAdrVals; |
||
2436 | Word IsOUT = Code & 2, |
||
2437 | IsSpecial = Code & 1; |
||
2438 | const tStrComp *pRegArg = IsOUT ? &ArgStr[2] : &ArgStr[1], |
||
2439 | *pIOArg = IsOUT ? &ArgStr[1] : &ArgStr[2]; |
||
2440 | |||
2441 | if (SetOpSizeFromCode(Code) |
||
2442 | && ChkArgCnt(2, 2) |
||
2443 | && CheckSup(True) |
||
2444 | && DecodeAdr(pRegArg, MModReg, &RegAdrVals)) |
||
2445 | { |
||
2446 | tAdrVals IOAdrVals; |
||
2447 | |||
2448 | if (OpSize > eSymbolSize16Bit) |
||
2449 | { |
||
2450 | WrStrErrorPos(ErrNum_InvOpSize, pRegArg); |
||
2451 | return; |
||
2452 | } |
||
2453 | switch (DecodeAdr(pIOArg, MModIO | MModDirect | (IsSpecial ? 0 : MModIReg), &IOAdrVals)) |
||
2454 | { |
||
2455 | case eModIReg: |
||
2456 | AppendCode(0x3c00 | (IsOUT << 8) | (OpSize << 8) | (IOAdrVals.Val << 4) | RegAdrVals.Val); |
||
2457 | break; |
||
2458 | case eModDirect: |
||
2459 | AppendCode(0x3a04 | (OpSize << 8) | (RegAdrVals.Val << 4) | Lo(Code)); |
||
2460 | AppendAdrVals(&IOAdrVals); |
||
2461 | break; |
||
2462 | default: |
||
2463 | break; |
||
2464 | } |
||
2465 | } |
||
2466 | } |
||
2467 | |||
2468 | /*!------------------------------------------------------------------------ |
||
2469 | * \fn DecodeCPRep(Word Code) |
||
2470 | * \brief decode CP[S](I/D)[R][D] instructions |
||
2471 | * \param Code instruction code |
||
2472 | * ------------------------------------------------------------------------ */ |
||
2473 | |||
2474 | static void DecodeCPRep(Word Code) |
||
2475 | { |
||
2476 | tAdrVals DestAdrVals, SrcAdrVals, CntAdrVals; |
||
2477 | Word Condition; |
||
2478 | tAdrMode DestMode = (Code & 0x02) ? eModIReg : eModReg; |
||
2479 | |||
2480 | if (!SetOpSizeFromCode(Code) |
||
2481 | || !ChkArgCnt(3, 4) |
||
2482 | || !DecodeCondition((ArgCnt == 4) ? &ArgStr[4] : NULL, &Condition)) |
||
2483 | return; |
||
2484 | |||
2485 | if ((DecodeAdr(&ArgStr[1], 1 << DestMode, &DestAdrVals) == DestMode) |
||
2486 | && (DecodeAdr(&ArgStr[2], MModIReg, &SrcAdrVals) == eModIReg)) |
||
2487 | { |
||
2488 | tSymbolSize SaveOpSize; |
||
2489 | |||
2490 | if (OpSize == eSymbolSizeUnknown) |
||
2491 | OpSize = eSymbolSize16Bit; |
||
2492 | SaveOpSize = OpSize; |
||
2493 | OpSize = eSymbolSize16Bit; |
||
2494 | if (DecodeAdr(&ArgStr[3], MModReg, &CntAdrVals) == eModReg) |
||
2495 | { |
||
2496 | if (SaveOpSize == eSymbolSize32Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2497 | else |
||
2498 | { |
||
2499 | int Index = |
||
2500 | ChkRegOverlap((unsigned)DestAdrVals.Val, ((DestMode == eModIReg) ? AddrRegSize() : SaveOpSize), |
||
2501 | (unsigned)SrcAdrVals.Val, (int)AddrRegSize(), |
||
2502 | (unsigned)CntAdrVals.Val, (int)eSymbolSize16Bit, |
||
2503 | 0, eSymbolSizeUnknown); |
||
2504 | |||
2505 | if (Index >= 0) |
||
2506 | WrStrErrorPos(ErrNum_OverlapReg, &ArgStr[Index + 1]); |
||
2507 | AppendCode(0xba00 | (SaveOpSize << 8) | (SrcAdrVals.Val << 4) | Lo(Code)); |
||
2508 | AppendCode((CntAdrVals.Val << 8) | (DestAdrVals.Val << 4) | Condition); |
||
2509 | } |
||
2510 | } |
||
2511 | } |
||
2512 | } |
||
2513 | |||
2514 | /*!------------------------------------------------------------------------ |
||
2515 | * \fn DecodeINOUTRep(Word Code) |
||
2516 | * \brief decode string I/O instructions |
||
2517 | * \param Code instruction machine code |
||
2518 | * ------------------------------------------------------------------------ */ |
||
2519 | |||
2520 | static void DecodeINOUTRep(Word Code) |
||
2521 | { |
||
2522 | tAdrVals DestAdrVals, SrcAdrVals; |
||
2523 | Word IsOUT = Code & 0x20; |
||
2524 | |||
2525 | if (!SetOpSizeFromCode(Code) |
||
2526 | || !CheckSup(True) |
||
2527 | || !ChkArgCnt(3, 3)) |
||
2528 | return; |
||
2529 | |||
2530 | if (DecodeAdr(&ArgStr[1], MModIReg | (IsOUT ? MModIO : 0), &DestAdrVals) |
||
2531 | && DecodeAdr(&ArgStr[2], MModIReg | (IsOUT ? 0 : MModIO), &SrcAdrVals)) |
||
2532 | { |
||
2533 | tAdrVals CntAdrVals; |
||
2534 | tSymbolSize SaveOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
2535 | |||
2536 | OpSize = eSymbolSize16Bit; |
||
2537 | if (DecodeAdr(&ArgStr[3], MModReg, &CntAdrVals)) |
||
2538 | { |
||
2539 | AppendCode(0x3a00 | (SaveOpSize << 8) | (SrcAdrVals.Val << 4) | ((Code >> 4) & 15)); |
||
2540 | AppendCode((CntAdrVals.Val << 8) | (DestAdrVals.Val << 4) | (Code & 15)); |
||
2541 | } |
||
2542 | } |
||
2543 | } |
||
2544 | |||
2545 | /*!------------------------------------------------------------------------ |
||
2546 | * \fn DecodeLDRep(Word Code) |
||
2547 | * \brief decode string copy instructions |
||
2548 | * \param Code instruction machine code |
||
2549 | * ------------------------------------------------------------------------ */ |
||
2550 | |||
2551 | static void DecodeLDRep(Word Code) |
||
2552 | { |
||
2553 | tAdrVals DestAdrVals, SrcAdrVals; |
||
2554 | |||
2555 | if (!SetOpSizeFromCode(Code) |
||
2556 | || !ChkArgCnt(3, 3)) |
||
2557 | return; |
||
2558 | |||
2559 | if (DecodeAdr(&ArgStr[1], MModIReg, &DestAdrVals) |
||
2560 | && DecodeAdr(&ArgStr[2], MModIReg, &SrcAdrVals)) |
||
2561 | { |
||
2562 | tAdrVals CntAdrVals; |
||
2563 | tSymbolSize SaveOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
2564 | |||
2565 | OpSize = eSymbolSize16Bit; |
||
2566 | if (DecodeAdr(&ArgStr[3], MModReg, &CntAdrVals)) |
||
2567 | { |
||
2568 | AppendCode(0xba00 | (SaveOpSize << 8) | (SrcAdrVals.Val << 4) | ((Code >> 4) & 15)); |
||
2569 | AppendCode((CntAdrVals.Val << 8) | (DestAdrVals.Val << 4) | (Code & 15)); |
||
2570 | } |
||
2571 | } |
||
2572 | } |
||
2573 | |||
2574 | /*!------------------------------------------------------------------------ |
||
2575 | * \fn DecodeTRRep(Word Code) |
||
2576 | * \brief decode string translate instructions |
||
2577 | * \param Code instruction machine code |
||
2578 | * ------------------------------------------------------------------------ */ |
||
2579 | |||
2580 | static void DecodeTRRep(Word Code) |
||
2581 | { |
||
2582 | tAdrVals DestAdrVals, SrcAdrVals, CntAdrVals; |
||
2583 | |||
2584 | /* op size only applies to counter reg */ |
||
2585 | |||
2586 | OpSize = eSymbolSize16Bit; |
||
2587 | if (ChkArgCnt(3, 3) |
||
2588 | && DecodeAdr(&ArgStr[1], MModIReg, &DestAdrVals) |
||
2589 | && DecodeAdr(&ArgStr[2], MModIReg, &SrcAdrVals) |
||
2590 | && DecodeAdr(&ArgStr[3], MModReg, &CntAdrVals)) |
||
2591 | { |
||
2592 | Boolean OK = True; |
||
2593 | int Index; |
||
2594 | |||
2595 | /* R0/R1 in non-seg mode or RR0 in seg mode must not be used as src/dest. |
||
2596 | R1 should not be used as counter. |
||
2597 | This is only spelled out for TRDB, but due to the implicit usage of RH1 |
||
2598 | in all translate instructions, this restriction effectively applies to |
||
2599 | them all. |
||
2600 | Since (R)R0 is anyway not allowed for indirect addressing, this reduces |
||
2601 | to check fo R1: */ |
||
2602 | |||
2603 | if (!Segmented() && (DestAdrVals.Val == 1)) |
||
2604 | { |
||
2605 | WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]); |
||
2606 | OK = False; |
||
2607 | } |
||
2608 | if (!Segmented() && (SrcAdrVals.Val == 1)) |
||
2609 | { |
||
2610 | WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]); |
||
2611 | OK = False; |
||
2612 | } |
||
2613 | if (CntAdrVals.Val == 1) |
||
2614 | { |
||
2615 | WrStrErrorPos(ErrNum_InvReg, &ArgStr[3]); |
||
2616 | OK = False; |
||
2617 | } |
||
2618 | |||
2619 | Index = ChkRegOverlap((unsigned)DestAdrVals.Val, AddrRegSize(), |
||
2620 | (unsigned)SrcAdrVals.Val, (int)AddrRegSize(), |
||
2621 | (unsigned)CntAdrVals.Val, (int)eSymbolSize16Bit, |
||
2622 | 0, eSymbolSizeUnknown); |
||
2623 | if (Index >= 0) |
||
2624 | WrStrErrorPos(ErrNum_OverlapReg, &ArgStr[Index + 1]); |
||
2625 | |||
2626 | if (OK) |
||
2627 | { |
||
2628 | AppendCode(0xb800 | (DestAdrVals.Val << 4) | ((Code >> 4) & 15)); |
||
2629 | AppendCode((CntAdrVals.Val << 8) | (SrcAdrVals.Val << 4) | (Code & 15)); |
||
2630 | } |
||
2631 | } |
||
2632 | } |
||
2633 | |||
2634 | /*!------------------------------------------------------------------------ |
||
2635 | * \fn DecodeLDK(Word Code) |
||
2636 | * \brief decode LDK instruction |
||
2637 | * \param Code machine code |
||
2638 | * ------------------------------------------------------------------------ */ |
||
2639 | |||
2640 | static void DecodeLDK(Word Code) |
||
2641 | { |
||
2642 | tAdrVals DestAdrVals; |
||
2643 | |||
2644 | if (ChkArgCnt(2, 2) |
||
2645 | && DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals)) |
||
2646 | { |
||
2647 | Word Value; |
||
2648 | Boolean OK; |
||
2649 | |||
2650 | if (OpSize != eSymbolSize16Bit) |
||
2651 | { |
||
2652 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2653 | return; |
||
2654 | } |
||
2655 | Value = EvalStrIntExpressionOffs(&ArgStr[2], !!(*ArgStr[2].str.p_str == '#'), UInt4, &OK); |
||
2656 | if (OK) |
||
2657 | AppendCode(Code | (DestAdrVals.Val << 4) | Value); |
||
2658 | } |
||
2659 | } |
||
2660 | |||
2661 | /*!------------------------------------------------------------------------ |
||
2662 | * \fn DecodeLDM(Word Code) |
||
2663 | * \brief decode LDM instruction |
||
2664 | * \param Code machine code |
||
2665 | * ------------------------------------------------------------------------ */ |
||
2666 | |||
2667 | static void DecodeLDM(Word Code) |
||
2668 | { |
||
2669 | Word Count; |
||
2670 | tEvalResult EvalResult; |
||
2671 | tAdrVals RegAdrVals, MemAdrVals; |
||
2672 | int RegArgIndex; |
||
2673 | |||
2674 | if (!ChkArgCnt(3, 3)) |
||
2675 | return; |
||
2676 | |||
2677 | Count = DecodeImm1_16(&ArgStr[3], &EvalResult); |
||
2678 | if (!EvalResult.OK) |
||
2679 | return; |
||
2680 | |||
2681 | switch (DecodeAdr(&ArgStr[1], MModReg | MModIReg | MModDirect | MModIndexed, &RegAdrVals)) |
||
2682 | { |
||
2683 | case eModReg: |
||
2684 | RegArgIndex = 1; |
||
2685 | if (!DecodeAdr(&ArgStr[2], MModIReg | MModDirect | MModIndexed, &MemAdrVals)) |
||
2686 | return; |
||
2687 | goto common; |
||
2688 | case eModIReg: |
||
2689 | case eModDirect: |
||
2690 | case eModIndexed: |
||
2691 | MemAdrVals = RegAdrVals; |
||
2692 | Code |= 0x0008; |
||
2693 | if (!DecodeAdr(&ArgStr[2], MModReg, &RegAdrVals)) |
||
2694 | return; |
||
2695 | RegArgIndex = 2; |
||
2696 | /* fall-thru */ |
||
2697 | common: |
||
2698 | if (OpSize != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[RegArgIndex]); |
||
2699 | else |
||
2700 | { |
||
2701 | if (RegAdrVals.Val + Count >= 16) WrStrErrorPos(ErrNum_RegNumWraparound, &ArgStr[3]); |
||
2702 | switch (MemAdrVals.Mode) |
||
2703 | { |
||
2704 | case eModIReg: |
||
2705 | AppendCode(Code | (MemAdrVals.Val << 4)); |
||
2706 | AppendCode((RegAdrVals.Val << 8) | Count); |
||
2707 | break; |
||
2708 | case eModDirect: |
||
2709 | case eModIndexed: |
||
2710 | AppendCode(Code | 0x4000 | (MemAdrVals.Val << 4)); |
||
2711 | AppendCode((RegAdrVals.Val << 8) | Count); |
||
2712 | AppendAdrVals(&MemAdrVals); |
||
2713 | break; |
||
2714 | default: |
||
2715 | break; |
||
2716 | } |
||
2717 | } |
||
2718 | break; |
||
2719 | default: |
||
2720 | break; |
||
2721 | } |
||
2722 | } |
||
2723 | |||
2724 | /*!------------------------------------------------------------------------ |
||
2725 | * \fn DecodeLDPS(Word Code) |
||
2726 | * \brief decode LDPS instruction |
||
2727 | * \param Code machine code |
||
2728 | * ------------------------------------------------------------------------ */ |
||
2729 | |||
2730 | static void DecodeLDPS(Word Code) |
||
2731 | { |
||
2732 | tAdrVals AdrVals; |
||
2733 | |||
2734 | if (ChkArgCnt(1, 1) |
||
2735 | && CheckSup(True)) |
||
2736 | switch (DecodeAdr(&ArgStr[1], MModIReg | MModDirect | MModIndexed, &AdrVals)) |
||
2737 | { |
||
2738 | case eModIReg: |
||
2739 | AppendCode(Code | 0x0000 | (AdrVals.Val << 4)); |
||
2740 | break; |
||
2741 | case eModDirect: |
||
2742 | case eModIndexed: |
||
2743 | AppendCode(Code | 0x4000 | (AdrVals.Val << 4)); |
||
2744 | AppendAdrVals(&AdrVals); |
||
2745 | break; |
||
2746 | default: |
||
2747 | break; |
||
2748 | } |
||
2749 | } |
||
2750 | |||
2751 | /*!------------------------------------------------------------------------ |
||
2752 | * \fn DecodeMREQ(Word Code) |
||
2753 | * \brief decode MREQ instruction |
||
2754 | * \param Code instruction code |
||
2755 | * ------------------------------------------------------------------------ */ |
||
2756 | |||
2757 | static void DecodeMREQ(Word Code) |
||
2758 | { |
||
2759 | tAdrVals AdrVals; |
||
2760 | |||
2761 | SetOpSize(eSymbolSize16Bit, &OpPart); |
||
2762 | if (ChkArgCnt(1, 1) |
||
2763 | && CheckSup(True) |
||
2764 | && DecodeAdr(&ArgStr[1], MModReg, &AdrVals)) |
||
2765 | AppendCode(Code | (AdrVals.Val << 4)); |
||
2766 | } |
||
2767 | |||
2768 | /*!------------------------------------------------------------------------ |
||
2769 | * \fn DecodePUSH_POP(Word Code) |
||
2770 | * \brief decode PUSH(L)/POP(L) |
||
2771 | * \param Code machine code & size |
||
2772 | * ------------------------------------------------------------------------ */ |
||
2773 | |||
2774 | static void DecodePUSH_POP(Word Code) |
||
2775 | { |
||
2776 | tAdrVals RegAdrVals; |
||
2777 | Word IsPOP = Code & 0x04; |
||
2778 | int OpArg = !IsPOP + 1, RegArg = 3 - OpArg; |
||
2779 | |||
2780 | if (SetOpSizeFromCode(Code) |
||
2781 | && ChkArgCnt(2, 2) |
||
2782 | && DecodeAdr(&ArgStr[RegArg], MModIReg, &RegAdrVals)) |
||
2783 | { |
||
2784 | tAdrVals OpAdrVals; |
||
2785 | |||
2786 | ImmOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
2787 | if (DecodeAdr(&ArgStr[OpArg], MModReg | MModIReg | MModDirect | MModIndexed | (IsPOP ? 0 : MModImm), &OpAdrVals)) |
||
2788 | { |
||
2789 | int Index; |
||
2790 | |||
2791 | if (OpSize == eSymbolSizeUnknown) |
||
2792 | OpSize = eSymbolSize16Bit; |
||
2793 | if ((OpSize < eSymbolSize16Bit) || (OpSize > eSymbolSize32Bit)) |
||
2794 | { |
||
2795 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[OpArg]); |
||
2796 | return; |
||
2797 | } |
||
2798 | switch (OpAdrVals.Mode) |
||
2799 | { |
||
2800 | case eModReg: |
||
2801 | Index = ChkRegOverlap((unsigned)OpAdrVals.Val, OpSize, |
||
2802 | (unsigned)RegAdrVals.Val, (int)AddrRegSize(), |
||
2803 | 0, eSymbolSizeUnknown); |
||
2804 | break; |
||
2805 | case eModIReg: |
||
2806 | Index = ChkRegOverlap((unsigned)OpAdrVals.Val, AddrRegSize(), |
||
2807 | (unsigned)RegAdrVals.Val, (int)AddrRegSize(), |
||
2808 | 0, eSymbolSizeUnknown); |
||
2809 | break; |
||
2810 | case eModIndexed: |
||
2811 | Index = ChkRegOverlap((unsigned)OpAdrVals.Val, eSymbolSize16Bit, |
||
2812 | (unsigned)RegAdrVals.Val, (int)AddrRegSize(), |
||
2813 | 0, eSymbolSizeUnknown); |
||
2814 | break; |
||
2815 | default: |
||
2816 | Index = -1; |
||
2817 | break; |
||
2818 | } |
||
2819 | if (Index >= 0) |
||
2820 | WrStrErrorPos(ErrNum_OverlapReg, &ArgStr[Index ? RegArg : OpArg]); |
||
2821 | Code = Lo(Code) | ((OpSize == eSymbolSize16Bit) ? 2 : 0); |
||
2822 | switch (OpAdrVals.Mode) |
||
2823 | { |
||
2824 | case eModImm: |
||
2825 | if (OpSize != eSymbolSize16Bit) WrStrErrorPos(ErrNum_InvOpSize, &OpPart); |
||
2826 | else |
||
2827 | { |
||
2828 | AppendCode(0x0d09 | (RegAdrVals.Val << 4)); |
||
2829 | AppendAdrVals(&OpAdrVals); |
||
2830 | } |
||
2831 | break; |
||
2832 | case eModReg: |
||
2833 | AppendCode(0x8000 | (Code << 8) | (RegAdrVals.Val << 4) | OpAdrVals.Val); |
||
2834 | break; |
||
2835 | case eModIReg: |
||
2836 | AppendCode(0x0000 | (Code << 8) | (RegAdrVals.Val << 4) | OpAdrVals.Val); |
||
2837 | break; |
||
2838 | case eModDirect: |
||
2839 | case eModIndexed: |
||
2840 | AppendCode(0x4000 | (Code << 8) | (RegAdrVals.Val << 4) | OpAdrVals.Val); |
||
2841 | AppendAdrVals(&OpAdrVals); |
||
2842 | break; |
||
2843 | default: |
||
2844 | break; |
||
2845 | } |
||
2846 | } |
||
2847 | } |
||
2848 | } |
||
2849 | |||
2850 | /*!------------------------------------------------------------------------ |
||
2851 | * \fn DecodeRET(Word Code) |
||
2852 | * \brief decode RET instruction |
||
2853 | * \param Code machine code |
||
2854 | * ------------------------------------------------------------------------ */ |
||
2855 | |||
2856 | static void DecodeRET(Word Code) |
||
2857 | { |
||
2858 | Word Condition; |
||
2859 | |||
2860 | if (ChkArgCnt(0, 1) |
||
2861 | && DecodeCondition((ArgCnt >= 1) ? &ArgStr[1] : NULL, &Condition)) |
||
2862 | AppendCode(Code | Condition); |
||
2863 | } |
||
2864 | |||
2865 | /*!------------------------------------------------------------------------ |
||
2866 | * \fn DecodeRotate(Word Code) |
||
2867 | * \brief handle rotate instructions |
||
2868 | * \param Code machine code |
||
2869 | * ------------------------------------------------------------------------ */ |
||
2870 | |||
2871 | static void DecodeRotate(Word Code) |
||
2872 | { |
||
2873 | tAdrVals RegAdrVals; |
||
2874 | |||
2875 | if (ChkArgCnt(1, 2) |
||
2876 | && SetOpSizeFromCode(Code) |
||
2877 | && DecodeAdr(&ArgStr[1], MModReg, &RegAdrVals)) |
||
2878 | { |
||
2879 | Word Count = 1; |
||
2880 | tEvalResult EvalResult; |
||
2881 | |||
2882 | if (OpSize > eSymbolSize16Bit) |
||
2883 | { |
||
2884 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2885 | return; |
||
2886 | } |
||
2887 | if (ArgCnt >= 2) |
||
2888 | { |
||
2889 | Count = EvalStrIntExpressionOffsWithResult(&ArgStr[2], !!(*ArgStr[2].str.p_str == '#'), UInt2, &EvalResult); |
||
2890 | if (EvalResult.OK && mFirstPassUnknownOrQuestionable(EvalResult.Flags)) |
||
2891 | Count = 1; |
||
2892 | } |
||
2893 | if (ChkRange(Count, 1, 2)) |
||
2894 | AppendCode(0xb200 | (OpSize << 8) | (RegAdrVals.Val << 4) | Lo(Code) | ((Count - 1) << 1)); |
||
2895 | } |
||
2896 | } |
||
2897 | |||
2898 | /*!------------------------------------------------------------------------ |
||
2899 | * \fn DecodeRotateDigit(Word Code) |
||
2900 | * \brief decode nibble-wide rotates |
||
2901 | * \param Code machine code |
||
2902 | * ------------------------------------------------------------------------ */ |
||
2903 | |||
2904 | static void DecodeRotateDigit(Word Code) |
||
2905 | { |
||
2906 | tAdrVals LinkAdrVals, SrcAdrVals; |
||
2907 | |||
2908 | SetOpSize(eSymbolSize8Bit, &OpPart); |
||
2909 | if (ChkArgCnt(2, 2) |
||
2910 | && DecodeAdr(&ArgStr[1], MModReg, &LinkAdrVals) |
||
2911 | && DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals)) |
||
2912 | AppendCode(Code | (SrcAdrVals.Val << 4) | LinkAdrVals.Val); |
||
2913 | } |
||
2914 | |||
2915 | /*!------------------------------------------------------------------------ |
||
2916 | * \fn DecodeSC(Word Code) |
||
2917 | * \brief decode SC instruction |
||
2918 | * \param Code machine code |
||
2919 | * ------------------------------------------------------------------------ */ |
||
2920 | |||
2921 | static void DecodeSC(Word Code) |
||
2922 | { |
||
2923 | if (ChkArgCnt(1, 1)) |
||
2924 | { |
||
2925 | Boolean OK; |
||
2926 | Word Arg = EvalStrIntExpressionOffs(&ArgStr[1], !!(*ArgStr[1].str.p_str == '#'), Int8, &OK); |
||
2927 | |||
2928 | if (OK) |
||
2929 | AppendCode(Code | (Arg & 0xff)); |
||
2930 | } |
||
2931 | } |
||
2932 | |||
2933 | /*!------------------------------------------------------------------------ |
||
2934 | * \fn DecodeSD(Word Code) |
||
2935 | * \brief decode dynamic shifts |
||
2936 | * \param Code machine code |
||
2937 | * ------------------------------------------------------------------------ */ |
||
2938 | |||
2939 | static void DecodeSD(Word Code) |
||
2940 | { |
||
2941 | tAdrVals DestAdrVals; |
||
2942 | |||
2943 | if (ChkArgCnt(2, 2) |
||
2944 | && SetOpSizeFromCode(Code) |
||
2945 | && DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals)) |
||
2946 | { |
||
2947 | tAdrVals SrcAdrVals; |
||
2948 | tSymbolSize SaveOpSize = (OpSize == eSymbolSizeUnknown) ? eSymbolSize16Bit : OpSize; |
||
2949 | |||
2950 | if (SaveOpSize > eSymbolSize32Bit) |
||
2951 | { |
||
2952 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2953 | return; |
||
2954 | } |
||
2955 | OpSize = eSymbolSize16Bit; |
||
2956 | if (DecodeAdr(&ArgStr[2], MModReg, &SrcAdrVals)) |
||
2957 | { |
||
2958 | AppendCode(0xb200 | (((SaveOpSize == eSymbolSize32Bit) ? 1 : SaveOpSize) << 8) | (DestAdrVals.Val << 4) | Lo(Code) | (SaveOpSize == eSymbolSize32Bit ? 4 : 0)); |
||
2959 | AppendCode(SrcAdrVals.Val << 8); |
||
2960 | } |
||
2961 | } |
||
2962 | } |
||
2963 | |||
2964 | /*!------------------------------------------------------------------------ |
||
2965 | * \fn DecodeShift(Word Code) |
||
2966 | * \brief decode statuc shifts |
||
2967 | * \param Code machine code |
||
2968 | * ------------------------------------------------------------------------ */ |
||
2969 | |||
2970 | static void DecodeShift(Word Code) |
||
2971 | { |
||
2972 | tAdrVals DestAdrVals; |
||
2973 | |||
2974 | if (ChkArgCnt(1, 2) |
||
2975 | && SetOpSizeFromCode(Code) |
||
2976 | && DecodeAdr(&ArgStr[1], MModReg, &DestAdrVals)) |
||
2977 | { |
||
2978 | Word Count; |
||
2979 | Word Negate = Code & 0x80; |
||
2980 | |||
2981 | if (OpSize == eSymbolSizeUnknown) |
||
2982 | OpSize = eSymbolSize16Bit; |
||
2983 | if (OpSize > eSymbolSize32Bit) |
||
2984 | { |
||
2985 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[1]); |
||
2986 | return; |
||
2987 | } |
||
2988 | |||
2989 | if (ArgCnt >= 2) |
||
2990 | { |
||
2991 | tEvalResult EvalResult; |
||
2992 | |||
2993 | Count = EvalStrIntExpressionOffsWithResult(&ArgStr[2], !!(*ArgStr[2].str.p_str == '#'), (OpSize == eSymbolSize32Bit) ? UInt6 : (OpSize == eSymbolSize16Bit) ? UInt5 : UInt4, &EvalResult); |
||
2994 | if (mFirstPassUnknownOrQuestionable(EvalResult.Flags)) |
||
2995 | Count = 1; |
||
2996 | if (!ChkRange(Count, Negate ? 1 : 0, 8 << OpSize)) |
||
2997 | return; |
||
2998 | } |
||
2999 | else |
||
3000 | Count = 1; |
||
3001 | |||
3002 | if (Negate) |
||
3003 | { |
||
3004 | Code ^= Negate; |
||
3005 | Count = 0x10000ul - Count; |
||
3006 | if (OpSize == eSymbolSize8Bit) |
||
3007 | Count &= 0xff; |
||
3008 | } |
||
3009 | AppendCode(0xb200 | (((OpSize == eSymbolSize32Bit) ? 1 : OpSize) << 8) | (DestAdrVals.Val << 4) | Lo(Code) | (OpSize == eSymbolSize32Bit ? 4 : 0)); |
||
3010 | AppendCode(Count); |
||
3011 | } |
||
3012 | } |
||
3013 | |||
3014 | /*!------------------------------------------------------------------------ |
||
3015 | * \fn DecodeTCC(Word Code) |
||
3016 | * \brief decode TCC instruction |
||
3017 | * \param Code machine code |
||
3018 | * ------------------------------------------------------------------------ */ |
||
3019 | |||
3020 | static void DecodeTCC(Word Code) |
||
3021 | { |
||
3022 | Word Condition; |
||
3023 | tAdrVals DestAdrVals; |
||
3024 | |||
3025 | if (ChkArgCnt(1, 2) |
||
3026 | && SetOpSizeFromCode(Code) |
||
3027 | && DecodeCondition((ArgCnt == 2) ? &ArgStr[1] : NULL, &Condition) |
||
3028 | && DecodeAdr(&ArgStr[ArgCnt], MModReg, &DestAdrVals)) |
||
3029 | { |
||
3030 | if (OpSize > eSymbolSize16Bit) |
||
3031 | { |
||
3032 | WrStrErrorPos(ErrNum_InvOpSize, &ArgStr[2]); |
||
3033 | return; |
||
3034 | } |
||
3035 | AppendCode(0xae00 | (OpSize << 8) | (DestAdrVals.Val << 4) | Condition); |
||
3036 | } |
||
3037 | } |
||
3038 | |||
3039 | /*!------------------------------------------------------------------------ |
||
3040 | * \fn DecodePORT(Word Code) |
||
3041 | * \brief decode PORT instruction |
||
3042 | * ------------------------------------------------------------------------ */ |
||
3043 | |||
3044 | static void DecodePORT(Word Code) |
||
3045 | { |
||
3046 | UNUSED(Code); |
||
3047 | CodeEquate(SegIO, 0, SegLimits[SegIO]); |
||
3048 | } |
||
3049 | |||
3050 | /*!------------------------------------------------------------------------ |
||
3051 | * \fn DecodeDEFBIT(Word Code) |
||
3052 | * \brief decode DEFBIT(B) instructions |
||
3053 | * \param Code machine code |
||
3054 | * ------------------------------------------------------------------------ */ |
||
3055 | |||
3056 | static void DecodeDEFBIT(Word Code) |
||
3057 | { |
||
3058 | LongWord BitSpec; |
||
3059 | |||
3060 | OpSize = (tSymbolSize)Code; |
||
3061 | |||
3062 | /* if in structure definition, add special element to structure */ |
||
3063 | |||
3064 | if (ActPC == StructSeg) |
||
3065 | { |
||
3066 | Boolean OK; |
||
3067 | Byte BitPos; |
||
3068 | PStructElem pElement; |
||
3069 | |||
3070 | if (!ChkArgCnt(2, 2)) |
||
3071 | return; |
||
3072 | BitPos = EvalBitPosition(&ArgStr[2], &OK, OpSize); |
||
3073 | if (!OK) |
||
3074 | return; |
||
3075 | pElement = CreateStructElem(&LabPart); |
||
3076 | if (!pElement) |
||
3077 | return; |
||
3078 | pElement->pRefElemName = as_strdup(ArgStr[1].str.p_str); |
||
3079 | pElement->OpSize = OpSize; |
||
3080 | pElement->BitPos = BitPos; |
||
3081 | pElement->ExpandFnc = ExpandZ8000Bit; |
||
3082 | AddStructElem(pInnermostNamedStruct->StructRec, pElement); |
||
3083 | } |
||
3084 | else |
||
3085 | { |
||
3086 | if (DecodeBitArg(&BitSpec, 1, ArgCnt, OpSize)) |
||
3087 | { |
||
3088 | *ListLine = '='; |
||
3089 | DissectBit_Z8000(ListLine + 1, STRINGSIZE - 3, BitSpec); |
||
3090 | PushLocHandle(-1); |
||
3091 | EnterIntSymbol(&LabPart, BitSpec, SegBData, False); |
||
3092 | PopLocHandle(); |
||
3093 | /* TODO: MakeUseList? */ |
||
3094 | } |
||
3095 | } |
||
3096 | } |
||
3097 | |||
3098 | /*--------------------------------------------------------------------------*/ |
||
3099 | /* Instruction Table Buildup/Teardown */ |
||
3100 | |||
3101 | /*!------------------------------------------------------------------------ |
||
3102 | * \fn InitFields(void) |
||
3103 | * \brief Set up hash table |
||
3104 | * ------------------------------------------------------------------------ */ |
||
3105 | |||
3106 | static void AddFixed(const char *NName, Word Code, Boolean Privileged) |
||
3107 | { |
||
3108 | order_array_rsv_end(FixedOrders, FixedOrder); |
||
3109 | FixedOrders[InstrZ].Code = Code; |
||
3110 | FixedOrders[InstrZ].Privileged = Privileged; |
||
3111 | AddInstTable(InstTable, NName, InstrZ++, DecodeFixed); |
||
3112 | } |
||
3113 | |||
3114 | static void AddCtl(const char *pName, Word Code, tCtlFlags Flags, tSymbolSize Size) |
||
3115 | { |
||
3116 | order_array_rsv_end(CtlRegs, tCtlReg); |
||
3117 | CtlRegs[InstrZ ].pName = pName; |
||
3118 | CtlRegs[InstrZ ].Code = Code; |
||
3119 | CtlRegs[InstrZ ].Flags = Flags; |
||
3120 | CtlRegs[InstrZ++].Size = Size; |
||
3121 | } |
||
3122 | |||
3123 | static void AddCondition(const char *pName, Word Code) |
||
3124 | { |
||
3125 | order_array_rsv_end(Conditions, tCondition); |
||
3126 | Conditions[InstrZ].pName = pName; |
||
3127 | Conditions[InstrZ++].Code = Code; |
||
3128 | } |
||
3129 | |||
3130 | static void AddSizeInstTable(const char *pName, unsigned SizeMask, Word Code, InstProc Proc) |
||
3131 | { |
||
3132 | char Name[20]; |
||
3133 | |||
3134 | AddInstTable(InstTable, pName, Code | 0xff00, Proc); |
||
3135 | if (SizeMask & (1 << eSymbolSize8Bit)) |
||
3136 | { |
||
3137 | as_snprintf(Name, sizeof(Name), "%sB", pName); |
||
3138 | AddInstTable(InstTable, Name, Code | (eSymbolSize8Bit << 8), Proc); |
||
3139 | } |
||
3140 | if (SizeMask & (1 << eSymbolSize32Bit)) |
||
3141 | { |
||
3142 | as_snprintf(Name, sizeof(Name), "%sL", pName); |
||
3143 | AddInstTable(InstTable, Name, Code | (eSymbolSize32Bit << 8), Proc); |
||
3144 | } |
||
3145 | } |
||
3146 | |||
3147 | static void InitFields(void) |
||
3148 | { |
||
3149 | InstTable = CreateInstTable(302); |
||
3150 | SetDynamicInstTable(InstTable); |
||
3151 | |||
3152 | add_null_pseudo(InstTable); |
||
3153 | |||
3154 | InstrZ = 0; |
||
3155 | AddFixed("HALT" , 0x7a00 , True ); |
||
3156 | AddFixed("IRET" , 0x7b00 , True ); |
||
3157 | AddFixed("MBIT" , 0x7b0a , True ); |
||
3158 | AddFixed("MRES" , 0x7b09 , True ); |
||
3159 | AddFixed("MSET" , 0x7b08 , True ); |
||
3160 | AddFixed("NOP" , NOPCode, False); |
||
3161 | |||
3162 | InstrZ = 0; |
||
3163 | AddCtl("FCW" , 2, ePrivileged | eSegMode | eNonSegMode , eSymbolSize16Bit); |
||
3164 | AddCtl("REFRESH" , 3, ePrivileged | eSegMode | eNonSegMode , eSymbolSize16Bit); |
||
3165 | AddCtl("PSAPSEG" , 4, ePrivileged | eSegMode , eSymbolSize16Bit); |
||
3166 | AddCtl("PSAPOFF" , 5, ePrivileged | eSegMode | eNonSegMode , eSymbolSize16Bit); |
||
3167 | AddCtl("PSAP" , 5, ePrivileged | eNonSegMode , eSymbolSize16Bit); |
||
3168 | AddCtl("NSPSEG" , 6, ePrivileged | eSegMode , eSymbolSize16Bit); |
||
3169 | AddCtl("NSPOFF" , 7, ePrivileged | eSegMode | eNonSegMode , eSymbolSize16Bit); |
||
3170 | AddCtl("NSP" , 7, ePrivileged | eNonSegMode , eSymbolSize16Bit); |
||
3171 | AddCtl("FLAGS" , 1, eSegMode | eNonSegMode , eSymbolSize8Bit ); |
||
3172 | CtlRegCnt = InstrZ; |
||
3173 | |||
3174 | InstrZ = 0; |
||
3175 | AddCondition("" , 0x08); |
||
3176 | AddCondition("F" , 0x00); |
||
3177 | AddCondition("LT" , 0x01); |
||
3178 | AddCondition("LE" , 0x02); |
||
3179 | AddCondition("ULE", 0x03); |
||
3180 | AddCondition("PE" , 0x04); |
||
3181 | AddCondition("MI" , 0x05); |
||
3182 | AddCondition("Z" , 0x06); |
||
3183 | AddCondition("ULT", 0x07); |
||
3184 | AddCondition("GE" , 0x09); |
||
3185 | AddCondition("GT" , 0x0a); |
||
3186 | AddCondition("UGT", 0x0b); |
||
3187 | AddCondition("PO" , 0x0c); |
||
3188 | AddCondition("PL" , 0x0d); |
||
3189 | AddCondition("NZ" , 0x0e); |
||
3190 | AddCondition("UGE", 0x0f); |
||
3191 | AddCondition("OV" , 0x04); |
||
3192 | AddCondition("EQ" , 0x06); |
||
3193 | AddCondition("C" , 0x07); |
||
3194 | AddCondition("NOV", 0x0c); |
||
3195 | AddCondition("NE" , 0x0e); |
||
3196 | AddCondition("NC" , 0x0f); |
||
3197 | |||
3198 | /* non-Zilog conditions */ |
||
3199 | |||
3200 | AddCondition("ZR" , 0x06); |
||
3201 | AddCondition("CY" , 0x07); |
||
3202 | AddCondition("LLE", 0x03); |
||
3203 | AddCondition("LLT", 0x07); |
||
3204 | AddCondition("LGT", 0x0b); |
||
3205 | AddCondition("LGE", 0x0f); |
||
3206 | AddCondition(NULL , 0); |
||
3207 | |||
3208 | |||
3209 | AddSizeInstTable("LD" , (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0, DecodeLD); |
||
3210 | AddInstTable(InstTable, "LDA" , 0, DecodeLDA); |
||
3211 | AddInstTable(InstTable, "LDAR", 0x3400, DecodeLDAR); |
||
3212 | AddInstTable(InstTable, "LDK" , 0xbd00, DecodeLDK); |
||
3213 | AddInstTable(InstTable, "LDM" , 0x1c01, DecodeLDM); |
||
3214 | AddInstTable(InstTable, "LDPS", 0x3900, DecodeLDPS); |
||
3215 | AddSizeInstTable("LDR", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x30, DecodeLDR); |
||
3216 | AddSizeInstTable("LDCTL", 1 << eSymbolSize8Bit, 0x00, DecodeLDCTL); |
||
3217 | AddSizeInstTable("ADD" , (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0, DecodeADD); |
||
3218 | AddSizeInstTable("SUB" , (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0, DecodeSUB); |
||
3219 | AddSizeInstTable("CP" , (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0, DecodeCP); |
||
3220 | AddSizeInstTable("ADC" , 1 << eSymbolSize8Bit, 0x34, DecodeADC_SBC); |
||
3221 | AddSizeInstTable("SBC" , 1 << eSymbolSize8Bit, 0x36, DecodeADC_SBC); |
||
3222 | AddSizeInstTable("AND" , 1 << eSymbolSize8Bit, 0x06, DecodeAND_OR_XOR); |
||
3223 | AddSizeInstTable("OR" , 1 << eSymbolSize8Bit, 0x04, DecodeAND_OR_XOR); |
||
3224 | AddSizeInstTable("XOR" , 1 << eSymbolSize8Bit, 0x08, DecodeAND_OR_XOR); |
||
3225 | AddSizeInstTable("INC" , 1 << eSymbolSize8Bit, 0x28, DecodeINC_DEC); |
||
3226 | AddSizeInstTable("DEC" , 1 << eSymbolSize8Bit, 0x2a, DecodeINC_DEC); |
||
3227 | AddSizeInstTable("BIT" , 1 << eSymbolSize8Bit, 0x26, DecodeBitOp); |
||
3228 | AddSizeInstTable("DIV" , 1 << eSymbolSize32Bit, 0x1a, DecodeMULT_DIV); |
||
3229 | AddSizeInstTable("MULT", 1 << eSymbolSize32Bit, 0x18, DecodeMULT_DIV); |
||
3230 | AddSizeInstTable("RES" , 1 << eSymbolSize8Bit, 0x22, DecodeBitOp); |
||
3231 | AddSizeInstTable("SET" , 1 << eSymbolSize8Bit, 0x24, DecodeBitOp); |
||
3232 | AddInstTable(InstTable, "CALL", 0x1f, DecodeCALL_JP); |
||
3233 | AddInstTable(InstTable, "JP" , 0x1e, DecodeCALL_JP); |
||
3234 | AddInstTable(InstTable, "CALR", 0xd000, DecodeCALR); |
||
3235 | AddInstTable(InstTable, "JR" , 0xe000, DecodeJR); |
||
3236 | AddInstTable(InstTable, "DJNZ" , 0xff00, DecodeDJNZ); |
||
3237 | AddInstTable(InstTable, "DBJNZ", eSymbolSize8Bit << 8, DecodeDJNZ); |
||
3238 | AddInstTable(InstTable, "RET", 0x9e00, DecodeRET); |
||
3239 | AddSizeInstTable("CLR" , 1 << eSymbolSize8Bit, 0x8c, DecodeCLR_COM_NEG_TSET); |
||
3240 | AddSizeInstTable("COM" , 1 << eSymbolSize8Bit, 0x0c, DecodeCLR_COM_NEG_TSET); |
||
3241 | AddSizeInstTable("NEG" , 1 << eSymbolSize8Bit, 0x2c, DecodeCLR_COM_NEG_TSET); |
||
3242 | AddSizeInstTable("TSET", 1 << eSymbolSize8Bit, 0x6c, DecodeCLR_COM_NEG_TSET); |
||
3243 | AddSizeInstTable("TEST", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x0c, DecodeTEST); |
||
3244 | AddSizeInstTable("EX", 1 << eSymbolSize8Bit, 0x2c, DecodeEX); |
||
3245 | AddSizeInstTable("EXTS", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x31, DecodeEXTS); |
||
3246 | AddInstTable(InstTable, "DAB", 0xb000, DecodeDAB); |
||
3247 | AddInstTable(InstTable, "COMFLG", 0x8d05, DecodeFLG); |
||
3248 | AddInstTable(InstTable, "SETFLG", 0x8d01, DecodeFLG); |
||
3249 | AddInstTable(InstTable, "RESFLG", 0x8d03, DecodeFLG); |
||
3250 | AddInstTable(InstTable, "DI", 0x7c00, DecodeDI_EI); |
||
3251 | AddInstTable(InstTable, "EI", 0x7c04, DecodeDI_EI); |
||
3252 | AddInstTable(InstTable, "MREQ", 0x7b0d, DecodeMREQ); |
||
3253 | AddSizeInstTable("IN" , 1 << eSymbolSize8Bit, 0x00, DecodeIN_SIN_OUT_SOUT); |
||
3254 | AddSizeInstTable("SIN" , 1 << eSymbolSize8Bit, 0x01, DecodeIN_SIN_OUT_SOUT); |
||
3255 | AddSizeInstTable("OUT" , 1 << eSymbolSize8Bit, 0x02, DecodeIN_SIN_OUT_SOUT); |
||
3256 | AddSizeInstTable("SOUT", 1 << eSymbolSize8Bit, 0x03, DecodeIN_SIN_OUT_SOUT); |
||
3257 | AddSizeInstTable("CPD" , 1 << eSymbolSize8Bit, 0x08, DecodeCPRep); |
||
3258 | AddSizeInstTable("CPDR" , 1 << eSymbolSize8Bit, 0x0c, DecodeCPRep); |
||
3259 | AddSizeInstTable("CPI" , 1 << eSymbolSize8Bit, 0x00, DecodeCPRep); |
||
3260 | AddSizeInstTable("CPIR" , 1 << eSymbolSize8Bit, 0x04, DecodeCPRep); |
||
3261 | AddSizeInstTable("CPSD" , 1 << eSymbolSize8Bit, 0x0a, DecodeCPRep); |
||
3262 | AddSizeInstTable("CPSDR", 1 << eSymbolSize8Bit, 0x0e, DecodeCPRep); |
||
3263 | AddSizeInstTable("CPSI" , 1 << eSymbolSize8Bit, 0x02, DecodeCPRep); |
||
3264 | AddSizeInstTable("CPSIR", 1 << eSymbolSize8Bit, 0x06, DecodeCPRep); |
||
3265 | AddSizeInstTable("IND" , 1 << eSymbolSize8Bit, 0x88, DecodeINOUTRep); |
||
3266 | AddSizeInstTable("INDR" , 1 << eSymbolSize8Bit, 0x80, DecodeINOUTRep); |
||
3267 | AddSizeInstTable("SIND" , 1 << eSymbolSize8Bit, 0x98, DecodeINOUTRep); |
||
3268 | AddSizeInstTable("SINDR", 1 << eSymbolSize8Bit, 0x90, DecodeINOUTRep); |
||
3269 | AddSizeInstTable("INI" , 1 << eSymbolSize8Bit, 0x08, DecodeINOUTRep); |
||
3270 | AddSizeInstTable("INIR" , 1 << eSymbolSize8Bit, 0x00, DecodeINOUTRep); |
||
3271 | AddSizeInstTable("SINI" , 1 << eSymbolSize8Bit, 0x18, DecodeINOUTRep); |
||
3272 | AddSizeInstTable("SINIR", 1 << eSymbolSize8Bit, 0x10, DecodeINOUTRep); |
||
3273 | AddSizeInstTable("OUTD" , 1 << eSymbolSize8Bit, 0xa8, DecodeINOUTRep); |
||
3274 | AddSizeInstTable("OTDR" , 1 << eSymbolSize8Bit, 0xa0, DecodeINOUTRep); |
||
3275 | AddSizeInstTable("SOUTD", 1 << eSymbolSize8Bit, 0xb8, DecodeINOUTRep); |
||
3276 | AddSizeInstTable("SOTDR", 1 << eSymbolSize8Bit, 0xb0, DecodeINOUTRep); |
||
3277 | AddSizeInstTable("OUTI" , 1 << eSymbolSize8Bit, 0x28, DecodeINOUTRep); |
||
3278 | AddSizeInstTable("OTIR" , 1 << eSymbolSize8Bit, 0x20, DecodeINOUTRep); |
||
3279 | AddSizeInstTable("SOUTI", 1 << eSymbolSize8Bit, 0x38, DecodeINOUTRep); |
||
3280 | AddSizeInstTable("SOTIR", 1 << eSymbolSize8Bit, 0x30, DecodeINOUTRep); |
||
3281 | AddSizeInstTable("LDD" , 1 << eSymbolSize8Bit, 0x98, DecodeLDRep); |
||
3282 | AddSizeInstTable("LDDR" , 1 << eSymbolSize8Bit, 0x90, DecodeLDRep); |
||
3283 | AddSizeInstTable("LDI" , 1 << eSymbolSize8Bit, 0x18, DecodeLDRep); |
||
3284 | AddSizeInstTable("LDIR" , 1 << eSymbolSize8Bit, 0x10, DecodeLDRep); |
||
3285 | AddInstTable(InstTable, "TRDB" , 0x80, DecodeTRRep); |
||
3286 | AddInstTable(InstTable, "TRDRB" , 0xc0, DecodeTRRep); |
||
3287 | AddInstTable(InstTable, "TRIB" , 0x00, DecodeTRRep); |
||
3288 | AddInstTable(InstTable, "TRIRB" , 0x40, DecodeTRRep); |
||
3289 | AddInstTable(InstTable, "TRTDB" , 0xa0, DecodeTRRep); |
||
3290 | AddInstTable(InstTable, "TRTDRB", 0xee, DecodeTRRep); |
||
3291 | AddInstTable(InstTable, "TRTIB" , 0x20, DecodeTRRep); |
||
3292 | AddInstTable(InstTable, "TRTIRB", 0x6e, DecodeTRRep); |
||
3293 | AddSizeInstTable("POP" , 1 << eSymbolSize32Bit, 0x15, DecodePUSH_POP); |
||
3294 | AddSizeInstTable("PUSH" , 1 << eSymbolSize32Bit, 0x11, DecodePUSH_POP); |
||
3295 | AddSizeInstTable("RL" , 1 << eSymbolSize8Bit, 0x00, DecodeRotate); |
||
3296 | AddSizeInstTable("RLC" , 1 << eSymbolSize8Bit, 0x08, DecodeRotate); |
||
3297 | AddSizeInstTable("RR" , 1 << eSymbolSize8Bit, 0x04, DecodeRotate); |
||
3298 | AddSizeInstTable("RRC" , 1 << eSymbolSize8Bit, 0x0c, DecodeRotate); |
||
3299 | AddInstTable(InstTable, "RLDB" , 0xbe00, DecodeRotateDigit); |
||
3300 | AddInstTable(InstTable, "RRDB" , 0xbc00, DecodeRotateDigit); |
||
3301 | AddSizeInstTable("SDA", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x0b, DecodeSD); |
||
3302 | AddSizeInstTable("SDL", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x03, DecodeSD); |
||
3303 | AddSizeInstTable("SLA", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x09, DecodeShift); |
||
3304 | AddSizeInstTable("SLL", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x01, DecodeShift); |
||
3305 | AddSizeInstTable("SRA", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x89, DecodeShift); |
||
3306 | AddSizeInstTable("SRL", (1 << eSymbolSize8Bit) | (1 << eSymbolSize32Bit), 0x81, DecodeShift); |
||
3307 | AddInstTable(InstTable, "SC", 0x7f00, DecodeSC); |
||
3308 | AddSizeInstTable("TCC", 1 << eSymbolSize8Bit, 0x00, DecodeTCC); |
||
3309 | |||
3310 | AddInstTable(InstTable, "PORT", 0, DecodePORT); |
||
3311 | AddInstTable(InstTable, "REG" , 0, CodeREG); |
||
3312 | AddInstTable(InstTable, "DEFBIT" , eSymbolSize16Bit, DecodeDEFBIT); |
||
3313 | AddInstTable(InstTable, "DEFBITB", eSymbolSize8Bit , DecodeDEFBIT); |
||
3314 | |||
3315 | AddIntelPseudo(InstTable, eIntPseudoFlag_BigEndian); |
||
3316 | } |
||
3317 | |||
3318 | /*!------------------------------------------------------------------------ |
||
3319 | * \fn DeinitFields(void) |
||
3320 | * \brief Tear down hash table |
||
3321 | * ------------------------------------------------------------------------ */ |
||
3322 | |||
3323 | static void DeinitFields(void) |
||
3324 | { |
||
3325 | order_array_free(CtlRegs); |
||
3326 | order_array_free(FixedOrders); |
||
3327 | order_array_free(Conditions); |
||
3328 | |||
3329 | DestroyInstTable(InstTable); |
||
3330 | } |
||
3331 | |||
3332 | /*---------------------------------------------------------------------*/ |
||
3333 | |||
3334 | /*!------------------------------------------------------------------------ |
||
3335 | * \fn MakeCode_Z8000(void) |
||
3336 | * \brief encode machine instruction |
||
3337 | * ------------------------------------------------------------------------ */ |
||
3338 | |||
3339 | static void MakeCode_Z8000(void) |
||
3340 | { |
||
3341 | ImmOpSize = OpSize = eSymbolSizeUnknown; |
||
3342 | |||
3343 | if (!LookupInstTable(InstTable, OpPart.str.p_str)) |
||
3344 | WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart); |
||
3345 | } |
||
3346 | |||
3347 | /*!------------------------------------------------------------------------ |
||
3348 | * \fn InternSymbol_Z8000(char *pArg, TempResult *pResult) |
||
3349 | * \brief handle built-in symbols on Z8000 |
||
3350 | * \param pArg source argument |
||
3351 | * \param pResult result buffer |
||
3352 | * ------------------------------------------------------------------------ */ |
||
3353 | |||
3354 | static void InternSymbol_Z8000(char *pArg, TempResult *pResult) |
||
3355 | { |
||
3356 | Word Reg; |
||
3357 | tSymbolSize Size; |
||
3358 | |||
3359 | if (DecodeRegCore(pArg, &Reg, &Size)) |
||
3360 | { |
||
3361 | pResult->Typ = TempReg; |
||
3362 | pResult->DataSize = Size; |
||
3363 | pResult->Contents.RegDescr.Reg = Reg; |
||
3364 | pResult->Contents.RegDescr.Dissect = DissectReg_Z8000; |
||
3365 | pResult->Contents.RegDescr.compare = NULL; |
||
3366 | } |
||
3367 | } |
||
3368 | |||
3369 | /*!------------------------------------------------------------------------ |
||
3370 | * \fn IsDef_Z8000(void) |
||
3371 | * \brief check whether insn makes own use of label |
||
3372 | * \return True if yes |
||
3373 | * ------------------------------------------------------------------------ */ |
||
3374 | |||
3375 | static Boolean IsDef_Z8000(void) |
||
3376 | { |
||
3377 | return Memo("REG") |
||
3378 | || Memo("PORT") |
||
3379 | || Memo("DEFBIT") |
||
3380 | || Memo("DEFBITB"); |
||
3381 | } |
||
3382 | |||
3383 | /*!------------------------------------------------------------------------ |
||
3384 | * \fn PotOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal) |
||
3385 | * \brief special ^ operator for AMD syntax |
||
3386 | * \param pErg operator result |
||
3387 | * \param pRVal input argument |
||
3388 | * ------------------------------------------------------------------------ */ |
||
3389 | |||
3390 | static Boolean PotMonadicOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal) |
||
3391 | { |
||
3392 | UNUSED(pLVal); |
||
3393 | if (!pRVal) |
||
3394 | return False; |
||
3395 | |||
3396 | /* If in front of a label, takes the address as an 'untyped' value. This |
||
3397 | will instruct the address decoder to use immediate instead of direct |
||
3398 | addressing: */ |
||
3399 | |||
3400 | if (pRVal->AddrSpaceMask) |
||
3401 | pErg->AddrSpaceMask = 0; |
||
3402 | |||
3403 | /* Vice-versa, for a constant, this makes an address of it: */ |
||
3404 | |||
3405 | else |
||
3406 | pErg->AddrSpaceMask |= (1 << SegCode); |
||
3407 | |||
3408 | /* clone remainder as-is */ |
||
3409 | |||
3410 | pErg->Typ = pRVal->Typ; |
||
3411 | pErg->Contents = pRVal->Contents; |
||
3412 | pErg->Flags |= (pLVal->Flags & eSymbolFlags_Promotable); |
||
3413 | if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pLVal->DataSize; |
||
3414 | return True; |
||
3415 | } |
||
3416 | |||
3417 | static const as_operator_t z8000_operators[] = |
||
3418 | { |
||
3419 | { "^" ,1 , e_op_monadic, 8, { TempInt | (TempInt << 4), 0, 0, 0 }, PotMonadicOp}, |
||
3420 | {NULL, 0 , e_op_monadic, 0, { 0, 0, 0, 0, 0 }, NULL} |
||
3421 | }; |
||
3422 | |||
3423 | /*!------------------------------------------------------------------------ |
||
3424 | * \fn SwitchTo_Z8000(void *pUser) |
||
3425 | * \brief prepare to assemble code for this target |
||
3426 | * \param pUser CPU properties |
||
3427 | * ------------------------------------------------------------------------ */ |
||
3428 | |||
3429 | static Boolean TrueFnc(void) |
||
3430 | { |
||
3431 | return True; |
||
3432 | } |
||
3433 | |||
3434 | static void SwitchTo_Z8000(void *pUser) |
||
3435 | { |
||
3436 | const TFamilyDescr *pDescr = FindFamilyByName("Z8000"); |
||
3437 | |||
3438 | TurnWords = True; |
||
3439 | SetIntConstMode(eIntConstModeIntel); |
||
3440 | |||
3441 | pCurrCPUProps = (const tCPUProps*)pUser; |
||
3442 | |||
3443 | PCSymbol = "$"; HeaderID = pDescr->Id; |
||
3444 | NOPCode = 0x8d07; |
||
3445 | DivideChars = ","; HasAttrs = False; |
||
3446 | |||
3447 | ValidSegs = (1 << SegCode) | (1 << SegIO); |
||
3448 | Grans[SegCode] = 1; ListGrans[SegCode] = 2; SegInits[SegCode] = 0; |
||
3449 | SegLimits[SegCode] = pCurrCPUProps->SuppSegmented ? 0x7fffff : 0xffff; |
||
3450 | Grans[SegIO] = 1; ListGrans[SegIO] = 1; SegInits[SegIO] = 0; |
||
3451 | SegLimits[SegIO] = 0xffff; |
||
3452 | MemIntType = Segmented() ? UInt23 : UInt16; |
||
3453 | |||
3454 | MakeCode = MakeCode_Z8000; |
||
3455 | IsDef = IsDef_Z8000; |
||
3456 | DissectReg = DissectReg_Z8000; |
||
3457 | DissectBit = DissectBit_Z8000; |
||
3458 | InternSymbol = InternSymbol_Z8000; |
||
3459 | SwitchFrom = DeinitFields; |
||
3460 | InitFields(); |
||
3461 | SetIsOccupiedFnc = TrueFnc; |
||
3462 | if (AMDSyntax) |
||
3463 | target_operators = z8000_operators; |
||
3464 | onoff_supmode_add(); |
||
3465 | } |
||
3466 | |||
3467 | /*!------------------------------------------------------------------------ |
||
3468 | * \fn codez8000_init(void) |
||
3469 | * \brief register target to AS |
||
3470 | * ------------------------------------------------------------------------ */ |
||
3471 | |||
3472 | static const tCPUProps CPUProps[] = |
||
3473 | { |
||
3474 | { "Z8001" , eCoreZ8001 , True }, |
||
3475 | { "Z8002" , eCoreZ8001 , False }, |
||
3476 | { "Z8003" , eCoreZ8003 , True }, |
||
3477 | { "Z8004" , eCoreZ8003 , False }, |
||
3478 | { NULL , eCoreNone , False } |
||
3479 | }; |
||
3480 | |||
3481 | void codez8000_init(void) |
||
3482 | { |
||
3483 | const tCPUProps *pRun; |
||
3484 | static const tCPUArg Z8000Args[] = |
||
3485 | { |
||
3486 | { "AMDSYNTAX", 0, 1, 0, &AMDSyntax }, |
||
3487 | { NULL , 0, 0, 0, NULL } |
||
3488 | }; |
||
3489 | |||
3490 | for (pRun = CPUProps; pRun->pName; pRun++) |
||
3491 | (void)AddCPUUserWithArgs(pRun->pName, SwitchTo_Z8000, (void*)pRun, NULL, Z8000Args); |
||
3492 | } |