1 /* code2650.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Codegenerator Signetics 2650 */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12 #include <string.h>
13 #include <ctype.h>
14
15 #include "nls.h"
16 #include "chunks.h"
17 #include "bpemu.h"
18 #include "strutil.h"
19
20 #include "asmdef.h"
21 #include "asmsub.h"
22 #include "asmpars.h"
23 #include "asmitree.h"
24 #include "codevars.h"
25 #include "headids.h"
26 #include "intpseudo.h"
27 #include "errmsg.h"
28
29 #include "code2650.h"
30
31 /*--------------------------------------------------------------------------*/
32 /* Local Variables */
33
34 static CPUVar CPU2650;
35
36 /*--------------------------------------------------------------------------*/
37 /* Expression Parsers */
38
DecodeReg(const char * pAsc,Byte * pRes)39 static Boolean DecodeReg(const char *pAsc, Byte *pRes)
40 {
41 Boolean Result;
42
43 Result = ((strlen(pAsc) == 2) && (as_toupper(pAsc[0]) == 'R') && (pAsc[1] >= '0') && (pAsc[1] <= '3'));
44 if (Result)
45 *pRes = pAsc[1] - '0';
46 return Result;
47 }
48
DecodeCondition(const char * pAsc,Byte * pRes)49 static Boolean DecodeCondition(const char *pAsc, Byte *pRes)
50 {
51 Boolean Result = TRUE;
52
53 if (!as_strcasecmp(pAsc, "EQ"))
54 *pRes = 0;
55 else if (!as_strcasecmp(pAsc, "GT"))
56 *pRes = 1;
57 else if (!as_strcasecmp(pAsc, "LT"))
58 *pRes = 2;
59 else if ((!as_strcasecmp(pAsc, "ALWAYS")) || (!as_strcasecmp(pAsc, "UN")))
60 *pRes = 3;
61 else
62 Result = FALSE;
63
64 return Result;
65 }
66
67 /*--------------------------------------------------------------------------*/
68 /* Instruction Decoders */
69
DecodeFixed(Word Index)70 static void DecodeFixed(Word Index)
71 {
72 if (ChkArgCnt(0, 0))
73 {
74 BAsmCode[0] = Index; CodeLen = 1;
75 }
76 }
77
DecodeOneReg(Word Index)78 static void DecodeOneReg(Word Index)
79 {
80 Byte Reg;
81
82 if (!ChkArgCnt(1, 1));
83 else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
84 else
85 {
86 BAsmCode[0] = Index | Reg; CodeLen = 1;
87 }
88 }
89
DecodeImm(Word Index)90 static void DecodeImm(Word Index)
91 {
92 Boolean OK;
93
94 if (ChkArgCnt(1, 1))
95 {
96 BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
97 if (OK)
98 {
99 BAsmCode[0] = Index; CodeLen = 2;
100 }
101 }
102 }
103
DecodeRegImm(Word Index)104 static void DecodeRegImm(Word Index)
105 {
106 Byte Reg;
107 Boolean OK;
108
109 if (!ChkArgCnt(2, 2));
110 else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
111 else
112 {
113 BAsmCode[1] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
114 if (OK)
115 {
116 BAsmCode[0] = Index | Reg; CodeLen = 2;
117 }
118 }
119 }
120
DecodeRegAbs(Word Index)121 static void DecodeRegAbs(Word Index)
122 {
123 Byte DReg, IReg;
124 Word AbsVal;
125 Boolean OK, IndFlag;
126
127 if (!ChkArgCnt(2, 4));
128 else if (!DecodeReg(ArgStr[1].Str, &DReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
129 else
130 {
131 IndFlag = *ArgStr[2].Str == '*';
132 AbsVal = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
133 if (OK)
134 {
135 BAsmCode[0] = Index;
136 BAsmCode[1] = Hi(AbsVal);
137 BAsmCode[2] = Lo(AbsVal);
138 if (IndFlag)
139 BAsmCode[1] |= 0x80;
140 if (ArgCnt == 2)
141 {
142 BAsmCode[0] |= DReg;
143 CodeLen = 3;
144 }
145 else
146 {
147 if (!DecodeReg(ArgStr[3].Str, &IReg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[3]);
148 else if (DReg != 0) WrError(ErrNum_InvAddrMode);
149 else
150 {
151 BAsmCode[0] |= IReg;
152 if (ArgCnt == 3)
153 {
154 BAsmCode[1] |= 0x60;
155 CodeLen = 3;
156 }
157 else if (!strcmp(ArgStr[4].Str, "-"))
158 {
159 BAsmCode[1] |= 0x40;
160 CodeLen = 3;
161 }
162 else if (!strcmp(ArgStr[4].Str, "+"))
163 {
164 BAsmCode[1] |= 0x20;
165 CodeLen = 3;
166 }
167 else
168 WrError(ErrNum_InvAddrMode);
169 }
170 }
171 }
172 }
173 }
174
DecodeRegRel(Word Index)175 static void DecodeRegRel(Word Index)
176 {
177 Byte Reg;
178 Boolean IndFlag, OK;
179 int Dist;
180 tSymbolFlags Flags;
181
182 if (!ChkArgCnt(2, 2));
183 else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
184 else
185 {
186 BAsmCode[0] = Index | Reg;
187 IndFlag = *ArgStr[2].Str == '*';
188 Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], IndFlag, UInt13, &OK, &Flags) - (EProgCounter() + 2);
189 if (OK)
190 {
191 if (((Dist < - 64) || (Dist > 63)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
192 else
193 {
194 BAsmCode[1] = Dist & 0x7f;
195 if (IndFlag)
196 BAsmCode[1] |= 0x80;
197 CodeLen = 2;
198 }
199 }
200 }
201 }
202
DecodeCondAbs(Word Index)203 static void DecodeCondAbs(Word Index)
204 {
205 Byte Cond;
206 Word Address;
207 Boolean OK, IndFlag;
208
209 if (!ChkArgCnt(2, 2));
210 else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
211 else
212 {
213 IndFlag = *ArgStr[2].Str == '*';
214 Address = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
215 if (OK)
216 {
217 BAsmCode[0] = Index | Cond;
218 BAsmCode[1] = Hi(Address);
219 if (IndFlag)
220 BAsmCode[1] |= 0x80;
221 BAsmCode[2] = Lo(Address);
222 CodeLen = 3;
223 }
224 }
225 }
226
DecodeCondRel(Word Index)227 static void DecodeCondRel(Word Index)
228 {
229 Byte Cond;
230 Boolean IndFlag, OK;
231 tSymbolFlags Flags;
232 int Dist;
233
234 if (!ChkArgCnt(2, 2));
235 else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
236 else
237 {
238 BAsmCode[0] = Index | Cond;
239 IndFlag = *ArgStr[2].Str == '*';
240 Dist = EvalStrIntExpressionOffsWithFlags(&ArgStr[2], IndFlag, UInt13, &OK, &Flags) - (EProgCounter() + 2);
241 if (OK)
242 {
243 if (((Dist < - 64) || (Dist > 63)) && !mSymbolQuestionable(Flags)) WrError(ErrNum_JmpDistTooBig);
244 else
245 {
246 BAsmCode[1] = Dist & 0x7f;
247 if (IndFlag)
248 BAsmCode[1] |= 0x80;
249 CodeLen = 2;
250 }
251 }
252 }
253 }
254
DecodeRegAbs2(Word Index)255 static void DecodeRegAbs2(Word Index)
256 {
257 Byte Reg;
258 Word AbsVal;
259 Boolean IndFlag, OK;
260
261 if (!ChkArgCnt(2, 2));
262 else if (!DecodeReg(ArgStr[1].Str, &Reg)) WrStrErrorPos(ErrNum_InvReg, &ArgStr[1]);
263 else
264 {
265 BAsmCode[0] = Index | Reg;
266 IndFlag = *ArgStr[2].Str == '*';
267 AbsVal = EvalStrIntExpressionOffs(&ArgStr[2], IndFlag, UInt13, &OK);
268 if (OK)
269 {
270 BAsmCode[1] = Hi(AbsVal);
271 if (IndFlag)
272 BAsmCode[1] |= 0x80;
273 BAsmCode[2] = Lo(AbsVal);
274 CodeLen = 3;
275 }
276 }
277 }
278
DecodeBrAbs(Word Index)279 static void DecodeBrAbs(Word Index)
280 {
281 Byte Reg = 3;
282 Word AbsVal;
283 Boolean IndFlag, OK;
284
285 if (!ChkArgCnt(1, 2));
286 else if ((ArgCnt == 2) && (!DecodeReg(ArgStr[2].Str, &Reg))) WrStrErrorPos(ErrNum_InvReg, &ArgStr[2]);
287 else if (Reg != 3) WrError(ErrNum_InvAddrMode);
288 else
289 {
290 BAsmCode[0] = Index | Reg;
291 IndFlag = *ArgStr[1].Str == '*';
292 AbsVal = EvalStrIntExpressionOffs(&ArgStr[1], IndFlag, UInt13, &OK);
293 if (OK)
294 {
295 BAsmCode[1] = Hi(AbsVal);
296 if (IndFlag)
297 BAsmCode[1] |= 0x80;
298 BAsmCode[2] = Lo(AbsVal);
299 CodeLen = 3;
300 }
301 }
302 }
303
DecodeCond(Word Index)304 static void DecodeCond(Word Index)
305 {
306 Byte Cond;
307
308 if (!ChkArgCnt(1, 1));
309 else if (!DecodeCondition(ArgStr[1].Str, &Cond)) WrStrErrorPos(ErrNum_UndefCond, &ArgStr[1]);
310 else
311 {
312 BAsmCode[0] = Index | Cond;
313 CodeLen = 1;
314 }
315 }
316
DecodeZero(Word Index)317 static void DecodeZero(Word Index)
318 {
319 Boolean IndFlag, OK;
320
321 if (ChkArgCnt(1, 1))
322 {
323 BAsmCode[0] = Index;
324 IndFlag = *ArgStr[1].Str == '*';
325 BAsmCode[1] = EvalStrIntExpressionOffs(&ArgStr[1], IndFlag, UInt7, &OK);
326 if (OK)
327 {
328 if (IndFlag)
329 BAsmCode[1] |= 0x80;
330 CodeLen = 2;
331 }
332 }
333 }
334
335 /*--------------------------------------------------------------------------*/
336 /* Code Table Handling */
337
AddFixed(const char * pName,Word Code)338 static void AddFixed(const char *pName, Word Code)
339 {
340 AddInstTable(InstTable, pName, Code, DecodeFixed);
341 }
342
AddOneReg(const char * pName,Word Code)343 static void AddOneReg(const char *pName, Word Code)
344 {
345 AddInstTable(InstTable, pName, Code, DecodeOneReg);
346 }
347
AddImm(const char * pName,Word Code)348 static void AddImm(const char *pName, Word Code)
349 {
350 AddInstTable(InstTable, pName, Code, DecodeImm);
351 }
352
AddRegImm(const char * pName,Word Code)353 static void AddRegImm(const char *pName, Word Code)
354 {
355 AddInstTable(InstTable, pName, Code, DecodeRegImm);
356 }
357
AddRegAbs(const char * pName,Word Code)358 static void AddRegAbs(const char *pName, Word Code)
359 {
360 AddInstTable(InstTable, pName, Code, DecodeRegAbs);
361 }
362
AddRegRel(const char * pName,Word Code)363 static void AddRegRel(const char *pName, Word Code)
364 {
365 AddInstTable(InstTable, pName, Code, DecodeRegRel);
366 }
367
AddCondAbs(const char * pName,Word Code)368 static void AddCondAbs(const char *pName, Word Code)
369 {
370 AddInstTable(InstTable, pName, Code, DecodeCondAbs);
371 }
372
AddCondRel(const char * pName,Word Code)373 static void AddCondRel(const char *pName, Word Code)
374 {
375 AddInstTable(InstTable, pName, Code, DecodeCondRel);
376 }
377
AddRegAbs2(const char * pName,Word Code)378 static void AddRegAbs2(const char *pName, Word Code)
379 {
380 AddInstTable(InstTable, pName, Code, DecodeRegAbs2);
381 }
382
AddBrAbs(const char * pName,Word Code)383 static void AddBrAbs(const char *pName, Word Code)
384 {
385 AddInstTable(InstTable, pName, Code, DecodeBrAbs);
386 }
387
AddCond(const char * pName,Word Code)388 static void AddCond(const char *pName, Word Code)
389 {
390 AddInstTable(InstTable, pName, Code, DecodeCond);
391 }
392
AddZero(const char * pName,Word Code)393 static void AddZero(const char *pName, Word Code)
394 {
395 AddInstTable(InstTable, pName, Code, DecodeZero);
396 }
397
InitFields(void)398 static void InitFields(void)
399 {
400 InstTable = CreateInstTable(203);
401
402 AddFixed("NOP", 0xc0);
403 AddFixed("HALT", 0x40);
404 AddFixed("LPSL", 0x93);
405 AddFixed("LPSU", 0x92);
406 AddFixed("SPSL", 0x13);
407 AddFixed("SPSU", 0x12);
408
409 AddOneReg("ADDZ", 0x80);
410 AddOneReg("ANDZ", 0x40);
411 AddOneReg("COMZ", 0xe0);
412 AddOneReg("DAR", 0x94);
413 AddOneReg("EORZ", 0x20);
414 AddOneReg("IORZ", 0x60);
415 AddOneReg("LODZ", 0x00);
416 AddOneReg("REDC", 0x30);
417 AddOneReg("REDD", 0x70);
418 AddOneReg("RRL", 0xd0);
419 AddOneReg("RRR", 0x50);
420 AddOneReg("STRZ", 0xc0);
421 AddOneReg("SUBZ", 0xa0);
422 AddOneReg("WRTC", 0xb0);
423 AddOneReg("WRTD", 0xf0);
424
425 AddImm("CPSL", 0x75);
426 AddImm("CPSU", 0x74);
427 AddImm("PPSL", 0x77);
428 AddImm("PPSU", 0x76);
429 AddImm("TPSL", 0xb5);
430 AddImm("TPSU", 0xb4);
431
432 AddRegImm("ADDI", 0x84);
433 AddRegImm("ANDI", 0x44);
434 AddRegImm("COMI", 0xe4);
435 AddRegImm("EORI", 0x24);
436 AddRegImm("IORI", 0x64);
437 AddRegImm("LODI", 0x04);
438 AddRegImm("REDE", 0x54);
439 AddRegImm("SUBI", 0xa4);
440 AddRegImm("TMI", 0xf4);
441 AddRegImm("WRTE", 0xd4);
442
443 AddRegAbs("ADDA", 0x8c);
444 AddRegAbs("ANDA", 0x4c);
445 AddRegAbs("COMA", 0xec);
446 AddRegAbs("EORA", 0x2c);
447 AddRegAbs("IORA", 0x6c);
448 AddRegAbs("LODA", 0x0c);
449 AddRegAbs("STRA", 0xcc);
450 AddRegAbs("SUBA", 0xac);
451
452 AddRegRel("ADDR", 0x88);
453 AddRegRel("ANDR", 0x48);
454 AddRegRel("BDRR", 0xf8);
455 AddRegRel("BIRR", 0xd8);
456 AddRegRel("BRNR", 0x58);
457 AddRegRel("BSNR", 0x78);
458 AddRegRel("COMR", 0xe8);
459 AddRegRel("EORR", 0x28);
460 AddRegRel("IORR", 0x68);
461 AddRegRel("LODR", 0x08);
462 AddRegRel("STRR", 0xc8);
463 AddRegRel("SUBR", 0xa8);
464
465 AddCondAbs("BCFA", 0x9c);
466 AddCondAbs("BCTA", 0x1c);
467 AddCondAbs("BSFA", 0xbc);
468 AddCondAbs("BSTA", 0x3c);
469
470 AddCondRel("BCFR", 0x98);
471 AddCondRel("BCTR", 0x18);
472 AddCondRel("BSFR", 0xb8);
473 AddCondRel("BSTR", 0x38);
474
475 AddRegAbs2("BDRA", 0xfc);
476 AddRegAbs2("BIRA", 0xdc);
477 AddRegAbs2("BRNA", 0x5c);
478 AddRegAbs2("BSNA", 0x7c);
479
480 AddBrAbs("BSXA", 0xbf);
481 AddBrAbs("BXA", 0x9f);
482
483 AddCond("RETC", 0x14);
484 AddCond("RETE", 0x34);
485
486 AddZero("ZBRR", 0x9b);
487 AddZero("ZBSR", 0xbb);
488 }
489
DeinitFields(void)490 static void DeinitFields(void)
491 {
492 DestroyInstTable(InstTable);
493 }
494
495 /*--------------------------------------------------------------------------*/
496 /* Callbacks */
497
MakeCode_2650(void)498 static void MakeCode_2650(void)
499 {
500 char *pPos;
501
502 CodeLen = 0;
503
504 DontPrint = False;
505
506 /* Nullanweisung */
507
508 if ((*OpPart.Str == '\0') && (ArgCnt == 0))
509 return;
510
511 /* Pseudoanweisungen */
512
513 if (DecodeIntelPseudo(False)) return;
514
515 /* try to split off first (register) operand from instruction */
516
517 pPos = strchr(OpPart.Str, ',');
518 if (pPos)
519 {
520 int ArgC;
521
522 IncArgCnt();
523 for (ArgC = ArgCnt - 1; ArgC >= 1; ArgC--)
524 StrCompCopy(&ArgStr[ArgC + 1], &ArgStr[ArgC]);
525 StrCompSplitRight(&OpPart, &ArgStr[1], pPos);
526 }
527
528 /* alles aus der Tabelle */
529
530 if (!LookupInstTable(InstTable, OpPart.Str))
531 WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
532 }
533
IsDef_2650(void)534 static Boolean IsDef_2650(void)
535 {
536 return FALSE;
537 }
538
SwitchFrom_2650(void)539 static void SwitchFrom_2650(void)
540 {
541 DeinitFields();
542 }
543
SwitchTo_2650(void)544 static void SwitchTo_2650(void)
545 {
546 PFamilyDescr pDescr;
547
548 TurnWords = False; ConstMode = ConstModeMoto;
549
550 pDescr = FindFamilyByName("2650");
551 PCSymbol = "$"; HeaderID = pDescr->Id; NOPCode = 0xc0;
552 DivideChars = ","; HasAttrs = False;
553
554 ValidSegs = (1 << SegCode);
555 Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
556 SegLimits[SegCode] = 0x1fffl;
557
558 MakeCode = MakeCode_2650; IsDef = IsDef_2650;
559
560 SwitchFrom = SwitchFrom_2650; InitFields();
561 }
562
563 /*--------------------------------------------------------------------------*/
564 /* Initialisierung */
565
code2650_init(void)566 void code2650_init(void)
567 {
568 CPU2650 = AddCPU("2650", SwitchTo_2650);
569 }
570