struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / src / z80 / peep.c
blob18bdf56b56cd31ab90c92241a3de7ee7fbf820ec
1 /*-------------------------------------------------------------------------
2 peep.c - source file for peephole optimizer helper functions
4 Written By - Philipp Klaus Krause
5 Copyright (C) 2020, Sebastian 'basxto' Riedel <sdcc@basxto.de>
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
26 #include "common.h"
27 #include "SDCCicode.h"
28 #include "z80.h"
29 #include "SDCCglobl.h"
30 #include "SDCCpeeph.h"
31 #include "gen.h"
33 #define NOTUSEDERROR() do {werror(E_INTERNAL_ERROR, __FILE__, __LINE__, "error in notUsed()");} while(0)
35 #if 0
36 #define D(_s) { printf _s; fflush(stdout); }
37 #else
38 #define D(_s)
39 #endif
41 #define ISINST(l, i) (!STRNCASECMP((l), (i), sizeof(i) - 1) && (!(l)[sizeof(i) - 1] || isspace((unsigned char)((l)[sizeof(i) - 1]))))
43 typedef enum
45 S4O_CONDJMP,
46 S4O_WR_OP,
47 S4O_RD_OP,
48 S4O_TERM,
49 S4O_VISITED,
50 S4O_ABORT,
51 S4O_CONTINUE
52 } S4O_RET;
54 static struct
56 lineNode *head;
57 } _G;
59 extern bool z80_regs_used_as_parms_in_calls_from_current_function[IYH_IDX + 1];
60 extern bool z80_symmParm_in_calls_from_current_function;
61 extern bool z80_regs_preserved_in_calls_from_current_function[IYH_IDX + 1];
63 /*-----------------------------------------------------------------*/
64 /* univisitLines - clear "visited" flag in all lines */
65 /*-----------------------------------------------------------------*/
66 static void
67 unvisitLines (lineNode *pl)
69 for (; pl; pl = pl->next)
70 pl->visited = FALSE;
73 #define AOP(op) op->aop
74 #define AOP_SIZE(op) AOP(op)->size
76 /*-----------------------------------------------------------------*/
77 /* incLabelJmpToCount - increment counter "jmpToCount" in entry */
78 /* of the list labelHash */
79 /*-----------------------------------------------------------------*/
80 static bool
81 incLabelJmpToCount (const char *label)
83 labelHashEntry *entry;
85 entry = getLabelRef (label, _G.head);
86 if (!entry)
87 return FALSE;
88 entry->jmpToCount++;
89 return TRUE;
92 /*-----------------------------------------------------------------*/
93 /* findLabel - */
94 /* 1. extracts label in the opcode pl */
95 /* 2. increment "label jump-to count" in labelHash */
96 /* 3. search lineNode with label definition and return it */
97 /*-----------------------------------------------------------------*/
98 static lineNode *
99 findLabel (const lineNode *pl)
101 char *p;
102 lineNode *cpl;
104 /* 1. extract label in opcode */
106 /* In each z80 jumping opcode the label is at the end of the opcode */
107 p = strlen (pl->line) - 1 + pl->line;
109 /* scan backward until ',' or '\t' */
110 for (; p > pl->line; p--)
111 if (*p == ',' || isspace(*p))
112 break;
114 /* sanity check */
115 if (p == pl->line)
117 NOTUSEDERROR();
118 return NULL;
121 /* skip ',' resp. '\t' */
122 ++p;
124 /* 2. increment "label jump-to count" */
125 if (!incLabelJmpToCount (p))
126 return NULL;
128 /* 3. search lineNode with label definition and return it */
129 for (cpl = _G.head; cpl; cpl = cpl->next)
130 if (cpl->isLabel &&
131 strncmp (p, cpl->line, strlen(p)) == 0 &&
132 cpl->line[strlen(p)] == ':')
133 return cpl;
135 return NULL;
138 /* Check if reading arg implies reading what. */
139 static bool argCont(const char *arg, const char *what)
141 wassert (arg);
143 while(isspace (*arg) || *arg == ',')
144 arg++;
146 if (arg[0] == '#' || arg[0] == '_')
147 return false;
149 if(arg[0] == '(' && arg[1] && arg[2] && (arg[2] != ')' && arg[3] != ')')
150 && !(IS_SM83 && (arg[3] == '-' || arg[3] == '+') && arg[4] == ')'))
151 return false;
153 if(*arg == '(')
154 arg++;
156 if (arg[0] == '#' || arg[0] == '_')
157 return false;
159 // Get suitable end to avoid reading into further arguments.
160 const char *end = strchr(arg, ',');
161 if (!end)
162 end = arg + strlen(arg);
164 const char *found = StrStr(arg, what);
166 return(found && found < end);
169 static bool
170 z80MightBeParmInCallFromCurrentFunction(const char *what)
172 if (strchr(what, 'l') && z80_regs_used_as_parms_in_calls_from_current_function[L_IDX])
173 return TRUE;
174 if (strchr(what, 'h') && z80_regs_used_as_parms_in_calls_from_current_function[H_IDX])
175 return TRUE;
176 if (strchr(what, 'e') && z80_regs_used_as_parms_in_calls_from_current_function[E_IDX])
177 return TRUE;
178 if (strchr(what, 'd') && z80_regs_used_as_parms_in_calls_from_current_function[D_IDX])
179 return TRUE;
180 if (strchr(what, 'c') && z80_regs_used_as_parms_in_calls_from_current_function[C_IDX])
181 return TRUE;
182 if (strchr(what, 'b') && z80_regs_used_as_parms_in_calls_from_current_function[B_IDX])
183 return TRUE;
184 if (strchr(what, 'a') && z80_regs_used_as_parms_in_calls_from_current_function[A_IDX])
185 return true;
186 if (strstr(what, "iy") && (z80_regs_used_as_parms_in_calls_from_current_function[IYL_IDX] || z80_regs_used_as_parms_in_calls_from_current_function[IYH_IDX]))
187 return true;
189 return false;
192 /* Check if the flag implies reading what. */
193 static bool
194 z80MightReadFlagCondition(const char *cond, const char *what)
196 while(isspace (*cond))
197 cond++;
199 if(!STRNCASECMP(cond, "po", 2) || !STRNCASECMP(cond, "pe", 2))
200 return !strcmp(what, "pf");
201 if(tolower(cond[0]) == 'm' || tolower(cond[0]) == 'p')
202 return !strcmp(what, "sf");
204 // skip inverted conditions
205 if(tolower(cond[0]) == 'n')
206 cond++;
208 if(tolower(cond[0]) == 'c')
209 return !strcmp(what, "cf");
210 if(tolower(cond[0]) == 'z')
211 return !strcmp(what, "zf");
212 return true;
215 static bool
216 z80MightReadFlag(const lineNode *pl, const char *what)
218 if(ISINST(pl->line, "ld") ||
219 ISINST(pl->line, "or") ||
220 ISINST(pl->line, "cp") ||
221 ISINST(pl->line, "di") ||
222 ISINST(pl->line, "ei") ||
223 ISINST(pl->line, "im") ||
224 ISINST(pl->line, "in"))
225 return false;
226 if(ISINST(pl->line, "nop") ||
227 ISINST(pl->line, "add") ||
228 ISINST(pl->line, "sub") ||
229 ISINST(pl->line, "and") ||
230 ISINST(pl->line, "xor") ||
231 ISINST(pl->line, "dec") ||
232 ISINST(pl->line, "inc") ||
233 ISINST(pl->line, "cpl") ||
234 ISINST(pl->line, "bit") ||
235 ISINST(pl->line, "res") ||
236 ISINST(pl->line, "set") ||
237 ISINST(pl->line, "pop") ||
238 ISINST(pl->line, "rlc") ||
239 ISINST(pl->line, "rrc") ||
240 ISINST(pl->line, "sla") ||
241 ISINST(pl->line, "sra") ||
242 ISINST(pl->line, "srl") ||
243 ISINST(pl->line, "scf") ||
244 ISINST(pl->line, "cpd") ||
245 ISINST(pl->line, "cpi") ||
246 ISINST(pl->line, "ind") ||
247 ISINST(pl->line, "ini") ||
248 ISINST(pl->line, "ldd") ||
249 ISINST(pl->line, "ldi") ||
250 ISINST(pl->line, "neg") ||
251 ISINST(pl->line, "rld") ||
252 ISINST(pl->line, "rrd") ||
253 ISINST(pl->line, "mlt") ||
254 ISINST(pl->line, "out"))
255 return false;
256 if(ISINST(pl->line, "halt") ||
257 ISINST(pl->line, "rlca") ||
258 ISINST(pl->line, "rrca") ||
259 ISINST(pl->line, "cpdr") ||
260 ISINST(pl->line, "cpir") ||
261 ISINST(pl->line, "indr") ||
262 ISINST(pl->line, "inir") ||
263 ISINST(pl->line, "lddr") ||
264 ISINST(pl->line, "ldir") ||
265 ISINST(pl->line, "outd") ||
266 ISINST(pl->line, "outi") ||
267 ISINST(pl->line, "djnz"))
268 return false;
270 if(IS_RAB &&
271 ISINST(pl->line, "bool"))
272 return false;
274 if(IS_SM83 &&
275 (ISINST(pl->line, "stop") ||
276 ISINST(pl->line, "ldh")))
277 return false;
279 if((IS_SM83 || IS_Z80N) &&
280 ISINST(pl->line, "swap"))
281 return false;
283 if(IS_R800 &&
284 (ISINST(pl->line, "multu") ||
285 ISINST(pl->line, "multuw")))
286 return false;
288 if(ISINST(pl->line, "rl") ||
289 ISINST(pl->line, "rr") ||
290 ISINST(pl->line, "rla") ||
291 ISINST(pl->line, "rra") ||
292 ISINST(pl->line, "sbc") ||
293 ISINST(pl->line, "adc") ||
294 ISINST(pl->line, "ccf"))
295 return (!strcmp(what, "cf"));
297 if(ISINST(pl->line, "daa"))
298 return (!strcmp(what, "cf") || !strcmp(what, "nf") ||
299 !strcmp(what, "hf"));
301 if(ISINST(pl->line, "push"))
302 return (argCont(pl->line + 4, "af"));
304 if(ISINST(pl->line, "ex"))
305 return (argCont(pl->line + 2, "af"));
307 // catch c, nc, z, nz, po, pe, p and m
308 if(ISINST(pl->line, "jp") ||
309 ISINST(pl->line, "jr"))
310 return (strchr(pl->line, ',') && z80MightReadFlagCondition(pl->line + 2, what));
312 // flags don't matter according to calling convention
313 if(ISINST(pl->line, "reti") ||
314 ISINST(pl->line, "retn"))
315 return false;
317 if(ISINST(pl->line, "call"))
318 return (strchr(pl->line, ',') && z80MightReadFlagCondition(pl->line + 4, what));
320 if(ISINST(pl->line, "ret"))
321 return (pl->line[3] == '\t' && z80MightReadFlagCondition(pl->line + 3, what));
323 // we don't know anything about this
324 if(ISINST(pl->line, "rst"))
325 return true;
327 if (IS_SM83 && ISINST(pl->line, "ldhl"))
328 return false;
330 if(IS_RAB && (ISINST(pl->line, "ioi") || ISINST(pl->line, "ioe") || ISINST(pl->line, "ipres")))
331 return(false);
333 if(IS_Z80N &&
334 (ISINST(pl->line, "bsla") ||
335 ISINST(pl->line, "bsra") ||
336 ISINST(pl->line, "bsrl") ||
337 ISINST(pl->line, "bsrf") ||
338 ISINST(pl->line, "brlc")))
339 return(false);
341 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) &&
342 ISINST(pl->line, "tst"))
343 return(false);
345 return true; // Fail-safe: we have no idea what happens at this line, so assume it might read anything.
348 static bool
349 z80MightRead(const lineNode *pl, const char *what)
351 if(strcmp(what, "iyl") == 0 || strcmp(what, "iyh") == 0)
352 what = "iy";
353 if(strcmp(what, "ixl") == 0 || strcmp(what, "ixh") == 0)
354 what = "ix";
356 if(ISINST(pl->line, "call") && strcmp(what, "sp") == 0)
357 return TRUE;
359 if(strcmp(pl->line, "call\t__initrleblock") == 0 && (strchr(what, 'd') != 0 || strchr(what, 'e') != 0))
360 return TRUE;
362 if(strcmp(pl->line, "call\t___sdcc_call_hl") == 0 && (strchr(what, 'h') != 0 || strchr(what, 'l') != 0))
363 return TRUE;
365 if(strcmp(pl->line, "call\t___sdcc_call_iy") == 0 && strstr(what, "iy") != 0)
366 return TRUE;
368 if(strncmp(pl->line, "call\t___sdcc_bcall_", 19) == 0)
369 if (strchr (what, pl->line[19]) != 0 || strchr (what, pl->line[20]) != 0 || strchr (what, pl->line[21]) != 0)
370 return TRUE;
372 if(ISINST(pl->line, "call") && strchr(pl->line, ',') == 0)
374 const symbol *f = findSym (SymbolTab, 0, pl->line + 6);
375 if (f && IS_FUNC (f->type))
376 return z80IsParmInCall(f->type, what);
377 else // Fallback needed for calls through function pointers and for calls to literal addresses.
378 return z80MightBeParmInCallFromCurrentFunction(what);
381 if(ISINST(pl->line, "reti") || ISINST(pl->line, "retn"))
382 return(strcmp(what, "sp") == 0);
384 if(ISINST(pl->line, "ret")) // --reserve-regs-iy and the sm83 port use ret in code gen for calls through function pointers
385 return((IY_RESERVED || IS_SM83) ? z80IsReturned(what) || z80MightBeParmInCallFromCurrentFunction(what) : z80IsReturned(what)) || strcmp(what, "sp") == 0;
387 if(!strcmp(pl->line, "ex\t(sp), hl") || !strcmp(pl->line, "ex\t(sp),hl"))
388 return(!strcmp(what, "h") || !strcmp(what, "l") || strcmp(what, "sp") == 0);
389 if(!strcmp(pl->line, "ex\t(sp), ix") || !strcmp(pl->line, "ex\t(sp),ix"))
390 return(!!strstr(what, "ix") || strcmp(what, "sp") == 0);
391 if(!strcmp(pl->line, "ex\t(sp), iy") || !strcmp(pl->line, "ex\t(sp),iy"))
392 return(!!strstr(what, "iy") || strcmp(what, "sp") == 0);
393 if(!strcmp(pl->line, "ex\tde, hl") || !strcmp(pl->line, "ex\tde,hl"))
394 return(!strcmp(what, "h") || !strcmp(what, "l") || !strcmp(what, "d") || !strcmp(what, "e"));
395 if(ISINST(pl->line, "ld"))
397 if(argCont(strchr(pl->line, ','), what))
398 return(true);
399 if(*(strchr(pl->line, ',') - 1) == ')' && strstr(pl->line + 3, what) &&
400 (strchr(pl->line, '#') == 0 || strchr(pl->line, '#') > strchr(pl->line, ',')) &&
401 (strchr(pl->line, '_') == 0 || strchr(pl->line, '_') > strchr(pl->line, ',')))
402 return(true);
403 if (!strcmp(what, "sp") && strchr(pl->line, '(')) // Assume any indirect memory access to be a stack access. This avoids optimizing out stackframe setups for local variables (bug #3173).
404 return(true);
405 return(false);
408 //ld a, #0x00
409 if((ISINST(pl->line, "xor") || ISINST(pl->line, "sub")) &&
410 (!strcmp(pl->line+4, "a, a") || !strcmp(pl->line+4, "a,a") || (!strchr(pl->line, ',') && !strcmp(pl->line+4, "a"))))
411 return(false);
413 //ld a, #0x00
414 if(!strcmp(pl->line, "and\ta, #0x00") || !strcmp(pl->line, "and\ta,#0x00") || !strcmp(pl->line, "and\t#0x00"))
415 return(false);
417 //ld a, #0xff
418 if(!strcmp(pl->line, "or\ta, #0xff") || !strcmp(pl->line, "or\ta,#0xff") || !strcmp(pl->line, "or\t#0xff"))
419 return(false);
421 if(ISINST(pl->line, "adc") ||
422 ISINST(pl->line, "add") ||
423 ISINST(pl->line, "and") ||
424 ISINST(pl->line, "sbc") ||
425 ISINST(pl->line, "sub") ||
426 ISINST(pl->line, "xor") ||
427 IS_R800 && ISINST(pl->line, "multu") ||
428 IS_R800 && ISINST(pl->line, "multuw"))
430 const char *arg;
431 if (ISINST(pl->line, "multu"))
432 arg = pl->line + 5;
433 else if (ISINST(pl->line, "multuw"))
434 arg = pl->line + 6;
435 else
436 arg = pl->line + 4;
437 while(isspace(*arg))
438 arg++;
439 if(arg[0] == 'a' && arg[1] == ',')
441 if(!strcmp(what, "a"))
442 return(true);
443 arg += 2;
445 else if(IS_Z80N && !strncmp(arg, "bc", 2) && *(arg + 2) == ',')
447 if(!strcmp(what, "b") || !strcmp(what, "c"))
448 return(true);
449 arg += 3;
451 else if(IS_Z80N && !strncmp(arg, "de", 2) && *(arg + 2) == ',')
453 if(!strcmp(what, "d") || !strcmp(what, "e"))
454 return(true);
455 arg += 3;
457 else if(!strncmp(arg, "hl", 2) && arg[2] == ',') // add hl, rr
459 if(!strcmp(what, "h") || !strcmp(what, "l"))
460 return(true);
461 arg += 3;
463 else if(!strncmp(arg, "sp", 2) && arg[2] == ',') // add sp, rr
465 if(!strcmp(what, "sp"))
466 return(true);
467 arg += 3;
469 else if(arg[0] == 'i') // add ix/y, rr
471 if(!strncmp(arg, what, 2))
472 return(true);
473 arg += 3;
475 return(argCont(arg, what));
478 if(ISINST(pl->line, "or") || ISINST(pl->line, "cp") )
480 const char *arg = pl->line + 3;
481 while(isspace(*arg))
482 arg++;
483 if(*arg == 'a' && *(arg + 1) == ',')
485 if(!strcmp(what, "a"))
486 return(true);
487 arg += 2;
489 else if(!strncmp(arg, "hl", 2) && *(arg + 2) == ',')
491 if(!strcmp(what, "h") || !strcmp(what, "l"))
492 return(true);
493 arg += 3;
495 else if(!strncmp(arg, "iy", 2) && *(arg + 2) == ',')
497 if(!strcmp(what, "iy"))
498 return(true);
499 arg += 3;
501 return(argCont(arg, what));
504 if(ISINST(pl->line, "neg"))
505 return(strcmp(what, "a") == 0);
507 if(ISINST(pl->line, "pop"))
508 return(strcmp(what, "sp") == 0);
510 if(ISINST(pl->line, "push"))
511 return(strstr(pl->line + 5, what) != 0 || strcmp(what, "sp") == 0);
513 if(ISINST(pl->line, "dec") ||
514 ISINST(pl->line, "inc"))
516 return(argCont(pl->line + 4, what));
519 if(ISINST(pl->line, "cpl"))
520 return(!strcmp(what, "a"));
522 if(ISINST(pl->line, "di") || ISINST(pl->line, "ei"))
523 return(false);
525 // Rotate and shift group
526 if(ISINST(pl->line, "rlca") ||
527 ISINST(pl->line, "rla") ||
528 ISINST(pl->line, "rrca") ||
529 ISINST(pl->line, "rra") ||
530 ISINST(pl->line, "daa"))
532 return(strcmp(what, "a") == 0);
534 if(ISINST(pl->line, "rl") ||
535 ISINST(pl->line, "rr"))
537 return(argCont(pl->line + 3, what));
539 if(ISINST(pl->line, "rlc") ||
540 ISINST(pl->line, "sla") ||
541 ISINST(pl->line, "rrc") ||
542 ISINST(pl->line, "sra") ||
543 ISINST(pl->line, "srl"))
545 return(argCont(pl->line + 4, what));
547 if((IS_SM83 || IS_Z80N) && ISINST(pl->line, "swap"))
549 return(argCont(pl->line + 5, what));
551 if(!IS_SM83 && !IS_RAB &&
552 (ISINST(pl->line, "rld") ||
553 ISINST(pl->line, "rrd")))
554 return(!!strstr("ahl", what));
556 // Bit set, reset and test group
557 if(ISINST(pl->line, "bit") ||
558 ISINST(pl->line, "set") ||
559 ISINST(pl->line, "res"))
561 return(argCont(strchr(pl->line + 4, ','), what));
564 if(ISINST(pl->line, "ccf") ||
565 ISINST(pl->line, "scf") ||
566 ISINST(pl->line, "nop") ||
567 ISINST(pl->line, "halt") ||
568 (IS_SM83 && ISINST(pl->line, "stop")))
569 return(false);
571 if(ISINST(pl->line, "jp") || ISINST(pl->line, "jr"))
572 return(false);
574 if(ISINST(pl->line, "djnz"))
575 return(strchr(what, 'b') != 0);
577 if(!IS_SM83 && (ISINST(pl->line, "ldd") || ISINST(pl->line, "lddr") || ISINST(pl->line, "ldi") || ISINST(pl->line, "ldir")))
578 return(strchr("bcdehl", *what));
579 if(IS_SM83 && (ISINST(pl->line, "ldd") || ISINST(pl->line, "ldi")))
580 return(strchr("hl", *what) || strstr(strchr(pl->line + 4, ','), what) != 0);
582 if(!IS_SM83 && !IS_RAB && (ISINST(pl->line, "cpd") || ISINST(pl->line, "cpdr") || ISINST(pl->line, "cpi") || ISINST(pl->line, "cpir")))
583 return(strchr("abchl", *what));
585 if(!IS_SM83 && !IS_RAB && ISINST(pl->line, "out"))
586 return(strstr(strchr(pl->line + 4, ','), what) != 0 || strstr(pl->line + 4, "(c)") && (!strcmp(what, "b") || !strcmp(what, "c")));
587 if(!IS_SM83 && !IS_RAB && ISINST(pl->line, "in"))
588 return(!strstr(strchr(pl->line + 4, ','), "(c)") && !strcmp(what, "a") || strstr(strchr(pl->line + 4, ','), "(c)") && (!strcmp(what, "b") || !strcmp(what, "c")));
590 if(IS_SM83 && (ISINST(pl->line, "out") || ISINST(pl->line, "ldh") || ISINST(pl->line, "in")))
591 return(strstr(strchr(pl->line + 3, ','), what) != 0 || (!strcmp(what, "c") && strstr(pl->line + 3, "(c)")));
593 if(!IS_SM83 && !IS_RAB &&
594 (ISINST(pl->line, "ini") || ISINST(pl->line, "ind") || ISINST(pl->line, "inir") || ISINST(pl->line, "indr") ||
595 ISINST(pl->line, "outi") || ISINST(pl->line, "outd") || ISINST(pl->line, "otir") || ISINST(pl->line, "otdr")))
596 return(strchr("bchl", *what));
598 if((IS_Z180 || IS_EZ80_Z80) && ISINST(pl->line, "in0"))
599 return(false);
601 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) && ISINST(pl->line, "mlt"))
602 return(argCont(pl->line + 4, what));
604 if((IS_Z180 || IS_EZ80_Z80) &&
605 (ISINST(pl->line, "otim") || ISINST(pl->line, "otimr") || ISINST(pl->line, "otir") || ISINST(pl->line, "otirx")))
606 return(strchr("bchl", *what));
608 if((IS_Z180 || IS_EZ80_Z80) && ISINST(pl->line, "slp"))
609 return(false);
611 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) && ISINST(pl->line, "tst"))
612 return(argCont(pl->line + 4, what));
614 if((IS_Z180 || IS_EZ80_Z80) && ISINST(pl->line, "tstio"))
615 return(!strcmp(what, "c"));
617 if(IS_RAB && (ISINST(pl->line, "ioi") || ISINST(pl->line, "ioe")))
618 return(false);
620 if(IS_RAB && ISINST(pl->line, "mul"))
621 return(!strcmp(what, "b") || !strcmp(what, "c") || !strcmp(what, "d") || !strcmp(what, "e"));
623 if(IS_RAB && ISINST(pl->line, "bool"))
624 return(argCont(pl->line + 5, what));
626 if(IS_R3KA && ISINST(pl->line, "lsdr") || ISINST(pl->line, "lidr") || ISINST(pl->line, "lsddr") || ISINST(pl->line, "lsidr"))
627 return(strchr("bcdehl", *what));
629 if(IS_EZ80_Z80 && ISINST(pl->line, "lea"))
630 return(argCont(strchr(pl->line + 4, ','), what));
632 if(IS_EZ80_Z80 && ISINST(pl->line, "pea"))
633 return(argCont(pl->line + 4, what) || !strcmp(what, "sp"));
635 if (IS_SM83 && (ISINST(pl->line, "lda") || ISINST(pl->line, "ldhl")))
636 return(!strcmp(what, "sp"));
638 if(IS_Z80N &&
639 (ISINST(pl->line, "bsla") ||
640 ISINST(pl->line, "bsra") ||
641 ISINST(pl->line, "bsrl") ||
642 ISINST(pl->line, "bsrf") ||
643 ISINST(pl->line, "brlc")))
644 return(strchr("bde", *what));
646 /* TODO: Can we know anything about rst? */
647 if(ISINST(pl->line, "rst"))
648 return(true);
650 return(true);
653 static bool
654 z80UncondJump(const lineNode *pl)
656 if((ISINST(pl->line, "jp") || ISINST(pl->line, "jr")) &&
657 strchr(pl->line, ',') == 0)
658 return TRUE;
659 return FALSE;
662 static bool
663 z80CondJump(const lineNode *pl)
665 if(((ISINST(pl->line, "jp") || ISINST(pl->line, "jr")) &&
666 strchr(pl->line, ',') != 0) ||
667 ISINST(pl->line, "djnz"))
668 return TRUE;
669 return FALSE;
672 // TODO: z80 flags only partly implemented
673 static bool
674 z80SurelyWritesFlag(const lineNode *pl, const char *what)
676 /* LD instruction is never change flags except LD A,I and LD A,R.
677 But it is most popular instruction so place it first */
678 if(ISINST(pl->line, "ld"))
680 if(IS_SM83 || IS_RAB || !!strcmp(what, "pf") ||
681 !argCont(pl->line+3, "a"))
682 return false;
683 const char *p = strchr(pl->line+4, ',');
684 if (p == NULL)
685 return false; /* unknown instruction */
686 ++p;
687 return argCont(p, "i") || argCont(p, "r");
690 if(ISINST(pl->line, "rlca") ||
691 ISINST(pl->line, "rrca") ||
692 ISINST(pl->line, "rra") ||
693 ISINST(pl->line, "rla"))
694 return (IS_SM83 || !!strcmp(what, "zf") && !!strcmp(what, "sf") && !!strcmp(what, "pf"));
696 if(ISINST(pl->line, "adc") ||
697 ISINST(pl->line, "and") ||
698 ISINST(pl->line, "sbc") ||
699 ISINST(pl->line, "sub") ||
700 ISINST(pl->line, "xor") ||
701 ISINST(pl->line, "and") ||
702 ISINST(pl->line, "rlc") ||
703 ISINST(pl->line, "rrc") ||
704 ISINST(pl->line, "sla") ||
705 ISINST(pl->line, "sra") ||
706 ISINST(pl->line, "srl") ||
707 ISINST(pl->line, "neg"))
708 return true;
710 if(ISINST(pl->line, "or") ||
711 ISINST(pl->line, "cp") ||
712 ISINST(pl->line, "rl") ||
713 ISINST(pl->line, "rr"))
714 return true;
716 if(ISINST(pl->line, "bit") ||
717 ISINST(pl->line, "cpd") ||
718 ISINST(pl->line, "cpi") ||
719 ISINST(pl->line, "ind") ||
720 ISINST(pl->line, "ini") ||
721 ISINST(pl->line, "rrd"))
722 return (!!strcmp(what, "cf"));
724 if(ISINST(pl->line, "cpdr") ||
725 ISINST(pl->line, "cpir") ||
726 ISINST(pl->line, "indr") ||
727 ISINST(pl->line, "inir") ||
728 ISINST(pl->line, "otdr") ||
729 ISINST(pl->line, "otir") ||
730 ISINST(pl->line, "outd") ||
731 ISINST(pl->line, "outi"))
732 return (!!strcmp(what, "cf"));
734 if(ISINST(pl->line, "daa"))
735 return (!!strcmp(what, "nf"));
737 if(ISINST(pl->line, "ccf") ||
738 ISINST(pl->line, "scf"))
739 return (!strcmp(what, "hf") || !strcmp(what, "nf") || !strcmp(what, "cf"));
741 if(ISINST(pl->line, "cpl"))
742 return (!strcmp(what, "hf") || !strcmp(what, "nf"));
744 if(ISINST(pl->line, "inc") || ISINST(pl->line, "dec"))
746 // 8-bit inc affects all flags other than c.
747 if (strlen(pl->line + 4) == 1 || // 8-bit register
748 !strcmp(pl->line + 4, "(hl)") ||
749 !strcmp(pl->line + 6, "(ix)") ||
750 !strcmp(pl->line + 6, "(iy)"))
751 return (!!strcmp(what, "cf"));
752 return false; // 16-bit inc does not affect flags.
755 if(ISINST(pl->line, "add"))
756 return (argCont(pl->line + 4, "a") ||
757 (!!strcmp(what, "zf") && !!strcmp(what, "sf") && !!strcmp(what, "pf")));
759 if(ISINST(pl->line, "ldd") ||
760 ISINST(pl->line, "lddr") ||
761 ISINST(pl->line, "ldi") ||
762 ISINST(pl->line, "ldir"))
763 return (!strcmp(what, "hf") || !strcmp(what, "pf") || !strcmp(what, "nf"));
765 // pop af writes
766 if(ISINST(pl->line, "pop"))
767 return (argCont(pl->line + 4, "af"));
769 // according to calling convention caller has to save flags
770 if(ISINST(pl->line, "ret") ||
771 ISINST(pl->line, "call"))
772 return true;
774 if(ISINST(pl->line, "rld") ||
775 ISINST(pl->line, "rrd"))
776 return (!strcmp(what, "hf") || !strcmp(what, "pf") || !strcmp(what, "nf"));
778 if(ISINST(pl->line, "djnz") ||
779 ISINST(pl->line, "ex") ||
780 ISINST(pl->line, "nop") ||
781 ISINST(pl->line, "out") ||
782 ISINST(pl->line, "push") ||
783 ISINST(pl->line, "res") ||
784 ISINST(pl->line, "set"))
785 return false;
787 if(IS_SM83 &&
788 (ISINST(pl->line, "swap") ||
789 ISINST(pl->line, "ldhl") ||
790 ISINST(pl->line, "lda")))
791 return true;
793 if(IS_Z80N &&
794 ISINST(pl->line, "swap"))
795 return false;
797 /* handle IN0 r,(n) and IN r,(c) instructions */
798 if(ISINST(pl->line, "in0") || (!strncmp(pl->line, "in\t", 3) &&
799 (!strcmp(pl->line+5, "(c)") || !strcmp(pl->line+5, "(bc)"))))
800 return (!!strcmp(what, "cf"));
802 if(IS_RAB &&
803 ISINST(pl->line, "bool"))
804 return true;
806 if(IS_RAB &&
807 ISINST(pl->line, "ipres"))
808 return false;
810 if(ISINST(pl->line, "mlt"))
811 return (!IS_Z80N);
813 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) &&
814 ISINST(pl->line, "tst"))
815 return true;
817 return false; // Fail-safe: we have no idea what happens at this line, so assume it writes nothing.
820 static bool
821 callSurelyWrites (const lineNode *pl, const char *what)
823 const symbol *f = 0;
824 if (ISINST(pl->line, "call") && !strchr(pl->line, ','))
825 f = findSym (SymbolTab, 0, pl->line + 6);
826 else if ((ISINST(pl->line, "jp") || ISINST(pl->line, "jr")) && !strchr(pl->line, ','))
827 f = findSym (SymbolTab, 0, pl->line + 4);
829 const bool *preserved_regs;
831 if (f && (strlen(what) == 2 && what[1] == 'f')) // Flags are never preserved across function calls.
832 return(true);
834 if(!strcmp(what, "ix"))
835 return(false);
837 if(f)
838 preserved_regs = f->type->funcAttrs.preserved_regs;
839 else if (ISINST(pl->line, "call"))
840 preserved_regs = z80_regs_preserved_in_calls_from_current_function;
841 else // Err on the safe side for jp and jr - might not be a function call, might e.g. be a jump table.
842 return (false);
844 if (!strcmp (what, "a"))
845 return !preserved_regs[A_IDX];
846 if (!strcmp (what, "c"))
847 return !preserved_regs[C_IDX];
848 if (!strcmp (what, "b"))
849 return !preserved_regs[B_IDX];
850 if (!strcmp (what, "e"))
851 return !preserved_regs[E_IDX];
852 if (!strcmp (what, "d"))
853 return !preserved_regs[D_IDX];
854 if (!strcmp (what, "l"))
855 return !preserved_regs[L_IDX];
856 if (!strcmp (what, "h"))
857 return !preserved_regs[H_IDX];
858 if (!strcmp (what, "iyl"))
859 return !preserved_regs[IYL_IDX];
860 if (!strcmp (what, "iyh"))
861 return !preserved_regs[IYH_IDX];
862 if (!strcmp (what, "iy"))
863 return !preserved_regs[IYL_IDX] && !preserved_regs[IYH_IDX];
865 return (false);
868 static bool
869 z80SurelyWrites (const lineNode *pl, const char *what)
871 if(strcmp(what, "iyl") == 0 || strcmp(what, "iyh") == 0)
872 what = "iy";
873 if(strcmp(what, "ixl") == 0 || strcmp(what, "ixh") == 0)
874 what = "ix";
876 //ld a, #0x00
877 if((ISINST(pl->line, "xor") || ISINST(pl->line, "sub")) && !strcmp(what, "a") &&
878 (!strcmp(pl->line+4, "a, a") || !strcmp(pl->line+4, "a,a") || (!strchr(pl->line, ',') && !strcmp(pl->line+4, "a"))))
879 return(true);
881 //ld a, #0x00
882 if(!strcmp(what, "a") && (!strcmp(pl->line, "and\ta, #0x00") || !strcmp(pl->line, "and\ta,#0x00") || !strcmp(pl->line, "and\t#0x00")))
883 return(true);
885 //ld a, #0xff
886 if(!strcmp(what, "a") && (!strcmp(pl->line, "or\ta, #0xff") || !strcmp(pl->line, "or\ta,#0xff") || !strcmp(pl->line, "or\t#0xff")))
887 return(true);
889 if(ISINST(pl->line, "ld") && strncmp(pl->line + 3, "hl", 2) == 0 && (what[0] == 'h' || what[0] == 'l'))
890 return(true);
891 if(ISINST(pl->line, "ld") && strncmp(pl->line + 3, "de", 2) == 0 && (what[0] == 'd' || what[0] == 'e'))
892 return(true);
893 if(ISINST(pl->line, "ld") && strncmp(pl->line + 3, "bc", 2) == 0 && (what[0] == 'b' || what[0] == 'c'))
894 return(true);
895 if((ISINST(pl->line, "ld") || ISINST(pl->line, "in"))
896 && strncmp(pl->line + 3, what, strlen(what)) == 0 && pl->line[3 + strlen(what)] == ',')
897 return(true);
899 if(IS_SM83 && (ISINST(pl->line, "ldd") || ISINST(pl->line, "ldi") || ISINST(pl->line, "ldh")))
900 return(strncmp(pl->line + 4, what, strlen(what)) == 0);
902 if(ISINST(pl->line, "pop") && strstr(pl->line + 4, what))
903 return(true);
904 if (ISINST(pl->line, "call") && strchr(pl->line, ',') == 0)
905 return (callSurelyWrites (pl, what));
907 if(strcmp(pl->line, "ret") == 0)
908 return true;
910 if (IS_Z180 || IS_EZ80_Z80 || IS_Z80N)
911 if (ISINST(pl->line, "mlt"))
912 return(strchr(pl->line + 4, *what) != 0);
914 if (IS_R800)
915 if (ISINST(pl->line, "multu"))
916 return(strchr("hl", *what) != NULL);
918 if (IS_R800)
919 if (ISINST(pl->line, "multuw"))
920 return(strchr("dehl", *what) != NULL);
922 if (IS_Z180 || IS_EZ80_Z80)
924 if (ISINST(pl->line, "otim") ||
925 ISINST(pl->line, "otimr") ||
926 ISINST(pl->line, "otdm") ||
927 ISINST(pl->line, "otdmr"))
928 return(strchr("bchl", *what) != NULL);
930 if (ISINST(pl->line, "in0"))
931 return(!strncmp(pl->line + 4, what, strlen(what)));
934 if (IS_EZ80_Z80 && ISINST(pl->line, "lea"))
935 return (strstr(pl->line + 4, what));
937 if (IS_SM83 && ISINST(pl->line, "lda") && strncmp(pl->line + 4, "hl", 2) == 0 && (what[0] == 'h' || what[0] == 'l'))
938 return(true);
940 if (IS_SM83 && ISINST(pl->line, "ldhl") && (what[0] == 'h' || what[0] == 'l'))
941 return(true);
943 return(false);
946 static bool
947 z80SurelyReturns(const lineNode *pl)
949 if(strcmp(pl->line, "ret") == 0)
950 return TRUE;
951 return FALSE;
954 /*-----------------------------------------------------------------*/
955 /* scan4op - "executes" and examines the assembler opcodes, */
956 /* follows conditional and un-conditional jumps. */
957 /* Moreover it registers all passed labels. */
958 /* */
959 /* Parameter: */
960 /* lineNode **pl */
961 /* scanning starts from pl; */
962 /* pl also returns the last scanned line */
963 /* const char *pReg */
964 /* points to a register (e.g. "ar0"). scan4op() tests for */
965 /* read or write operations with this register */
966 /* const char *untilOp */
967 /* points to NULL or a opcode (e.g. "push"). */
968 /* scan4op() returns if it hits this opcode. */
969 /* lineNode **plCond */
970 /* If a conditional branch is met plCond points to the */
971 /* lineNode of the conditional branch */
972 /* */
973 /* Returns: */
974 /* S4O_ABORT */
975 /* on error */
976 /* S4O_VISITED */
977 /* hit lineNode with "visited" flag set: scan4op() already */
978 /* scanned this opcode. */
979 /* S4O_FOUNDOPCODE */
980 /* found opcode and operand, to which untilOp and pReg are */
981 /* pointing to. */
982 /* S4O_RD_OP, S4O_WR_OP */
983 /* hit an opcode reading or writing from pReg */
984 /* S4O_CONDJMP */
985 /* hit a conditional jump opcode. pl and plCond return the */
986 /* two possible branches. */
987 /* S4O_TERM */
988 /* acall, lcall, ret and reti "terminate" a scan. */
989 /*-----------------------------------------------------------------*/
990 static S4O_RET
991 scan4op (lineNode **pl, const char *what, const char *untilOp,
992 lineNode **plCond)
994 bool isFlag = (strlen(what) == 2 && what[1] == 'f');
995 for (; *pl; *pl = (*pl)->next)
997 if (!(*pl)->line || (*pl)->isDebug || (*pl)->isComment || (*pl)->isLabel)
998 continue;
999 D(("Scanning %s for %s\n", (*pl)->line, what));
1000 /* don't optimize across inline assembler,
1001 e.g. isLabel doesn't work there */
1002 if ((*pl)->isInline)
1004 D(("S4O_RD_OP: Inline asm\n"));
1005 return S4O_ABORT;
1008 if ((*pl)->visited)
1010 D(("S4O_VISITED\n"));
1011 return S4O_VISITED;
1014 (*pl)->visited = TRUE;
1016 if(isFlag)
1018 if(z80MightReadFlag(*pl, what))
1020 D(("S4O_RD_OP (flag)\n"));
1021 return S4O_RD_OP;
1024 else
1026 if (z80MightRead (*pl, what))
1028 D (("S4O_RD_OP\n"));
1029 return S4O_RD_OP;
1033 if (z80UncondJump (*pl))
1035 lineNode *tlbl = findLabel (*pl);
1036 if (!tlbl) // jp/jr could be a tail call.
1038 const symbol *f = findSym (SymbolTab, 0, (*pl)->line + 4);
1039 if (f && z80IsParmInCall(f->type, what))
1041 D (("S4O_RD_OP\n"));
1042 return S4O_RD_OP;
1044 else if(callSurelyWrites (*pl, what))
1046 D (("S4O_WR_OP\n"));
1047 return S4O_WR_OP;
1050 *pl = tlbl;
1051 if (!*pl)
1053 D (("S4O_ABORT\n"));
1054 return S4O_ABORT;
1057 if (z80CondJump(*pl))
1059 *plCond = findLabel (*pl);
1060 if (!*plCond)
1062 D (("S4O_ABORT\n"));
1063 return S4O_ABORT;
1065 D (("S4O_CONDJMP\n"));
1066 return S4O_CONDJMP;
1069 if (isFlag)
1071 if (z80SurelyWritesFlag (*pl, what))
1073 D (("S4O_WR_OP (flag)\n"));
1074 return S4O_WR_OP;
1077 else
1079 if(z80SurelyWrites(*pl, what))
1081 D(("S4O_WR_OP\n"));
1082 return S4O_WR_OP;
1086 /* Don't need to check for de, hl since z80MightRead() does that */
1087 if(z80SurelyReturns(*pl))
1089 D(("S4O_TERM\n"));
1090 return S4O_TERM;
1093 D(("S4O_ABORT\n"));
1094 return S4O_ABORT;
1097 /*-----------------------------------------------------------------*/
1098 /* doTermScan - scan through area 2. This small wrapper handles: */
1099 /* - action required on different return values */
1100 /* - recursion in case of conditional branches */
1101 /*-----------------------------------------------------------------*/
1102 static bool
1103 doTermScan (lineNode **pl, const char *what)
1105 lineNode *plConditional;
1107 for (;; *pl = (*pl)->next)
1109 switch (scan4op (pl, what, NULL, &plConditional))
1111 case S4O_TERM:
1112 case S4O_VISITED:
1113 case S4O_WR_OP:
1114 /* all these are terminating conditions */
1115 return TRUE;
1116 case S4O_CONDJMP:
1117 /* two possible destinations: recurse */
1119 lineNode *pl2 = plConditional;
1120 D(("CONDJMP trying other branch first\n"));
1121 if (!doTermScan (&pl2, what))
1122 return FALSE;
1123 D(("Other branch OK.\n"));
1125 continue;
1126 case S4O_RD_OP:
1127 default:
1128 /* no go */
1129 return FALSE;
1134 /* Regular 8 bit reg */
1135 static bool
1136 isReg(const char *what)
1138 if(strlen(what) != 1)
1139 return FALSE;
1140 switch(*what)
1142 case 'a':
1143 case 'b':
1144 case 'c':
1145 case 'd':
1146 case 'e':
1147 case 'h':
1148 case 'l':
1149 return TRUE;
1151 return FALSE;
1154 /* 8-Bit reg only accessible by 16-bit and undocumented instructions */
1155 static bool
1156 isUReg(const char *what)
1158 if(strcmp(what, "iyl") == 0 || strcmp(what, "iyh") == 0)
1159 return TRUE;
1160 if(strcmp(what, "ixl") == 0 || strcmp(what, "ixh") == 0)
1161 return TRUE;
1162 return FALSE;
1165 static bool
1166 isRegPair(const char *what)
1168 if(strlen(what) != 2)
1169 return FALSE;
1170 if(strcmp(what, "bc") == 0)
1171 return TRUE;
1172 if(strcmp(what, "de") == 0)
1173 return TRUE;
1174 if(strcmp(what, "hl") == 0)
1175 return TRUE;
1176 if(strcmp(what, "ix") == 0)
1177 return TRUE;
1178 if(strcmp(what, "iy") == 0)
1179 return TRUE;
1180 return FALSE;
1183 /* Check that what is never read after endPl. */
1185 bool
1186 z80notUsed (const char *what, lineNode *endPl, lineNode *head)
1188 lineNode *pl;
1189 D(("Checking for %s\n", what));
1191 if(strcmp(what, "af") == 0)
1193 if(!z80notUsed("a", endPl, head))
1194 return FALSE;
1195 what++;
1198 if(strcmp(what, "f") == 0)
1199 return z80notUsed("zf", endPl, head) && z80notUsed("cf", endPl, head) &&
1200 z80notUsed("sf", endPl, head) && z80notUsed("pf", endPl, head) &&
1201 z80notUsed("nf", endPl, head) && z80notUsed("hf", endPl, head);
1203 if(strcmp(what, "iy") == 0)
1205 if(IY_RESERVED)
1206 return FALSE;
1207 return(z80notUsed("iyl", endPl, head) && z80notUsed("iyh", endPl, head));
1210 if(strcmp(what, "ix") == 0)
1211 return(z80notUsed("ixl", endPl, head) && z80notUsed("ixh", endPl, head));
1213 if(isRegPair(what))
1215 char low[2], high[2];
1216 low[0] = what[1];
1217 high[0] = what[0];
1218 low[1] = 0;
1219 high[1] = 0;
1220 return(z80notUsed(low, endPl, head) && z80notUsed(high, endPl, head));
1223 // P/V and L/V (rabbits) are the same flag
1224 if(!strcmp(what, "vf") || !strcmp(what, "lf"))
1225 what = "pf";
1227 // SM83 does not use what it does not have
1228 // but this allows to write rules for all Z80ies
1229 if(IS_SM83 && (!strcmp(what, "sf") || !strcmp(what, "pf")))
1231 D(("Flag %s does not exist\n", what));
1232 return true;
1235 // enable sp and flags
1236 if(!isReg(what) && !isUReg(what) &&
1237 strcmp(what, "sp") && strcmp(what+1, "f"))
1238 return FALSE;
1240 _G.head = head;
1242 unvisitLines (_G.head);
1244 pl = endPl->next;
1245 if (!doTermScan (&pl, what))
1246 return FALSE;
1248 return TRUE;
1251 bool
1252 z80notUsedFrom (const char *what, const char *label, lineNode *head)
1254 lineNode *cpl;
1256 for (cpl = head; cpl; cpl = cpl->next)
1258 if (cpl->isLabel && !strncmp (label, cpl->line, strlen(label)))
1260 return z80notUsed (what, cpl, head);
1264 return false;
1267 bool
1268 z80canAssign (const char *op1, const char *op2, const char *exotic)
1270 const char *dst, *src;
1272 // Indexed accesses: One is the indexed one, the other one needs to be a reg or immediate.
1273 if(exotic)
1275 if(!strcmp(exotic, "ix") || !strcmp(exotic, "iy"))
1277 if(isReg(op1) || (IS_EZ80_Z80 && isRegPair(op1)))
1278 return TRUE;
1280 else if(!strcmp(op2, "ix") || !strcmp(op2, "iy"))
1282 if(isReg(exotic) || exotic[0] == '#' || (IS_EZ80_Z80 && isRegPair(exotic)))
1283 return TRUE;
1286 return FALSE;
1289 // Everything else.
1290 dst = op1;
1291 src = op2;
1293 // 8-bit regs can be assigned to each other directly.
1294 if(isReg(dst) && isReg(src))
1295 return true;
1296 if(HAS_IYL_INST) // With some restrictions also for iyl, iyh, ixl, ixh.
1298 if (isUReg(dst) && isReg(src) && src[0] <= 'e')
1299 return true;
1300 if (isUReg(src) && isReg(dst) && dst[0] <= 'e')
1301 return true;
1302 if (isUReg(dst) && isUReg(src) && src[1] == dst[1])
1303 return true;
1306 // Immediates van be loaded into 8-bit registers.
1307 if((isReg(dst) || HAS_IYL_INST && isUReg(dst)) && src[0] == '#')
1308 return true;
1310 // Same if at most one of them is (hl).
1311 if((isReg(dst) || (IS_EZ80_Z80 && isRegPair(dst))) && !strcmp(src, "(hl)"))
1312 return TRUE;
1313 if(!strcmp(dst, "(hl)") && (isReg(src) || (IS_EZ80_Z80 && isRegPair(src))))
1314 return TRUE;
1316 // Can assign between a and (bc), (de), (hl+), (hl-)
1317 if(!strcmp(dst, "a") &&
1318 (!strcmp(src, "(bc)") || !strcmp(src, "(de)") || !strcmp(src, "(hl+)") || !strcmp(src, "(hl-)")))
1319 return TRUE;
1320 if((!strcmp(dst, "(bc)") || !strcmp(dst, "(de)") || !strcmp(src, "(hl+)") || !strcmp(src, "(hl-)"))
1321 && !strcmp(src, "a"))
1322 return TRUE;
1324 // Can load immediate values directly into registers and register pairs.
1325 if((isReg(dst) || isRegPair(dst) || !strcmp(src, "sp")) && src[0] == '#')
1326 return TRUE;
1328 if((!strcmp(dst, "a") || (!IS_SM83 && (isRegPair(dst) || !strcmp(src, "sp")))) && !strncmp(src, "(#", 2))
1329 return TRUE;
1330 if(!strncmp(dst, "(#", 2) && (!strcmp(src, "a") || (!IS_SM83 && isRegPair(src)) || !strcmp(src, "sp")))
1331 return TRUE;
1333 // Can load immediate values directly into (hl).
1334 if(!strcmp(dst, "(hl)") && src[0] == '#')
1335 return true;
1337 // Can load between hl / ix / iy and sp.
1338 if(!strcmp(dst, "sp") && (!strcmp(src, "hl") || !strcmp(src, "ix") || !strcmp(src, "iy")) ||
1339 (!strcmp(dst, "hl") || !strcmp(dst, "ix") || !strcmp(dst, "iy")) && !strcmp(src, "sp"))
1340 return true;
1342 // Rabbit can load between iy and hl.
1343 if (IS_RAB &&
1344 (!strcmp(dst, "hl") && (!strcmp(src, "ix") || !strcmp(src, "iy")) ||
1345 (!strcmp(dst, "ix") || !strcmp(dst, "iy")) && !strcmp(src, "hl")))
1346 return true;
1348 return false;
1351 static const char *
1352 registerBaseName (const char *op)
1354 if (!strcmp (op, "d") || !strcmp (op, "e") || !strcmp (op, "(de)"))
1355 return "de";
1356 if (!strcmp (op, "b") || !strcmp (op, "c") || !strcmp (op, "(bc)"))
1357 return "bc";
1358 if (!strcmp (op, "h") || !strcmp (op, "l") || !strcmp (op, "(hl)") || !strcmp (op, "(hl+)") || !strcmp (op, "(hl-)"))
1359 return "hl";
1360 if (!strcmp (op, "iyh") || !strcmp (op, "iyl") || strstr (op, "iy"))
1361 return "iy";
1362 if (!strcmp (op, "ixh") || !strcmp (op, "ixl") || strstr (op, "ix"))
1363 return "ix";
1364 if (!strcmp (op, "a"))
1365 return "af";
1366 return op;
1369 // canJoinRegs(reg_hi reg_lo [dst]) returns TRUE,
1370 bool z80canJoinRegs (const char **regs, char dst[20])
1372 //check for only 2 source registers
1373 if (!regs[0] || !regs[1] || regs[2])
1374 return FALSE;
1375 size_t l1 = strlen (regs[0]);
1376 size_t l2 = strlen (regs[1]);
1377 if (l1 + l2 >= 20)
1378 return FALSE;
1379 if (l1 == 0 || l2 == 0)
1381 if (l1 == 0 && l2 == 0)
1382 return FALSE;
1383 strcpy (dst, registerBaseName (regs[l1 ? 0 : 1]));
1385 else
1387 memcpy (&dst[0], regs[0], l1);
1388 memcpy (&dst[l1], regs[1], l2 + 1); //copy including \0
1390 if (!strcmp (dst, "ixhixl") || !strcmp (dst, "iyhiyl"))
1392 if (IS_SM83)
1393 return FALSE;
1394 dst[2] = '\0';
1396 return isRegPair (dst);
1399 bool z80canSplitReg (const char *reg, char dst[][16], int nDst)
1401 int i;
1402 if (nDst < 0 || nDst > 2)
1403 return FALSE;
1404 if (!strcmp (reg, "bc") || !strcmp (reg, "de") || !strcmp (reg, "hl"))
1406 for (i = 0; i < nDst; ++i)
1408 dst[i][0] = reg[i];
1409 dst[i][1] = '\0';
1412 else if (HAS_IYL_INST && (!strcmp (reg, "ix") || !strcmp (reg, "iy")))
1414 for (i = 0; i < nDst; ++i)
1416 dst[i][0] = reg[0];
1417 dst[i][1] = reg[1];
1418 dst[i][2] = "hl"[i];
1419 dst[i][3] = '\0';
1422 else
1423 return FALSE;
1425 return TRUE;
1428 int z80instructionSize(lineNode *pl)
1430 const char *op1start, *op2start;
1432 /* move to the first operand:
1433 * leading spaces are already removed, skip the mnemonic */
1434 for (op1start = pl->line; *op1start && !isspace (*op1start); ++op1start);
1436 /* skip the spaces between mnemonic and the operand */
1437 while (isspace (*op1start))
1438 ++op1start;
1439 if (!(*op1start))
1440 op1start = NULL;
1442 if (op1start)
1444 /* move to the second operand:
1445 * find the comma and skip the following spaces */
1446 op2start = strchr(op1start, ',');
1447 if (op2start)
1450 ++op2start;
1451 while (isspace (*op2start));
1453 if ('\0' == *op2start)
1454 op2start = NULL;
1457 else
1458 op2start = NULL;
1460 if(TARGET_IS_TLCS90) // Todo: More accurate estimate.
1461 return(6);
1463 /* All ld instructions */
1464 if(ISINST(pl->line, "ld"))
1466 /* These 4 are the only cases of 4 byte long ld instructions. */
1467 if(!STRNCASECMP(op1start, "ix", 2) || !STRNCASECMP(op1start, "iy", 2))
1468 return(4);
1469 if((argCont(op1start, "(ix)") || argCont(op1start, "(iy)")) && op2start[0] == '#')
1470 return(4);
1472 if(op1start[0] == '(' && STRNCASECMP(op1start, "(bc)", 4) &&
1473 STRNCASECMP(op1start, "(de)", 4) && STRNCASECMP(op1start, "(hl" , 3) &&
1474 STRNCASECMP(op2start, "hl", 2) && STRNCASECMP(op2start, "a", 1) &&
1475 (!IS_SM83 || STRNCASECMP(op2start, "sp", 2)) ||
1476 op2start[0] == '(' && STRNCASECMP(op2start, "(bc)", 4) &&
1477 STRNCASECMP(op1start, "(de)", 4) && STRNCASECMP(op2start, "(hl" , 3) &&
1478 STRNCASECMP(op1start, "hl", 2) && STRNCASECMP(op1start, "a", 1))
1479 return(4);
1481 /* Rabbit 16-bit pointer load */
1482 if(IS_RAB && !STRNCASECMP(op1start, "hl", 2) && (argCont(op2start, "(hl)") || argCont(op2start, "(iy)")))
1483 return(4);
1484 if(IS_RAB && !STRNCASECMP(op1start, "hl", 2) && (argCont(op2start, "(sp)") || argCont(op2start, "(ix)")))
1485 return(3);
1487 /* eZ80 16-bit pointer load */
1488 if(IS_EZ80_Z80 &&
1489 (!STRNCASECMP(op1start, "bc", 2) || !STRNCASECMP(op1start, "de", 2) || !STRNCASECMP(op1start, "hl", 2) || !STRNCASECMP(op1start, "ix", 2) || !STRNCASECMP(op1start, "iy", 2)))
1491 if (!STRNCASECMP(op2start, "(hl)", 4))
1492 return(2);
1493 if (argCont(op2start, "(ix)") || argCont(op2start, "(iy)"))
1494 return(3);
1496 if(IS_EZ80_Z80 &&
1497 (!STRNCASECMP(op2start, "bc", 2) || !STRNCASECMP(op2start, "de", 2) || !STRNCASECMP(op2start, "hl", 2) || !STRNCASECMP(op2start, "ix", 2) || !STRNCASECMP(op2start, "iy", 2)))
1499 if (!STRNCASECMP(op1start, "(hl)", 4))
1500 return(2);
1501 if (argCont(op1start, "(ix)") || argCont(op1start, "(iy)"))
1502 return(3);
1505 /* These 4 are the only remaining cases of 3 byte long ld instructions. */
1506 if(argCont(op2start, "(ix)") || argCont(op2start, "(iy)"))
1507 return(3);
1508 if(argCont(op1start, "(ix)") || argCont(op1start, "(iy)"))
1509 return(3);
1510 if((op1start[0] == '(' && STRNCASECMP(op1start, "(bc)", 4) && STRNCASECMP(op1start, "(de)", 4) && STRNCASECMP(op1start, "(hl", 3)) ||
1511 (op2start[0] == '(' && STRNCASECMP(op2start, "(bc)", 4) && STRNCASECMP(op2start, "(de)", 4) && STRNCASECMP(op2start, "(hl", 3)))
1512 return(3);
1513 if(op2start[0] == '#' &&
1514 (!STRNCASECMP(op1start, "bc", 2) || !STRNCASECMP(op1start, "de", 2) || !STRNCASECMP(op1start, "hl", 2) || !STRNCASECMP(op1start, "sp", 2)))
1515 return(3);
1517 /* These 3 are the only remaining cases of 2 byte long ld instructions. */
1518 if(op2start[0] == '#')
1519 return(2);
1520 if(!STRNCASECMP(op1start, "i", 1) || !STRNCASECMP(op1start, "r", 1) ||
1521 !STRNCASECMP(op2start, "i", 1) || !STRNCASECMP(op2start, "r", 1))
1522 return(2);
1523 if(!STRNCASECMP(op2start, "ix", 2) || !STRNCASECMP(op2start, "iy", 2))
1524 return(2);
1526 /* All other ld instructions */
1527 return(1);
1530 // load from sp with offset
1531 if(IS_SM83 && (ISINST(pl->line, "lda") || ISINST(pl->line, "ldhl")))
1533 return(2);
1535 // load from/to 0xffXX addresses
1536 if(IS_SM83 && (ISINST(pl->line, "ldh") || ISINST(pl->line, "in") || ISINST(pl->line, "out")))
1538 if(!STRNCASECMP(pl->line, "(c)", 3))
1539 return(1);
1540 return(2);
1543 /* Exchange */
1544 if(ISINST(pl->line, "exx"))
1545 return(1);
1546 if(ISINST(pl->line, "ex"))
1548 if(!op2start)
1550 werrorfl(pl->ic->filename, pl->ic->lineno, W_UNRECOGNIZED_ASM, __FUNCTION__, 4, pl->line);
1551 return(4);
1553 if(argCont(op1start, "(sp)") && (IS_RAB || !STRNCASECMP(op2start, "ix", 2) || !STRNCASECMP(op2start, "iy", 2)))
1554 return(2);
1555 return(1);
1558 /* Push / pop */
1559 if(ISINST(pl->line, "push") && IS_Z80N && op1start[0] == '#')
1560 return(4);
1561 if(ISINST(pl->line, "push") || ISINST(pl->line, "pop"))
1563 if(!STRNCASECMP(op1start, "ix", 2) || !STRNCASECMP(op1start, "iy", 2))
1564 return(2);
1565 return(1);
1568 /* 16 bit add / subtract / and / or */
1569 if(IS_Z80N && ISINST(pl->line, "add") && (!STRNCASECMP(op1start, "bc", 2) || !STRNCASECMP(op1start, "de", 2) || !STRNCASECMP(op1start, "hl", 2)))
1570 return(4);
1571 if((ISINST(pl->line, "add") || ISINST(pl->line, "adc") || ISINST(pl->line, "sbc") || IS_RAB && (ISINST(pl->line, "and") || ISINST(pl->line, "or"))) &&
1572 !STRNCASECMP(op1start, "hl", 2))
1574 if(ISINST(pl->line, "add") || ISINST(pl->line, "and") || ISINST(pl->line, "or"))
1575 return(1);
1576 return(2);
1578 if((ISINST(pl->line, "add") || IS_RAB && (ISINST(pl->line, "and") || ISINST(pl->line, "or")))&& (!STRNCASECMP(op1start, "ix", 2) || !STRNCASECMP(op1start, "iy", 2)))
1579 return(2);
1581 /* signed 8 bit adjustment to stack pointer */
1582 if((IS_RAB || IS_SM83) && ISINST(pl->line, "add") && !STRNCASECMP(op1start, "sp", 2))
1583 return(2);
1585 /* 16 bit adjustment to stack pointer */
1586 if(IS_TLCS90 && ISINST(pl->line, "add") && !STRNCASECMP(op1start, "sp", 2))
1587 return(3);
1589 /* 8 bit arithmetic, two operands */
1590 if(op2start && op1start[0] == 'a' &&
1591 (ISINST(pl->line, "add") || ISINST(pl->line, "adc") || ISINST(pl->line, "sub") || ISINST(pl->line, "sbc") ||
1592 ISINST(pl->line, "cp") || ISINST(pl->line, "and") || ISINST(pl->line, "or") || ISINST(pl->line, "xor")))
1594 if(argCont(op2start, "(ix)") || argCont(op2start, "(iy)"))
1595 return(3);
1596 if(op2start[0] == '#')
1597 return(2);
1598 return(1);
1600 /* 8 bit arithmetic, shorthand for a */
1601 if(!op2start &&
1602 (ISINST(pl->line, "add") || ISINST(pl->line, "adc") || ISINST(pl->line, "sub") || ISINST(pl->line, "sbc") ||
1603 ISINST(pl->line, "cp") || ISINST(pl->line, "and") || ISINST(pl->line, "or") || ISINST(pl->line, "xor")))
1605 if(argCont(op1start, "(ix)") || argCont(op1start, "(iy)"))
1606 return(3);
1607 if(op1start[0] == '#')
1608 return(2);
1609 return(1);
1612 if(ISINST(pl->line, "rlca") || ISINST(pl->line, "rla") || ISINST(pl->line, "rrca") || ISINST(pl->line, "rra"))
1613 return(1);
1615 /* Increment / decrement */
1616 if(ISINST(pl->line, "inc") || ISINST(pl->line, "dec"))
1618 if(!STRNCASECMP(op1start, "ix", 2) || !STRNCASECMP(op1start, "iy", 2))
1619 return(2);
1620 if(argCont(op1start, "(ix)") || argCont(op1start, "(iy)"))
1621 return(3);
1622 return(1);
1625 if(ISINST(pl->line, "rlc") || ISINST(pl->line, "rl") || ISINST(pl->line, "rrc") || ISINST(pl->line, "rr") ||
1626 ISINST(pl->line, "sla") || ISINST(pl->line, "sra") || ISINST(pl->line, "srl"))
1628 if(argCont(op1start, "(ix)") || argCont(op1start, "(iy)"))
1629 return(4);
1630 return(2);
1633 if(ISINST(pl->line, "rld") || ISINST(pl->line, "rrd"))
1634 return(2);
1636 /* Bit */
1637 if(ISINST(pl->line, "bit") || ISINST(pl->line, "set") || ISINST(pl->line, "res"))
1639 if(argCont(op2start, "(ix)") || argCont(op2start, "(iy)"))
1640 return(4);
1641 return(2);
1644 if(ISINST(pl->line, "jr") || ISINST(pl->line, "djnz"))
1645 return(2);
1647 if(ISINST(pl->line, "jp"))
1649 if(!STRNCASECMP(op1start, "(hl)", 4))
1650 return(1);
1651 if(!STRNCASECMP(op1start, "(ix)", 4) || !STRNCASECMP(op1start, "(iy)", 4))
1652 return(2);
1653 return(3);
1656 if (IS_RAB &&
1657 (ISINST(pl->line, "ipset3") || ISINST(pl->line, "ipset2") ||
1658 ISINST(pl->line, "ipset1") || ISINST(pl->line, "ipset0") ||
1659 ISINST(pl->line, "ipres")))
1660 return(2);
1662 if(!IS_SM83 && (ISINST(pl->line, "reti") || ISINST(pl->line, "retn")))
1663 return(2);
1665 if(ISINST(pl->line, "ret") || ISINST(pl->line, "reti") || ISINST(pl->line, "rst"))
1666 return(1);
1668 if(ISINST(pl->line, "call"))
1669 return(3);
1671 /* Alias for ld a, (hl+)/(hld) etc */
1672 if(IS_SM83 && (ISINST(pl->line, "ldi") || ISINST(pl->line, "ldd")))
1673 return (1);
1675 if(ISINST(pl->line, "ldi") || ISINST(pl->line, "ldd") || ISINST(pl->line, "cpi") || ISINST(pl->line, "cpd"))
1676 return(2);
1678 if(ISINST(pl->line, "neg"))
1679 return(2);
1681 if(ISINST(pl->line, "daa") || ISINST(pl->line, "cpl") || ISINST(pl->line, "ccf") || ISINST(pl->line, "scf") ||
1682 ISINST(pl->line, "nop") || ISINST(pl->line, "halt") || ISINST(pl->line, "ei") || ISINST(pl->line, "di"))
1683 return(1);
1685 /* We always emit 2B stop due to hardware bugs*/
1686 if (IS_SM83 && ISINST(pl->line, "stop"))
1687 return(2);
1689 if(ISINST(pl->line, "im"))
1690 return(2);
1692 if(ISINST(pl->line, "in") || ISINST(pl->line, "out") || ISINST(pl->line, "ot") ||
1693 ISINST(pl->line, "ini") || ISINST(pl->line, "inir") || ISINST(pl->line, "ind") ||
1694 ISINST(pl->line, "indr") || ISINST(pl->line, "outi") || ISINST(pl->line, "otir") ||
1695 ISINST(pl->line, "outd") || ISINST(pl->line, "otdr"))
1697 return(2);
1700 if((IS_Z180 || IS_EZ80_Z80) && (ISINST(pl->line, "in0") || ISINST(pl->line, "out0")))
1701 return(3);
1703 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) && ISINST(pl->line, "mlt"))
1704 return(2);
1706 if (IS_R800 && (ISINST(pl->line, "multu") || ISINST(pl->line, "multuw")))
1707 return(2);
1709 if((IS_Z180 || IS_EZ80_Z80 || IS_Z80N) && ISINST(pl->line, "tst"))
1710 return((op1start[0] == '#' || op2start && op1start[0] == '#') ? 3 : 2);
1712 if(IS_RAB && (ISINST(pl->line, "ioi") || ISINST(pl->line, "ioe")))
1713 return(1);
1715 if(IS_RAB && ISINST(pl->line, "mul"))
1716 return(1);
1718 if(ISINST(pl->line, "lddr") || ISINST(pl->line, "ldir") || ISINST(pl->line, "cpir") || ISINST(pl->line, "cpdr"))
1719 return(2);
1721 if(IS_R3KA &&
1722 (ISINST(pl->line, "lddsr") || ISINST(pl->line, "ldisr") ||
1723 ISINST(pl->line, "lsdr") || ISINST(pl->line, "lsir") ||
1724 ISINST(pl->line, "lsddr") || ISINST(pl->line, "lsidr")))
1725 return(2);
1727 if(IS_R3KA && (ISINST(pl->line, "uma") || ISINST(pl->line, "ums")))
1728 return(2);
1730 if(IS_RAB && ISINST(pl->line, "bool"))
1731 return(!STRNCASECMP(op1start, "hl", 2) ? 1 : 2);
1733 if(IS_EZ80_Z80 && (ISINST(pl->line, "lea") || ISINST(pl->line, "pea")))
1734 return(3);
1736 if((IS_SM83 || IS_Z80N) && ISINST(pl->line, "swap"))
1737 return(2);
1739 if(IS_Z80N && (ISINST(pl->line, "swapnib") || ISINST(pl->line, "mirror") || ISINST(pl->line, "mul") ||
1740 ISINST(pl->line, "outinb") || ISINST(pl->line, "ldix") || ISINST(pl->line, "ldirx") ||
1741 ISINST(pl->line, "lddx") || ISINST(pl->line, "lddrx") || ISINST(pl->line, "ldpirx")))
1742 return(2);
1744 if(IS_Z80N &&
1745 (ISINST(pl->line, "bsla") ||
1746 ISINST(pl->line, "bsra") ||
1747 ISINST(pl->line, "bsrl") ||
1748 ISINST(pl->line, "bsrf") ||
1749 ISINST(pl->line, "brlc")))
1750 return(2);
1752 if(IS_Z80N && ISINST(pl->line, "nextreg"))
1753 return(op2start && !STRNCASECMP(op2start, "a", 1) ? 3 : 4);
1755 if(ISINST(pl->line, ".db") || ISINST(pl->line, ".byte"))
1757 int i, j;
1758 for(i = 1, j = 0; pl->line[j]; i += pl->line[j] == ',', j++);
1759 return(i);
1762 if(ISINST(pl->line, ".dw") || ISINST(pl->line, ".word"))
1764 int i, j;
1765 for(i = 1, j = 0; pl->line[j]; i += pl->line[j] == ',', j++);
1766 return(i * 2);
1769 if(IS_SM83 && ISINST(pl->line, ".tile"))
1771 const char *value;
1772 int i;
1773 // skip directive
1774 for (value = pl->line; *value && !isspace (*value); ++value);
1775 // skip space
1776 for (; *value && isspace (*value); ++value);
1777 // just part of the syntax
1778 if(*value == '^')
1779 ++value;
1780 // delimiter can be freely chosen
1781 char delimiter = *(value++);
1782 for (i = 0; *value && *value != delimiter; ++value, ++i);
1783 // has to end with delimiter
1784 // 8 characters per 2B tile
1785 if (*value == delimiter && i%8 == 0)
1786 return i/4;
1790 /* If the instruction is unrecognized, we shouldn't try to optimize. */
1791 /* For all we know it might be some .ds or similar possibly long line */
1792 /* Return a large value to discourage optimization. */
1793 if (pl->ic)
1794 werrorfl(pl->ic->filename, pl->ic->lineno, W_UNRECOGNIZED_ASM, __func__, 999, pl->line);
1795 else
1796 werrorfl("unknown", 0, W_UNRECOGNIZED_ASM, __func__, 999, pl->line);
1797 return(999);
1800 bool z80symmParmStack (const char *name)
1802 if (!strcmp (name, "___sdcc_enter_ix"))
1803 return false;
1804 return z80_symmParm_in_calls_from_current_function;