1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 With reg params for mul and div 16234 202 162D
22 Michael Hope <michaelh@earthling.net> 2000
23 Based on the mcs51 generator -
24 Sandeep Dutta . sandeep.dutta@usa.net (1998)
25 and - Jean-Louis VERN.jlvern@writeme.com (1999)
27 This program is free software; you can redistribute it and/or modify it
28 under the terms of the GNU General Public License as published by the
29 Free Software Foundation; either version 2, or (at your option) any
32 This program is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 In other words, you are welcome to use, share and improve this program.
43 You are forbidden to forbid anyone else to use, share and improve
44 what you give them. Help stamp out software-hoarding!
46 -------------------------------------------------------------------------*/
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
64 /* this is the down and dirty file with all kinds of kludgy & hacky
65 stuff. This is what it is all about CODE GENERATION for a specific MCU.
66 Some of the routines may be reusable, will have to see */
69 static char *_z80_return[] =
71 static char *_gbz80_return[] =
73 static char **_fReturn;
79 static char *accUse[] =
81 static char *hlUse[] =
90 extern FILE *codeOutFile;
130 "iy", "iy.l?", "iy.h?"
134 "ix", "ix.l?", "ix.h?"
138 #define RESULTONSTACK(x) \
139 (IC_RESULT(x) && IC_RESULT(x)->aop && \
140 IC_RESULT(x)->aop->type == AOP_STK )
142 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
143 #define CLRC emitcode("xor","a,a");
145 lineNode *lineHead = NULL;
146 lineNode *lineCurr = NULL;
148 static const unsigned char SLMask[] =
149 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
150 static const unsigned char SRMask[] =
151 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
190 static char *aopGet (asmop * aop, int offset, bool bit16);
195 /* Clean up the line so that it is 'prettier' */
196 if (strchr (buf, ':'))
198 /* Is a label - cant do anything */
201 /* Change the first (and probably only) ' ' to a tab so
216 emit2 (const char *szFormat,...)
221 va_start (ap, szFormat);
223 tvsprintf (buffer, szFormat, ap);
226 lineCurr = (lineCurr ?
227 connectLine (lineCurr, newLineNode (buffer)) :
228 (lineHead = newLineNode (buffer)));
230 lineCurr->isInline = inLine;
231 lineCurr->isDebug = debugLine;
234 /*-----------------------------------------------------------------*/
235 /* emitcode - writes the code into a file : for now it is simple */
236 /*-----------------------------------------------------------------*/
238 emitcode (const char *inst, const char *fmt,...)
241 char lb[MAX_INLINEASM];
248 sprintf (lb, "%s\t", inst);
249 vsprintf (lb + (strlen (lb)), fmt, ap);
252 vsprintf (lb, fmt, ap);
254 while (isspace (*lbp))
258 lineCurr = (lineCurr ?
259 connectLine (lineCurr, newLineNode (lb)) :
260 (lineHead = newLineNode (lb)));
261 lineCurr->isInline = inLine;
262 lineCurr->isDebug = debugLine;
279 emitcode("ld", "sp,ix");
280 emitcode("pop", "ix");
281 emitcode("pop", "de");
287 getPairName (asmop * aop)
289 if (aop->type == AOP_REG)
291 switch (aop->aopu.aop_reg[0]->rIdx)
304 else if (aop->type == AOP_STR)
306 switch (*aop->aopu.aop_str[0])
324 getPairId (asmop * aop)
328 if (aop->type == AOP_REG)
330 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
334 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
338 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
343 if (aop->type == AOP_STR)
345 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
349 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
353 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
362 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
366 return (getPairId (aop) != PAIR_INVALID);
370 isPtrPair (asmop * aop)
372 PAIR_ID pairId = getPairId (aop);
383 /** Push a register pair onto the stack */
385 genPairPush (asmop * aop)
387 emitcode ("push", "%s", getPairName (aop));
391 /*-----------------------------------------------------------------*/
392 /* newAsmop - creates a new asmOp */
393 /*-----------------------------------------------------------------*/
395 newAsmop (short type)
399 aop = Safe_calloc (1, sizeof (asmop));
404 /*-----------------------------------------------------------------*/
405 /* aopForSym - for a true symbol */
406 /*-----------------------------------------------------------------*/
408 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
415 wassert (sym->etype);
417 space = SPEC_OCLS (sym->etype);
419 /* if already has one */
423 /* Assign depending on the storage class */
424 if (sym->onStack || sym->iaccess)
426 emitcode ("", "; AOP_STK for %s", sym->rname);
427 sym->aop = aop = newAsmop (AOP_STK);
428 aop->size = getSize (sym->type);
429 aop->aopu.aop_stk = sym->stack;
433 /* special case for a function */
434 if (IS_FUNC (sym->type))
436 sym->aop = aop = newAsmop (AOP_IMMD);
437 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
438 strcpy (aop->aopu.aop_immd, sym->rname);
445 /* if it is in direct space */
446 if (IN_REGSP (space) && !requires_a)
448 sym->aop = aop = newAsmop (AOP_SFR);
449 aop->aopu.aop_dir = sym->rname;
450 aop->size = getSize (sym->type);
451 emitcode ("", "; AOP_SFR for %s", sym->rname);
456 /* only remaining is far space */
457 /* in which case DPTR gets the address */
460 emitcode ("", "; AOP_HL for %s", sym->rname);
461 sym->aop = aop = newAsmop (AOP_HL);
465 sym->aop = aop = newAsmop (AOP_IY);
467 aop->size = getSize (sym->type);
468 aop->aopu.aop_dir = sym->rname;
470 /* if it is in code space */
471 if (IN_CODESPACE (space))
477 /*-----------------------------------------------------------------*/
478 /* aopForRemat - rematerialzes an object */
479 /*-----------------------------------------------------------------*/
481 aopForRemat (symbol * sym)
484 iCode *ic = sym->rematiCode;
485 asmop *aop = newAsmop (AOP_IMMD);
489 /* if plus or minus print the right hand side */
490 if (ic->op == '+' || ic->op == '-')
492 /* PENDING: for re-target */
493 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
496 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
499 /* we reached the end */
500 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
504 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
505 strcpy (aop->aopu.aop_immd, buffer);
509 /*-----------------------------------------------------------------*/
510 /* regsInCommon - two operands have some registers in common */
511 /*-----------------------------------------------------------------*/
513 regsInCommon (operand * op1, operand * op2)
518 /* if they have registers in common */
519 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
522 sym1 = OP_SYMBOL (op1);
523 sym2 = OP_SYMBOL (op2);
525 if (sym1->nRegs == 0 || sym2->nRegs == 0)
528 for (i = 0; i < sym1->nRegs; i++)
534 for (j = 0; j < sym2->nRegs; j++)
539 if (sym2->regs[j] == sym1->regs[i])
547 /*-----------------------------------------------------------------*/
548 /* operandsEqu - equivalent */
549 /*-----------------------------------------------------------------*/
551 operandsEqu (operand * op1, operand * op2)
555 /* if they not symbols */
556 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
559 sym1 = OP_SYMBOL (op1);
560 sym2 = OP_SYMBOL (op2);
562 /* if both are itemps & one is spilt
563 and the other is not then false */
564 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
565 sym1->isspilt != sym2->isspilt)
568 /* if they are the same */
572 if (strcmp (sym1->rname, sym2->rname) == 0)
576 /* if left is a tmp & right is not */
577 if (IS_ITEMP (op1) &&
580 (sym1->usl.spillLoc == sym2))
583 if (IS_ITEMP (op2) &&
587 (sym2->usl.spillLoc == sym1))
593 /*-----------------------------------------------------------------*/
594 /* sameRegs - two asmops have the same registers */
595 /*-----------------------------------------------------------------*/
597 sameRegs (asmop * aop1, asmop * aop2)
601 if (aop1->type == AOP_SFR ||
602 aop2->type == AOP_SFR)
608 if (aop1->type != AOP_REG ||
609 aop2->type != AOP_REG)
612 if (aop1->size != aop2->size)
615 for (i = 0; i < aop1->size; i++)
616 if (aop1->aopu.aop_reg[i] !=
617 aop2->aopu.aop_reg[i])
623 /*-----------------------------------------------------------------*/
624 /* aopOp - allocates an asmop for an operand : */
625 /*-----------------------------------------------------------------*/
627 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
636 /* if this a literal */
637 if (IS_OP_LITERAL (op))
639 op->aop = aop = newAsmop (AOP_LIT);
640 aop->aopu.aop_lit = op->operand.valOperand;
641 aop->size = getSize (operandType (op));
645 /* if already has a asmop then continue */
649 /* if the underlying symbol has a aop */
650 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
652 op->aop = OP_SYMBOL (op)->aop;
656 /* if this is a true symbol */
657 if (IS_TRUE_SYMOP (op))
659 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
663 /* this is a temporary : this has
669 e) can be a return use only */
671 sym = OP_SYMBOL (op);
673 /* if the type is a conditional */
674 if (sym->regType == REG_CND)
676 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
681 /* if it is spilt then two situations
683 b) has a spill location */
684 if (sym->isspilt || sym->nRegs == 0)
686 /* rematerialize it NOW */
689 sym->aop = op->aop = aop =
691 aop->size = getSize (sym->type);
698 if (sym->accuse == ACCUSE_A)
700 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
701 aop->size = getSize (sym->type);
702 for (i = 0; i < 2; i++)
703 aop->aopu.aop_str[i] = accUse[i];
705 else if (sym->accuse == ACCUSE_HL)
708 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
709 aop->size = getSize (sym->type);
710 for (i = 0; i < 2; i++)
711 aop->aopu.aop_str[i] = hlUse[i];
721 aop = op->aop = sym->aop = newAsmop (AOP_STR);
722 aop->size = getSize (sym->type);
723 for (i = 0; i < 4; i++)
724 aop->aopu.aop_str[i] = _fReturn[i];
728 /* else spill location */
729 sym->aop = op->aop = aop =
730 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
731 aop->size = getSize (sym->type);
735 /* must be in a register */
736 sym->aop = op->aop = aop = newAsmop (AOP_REG);
737 aop->size = sym->nRegs;
738 for (i = 0; i < sym->nRegs; i++)
739 aop->aopu.aop_reg[i] = sym->regs[i];
742 /*-----------------------------------------------------------------*/
743 /* freeAsmop - free up the asmop given to an operand */
744 /*----------------------------------------------------------------*/
746 freeAsmop (operand * op, asmop * aaop, iCode * ic)
764 /* all other cases just dealloc */
770 OP_SYMBOL (op)->aop = NULL;
771 /* if the symbol has a spill */
773 SPIL_LOC (op)->aop = NULL;
779 isLitWord (asmop * aop)
781 /* if (aop->size != 2)
794 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
800 if (aop->size != 2 && aop->type != AOP_HL)
803 /* depending on type */
809 /* PENDING: for re-target */
811 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
813 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
814 rs = Safe_calloc (1, strlen (s) + 1);
819 value *val = aop->aopu.aop_lit;
820 /* if it is a float then it gets tricky */
821 /* otherwise it is fairly simple */
822 if (!IS_FLOAT (val->type))
824 unsigned long v = floatFromVal (val);
830 tsprintf (buffer, "!immedword", v);
832 tsprintf (buffer, "!constword", v);
833 rs = Safe_calloc (1, strlen (buffer) + 1);
834 return strcpy (rs, buffer);
840 convertFloat (&f, floatFromVal (val));
842 tsprintf (buffer, "!immedword", f.w[offset / 2]);
844 tsprintf (buffer, "!constword", f.w[offset / 2]);
845 rs = Safe_calloc (1, strlen (buffer) + 1);
846 return strcpy (rs, buffer);
855 aopGetWord (asmop * aop, int offset)
857 return aopGetLitWordLong (aop, offset, TRUE);
861 isPtr (const char *s)
863 if (!strcmp (s, "hl"))
865 if (!strcmp (s, "ix"))
867 if (!strcmp (s, "iy"))
873 adjustPair (const char *pair, int *pold, int new)
879 emitcode ("inc", "%s", pair);
884 emitcode ("dec", "%s", pair);
890 spillPair (PAIR_ID pairId)
892 _G.pairs[pairId].last_type = AOP_INVALID;
893 _G.pairs[pairId].lit = NULL;
904 requiresHL (asmop * aop)
917 fetchLitSpecial (asmop * aop, bool negate, bool xor)
920 value *val = aop->aopu.aop_lit;
922 wassert (aop->type == AOP_LIT);
923 wassert (!IS_FLOAT (val->type));
925 v = floatFromVal (val);
933 tsprintf (buffer, "!immedword", v);
934 return gc_strdup (buffer);
938 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
941 const char *pair = _pairs[pairId].name;
942 l = aopGetLitWordLong (left, 0, FALSE);
947 if (pairId == PAIR_HL || pairId == PAIR_IY)
949 if (_G.pairs[pairId].last_type == left->type)
951 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
953 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
955 adjustPair (pair, &_G.pairs[pairId].offset, offset);
958 if (pairId == PAIR_IY && abs (offset) < 127)
965 _G.pairs[pairId].last_type = left->type;
966 _G.pairs[pairId].lit = gc_strdup (l);
967 _G.pairs[pairId].offset = offset;
969 if (IS_GB && pairId == PAIR_DE && 0)
971 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
973 if (abs (_G.pairs[pairId].offset - offset) < 3)
975 adjustPair (pair, &_G.pairs[pairId].offset, offset);
979 _G.pairs[pairId].last_type = left->type;
980 _G.pairs[pairId].lit = gc_strdup (l);
981 _G.pairs[pairId].offset = offset;
983 /* Both a lit on the right and a true symbol on the left */
985 emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
987 emit2 ("ld %s,!hashedstr", pair, l);
991 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
993 /* if this is remateriazable */
996 fetchLitPair (pairId, aop, offset);
999 { /* we need to get it byte by byte */
1000 if (pairId == PAIR_HL && IS_GB && requiresHL (aop))
1002 aopGet (aop, offset, FALSE);
1006 emit2 ("ld l,!*hl");
1007 emit2 ("ld h,!immedbyte", 0);
1011 emit2 ("ld h,!*hl");
1015 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1018 else if (IS_Z80 && aop->type == AOP_IY)
1020 /* Instead of fetching relative to IY, just grab directly
1021 from the address IY refers to */
1022 char *l = aopGetLitWordLong (aop, offset, FALSE);
1024 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1028 emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1029 emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1031 /* PENDING: check? */
1032 if (pairId == PAIR_HL)
1033 spillPair (PAIR_HL);
1038 fetchPair (PAIR_ID pairId, asmop * aop)
1040 fetchPairLong (pairId, aop, 0);
1044 fetchHL (asmop * aop)
1046 fetchPair (PAIR_HL, aop);
1050 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1052 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1057 fetchLitPair (pairId, aop, 0);
1060 fetchLitPair (pairId, aop, offset);
1061 _G.pairs[pairId].offset = offset;
1065 /* Doesnt include _G.stack.pushed */
1066 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1067 if (aop->aopu.aop_stk > 0)
1069 abso += _G.stack.param_offset;
1071 assert (pairId == PAIR_HL);
1072 /* In some cases we can still inc or dec hl */
1073 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1075 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1079 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1081 _G.pairs[pairId].offset = abso;
1087 _G.pairs[pairId].last_type = aop->type;
1093 emit2 ("!tlabeldef", key);
1097 /*-----------------------------------------------------------------*/
1098 /* aopGet - for fetching value of the aop */
1099 /*-----------------------------------------------------------------*/
1101 aopGet (asmop * aop, int offset, bool bit16)
1106 /* offset is greater than size then zero */
1107 /* PENDING: this seems a bit screwed in some pointer cases. */
1108 if (offset > (aop->size - 1) &&
1109 aop->type != AOP_LIT)
1112 /* depending on type */
1116 /* PENDING: re-target */
1118 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1123 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1126 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1129 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1134 rs = Safe_calloc (1, strlen (s) + 1);
1140 emitcode ("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1142 rs = Safe_calloc (1, strlen (s) + 1);
1148 emitcode ("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1150 rs = Safe_calloc (1, strlen (s) + 1);
1155 return aop->aopu.aop_reg[offset]->name;
1159 setupPair (PAIR_HL, aop, offset);
1160 tsprintf (s, "!*hl");
1161 return gc_strdup (s);
1165 setupPair (PAIR_IY, aop, offset);
1166 tsprintf (s, "!*iyx", offset);
1167 rs = Safe_calloc (1, strlen (s) + 1);
1174 setupPair (PAIR_HL, aop, offset);
1175 tsprintf (s, "!*hl");
1179 if (aop->aopu.aop_stk >= 0)
1180 offset += _G.stack.param_offset;
1181 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1183 rs = Safe_calloc (1, strlen (s) + 1);
1198 wassert (offset < 2);
1199 return aop->aopu.aop_str[offset];
1202 return aopLiteral (aop->aopu.aop_lit, offset);
1206 return aop->aopu.aop_str[offset];
1210 wassertl (0, "aopget got unsupported aop->type");
1215 isRegString (const char *s)
1217 if (!strcmp (s, "b") ||
1229 isConstant (const char *s)
1231 /* This is a bit of a hack... */
1232 return (*s == '#' || *s == '$');
1236 canAssignToPtr (const char *s)
1238 if (isRegString (s))
1245 /*-----------------------------------------------------------------*/
1246 /* aopPut - puts a string for a aop */
1247 /*-----------------------------------------------------------------*/
1249 aopPut (asmop * aop, const char *s, int offset)
1251 if (aop->size && offset > (aop->size - 1))
1253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1254 "aopPut got offset > aop->size");
1258 /* will assign value to value */
1259 /* depending on where it is ofcourse */
1265 if (strcmp (s, "a"))
1266 emitcode ("ld", "a,%s", s);
1267 emitcode ("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1272 if (strcmp (s, "a"))
1273 emitcode ("ld", "a,%s", s);
1274 emitcode ("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1278 if (!strcmp (s, "!*hl"))
1279 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1282 aop->aopu.aop_reg[offset]->name, s);
1287 setupPair (PAIR_IY, aop, offset);
1288 if (!canAssignToPtr (s))
1290 emit2 ("ld a,%s", s);
1291 emit2 ("ld !*iyx,a", offset);
1294 emit2 ("ld !*iyx,%s", offset, s);
1299 /* PENDING: for re-target */
1300 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1302 emit2 ("ld a,!*hl");
1305 setupPair (PAIR_HL, aop, offset);
1307 emit2 ("ld !*hl,%s", s);
1313 /* PENDING: re-target */
1314 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1316 emit2 ("ld a,!*hl");
1319 setupPair (PAIR_HL, aop, offset);
1320 if (!canAssignToPtr (s))
1322 emit2 ("ld a,%s", s);
1323 emit2 ("ld !*hl,a");
1326 emit2 ("ld !*hl,%s", s);
1330 if (aop->aopu.aop_stk >= 0)
1331 offset += _G.stack.param_offset;
1332 if (!canAssignToPtr (s))
1334 emit2 ("ld a,%s", s);
1335 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1338 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1343 /* if bit variable */
1344 if (!aop->aopu.aop_dir)
1351 /* In bit space but not in C - cant happen */
1358 if (strcmp (aop->aopu.aop_str[offset], s))
1360 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1366 if (!offset && (strcmp (s, "acc") == 0))
1371 emitcode ("", "; Error aopPut AOP_ACC");
1375 if (strcmp (aop->aopu.aop_str[offset], s))
1376 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1381 wassert (offset < 2);
1382 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1386 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1387 "aopPut got unsupported aop->type");
1392 #define AOP(op) op->aop
1393 #define AOP_TYPE(op) AOP(op)->type
1394 #define AOP_SIZE(op) AOP(op)->size
1395 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1398 commitPair (asmop * aop, PAIR_ID id)
1400 if (id == PAIR_HL && requiresHL (aop))
1404 aopPut (aop, "a", 0);
1405 aopPut (aop, "d", 1);
1409 aopPut (aop, _pairs[id].l, 0);
1410 aopPut (aop, _pairs[id].h, 1);
1414 /*-----------------------------------------------------------------*/
1415 /* getDataSize - get the operand data size */
1416 /*-----------------------------------------------------------------*/
1418 getDataSize (operand * op)
1421 size = AOP_SIZE (op);
1430 /*-----------------------------------------------------------------*/
1431 /* movLeft2Result - move byte from left to result */
1432 /*-----------------------------------------------------------------*/
1434 movLeft2Result (operand * left, int offl,
1435 operand * result, int offr, int sign)
1438 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1440 l = aopGet (AOP (left), offl, FALSE);
1444 aopPut (AOP (result), l, offr);
1454 /** Put Acc into a register set
1457 outAcc (operand * result)
1460 size = getDataSize (result);
1463 aopPut (AOP (result), "a", 0);
1466 /* unsigned or positive */
1469 aopPut (AOP (result), zero, offset++);
1474 /** Take the value in carry and put it into a register
1477 outBitCLong (operand * result, bool swap_sense)
1479 /* if the result is bit */
1480 if (AOP_TYPE (result) == AOP_CRY)
1482 emitcode ("", "; Note: outBitC form 1");
1483 aopPut (AOP (result), "blah", 0);
1487 emit2 ("ld a,!zero");
1490 emit2 ("xor a,!immedbyte", 1);
1496 outBitC (operand * result)
1498 outBitCLong (result, FALSE);
1501 /*-----------------------------------------------------------------*/
1502 /* toBoolean - emit code for orl a,operator(sizeop) */
1503 /*-----------------------------------------------------------------*/
1505 toBoolean (operand * oper)
1507 int size = AOP_SIZE (oper);
1511 emitcode ("ld", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1514 emitcode ("or", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1518 if (AOP (oper)->type != AOP_ACC)
1521 emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
1526 /*-----------------------------------------------------------------*/
1527 /* genNot - generate code for ! operation */
1528 /*-----------------------------------------------------------------*/
1532 sym_link *optype = operandType (IC_LEFT (ic));
1534 /* assign asmOps to operand & result */
1535 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1536 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1538 /* if in bit space then a special case */
1539 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1544 /* if type float then do float */
1545 if (IS_FLOAT (optype))
1550 toBoolean (IC_LEFT (ic));
1555 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1556 emit2 ("sub a,!one");
1557 outBitC (IC_RESULT (ic));
1559 /* release the aops */
1560 freeAsmop (IC_LEFT (ic), NULL, ic);
1561 freeAsmop (IC_RESULT (ic), NULL, ic);
1564 /*-----------------------------------------------------------------*/
1565 /* genCpl - generate code for complement */
1566 /*-----------------------------------------------------------------*/
1574 /* assign asmOps to operand & result */
1575 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1576 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1578 /* if both are in bit space then
1580 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1581 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1586 size = AOP_SIZE (IC_RESULT (ic));
1589 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1591 emitcode ("cpl", "");
1592 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1595 /* release the aops */
1596 freeAsmop (IC_LEFT (ic), NULL, ic);
1597 freeAsmop (IC_RESULT (ic), NULL, ic);
1600 /*-----------------------------------------------------------------*/
1601 /* genUminus - unary minus code generation */
1602 /*-----------------------------------------------------------------*/
1604 genUminus (iCode * ic)
1607 sym_link *optype, *rtype;
1610 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1611 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1613 /* if both in bit space then special
1615 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1616 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1622 optype = operandType (IC_LEFT (ic));
1623 rtype = operandType (IC_RESULT (ic));
1625 /* if float then do float stuff */
1626 if (IS_FLOAT (optype))
1632 /* otherwise subtract from zero */
1633 size = AOP_SIZE (IC_LEFT (ic));
1638 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1639 emit2 ("ld a,!zero");
1640 emit2 ("sbc a,%s", l);
1641 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1644 /* if any remaining bytes in the result */
1645 /* we just need to propagate the sign */
1646 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1651 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1655 /* release the aops */
1656 freeAsmop (IC_LEFT (ic), NULL, ic);
1657 freeAsmop (IC_RESULT (ic), NULL, ic);
1661 _push (PAIR_ID pairId)
1663 emit2 ("push %s", _pairs[pairId].name);
1664 _G.stack.pushed += 2;
1668 _pop (PAIR_ID pairId)
1670 emit2 ("pop %s", _pairs[pairId].name);
1671 _G.stack.pushed -= 2;
1675 /*-----------------------------------------------------------------*/
1676 /* assignResultValue - */
1677 /*-----------------------------------------------------------------*/
1679 assignResultValue (operand * oper)
1681 int size = AOP_SIZE (oper);
1684 wassert (size <= 4);
1685 topInA = requiresHL (AOP (oper));
1689 wassert (size <= 2);
1691 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1693 /* We do it the hard way here. */
1695 aopPut (AOP (oper), _fReturn[0], 0);
1696 aopPut (AOP (oper), _fReturn[1], 1);
1697 emitcode ("pop", "de");
1698 _G.stack.pushed -= 2;
1699 aopPut (AOP (oper), _fReturn[0], 2);
1700 aopPut (AOP (oper), _fReturn[1], 3);
1706 aopPut (AOP (oper), _fReturn[size], size);
1711 /*-----------------------------------------------------------------*/
1712 /* genIpush - genrate code for pushing this gets a little complex */
1713 /*-----------------------------------------------------------------*/
1715 genIpush (iCode * ic)
1717 int size, offset = 0;
1720 /* if this is not a parm push : ie. it is spill push
1721 and spill push is always done on the local stack */
1724 /* and the item is spilt then do nothing */
1725 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1728 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1729 size = AOP_SIZE (IC_LEFT (ic));
1730 /* push it on the stack */
1731 if (isPair (AOP (IC_LEFT (ic))))
1733 emitcode ("push", getPairName (AOP (IC_LEFT (ic))));
1734 _G.stack.pushed += 2;
1741 /* Simple for now - load into A and PUSH AF */
1742 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1744 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1746 emit2 ("ld a,(%s)", l);
1750 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1751 emit2 ("ld a,%s", l);
1761 /* Hmmm... what about saving the currently used registers
1764 /* then do the push */
1765 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1767 size = AOP_SIZE (IC_LEFT (ic));
1769 if (isPair (AOP (IC_LEFT (ic))))
1771 _G.stack.pushed += 2;
1772 emitcode ("push", "%s", getPairName (AOP (IC_LEFT (ic))));
1778 fetchHL (AOP (IC_LEFT (ic)));
1779 emitcode ("push", "hl");
1780 spillPair (PAIR_HL);
1781 _G.stack.pushed += 2;
1786 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1787 emitcode ("push", "hl");
1788 spillPair (PAIR_HL);
1789 _G.stack.pushed += 2;
1790 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1791 emitcode ("push", "hl");
1792 spillPair (PAIR_HL);
1793 _G.stack.pushed += 2;
1799 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1801 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1803 emit2 ("ld a,(%s)", l);
1807 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1808 emit2 ("ld a,%s", l);
1810 emitcode ("push", "af");
1811 emitcode ("inc", "sp");
1816 freeAsmop (IC_LEFT (ic), NULL, ic);
1819 /*-----------------------------------------------------------------*/
1820 /* genIpop - recover the registers: can happen only for spilling */
1821 /*-----------------------------------------------------------------*/
1823 genIpop (iCode * ic)
1828 /* if the temp was not pushed then */
1829 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1832 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1833 size = AOP_SIZE (IC_LEFT (ic));
1834 offset = (size - 1);
1835 if (isPair (AOP (IC_LEFT (ic))))
1837 emitcode ("pop", getPairName (AOP (IC_LEFT (ic))));
1843 emitcode ("dec", "sp");
1844 emitcode ("pop", "hl");
1845 spillPair (PAIR_HL);
1846 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1850 freeAsmop (IC_LEFT (ic), NULL, ic);
1854 _isPairUsed (iCode * ic, PAIR_ID pairId)
1860 if (bitVectBitValue (ic->rUsed, D_IDX))
1862 if (bitVectBitValue (ic->rUsed, E_IDX))
1872 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1876 symbol *sym = OP_SYMBOL (op);
1878 if (sym->isspilt || sym->nRegs == 0)
1881 aopOp (op, ic, FALSE, FALSE);
1884 if (aop->type == AOP_REG)
1887 for (i = 0; i < aop->size; i++)
1889 if (pairId == PAIR_DE)
1891 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1892 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
1894 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
1904 freeAsmop (IC_LEFT (ic), NULL, ic);
1908 /* This is quite unfortunate */
1910 setArea (int inHome)
1912 static int lastArea = 0;
1915 if (_G.in_home != inHome) {
1917 const char *sz = port->mem.code_name;
1918 port->mem.code_name = "HOME";
1919 emit2("!area", CODE_NAME);
1920 port->mem.code_name = sz;
1923 emit2("!area", CODE_NAME); */
1924 _G.in_home = inHome;
1934 /** Emit the code for a call statement
1937 emitCall (iCode * ic, bool ispcall)
1940 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
1942 /* if caller saves & we have not saved then */
1948 /* if send set is not empty then assign */
1953 int n = elementsInSet (sendSet);
1954 if (IS_Z80 && n == 2 && _isPairUsed (ic, PAIR_DE))
1956 /* Only push de if it is used and if it's not used
1957 in the return value */
1958 /* Panic if partly used */
1959 if (_opUsesPair (IC_RESULT (ic), ic, PAIR_DE) == 1)
1961 emit2 ("; Warning: de crossover");
1963 else if (!_opUsesPair (IC_RESULT (ic), ic, PAIR_DE))
1971 if (IS_Z80 && n == 2)
1973 /* Want to load HL first, then DE as HL may = DE */
1974 sic = setFirstItem (sendSet);
1975 sic = setNextItem (sendSet);
1976 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1977 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
1979 freeAsmop (IC_LEFT (sic), NULL, sic);
1980 sic = setFirstItem (sendSet);
1981 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1982 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
1984 freeAsmop (IC_LEFT (sic), NULL, sic);
1988 for (sic = setFirstItem (sendSet); sic;
1989 sic = setNextItem (sendSet))
1992 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1993 size = AOP_SIZE (IC_LEFT (sic));
1994 wassert (size <= 2);
1995 /* Always send in pairs */
1999 if (IS_Z80 && n == 1)
2000 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2002 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
2005 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2008 /* Send set too big */
2012 freeAsmop (IC_LEFT (sic), NULL, sic);
2023 if (IS_BANKEDCALL (detype))
2025 werror (W_INDIR_BANKED);
2027 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2029 if (isLitWord (AOP (IC_LEFT (ic))))
2031 emitcode ("", "; Special case where the pCall is to a constant");
2032 emitcode ("call", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2036 symbol *rlbl = newiTempLabel (NULL);
2037 spillPair (PAIR_HL);
2038 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2039 emitcode ("push", "hl");
2040 _G.stack.pushed += 2;
2042 fetchHL (AOP (IC_LEFT (ic)));
2044 emit2 ("!tlabeldef", (rlbl->key + 100));
2045 _G.stack.pushed -= 2;
2047 freeAsmop (IC_LEFT (ic), NULL, ic);
2051 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2052 OP_SYMBOL (IC_LEFT (ic))->rname :
2053 OP_SYMBOL (IC_LEFT (ic))->name;
2054 if (IS_BANKEDCALL (detype))
2056 emit2 ("call banked_call");
2057 emit2 ("!dws", name);
2058 emit2 ("!dw !bankimmeds", name);
2063 emit2 ("call %s", name);
2068 /* if we need assign a result value */
2069 if ((IS_ITEMP (IC_RESULT (ic)) &&
2070 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2071 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2072 IS_TRUE_SYMOP (IC_RESULT (ic)))
2076 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2079 assignResultValue (IC_RESULT (ic));
2081 freeAsmop (IC_RESULT (ic), NULL, ic);
2084 /* adjust the stack for parameters if required */
2087 int i = ic->parmBytes;
2088 _G.stack.pushed -= i;
2091 emit2 ("!ldaspsp", i);
2098 emitcode ("ld", "hl,#%d", i);
2099 emitcode ("add", "hl,sp");
2100 emitcode ("ld", "sp,hl");
2106 emitcode ("pop", "hl");
2110 emitcode ("inc", "sp");
2119 /*-----------------------------------------------------------------*/
2120 /* genCall - generates a call statement */
2121 /*-----------------------------------------------------------------*/
2123 genCall (iCode * ic)
2125 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
2126 emitCall (ic, FALSE);
2129 /*-----------------------------------------------------------------*/
2130 /* genPcall - generates a call by pointer statement */
2131 /*-----------------------------------------------------------------*/
2133 genPcall (iCode * ic)
2135 emitCall (ic, TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* resultRemat - result is rematerializable */
2140 /*-----------------------------------------------------------------*/
2142 resultRemat (iCode * ic)
2144 if (SKIP_IC (ic) || ic->op == IFX)
2147 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2149 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2150 if (sym->remat && !POINTER_SET (ic))
2157 extern set *publics;
2159 /*-----------------------------------------------------------------*/
2160 /* genFunction - generated code for function entry */
2161 /*-----------------------------------------------------------------*/
2163 genFunction (iCode * ic)
2165 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2169 setArea (IS_NONBANKED (sym->etype));
2172 if (!IS_STATIC (sym->etype))
2174 addSetIfnotP (&publics, sym);
2177 /* create the function header */
2178 emit2 ("!functionheader", sym->name);
2179 /* PENDING: portability. */
2180 emit2 ("__%s_start:", sym->rname);
2181 emit2 ("!functionlabeldef", sym->rname);
2183 fetype = getSpec (operandType (IC_LEFT (ic)));
2185 /* if critical function then turn interrupts off */
2186 if (SPEC_CRTCL (fetype))
2189 /* if this is an interrupt service routine then
2190 save acc, b, dpl, dph */
2191 if (IS_ISR (sym->etype))
2195 /* PENDING: callee-save etc */
2197 /* If BC or DE are used, then push */
2198 _G.stack.pushed_bc = 0;
2199 _G.stack.pushed_de = 0;
2200 _G.stack.param_offset = 0;
2204 for (i = 0; i < sym->regsUsed->size; i++)
2206 if (bitVectBitValue (sym->regsUsed, i))
2212 _G.stack.pushed_bc = 1;
2217 _G.stack.pushed_de = 1;
2222 if (_G.stack.pushed_bc)
2225 _G.stack.param_offset += 2;
2227 if (_G.stack.pushed_de)
2230 _G.stack.param_offset += 2;
2234 /* adjust the stack for the function */
2235 _G.stack.last = sym->stack;
2238 emit2 ("!enterx", sym->stack);
2241 _G.stack.offset = sym->stack;
2244 /*-----------------------------------------------------------------*/
2245 /* genEndFunction - generates epilogue for functions */
2246 /*-----------------------------------------------------------------*/
2248 genEndFunction (iCode * ic)
2250 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2252 if (IS_ISR (sym->etype))
2258 if (SPEC_CRTCL (sym->etype))
2261 /* PENDING: calleeSave */
2263 /* if debug then send end of function */
2264 if (options.debug && currFunc)
2267 emitcode ("", "C$%s$%d$%d$%d ==.",
2268 FileBaseName (ic->filename), currFunc->lastLine,
2269 ic->level, ic->block);
2270 if (IS_STATIC (currFunc->etype))
2271 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2273 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2276 if (_G.stack.offset)
2277 emit2 ("!leavex", _G.stack.offset);
2281 if (_G.stack.pushed_de)
2283 if (_G.stack.pushed_bc)
2285 /* Both baned and non-banked just ret */
2288 /* PENDING: portability. */
2289 emit2 ("__%s_end:", sym->rname);
2291 _G.flush_statics = 1;
2292 _G.stack.pushed = 0;
2293 _G.stack.offset = 0;
2296 /*-----------------------------------------------------------------*/
2297 /* genRet - generate code for return statement */
2298 /*-----------------------------------------------------------------*/
2303 /* Errk. This is a hack until I can figure out how
2304 to cause dehl to spill on a call */
2305 int size, offset = 0;
2307 /* if we have no return value then
2308 just generate the "ret" */
2312 /* we have something to return then
2313 move the return value into place */
2314 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315 size = AOP_SIZE (IC_LEFT (ic));
2317 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2321 emitcode ("ld", "de,%s", l);
2325 emitcode ("ld", "hl,%s", l);
2330 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2332 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2333 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2339 l = aopGet (AOP (IC_LEFT (ic)), offset,
2341 if (strcmp (_fReturn[offset], l))
2342 emitcode ("ld", "%s,%s", _fReturn[offset++], l);
2346 freeAsmop (IC_LEFT (ic), NULL, ic);
2349 /* generate a jump to the return label
2350 if the next is not the return statement */
2351 if (!(ic->next && ic->next->op == LABEL &&
2352 IC_LABEL (ic->next) == returnLabel))
2354 emit2 ("jp !tlabel", returnLabel->key + 100);
2357 /*-----------------------------------------------------------------*/
2358 /* genLabel - generates a label */
2359 /*-----------------------------------------------------------------*/
2361 genLabel (iCode * ic)
2363 /* special case never generate */
2364 if (IC_LABEL (ic) == entryLabel)
2367 emitLabel (IC_LABEL (ic)->key + 100);
2370 /*-----------------------------------------------------------------*/
2371 /* genGoto - generates a ljmp */
2372 /*-----------------------------------------------------------------*/
2374 genGoto (iCode * ic)
2376 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2379 /*-----------------------------------------------------------------*/
2380 /* genPlusIncr :- does addition with increment if possible */
2381 /*-----------------------------------------------------------------*/
2383 genPlusIncr (iCode * ic)
2385 unsigned int icount;
2386 unsigned int size = getDataSize (IC_RESULT (ic));
2387 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2389 /* will try to generate an increment */
2390 /* if the right side is not a literal
2392 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2395 emitcode ("", "; genPlusIncr");
2397 icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2399 /* If result is a pair */
2400 if (resultId != PAIR_INVALID)
2402 if (isLitWord (AOP (IC_LEFT (ic))))
2404 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2407 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2409 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2410 emitcode ("add", "hl,%s", getPairName (AOP (IC_LEFT (ic))));
2416 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2420 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2421 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2425 emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
2430 /* if the literal value of the right hand side
2431 is greater than 4 then it is not worth it */
2435 /* if increment 16 bits in register */
2436 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2442 symbol *tlbl = NULL;
2443 tlbl = newiTempLabel (NULL);
2446 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2449 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2452 emitLabel (tlbl->key + 100);
2456 /* if the sizes are greater than 1 then we cannot */
2457 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2458 AOP_SIZE (IC_LEFT (ic)) > 1)
2461 /* we can if the aops of the left & result match or
2462 if they are in registers and the registers are the
2464 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2467 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2474 /*-----------------------------------------------------------------*/
2475 /* outBitAcc - output a bit in acc */
2476 /*-----------------------------------------------------------------*/
2478 outBitAcc (operand * result)
2480 symbol *tlbl = newiTempLabel (NULL);
2481 /* if the result is a bit */
2482 if (AOP_TYPE (result) == AOP_CRY)
2488 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2489 emit2 ("ld a,!one");
2490 emitLabel (tlbl->key + 100);
2495 /*-----------------------------------------------------------------*/
2496 /* genPlus - generates code for addition */
2497 /*-----------------------------------------------------------------*/
2499 genPlus (iCode * ic)
2501 int size, offset = 0;
2503 /* special cases :- */
2505 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2506 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2507 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2509 /* Swap the left and right operands if:
2511 if literal, literal on the right or
2512 if left requires ACC or right is already
2515 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2516 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2517 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2519 operand *t = IC_RIGHT (ic);
2520 IC_RIGHT (ic) = IC_LEFT (ic);
2524 /* if both left & right are in bit
2526 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2527 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2533 /* if left in bit space & right literal */
2534 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2535 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2537 /* Can happen I guess */
2541 /* if I can do an increment instead
2542 of add then GOOD for ME */
2543 if (genPlusIncr (ic) == TRUE)
2546 emit2 ("; genPlusIncr failed");
2548 size = getDataSize (IC_RESULT (ic));
2550 /* Special case when left and right are constant */
2551 if (isPair (AOP (IC_RESULT (ic))))
2555 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2556 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2562 sprintf (buffer, "#(%s + %s)", left, right);
2563 emitcode ("ld", "%s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2568 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2570 /* Fetch into HL then do the add */
2571 spillPair (PAIR_HL);
2572 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2573 emitcode ("add", "hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2578 ld hl,sp+n trashes C so we cant afford to do it during an
2579 add with stack based varibles. Worst case is:
2592 So you cant afford to load up hl if either left, right, or result
2593 is on the stack (*sigh*) The alt is:
2601 Combinations in here are:
2602 * If left or right are in bc then the loss is small - trap later
2603 * If the result is in bc then the loss is also small
2607 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2608 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2609 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2611 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2612 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2613 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2614 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2616 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2618 /* Swap left and right */
2619 operand *t = IC_RIGHT (ic);
2620 IC_RIGHT (ic) = IC_LEFT (ic);
2623 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2625 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2626 emit2 ("add hl,bc");
2630 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2631 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2632 emit2 ("add hl,de");
2634 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2639 emit2 ("; WARNING: This add is probably broken.\n");
2646 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2648 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2651 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2654 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2658 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2661 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2664 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2666 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2670 freeAsmop (IC_LEFT (ic), NULL, ic);
2671 freeAsmop (IC_RIGHT (ic), NULL, ic);
2672 freeAsmop (IC_RESULT (ic), NULL, ic);
2676 /*-----------------------------------------------------------------*/
2677 /* genMinusDec :- does subtraction with deccrement if possible */
2678 /*-----------------------------------------------------------------*/
2680 genMinusDec (iCode * ic)
2682 unsigned int icount;
2683 unsigned int size = getDataSize (IC_RESULT (ic));
2685 /* will try to generate an increment */
2686 /* if the right side is not a literal we cannot */
2687 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2690 /* if the literal value of the right hand side
2691 is greater than 4 then it is not worth it */
2692 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2695 size = getDataSize (IC_RESULT (ic));
2698 /* if increment 16 bits in register */
2699 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2703 symbol *tlbl = newiTempLabel (NULL);
2704 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2705 emitcode ("jp", "np," LABEL_STR, tlbl->key + 100);
2707 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2712 emitLabel (tlbl->key + 100);
2717 /* if decrement 16 bits in register */
2718 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2719 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2722 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2726 /* If result is a pair */
2727 if (isPair (AOP (IC_RESULT (ic))))
2729 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2730 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2732 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2736 /* if the sizes are greater than 1 then we cannot */
2737 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2738 AOP_SIZE (IC_LEFT (ic)) > 1)
2741 /* we can if the aops of the left & result match or if they are in
2742 registers and the registers are the same */
2743 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2746 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2753 /*-----------------------------------------------------------------*/
2754 /* genMinus - generates code for subtraction */
2755 /*-----------------------------------------------------------------*/
2757 genMinus (iCode * ic)
2759 int size, offset = 0;
2760 unsigned long lit = 0L;
2762 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2763 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2764 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2766 /* special cases :- */
2767 /* if both left & right are in bit space */
2768 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2769 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2775 /* if I can do an decrement instead of subtract then GOOD for ME */
2776 if (genMinusDec (ic) == TRUE)
2779 size = getDataSize (IC_RESULT (ic));
2781 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2786 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2790 /* Same logic as genPlus */
2793 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2794 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2795 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2797 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2798 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2799 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2800 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2802 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2803 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2805 if (left == PAIR_INVALID && right == PAIR_INVALID)
2810 else if (right == PAIR_INVALID)
2812 else if (left == PAIR_INVALID)
2815 fetchPair (left, AOP (IC_LEFT (ic)));
2816 /* Order is important. Right may be HL */
2817 fetchPair (right, AOP (IC_RIGHT (ic)));
2819 emit2 ("ld a,%s", _pairs[left].l);
2820 emit2 ("sub a,%s", _pairs[right].l);
2822 emit2 ("ld a,%s", _pairs[left].h);
2823 emit2 ("sbc a,%s", _pairs[right].h);
2825 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2826 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2831 emit2 ("; WARNING: This sub is probably broken.\n");
2836 /* if literal, add a,#-lit, else normal subb */
2839 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2840 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2843 emitcode ("sub", "a,%s",
2844 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2846 emitcode ("sbc", "a,%s",
2847 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2851 /* first add without previous c */
2853 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2855 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2857 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2860 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2861 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2862 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2866 freeAsmop (IC_LEFT (ic), NULL, ic);
2867 freeAsmop (IC_RIGHT (ic), NULL, ic);
2868 freeAsmop (IC_RESULT (ic), NULL, ic);
2871 /*-----------------------------------------------------------------*/
2872 /* genMult - generates code for multiplication */
2873 /*-----------------------------------------------------------------*/
2875 genMult (iCode * ic)
2877 /* Shouldn't occur - all done through function calls */
2881 /*-----------------------------------------------------------------*/
2882 /* genDiv - generates code for division */
2883 /*-----------------------------------------------------------------*/
2887 /* Shouldn't occur - all done through function calls */
2891 /*-----------------------------------------------------------------*/
2892 /* genMod - generates code for division */
2893 /*-----------------------------------------------------------------*/
2897 /* Shouldn't occur - all done through function calls */
2901 /*-----------------------------------------------------------------*/
2902 /* genIfxJump :- will create a jump depending on the ifx */
2903 /*-----------------------------------------------------------------*/
2905 genIfxJump (iCode * ic, char *jval)
2910 /* if true label then we jump if condition
2914 jlbl = IC_TRUE (ic);
2915 if (!strcmp (jval, "a"))
2919 else if (!strcmp (jval, "c"))
2923 else if (!strcmp (jval, "nc"))
2929 /* The buffer contains the bit on A that we should test */
2935 /* false label is present */
2936 jlbl = IC_FALSE (ic);
2937 if (!strcmp (jval, "a"))
2941 else if (!strcmp (jval, "c"))
2945 else if (!strcmp (jval, "nc"))
2951 /* The buffer contains the bit on A that we should test */
2955 /* Z80 can do a conditional long jump */
2956 if (!strcmp (jval, "a"))
2958 emitcode ("or", "a,a");
2960 else if (!strcmp (jval, "c"))
2963 else if (!strcmp (jval, "nc"))
2968 emitcode ("bit", "%s,a", jval);
2970 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
2972 /* mark the icode as generated */
2977 _getPairIdName (PAIR_ID id)
2979 return _pairs[id].name;
2982 /** Generic compare for > or <
2985 genCmp (operand * left, operand * right,
2986 operand * result, iCode * ifx, int sign)
2988 int size, offset = 0;
2989 unsigned long lit = 0L;
2990 bool swap_sense = FALSE;
2992 /* if left & right are bit variables */
2993 if (AOP_TYPE (left) == AOP_CRY &&
2994 AOP_TYPE (right) == AOP_CRY)
2996 /* Cant happen on the Z80 */
3001 /* subtract right from left if at the
3002 end the carry flag is set then we know that
3003 left is greater than right */
3004 size = max (AOP_SIZE (left), AOP_SIZE (right));
3006 /* if unsigned char cmp with lit, just compare */
3008 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3010 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3013 emit2 ("xor a,!immedbyte", 0x80);
3014 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3017 emitcode ("cp", "%s", aopGet (AOP (right), offset, FALSE));
3023 If the left or the right is a lit:
3024 Load -lit into HL, add to right via, check sense.
3026 if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3028 PAIR_ID id = PAIR_DE;
3029 asmop *lit = AOP (right);
3030 asmop *op = AOP (left);
3033 if (AOP_TYPE (left) == AOP_LIT)
3041 emit2 ("ld e,%s", aopGet (op, 0, 0));
3042 emit2 ("ld a,%s", aopGet (op, 1, 0));
3043 emit2 ("xor a,!immedbyte", 0x80);
3048 id = getPairId (op);
3049 if (id == PAIR_INVALID)
3051 fetchPair (PAIR_DE, op);
3055 spillPair (PAIR_HL);
3056 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3057 emit2 ("add hl,%s", _getPairIdName (id));
3060 if (AOP_TYPE (right) == AOP_LIT)
3062 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3063 /* optimize if(x < 0) or if(x >= 0) */
3068 /* No sign so it's always false */
3073 /* Just load in the top most bit */
3074 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3075 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3077 genIfxJump (ifx, "7");
3081 emitcode ("rlc", "a");
3088 /* First setup h and l contaning the top most bytes XORed */
3089 bool fDidXor = FALSE;
3090 if (AOP_TYPE (left) == AOP_LIT)
3092 unsigned long lit = (unsigned long)
3093 floatFromVal (AOP (left)->aopu.aop_lit);
3094 emit2 ("ld %s,!immedbyte", _fTmp[0],
3095 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3099 emitcode ("ld", "a,%s", aopGet (AOP (left), size - 1, FALSE));
3100 emit2 ("xor a,!immedbyte", 0x80);
3101 emitcode ("ld", "%s,a", _fTmp[0]);
3104 if (AOP_TYPE (right) == AOP_LIT)
3106 unsigned long lit = (unsigned long)
3107 floatFromVal (AOP (right)->aopu.aop_lit);
3108 emit2 ("ld %s,!immedbyte", _fTmp[1],
3109 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3113 emitcode ("ld", "a,%s", aopGet (AOP (right), size - 1, FALSE));
3114 emit2 ("xor a,!immedbyte", 0x80);
3115 emitcode ("ld", "%s,a", _fTmp[1]);
3127 /* Do a long subtract */
3130 MOVA (aopGet (AOP (left), offset, FALSE));
3132 if (sign && size == 0)
3134 emitcode ("ld", "a,%s", _fTmp[0]);
3135 emitcode ("sbc", "a,%s", _fTmp[1]);
3139 /* Subtract through, propagating the carry */
3140 emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3147 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3149 outBitCLong (result, swap_sense);
3153 /* if the result is used in the next
3154 ifx conditional branch then generate
3155 code a little differently */
3157 genIfxJump (ifx, swap_sense ? "nc" : "c");
3159 outBitCLong (result, swap_sense);
3160 /* leave the result in acc */
3164 /*-----------------------------------------------------------------*/
3165 /* genCmpGt :- greater than comparison */
3166 /*-----------------------------------------------------------------*/
3168 genCmpGt (iCode * ic, iCode * ifx)
3170 operand *left, *right, *result;
3171 sym_link *letype, *retype;
3174 left = IC_LEFT (ic);
3175 right = IC_RIGHT (ic);
3176 result = IC_RESULT (ic);
3178 letype = getSpec (operandType (left));
3179 retype = getSpec (operandType (right));
3180 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3181 /* assign the amsops */
3182 aopOp (left, ic, FALSE, FALSE);
3183 aopOp (right, ic, FALSE, FALSE);
3184 aopOp (result, ic, TRUE, FALSE);
3186 genCmp (right, left, result, ifx, sign);
3188 freeAsmop (left, NULL, ic);
3189 freeAsmop (right, NULL, ic);
3190 freeAsmop (result, NULL, ic);
3193 /*-----------------------------------------------------------------*/
3194 /* genCmpLt - less than comparisons */
3195 /*-----------------------------------------------------------------*/
3197 genCmpLt (iCode * ic, iCode * ifx)
3199 operand *left, *right, *result;
3200 sym_link *letype, *retype;
3203 left = IC_LEFT (ic);
3204 right = IC_RIGHT (ic);
3205 result = IC_RESULT (ic);
3207 letype = getSpec (operandType (left));
3208 retype = getSpec (operandType (right));
3209 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3211 /* assign the amsops */
3212 aopOp (left, ic, FALSE, FALSE);
3213 aopOp (right, ic, FALSE, FALSE);
3214 aopOp (result, ic, TRUE, FALSE);
3216 genCmp (left, right, result, ifx, sign);
3218 freeAsmop (left, NULL, ic);
3219 freeAsmop (right, NULL, ic);
3220 freeAsmop (result, NULL, ic);
3223 /*-----------------------------------------------------------------*/
3224 /* gencjneshort - compare and jump if not equal */
3225 /*-----------------------------------------------------------------*/
3227 gencjneshort (operand * left, operand * right, symbol * lbl)
3229 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3231 unsigned long lit = 0L;
3233 /* Swap the left and right if it makes the computation easier */
3234 if (AOP_TYPE (left) == AOP_LIT)
3241 if (AOP_TYPE (right) == AOP_LIT)
3242 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3244 /* if the right side is a literal then anything goes */
3245 if (AOP_TYPE (right) == AOP_LIT &&
3246 AOP_TYPE (left) != AOP_DIR)
3250 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3257 emitcode ("or", "a,%s", aopGet (AOP (left), offset, FALSE));
3262 emitcode ("or", "a,a");
3264 emit2 ("jp nz,!tlabel", lbl->key + 100);
3270 emitcode ("ld", "a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3271 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3272 emitcode ("or", "a,a");
3274 emitcode ("cp", "a,%s", aopGet (AOP (right), offset, FALSE));
3275 emit2 ("jp nz,!tlabel", lbl->key + 100);
3280 /* if the right side is in a register or in direct space or
3281 if the left is a pointer register & right is not */
3282 else if (AOP_TYPE (right) == AOP_REG ||
3283 AOP_TYPE (right) == AOP_DIR ||
3284 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3288 MOVA (aopGet (AOP (left), offset, FALSE));
3289 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3290 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3292 emit2 ("jp nz,!tlabel", lbl->key + 100);
3295 emitcode ("cp", "%s ; 4", aopGet (AOP (right), offset, FALSE));
3296 emit2 ("jp nz,!tlabel", lbl->key + 100);
3303 /* right is a pointer reg need both a & b */
3304 /* PENDING: is this required? */
3307 MOVA (aopGet (AOP (right), offset, FALSE));
3308 emitcode ("cp", "%s ; 5", aopGet (AOP (left), offset, FALSE));
3309 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3315 /*-----------------------------------------------------------------*/
3316 /* gencjne - compare and jump if not equal */
3317 /*-----------------------------------------------------------------*/
3319 gencjne (operand * left, operand * right, symbol * lbl)
3321 symbol *tlbl = newiTempLabel (NULL);
3323 gencjneshort (left, right, lbl);
3326 emit2 ("ld a,!one");
3327 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3328 emitLabel (lbl->key + 100);
3329 emitcode ("xor", "a,a");
3330 emitLabel (tlbl->key + 100);
3333 /*-----------------------------------------------------------------*/
3334 /* genCmpEq - generates code for equal to */
3335 /*-----------------------------------------------------------------*/
3337 genCmpEq (iCode * ic, iCode * ifx)
3339 operand *left, *right, *result;
3341 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3342 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3343 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3345 /* Swap operands if it makes the operation easier. ie if:
3346 1. Left is a literal.
3348 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3350 operand *t = IC_RIGHT (ic);
3351 IC_RIGHT (ic) = IC_LEFT (ic);
3355 if (ifx && !AOP_SIZE (result))
3358 /* if they are both bit variables */
3359 if (AOP_TYPE (left) == AOP_CRY &&
3360 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3366 tlbl = newiTempLabel (NULL);
3367 gencjneshort (left, right, tlbl);
3370 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3371 emitLabel (tlbl->key + 100);
3375 /* PENDING: do this better */
3376 symbol *lbl = newiTempLabel (NULL);
3377 emit2 ("!shortjp !tlabel", lbl->key + 100);
3378 emitLabel (tlbl->key + 100);
3379 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3380 emitLabel (lbl->key + 100);
3383 /* mark the icode as generated */
3388 /* if they are both bit variables */
3389 if (AOP_TYPE (left) == AOP_CRY &&
3390 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3396 gencjne (left, right, newiTempLabel (NULL));
3397 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3403 genIfxJump (ifx, "a");
3406 /* if the result is used in an arithmetic operation
3407 then put the result in place */
3408 if (AOP_TYPE (result) != AOP_CRY)
3412 /* leave the result in acc */
3416 freeAsmop (left, NULL, ic);
3417 freeAsmop (right, NULL, ic);
3418 freeAsmop (result, NULL, ic);
3421 /*-----------------------------------------------------------------*/
3422 /* ifxForOp - returns the icode containing the ifx for operand */
3423 /*-----------------------------------------------------------------*/
3425 ifxForOp (operand * op, iCode * ic)
3427 /* if true symbol then needs to be assigned */
3428 if (IS_TRUE_SYMOP (op))
3431 /* if this has register type condition and
3432 the next instruction is ifx with the same operand
3433 and live to of the operand is upto the ifx only then */
3435 ic->next->op == IFX &&
3436 IC_COND (ic->next)->key == op->key &&
3437 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3443 /*-----------------------------------------------------------------*/
3444 /* genAndOp - for && operation */
3445 /*-----------------------------------------------------------------*/
3447 genAndOp (iCode * ic)
3449 operand *left, *right, *result;
3452 /* note here that && operations that are in an if statement are
3453 taken away by backPatchLabels only those used in arthmetic
3454 operations remain */
3455 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3456 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3457 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3459 /* if both are bit variables */
3460 if (AOP_TYPE (left) == AOP_CRY &&
3461 AOP_TYPE (right) == AOP_CRY)
3467 tlbl = newiTempLabel (NULL);
3469 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3471 emitLabel (tlbl->key + 100);
3475 freeAsmop (left, NULL, ic);
3476 freeAsmop (right, NULL, ic);
3477 freeAsmop (result, NULL, ic);
3480 /*-----------------------------------------------------------------*/
3481 /* genOrOp - for || operation */
3482 /*-----------------------------------------------------------------*/
3484 genOrOp (iCode * ic)
3486 operand *left, *right, *result;
3489 /* note here that || operations that are in an
3490 if statement are taken away by backPatchLabels
3491 only those used in arthmetic operations remain */
3492 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3493 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3494 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3496 /* if both are bit variables */
3497 if (AOP_TYPE (left) == AOP_CRY &&
3498 AOP_TYPE (right) == AOP_CRY)
3504 tlbl = newiTempLabel (NULL);
3506 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3508 emitLabel (tlbl->key + 100);
3512 freeAsmop (left, NULL, ic);
3513 freeAsmop (right, NULL, ic);
3514 freeAsmop (result, NULL, ic);
3517 /*-----------------------------------------------------------------*/
3518 /* isLiteralBit - test if lit == 2^n */
3519 /*-----------------------------------------------------------------*/
3521 isLiteralBit (unsigned long lit)
3523 unsigned long pw[32] =
3524 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3525 0x100L, 0x200L, 0x400L, 0x800L,
3526 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3527 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3528 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3529 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3530 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3533 for (idx = 0; idx < 32; idx++)
3539 /*-----------------------------------------------------------------*/
3540 /* jmpTrueOrFalse - */
3541 /*-----------------------------------------------------------------*/
3543 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3545 // ugly but optimized by peephole
3548 symbol *nlbl = newiTempLabel (NULL);
3549 emit2 ("jp !tlabel", nlbl->key + 100);
3550 emitLabel (tlbl->key + 100);
3551 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3552 emitLabel (nlbl->key + 100);
3556 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3557 emitLabel (tlbl->key + 100);
3562 /*-----------------------------------------------------------------*/
3563 /* genAnd - code for and */
3564 /*-----------------------------------------------------------------*/
3566 genAnd (iCode * ic, iCode * ifx)
3568 operand *left, *right, *result;
3569 int size, offset = 0;
3570 unsigned long lit = 0L;
3573 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3574 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3575 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3578 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3580 AOP_TYPE (left), AOP_TYPE (right));
3581 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3583 AOP_SIZE (left), AOP_SIZE (right));
3586 /* if left is a literal & right is not then exchange them */
3587 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3588 AOP_NEEDSACC (left))
3590 operand *tmp = right;
3595 /* if result = right then exchange them */
3596 if (sameRegs (AOP (result), AOP (right)))
3598 operand *tmp = right;
3603 /* if right is bit then exchange them */
3604 if (AOP_TYPE (right) == AOP_CRY &&
3605 AOP_TYPE (left) != AOP_CRY)
3607 operand *tmp = right;
3611 if (AOP_TYPE (right) == AOP_LIT)
3612 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3614 size = AOP_SIZE (result);
3616 if (AOP_TYPE (left) == AOP_CRY)
3622 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3623 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3624 if ((AOP_TYPE (right) == AOP_LIT) &&
3625 (AOP_TYPE (result) == AOP_CRY) &&
3626 (AOP_TYPE (left) != AOP_CRY))
3628 int posbit = isLiteralBit (lit);
3633 MOVA (aopGet (AOP (left), posbit >> 3, FALSE));
3638 emitcode ("mov", "c,acc.%d", posbit & 0x07);
3645 sprintf (buffer, "%d", posbit & 0x07);
3646 genIfxJump (ifx, buffer);
3657 symbol *tlbl = newiTempLabel (NULL);
3658 int sizel = AOP_SIZE (left);
3662 emitcode ("setb", "c");
3666 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3668 MOVA (aopGet (AOP (left), offset, FALSE));
3670 if ((posbit = isLiteralBit (bytelit)) != 0)
3673 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3677 if (bytelit != 0x0FFL)
3678 emitcode ("and", "a,%s",
3679 aopGet (AOP (right), offset, FALSE));
3683 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3688 // bit = left & literal
3691 emitcode ("clr", "c");
3692 emit2 ("!tlabeldef", tlbl->key + 100);
3694 // if(left & literal)
3698 jmpTrueOrFalse (ifx, tlbl);
3706 /* if left is same as result */
3707 if (sameRegs (AOP (result), AOP (left)))
3709 for (; size--; offset++)
3711 if (AOP_TYPE (right) == AOP_LIT)
3713 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3718 aopPut (AOP (result), zero, offset);
3721 MOVA (aopGet (AOP (left), offset, FALSE));
3722 emitcode ("and", "a,%s",
3723 aopGet (AOP (right), offset, FALSE));
3724 aopPut (AOP (left), "a", offset);
3731 if (AOP_TYPE (left) == AOP_ACC)
3737 MOVA (aopGet (AOP (left), offset, FALSE));
3738 emitcode ("and", "a,%s",
3739 aopGet (AOP (right), offset, FALSE));
3740 aopPut (AOP (left), "a", offset);
3747 // left & result in different registers
3748 if (AOP_TYPE (result) == AOP_CRY)
3754 for (; (size--); offset++)
3757 // result = left & right
3758 if (AOP_TYPE (right) == AOP_LIT)
3760 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3762 aopPut (AOP (result),
3763 aopGet (AOP (left), offset, FALSE),
3767 else if (bytelit == 0)
3769 aopPut (AOP (result), zero, offset);
3773 // faster than result <- left, anl result,right
3774 // and better if result is SFR
3775 if (AOP_TYPE (left) == AOP_ACC)
3776 emitcode ("and", "a,%s", aopGet (AOP (right), offset, FALSE));
3779 MOVA (aopGet (AOP (left), offset, FALSE));
3780 emitcode ("and", "a,%s",
3781 aopGet (AOP (right), offset, FALSE));
3783 aopPut (AOP (result), "a", offset);
3790 freeAsmop (left, NULL, ic);
3791 freeAsmop (right, NULL, ic);
3792 freeAsmop (result, NULL, ic);
3795 /*-----------------------------------------------------------------*/
3796 /* genOr - code for or */
3797 /*-----------------------------------------------------------------*/
3799 genOr (iCode * ic, iCode * ifx)
3801 operand *left, *right, *result;
3802 int size, offset = 0;
3803 unsigned long lit = 0L;
3805 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3806 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3807 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3810 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3812 AOP_TYPE (left), AOP_TYPE (right));
3813 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3815 AOP_SIZE (left), AOP_SIZE (right));
3818 /* if left is a literal & right is not then exchange them */
3819 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3820 AOP_NEEDSACC (left))
3822 operand *tmp = right;
3827 /* if result = right then exchange them */
3828 if (sameRegs (AOP (result), AOP (right)))
3830 operand *tmp = right;
3835 /* if right is bit then exchange them */
3836 if (AOP_TYPE (right) == AOP_CRY &&
3837 AOP_TYPE (left) != AOP_CRY)
3839 operand *tmp = right;
3843 if (AOP_TYPE (right) == AOP_LIT)
3844 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3846 size = AOP_SIZE (result);
3848 if (AOP_TYPE (left) == AOP_CRY)
3854 if ((AOP_TYPE (right) == AOP_LIT) &&
3855 (AOP_TYPE (result) == AOP_CRY) &&
3856 (AOP_TYPE (left) != AOP_CRY))
3862 /* if left is same as result */
3863 if (sameRegs (AOP (result), AOP (left)))
3865 for (; size--; offset++)
3867 if (AOP_TYPE (right) == AOP_LIT)
3869 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3873 MOVA (aopGet (AOP (left), offset, FALSE));
3874 emitcode ("or", "a,%s",
3875 aopGet (AOP (right), offset, FALSE));
3876 aopPut (AOP (result), "a", offset);
3881 if (AOP_TYPE (left) == AOP_ACC)
3882 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3885 MOVA (aopGet (AOP (left), offset, FALSE));
3886 emitcode ("or", "a,%s",
3887 aopGet (AOP (right), offset, FALSE));
3888 aopPut (AOP (result), "a", offset);
3895 // left & result in different registers
3896 if (AOP_TYPE (result) == AOP_CRY)
3901 for (; (size--); offset++)
3904 // result = left & right
3905 if (AOP_TYPE (right) == AOP_LIT)
3907 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3909 aopPut (AOP (result),
3910 aopGet (AOP (left), offset, FALSE),
3915 // faster than result <- left, anl result,right
3916 // and better if result is SFR
3917 if (AOP_TYPE (left) == AOP_ACC)
3918 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3921 MOVA (aopGet (AOP (left), offset, FALSE));
3922 emitcode ("or", "a,%s",
3923 aopGet (AOP (right), offset, FALSE));
3925 aopPut (AOP (result), "a", offset);
3926 /* PENDING: something weird is going on here. Add exception. */
3927 if (AOP_TYPE (result) == AOP_ACC)
3933 freeAsmop (left, NULL, ic);
3934 freeAsmop (right, NULL, ic);
3935 freeAsmop (result, NULL, ic);
3938 /*-----------------------------------------------------------------*/
3939 /* genXor - code for xclusive or */
3940 /*-----------------------------------------------------------------*/
3942 genXor (iCode * ic, iCode * ifx)
3944 operand *left, *right, *result;
3945 int size, offset = 0;
3946 unsigned long lit = 0L;
3948 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3949 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3950 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3952 /* if left is a literal & right is not then exchange them */
3953 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3954 AOP_NEEDSACC (left))
3956 operand *tmp = right;
3961 /* if result = right then exchange them */
3962 if (sameRegs (AOP (result), AOP (right)))
3964 operand *tmp = right;
3969 /* if right is bit then exchange them */
3970 if (AOP_TYPE (right) == AOP_CRY &&
3971 AOP_TYPE (left) != AOP_CRY)
3973 operand *tmp = right;
3977 if (AOP_TYPE (right) == AOP_LIT)
3978 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3980 size = AOP_SIZE (result);
3982 if (AOP_TYPE (left) == AOP_CRY)
3988 if ((AOP_TYPE (right) == AOP_LIT) &&
3989 (AOP_TYPE (result) == AOP_CRY) &&
3990 (AOP_TYPE (left) != AOP_CRY))
3996 /* if left is same as result */
3997 if (sameRegs (AOP (result), AOP (left)))
3999 for (; size--; offset++)
4001 if (AOP_TYPE (right) == AOP_LIT)
4003 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4007 MOVA (aopGet (AOP (right), offset, FALSE));
4008 emitcode ("xor", "a,%s",
4009 aopGet (AOP (left), offset, FALSE));
4010 aopPut (AOP (result), "a", 0);
4015 if (AOP_TYPE (left) == AOP_ACC)
4016 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4019 MOVA (aopGet (AOP (right), offset, FALSE));
4020 emitcode ("xor", "a,%s",
4021 aopGet (AOP (left), offset, FALSE));
4022 aopPut (AOP (result), "a", 0);
4029 // left & result in different registers
4030 if (AOP_TYPE (result) == AOP_CRY)
4035 for (; (size--); offset++)
4038 // result = left & right
4039 if (AOP_TYPE (right) == AOP_LIT)
4041 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4043 aopPut (AOP (result),
4044 aopGet (AOP (left), offset, FALSE),
4049 // faster than result <- left, anl result,right
4050 // and better if result is SFR
4051 if (AOP_TYPE (left) == AOP_ACC)
4052 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4055 MOVA (aopGet (AOP (right), offset, FALSE));
4056 emitcode ("xor", "a,%s",
4057 aopGet (AOP (left), offset, FALSE));
4058 aopPut (AOP (result), "a", 0);
4060 aopPut (AOP (result), "a", offset);
4065 freeAsmop (left, NULL, ic);
4066 freeAsmop (right, NULL, ic);
4067 freeAsmop (result, NULL, ic);
4070 /*-----------------------------------------------------------------*/
4071 /* genInline - write the inline code out */
4072 /*-----------------------------------------------------------------*/
4074 genInline (iCode * ic)
4076 char buffer[MAX_INLINEASM];
4080 inLine += (!options.asmpeep);
4081 strcpy (buffer, IC_INLINE (ic));
4083 /* emit each line as a code */
4108 /* emitcode("",buffer); */
4109 inLine -= (!options.asmpeep);
4112 /*-----------------------------------------------------------------*/
4113 /* genRRC - rotate right with carry */
4114 /*-----------------------------------------------------------------*/
4121 /*-----------------------------------------------------------------*/
4122 /* genRLC - generate code for rotate left with carry */
4123 /*-----------------------------------------------------------------*/
4130 /*-----------------------------------------------------------------*/
4131 /* shiftR2Left2Result - shift right two bytes from left to result */
4132 /*-----------------------------------------------------------------*/
4134 shiftR2Left2Result (operand * left, int offl,
4135 operand * result, int offr,
4136 int shCount, int sign)
4138 movLeft2Result (left, offl, result, offr, 0);
4139 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4147 /* if (AOP(result)->type == AOP_REG) { */
4150 symbol *tlbl, *tlbl1;
4153 tlbl = newiTempLabel (NULL);
4154 tlbl1 = newiTempLabel (NULL);
4156 /* Left is already in result - so now do the shift */
4159 emit2 ("ld a,!immedbyte+1", shCount);
4160 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4161 emitLabel (tlbl->key + 100);
4164 emitcode ("or", "a,a");
4168 l = aopGet (AOP (result), --offset, FALSE);
4169 emitcode ("rr", "%s", l);
4173 emitLabel (tlbl1->key + 100);
4174 emitcode ("dec", "a");
4175 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4180 /*-----------------------------------------------------------------*/
4181 /* shiftL2Left2Result - shift left two bytes from left to result */
4182 /*-----------------------------------------------------------------*/
4184 shiftL2Left2Result (operand * left, int offl,
4185 operand * result, int offr, int shCount)
4187 if (sameRegs (AOP (result), AOP (left)) &&
4188 ((offl + MSB16) == offr))
4194 /* Copy left into result */
4195 movLeft2Result (left, offl, result, offr, 0);
4196 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4198 /* PENDING: for now just see if it'll work. */
4199 /*if (AOP(result)->type == AOP_REG) { */
4203 symbol *tlbl, *tlbl1;
4206 tlbl = newiTempLabel (NULL);
4207 tlbl1 = newiTempLabel (NULL);
4209 /* Left is already in result - so now do the shift */
4212 emit2 ("ld a,!immedbyte+1", shCount);
4213 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4214 emitLabel (tlbl->key + 100);
4217 emitcode ("or", "a,a");
4220 l = aopGet (AOP (result), offset++, FALSE);
4221 emitcode ("rl", "%s", l);
4225 emitLabel (tlbl1->key + 100);
4226 emitcode ("dec", "a");
4227 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4232 /*-----------------------------------------------------------------*/
4233 /* AccRol - rotate left accumulator by known count */
4234 /*-----------------------------------------------------------------*/
4236 AccRol (int shCount)
4238 shCount &= 0x0007; // shCount : 0..7
4245 emitcode ("rl", "a");
4248 emitcode ("rl", "a");
4249 emitcode ("rl", "a");
4252 emitcode ("rl", "a");
4253 emitcode ("rl", "a");
4254 emitcode ("rl", "a");
4257 emitcode ("rl", "a");
4258 emitcode ("rl", "a");
4259 emitcode ("rl", "a");
4260 emitcode ("rl", "a");
4263 emitcode ("rr", "a");
4264 emitcode ("rr", "a");
4265 emitcode ("rr", "a");
4268 emitcode ("rr", "a");
4269 emitcode ("rr", "a");
4272 emitcode ("rr", "a");
4277 /*-----------------------------------------------------------------*/
4278 /* AccLsh - left shift accumulator by known count */
4279 /*-----------------------------------------------------------------*/
4281 AccLsh (int shCount)
4287 emitcode ("add", "a,a");
4289 else if (shCount == 2)
4291 emitcode ("add", "a,a");
4292 emitcode ("add", "a,a");
4296 /* rotate left accumulator */
4298 /* and kill the lower order bits */
4299 emit2 ("and a,!immedbyte", SLMask[shCount]);
4304 /*-----------------------------------------------------------------*/
4305 /* shiftL1Left2Result - shift left one byte from left to result */
4306 /*-----------------------------------------------------------------*/
4308 shiftL1Left2Result (operand * left, int offl,
4309 operand * result, int offr, int shCount)
4312 l = aopGet (AOP (left), offl, FALSE);
4314 /* shift left accumulator */
4316 aopPut (AOP (result), "a", offr);
4320 /*-----------------------------------------------------------------*/
4321 /* genlshTwo - left shift two bytes by known amount != 0 */
4322 /*-----------------------------------------------------------------*/
4324 genlshTwo (operand * result, operand * left, int shCount)
4326 int size = AOP_SIZE (result);
4328 wassert (size == 2);
4330 /* if shCount >= 8 */
4338 movLeft2Result (left, LSB, result, MSB16, 0);
4339 aopPut (AOP (result), zero, 0);
4340 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4344 movLeft2Result (left, LSB, result, MSB16, 0);
4345 aopPut (AOP (result), zero, 0);
4350 aopPut (AOP (result), zero, LSB);
4353 /* 1 <= shCount <= 7 */
4362 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4367 /*-----------------------------------------------------------------*/
4368 /* genlshOne - left shift a one byte quantity by known count */
4369 /*-----------------------------------------------------------------*/
4371 genlshOne (operand * result, operand * left, int shCount)
4373 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4376 /*-----------------------------------------------------------------*/
4377 /* genLeftShiftLiteral - left shifting by known count */
4378 /*-----------------------------------------------------------------*/
4380 genLeftShiftLiteral (operand * left,
4385 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4388 freeAsmop (right, NULL, ic);
4390 aopOp (left, ic, FALSE, FALSE);
4391 aopOp (result, ic, FALSE, FALSE);
4393 size = getSize (operandType (result));
4396 emitcode ("; shift left ", "result %d, left %d", size,
4400 /* I suppose that the left size >= result size */
4406 else if (shCount >= (size * 8))
4408 aopPut (AOP (result), zero, size);
4414 genlshOne (result, left, shCount);
4417 genlshTwo (result, left, shCount);
4426 freeAsmop (left, NULL, ic);
4427 freeAsmop (result, NULL, ic);
4430 /*-----------------------------------------------------------------*/
4431 /* genLeftShift - generates code for left shifting */
4432 /*-----------------------------------------------------------------*/
4434 genLeftShift (iCode * ic)
4438 symbol *tlbl, *tlbl1;
4439 operand *left, *right, *result;
4441 right = IC_RIGHT (ic);
4442 left = IC_LEFT (ic);
4443 result = IC_RESULT (ic);
4445 aopOp (right, ic, FALSE, FALSE);
4447 /* if the shift count is known then do it
4448 as efficiently as possible */
4449 if (AOP_TYPE (right) == AOP_LIT)
4451 genLeftShiftLiteral (left, right, result, ic);
4455 /* shift count is unknown then we have to form a loop get the loop
4456 count in B : Note: we take only the lower order byte since
4457 shifting more that 32 bits make no sense anyway, ( the largest
4458 size of an object can be only 32 bits ) */
4459 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4460 emitcode ("inc", "a");
4461 freeAsmop (right, NULL, ic);
4462 aopOp (left, ic, FALSE, FALSE);
4463 aopOp (result, ic, FALSE, FALSE);
4465 /* now move the left to the result if they are not the
4468 if (!sameRegs (AOP (left), AOP (result)))
4471 size = AOP_SIZE (result);
4475 l = aopGet (AOP (left), offset, FALSE);
4476 aopPut (AOP (result), l, offset);
4481 size = AOP_SIZE (result);
4485 l = aopGet (AOP (left), offset, FALSE);
4486 aopPut (AOP (result), l, offset);
4492 tlbl = newiTempLabel (NULL);
4493 size = AOP_SIZE (result);
4495 tlbl1 = newiTempLabel (NULL);
4497 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4498 emitLabel (tlbl->key + 100);
4499 l = aopGet (AOP (result), offset, FALSE);
4500 emitcode ("or", "a,a");
4503 l = aopGet (AOP (result), offset++, FALSE);
4504 emitcode ("rl", "%s", l);
4506 emitLabel (tlbl1->key + 100);
4507 emitcode ("dec", "a");
4508 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4510 freeAsmop (left, NULL, ic);
4511 freeAsmop (result, NULL, ic);
4514 /*-----------------------------------------------------------------*/
4515 /* genrshOne - left shift two bytes by known amount != 0 */
4516 /*-----------------------------------------------------------------*/
4518 genrshOne (operand * result, operand * left, int shCount)
4521 int size = AOP_SIZE (result);
4524 wassert (size == 1);
4525 wassert (shCount < 8);
4527 l = aopGet (AOP (left), 0, FALSE);
4528 if (AOP (result)->type == AOP_REG)
4530 aopPut (AOP (result), l, 0);
4531 l = aopGet (AOP (result), 0, FALSE);
4533 emitcode ("srl", "%s", l);
4540 emitcode ("srl", "a");
4542 aopPut (AOP (result), "a", 0);
4546 /*-----------------------------------------------------------------*/
4547 /* AccRsh - right shift accumulator by known count */
4548 /*-----------------------------------------------------------------*/
4550 AccRsh (int shCount)
4554 /* rotate right accumulator */
4555 AccRol (8 - shCount);
4556 /* and kill the higher order bits */
4557 emit2 ("and a,!immedbyte", SRMask[shCount]);
4561 /*-----------------------------------------------------------------*/
4562 /* shiftR1Left2Result - shift right one byte from left to result */
4563 /*-----------------------------------------------------------------*/
4565 shiftR1Left2Result (operand * left, int offl,
4566 operand * result, int offr,
4567 int shCount, int sign)
4569 MOVA (aopGet (AOP (left), offl, FALSE));
4578 aopPut (AOP (result), "a", offr);
4581 /*-----------------------------------------------------------------*/
4582 /* genrshTwo - right shift two bytes by known amount != 0 */
4583 /*-----------------------------------------------------------------*/
4585 genrshTwo (operand * result, operand * left,
4586 int shCount, int sign)
4588 /* if shCount >= 8 */
4594 shiftR1Left2Result (left, MSB16, result, LSB,
4599 movLeft2Result (left, MSB16, result, LSB, sign);
4601 aopPut (AOP (result), zero, 1);
4603 /* 1 <= shCount <= 7 */
4606 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4610 /*-----------------------------------------------------------------*/
4611 /* genRightShiftLiteral - left shifting by known count */
4612 /*-----------------------------------------------------------------*/
4614 genRightShiftLiteral (operand * left,
4619 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4622 freeAsmop (right, NULL, ic);
4624 aopOp (left, ic, FALSE, FALSE);
4625 aopOp (result, ic, FALSE, FALSE);
4627 size = getSize (operandType (result));
4629 emitcode ("; shift right ", "result %d, left %d", size,
4632 /* I suppose that the left size >= result size */
4638 else if (shCount >= (size * 8))
4640 aopPut (AOP (result), zero, size);
4646 genrshOne (result, left, shCount);
4649 /* PENDING: sign support */
4650 genrshTwo (result, left, shCount, FALSE);
4659 freeAsmop (left, NULL, ic);
4660 freeAsmop (result, NULL, ic);
4663 /*-----------------------------------------------------------------*/
4664 /* genRightShift - generate code for right shifting */
4665 /*-----------------------------------------------------------------*/
4667 genRightShift (iCode * ic)
4669 operand *right, *left, *result;
4671 int size, offset, first = 1;
4675 symbol *tlbl, *tlbl1;
4677 /* if signed then we do it the hard way preserve the
4678 sign bit moving it inwards */
4679 retype = getSpec (operandType (IC_RESULT (ic)));
4681 is_signed = !SPEC_USIGN (retype);
4683 /* signed & unsigned types are treated the same : i.e. the
4684 signed is NOT propagated inwards : quoting from the
4685 ANSI - standard : "for E1 >> E2, is equivalent to division
4686 by 2**E2 if unsigned or if it has a non-negative value,
4687 otherwise the result is implementation defined ", MY definition
4688 is that the sign does not get propagated */
4690 right = IC_RIGHT (ic);
4691 left = IC_LEFT (ic);
4692 result = IC_RESULT (ic);
4694 aopOp (right, ic, FALSE, FALSE);
4696 /* if the shift count is known then do it
4697 as efficiently as possible */
4698 if (AOP_TYPE (right) == AOP_LIT)
4700 genRightShiftLiteral (left, right, result, ic);
4704 aopOp (left, ic, FALSE, FALSE);
4705 aopOp (result, ic, FALSE, FALSE);
4707 /* now move the left to the result if they are not the
4709 if (!sameRegs (AOP (left), AOP (result)) &&
4710 AOP_SIZE (result) > 1)
4713 size = AOP_SIZE (result);
4717 l = aopGet (AOP (left), offset, FALSE);
4718 aopPut (AOP (result), l, offset);
4723 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4724 emitcode ("inc", "a");
4725 freeAsmop (right, NULL, ic);
4727 tlbl = newiTempLabel (NULL);
4728 tlbl1 = newiTempLabel (NULL);
4729 size = AOP_SIZE (result);
4732 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4733 emitLabel (tlbl->key + 100);
4736 l = aopGet (AOP (result), offset--, FALSE);
4740 emitcode ("sra", "%s", l);
4742 emitcode ("srl", "%s", l);
4746 emitcode ("rr", "%s", l);
4748 emitLabel (tlbl1->key + 100);
4749 emitcode ("dec", "a");
4750 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4752 freeAsmop (left, NULL, ic);
4753 freeAsmop (result, NULL, ic);
4756 /*-----------------------------------------------------------------*/
4757 /* genGenPointerGet - get value from generic pointer space */
4758 /*-----------------------------------------------------------------*/
4760 genGenPointerGet (operand * left,
4761 operand * result, iCode * ic)
4764 sym_link *retype = getSpec (operandType (result));
4770 aopOp (left, ic, FALSE, FALSE);
4771 aopOp (result, ic, FALSE, FALSE);
4773 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4776 if (isPtrPair (AOP (left)))
4778 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4779 aopPut (AOP (result), buffer, 0);
4783 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4784 aopPut (AOP (result), "a", 0);
4786 freeAsmop (left, NULL, ic);
4790 /* For now we always load into IY */
4791 /* if this is remateriazable */
4792 fetchPair (pair, AOP (left));
4794 /* so iy now contains the address */
4795 freeAsmop (left, NULL, ic);
4797 /* if bit then unpack */
4798 if (IS_BITVAR (retype))
4804 size = AOP_SIZE (result);
4809 /* PENDING: make this better */
4810 if (!IS_GB && AOP (result)->type == AOP_REG)
4812 aopPut (AOP (result), "!*hl", offset++);
4816 emit2 ("ld a,!*pair", _pairs[pair].name);
4817 aopPut (AOP (result), "a", offset++);
4821 emit2 ("inc %s", _pairs[pair].name);
4822 _G.pairs[pair].offset++;
4828 freeAsmop (result, NULL, ic);
4831 /*-----------------------------------------------------------------*/
4832 /* genPointerGet - generate code for pointer get */
4833 /*-----------------------------------------------------------------*/
4835 genPointerGet (iCode * ic)
4837 operand *left, *result;
4838 sym_link *type, *etype;
4840 left = IC_LEFT (ic);
4841 result = IC_RESULT (ic);
4843 /* depending on the type of pointer we need to
4844 move it to the correct pointer register */
4845 type = operandType (left);
4846 etype = getSpec (type);
4848 genGenPointerGet (left, result, ic);
4852 isRegOrLit (asmop * aop)
4854 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4859 /*-----------------------------------------------------------------*/
4860 /* genGenPointerSet - stores the value into a pointer location */
4861 /*-----------------------------------------------------------------*/
4863 genGenPointerSet (operand * right,
4864 operand * result, iCode * ic)
4867 sym_link *retype = getSpec (operandType (right));
4868 PAIR_ID pairId = PAIR_HL;
4870 aopOp (result, ic, FALSE, FALSE);
4871 aopOp (right, ic, FALSE, FALSE);
4876 /* Handle the exceptions first */
4877 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
4880 char *l = aopGet (AOP (right), 0, FALSE);
4881 const char *pair = getPairName (AOP (result));
4882 if (canAssignToPtr (l) && isPtr (pair))
4884 emit2 ("ld !*pair,%s", pair, l);
4889 emit2 ("ld !*pair,a", pair);
4894 /* if the operand is already in dptr
4895 then we do nothing else we move the value to dptr */
4896 if (AOP_TYPE (result) != AOP_STR)
4898 fetchPair (pairId, AOP (result));
4900 /* so hl know contains the address */
4901 freeAsmop (result, NULL, ic);
4903 /* if bit then unpack */
4904 if (IS_BITVAR (retype))
4910 size = AOP_SIZE (right);
4915 char *l = aopGet (AOP (right), offset, FALSE);
4916 if (isRegOrLit (AOP (right)) && !IS_GB)
4918 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
4923 emit2 ("ld !*pair,a", _pairs[pairId].name);
4927 emitcode ("inc", _pairs[pairId].name);
4928 _G.pairs[pairId].offset++;
4934 freeAsmop (right, NULL, ic);
4937 /*-----------------------------------------------------------------*/
4938 /* genPointerSet - stores the value into a pointer location */
4939 /*-----------------------------------------------------------------*/
4941 genPointerSet (iCode * ic)
4943 operand *right, *result;
4944 sym_link *type, *etype;
4946 right = IC_RIGHT (ic);
4947 result = IC_RESULT (ic);
4949 /* depending on the type of pointer we need to
4950 move it to the correct pointer register */
4951 type = operandType (result);
4952 etype = getSpec (type);
4954 genGenPointerSet (right, result, ic);
4957 /*-----------------------------------------------------------------*/
4958 /* genIfx - generate code for Ifx statement */
4959 /*-----------------------------------------------------------------*/
4961 genIfx (iCode * ic, iCode * popIc)
4963 operand *cond = IC_COND (ic);
4966 aopOp (cond, ic, FALSE, TRUE);
4968 /* get the value into acc */
4969 if (AOP_TYPE (cond) != AOP_CRY)
4973 /* the result is now in the accumulator */
4974 freeAsmop (cond, NULL, ic);
4976 /* if there was something to be popped then do it */
4980 /* if the condition is a bit variable */
4981 if (isbit && IS_ITEMP (cond) &&
4983 genIfxJump (ic, SPIL_LOC (cond)->rname);
4984 else if (isbit && !IS_ITEMP (cond))
4985 genIfxJump (ic, OP_SYMBOL (cond)->rname);
4987 genIfxJump (ic, "a");
4992 /*-----------------------------------------------------------------*/
4993 /* genAddrOf - generates code for address of */
4994 /*-----------------------------------------------------------------*/
4996 genAddrOf (iCode * ic)
4998 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5000 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5002 /* if the operand is on the stack then we
5003 need to get the stack offset of this
5010 if (sym->stack <= 0)
5012 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5016 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5018 emitcode ("ld", "d,h");
5019 emitcode ("ld", "e,l");
5023 emit2 ("ld de,!hashedstr", sym->rname);
5025 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5026 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5033 /* if it has an offset then we need to compute it */
5035 emitcode ("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5037 emitcode ("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5038 emitcode ("add", "hl,sp");
5042 emitcode ("ld", "hl,#%s", sym->rname);
5044 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5045 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5047 freeAsmop (IC_RESULT (ic), NULL, ic);
5050 /*-----------------------------------------------------------------*/
5051 /* genAssign - generate code for assignment */
5052 /*-----------------------------------------------------------------*/
5054 genAssign (iCode * ic)
5056 operand *result, *right;
5058 unsigned long lit = 0L;
5060 result = IC_RESULT (ic);
5061 right = IC_RIGHT (ic);
5064 /* Dont bother assigning if they are the same */
5065 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5067 emitcode ("", "; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5072 aopOp (right, ic, FALSE, FALSE);
5073 aopOp (result, ic, TRUE, FALSE);
5075 /* if they are the same registers */
5076 if (sameRegs (AOP (right), AOP (result)))
5078 emitcode ("", "; (registers are the same)");
5082 /* if the result is a bit */
5083 if (AOP_TYPE (result) == AOP_CRY)
5089 size = AOP_SIZE (result);
5092 if (AOP_TYPE (right) == AOP_LIT)
5093 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5094 if (isPair (AOP (result)))
5096 fetchPair (getPairId (AOP (result)), AOP (right));
5098 else if ((size > 1) &&
5099 (AOP_TYPE (result) != AOP_REG) &&
5100 (AOP_TYPE (right) == AOP_LIT) &&
5101 !IS_FLOAT (operandType (right)) &&
5104 bool fXored = FALSE;
5106 /* Work from the top down.
5107 Done this way so that we can use the cached copy of 0
5108 in A for a fast clear */
5111 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5113 if (!fXored && size > 1)
5115 emitcode ("xor", "a,a");
5120 aopPut (AOP (result), "a", offset);
5124 aopPut (AOP (result), zero, offset);
5128 aopPut (AOP (result),
5129 aopGet (AOP (right), offset, FALSE),
5134 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5136 /* Special case. Load into a and d, then load out. */
5137 MOVA (aopGet (AOP (right), 0, FALSE));
5138 emitcode ("ld", "e,%s", aopGet (AOP (right), 1, FALSE));
5139 aopPut (AOP (result), "a", 0);
5140 aopPut (AOP (result), "e", 1);
5146 /* PENDING: do this check better */
5147 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5149 MOVA (aopGet (AOP (right), offset, FALSE));
5150 aopPut (AOP (result), "a", offset);
5153 aopPut (AOP (result),
5154 aopGet (AOP (right), offset, FALSE),
5161 freeAsmop (right, NULL, ic);
5162 freeAsmop (result, NULL, ic);
5165 /*-----------------------------------------------------------------*/
5166 /* genJumpTab - genrates code for jump table */
5167 /*-----------------------------------------------------------------*/
5169 genJumpTab (iCode * ic)
5174 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5175 /* get the condition into accumulator */
5176 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5178 emitcode ("push", "de");
5179 emitcode ("ld", "e,%s", l);
5180 emit2 ("ld d,!zero");
5181 jtab = newiTempLabel (NULL);
5183 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5184 emitcode ("add", "hl,de");
5185 emitcode ("add", "hl,de");
5186 emitcode ("add", "hl,de");
5187 freeAsmop (IC_JTCOND (ic), NULL, ic);
5189 emitcode ("pop", "de");
5191 emitLabel (jtab->key + 100);
5192 /* now generate the jump labels */
5193 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5194 jtab = setNextItem (IC_JTLABELS (ic)))
5195 emit2 ("jp !tlabel", jtab->key + 100);
5198 /*-----------------------------------------------------------------*/
5199 /* genCast - gen code for casting */
5200 /*-----------------------------------------------------------------*/
5202 genCast (iCode * ic)
5204 operand *result = IC_RESULT (ic);
5205 sym_link *ctype = operandType (IC_LEFT (ic));
5206 operand *right = IC_RIGHT (ic);
5209 /* if they are equivalent then do nothing */
5210 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5213 aopOp (right, ic, FALSE, FALSE);
5214 aopOp (result, ic, FALSE, FALSE);
5216 /* if the result is a bit */
5217 if (AOP_TYPE (result) == AOP_CRY)
5222 /* if they are the same size : or less */
5223 if (AOP_SIZE (result) <= AOP_SIZE (right))
5226 /* if they are in the same place */
5227 if (sameRegs (AOP (right), AOP (result)))
5230 /* if they in different places then copy */
5231 size = AOP_SIZE (result);
5235 aopPut (AOP (result),
5236 aopGet (AOP (right), offset, FALSE),
5243 /* PENDING: should be OK. */
5245 /* if the result is of type pointer */
5252 /* so we now know that the size of destination is greater
5253 than the size of the source */
5254 /* we move to result for the size of source */
5255 size = AOP_SIZE (right);
5259 aopPut (AOP (result),
5260 aopGet (AOP (right), offset, FALSE),
5265 /* now depending on the sign of the destination */
5266 size = AOP_SIZE (result) - AOP_SIZE (right);
5267 /* Unsigned or not an integral type - right fill with zeros */
5268 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5271 aopPut (AOP (result), zero, offset++);
5275 /* we need to extend the sign :{ */
5276 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5279 emitcode ("", "; genCast: sign extend untested.");
5280 emitcode ("rla", "");
5281 emitcode ("sbc", "a,a");
5283 aopPut (AOP (result), "a", offset++);
5287 freeAsmop (right, NULL, ic);
5288 freeAsmop (result, NULL, ic);
5291 /*-----------------------------------------------------------------*/
5292 /* genReceive - generate code for a receive iCode */
5293 /*-----------------------------------------------------------------*/
5295 genReceive (iCode * ic)
5297 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5298 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5299 IS_TRUE_SYMOP (IC_RESULT (ic))))
5306 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5308 assignResultValue (IC_RESULT (ic));
5311 freeAsmop (IC_RESULT (ic), NULL, ic);
5314 /*-----------------------------------------------------------------*/
5315 /* genZ80Code - generate code for Z80 based controllers */
5316 /*-----------------------------------------------------------------*/
5318 genZ80Code (iCode * lic)
5326 _fReturn = _gbz80_return;
5327 _fTmp = _gbz80_return;
5331 _fReturn = _z80_return;
5332 _fTmp = _z80_return;
5334 tsprintf (zero, "!zero");
5336 lineHead = lineCurr = NULL;
5338 /* if debug information required */
5339 if (options.debug && currFunc)
5341 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5343 if (IS_STATIC (currFunc->etype))
5344 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
5346 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
5349 /* stack pointer name */
5353 for (ic = lic; ic; ic = ic->next)
5356 if (cln != ic->lineno)
5361 emitcode ("", "C$%s$%d$%d$%d ==.",
5362 FileBaseName (ic->filename), ic->lineno,
5363 ic->level, ic->block);
5366 emitcode (";", "%s %d", ic->filename, ic->lineno);
5369 /* if the result is marked as
5370 spilt and rematerializable or code for
5371 this has already been generated then
5373 if (resultRemat (ic) || ic->generated)
5376 /* depending on the operation */
5380 emitcode ("", "; genNot");
5385 emitcode ("", "; genCpl");
5390 emitcode ("", "; genUminus");
5395 emitcode ("", "; genIpush");
5400 /* IPOP happens only when trying to restore a
5401 spilt live range, if there is an ifx statement
5402 following this pop then the if statement might
5403 be using some of the registers being popped which
5404 would destory the contents of the register so
5405 we need to check for this condition and handle it */
5407 ic->next->op == IFX &&
5408 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5410 emitcode ("", "; genIfx");
5411 genIfx (ic->next, ic);
5415 emitcode ("", "; genIpop");
5421 emitcode ("", "; genCall");
5426 emitcode ("", "; genPcall");
5431 emitcode ("", "; genFunction");
5436 emitcode ("", "; genEndFunction");
5437 genEndFunction (ic);
5441 emitcode ("", "; genRet");
5446 emitcode ("", "; genLabel");
5451 emitcode ("", "; genGoto");
5456 emitcode ("", "; genPlus");
5461 emitcode ("", "; genMinus");
5466 emitcode ("", "; genMult");
5471 emitcode ("", "; genDiv");
5476 emitcode ("", "; genMod");
5481 emitcode ("", "; genCmpGt");
5482 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5486 emitcode ("", "; genCmpLt");
5487 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5494 /* note these two are xlated by algebraic equivalence
5495 during parsing SDCC.y */
5496 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5497 "got '>=' or '<=' shouldn't have come here");
5501 emitcode ("", "; genCmpEq");
5502 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5506 emitcode ("", "; genAndOp");
5511 emitcode ("", "; genOrOp");
5516 emitcode ("", "; genXor");
5517 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5521 emitcode ("", "; genOr");
5522 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5526 emitcode ("", "; genAnd");
5527 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5531 emitcode ("", "; genInline");
5536 emitcode ("", "; genRRC");
5541 emitcode ("", "; genRLC");
5546 emitcode ("", "; genHBIT");
5550 emitcode ("", "; genLeftShift");
5555 emitcode ("", "; genRightShift");
5559 case GET_VALUE_AT_ADDRESS:
5560 emitcode ("", "; genPointerGet");
5566 if (POINTER_SET (ic))
5568 emitcode ("", "; genAssign (pointer)");
5573 emitcode ("", "; genAssign");
5579 emitcode ("", "; genIfx");
5584 emitcode ("", "; genAddrOf");
5589 emitcode ("", "; genJumpTab");
5594 emitcode ("", "; genCast");
5599 emitcode ("", "; genReceive");
5604 emitcode ("", "; addSet");
5605 addSet (&sendSet, ic);
5610 /* piCode(ic,stdout); */
5616 /* now we are ready to call the
5617 peep hole optimizer */
5618 if (!options.nopeep)
5619 peepHole (&lineHead);
5621 /* This is unfortunate */
5622 /* now do the actual printing */
5624 FILE *fp = codeOutFile;
5625 if (isInHome () && codeOutFile == code->oFile)
5626 codeOutFile = home->oFile;
5627 printLine (lineHead, codeOutFile);
5628 if (_G.flush_statics)
5631 _G.flush_statics = 0;