1 /* codecop4.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Codegeneratormodul COP4-Familie */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12
13 #include "bpemu.h"
14 #include "asmdef.h"
15 #include "asmpars.h"
16 #include "asmsub.h"
17 #include "asmitree.h"
18 #include "headids.h"
19 #include "codevars.h"
20 #include "intpseudo.h"
21 #include "natpseudo.h"
22 #include "errmsg.h"
23
24 #include "codecop4.h"
25
26 #define FixedOrderCnt 44
27 #define ImmOrderCnt 3
28
29 #define M_CPUCOP410 (1 << 0)
30 #define M_CPUCOP420 (1 << 1)
31 #define M_CPUCOP440 (1 << 2)
32 #define M_CPUCOP444 (1 << 3)
33
34 typedef struct
35 {
36 Word CPUMask;
37 Word Code;
38 } FixedOrder;
39
40 static CPUVar CPUCOP410, CPUCOP420, CPUCOP440, CPUCOP444;
41 static IntType AdrInt;
42
43 static FixedOrder *FixedOrders, *ImmOrders;
44
45 /*---------------------------------------------------------------------------*/
46 /* Code Generators */
47
DecodeFixed(Word Index)48 static void DecodeFixed(Word Index)
49 {
50 FixedOrder *pOrder = FixedOrders + Index;
51
52 if (ChkArgCnt(0, 0)
53 && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
54 {
55 if (Hi(pOrder->Code))
56 BAsmCode[CodeLen++] = Hi(pOrder->Code);
57 BAsmCode[CodeLen++] = Lo(pOrder->Code);
58 }
59 }
60
DecodeSK(Word Index)61 static void DecodeSK(Word Index)
62 {
63 if (ChkArgCnt(1, 1))
64 {
65 Byte Bit;
66 Boolean OK;
67
68 Bit = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
69 if (OK)
70 {
71 if (Index)
72 BAsmCode[CodeLen++] = Index;
73 BAsmCode[CodeLen++] = 0x01 | ((Bit & 1) << 4) | (Bit & 2);
74 }
75 }
76 }
77
DecodeImm(Word Index)78 static void DecodeImm(Word Index)
79 {
80 FixedOrder *pOrder = ImmOrders + Index;
81
82 if (ChkArgCnt(1, 1)
83 && (ChkExactCPUMask(pOrder->CPUMask, CPUCOP410) >= 0))
84 {
85 Byte Val;
86 Boolean OK;
87
88 Val = EvalStrIntExpression(&ArgStr[1], Int4, &OK);
89 if (OK)
90 {
91 if (Hi(pOrder->Code))
92 BAsmCode[CodeLen++] = Hi(pOrder->Code);
93 BAsmCode[CodeLen++] = Lo(pOrder->Code) | (Val & 0x0f);
94 }
95 }
96 }
97
DecodeJmp(Word Index)98 static void DecodeJmp(Word Index)
99 {
100 if (ChkArgCnt(1, 1))
101 {
102 Word Addr;
103 Boolean OK;
104
105 Addr = EvalStrIntExpression(&ArgStr[1], AdrInt, &OK);
106 if (OK)
107 {
108 BAsmCode[CodeLen++] = Index | Hi(Addr);
109 BAsmCode[CodeLen++] = Lo(Addr);
110 }
111 }
112 }
113
DecodeReg(Word Index)114 static void DecodeReg(Word Index)
115 {
116 if (ChkArgCnt(1, 1))
117 {
118 Byte Reg;
119 Boolean OK;
120
121 Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
122 if (OK)
123 {
124 BAsmCode[CodeLen++] = Index | ((Reg & 3) << 4);;
125 }
126 }
127 }
128
DecodeAISC(Word Index)129 static void DecodeAISC(Word Index)
130 {
131 UNUSED(Index);
132
133 if (ChkArgCnt(1, 1))
134 {
135 Byte Val;
136 Boolean OK;
137 tSymbolFlags Flags;
138
139 Val = EvalStrIntExpressionWithFlags(&ArgStr[1], Int4, &OK, &Flags);
140 if (mFirstPassUnknown(Flags))
141 Val = 1;
142 if (OK)
143 {
144 if (!Val) WrError(ErrNum_UnderRange);
145 else
146 BAsmCode[CodeLen++] = 0x50 | (Val & 0x0f);
147 }
148 }
149 }
150
DecodeRMB(Word Index)151 static void DecodeRMB(Word Index)
152 {
153 UNUSED(Index);
154
155 if (ChkArgCnt(1, 1))
156 {
157 Byte Reg;
158 Boolean OK;
159 static Byte Vals[4] = { 0x4c, 0x45, 0x42, 0x43 };
160
161 Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
162 if (OK)
163 {
164 BAsmCode[CodeLen++] = Vals[Reg & 3];
165 }
166 }
167 }
168
DecodeSMB(Word Index)169 static void DecodeSMB(Word Index)
170 {
171 UNUSED(Index);
172
173 if (ChkArgCnt(1, 1))
174 {
175 Byte Reg;
176 Boolean OK;
177 static Byte Vals[4] = { 0x4d, 0x47, 0x46, 0x4b };
178
179 Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
180 if (OK)
181 {
182 BAsmCode[CodeLen++] = Vals[Reg & 3];
183 }
184 }
185 }
186
DecodeXAD(Word Index)187 static void DecodeXAD(Word Index)
188 {
189 UNUSED(Index);
190
191 if (ChkArgCnt(2, 2))
192 {
193 Byte Reg1, Reg2;
194 Boolean OK;
195 tSymbolFlags Flags;
196
197 Reg1 = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt2, &OK, &Flags);
198 if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
199 Reg1 = 3;
200 if (OK)
201 {
202 Reg2 = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
203 if (mFirstPassUnknown(Flags) && (MomCPU < CPUCOP420))
204 Reg2 = 15;
205 if (OK)
206 {
207 if ((MomCPU < CPUCOP420) && ((Reg1 != 3) || (Reg2 != 15))) WrError(ErrNum_InvAddrMode);
208 else
209 {
210 BAsmCode[CodeLen++] = 0x23;
211 BAsmCode[CodeLen++] = 0x80 | (Reg1 << 4) | Reg2;
212 }
213 }
214 }
215 }
216 }
217
DecodeLBI(Word Index)218 static void DecodeLBI(Word Index)
219 {
220 UNUSED(Index);
221
222 if (ChkArgCnt(2, 2))
223 {
224 Byte Reg, Val;
225 Boolean OK;
226
227 Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
228 if (OK)
229 {
230 tSymbolFlags Flags;
231
232 Val = EvalStrIntExpressionWithFlags(&ArgStr[2], UInt4, &OK, &Flags);
233 if (mFirstPassUnknown(Flags))
234 Val = 0;
235 if (OK)
236 {
237 if ((Val > 0) && (Val < 9))
238 {
239 if (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0)
240 {
241 BAsmCode[CodeLen++] = 0x33;
242 BAsmCode[CodeLen++] = 0x80 | (Reg << 4) | Val;
243 }
244 }
245 else
246 {
247 Val = (Val - 1) & 0x0f;
248 BAsmCode[CodeLen++] = (Reg << 4) | Val;
249 }
250 }
251 }
252 }
253 }
254
DecodeLDD(Word Index)255 static void DecodeLDD(Word Index)
256 {
257 UNUSED(Index);
258
259 if (ChkArgCnt(2, 2)
260 && (ChkExactCPUMask(M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP440, CPUCOP410) >= 0))
261 {
262 Byte Reg, Val;
263 Boolean OK;
264
265 Reg = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
266 if (OK)
267 {
268 Val = EvalStrIntExpression(&ArgStr[2], UInt4, &OK);
269 if (OK)
270 {
271 BAsmCode[CodeLen++] = 0x23;
272 BAsmCode[CodeLen++] = (Reg << 4) | Val;
273 }
274 }
275 }
276 }
277
DecodeJSRP(Word Index)278 static void DecodeJSRP(Word Index)
279 {
280 UNUSED(Index);
281
282 if (ChkArgCnt(1, 1))
283 {
284 Word Addr;
285 Boolean OK;
286 tSymbolFlags Flags;
287
288 Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
289 if (mFirstPassUnknown(Flags))
290 Addr = 2 << 6;
291 if (OK)
292 {
293 if (((Addr >> 6) != 2) || (Addr == 0xbf)) WrError(ErrNum_NotFromThisAddress);
294 else if ((EProgCounter() >> 7) == 1) WrError(ErrNum_NotOnThisAddress);
295 else
296 BAsmCode[CodeLen++] = 0x80 | (Addr & 0x3f);
297 }
298 }
299 }
300
DecodeJP(Word Index)301 static void DecodeJP(Word Index)
302 {
303 UNUSED(Index);
304
305 if (ChkArgCnt(1, 1))
306 {
307 Word Addr, CurrPC;
308 Boolean OK;
309 tSymbolFlags Flags;
310
311 Addr = EvalStrIntExpressionWithFlags(&ArgStr[1], AdrInt, &OK, &Flags);
312 if (mFirstPassUnknown(Flags))
313 Addr = EProgCounter() & (~0x1f);
314 if (OK)
315 {
316 CurrPC = EProgCounter();
317 if ((Addr & 0x3f) == 0x3f)
318 WrError(ErrNum_NotFromThisAddress);
319 if (((CurrPC >> 7) == 1) && ((Addr >> 7) == 1))
320 BAsmCode[CodeLen++] = 0x80 | (Addr & 0x7f);
321 else
322 {
323 Word PossPage;
324
325 PossPage = CurrPC >> 6;
326 if ((CurrPC & 0x3f) == 0x3f)
327 {
328 PossPage++;
329 if (mFirstPassUnknown(Flags))
330 Addr += 0x40;
331 }
332
333 if (PossPage == (Addr >> 6))
334 BAsmCode[CodeLen++] = 0xc0 | (Addr & 0x3f);
335 else
336 WrError(ErrNum_NotFromThisAddress);
337 }
338 }
339 }
340 }
341
342 /*---------------------------------------------------------------------------*/
343 /* Code Table Handling */
344
AddFixed(const char * NName,Word NCode,Word NMask)345 static void AddFixed(const char *NName, Word NCode, Word NMask)
346 {
347 if (InstrZ >= FixedOrderCnt)
348 exit(0);
349 else
350 {
351 FixedOrders[InstrZ].Code = NCode;
352 FixedOrders[InstrZ].CPUMask = NMask;
353 AddInstTable(InstTable, NName, InstrZ++, DecodeFixed);
354 }
355 }
356
AddImm(const char * NName,Word NCode,Word NMask)357 static void AddImm(const char *NName, Word NCode, Word NMask)
358 {
359 if (InstrZ >= ImmOrderCnt)
360 exit(0);
361 else
362 {
363 ImmOrders[InstrZ].Code = NCode;
364 ImmOrders[InstrZ].CPUMask = NMask;
365 AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
366 }
367 }
368
InitFields(void)369 static void InitFields(void)
370 {
371 InstTable = CreateInstTable(173);
372
373 FixedOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * FixedOrderCnt);
374 InstrZ = 0;
375 AddFixed("ASC" , 0x30, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
376 AddFixed("ADD" , 0x31, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
377 AddFixed("CLRA" , 0x00, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
378 AddFixed("COMP" , 0x40, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
379 AddFixed("NOP" , 0x44, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
380 AddFixed("RC" , 0x32, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
381 AddFixed("SC" , 0x22, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
382 AddFixed("XOR" , 0x02, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
383 AddFixed("JID" , 0xff, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
384 AddFixed("RET" , 0x48, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
385 AddFixed("RETSK", 0x49, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
386 AddFixed("CAMQ" , 0x333c, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
387 AddFixed("CAME" , 0x331f, M_CPUCOP440 );
388 AddFixed("CAMT" , 0x333f, M_CPUCOP440 | M_CPUCOP444);
389 AddFixed("CAMR" , 0x333d, M_CPUCOP440 );
390 AddFixed("CEMA" , 0x330f, M_CPUCOP440 );
391 AddFixed("CTMA" , 0x332f, M_CPUCOP440 | M_CPUCOP444);
392 AddFixed("LQID" , 0xbf, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
393 AddFixed("CAB" , 0x50, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
394 AddFixed("CBA" , 0x4e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
395 AddFixed("SKC" , 0x20, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
396 AddFixed("SKE" , 0x21, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
397 AddFixed("SKGZ" , 0x3321, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
398 AddFixed("SKSZ" , 0x331c, M_CPUCOP440 | M_CPUCOP444);
399 AddFixed("ING" , 0x332a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
400 AddFixed("INH" , 0x332b, M_CPUCOP440 );
401 AddFixed("INL" , 0x332e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
402 AddFixed("INR" , 0x332d, M_CPUCOP440 );
403 AddFixed("OBD" , 0x333e, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
404 AddFixed("OMG" , 0x333a, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
405 AddFixed("OMH" , 0x333b, M_CPUCOP440 );
406 AddFixed("XAS" , 0x4f, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
407 AddFixed("ADT" , 0x4a, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
408 AddFixed("CASC" , 0x10, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
409 AddFixed("CQMA" , 0x332c, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
410 AddFixed("SKT" , 0x41, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
411 AddFixed("XABR" , 0x12, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
412 AddFixed("ININ" , 0x3328, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
413 AddFixed("INIL" , 0x3329, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
414 AddFixed("OR" , 0x331a, M_CPUCOP440 );
415 AddFixed("LID" , 0x3319, M_CPUCOP440 );
416 AddFixed("XAN" , 0x330b, M_CPUCOP440 );
417 AddFixed("HALT" , 0x3338, M_CPUCOP444);
418 AddFixed("IT" , 0x3339, M_CPUCOP444);
419
420 AddInstTable(InstTable, "SKGBZ", 0x33, DecodeSK);
421 AddInstTable(InstTable, "SKMBZ", 0x00, DecodeSK);
422
423 ImmOrders = (FixedOrder*)malloc(sizeof(FixedOrder) * ImmOrderCnt);
424 InstrZ = 0;
425 AddImm("STII" , 0x70, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
426 AddImm("LEI" , 0x3360, M_CPUCOP410 | M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
427 AddImm("OGI" , 0x3350, M_CPUCOP420 | M_CPUCOP440 | M_CPUCOP444);
428
429 AddInstTable(InstTable, "JMP" , 0x60, DecodeJmp);
430 AddInstTable(InstTable, "JSR" , 0x68, DecodeJmp);
431
432 AddInstTable(InstTable, "LD" , 0x05, DecodeReg);
433 AddInstTable(InstTable, "X" , 0x06, DecodeReg);
434 AddInstTable(InstTable, "XDS" , 0x07, DecodeReg);
435 AddInstTable(InstTable, "XIS" , 0x04, DecodeReg);
436
437 AddInstTable(InstTable, "AISC" , 0x00, DecodeAISC);
438 AddInstTable(InstTable, "RMB" , 0x00, DecodeRMB);
439 AddInstTable(InstTable, "SMB" , 0x00, DecodeSMB);
440
441 AddInstTable(InstTable, "XAD" , 0x00, DecodeXAD);
442
443 AddInstTable(InstTable, "LBI" , 0x00, DecodeLBI);
444
445 AddInstTable(InstTable, "LDD" , 0x00, DecodeLDD);
446
447 AddInstTable(InstTable, "JSRP" , 0x00, DecodeJSRP);
448
449 AddInstTable(InstTable, "JP" , 0x00, DecodeJP);
450 }
451
DeinitFields(void)452 static void DeinitFields(void)
453 {
454 free(FixedOrders);
455 free(ImmOrders);
456 DestroyInstTable(InstTable);
457 }
458
459 /*---------------------------------------------------------------------------*/
460
MakeCode_COP4(void)461 static void MakeCode_COP4(void)
462 {
463 CodeLen = 0; DontPrint = False;
464
465 /* zu ignorierendes */
466
467 if (*OpPart.Str == '\0') return;
468
469 /* pseudo instructions */
470
471 if (DecodeNatPseudo()) return;
472 if (DecodeIntelPseudo(False)) return;
473
474 /* machine instructions */
475
476 if (!LookupInstTable(InstTable, OpPart.Str))
477 WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
478 }
479
SwitchFrom_COP4(void)480 static void SwitchFrom_COP4(void)
481 {
482 DeinitFields();
483 }
484
IsDef_COP4(void)485 static Boolean IsDef_COP4(void)
486 {
487 return False;
488 }
489
SwitchTo_COP4(void)490 static void SwitchTo_COP4(void)
491 {
492 PFamilyDescr pDescr;
493
494 pDescr = FindFamilyByName("COP4");
495
496 TurnWords = False; ConstMode = ConstModeC;
497
498 PCSymbol = "."; HeaderID = pDescr->Id;
499 NOPCode = 0x44;
500 DivideChars = ","; HasAttrs = False;
501
502 ValidSegs = (1 << SegCode);
503 Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
504 if (MomCPU >= CPUCOP440)
505 {
506 SegLimits[SegCode] = 0x7ff;
507 AdrInt = UInt11;
508 }
509 else if (MomCPU >= CPUCOP420)
510 {
511 SegLimits[SegCode] = 0x3ff;
512 AdrInt = UInt10;
513 }
514 else
515 {
516 SegLimits[SegCode] = 0x1ff;
517 AdrInt = UInt9;
518 }
519
520 MakeCode = MakeCode_COP4; IsDef = IsDef_COP4;
521 SwitchFrom = SwitchFrom_COP4; InitFields();
522 }
523
codecop4_init(void)524 void codecop4_init(void)
525 {
526 CPUCOP410 = AddCPU("COP410", SwitchTo_COP4);
527 CPUCOP420 = AddCPU("COP420", SwitchTo_COP4);
528 CPUCOP440 = AddCPU("COP440", SwitchTo_COP4);
529 CPUCOP444 = AddCPU("COP444", SwitchTo_COP4);
530 }
531