Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* codest6.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS-Portierung */ |
||
6 | /* */ |
||
7 | /* Codegenerator ST6-Familie */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "stdinc.h" |
||
12 | #include <string.h> |
||
13 | |||
14 | #include "strutil.h" |
||
15 | #include "bpemu.h" |
||
16 | #include "asmdef.h" |
||
17 | #include "asmsub.h" |
||
18 | #include "asmpars.h" |
||
19 | #include "asmitree.h" |
||
20 | #include "asmstructs.h" |
||
21 | #include "codepseudo.h" |
||
22 | #include "motpseudo.h" |
||
23 | #include "codevars.h" |
||
24 | #include "errmsg.h" |
||
25 | #include "intformat.h" |
||
26 | |||
27 | #include "codest6.h" |
||
28 | |||
29 | #define ModNone (-1) |
||
30 | #define ModAcc 0 |
||
31 | #define MModAcc (1 << ModAcc) |
||
32 | #define ModDir 1 |
||
33 | #define MModDir (1 << ModDir) |
||
34 | #define ModInd 2 |
||
35 | #define MModInd (1 << ModInd) |
||
36 | |||
37 | |||
38 | static Byte AdrMode; |
||
39 | static ShortInt AdrType; |
||
40 | static Byte AdrVal; |
||
41 | |||
42 | static LongInt WinAssume, PRPRVal; |
||
43 | |||
44 | typedef struct |
||
45 | { |
||
46 | const char *pName; |
||
47 | IntType CodeAdrInt; |
||
48 | } tCPUProps; |
||
49 | |||
50 | #define ASSUMEST6Count 2 |
||
51 | static ASSUMERec ASSUMEST6s[ASSUMEST6Count] = |
||
52 | { |
||
53 | { "PRPR", &PRPRVal , 0, 0x03, 0x04, NULL }, |
||
54 | { "ROMBASE", &WinAssume, 0, 0x3f, 0x40, NULL }, |
||
55 | }; |
||
56 | static const tCPUProps *pCurrCPUProps; |
||
57 | |||
58 | /*---------------------------------------------------------------------------------*/ |
||
59 | /* Helper Functions */ |
||
60 | |||
61 | static void ResetAdr(void) |
||
62 | { |
||
63 | AdrType = ModNone; AdrCnt = 0; |
||
64 | } |
||
65 | |||
66 | static void DecodeAdr(const tStrComp *pArg, Byte Mask) |
||
67 | { |
||
68 | Integer AdrInt; |
||
69 | tEvalResult EvalResult; |
||
70 | |||
71 | ResetAdr(); |
||
72 | |||
73 | if ((!as_strcasecmp(pArg->str.p_str, "A")) && (Mask & MModAcc)) |
||
74 | { |
||
75 | AdrType = ModAcc; |
||
76 | goto chk; |
||
77 | } |
||
78 | |||
79 | if (!as_strcasecmp(pArg->str.p_str, "(X)")) |
||
80 | { |
||
81 | AdrType = ModInd; |
||
82 | AdrMode = 0; |
||
83 | goto chk; |
||
84 | } |
||
85 | |||
86 | if (!as_strcasecmp(pArg->str.p_str, "(Y)")) |
||
87 | { |
||
88 | AdrType = ModInd; |
||
89 | AdrMode = 1; |
||
90 | goto chk; |
||
91 | } |
||
92 | |||
93 | AdrInt = EvalStrIntExpressionWithResult(pArg, UInt16, &EvalResult); |
||
94 | if (EvalResult.OK) |
||
95 | { |
||
96 | if (EvalResult.AddrSpaceMask & (1 << SegCode)) |
||
97 | { |
||
98 | AdrType = ModDir; |
||
99 | AdrVal = (AdrInt & 0x3f) + 0x40; |
||
100 | AdrCnt=1; |
||
101 | if (!mFirstPassUnknown(EvalResult.Flags)) |
||
102 | if (WinAssume != (AdrInt >> 6)) WrError(ErrNum_InAccPage); |
||
103 | } |
||
104 | else |
||
105 | { |
||
106 | if (mFirstPassUnknown(EvalResult.Flags)) AdrInt = Lo(AdrInt); |
||
107 | if (AdrInt > 0xff) WrError(ErrNum_OverRange); |
||
108 | else |
||
109 | { |
||
110 | AdrType = ModDir; |
||
111 | AdrVal = AdrInt; |
||
112 | goto chk; |
||
113 | } |
||
114 | } |
||
115 | } |
||
116 | |||
117 | chk: |
||
118 | if ((AdrType != ModNone) && (!(Mask & (1 << AdrType)))) |
||
119 | { |
||
120 | ResetAdr(); WrError(ErrNum_InvAddrMode); |
||
121 | } |
||
122 | } |
||
123 | |||
124 | static Boolean IsReg(Byte Adr) |
||
125 | { |
||
126 | return ((Adr & 0xfc) == 0x80); |
||
127 | } |
||
128 | |||
129 | static Byte MirrBit(Byte inp) |
||
130 | { |
||
131 | return (((inp & 1) << 2) + (inp & 2) + ((inp & 4) >> 2)); |
||
132 | } |
||
133 | |||
134 | /*--------------------------------------------------------------------------*/ |
||
135 | /* Bit Symbol Handling */ |
||
136 | |||
137 | /* |
||
138 | * Compact representation of bits in symbol table: |
||
139 | * bits 0..2: bit position |
||
140 | * bits 3...10: register address in DATA/SFR space |
||
141 | */ |
||
142 | |||
143 | /*!------------------------------------------------------------------------ |
||
144 | * \fn EvalBitPosition(const tStrComp *pArg, Boolean *pOK) |
||
145 | * \brief evaluate bit position |
||
146 | * \param bit position argument (with or without #) |
||
147 | * \param pOK parsing OK? |
||
148 | * \return numeric bit position |
||
149 | * ------------------------------------------------------------------------ */ |
||
150 | |||
151 | static LongWord EvalBitPosition(const tStrComp *pArg, Boolean *pOK) |
||
152 | { |
||
153 | return EvalStrIntExpressionOffs(pArg, !!(*pArg->str.p_str == '#'), UInt3, pOK); |
||
154 | } |
||
155 | |||
156 | /*!------------------------------------------------------------------------ |
||
157 | * \fn AssembleBitSymbol(Byte BitPos, Word Address) |
||
158 | * \brief build the compact internal representation of a bit symbol |
||
159 | * \param BitPos bit position in word |
||
160 | * \param Address register address |
||
161 | * \return compact representation |
||
162 | * ------------------------------------------------------------------------ */ |
||
163 | |||
164 | static LongWord AssembleBitSymbol(Byte BitPos, Word Address) |
||
165 | { |
||
166 | return (BitPos & 7) |
||
167 | | (((LongWord)Address & 0xff) << 3); |
||
168 | } |
||
169 | |||
170 | /*!------------------------------------------------------------------------ |
||
171 | * \fn DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg) |
||
172 | * \brief encode a bit symbol, address & bit position separated |
||
173 | * \param pResult resulting encoded bit |
||
174 | * \param pRegArg register argument |
||
175 | * \param pBitArg bit argument |
||
176 | * \return True if success |
||
177 | * ------------------------------------------------------------------------ */ |
||
178 | |||
179 | static Boolean DecodeBitArg2(LongWord *pResult, const tStrComp *pRegArg, const tStrComp *pBitArg) |
||
180 | { |
||
181 | Boolean OK; |
||
182 | LongWord Addr; |
||
183 | Byte BitPos; |
||
184 | |||
185 | BitPos = EvalBitPosition(pBitArg, &OK); |
||
186 | if (!OK) |
||
187 | return False; |
||
188 | |||
189 | Addr = EvalStrIntExpression(pRegArg, UInt8, &OK); |
||
190 | if (!OK) |
||
191 | return False; |
||
192 | |||
193 | *pResult = AssembleBitSymbol(BitPos, Addr); |
||
194 | |||
195 | return True; |
||
196 | } |
||
197 | |||
198 | /*!------------------------------------------------------------------------ |
||
199 | * \fn DecodeBitArg(LongWord *pResult, int Start, int Stop) |
||
200 | * \brief encode a bit symbol from instruction argument(s) |
||
201 | * \param pResult resulting encoded bit |
||
202 | * \param Start first argument |
||
203 | * \param Stop last argument |
||
204 | * \return True if success |
||
205 | * ------------------------------------------------------------------------ */ |
||
206 | |||
207 | static Boolean DecodeBitArg(LongWord *pResult, int Start, int Stop) |
||
208 | { |
||
209 | *pResult = 0; |
||
210 | |||
211 | /* Just one argument -> parse as bit argument */ |
||
212 | |||
213 | if (Start == Stop) |
||
214 | { |
||
215 | tEvalResult EvalResult; |
||
216 | |||
217 | *pResult = EvalStrIntExpressionWithResult(&ArgStr[Start], UInt11, &EvalResult); |
||
218 | if (EvalResult.OK) |
||
219 | ChkSpace(SegBData, EvalResult.AddrSpaceMask); |
||
220 | return EvalResult.OK; |
||
221 | } |
||
222 | |||
223 | /* register & bit position are given as separate arguments */ |
||
224 | |||
225 | else if (Stop == Start + 1) |
||
226 | return DecodeBitArg2(pResult, &ArgStr[Stop], &ArgStr[Start]); |
||
227 | |||
228 | /* other # of arguments not allowed */ |
||
229 | |||
230 | else |
||
231 | { |
||
232 | WrError(ErrNum_WrongArgCnt); |
||
233 | return False; |
||
234 | } |
||
235 | } |
||
236 | |||
237 | /*!------------------------------------------------------------------------ |
||
238 | * \fn DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos) |
||
239 | * \brief transform compact represenation of bit (field) symbol into components |
||
240 | * \param BitSymbol compact storage |
||
241 | * \param pAddress (I/O) register address |
||
242 | * \param pBitPos (start) bit position |
||
243 | * \return constant True |
||
244 | * ------------------------------------------------------------------------ */ |
||
245 | |||
246 | static Boolean DissectBitSymbol(LongWord BitSymbol, Word *pAddress, Byte *pBitPos) |
||
247 | { |
||
248 | *pAddress = (BitSymbol >> 3) & 0xffff; |
||
249 | *pBitPos = BitSymbol & 7; |
||
250 | return True; |
||
251 | } |
||
252 | |||
253 | /*!------------------------------------------------------------------------ |
||
254 | * \fn DissectBit_ST6(char *pDest, size_t DestSize, LargeWord Inp) |
||
255 | * \brief dissect compact storage of bit (field) into readable form for listing |
||
256 | * \param pDest destination for ASCII representation |
||
257 | * \param DestSize destination buffer size |
||
258 | * \param Inp compact storage |
||
259 | * ------------------------------------------------------------------------ */ |
||
260 | |||
261 | static void DissectBit_ST6(char *pDest, size_t DestSize, LargeWord Inp) |
||
262 | { |
||
263 | Byte BitPos; |
||
264 | Word Address; |
||
265 | |||
266 | DissectBitSymbol(Inp, &Address, &BitPos); |
||
267 | |||
268 | as_snprintf(pDest, DestSize, "%02.*u%s.%u", |
||
269 | ListRadixBase, (unsigned)Address, GetIntConstIntelSuffix(ListRadixBase), |
||
270 | (unsigned)BitPos); |
||
271 | } |
||
272 | |||
273 | /*!------------------------------------------------------------------------ |
||
274 | * \fn ExpandST6Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base) |
||
275 | * \brief expands bit definition when a structure is instantiated |
||
276 | * \param pVarName desired symbol name |
||
277 | * \param pStructElem element definition |
||
278 | * \param Base base address of instantiated structure |
||
279 | * ------------------------------------------------------------------------ */ |
||
280 | |||
281 | static void ExpandST6Bit(const tStrComp *pVarName, const struct sStructElem *pStructElem, LargeWord Base) |
||
282 | { |
||
283 | LongWord Address = Base + pStructElem->Offset; |
||
284 | |||
285 | if (pInnermostNamedStruct) |
||
286 | { |
||
287 | PStructElem pElem = CloneStructElem(pVarName, pStructElem); |
||
288 | |||
289 | if (!pElem) |
||
290 | return; |
||
291 | pElem->Offset = Address; |
||
292 | AddStructElem(pInnermostNamedStruct->StructRec, pElem); |
||
293 | } |
||
294 | else |
||
295 | { |
||
296 | if (!ChkRange(Address, 0, 0xff) |
||
297 | || !ChkRange(pStructElem->BitPos, 0, 7)) |
||
298 | return; |
||
299 | |||
300 | PushLocHandle(-1); |
||
301 | EnterIntSymbol(pVarName, AssembleBitSymbol(pStructElem->BitPos, Address), SegBData, False); |
||
302 | PopLocHandle(); |
||
303 | /* TODO: MakeUseList? */ |
||
304 | } |
||
305 | } |
||
306 | |||
307 | /*---------------------------------------------------------------------------------*/ |
||
308 | /* Instruction Decoders */ |
||
309 | |||
310 | static void DecodeFixed(Word Code) |
||
311 | { |
||
312 | if (ChkArgCnt(0, 0)) |
||
313 | { |
||
314 | CodeLen = 1; |
||
315 | BAsmCode[0] = Code; |
||
316 | } |
||
317 | } |
||
318 | |||
319 | static void DecodeLD(Word Code) |
||
320 | { |
||
321 | UNUSED(Code); |
||
322 | |||
323 | if (ChkArgCnt(2, 2)) |
||
324 | { |
||
325 | DecodeAdr(&ArgStr[1], MModAcc | MModDir | MModInd); |
||
326 | switch (AdrType) |
||
327 | { |
||
328 | case ModAcc: |
||
329 | DecodeAdr(&ArgStr[2], MModDir | MModInd); |
||
330 | switch (AdrType) |
||
331 | { |
||
332 | case ModDir: |
||
333 | if (IsReg(AdrVal)) |
||
334 | { |
||
335 | CodeLen = 1; |
||
336 | BAsmCode[0] = 0x35 + ((AdrVal & 3) << 6); |
||
337 | } |
||
338 | else |
||
339 | { |
||
340 | CodeLen = 2; |
||
341 | BAsmCode[0] = 0x1f; |
||
342 | BAsmCode[1] = AdrVal; |
||
343 | } |
||
344 | break; |
||
345 | case ModInd: |
||
346 | CodeLen = 1; |
||
347 | BAsmCode[0] = 0x07 + (AdrMode << 3); |
||
348 | break; |
||
349 | } |
||
350 | break; |
||
351 | case ModDir: |
||
352 | DecodeAdr(&ArgStr[2], MModAcc); |
||
353 | if (AdrType != ModNone) |
||
354 | { |
||
355 | if (IsReg(AdrVal)) |
||
356 | { |
||
357 | CodeLen = 1; |
||
358 | BAsmCode[0] = 0x3d + ((AdrVal & 3) << 6); |
||
359 | } |
||
360 | else |
||
361 | { |
||
362 | CodeLen = 2; |
||
363 | BAsmCode[0] = 0x9f; |
||
364 | BAsmCode[1] = AdrVal; |
||
365 | } |
||
366 | } |
||
367 | break; |
||
368 | case ModInd: |
||
369 | DecodeAdr(&ArgStr[2], MModAcc); |
||
370 | if (AdrType != ModNone) |
||
371 | { |
||
372 | CodeLen = 1; |
||
373 | BAsmCode[0] = 0x87 + (AdrMode << 3); |
||
374 | } |
||
375 | break; |
||
376 | } |
||
377 | } |
||
378 | } |
||
379 | |||
380 | static void DecodeLDI(Word Code) |
||
381 | { |
||
382 | UNUSED(Code); |
||
383 | |||
384 | if (ChkArgCnt(2, 2)) |
||
385 | { |
||
386 | Boolean OK; |
||
387 | |||
388 | Integer AdrInt = EvalStrIntExpression(&ArgStr[2], Int8, &OK); |
||
389 | if (OK) |
||
390 | { |
||
391 | DecodeAdr(&ArgStr[1], MModAcc | MModDir); |
||
392 | switch (AdrType) |
||
393 | { |
||
394 | case ModAcc: |
||
395 | CodeLen = 2; |
||
396 | BAsmCode[0] = 0x17; |
||
397 | BAsmCode[1] = Lo(AdrInt); |
||
398 | break; |
||
399 | case ModDir: |
||
400 | CodeLen = 3; |
||
401 | BAsmCode[0] = 0x0d; |
||
402 | BAsmCode[1] = AdrVal; |
||
403 | BAsmCode[2] = Lo(AdrInt); |
||
404 | break; |
||
405 | } |
||
406 | } |
||
407 | } |
||
408 | } |
||
409 | |||
410 | static void DecodeRel(Word Code) |
||
411 | { |
||
412 | if (ChkArgCnt(1, 1)) |
||
413 | { |
||
414 | Boolean OK; |
||
415 | tSymbolFlags Flags; |
||
416 | Integer AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt16, &OK, &Flags) - (EProgCounter() + 1); |
||
417 | |||
418 | if (OK) |
||
419 | { |
||
420 | if (!mSymbolQuestionable(Flags) && ((AdrInt < -16) || (AdrInt > 15))) WrError(ErrNum_JmpDistTooBig); |
||
421 | else |
||
422 | { |
||
423 | CodeLen = 1; |
||
424 | BAsmCode[0] = Code + ((AdrInt << 3) & 0xf8); |
||
425 | } |
||
426 | } |
||
427 | } |
||
428 | } |
||
429 | |||
430 | static void DecodeJP_CALL(Word Code) |
||
431 | { |
||
432 | if (ChkArgCnt(1, 1)) |
||
433 | { |
||
434 | Boolean OK; |
||
435 | Word AdrInt; |
||
436 | tSymbolFlags Flags; |
||
437 | |||
438 | AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[1], pCurrCPUProps->CodeAdrInt, &OK, &Flags); |
||
439 | if (OK) |
||
440 | { |
||
441 | Word DestPage = AdrInt >> 11; |
||
442 | |||
443 | /* CPU program space's page 1 (800h...0fffh) always accesses ROM space page 1. |
||
444 | CPU program space's page 0 (000h...7ffh) accesses 2K ROM space pages as defined by PRPR. */ |
||
445 | |||
446 | if (!mFirstPassUnknown(Flags) && (DestPage != 1)) |
||
447 | { |
||
448 | Word SrcPage = EProgCounter() >> 11; |
||
449 | |||
450 | /* Jump from page 1 is allowed to page defined by PRPR. |
||
451 | Jump from any other page is only allowed back to page 1 or within same page. */ |
||
452 | |||
453 | if (DestPage != ((SrcPage == 1) ? PRPRVal : SrcPage)) WrError(ErrNum_InAccPage); |
||
454 | |||
455 | AdrInt &= 0x7ff; |
||
456 | } |
||
457 | CodeLen = 2; |
||
458 | BAsmCode[0] = Code + ((AdrInt & 0x00f) << 4); |
||
459 | BAsmCode[1] = AdrInt >> 4; |
||
460 | } |
||
461 | } |
||
462 | } |
||
463 | |||
464 | static void DecodeALU(Word Code) |
||
465 | { |
||
466 | if (ChkArgCnt(2, 2)) |
||
467 | { |
||
468 | DecodeAdr(&ArgStr[1], MModAcc); |
||
469 | if (AdrType != ModNone) |
||
470 | { |
||
471 | DecodeAdr(&ArgStr[2], MModDir | MModInd); |
||
472 | switch (AdrType) |
||
473 | { |
||
474 | case ModDir: |
||
475 | CodeLen = 2; |
||
476 | BAsmCode[0] = Code + 0x18; |
||
477 | BAsmCode[1] = AdrVal; |
||
478 | break; |
||
479 | case ModInd: |
||
480 | CodeLen = 1; |
||
481 | BAsmCode[0] = Code + (AdrMode << 3); |
||
482 | break; |
||
483 | } |
||
484 | } |
||
485 | } |
||
486 | } |
||
487 | |||
488 | static void DecodeALUImm(Word Code) |
||
489 | { |
||
490 | if (ChkArgCnt(2, 2)) |
||
491 | { |
||
492 | DecodeAdr(&ArgStr[1], MModAcc); |
||
493 | if (AdrType != ModNone) |
||
494 | { |
||
495 | Boolean OK; |
||
496 | BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK); |
||
497 | if (OK) |
||
498 | { |
||
499 | CodeLen = 2; |
||
500 | BAsmCode[0] = Code + 0x10; |
||
501 | } |
||
502 | } |
||
503 | } |
||
504 | } |
||
505 | |||
506 | static void DecodeCLR(Word Code) |
||
507 | { |
||
508 | UNUSED(Code); |
||
509 | |||
510 | if (ChkArgCnt(1, 1)) |
||
511 | { |
||
512 | DecodeAdr(&ArgStr[1], MModAcc | MModDir); |
||
513 | switch (AdrType) |
||
514 | { |
||
515 | case ModAcc: |
||
516 | CodeLen = 2; |
||
517 | BAsmCode[0] = 0xdf; |
||
518 | BAsmCode[1] = 0xff; |
||
519 | break; |
||
520 | case ModDir: |
||
521 | CodeLen = 3; |
||
522 | BAsmCode[0] = 0x0d; |
||
523 | BAsmCode[1] = AdrVal; |
||
524 | BAsmCode[2] = 0; |
||
525 | break; |
||
526 | } |
||
527 | } |
||
528 | } |
||
529 | |||
530 | static void DecodeAcc(Word Code) |
||
531 | { |
||
532 | if (ChkArgCnt(1, 1)) |
||
533 | { |
||
534 | DecodeAdr(&ArgStr[1], MModAcc); |
||
535 | if (AdrType != ModNone) |
||
536 | { |
||
537 | BAsmCode[CodeLen++] = Lo(Code); |
||
538 | if (Hi(Code)) |
||
539 | BAsmCode[CodeLen++] = Hi(Code); |
||
540 | } |
||
541 | } |
||
542 | } |
||
543 | |||
544 | static void DecodeINC_DEC(Word Code) |
||
545 | { |
||
546 | if (ChkArgCnt(1, 1)) |
||
547 | { |
||
548 | DecodeAdr(&ArgStr[1], MModDir | MModInd); |
||
549 | switch (AdrType) |
||
550 | { |
||
551 | case ModDir: |
||
552 | if (IsReg(AdrVal)) |
||
553 | { |
||
554 | CodeLen = 1; |
||
555 | BAsmCode[0] = Code + 0x15 + ((AdrVal & 3) << 6); |
||
556 | } |
||
557 | else |
||
558 | { |
||
559 | CodeLen = 2; |
||
560 | BAsmCode[0] = 0x7f + (Code << 4); |
||
561 | BAsmCode[1] = AdrVal; |
||
562 | } |
||
563 | break; |
||
564 | case ModInd: |
||
565 | CodeLen = 1; |
||
566 | BAsmCode[0] = 0x67 + (AdrMode << 3) + (Code << 4); |
||
567 | break; |
||
568 | } |
||
569 | } |
||
570 | } |
||
571 | |||
572 | static void DecodeSET_RES(Word Code) |
||
573 | { |
||
574 | LongWord PackedAddr; |
||
575 | |||
576 | if (ChkArgCnt(1, 2) |
||
577 | && DecodeBitArg(&PackedAddr, 1, ArgCnt)) |
||
578 | { |
||
579 | Word RegAddr; |
||
580 | Byte BitPos; |
||
581 | |||
582 | DissectBitSymbol(PackedAddr, &RegAddr, &BitPos); |
||
583 | BAsmCode[0] = (MirrBit(BitPos) << 5) | Code; |
||
584 | BAsmCode[1] = RegAddr; |
||
585 | CodeLen = 2; |
||
586 | } |
||
587 | } |
||
588 | |||
589 | static void DecodeJRR_JRS(Word Code) |
||
590 | { |
||
591 | LongWord PackedAddr; |
||
592 | |||
593 | if (ChkArgCnt(2, 3) |
||
594 | && DecodeBitArg(&PackedAddr, 1, ArgCnt - 1)) |
||
595 | { |
||
596 | Word RegAddr; |
||
597 | Byte BitPos; |
||
598 | Boolean OK; |
||
599 | Integer AdrInt; |
||
600 | tSymbolFlags Flags; |
||
601 | |||
602 | DissectBitSymbol(PackedAddr, &RegAddr, &BitPos); |
||
603 | BAsmCode[0] = (MirrBit(BitPos) << 5) | Code; |
||
604 | BAsmCode[1] = RegAddr; |
||
605 | AdrInt = EvalStrIntExpressionWithFlags(&ArgStr[ArgCnt], UInt16, &OK, &Flags) - (EProgCounter() + 3); |
||
606 | if (OK) |
||
607 | { |
||
608 | if (!mSymbolQuestionable(Flags) && ((AdrInt > 127) || (AdrInt < -128))) WrError(ErrNum_JmpDistTooBig); |
||
609 | else |
||
610 | { |
||
611 | CodeLen = 3; |
||
612 | BAsmCode[2] = Lo(AdrInt); |
||
613 | } |
||
614 | } |
||
615 | } |
||
616 | } |
||
617 | |||
618 | static void DecodeSFR(Word Code) |
||
619 | { |
||
620 | UNUSED(Code); |
||
621 | CodeEquate(SegData, 0, 0xff); |
||
622 | } |
||
623 | |||
624 | /*!------------------------------------------------------------------------ |
||
625 | * \fn DecodeASCII_ASCIZ(Word IsZ) |
||
626 | * \brief handle ASCII/ASCIZ instructions |
||
627 | * \param IsZ 1 if it's ASCIZ |
||
628 | * ------------------------------------------------------------------------ */ |
||
629 | |||
630 | static void DecodeASCII_ASCIZ(Word IsZ) |
||
631 | { |
||
632 | if (ChkArgCnt(1, ArgCntMax)) |
||
633 | { |
||
634 | int l; |
||
635 | Boolean OK = True; |
||
636 | tStrComp *pArg; |
||
637 | TempResult t; |
||
638 | |||
639 | as_tempres_ini(&t); |
||
640 | forallargs(pArg, OK) |
||
641 | { |
||
642 | EvalStrExpression(pArg, &t); |
||
643 | switch (t.Typ) |
||
644 | { |
||
645 | case TempString: |
||
646 | { |
||
647 | if (as_chartrans_xlate_nonz_dynstr(CurrTransTable->p_table, &t.Contents.str, pArg)) |
||
648 | OK = False; |
||
649 | else |
||
650 | { |
||
651 | l = t.Contents.str.len; |
||
652 | if (SetMaxCodeLen(CodeLen + l + IsZ)) |
||
653 | { |
||
654 | WrStrErrorPos(ErrNum_CodeOverflow, pArg); OK = False; |
||
655 | } |
||
656 | else |
||
657 | { |
||
658 | memcpy(BAsmCode + CodeLen, t.Contents.str.p_str, l); |
||
659 | CodeLen += l; |
||
660 | if (IsZ) |
||
661 | BAsmCode[CodeLen++] = 0; |
||
662 | } |
||
663 | } |
||
664 | break; |
||
665 | } |
||
666 | case TempNone: |
||
667 | OK = False; |
||
668 | break; |
||
669 | default: |
||
670 | WrStrErrorPos(ErrNum_ExpectString, pArg); |
||
671 | OK = False; |
||
672 | } |
||
673 | } |
||
674 | as_tempres_free(&t); |
||
675 | if (!OK) |
||
676 | CodeLen = 0; |
||
677 | } |
||
678 | } |
||
679 | |||
680 | /*!------------------------------------------------------------------------ |
||
681 | * \fn DecodeBIT(Word Code) |
||
682 | * \brief decode BIT instruction |
||
683 | * ------------------------------------------------------------------------ */ |
||
684 | |||
685 | static void DecodeBIT(Word Code) |
||
686 | { |
||
687 | LongWord BitSpec; |
||
688 | |||
689 | UNUSED(Code); |
||
690 | |||
691 | /* if in structure definition, add special element to structure */ |
||
692 | |||
693 | if (ActPC == StructSeg) |
||
694 | { |
||
695 | Boolean OK; |
||
696 | Byte BitPos; |
||
697 | PStructElem pElement; |
||
698 | |||
699 | if (!ChkArgCnt(2, 2)) |
||
700 | return; |
||
701 | BitPos = EvalBitPosition(&ArgStr[2], &OK); |
||
702 | if (!OK) |
||
703 | return; |
||
704 | pElement = CreateStructElem(&LabPart); |
||
705 | if (!pElement) |
||
706 | return; |
||
707 | pElement->pRefElemName = as_strdup(ArgStr[1].str.p_str); |
||
708 | pElement->OpSize = eSymbolSize8Bit; |
||
709 | pElement->BitPos = BitPos; |
||
710 | pElement->ExpandFnc = ExpandST6Bit; |
||
711 | AddStructElem(pInnermostNamedStruct->StructRec, pElement); |
||
712 | } |
||
713 | else |
||
714 | { |
||
715 | if (DecodeBitArg(&BitSpec, 1, ArgCnt)) |
||
716 | { |
||
717 | *ListLine = '='; |
||
718 | DissectBit_ST6(ListLine + 1, STRINGSIZE - 3, BitSpec); |
||
719 | PushLocHandle(-1); |
||
720 | EnterIntSymbol(&LabPart, BitSpec, SegBData, False); |
||
721 | PopLocHandle(); |
||
722 | /* TODO: MakeUseList? */ |
||
723 | } |
||
724 | } |
||
725 | } |
||
726 | |||
727 | /*---------------------------------------------------------------------------------*/ |
||
728 | /* code table handling */ |
||
729 | |||
730 | static void AddFixed(const char *NName, Byte NCode) |
||
731 | { |
||
732 | AddInstTable(InstTable, NName, NCode, DecodeFixed); |
||
733 | } |
||
734 | |||
735 | static void AddRel(const char *NName, Byte NCode) |
||
736 | { |
||
737 | AddInstTable(InstTable, NName, NCode, DecodeRel); |
||
738 | } |
||
739 | |||
740 | static void AddALU(const char *NName, const char *NNameImm, Byte NCode) |
||
741 | { |
||
742 | AddInstTable(InstTable, NName, NCode, DecodeALU); |
||
743 | AddInstTable(InstTable, NNameImm, NCode, DecodeALUImm); |
||
744 | } |
||
745 | |||
746 | static void AddAcc(const char *NName, Word NCode) |
||
747 | { |
||
748 | AddInstTable(InstTable, NName, NCode, DecodeAcc); |
||
749 | } |
||
750 | |||
751 | static void InitFields(void) |
||
752 | { |
||
753 | InstTable = CreateInstTable(201); |
||
754 | |||
755 | add_null_pseudo(InstTable); |
||
756 | |||
757 | AddInstTable(InstTable, "LD", 0, DecodeLD); |
||
758 | AddInstTable(InstTable, "LDI", 0, DecodeLDI); |
||
759 | AddInstTable(InstTable, "JP", 0x09, DecodeJP_CALL); |
||
760 | AddInstTable(InstTable, "CALL", 0x01, DecodeJP_CALL); |
||
761 | AddInstTable(InstTable, "CLR", 0, DecodeCLR); |
||
762 | AddInstTable(InstTable, "INC", 0, DecodeINC_DEC); |
||
763 | AddInstTable(InstTable, "DEC", 8, DecodeINC_DEC); |
||
764 | AddInstTable(InstTable, "SET", 0x1b, DecodeSET_RES); |
||
765 | AddInstTable(InstTable, "RES", 0x0b, DecodeSET_RES); |
||
766 | AddInstTable(InstTable, "JRR", 0x03, DecodeJRR_JRS); |
||
767 | AddInstTable(InstTable, "JRS", 0x13, DecodeJRR_JRS); |
||
768 | AddInstTable(InstTable, "SFR", 0, DecodeSFR); |
||
769 | AddInstTable(InstTable, "ASCII", 0, DecodeASCII_ASCIZ); |
||
770 | AddInstTable(InstTable, "ASCIZ", 1, DecodeASCII_ASCIZ); |
||
771 | AddInstTable(InstTable, "BYTE", 0, DecodeMotoBYT); |
||
772 | AddInstTable(InstTable, "WORD", e_moto_pseudo_flags_le, DecodeMotoADR); |
||
773 | AddInstTable(InstTable, "BLOCK", e_moto_pseudo_flags_none, DecodeMotoDFS); |
||
774 | AddInstTable(InstTable, "BIT", 0, DecodeBIT); |
||
775 | |||
776 | AddFixed("NOP" , 0x04); |
||
777 | AddFixed("RET" , 0xcd); |
||
778 | AddFixed("RETI", 0x4d); |
||
779 | AddFixed("STOP", 0x6d); |
||
780 | AddFixed("WAIT", 0xed); |
||
781 | |||
782 | AddRel("JRZ" , 0x04); |
||
783 | AddRel("JRNZ", 0x00); |
||
784 | AddRel("JRC" , 0x06); |
||
785 | AddRel("JRNC", 0x02); |
||
786 | |||
787 | AddALU("ADD" , "ADDI" , 0x47); |
||
788 | AddALU("AND" , "ANDI" , 0xa7); |
||
789 | AddALU("CP" , "CPI" , 0x27); |
||
790 | AddALU("SUB" , "SUBI" , 0xc7); |
||
791 | |||
792 | AddAcc("COM", 0x002d); |
||
793 | AddAcc("RLC", 0x00ad); |
||
794 | AddAcc("SLA", 0xff5f); |
||
795 | } |
||
796 | |||
797 | static void DeinitFields(void) |
||
798 | { |
||
799 | DestroyInstTable(InstTable); |
||
800 | } |
||
801 | |||
802 | /*!------------------------------------------------------------------------ |
||
803 | * \fn MakeCode_ST6(void) |
||
804 | * \brief entry point to decode machine instructions |
||
805 | * ------------------------------------------------------------------------ */ |
||
806 | |||
807 | static void MakeCode_ST6(void) |
||
808 | { |
||
809 | if (!LookupInstTable(InstTable, OpPart.str.p_str)) |
||
810 | WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart); |
||
811 | } |
||
812 | |||
813 | /*!------------------------------------------------------------------------ |
||
814 | * \fn InitCode_ST6(void) |
||
815 | * \brief per-pass initializations for ST6 |
||
816 | * ------------------------------------------------------------------------ */ |
||
817 | |||
818 | static void InitCode_ST6(void) |
||
819 | { |
||
820 | WinAssume = 0x40; |
||
821 | PRPRVal = 0; |
||
822 | } |
||
823 | |||
824 | /*!------------------------------------------------------------------------ |
||
825 | * \fn IsDef_ST6(void) |
||
826 | * \brief does instruction consume label field? |
||
827 | * \return true if to be consumed |
||
828 | * ------------------------------------------------------------------------ */ |
||
829 | |||
830 | static Boolean IsDef_ST6(void) |
||
831 | { |
||
832 | return Memo("SFR") || Memo("BIT"); |
||
833 | } |
||
834 | |||
835 | /*!------------------------------------------------------------------------ |
||
836 | * \fn SwitchFrom_ST6(void) |
||
837 | * \brief cleanup after switching away from target |
||
838 | * ------------------------------------------------------------------------ */ |
||
839 | |||
840 | static void SwitchFrom_ST6(void) |
||
841 | { |
||
842 | DeinitFields(); |
||
843 | } |
||
844 | |||
845 | static Boolean TrueFnc(void) |
||
846 | { |
||
847 | return True; |
||
848 | } |
||
849 | |||
850 | /*!------------------------------------------------------------------------ |
||
851 | * \fn InternSymbol_ST6(char *pArg, TempResult *pErg) |
||
852 | * \brief check for built-in symbols |
||
853 | * \param pAsc ASCII repr. of symbol |
||
854 | * \param pErg result buffer |
||
855 | * ------------------------------------------------------------------------ */ |
||
856 | |||
857 | static void InternSymbol_ST6(char *pArg, TempResult *pErg) |
||
858 | { |
||
859 | int z; |
||
860 | #define RegCnt 5 |
||
861 | static const char RegNames[RegCnt + 1][2] = {"A", "V", "W", "X", "Y"}; |
||
862 | static const Byte RegCodes[RegCnt + 1] = {0xff, 0x82, 0x83, 0x80, 0x81}; |
||
863 | |||
864 | for (z = 0; z < RegCnt; z++) |
||
865 | if (!as_strcasecmp(pArg, RegNames[z])) |
||
866 | { |
||
867 | as_tempres_set_int(pErg, RegCodes[z]); |
||
868 | pErg->AddrSpaceMask |= (1 << SegData); |
||
869 | } |
||
870 | } |
||
871 | |||
872 | /*!------------------------------------------------------------------------ |
||
873 | * \fn SwitchTo_ST6(void) |
||
874 | * \brief switch to target |
||
875 | * ------------------------------------------------------------------------ */ |
||
876 | |||
877 | static void SwitchTo_ST6(void *pUser) |
||
878 | { |
||
879 | int ASSUMEOffset; |
||
880 | |||
881 | pCurrCPUProps = (const tCPUProps*)pUser; |
||
882 | TurnWords = False; |
||
883 | SetIntConstMode(eIntConstModeIntel); |
||
884 | SetIsOccupiedFnc = TrueFnc; |
||
885 | |||
886 | PCSymbol = "PC"; HeaderID = 0x78; NOPCode = 0x04; |
||
887 | DivideChars = ","; HasAttrs = False; |
||
888 | |||
889 | ValidSegs = (1 << SegCode) | (1 << SegData); |
||
890 | Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0; |
||
891 | SegLimits[SegCode] = IntTypeDefs[pCurrCPUProps->CodeAdrInt].Max; |
||
892 | Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0; |
||
893 | SegLimits[SegData] = 0xff; |
||
894 | |||
895 | ASSUMEOffset = (SegLimits[SegCode] > 0xfff) ? 0 : 1; |
||
896 | pASSUMERecs = ASSUMEST6s + ASSUMEOffset; |
||
897 | ASSUMERecCnt = ASSUMEST6Count - ASSUMEOffset; |
||
898 | |||
899 | MakeCode = MakeCode_ST6; |
||
900 | IsDef = IsDef_ST6; |
||
901 | SwitchFrom = SwitchFrom_ST6; |
||
902 | DissectBit = DissectBit_ST6; |
||
903 | InternSymbol = InternSymbol_ST6; |
||
904 | |||
905 | InitFields(); |
||
906 | } |
||
907 | |||
908 | /*!------------------------------------------------------------------------ |
||
909 | * \fn codest6_init(void) |
||
910 | * \brief register ST6 target |
||
911 | * ------------------------------------------------------------------------ */ |
||
912 | |||
913 | static const tCPUProps CPUProps[] = |
||
914 | { |
||
915 | { "ST6200", UInt12 }, |
||
916 | { "ST6201", UInt12 }, |
||
917 | { "ST6203", UInt12 }, |
||
918 | { "ST6208", UInt12 }, |
||
919 | { "ST6209", UInt12 }, |
||
920 | { "ST6210", UInt12 }, |
||
921 | { "ST6215", UInt12 }, |
||
922 | { "ST6218", UInt13 }, |
||
923 | { "ST6220", UInt12 }, |
||
924 | { "ST6225", UInt12 }, |
||
925 | { "ST6228", UInt13 }, |
||
926 | { "ST6230", UInt13 }, |
||
927 | { "ST6232", UInt13 }, |
||
928 | { "ST6235", UInt13 }, |
||
929 | { "ST6240", UInt13 }, |
||
930 | { "ST6242", UInt13 }, |
||
931 | { "ST6245", UInt12 }, |
||
932 | { "ST6246", UInt12 }, |
||
933 | { "ST6252", UInt12 }, |
||
934 | { "ST6253", UInt12 }, |
||
935 | { "ST6255", UInt12 }, |
||
936 | { "ST6260", UInt12 }, |
||
937 | { "ST6262", UInt12 }, |
||
938 | { "ST6263", UInt12 }, |
||
939 | { "ST6265", UInt12 }, |
||
940 | { "ST6280", UInt13 }, |
||
941 | { "ST6285", UInt13 }, |
||
942 | { NULL , (IntType)0 }, |
||
943 | }; |
||
944 | |||
945 | void codest6_init(void) |
||
946 | { |
||
947 | const tCPUProps *pProp; |
||
948 | |||
949 | for (pProp = CPUProps; pProp->pName; pProp++) |
||
950 | (void)AddCPUUser(pProp->pName, SwitchTo_ST6, (void*)pProp, NULL); |
||
951 | |||
952 | AddInitPassProc(InitCode_ST6); |
||
953 | } |