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