1 /* code75xx.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* Codegenerator NEC 75xx                                                    */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include <string.h>
13 #include <ctype.h>
14 
15 #include "nls.h"
16 #include "strutil.h"
17 #include "headids.h"
18 #include "bpemu.h"
19 #include "asmdef.h"
20 #include "asmsub.h"
21 #include "asmpars.h"
22 #include "asmitree.h"
23 #include "codepseudo.h"
24 #include "intpseudo.h"
25 #include "codevars.h"
26 #include "errmsg.h"
27 
28 #include "code75xx.h"
29 
30 static CPUVar CPU7566, CPU7508;
31 static IntType CodeIntType, DataIntType;
32 
33 /*-------------------------------------------------------------------------*/
34 /* code generation */
35 
PutCode(Word Code)36 static void PutCode(Word Code)
37 {
38   CodeLen = 0;
39   if (Hi(Code))
40     BAsmCode[CodeLen++] = Hi(Code);
41   BAsmCode[CodeLen++] = Lo(Code);
42 }
43 
DecodeFixed(Word Index)44 static void DecodeFixed(Word Index)
45 {
46   if (ChkArgCnt(0, 0))
47     PutCode(Index);
48 }
49 
DecodeImm4(Word Index)50 static void DecodeImm4(Word Index)
51 {
52   if (ChkArgCnt(1, 1))
53   {
54     tEvalResult EvalResult;
55     Word Value = EvalStrIntExpressionWithResult(&ArgStr[1], Int4, &EvalResult);
56 
57     if (EvalResult.OK)
58     {
59       PutCode(Index | (Value & 15));
60       if (Memo("OP"))
61         ChkSpace(SegIO, EvalResult.AddrSpaceMask);
62     }
63   }
64 }
65 
DecodeImm5(Word Index)66 static void DecodeImm5(Word Index)
67 {
68   if (ChkArgCnt(1, 1))
69   {
70     Boolean OK;
71     Word Value;
72 
73     Value = EvalStrIntExpression(&ArgStr[1], Int5, &OK);
74     if (OK)
75       PutCode(Index | (Value & 31));
76   }
77 }
78 
DecodeImm8(Word Index)79 static void DecodeImm8(Word Index)
80 {
81   if (ChkArgCnt(1, 1))
82   {
83     Boolean OK;
84     Word Value;
85 
86     Value = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
87     if (OK)
88     {
89       PutCode(Index);
90       BAsmCode[CodeLen++] = Value;
91     }
92   }
93 }
94 
DecodeImm2(Word Index)95 static void DecodeImm2(Word Index)
96 {
97   if (ChkArgCnt(1, 1))
98   {
99     Boolean OK;
100     Word Value;
101 
102     Value = EvalStrIntExpression(&ArgStr[1], UInt2, &OK);
103     if (OK)
104       PutCode(Index | (Value & 3));
105   }
106 }
107 
DecodeImm3(Word Index)108 static void DecodeImm3(Word Index)
109 {
110   if (ChkArgCnt(1, 1))
111   {
112     tEvalResult EvalResult;
113     Word Value = EvalStrIntExpressionWithResult(&ArgStr[1], UInt3, &EvalResult);
114     if (EvalResult.OK)
115     {
116       PutCode(Index | (Value & 7));
117       if (Memo("OP"))
118         ChkSpace(SegIO, EvalResult.AddrSpaceMask);
119     }
120   }
121 }
122 
DecodePR(Word Index)123 static void DecodePR(Word Index)
124 {
125   if (!ChkArgCnt(1, 1));
126   else if (!as_strcasecmp(ArgStr[1].Str, "HL-"))
127     PutCode(Index | 0x10);
128   else if (!as_strcasecmp(ArgStr[1].Str, "HL+"))
129     PutCode(Index | 0x11);
130   else if (!as_strcasecmp(ArgStr[1].Str, "HL"))
131     PutCode(Index | 0x12);
132   else if ((MomCPU == CPU7508) && (!as_strcasecmp(ArgStr[1].Str, "DL")))
133     PutCode(Index | 0x00);
134   else if ((MomCPU == CPU7508) && (!as_strcasecmp(ArgStr[1].Str, "DE")))
135     PutCode(Index | 0x01);
136   else
137     WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
138 }
139 
DecodeDataMem(Word Index)140 static void DecodeDataMem(Word Index)
141 {
142   if (ChkArgCnt(1, 1))
143   {
144     tEvalResult EvalResult;
145     Word Value = EvalStrIntExpressionWithResult(&ArgStr[1], DataIntType, &EvalResult);
146     if (EvalResult.OK)
147     {
148       PutCode(Index);
149       BAsmCode[CodeLen++] = Value & SegLimits[SegData];
150       ChkSpace(SegData, EvalResult.AddrSpaceMask);
151     }
152   }
153 }
154 
DecodeAbs(Word Index)155 static void DecodeAbs(Word Index)
156 {
157   if (ChkArgCnt(1, 1))
158   {
159     tEvalResult EvalResult;
160     Word Address;
161     IntType Type = CodeIntType;
162     Word SegLimit = SegLimits[SegCode];
163 
164     /* CALL can only address first 2K on 7508! */
165 
166     if ((Memo("CALL")) && (MomCPU == CPU7508))
167     {
168       Type = UInt11;
169       SegLimit = 0x1fff;
170     }
171 
172     Address = EvalStrIntExpressionWithResult(&ArgStr[1], Type, &EvalResult);
173     if (EvalResult.OK)
174     {
175       PutCode(Index | (Address & SegLimit));
176       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
177     }
178   }
179 }
180 
DecodeJCP(Word Index)181 static void DecodeJCP(Word Index)
182 {
183   if (ChkArgCnt(1, 1))
184   {
185     tEvalResult EvalResult;
186     Word Address = EvalStrIntExpressionWithResult(&ArgStr[1], CodeIntType, &EvalResult);
187 
188     if (EvalResult.OK && ChkSamePage(Address, EProgCounter() + 1, 6, EvalResult.Flags))
189     {
190       PutCode(Index | (Address & 0x3f));
191       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
192     }
193   }
194 }
195 
DecodeCAL(Word Index)196 static void DecodeCAL(Word Index)
197 {
198   if (ChkArgCnt(1, 1))
199   {
200     tEvalResult EvalResult;
201     Word Address = EvalStrIntExpressionWithResult(&ArgStr[1], CodeIntType, &EvalResult);
202 
203     if (mFirstPassUnknown(EvalResult.Flags))
204       Address = (Address & 0x1c7) | 0x100;
205     if (EvalResult.OK)
206     {
207       if ((Address & 0x338) != 0x100) WrError(ErrNum_OverRange);
208       else
209         PutCode(Index | ((Address & 0x0c0) >> 3) | (Address & 7));
210       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
211     }
212   }
213 }
214 
DecodeLHLT(Word Index)215 static void DecodeLHLT(Word Index)
216 {
217   if (ChkArgCnt(1, 1))
218   {
219     tEvalResult EvalResult;
220     Word Address = EvalStrIntExpressionWithResult(&ArgStr[1], CodeIntType, &EvalResult);
221 
222     if (mFirstPassUnknown(EvalResult.Flags))
223       Address = (Address & 0x00cf) | 0x00c0;
224     if (EvalResult.OK)
225     {
226       if ((Address < 0xc0) || (Address > 0xcf)) WrError(ErrNum_OverRange);
227       else
228         PutCode(Index | (Address & 0xf));
229       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
230     }
231   }
232 }
233 
DecodeCALT(Word Index)234 static void DecodeCALT(Word Index)
235 {
236   if (ChkArgCnt(1, 1))
237   {
238     tEvalResult EvalResult;
239     Word Address = EvalStrIntExpressionWithResult(&ArgStr[1], CodeIntType, &EvalResult);
240 
241     if (mFirstPassUnknown(EvalResult.Flags))
242       Address = (Address & 0x00ff) | 0x00c0;
243     if (EvalResult.OK)
244     {
245       if ((Address < 0xd0) || (Address > 0xff)) WrError(ErrNum_OverRange);
246       else
247         PutCode(Index | (Address & 0x3f));
248       ChkSpace(SegCode, EvalResult.AddrSpaceMask);
249     }
250   }
251 }
252 
DecodeLogPort(Word Index)253 static void DecodeLogPort(Word Index)
254 {
255   if (ChkArgCnt(2, 2))
256   {
257     tEvalResult EvalResult;
258     Word Port, Mask;
259 
260     Port = EvalStrIntExpressionWithResult(&ArgStr[1], UInt4, &EvalResult);
261     if (EvalResult.OK)
262     {
263       ChkSpace(SegIO, EvalResult.AddrSpaceMask);
264       Mask = EvalStrIntExpressionWithResult(&ArgStr[2], UInt4, &EvalResult);
265       if (EvalResult.OK)
266         PutCode(Index | ((Mask & 15) << 4) | (Port & 15));
267     }
268   }
269 }
270 
271 /*-------------------------------------------------------------------------*/
272 /* dynamische Codetabellenverwaltung */
273 
AddFixed(const char * NewName,Word NewCode)274 static void AddFixed(const char *NewName, Word NewCode)
275 {
276   AddInstTable(InstTable, NewName, NewCode, DecodeFixed);
277 }
278 
AddImm4(const char * NewName,Word NewCode)279 static void AddImm4(const char *NewName, Word NewCode)
280 {
281   AddInstTable(InstTable, NewName, NewCode, DecodeImm4);
282 }
283 
AddImm2(const char * NewName,Word NewCode)284 static void AddImm2(const char *NewName, Word NewCode)
285 {
286   AddInstTable(InstTable, NewName, NewCode, DecodeImm2);
287 }
288 
AddImm5(const char * NewName,Word NewCode)289 static void AddImm5(const char *NewName, Word NewCode)
290 {
291   AddInstTable(InstTable, NewName, NewCode, DecodeImm5);
292 }
293 
AddImm8(const char * NewName,Word NewCode)294 static void AddImm8(const char *NewName, Word NewCode)
295 {
296   AddInstTable(InstTable, NewName, NewCode, DecodeImm8);
297 }
298 
AddImm3(const char * NewName,Word NewCode)299 static void AddImm3(const char *NewName, Word NewCode)
300 {
301   AddInstTable(InstTable, NewName, NewCode, DecodeImm3);
302 }
303 
AddPR(const char * NewName,Word NewCode)304 static void AddPR(const char *NewName, Word NewCode)
305 {
306   AddInstTable(InstTable, NewName, NewCode, DecodePR);
307 }
308 
AddDataMem(const char * NewName,Word NewCode)309 static void AddDataMem(const char *NewName, Word NewCode)
310 {
311   AddInstTable(InstTable, NewName, NewCode, DecodeDataMem);
312 }
313 
AddAbs(const char * NewName,Word NewCode)314 static void AddAbs(const char *NewName, Word NewCode)
315 {
316   AddInstTable(InstTable, NewName, NewCode, DecodeAbs);
317 }
318 
InitFields(void)319 static void InitFields(void)
320 {
321   InstTable = CreateInstTable(103);
322   AddFixed("ST"    , 0x57);
323   AddFixed("XAL"   , 0x7b);
324   AddFixed("ASC"   , 0x7d);
325   AddFixed("ACSC"  , 0x7c);
326   AddFixed("EXL"   , 0x7e);
327   AddFixed("CMA"   , 0x7f);
328   AddFixed("RC"    , 0x78);
329   AddFixed("SC"    , 0x79);
330   AddFixed("ILS"   , 0x59);
331   AddFixed("DLS"   , 0x58);
332   AddFixed("RT"    , 0x53);
333   AddFixed("RTS"   , 0x5b);
334   AddFixed("TAMSP" , 0x3f31);
335   AddFixed("SKC"   , 0x5a);
336   AddFixed("SKAEM" , 0x5f);
337   AddFixed("TAMSIO", 0x3f3e);
338   AddFixed("TSIOAM", 0x3f3a);
339   AddFixed("SIO"   , 0x3f33);
340   AddFixed("TIMER" , 0x3f32);
341   AddFixed("TCNTAM", 0x3f3b);
342   AddFixed("IPL"   , 0x70);
343   AddFixed("OPL"   , 0x72);
344   AddFixed("HALT"  , 0x3f36);
345   AddFixed("STOP"  , 0x3f37);
346   AddFixed("NOP"  , 0x00);
347   if (MomCPU == CPU7566)
348   {
349     AddFixed("RPBL"  , 0x5c);
350     AddFixed("SPBL"  , 0x5d);
351   }
352   if (MomCPU == CPU7508)
353   {
354     AddFixed("LAMTL", 0x3f34);
355     AddFixed("TAD", 0x3eaa);
356     AddFixed("TAE", 0x3e8a);
357     AddFixed("TAH", 0x3eba);
358     AddFixed("TAL", 0x3e9a);
359     AddFixed("TDA", 0x3eab);
360     AddFixed("TEA", 0x3e8b);
361     AddFixed("THA", 0x3ebb);
362     AddFixed("TLA", 0x3e9b);
363     AddFixed("XAD", 0x4a);
364     AddFixed("XAE", 0x4b);
365     AddFixed("XAH", 0x7a);
366     AddFixed("ANL", 0x3fb2);
367     AddFixed("ORL", 0x3fb6);
368     AddFixed("RAR", 0x3fb3);
369     AddFixed("IES", 0x49);
370     AddFixed("DES", 0x48);
371     AddFixed("RTPSW", 0x43);
372     AddFixed("PSHDE", 0x3e8e);
373     AddFixed("PSHHL", 0x3e9e);
374     AddFixed("POPDE", 0x3e8f);
375     AddFixed("POPHL", 0x3e9f);
376     AddFixed("TSPAM", 0x3f35);
377     AddFixed("TAMMOD", 0x3f3f);
378     AddFixed("IP1", 0x71);
379     AddFixed("IP54", 0x3f38);
380     AddFixed("OP3", 0x73);
381     AddFixed("OP54", 0x3f3c);
382   }
383 
384   AddImm4("LAI", 0x10);
385   AddImm4("AISC", 0x00);
386   AddImm4("SKAEI", 0x3f60);
387   if (MomCPU == CPU7566)
388   {
389     AddImm4("STII", 0x40);
390   }
391   if (MomCPU == CPU7508)
392   {
393     AddImm4("LDI", 0x3e20);
394     AddImm4("LEI", 0x3e00);
395     AddImm4("LHI", 0x3e30);
396     AddImm4("LLI", 0x3e10);
397     AddImm4("JAM", 0x3f10);
398     AddImm4("SKDEI", 0x3e60);
399     AddImm4("SKEEI", 0x3e40);
400     AddImm4("SKHEI", 0x3e70);
401     AddImm4("SKLEI", 0x3e50);
402     AddImm4("OP", 0x3fe0);
403   }
404 
405   AddImm2("RMB", 0x68);
406   AddImm2("SMB", 0x6c);
407   AddImm2("SKABT", 0x74);
408   AddImm2("SKMBT", 0x64);
409   AddImm2("SKMBF", 0x60);
410   if (MomCPU == CPU7566)
411   {
412     AddImm2("SKI", 0x3d40);
413     AddImm2("LHI", 0x28);
414   }
415 
416   if (MomCPU == CPU7508)
417   {
418     AddImm3("EI", 0x3f90);
419     AddImm3("DI", 0x3f80);
420     AddImm3("SKI", 0x3f40);
421     AddImm3("IP", 0x3fc0);
422   }
423 
424   if (MomCPU == CPU7566)
425   {
426     AddImm5("LHLI", 0xc0);
427   }
428 
429   if (MomCPU == CPU7508)
430   {
431     AddImm8("LDEI", 0x4f);
432     AddImm8("LHLI", 0x4e);
433   }
434 
435   AddPR("LAM", 0x40);
436   AddPR("XAM", 0x44);
437 
438   AddDataMem("IDRS", 0x3d);
439   AddDataMem("DDRS", 0x3c);
440   if (MomCPU == CPU7508)
441   {
442     AddDataMem("LADR", 0x38);
443     AddDataMem("XADR", 0x39);
444     AddDataMem("XHDR", 0x3a);
445     AddDataMem("XLDR", 0x3b);
446   }
447 
448   AddAbs("JMP" , 0x2000);
449   AddAbs("CALL", 0x3000);
450   AddInstTable(InstTable, "JCP", 0x80, DecodeJCP);
451   if (MomCPU == CPU7566)
452   {
453     AddInstTable(InstTable, "CAL", 0xe0, DecodeCAL);
454   }
455   if (MomCPU == CPU7508)
456   {
457     AddInstTable(InstTable, "LHLT", 0xc0, DecodeLHLT);
458     AddInstTable(InstTable, "CALT", 0xc0, DecodeCALT);
459     AddInstTable(InstTable, "ANP", 0x4c00, DecodeLogPort);
460     AddInstTable(InstTable, "ORP", 0x4d00, DecodeLogPort);
461   }
462 }
463 
DeinitFields(void)464 static void DeinitFields(void)
465 {
466   DestroyInstTable(InstTable);
467 }
468 
469 /*-------------------------------------------------------------------------*/
470 
MakeCode_75xx(void)471 static void MakeCode_75xx(void)
472 {
473   CodeLen = 0; DontPrint = False;
474 
475   /* zu ignorierendes */
476 
477   if (Memo("")) return;
478 
479   /* Pseudoanweisungen */
480 
481   if (DecodeIntelPseudo(True)) return;
482 
483   if (!LookupInstTable(InstTable, OpPart.Str))
484     WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
485 }
486 
IsDef_75xx(void)487 static Boolean IsDef_75xx(void)
488 {
489   return False;
490 }
491 
SwitchFrom_75xx(void)492 static void SwitchFrom_75xx(void)
493 {
494   DeinitFields();
495 }
496 
SwitchTo_75xx(void)497 static void SwitchTo_75xx(void)
498 {
499   TurnWords = False; ConstMode = ConstModeIntel;
500 
501   PCSymbol = "PC"; HeaderID = FindFamilyByName("75xx")->Id; NOPCode = 0x00;
502   DivideChars = ","; HasAttrs = False;
503 
504   ValidSegs = (1 << SegCode) | (1 << SegData);
505   Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegInits[SegCode] = 0;
506   Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegData] = 0;
507   if (MomCPU == CPU7508)
508   {
509     ValidSegs |= (1 << SegIO);
510     Grans[SegIO] = 1; ListGrans[SegIO] = 1; SegInits[SegIO] = 0; SegLimits[SegIO] = 15;
511 
512     SegLimits[SegData] = 0xff;
513     DataIntType = UInt8;
514     SegLimits[SegCode] = 0xfff;
515     CodeIntType = UInt12;
516   }
517   else
518   {
519     SegLimits[SegData] = 0x3f;
520     DataIntType = UInt6;
521     SegLimits[SegCode] = 0x3ff;
522     CodeIntType = UInt10;
523   }
524 
525   MakeCode = MakeCode_75xx; IsDef = IsDef_75xx;
526   SwitchFrom = SwitchFrom_75xx; InitFields();
527 }
528 
code75xx_init(void)529 void code75xx_init(void)
530 {
531   CPU7566 = AddCPU("7566", SwitchTo_75xx);
532   CPU7508 = AddCPU("7508", SwitchTo_75xx);
533 }
534