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 1. Starting again at 3 Aug 01 34965 93 219C
24 Includes long mul/div in code
25 2. Optimised memcpy for acc use 32102 102 226B
26 3. Optimised strcpy for acc use 27819 117 2237
27 3a Optimised memcpy fun
28 4. Optimised strcmp fun 21999 149 2294
29 5. Optimised strcmp further 21660 151 228C
30 6. Optimised memcpy by unroling 20885 157 2201
32 Michael Hope <michaelh@juju.net.nz> 2000
33 Based on the mcs51 generator -
34 Sandeep Dutta . sandeep.dutta@usa.net (1998)
35 and - Jean-Louis VERN.jlvern@writeme.com (1999)
37 This program is free software; you can redistribute it and/or modify it
38 under the terms of the GNU General Public License as published by the
39 Free Software Foundation; either version 2, or (at your option) any
42 This program is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
48 You should have received a copy of the GNU General Public License
49 along with this program; if not, write to the Free Software
50 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
52 In other words, you are welcome to use, share and improve this program.
53 You are forbidden to forbid anyone else to use, share and improve
54 what you give them. Help stamp out software-hoarding!
56 -------------------------------------------------------------------------*/
63 #ifdef HAVE_SYS_ISA_DEFS_H
64 #include <sys/isa_defs.h>
68 #include "SDCCglobl.h"
69 #include "SDCCpeeph.h"
74 /* this is the down and dirty file with all kinds of kludgy & hacky
75 stuff. This is what it is all about CODE GENERATION for a specific MCU.
76 Some of the routines may be reusable, will have to see */
78 /* Z80 calling convention description.
79 Parameters are passed right to left. As the stack grows downwards,
80 the parameters are arranged in left to right in memory.
81 Parameters may be passed in the HL and DE registers with one
83 PENDING: What if the parameter is a long?
84 Everything is caller saves. i.e. the caller must save any registers
85 that it wants to preserve over the call.
86 The return value is returned in DEHL. DE is normally used as a
87 working register pair. Caller saves allows it to be used for a
89 va args functions do not use register parameters. All arguments
90 are passed on the stack.
91 IX is used as an index register to the top of the local variable
92 area. ix-0 is the top most local variable.
99 static char *_z80_return[] =
100 {"l", "h", "e", "d"};
101 static char *_gbz80_return[] =
102 {"e", "d", "l", "h"};
103 static char *_fReceive[] =
104 { "c", "b", "e", "d" };
106 static char **_fReturn;
109 extern FILE *codeOutFile;
128 } _pairs[NUM_PAIRS] = {
129 { "??1", "?2", "?3" },
134 { "iy", "iy.l?", "iy.h?" },
135 { "ix", "ix.l?", "ix.h?" }
139 #define ACC_NAME _pairs[PAIR_AF].h
141 #define RESULTONSTACK(x) \
142 (IC_RESULT(x) && IC_RESULT(x)->aop && \
143 IC_RESULT(x)->aop->type == AOP_STK )
174 const char *lastFunctionName;
180 /** TRUE if the registers have already been saved. */
193 static const char *aopGet (asmop * aop, int offset, bool bit16);
198 /* Clean up the line so that it is 'prettier' */
199 if (strchr (buf, ':'))
201 /* Is a label - cant do anything */
204 /* Change the first (and probably only) ' ' to a tab so
219 _vemit2 (const char *szFormat, va_list ap)
223 tvsprintf (buffer, szFormat, ap);
226 _G.lines.current = (_G.lines.current ?
227 connectLine (_G.lines.current, newLineNode (buffer)) :
228 (_G.lines.head = newLineNode (buffer)));
230 _G.lines.current->isInline = _G.lines.isInline;
234 emit2 (const char *szFormat,...)
238 va_start (ap, szFormat);
240 _vemit2 (szFormat, ap);
246 emitDebug (const char *szFormat,...)
252 va_start (ap, szFormat);
254 _vemit2 (szFormat, ap);
260 /*-----------------------------------------------------------------*/
261 /* emit2 - writes the code into a file : for now it is simple */
262 /*-----------------------------------------------------------------*/
264 _emit2 (const char *inst, const char *fmt,...)
267 char lb[INITIAL_INLINEASM];
274 sprintf (lb, "%s\t", inst);
275 vsprintf (lb + (strlen (lb)), fmt, ap);
278 vsprintf (lb, fmt, ap);
280 while (isspace (*lbp))
285 _G.lines.current = (_G.lines.current ?
286 connectLine (_G.lines.current, newLineNode (lb)) :
287 (_G.lines.head = newLineNode (lb)));
289 _G.lines.current->isInline = _G.lines.isInline;
294 _emitMove(const char *to, const char *from)
296 if (strcasecmp(to, from) != 0)
298 emit2("ld %s,%s", to, from);
303 // Could leave this to the peephole, but sometimes the peephole is inhibited.
308 _moveA(const char *moveFrom)
310 // Let the peephole optimiser take care of redundent loads
311 _emitMove(ACC_NAME, moveFrom);
321 getPairName (asmop * aop)
323 if (aop->type == AOP_REG)
325 switch (aop->aopu.aop_reg[0]->rIdx)
338 else if (aop->type == AOP_STR)
340 switch (*aop->aopu.aop_str[0])
358 getPairId (asmop * aop)
362 if (aop->type == AOP_REG)
364 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
368 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
372 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
377 if (aop->type == AOP_STR)
379 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
383 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
387 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
396 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
400 return (getPairId (aop) != PAIR_INVALID);
404 isPtrPair (asmop * aop)
406 PAIR_ID pairId = getPairId (aop);
417 /** Push a register pair onto the stack */
419 genPairPush (asmop * aop)
421 emit2 ("push %s", getPairName (aop));
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp */
427 /*-----------------------------------------------------------------*/
429 newAsmop (short type)
433 aop = Safe_calloc (1, sizeof (asmop));
438 /*-----------------------------------------------------------------*/
439 /* aopForSym - for a true symbol */
440 /*-----------------------------------------------------------------*/
442 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
449 wassert (sym->etype);
451 space = SPEC_OCLS (sym->etype);
453 /* if already has one */
457 /* Assign depending on the storage class */
458 if (sym->onStack || sym->iaccess)
460 emitDebug ("; AOP_STK for %s", sym->rname);
461 sym->aop = aop = newAsmop (AOP_STK);
462 aop->size = getSize (sym->type);
463 aop->aopu.aop_stk = sym->stack;
467 /* special case for a function */
468 if (IS_FUNC (sym->type))
470 sym->aop = aop = newAsmop (AOP_IMMD);
471 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
472 strcpy (aop->aopu.aop_immd, sym->rname);
479 /* if it is in direct space */
480 if (IN_REGSP (space) && !requires_a)
482 sym->aop = aop = newAsmop (AOP_SFR);
483 aop->aopu.aop_dir = sym->rname;
484 aop->size = getSize (sym->type);
485 emitDebug ("; AOP_SFR for %s", sym->rname);
490 /* only remaining is far space */
491 /* in which case DPTR gets the address */
494 emitDebug ("; AOP_HL for %s", sym->rname);
495 sym->aop = aop = newAsmop (AOP_HL);
499 sym->aop = aop = newAsmop (AOP_IY);
501 aop->size = getSize (sym->type);
502 aop->aopu.aop_dir = sym->rname;
504 /* if it is in code space */
505 if (IN_CODESPACE (space))
511 /*-----------------------------------------------------------------*/
512 /* aopForRemat - rematerialzes an object */
513 /*-----------------------------------------------------------------*/
515 aopForRemat (symbol * sym)
518 iCode *ic = sym->rematiCode;
519 asmop *aop = newAsmop (AOP_IMMD);
523 /* if plus or minus print the right hand side */
524 if (ic->op == '+' || ic->op == '-')
526 /* PENDING: for re-target */
527 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
530 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
533 /* we reached the end */
534 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
538 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
539 strcpy (aop->aopu.aop_immd, buffer);
543 /*-----------------------------------------------------------------*/
544 /* regsInCommon - two operands have some registers in common */
545 /*-----------------------------------------------------------------*/
547 regsInCommon (operand * op1, operand * op2)
552 /* if they have registers in common */
553 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
556 sym1 = OP_SYMBOL (op1);
557 sym2 = OP_SYMBOL (op2);
559 if (sym1->nRegs == 0 || sym2->nRegs == 0)
562 for (i = 0; i < sym1->nRegs; i++)
568 for (j = 0; j < sym2->nRegs; j++)
573 if (sym2->regs[j] == sym1->regs[i])
581 /*-----------------------------------------------------------------*/
582 /* operandsEqu - equivalent */
583 /*-----------------------------------------------------------------*/
585 operandsEqu (operand * op1, operand * op2)
589 /* if they not symbols */
590 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
593 sym1 = OP_SYMBOL (op1);
594 sym2 = OP_SYMBOL (op2);
596 /* if both are itemps & one is spilt
597 and the other is not then false */
598 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
599 sym1->isspilt != sym2->isspilt)
602 /* if they are the same */
606 if (strcmp (sym1->rname, sym2->rname) == 0)
610 /* if left is a tmp & right is not */
611 if (IS_ITEMP (op1) &&
614 (sym1->usl.spillLoc == sym2))
617 if (IS_ITEMP (op2) &&
621 (sym2->usl.spillLoc == sym1))
627 /*-----------------------------------------------------------------*/
628 /* sameRegs - two asmops have the same registers */
629 /*-----------------------------------------------------------------*/
631 sameRegs (asmop * aop1, asmop * aop2)
635 if (aop1->type == AOP_SFR ||
636 aop2->type == AOP_SFR)
642 if (aop1->type != AOP_REG ||
643 aop2->type != AOP_REG)
646 if (aop1->size != aop2->size)
649 for (i = 0; i < aop1->size; i++)
650 if (aop1->aopu.aop_reg[i] !=
651 aop2->aopu.aop_reg[i])
657 /*-----------------------------------------------------------------*/
658 /* aopOp - allocates an asmop for an operand : */
659 /*-----------------------------------------------------------------*/
661 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
670 /* if this a literal */
671 if (IS_OP_LITERAL (op))
673 op->aop = aop = newAsmop (AOP_LIT);
674 aop->aopu.aop_lit = op->operand.valOperand;
675 aop->size = getSize (operandType (op));
679 /* if already has a asmop then continue */
683 /* if the underlying symbol has a aop */
684 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
686 op->aop = OP_SYMBOL (op)->aop;
690 /* if this is a true symbol */
691 if (IS_TRUE_SYMOP (op))
693 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
697 /* this is a temporary : this has
703 e) can be a return use only */
705 sym = OP_SYMBOL (op);
707 /* if the type is a conditional */
708 if (sym->regType == REG_CND)
710 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
715 /* if it is spilt then two situations
717 b) has a spill location */
718 if (sym->isspilt || sym->nRegs == 0)
720 /* rematerialize it NOW */
723 sym->aop = op->aop = aop =
725 aop->size = getSize (sym->type);
731 if (sym->accuse == ACCUSE_A)
733 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
734 aop->size = getSize (sym->type);
735 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
737 aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
739 else if (sym->accuse == ACCUSE_HL)
742 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
743 aop->size = getSize (sym->type);
744 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
745 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
746 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
758 aop = op->aop = sym->aop = newAsmop (AOP_STR);
759 aop->size = getSize (sym->type);
760 for (i = 0; i < 4; i++)
761 aop->aopu.aop_str[i] = _fReturn[i];
765 /* else spill location */
766 sym->aop = op->aop = aop =
767 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
768 aop->size = getSize (sym->type);
772 /* must be in a register */
773 sym->aop = op->aop = aop = newAsmop (AOP_REG);
774 aop->size = sym->nRegs;
775 for (i = 0; i < sym->nRegs; i++)
776 aop->aopu.aop_reg[i] = sym->regs[i];
779 /*-----------------------------------------------------------------*/
780 /* freeAsmop - free up the asmop given to an operand */
781 /*----------------------------------------------------------------*/
783 freeAsmop (operand * op, asmop * aaop, iCode * ic)
801 /* all other cases just dealloc */
807 OP_SYMBOL (op)->aop = NULL;
808 /* if the symbol has a spill */
810 SPIL_LOC (op)->aop = NULL;
816 isLitWord (asmop * aop)
818 /* if (aop->size != 2)
831 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
836 /* depending on type */
842 /* PENDING: for re-target */
844 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
846 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
852 value *val = aop->aopu.aop_lit;
853 /* if it is a float then it gets tricky */
854 /* otherwise it is fairly simple */
855 if (!IS_FLOAT (val->type))
857 unsigned long v = (unsigned long) floatFromVal (val);
863 else if (offset == 0)
869 wassertl(0, "Encountered an invalid offset while fetching a literal");
873 tsprintf (buffer, "!immedword", v);
875 tsprintf (buffer, "!constword", v);
877 return gc_strdup(buffer);
883 convertFloat (&f, floatFromVal (val));
885 tsprintf (buffer, "!immedword", f.w[offset / 2]);
887 tsprintf (buffer, "!constword", f.w[offset / 2]);
888 rs = Safe_calloc (1, strlen (buffer) + 1);
889 return strcpy (rs, buffer);
898 aopGetWord (asmop * aop, int offset)
900 return aopGetLitWordLong (aop, offset, TRUE);
904 isPtr (const char *s)
906 if (!strcmp (s, "hl"))
908 if (!strcmp (s, "ix"))
910 if (!strcmp (s, "iy"))
916 adjustPair (const char *pair, int *pold, int new)
922 emit2 ("inc %s", pair);
927 emit2 ("dec %s", pair);
933 spillPair (PAIR_ID pairId)
935 _G.pairs[pairId].last_type = AOP_INVALID;
936 _G.pairs[pairId].lit = NULL;
947 requiresHL (asmop * aop)
961 fetchLitSpecial (asmop * aop, bool negate, bool xor)
964 value *val = aop->aopu.aop_lit;
966 wassert (aop->type == AOP_LIT);
967 wassert (!IS_FLOAT (val->type));
969 v = (unsigned long) floatFromVal (val);
977 tsprintf (buffer, "!immedword", v);
978 return gc_strdup (buffer);
982 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
985 const char *pair = _pairs[pairId].name;
986 l = aopGetLitWordLong (left, offset, FALSE);
991 if (pairId == PAIR_HL || pairId == PAIR_IY)
993 if (_G.pairs[pairId].last_type == left->type)
995 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
997 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
999 adjustPair (pair, &_G.pairs[pairId].offset, offset);
1002 if (pairId == PAIR_IY && abs (offset) < 127)
1009 _G.pairs[pairId].last_type = left->type;
1010 _G.pairs[pairId].lit = gc_strdup (l);
1011 _G.pairs[pairId].offset = offset;
1013 if (IS_GB && pairId == PAIR_DE && 0)
1015 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
1017 if (abs (_G.pairs[pairId].offset - offset) < 3)
1019 adjustPair (pair, &_G.pairs[pairId].offset, offset);
1023 _G.pairs[pairId].last_type = left->type;
1024 _G.pairs[pairId].lit = gc_strdup (l);
1025 _G.pairs[pairId].offset = offset;
1027 /* Both a lit on the right and a true symbol on the left */
1028 emit2 ("ld %s,!hashedstr", pair, l);
1032 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
1034 /* if this is remateriazable */
1035 if (isLitWord (aop)) {
1036 fetchLitPair (pairId, aop, offset);
1039 /* we need to get it byte by byte */
1040 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1041 aopGet (aop, offset, FALSE);
1042 switch (aop->size) {
1044 emit2 ("ld l,!*hl");
1045 emit2 ("ld h,!immedbyte", 0);
1049 emit2 ("ld h,!*hl");
1053 emitDebug ("; WARNING: mlh woosed out. This code is invalid.");
1056 else if (IS_Z80 && aop->type == AOP_IY) {
1057 /* Instead of fetching relative to IY, just grab directly
1058 from the address IY refers to */
1059 char *l = aopGetLitWordLong (aop, offset, FALSE);
1061 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1063 if (aop->size < 2) {
1064 emit2("ld %s,!zero", _pairs[pairId].h);
1068 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1069 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1071 /* PENDING: check? */
1072 if (pairId == PAIR_HL)
1073 spillPair (PAIR_HL);
1078 fetchPair (PAIR_ID pairId, asmop * aop)
1080 fetchPairLong (pairId, aop, 0);
1084 fetchHL (asmop * aop)
1086 fetchPair (PAIR_HL, aop);
1090 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1092 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1097 fetchLitPair (pairId, aop, 0);
1100 fetchLitPair (pairId, aop, offset);
1101 _G.pairs[pairId].offset = offset;
1105 /* Doesnt include _G.stack.pushed */
1106 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1107 if (aop->aopu.aop_stk > 0)
1109 abso += _G.stack.param_offset;
1111 assert (pairId == PAIR_HL);
1112 /* In some cases we can still inc or dec hl */
1113 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1115 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1119 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1121 _G.pairs[pairId].offset = abso;
1127 _G.pairs[pairId].last_type = aop->type;
1133 emit2 ("!tlabeldef", key);
1137 /*-----------------------------------------------------------------*/
1138 /* aopGet - for fetching value of the aop */
1139 /*-----------------------------------------------------------------*/
1141 aopGet (asmop * aop, int offset, bool bit16)
1145 /* offset is greater than size then zero */
1146 /* PENDING: this seems a bit screwed in some pointer cases. */
1147 if (offset > (aop->size - 1) &&
1148 aop->type != AOP_LIT)
1150 tsprintf (s, "!zero");
1151 return gc_strdup(s);
1154 /* depending on type */
1158 /* PENDING: re-target */
1160 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1165 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1168 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1171 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1177 return gc_strdup(s);
1181 emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
1184 return gc_strdup(s);
1188 emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
1191 return gc_strdup(s);
1194 return aop->aopu.aop_reg[offset]->name;
1198 setupPair (PAIR_HL, aop, offset);
1199 tsprintf (s, "!*hl");
1201 return gc_strdup (s);
1205 setupPair (PAIR_IY, aop, offset);
1206 tsprintf (s, "!*iyx", offset);
1208 return gc_strdup(s);
1213 setupPair (PAIR_HL, aop, offset);
1214 tsprintf (s, "!*hl");
1218 if (aop->aopu.aop_stk >= 0)
1219 offset += _G.stack.param_offset;
1220 tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
1223 return gc_strdup(s);
1235 tsprintf(s, "!zero");
1236 return gc_strdup(s);
1240 wassert (offset < 2);
1241 return aop->aopu.aop_str[offset];
1244 return aopLiteral (aop->aopu.aop_lit, offset);
1248 return aop->aopu.aop_str[offset];
1253 wassertl (0, "aopget got unsupported aop->type");
1258 isRegString (const char *s)
1260 if (!strcmp (s, "b") ||
1272 isConstant (const char *s)
1274 /* This is a bit of a hack... */
1275 return (*s == '#' || *s == '$');
1279 canAssignToPtr (const char *s)
1281 if (isRegString (s))
1288 /*-----------------------------------------------------------------*/
1289 /* aopPut - puts a string for a aop */
1290 /*-----------------------------------------------------------------*/
1292 aopPut (asmop * aop, const char *s, int offset)
1296 if (aop->size && offset > (aop->size - 1))
1298 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1299 "aopPut got offset > aop->size");
1304 tsprintf(buffer2, s);
1307 /* will assign value to value */
1308 /* depending on where it is ofcourse */
1314 if (strcmp (s, "a"))
1315 emit2 ("ld a,%s", s);
1316 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1321 if (strcmp (s, "a"))
1322 emit2 ("ld a,%s", s);
1323 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1327 if (!strcmp (s, "!*hl"))
1328 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1331 aop->aopu.aop_reg[offset]->name, s);
1336 setupPair (PAIR_IY, aop, offset);
1337 if (!canAssignToPtr (s))
1339 emit2 ("ld a,%s", s);
1340 emit2 ("ld !*iyx,a", offset);
1343 emit2 ("ld !*iyx,%s", offset, s);
1348 /* PENDING: for re-target */
1349 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1351 emit2 ("ld a,!*hl");
1354 setupPair (PAIR_HL, aop, offset);
1356 emit2 ("ld !*hl,%s", s);
1362 /* PENDING: re-target */
1363 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1365 emit2 ("ld a,!*hl");
1368 setupPair (PAIR_HL, aop, offset);
1369 if (!canAssignToPtr (s))
1371 emit2 ("ld a,%s", s);
1372 emit2 ("ld !*hl,a");
1375 emit2 ("ld !*hl,%s", s);
1379 if (aop->aopu.aop_stk >= 0)
1380 offset += _G.stack.param_offset;
1381 if (!canAssignToPtr (s))
1383 emit2 ("ld a,%s", s);
1384 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1387 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1392 /* if bit variable */
1393 if (!aop->aopu.aop_dir)
1400 /* In bit space but not in C - cant happen */
1407 if (strcmp (aop->aopu.aop_str[offset], s))
1409 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1415 if (!offset && (strcmp (s, "acc") == 0))
1420 emitDebug ("; Error aopPut AOP_ACC");
1424 if (strcmp (aop->aopu.aop_str[offset], s))
1425 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1430 wassert (offset < 2);
1431 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1435 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1436 "aopPut got unsupported aop->type");
1441 #define AOP(op) op->aop
1442 #define AOP_TYPE(op) AOP(op)->type
1443 #define AOP_SIZE(op) AOP(op)->size
1444 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1447 commitPair (asmop * aop, PAIR_ID id)
1449 if (id == PAIR_HL && requiresHL (aop))
1453 aopPut (aop, "a", 0);
1454 aopPut (aop, "d", 1);
1458 aopPut (aop, _pairs[id].l, 0);
1459 aopPut (aop, _pairs[id].h, 1);
1463 /*-----------------------------------------------------------------*/
1464 /* getDataSize - get the operand data size */
1465 /*-----------------------------------------------------------------*/
1467 getDataSize (operand * op)
1470 size = AOP_SIZE (op);
1479 /*-----------------------------------------------------------------*/
1480 /* movLeft2Result - move byte from left to result */
1481 /*-----------------------------------------------------------------*/
1483 movLeft2Result (operand * left, int offl,
1484 operand * result, int offr, int sign)
1487 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1489 l = aopGet (AOP (left), offl, FALSE);
1493 aopPut (AOP (result), l, offr);
1503 /** Put Acc into a register set
1506 outAcc (operand * result)
1509 size = getDataSize (result);
1512 aopPut (AOP (result), "a", 0);
1515 /* unsigned or positive */
1518 aopPut (AOP (result), "!zero", offset++);
1523 /** Take the value in carry and put it into a register
1526 outBitCLong (operand * result, bool swap_sense)
1528 /* if the result is bit */
1529 if (AOP_TYPE (result) == AOP_CRY)
1531 emitDebug ("; Note: outBitC form 1");
1532 aopPut (AOP (result), "blah", 0);
1536 emit2 ("ld a,!zero");
1539 emit2 ("xor a,!immedbyte", 1);
1545 outBitC (operand * result)
1547 outBitCLong (result, FALSE);
1550 /*-----------------------------------------------------------------*/
1551 /* toBoolean - emit code for orl a,operator(sizeop) */
1552 /*-----------------------------------------------------------------*/
1554 _toBoolean (operand * oper)
1556 int size = AOP_SIZE (oper);
1560 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1563 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1567 if (AOP (oper)->type != AOP_ACC)
1570 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation */
1577 /*-----------------------------------------------------------------*/
1581 sym_link *optype = operandType (IC_LEFT (ic));
1583 /* assign asmOps to operand & result */
1584 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1585 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1587 /* if in bit space then a special case */
1588 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593 /* if type float then do float */
1594 if (IS_FLOAT (optype))
1599 _toBoolean (IC_LEFT (ic));
1604 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1605 emit2 ("sub a,!one");
1606 outBitC (IC_RESULT (ic));
1608 /* release the aops */
1609 freeAsmop (IC_LEFT (ic), NULL, ic);
1610 freeAsmop (IC_RESULT (ic), NULL, ic);
1613 /*-----------------------------------------------------------------*/
1614 /* genCpl - generate code for complement */
1615 /*-----------------------------------------------------------------*/
1623 /* assign asmOps to operand & result */
1624 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1625 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1627 /* if both are in bit space then
1629 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1630 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1635 size = AOP_SIZE (IC_RESULT (ic));
1638 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1641 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1644 /* release the aops */
1645 freeAsmop (IC_LEFT (ic), NULL, ic);
1646 freeAsmop (IC_RESULT (ic), NULL, ic);
1649 /*-----------------------------------------------------------------*/
1650 /* genUminus - unary minus code generation */
1651 /*-----------------------------------------------------------------*/
1653 genUminus (iCode * ic)
1656 sym_link *optype, *rtype;
1659 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1660 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1662 /* if both in bit space then special
1664 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1665 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1671 optype = operandType (IC_LEFT (ic));
1672 rtype = operandType (IC_RESULT (ic));
1674 /* if float then do float stuff */
1675 if (IS_FLOAT (optype))
1681 /* otherwise subtract from zero */
1682 size = AOP_SIZE (IC_LEFT (ic));
1687 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1688 emit2 ("ld a,!zero");
1689 emit2 ("sbc a,%s", l);
1690 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1693 /* if any remaining bytes in the result */
1694 /* we just need to propagate the sign */
1695 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1700 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1704 /* release the aops */
1705 freeAsmop (IC_LEFT (ic), NULL, ic);
1706 freeAsmop (IC_RESULT (ic), NULL, ic);
1710 _push (PAIR_ID pairId)
1712 emit2 ("push %s", _pairs[pairId].name);
1713 _G.stack.pushed += 2;
1717 _pop (PAIR_ID pairId)
1719 emit2 ("pop %s", _pairs[pairId].name);
1720 _G.stack.pushed -= 2;
1724 /*-----------------------------------------------------------------*/
1725 /* assignResultValue - */
1726 /*-----------------------------------------------------------------*/
1728 assignResultValue (operand * oper)
1730 int size = AOP_SIZE (oper);
1733 wassert (size <= 4);
1734 topInA = requiresHL (AOP (oper));
1738 wassert (size <= 2);
1740 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1742 /* We do it the hard way here. */
1744 aopPut (AOP (oper), _fReturn[0], 0);
1745 aopPut (AOP (oper), _fReturn[1], 1);
1747 _G.stack.pushed -= 2;
1748 aopPut (AOP (oper), _fReturn[0], 2);
1749 aopPut (AOP (oper), _fReturn[1], 3);
1755 aopPut (AOP (oper), _fReturn[size], size);
1761 _saveRegsForCall(iCode *ic, int sendSetSize)
1764 o Stack parameters are pushed before this function enters
1765 o DE and BC may be used in this function.
1766 o HL and DE may be used to return the result.
1767 o HL and DE may be used to send variables.
1768 o DE and BC may be used to store the result value.
1769 o HL may be used in computing the sent value of DE
1770 o The iPushes for other parameters occur before any addSets
1772 Logic: (to be run inside the first iPush or if none, before sending)
1773 o Compute if DE and/or BC are in use over the call
1774 o Compute if DE is used in the send set
1775 o Compute if DE and/or BC are used to hold the result value
1776 o If (DE is used, or in the send set) and is not used in the result, push.
1777 o If BC is used and is not in the result, push
1779 o If DE is used in the send set, fetch
1780 o If HL is used in the send set, fetch
1784 if (_G.saves.saved == FALSE) {
1785 bool deInUse, bcInUse;
1787 bool bcInRet = FALSE, deInRet = FALSE;
1791 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1795 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
1799 /* Has no result, so in use is all of in use */
1804 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
1805 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
1807 deSending = (sendSetSize > 1);
1809 emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
1811 if (bcInUse && bcInRet == FALSE) {
1813 _G.stack.pushedBC = TRUE;
1815 if (deInUse && deInRet == FALSE) {
1817 _G.stack.pushedDE = TRUE;
1820 _G.saves.saved = TRUE;
1823 /* Already saved. */
1827 /*-----------------------------------------------------------------*/
1828 /* genIpush - genrate code for pushing this gets a little complex */
1829 /*-----------------------------------------------------------------*/
1831 genIpush (iCode * ic)
1833 int size, offset = 0;
1836 /* if this is not a parm push : ie. it is spill push
1837 and spill push is always done on the local stack */
1840 wassertl(0, "Encountered an unsupported spill push.");
1844 if (_G.saves.saved == FALSE) {
1845 /* Caller saves, and this is the first iPush. */
1846 /* Scan ahead until we find the function that we are pushing parameters to.
1847 Count the number of addSets on the way to figure out what registers
1848 are used in the send set.
1851 iCode *walk = ic->next;
1854 if (walk->op == SEND) {
1857 else if (walk->op == CALL || walk->op == PCALL) {
1866 _saveRegsForCall(walk, nAddSets);
1869 /* Already saved by another iPush. */
1872 /* then do the push */
1873 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1875 size = AOP_SIZE (IC_LEFT (ic));
1877 if (isPair (AOP (IC_LEFT (ic))))
1879 _G.stack.pushed += 2;
1880 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1886 fetchHL (AOP (IC_LEFT (ic)));
1888 spillPair (PAIR_HL);
1889 _G.stack.pushed += 2;
1894 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1896 spillPair (PAIR_HL);
1897 _G.stack.pushed += 2;
1898 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1900 spillPair (PAIR_HL);
1901 _G.stack.pushed += 2;
1907 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1909 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1911 emit2 ("ld a,(%s)", l);
1915 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1916 emit2 ("ld a,%s", l);
1924 freeAsmop (IC_LEFT (ic), NULL, ic);
1927 /*-----------------------------------------------------------------*/
1928 /* genIpop - recover the registers: can happen only for spilling */
1929 /*-----------------------------------------------------------------*/
1931 genIpop (iCode * ic)
1936 /* if the temp was not pushed then */
1937 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1940 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1941 size = AOP_SIZE (IC_LEFT (ic));
1942 offset = (size - 1);
1943 if (isPair (AOP (IC_LEFT (ic))))
1945 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
1953 spillPair (PAIR_HL);
1954 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1958 freeAsmop (IC_LEFT (ic), NULL, ic);
1961 /* This is quite unfortunate */
1963 setArea (int inHome)
1966 static int lastArea = 0;
1968 if (_G.in_home != inHome) {
1970 const char *sz = port->mem.code_name;
1971 port->mem.code_name = "HOME";
1972 emit2("!area", CODE_NAME);
1973 port->mem.code_name = sz;
1976 emit2("!area", CODE_NAME); */
1977 _G.in_home = inHome;
1988 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1992 symbol *sym = OP_SYMBOL (op);
1994 if (sym->isspilt || sym->nRegs == 0)
1997 aopOp (op, ic, FALSE, FALSE);
2000 if (aop->type == AOP_REG)
2003 for (i = 0; i < aop->size; i++)
2005 if (pairId == PAIR_DE)
2007 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2008 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2010 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2013 else if (pairId == PAIR_BC)
2015 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2016 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2018 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2028 freeAsmop (IC_LEFT (ic), NULL, ic);
2032 /** Emit the code for a call statement
2035 emitCall (iCode * ic, bool ispcall)
2037 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
2039 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2041 /* if caller saves & we have not saved then */
2047 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2049 /* if send set is not empty then assign */
2054 int nSend = elementsInSet(_G.sendSet);
2055 bool swapped = FALSE;
2057 int _z80_sendOrder[] = {
2062 /* Check if the parameters are swapped. If so route through hl instead. */
2063 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2065 sic = setFirstItem(_G.sendSet);
2066 sic = setNextItem(_G.sendSet);
2068 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2069 /* The second send value is loaded from one the one that holds the first
2070 send, i.e. it is overwritten. */
2071 /* Cache the first in HL, and load the second from HL instead. */
2072 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2073 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2079 for (sic = setFirstItem (_G.sendSet); sic;
2080 sic = setNextItem (_G.sendSet))
2083 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2085 size = AOP_SIZE (IC_LEFT (sic));
2086 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2087 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2089 // PENDING: Mild hack
2090 if (swapped == TRUE && send == 1) {
2092 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2095 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2097 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2100 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2104 freeAsmop (IC_LEFT (sic), NULL, sic);
2111 if (IS_BANKEDCALL (detype))
2113 werror (W_INDIR_BANKED);
2115 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2117 if (isLitWord (AOP (IC_LEFT (ic))))
2119 emitDebug ("; Special case where the pCall is to a constant");
2120 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2124 symbol *rlbl = newiTempLabel (NULL);
2125 spillPair (PAIR_HL);
2126 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2128 _G.stack.pushed += 2;
2130 fetchHL (AOP (IC_LEFT (ic)));
2132 emit2 ("!tlabeldef", (rlbl->key + 100));
2133 _G.stack.pushed -= 2;
2135 freeAsmop (IC_LEFT (ic), NULL, ic);
2139 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2140 OP_SYMBOL (IC_LEFT (ic))->rname :
2141 OP_SYMBOL (IC_LEFT (ic))->name;
2142 if (IS_BANKEDCALL (detype))
2144 emit2 ("call banked_call");
2145 emit2 ("!dws", name);
2146 emit2 ("!dw !bankimmeds", name);
2151 emit2 ("call %s", name);
2156 /* Mark the regsiters as restored. */
2157 _G.saves.saved = FALSE;
2159 /* if we need assign a result value */
2160 if ((IS_ITEMP (IC_RESULT (ic)) &&
2161 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2162 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2163 IS_TRUE_SYMOP (IC_RESULT (ic)))
2166 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2168 assignResultValue (IC_RESULT (ic));
2170 freeAsmop (IC_RESULT (ic), NULL, ic);
2173 /* adjust the stack for parameters if required */
2176 int i = ic->parmBytes;
2178 _G.stack.pushed -= i;
2181 emit2 ("!ldaspsp", i);
2188 emit2 ("ld hl,#%d", i);
2189 emit2 ("add hl,sp");
2206 if (_G.stack.pushedDE)
2208 bool dInUse = bitVectBitValue(rInUse, D_IDX);
2209 bool eInUse = bitVectBitValue(rInUse, E_IDX);
2211 if (dInUse && eInUse)
2227 wassertl (0, "Neither D or E were in use but it was pushed.");
2229 _G.stack.pushedDE = FALSE;
2232 if (_G.stack.pushedBC)
2234 bool bInUse = bitVectBitValue(rInUse, B_IDX);
2235 bool cInUse = bitVectBitValue(rInUse, C_IDX);
2237 // If both B and C are used in the return value, then we won't get
2239 if (bInUse && cInUse)
2255 wassertl (0, "Neither B or C were in use but it was pushed.");
2257 _G.stack.pushedBC = FALSE;
2261 /*-----------------------------------------------------------------*/
2262 /* genCall - generates a call statement */
2263 /*-----------------------------------------------------------------*/
2265 genCall (iCode * ic)
2267 emitCall (ic, FALSE);
2270 /*-----------------------------------------------------------------*/
2271 /* genPcall - generates a call by pointer statement */
2272 /*-----------------------------------------------------------------*/
2274 genPcall (iCode * ic)
2276 emitCall (ic, TRUE);
2279 /*-----------------------------------------------------------------*/
2280 /* resultRemat - result is rematerializable */
2281 /*-----------------------------------------------------------------*/
2283 resultRemat (iCode * ic)
2285 if (SKIP_IC (ic) || ic->op == IFX)
2288 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2290 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2291 if (sym->remat && !POINTER_SET (ic))
2298 extern set *publics;
2300 /*-----------------------------------------------------------------*/
2301 /* genFunction - generated code for function entry */
2302 /*-----------------------------------------------------------------*/
2304 genFunction (iCode * ic)
2306 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2310 bool bcInUse = FALSE;
2311 bool deInUse = FALSE;
2314 setArea (IS_NONBANKED (sym->etype));
2316 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2319 _G.receiveOffset = 0;
2323 if (!IS_STATIC (sym->etype))
2325 addSetIfnotP (&publics, sym);
2329 /* Record the last function name for debugging. */
2330 _G.lastFunctionName = sym->rname;
2332 /* Create the function header */
2333 emit2 ("!functionheader", sym->name);
2334 /* PENDING: portability. */
2335 emit2 ("__%s_start:", sym->rname);
2336 emit2 ("!functionlabeldef", sym->rname);
2338 if (options.profile)
2340 emit2 ("!profileenter");
2343 fetype = getSpec (operandType (IC_LEFT (ic)));
2345 /* if critical function then turn interrupts off */
2346 if (SPEC_CRTCL (fetype))
2349 /* if this is an interrupt service routine then save all potentially used registers. */
2350 if (IS_ISR (sym->etype))
2355 /* PENDING: callee-save etc */
2357 _G.stack.param_offset = 0;
2360 /* Detect which registers are used. */
2364 for (i = 0; i < sym->regsUsed->size; i++)
2366 if (bitVectBitValue (sym->regsUsed, i))
2380 /* Other systems use DE as a temporary. */
2391 _G.stack.param_offset += 2;
2394 _G.stack.pushedBC = bcInUse;
2399 _G.stack.param_offset += 2;
2402 _G.stack.pushedDE = deInUse;
2405 /* adjust the stack for the function */
2406 _G.stack.last = sym->stack;
2409 emit2 ("!enterx", sym->stack);
2412 _G.stack.offset = sym->stack;
2415 /*-----------------------------------------------------------------*/
2416 /* genEndFunction - generates epilogue for functions */
2417 /*-----------------------------------------------------------------*/
2419 genEndFunction (iCode * ic)
2421 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2423 if (IS_ISR (sym->etype))
2429 if (SPEC_CRTCL (sym->etype))
2432 /* PENDING: calleeSave */
2434 if (_G.stack.offset)
2436 emit2 ("!leavex", _G.stack.offset);
2444 if (_G.stack.pushedDE)
2447 _G.stack.pushedDE = FALSE;
2450 if (_G.stack.pushedDE)
2453 _G.stack.pushedDE = FALSE;
2457 if (options.profile)
2459 emit2 ("!profileexit");
2463 /* Both baned and non-banked just ret */
2466 /* PENDING: portability. */
2467 emit2 ("__%s_end:", sym->rname);
2469 _G.flushStatics = 1;
2470 _G.stack.pushed = 0;
2471 _G.stack.offset = 0;
2474 /*-----------------------------------------------------------------*/
2475 /* genRet - generate code for return statement */
2476 /*-----------------------------------------------------------------*/
2481 /* Errk. This is a hack until I can figure out how
2482 to cause dehl to spill on a call */
2483 int size, offset = 0;
2485 /* if we have no return value then
2486 just generate the "ret" */
2490 /* we have something to return then
2491 move the return value into place */
2492 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2493 size = AOP_SIZE (IC_LEFT (ic));
2495 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2499 emit2 ("ld de,%s", l);
2503 emit2 ("ld hl,%s", l);
2508 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2510 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2511 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2517 l = aopGet (AOP (IC_LEFT (ic)), offset,
2519 if (strcmp (_fReturn[offset], l))
2520 emit2 ("ld %s,%s", _fReturn[offset++], l);
2524 freeAsmop (IC_LEFT (ic), NULL, ic);
2527 /* generate a jump to the return label
2528 if the next is not the return statement */
2529 if (!(ic->next && ic->next->op == LABEL &&
2530 IC_LABEL (ic->next) == returnLabel))
2532 emit2 ("jp !tlabel", returnLabel->key + 100);
2535 /*-----------------------------------------------------------------*/
2536 /* genLabel - generates a label */
2537 /*-----------------------------------------------------------------*/
2539 genLabel (iCode * ic)
2541 /* special case never generate */
2542 if (IC_LABEL (ic) == entryLabel)
2545 emitLabel (IC_LABEL (ic)->key + 100);
2548 /*-----------------------------------------------------------------*/
2549 /* genGoto - generates a ljmp */
2550 /*-----------------------------------------------------------------*/
2552 genGoto (iCode * ic)
2554 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2557 /*-----------------------------------------------------------------*/
2558 /* genPlusIncr :- does addition with increment if possible */
2559 /*-----------------------------------------------------------------*/
2561 genPlusIncr (iCode * ic)
2563 unsigned int icount;
2564 unsigned int size = getDataSize (IC_RESULT (ic));
2565 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2567 /* will try to generate an increment */
2568 /* if the right side is not a literal
2570 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2573 emitDebug ("; genPlusIncr");
2575 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2577 /* If result is a pair */
2578 if (resultId != PAIR_INVALID)
2580 if (isLitWord (AOP (IC_LEFT (ic))))
2582 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2585 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2587 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2588 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2594 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2598 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2599 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2603 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2608 /* if the literal value of the right hand side
2609 is greater than 4 then it is not worth it */
2613 /* if increment 16 bits in register */
2614 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2620 symbol *tlbl = NULL;
2621 tlbl = newiTempLabel (NULL);
2624 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2627 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2630 emitLabel (tlbl->key + 100);
2634 /* if the sizes are greater than 1 then we cannot */
2635 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2636 AOP_SIZE (IC_LEFT (ic)) > 1)
2639 /* we can if the aops of the left & result match or
2640 if they are in registers and the registers are the
2642 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2646 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2654 /*-----------------------------------------------------------------*/
2655 /* outBitAcc - output a bit in acc */
2656 /*-----------------------------------------------------------------*/
2658 outBitAcc (operand * result)
2660 symbol *tlbl = newiTempLabel (NULL);
2661 /* if the result is a bit */
2662 if (AOP_TYPE (result) == AOP_CRY)
2668 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2669 emit2 ("ld a,!one");
2670 emitLabel (tlbl->key + 100);
2675 /*-----------------------------------------------------------------*/
2676 /* genPlus - generates code for addition */
2677 /*-----------------------------------------------------------------*/
2679 genPlus (iCode * ic)
2681 int size, offset = 0;
2683 /* special cases :- */
2685 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2686 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2687 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2689 /* Swap the left and right operands if:
2691 if literal, literal on the right or
2692 if left requires ACC or right is already
2695 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2696 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2697 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2699 operand *t = IC_RIGHT (ic);
2700 IC_RIGHT (ic) = IC_LEFT (ic);
2704 /* if both left & right are in bit
2706 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2707 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2713 /* if left in bit space & right literal */
2714 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2715 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2717 /* Can happen I guess */
2721 /* if I can do an increment instead
2722 of add then GOOD for ME */
2723 if (genPlusIncr (ic) == TRUE)
2726 emitDebug ("; genPlusIncr failed");
2728 size = getDataSize (IC_RESULT (ic));
2730 /* Special case when left and right are constant */
2731 if (isPair (AOP (IC_RESULT (ic))))
2735 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2736 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2742 sprintf (buffer, "#(%s + %s)", left, right);
2743 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2748 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2750 /* Fetch into HL then do the add */
2751 spillPair (PAIR_HL);
2752 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2753 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2758 ld hl,sp+n trashes C so we cant afford to do it during an
2759 add with stack based varibles. Worst case is:
2772 So you cant afford to load up hl if either left, right, or result
2773 is on the stack (*sigh*) The alt is:
2781 Combinations in here are:
2782 * If left or right are in bc then the loss is small - trap later
2783 * If the result is in bc then the loss is also small
2787 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2788 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2789 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2791 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2792 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2793 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2794 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2796 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2798 /* Swap left and right */
2799 operand *t = IC_RIGHT (ic);
2800 IC_RIGHT (ic) = IC_LEFT (ic);
2803 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2805 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2806 emit2 ("add hl,bc");
2810 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2811 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2812 emit2 ("add hl,de");
2814 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2819 emitDebug ("; WARNING: This add is probably broken.\n");
2826 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2828 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2831 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2834 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2838 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2841 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2844 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2846 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2850 freeAsmop (IC_LEFT (ic), NULL, ic);
2851 freeAsmop (IC_RIGHT (ic), NULL, ic);
2852 freeAsmop (IC_RESULT (ic), NULL, ic);
2856 /*-----------------------------------------------------------------*/
2857 /* genMinusDec :- does subtraction with deccrement if possible */
2858 /*-----------------------------------------------------------------*/
2860 genMinusDec (iCode * ic)
2862 unsigned int icount;
2863 unsigned int size = getDataSize (IC_RESULT (ic));
2865 /* will try to generate an increment */
2866 /* if the right side is not a literal we cannot */
2867 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2870 /* if the literal value of the right hand side
2871 is greater than 4 then it is not worth it */
2872 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2875 size = getDataSize (IC_RESULT (ic));
2877 /* if decrement 16 bits in register */
2878 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2879 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2882 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2886 /* If result is a pair */
2887 if (isPair (AOP (IC_RESULT (ic))))
2889 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2890 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2892 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2896 /* if increment 16 bits in register */
2897 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2900 fetchPair (PAIR_HL, AOP (IC_RESULT (ic)));
2905 aopPut (AOP (IC_RESULT (ic)), "l", LSB);
2906 aopPut (AOP (IC_RESULT (ic)), "h", MSB16);
2912 /* if the sizes are greater than 1 then we cannot */
2913 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2914 AOP_SIZE (IC_LEFT (ic)) > 1)
2917 /* we can if the aops of the left & result match or if they are in
2918 registers and the registers are the same */
2919 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2922 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2929 /*-----------------------------------------------------------------*/
2930 /* genMinus - generates code for subtraction */
2931 /*-----------------------------------------------------------------*/
2933 genMinus (iCode * ic)
2935 int size, offset = 0;
2936 unsigned long lit = 0L;
2938 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2939 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2940 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2942 /* special cases :- */
2943 /* if both left & right are in bit space */
2944 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2945 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2951 /* if I can do an decrement instead of subtract then GOOD for ME */
2952 if (genMinusDec (ic) == TRUE)
2955 size = getDataSize (IC_RESULT (ic));
2957 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2962 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2966 /* Same logic as genPlus */
2969 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2970 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2971 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2973 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2974 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2975 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2976 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2978 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2979 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2981 if (left == PAIR_INVALID && right == PAIR_INVALID)
2986 else if (right == PAIR_INVALID)
2988 else if (left == PAIR_INVALID)
2991 fetchPair (left, AOP (IC_LEFT (ic)));
2992 /* Order is important. Right may be HL */
2993 fetchPair (right, AOP (IC_RIGHT (ic)));
2995 emit2 ("ld a,%s", _pairs[left].l);
2996 emit2 ("sub a,%s", _pairs[right].l);
2998 emit2 ("ld a,%s", _pairs[left].h);
2999 emit2 ("sbc a,%s", _pairs[right].h);
3001 aopPut (AOP (IC_RESULT (ic)), "a", 1);
3002 aopPut (AOP (IC_RESULT (ic)), "e", 0);
3007 emitDebug ("; WARNING: This sub is probably broken.\n");
3012 /* if literal, add a,#-lit, else normal subb */
3015 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3016 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3020 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3023 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3027 /* first add without previous c */
3029 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
3031 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3033 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3036 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3037 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3038 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3042 freeAsmop (IC_LEFT (ic), NULL, ic);
3043 freeAsmop (IC_RIGHT (ic), NULL, ic);
3044 freeAsmop (IC_RESULT (ic), NULL, ic);
3047 /*-----------------------------------------------------------------*/
3048 /* genMult - generates code for multiplication */
3049 /*-----------------------------------------------------------------*/
3051 genMult (iCode * ic)
3053 /* Shouldn't occur - all done through function calls */
3057 /*-----------------------------------------------------------------*/
3058 /* genDiv - generates code for division */
3059 /*-----------------------------------------------------------------*/
3063 /* Shouldn't occur - all done through function calls */
3067 /*-----------------------------------------------------------------*/
3068 /* genMod - generates code for division */
3069 /*-----------------------------------------------------------------*/
3073 /* Shouldn't occur - all done through function calls */
3077 /*-----------------------------------------------------------------*/
3078 /* genIfxJump :- will create a jump depending on the ifx */
3079 /*-----------------------------------------------------------------*/
3081 genIfxJump (iCode * ic, char *jval)
3086 /* if true label then we jump if condition
3090 jlbl = IC_TRUE (ic);
3091 if (!strcmp (jval, "a"))
3095 else if (!strcmp (jval, "c"))
3099 else if (!strcmp (jval, "nc"))
3105 /* The buffer contains the bit on A that we should test */
3111 /* false label is present */
3112 jlbl = IC_FALSE (ic);
3113 if (!strcmp (jval, "a"))
3117 else if (!strcmp (jval, "c"))
3121 else if (!strcmp (jval, "nc"))
3127 /* The buffer contains the bit on A that we should test */
3131 /* Z80 can do a conditional long jump */
3132 if (!strcmp (jval, "a"))
3136 else if (!strcmp (jval, "c"))
3139 else if (!strcmp (jval, "nc"))
3144 emit2 ("bit %s,a", jval);
3146 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3148 /* mark the icode as generated */
3153 _getPairIdName (PAIR_ID id)
3155 return _pairs[id].name;
3158 /** Generic compare for > or <
3161 genCmp (operand * left, operand * right,
3162 operand * result, iCode * ifx, int sign)
3164 int size, offset = 0;
3165 unsigned long lit = 0L;
3166 bool swap_sense = FALSE;
3168 /* if left & right are bit variables */
3169 if (AOP_TYPE (left) == AOP_CRY &&
3170 AOP_TYPE (right) == AOP_CRY)
3172 /* Cant happen on the Z80 */
3177 /* subtract right from left if at the
3178 end the carry flag is set then we know that
3179 left is greater than right */
3180 size = max (AOP_SIZE (left), AOP_SIZE (right));
3182 /* if unsigned char cmp with lit, just compare */
3184 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3186 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3189 emit2 ("xor a,!immedbyte", 0x80);
3190 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3193 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3199 If the left or the right is a lit:
3200 Load -lit into HL, add to right via, check sense.
3202 if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3204 PAIR_ID id = PAIR_DE;
3205 asmop *lit = AOP (right);
3206 asmop *op = AOP (left);
3209 if (AOP_TYPE (left) == AOP_LIT)
3217 emit2 ("ld e,%s", aopGet (op, 0, 0));
3218 emit2 ("ld a,%s", aopGet (op, 1, 0));
3219 emit2 ("xor a,!immedbyte", 0x80);
3224 id = getPairId (op);
3225 if (id == PAIR_INVALID)
3227 fetchPair (PAIR_DE, op);
3231 spillPair (PAIR_HL);
3232 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3233 emit2 ("add hl,%s", _getPairIdName (id));
3236 if (AOP_TYPE (right) == AOP_LIT)
3238 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3239 /* optimize if(x < 0) or if(x >= 0) */
3244 /* No sign so it's always false */
3249 /* Just load in the top most bit */
3250 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3251 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3253 genIfxJump (ifx, "7");
3264 /* First setup h and l contaning the top most bytes XORed */
3265 bool fDidXor = FALSE;
3266 if (AOP_TYPE (left) == AOP_LIT)
3268 unsigned long lit = (unsigned long)
3269 floatFromVal (AOP (left)->aopu.aop_lit);
3270 emit2 ("ld %s,!immedbyte", _fTmp[0],
3271 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3275 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3276 emit2 ("xor a,!immedbyte", 0x80);
3277 emit2 ("ld %s,a", _fTmp[0]);
3280 if (AOP_TYPE (right) == AOP_LIT)
3282 unsigned long lit = (unsigned long)
3283 floatFromVal (AOP (right)->aopu.aop_lit);
3284 emit2 ("ld %s,!immedbyte", _fTmp[1],
3285 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3289 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3290 emit2 ("xor a,!immedbyte", 0x80);
3291 emit2 ("ld %s,a", _fTmp[1]);
3303 /* Do a long subtract */
3306 _moveA (aopGet (AOP (left), offset, FALSE));
3308 if (sign && size == 0)
3310 emit2 ("ld a,%s", _fTmp[0]);
3311 emit2 ("sbc a,%s", _fTmp[1]);
3315 /* Subtract through, propagating the carry */
3316 emit2 ("sbc a,%s", aopGet (AOP (right), offset++, FALSE));
3323 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3325 outBitCLong (result, swap_sense);
3329 /* if the result is used in the next
3330 ifx conditional branch then generate
3331 code a little differently */
3333 genIfxJump (ifx, swap_sense ? "nc" : "c");
3335 outBitCLong (result, swap_sense);
3336 /* leave the result in acc */
3340 /*-----------------------------------------------------------------*/
3341 /* genCmpGt :- greater than comparison */
3342 /*-----------------------------------------------------------------*/
3344 genCmpGt (iCode * ic, iCode * ifx)
3346 operand *left, *right, *result;
3347 sym_link *letype, *retype;
3350 left = IC_LEFT (ic);
3351 right = IC_RIGHT (ic);
3352 result = IC_RESULT (ic);
3354 letype = getSpec (operandType (left));
3355 retype = getSpec (operandType (right));
3356 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3357 /* assign the amsops */
3358 aopOp (left, ic, FALSE, FALSE);
3359 aopOp (right, ic, FALSE, FALSE);
3360 aopOp (result, ic, TRUE, FALSE);
3362 genCmp (right, left, result, ifx, sign);
3364 freeAsmop (left, NULL, ic);
3365 freeAsmop (right, NULL, ic);
3366 freeAsmop (result, NULL, ic);
3369 /*-----------------------------------------------------------------*/
3370 /* genCmpLt - less than comparisons */
3371 /*-----------------------------------------------------------------*/
3373 genCmpLt (iCode * ic, iCode * ifx)
3375 operand *left, *right, *result;
3376 sym_link *letype, *retype;
3379 left = IC_LEFT (ic);
3380 right = IC_RIGHT (ic);
3381 result = IC_RESULT (ic);
3383 letype = getSpec (operandType (left));
3384 retype = getSpec (operandType (right));
3385 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3387 /* assign the amsops */
3388 aopOp (left, ic, FALSE, FALSE);
3389 aopOp (right, ic, FALSE, FALSE);
3390 aopOp (result, ic, TRUE, FALSE);
3392 genCmp (left, right, result, ifx, sign);
3394 freeAsmop (left, NULL, ic);
3395 freeAsmop (right, NULL, ic);
3396 freeAsmop (result, NULL, ic);
3399 /*-----------------------------------------------------------------*/
3400 /* gencjneshort - compare and jump if not equal */
3401 /*-----------------------------------------------------------------*/
3403 gencjneshort (operand * left, operand * right, symbol * lbl)
3405 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3407 unsigned long lit = 0L;
3409 /* Swap the left and right if it makes the computation easier */
3410 if (AOP_TYPE (left) == AOP_LIT)
3417 if (AOP_TYPE (right) == AOP_LIT)
3418 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3420 /* if the right side is a literal then anything goes */
3421 if (AOP_TYPE (right) == AOP_LIT &&
3422 AOP_TYPE (left) != AOP_DIR)
3426 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3433 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
3440 emit2 ("jp nz,!tlabel", lbl->key + 100);
3446 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3447 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3450 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3451 emit2 ("jp nz,!tlabel", lbl->key + 100);
3456 /* if the right side is in a register or in direct space or
3457 if the left is a pointer register & right is not */
3458 else if (AOP_TYPE (right) == AOP_REG ||
3459 AOP_TYPE (right) == AOP_DIR ||
3460 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3464 _moveA (aopGet (AOP (left), offset, FALSE));
3465 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3466 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3468 emit2 ("jp nz,!tlabel", lbl->key + 100);
3471 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3472 emit2 ("jp nz,!tlabel", lbl->key + 100);
3479 /* right is a pointer reg need both a & b */
3480 /* PENDING: is this required? */
3483 _moveA (aopGet (AOP (right), offset, FALSE));
3484 emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
3485 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3491 /*-----------------------------------------------------------------*/
3492 /* gencjne - compare and jump if not equal */
3493 /*-----------------------------------------------------------------*/
3495 gencjne (operand * left, operand * right, symbol * lbl)
3497 symbol *tlbl = newiTempLabel (NULL);
3499 gencjneshort (left, right, lbl);
3502 emit2 ("ld a,!one");
3503 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3504 emitLabel (lbl->key + 100);
3506 emitLabel (tlbl->key + 100);
3509 /*-----------------------------------------------------------------*/
3510 /* genCmpEq - generates code for equal to */
3511 /*-----------------------------------------------------------------*/
3513 genCmpEq (iCode * ic, iCode * ifx)
3515 operand *left, *right, *result;
3517 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3518 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3519 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3521 emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3523 /* Swap operands if it makes the operation easier. ie if:
3524 1. Left is a literal.
3526 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3528 operand *t = IC_RIGHT (ic);
3529 IC_RIGHT (ic) = IC_LEFT (ic);
3533 if (ifx && !AOP_SIZE (result))
3536 /* if they are both bit variables */
3537 if (AOP_TYPE (left) == AOP_CRY &&
3538 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3544 tlbl = newiTempLabel (NULL);
3545 gencjneshort (left, right, tlbl);
3548 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3549 emitLabel (tlbl->key + 100);
3553 /* PENDING: do this better */
3554 symbol *lbl = newiTempLabel (NULL);
3555 emit2 ("!shortjp !tlabel", lbl->key + 100);
3556 emitLabel (tlbl->key + 100);
3557 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3558 emitLabel (lbl->key + 100);
3561 /* mark the icode as generated */
3566 /* if they are both bit variables */
3567 if (AOP_TYPE (left) == AOP_CRY &&
3568 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3574 gencjne (left, right, newiTempLabel (NULL));
3575 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3581 genIfxJump (ifx, "a");
3584 /* if the result is used in an arithmetic operation
3585 then put the result in place */
3586 if (AOP_TYPE (result) != AOP_CRY)
3590 /* leave the result in acc */
3594 freeAsmop (left, NULL, ic);
3595 freeAsmop (right, NULL, ic);
3596 freeAsmop (result, NULL, ic);
3599 /*-----------------------------------------------------------------*/
3600 /* ifxForOp - returns the icode containing the ifx for operand */
3601 /*-----------------------------------------------------------------*/
3603 ifxForOp (operand * op, iCode * ic)
3605 /* if true symbol then needs to be assigned */
3606 if (IS_TRUE_SYMOP (op))
3609 /* if this has register type condition and
3610 the next instruction is ifx with the same operand
3611 and live to of the operand is upto the ifx only then */
3613 ic->next->op == IFX &&
3614 IC_COND (ic->next)->key == op->key &&
3615 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3621 /*-----------------------------------------------------------------*/
3622 /* genAndOp - for && operation */
3623 /*-----------------------------------------------------------------*/
3625 genAndOp (iCode * ic)
3627 operand *left, *right, *result;
3630 /* note here that && operations that are in an if statement are
3631 taken away by backPatchLabels only those used in arthmetic
3632 operations remain */
3633 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3634 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3635 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3637 /* if both are bit variables */
3638 if (AOP_TYPE (left) == AOP_CRY &&
3639 AOP_TYPE (right) == AOP_CRY)
3645 tlbl = newiTempLabel (NULL);
3647 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3649 emitLabel (tlbl->key + 100);
3653 freeAsmop (left, NULL, ic);
3654 freeAsmop (right, NULL, ic);
3655 freeAsmop (result, NULL, ic);
3658 /*-----------------------------------------------------------------*/
3659 /* genOrOp - for || operation */
3660 /*-----------------------------------------------------------------*/
3662 genOrOp (iCode * ic)
3664 operand *left, *right, *result;
3667 /* note here that || operations that are in an
3668 if statement are taken away by backPatchLabels
3669 only those used in arthmetic operations remain */
3670 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3671 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3672 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3674 /* if both are bit variables */
3675 if (AOP_TYPE (left) == AOP_CRY &&
3676 AOP_TYPE (right) == AOP_CRY)
3682 tlbl = newiTempLabel (NULL);
3684 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3686 emitLabel (tlbl->key + 100);
3690 freeAsmop (left, NULL, ic);
3691 freeAsmop (right, NULL, ic);
3692 freeAsmop (result, NULL, ic);
3695 /*-----------------------------------------------------------------*/
3696 /* isLiteralBit - test if lit == 2^n */
3697 /*-----------------------------------------------------------------*/
3699 isLiteralBit (unsigned long lit)
3701 unsigned long pw[32] =
3702 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3703 0x100L, 0x200L, 0x400L, 0x800L,
3704 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3705 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3706 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3707 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3708 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3711 for (idx = 0; idx < 32; idx++)
3717 /*-----------------------------------------------------------------*/
3718 /* jmpTrueOrFalse - */
3719 /*-----------------------------------------------------------------*/
3721 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3723 // ugly but optimized by peephole
3726 symbol *nlbl = newiTempLabel (NULL);
3727 emit2 ("jp !tlabel", nlbl->key + 100);
3728 emitLabel (tlbl->key + 100);
3729 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3730 emitLabel (nlbl->key + 100);
3734 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3735 emitLabel (tlbl->key + 100);
3740 /*-----------------------------------------------------------------*/
3741 /* genAnd - code for and */
3742 /*-----------------------------------------------------------------*/
3744 genAnd (iCode * ic, iCode * ifx)
3746 operand *left, *right, *result;
3747 int size, offset = 0;
3748 unsigned long lit = 0L;
3751 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3752 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3753 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3756 emitDebug ("; Type res[%d] = l[%d]&r[%d]",
3758 AOP_TYPE (left), AOP_TYPE (right));
3759 emitDebug ("; Size res[%d] = l[%d]&r[%d]",
3761 AOP_SIZE (left), AOP_SIZE (right));
3764 /* if left is a literal & right is not then exchange them */
3765 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3766 AOP_NEEDSACC (left))
3768 operand *tmp = right;
3773 /* if result = right then exchange them */
3774 if (sameRegs (AOP (result), AOP (right)))
3776 operand *tmp = right;
3781 /* if right is bit then exchange them */
3782 if (AOP_TYPE (right) == AOP_CRY &&
3783 AOP_TYPE (left) != AOP_CRY)
3785 operand *tmp = right;
3789 if (AOP_TYPE (right) == AOP_LIT)
3790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3792 size = AOP_SIZE (result);
3794 if (AOP_TYPE (left) == AOP_CRY)
3800 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3801 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3802 if ((AOP_TYPE (right) == AOP_LIT) &&
3803 (AOP_TYPE (result) == AOP_CRY) &&
3804 (AOP_TYPE (left) != AOP_CRY))
3806 int posbit = isLiteralBit (lit);
3811 _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
3816 emit2 ("mov c,acc.%d", posbit & 0x07);
3823 sprintf (buffer, "%d", posbit & 0x07);
3824 genIfxJump (ifx, buffer);
3835 symbol *tlbl = newiTempLabel (NULL);
3836 int sizel = AOP_SIZE (left);
3844 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3846 _moveA (aopGet (AOP (left), offset, FALSE));
3848 if ((posbit = isLiteralBit (bytelit)) != 0)
3851 emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3855 if (bytelit != 0x0FFL)
3857 aopGet (AOP (right), offset, FALSE));
3861 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3866 // bit = left & literal
3870 emit2 ("!tlabeldef", tlbl->key + 100);
3872 // if(left & literal)
3876 jmpTrueOrFalse (ifx, tlbl);
3884 /* if left is same as result */
3885 if (sameRegs (AOP (result), AOP (left)))
3887 for (; size--; offset++)
3889 if (AOP_TYPE (right) == AOP_LIT)
3891 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3896 aopPut (AOP (result), "!zero", offset);
3899 _moveA (aopGet (AOP (left), offset, FALSE));
3901 aopGet (AOP (right), offset, FALSE));
3902 aopPut (AOP (left), "a", offset);
3909 if (AOP_TYPE (left) == AOP_ACC)
3915 _moveA (aopGet (AOP (left), offset, FALSE));
3917 aopGet (AOP (right), offset, FALSE));
3918 aopPut (AOP (left), "a", offset);
3925 // left & result in different registers
3926 if (AOP_TYPE (result) == AOP_CRY)
3932 for (; (size--); offset++)
3935 // result = left & right
3936 if (AOP_TYPE (right) == AOP_LIT)
3938 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3940 aopPut (AOP (result),
3941 aopGet (AOP (left), offset, FALSE),
3945 else if (bytelit == 0)
3947 aopPut (AOP (result), "!zero", offset);
3951 // faster than result <- left, anl result,right
3952 // and better if result is SFR
3953 if (AOP_TYPE (left) == AOP_ACC)
3954 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
3957 _moveA (aopGet (AOP (left), offset, FALSE));
3959 aopGet (AOP (right), offset, FALSE));
3961 aopPut (AOP (result), "a", offset);
3968 freeAsmop (left, NULL, ic);
3969 freeAsmop (right, NULL, ic);
3970 freeAsmop (result, NULL, ic);
3973 /*-----------------------------------------------------------------*/
3974 /* genOr - code for or */
3975 /*-----------------------------------------------------------------*/
3977 genOr (iCode * ic, iCode * ifx)
3979 operand *left, *right, *result;
3980 int size, offset = 0;
3981 unsigned long lit = 0L;
3983 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3984 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3985 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3988 emitDebug ("; Type res[%d] = l[%d]&r[%d]",
3990 AOP_TYPE (left), AOP_TYPE (right));
3991 emitDebug ("; Size res[%d] = l[%d]&r[%d]",
3993 AOP_SIZE (left), AOP_SIZE (right));
3996 /* if left is a literal & right is not then exchange them */
3997 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3998 AOP_NEEDSACC (left))
4000 operand *tmp = right;
4005 /* if result = right then exchange them */
4006 if (sameRegs (AOP (result), AOP (right)))
4008 operand *tmp = right;
4013 /* if right is bit then exchange them */
4014 if (AOP_TYPE (right) == AOP_CRY &&
4015 AOP_TYPE (left) != AOP_CRY)
4017 operand *tmp = right;
4021 if (AOP_TYPE (right) == AOP_LIT)
4022 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4024 size = AOP_SIZE (result);
4026 if (AOP_TYPE (left) == AOP_CRY)
4032 if ((AOP_TYPE (right) == AOP_LIT) &&
4033 (AOP_TYPE (result) == AOP_CRY) &&
4034 (AOP_TYPE (left) != AOP_CRY))
4040 /* if left is same as result */
4041 if (sameRegs (AOP (result), AOP (left)))
4043 for (; size--; offset++)
4045 if (AOP_TYPE (right) == AOP_LIT)
4047 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4051 _moveA (aopGet (AOP (left), offset, FALSE));
4053 aopGet (AOP (right), offset, FALSE));
4054 aopPut (AOP (result), "a", offset);
4059 if (AOP_TYPE (left) == AOP_ACC)
4060 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4063 _moveA (aopGet (AOP (left), offset, FALSE));
4065 aopGet (AOP (right), offset, FALSE));
4066 aopPut (AOP (result), "a", offset);
4073 // left & result in different registers
4074 if (AOP_TYPE (result) == AOP_CRY)
4079 for (; (size--); offset++)
4082 // result = left & right
4083 if (AOP_TYPE (right) == AOP_LIT)
4085 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4087 aopPut (AOP (result),
4088 aopGet (AOP (left), offset, FALSE),
4093 // faster than result <- left, anl result,right
4094 // and better if result is SFR
4095 if (AOP_TYPE (left) == AOP_ACC)
4096 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4099 _moveA (aopGet (AOP (left), offset, FALSE));
4101 aopGet (AOP (right), offset, FALSE));
4103 aopPut (AOP (result), "a", offset);
4104 /* PENDING: something weird is going on here. Add exception. */
4105 if (AOP_TYPE (result) == AOP_ACC)
4111 freeAsmop (left, NULL, ic);
4112 freeAsmop (right, NULL, ic);
4113 freeAsmop (result, NULL, ic);
4116 /*-----------------------------------------------------------------*/
4117 /* genXor - code for xclusive or */
4118 /*-----------------------------------------------------------------*/
4120 genXor (iCode * ic, iCode * ifx)
4122 operand *left, *right, *result;
4123 int size, offset = 0;
4124 unsigned long lit = 0L;
4126 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4127 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4128 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4130 /* if left is a literal & right is not then exchange them */
4131 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4132 AOP_NEEDSACC (left))
4134 operand *tmp = right;
4139 /* if result = right then exchange them */
4140 if (sameRegs (AOP (result), AOP (right)))
4142 operand *tmp = right;
4147 /* if right is bit then exchange them */
4148 if (AOP_TYPE (right) == AOP_CRY &&
4149 AOP_TYPE (left) != AOP_CRY)
4151 operand *tmp = right;
4155 if (AOP_TYPE (right) == AOP_LIT)
4156 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4158 size = AOP_SIZE (result);
4160 if (AOP_TYPE (left) == AOP_CRY)
4166 if ((AOP_TYPE (right) == AOP_LIT) &&
4167 (AOP_TYPE (result) == AOP_CRY) &&
4168 (AOP_TYPE (left) != AOP_CRY))
4174 /* if left is same as result */
4175 if (sameRegs (AOP (result), AOP (left)))
4177 for (; size--; offset++)
4179 if (AOP_TYPE (right) == AOP_LIT)
4181 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4185 _moveA (aopGet (AOP (right), offset, FALSE));
4187 aopGet (AOP (left), offset, FALSE));
4188 aopPut (AOP (result), "a", offset);
4193 if (AOP_TYPE (left) == AOP_ACC)
4195 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4199 _moveA (aopGet (AOP (right), offset, FALSE));
4201 aopGet (AOP (left), offset, FALSE));
4202 aopPut (AOP (result), "a", 0);
4209 // left & result in different registers
4210 if (AOP_TYPE (result) == AOP_CRY)
4215 for (; (size--); offset++)
4218 // result = left & right
4219 if (AOP_TYPE (right) == AOP_LIT)
4221 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4223 aopPut (AOP (result),
4224 aopGet (AOP (left), offset, FALSE),
4229 // faster than result <- left, anl result,right
4230 // and better if result is SFR
4231 if (AOP_TYPE (left) == AOP_ACC)
4233 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4237 _moveA (aopGet (AOP (right), offset, FALSE));
4239 aopGet (AOP (left), offset, FALSE));
4241 aopPut (AOP (result), "a", offset);
4246 freeAsmop (left, NULL, ic);
4247 freeAsmop (right, NULL, ic);
4248 freeAsmop (result, NULL, ic);
4251 /*-----------------------------------------------------------------*/
4252 /* genInline - write the inline code out */
4253 /*-----------------------------------------------------------------*/
4255 genInline (iCode * ic)
4257 char *buffer, *bp, *bp1;
4259 _G.lines.isInline += (!options.asmpeep);
4261 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4262 strcpy (buffer, IC_INLINE (ic));
4264 /* emit each line as a code */
4289 _G.lines.isInline -= (!options.asmpeep);
4293 /*-----------------------------------------------------------------*/
4294 /* genRRC - rotate right with carry */
4295 /*-----------------------------------------------------------------*/
4302 /*-----------------------------------------------------------------*/
4303 /* genRLC - generate code for rotate left with carry */
4304 /*-----------------------------------------------------------------*/
4311 /*-----------------------------------------------------------------*/
4312 /* genGetHbit - generates code get highest order bit */
4313 /*-----------------------------------------------------------------*/
4315 genGetHbit (iCode * ic)
4317 operand *left, *result;
4318 left = IC_LEFT (ic);
4319 result = IC_RESULT (ic);
4320 aopOp (left, ic, FALSE, FALSE);
4321 aopOp (result, ic, FALSE, FALSE);
4323 /* get the highest order byte into a */
4324 emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4326 if (AOP_TYPE (result) == AOP_CRY)
4334 /* PENDING: For re-target. */
4340 freeAsmop (left, NULL, ic);
4341 freeAsmop (result, NULL, ic);
4345 emitRsh2 (asmop *aop, int size, int is_signed)
4351 const char *l = aopGet (aop, size, FALSE);
4354 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4364 /*-----------------------------------------------------------------*/
4365 /* shiftR2Left2Result - shift right two bytes from left to result */
4366 /*-----------------------------------------------------------------*/
4368 shiftR2Left2Result (operand * left, int offl,
4369 operand * result, int offr,
4370 int shCount, int is_signed)
4373 symbol *tlbl, *tlbl1;
4375 movLeft2Result (left, offl, result, offr, 0);
4376 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4378 /* if (AOP(result)->type == AOP_REG) { */
4380 tlbl = newiTempLabel (NULL);
4381 tlbl1 = newiTempLabel (NULL);
4383 /* Left is already in result - so now do the shift */
4388 emitRsh2 (AOP (result), size, is_signed);
4393 emit2 ("ld a,!immedbyte+1", shCount);
4394 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4395 emitLabel (tlbl->key + 100);
4397 emitRsh2 (AOP (result), size, is_signed);
4399 emitLabel (tlbl1->key + 100);
4401 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4405 /*-----------------------------------------------------------------*/
4406 /* shiftL2Left2Result - shift left two bytes from left to result */
4407 /*-----------------------------------------------------------------*/
4409 shiftL2Left2Result (operand * left, int offl,
4410 operand * result, int offr, int shCount)
4412 if (sameRegs (AOP (result), AOP (left)) &&
4413 ((offl + MSB16) == offr))
4419 /* Copy left into result */
4420 movLeft2Result (left, offl, result, offr, 0);
4421 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4423 /* PENDING: for now just see if it'll work. */
4424 /*if (AOP(result)->type == AOP_REG) { */
4428 symbol *tlbl, *tlbl1;
4431 tlbl = newiTempLabel (NULL);
4432 tlbl1 = newiTempLabel (NULL);
4434 /* Left is already in result - so now do the shift */
4437 emit2 ("ld a,!immedbyte+1", shCount);
4438 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4439 emitLabel (tlbl->key + 100);
4445 l = aopGet (AOP (result), offset, FALSE);
4453 emitLabel (tlbl1->key + 100);
4455 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4460 /*-----------------------------------------------------------------*/
4461 /* AccRol - rotate left accumulator by known count */
4462 /*-----------------------------------------------------------------*/
4464 AccRol (int shCount)
4466 shCount &= 0x0007; // shCount : 0..7
4505 /*-----------------------------------------------------------------*/
4506 /* AccLsh - left shift accumulator by known count */
4507 /*-----------------------------------------------------------------*/
4509 AccLsh (int shCount)
4511 static const unsigned char SLMask[] =
4513 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4522 else if (shCount == 2)
4529 /* rotate left accumulator */
4531 /* and kill the lower order bits */
4532 emit2 ("and a,!immedbyte", SLMask[shCount]);
4537 /*-----------------------------------------------------------------*/
4538 /* shiftL1Left2Result - shift left one byte from left to result */
4539 /*-----------------------------------------------------------------*/
4541 shiftL1Left2Result (operand * left, int offl,
4542 operand * result, int offr, int shCount)
4545 l = aopGet (AOP (left), offl, FALSE);
4547 /* shift left accumulator */
4549 aopPut (AOP (result), "a", offr);
4553 /*-----------------------------------------------------------------*/
4554 /* genlshTwo - left shift two bytes by known amount != 0 */
4555 /*-----------------------------------------------------------------*/
4557 genlshTwo (operand * result, operand * left, int shCount)
4559 int size = AOP_SIZE (result);
4561 wassert (size == 2);
4563 /* if shCount >= 8 */
4571 movLeft2Result (left, LSB, result, MSB16, 0);
4572 aopPut (AOP (result), "!zero", 0);
4573 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4577 movLeft2Result (left, LSB, result, MSB16, 0);
4578 aopPut (AOP (result), "!zero", 0);
4583 aopPut (AOP (result), "!zero", LSB);
4586 /* 1 <= shCount <= 7 */
4595 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4600 /*-----------------------------------------------------------------*/
4601 /* genlshOne - left shift a one byte quantity by known count */
4602 /*-----------------------------------------------------------------*/
4604 genlshOne (operand * result, operand * left, int shCount)
4606 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4609 /*-----------------------------------------------------------------*/
4610 /* genLeftShiftLiteral - left shifting by known count */
4611 /*-----------------------------------------------------------------*/
4613 genLeftShiftLiteral (operand * left,
4618 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4621 freeAsmop (right, NULL, ic);
4623 aopOp (left, ic, FALSE, FALSE);
4624 aopOp (result, ic, FALSE, FALSE);
4626 size = getSize (operandType (result));
4629 emitDebug ("; shift left result %d, left %d", size,
4633 /* I suppose that the left size >= result size */
4639 else if (shCount >= (size * 8))
4643 aopPut (AOP (result), "!zero", size);
4651 genlshOne (result, left, shCount);
4654 genlshTwo (result, left, shCount);
4657 wassertl (0, "Shifting of longs is currently unsupported");
4663 freeAsmop (left, NULL, ic);
4664 freeAsmop (result, NULL, ic);
4667 /*-----------------------------------------------------------------*/
4668 /* genLeftShift - generates code for left shifting */
4669 /*-----------------------------------------------------------------*/
4671 genLeftShift (iCode * ic)
4675 symbol *tlbl, *tlbl1;
4676 operand *left, *right, *result;
4678 right = IC_RIGHT (ic);
4679 left = IC_LEFT (ic);
4680 result = IC_RESULT (ic);
4682 aopOp (right, ic, FALSE, FALSE);
4684 /* if the shift count is known then do it
4685 as efficiently as possible */
4686 if (AOP_TYPE (right) == AOP_LIT)
4688 genLeftShiftLiteral (left, right, result, ic);
4692 /* shift count is unknown then we have to form a loop get the loop
4693 count in B : Note: we take only the lower order byte since
4694 shifting more that 32 bits make no sense anyway, ( the largest
4695 size of an object can be only 32 bits ) */
4696 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4698 freeAsmop (right, NULL, ic);
4699 aopOp (left, ic, FALSE, FALSE);
4700 aopOp (result, ic, FALSE, FALSE);
4702 /* now move the left to the result if they are not the
4705 if (!sameRegs (AOP (left), AOP (result)))
4708 size = AOP_SIZE (result);
4712 l = aopGet (AOP (left), offset, FALSE);
4713 aopPut (AOP (result), l, offset);
4718 size = AOP_SIZE (result);
4722 l = aopGet (AOP (left), offset, FALSE);
4723 aopPut (AOP (result), l, offset);
4729 tlbl = newiTempLabel (NULL);
4730 size = AOP_SIZE (result);
4732 tlbl1 = newiTempLabel (NULL);
4734 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4735 emitLabel (tlbl->key + 100);
4736 l = aopGet (AOP (result), offset, FALSE);
4742 l = aopGet (AOP (result), offset++, FALSE);
4745 emitLabel (tlbl1->key + 100);
4747 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4749 freeAsmop (left, NULL, ic);
4750 freeAsmop (result, NULL, ic);
4753 /*-----------------------------------------------------------------*/
4754 /* genrshOne - left shift two bytes by known amount != 0 */
4755 /*-----------------------------------------------------------------*/
4757 genrshOne (operand * result, operand * left, int shCount, int is_signed)
4760 int size = AOP_SIZE (result);
4763 wassert (size == 1);
4764 wassert (shCount < 8);
4766 l = aopGet (AOP (left), 0, FALSE);
4770 if (AOP (result)->type == AOP_REG)
4772 aopPut (AOP (result), l, 0);
4773 l = aopGet (AOP (result), 0, FALSE);
4776 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4784 emit2 ("%s a", is_signed ? "sra" : "srl");
4786 aopPut (AOP (result), "a", 0);
4790 /*-----------------------------------------------------------------*/
4791 /* AccRsh - right shift accumulator by known count */
4792 /*-----------------------------------------------------------------*/
4794 AccRsh (int shCount)
4796 static const unsigned char SRMask[] =
4798 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4803 /* rotate right accumulator */
4804 AccRol (8 - shCount);
4805 /* and kill the higher order bits */
4806 emit2 ("and a,!immedbyte", SRMask[shCount]);
4810 /*-----------------------------------------------------------------*/
4811 /* shiftR1Left2Result - shift right one byte from left to result */
4812 /*-----------------------------------------------------------------*/
4814 shiftR1Left2Result (operand * left, int offl,
4815 operand * result, int offr,
4816 int shCount, int sign)
4818 _moveA (aopGet (AOP (left), offl, FALSE));
4827 aopPut (AOP (result), "a", offr);
4830 /*-----------------------------------------------------------------*/
4831 /* genrshTwo - right shift two bytes by known amount != 0 */
4832 /*-----------------------------------------------------------------*/
4834 genrshTwo (operand * result, operand * left,
4835 int shCount, int sign)
4837 /* if shCount >= 8 */
4843 shiftR1Left2Result (left, MSB16, result, LSB,
4848 movLeft2Result (left, MSB16, result, LSB, sign);
4850 aopPut (AOP (result), "!zero", 1);
4852 /* 1 <= shCount <= 7 */
4855 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4859 /*-----------------------------------------------------------------*/
4860 /* genRightShiftLiteral - left shifting by known count */
4861 /*-----------------------------------------------------------------*/
4863 genRightShiftLiteral (operand * left,
4869 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4872 freeAsmop (right, NULL, ic);
4874 aopOp (left, ic, FALSE, FALSE);
4875 aopOp (result, ic, FALSE, FALSE);
4877 size = getSize (operandType (result));
4879 emitDebug ("; shift right result %d, left %d", size,
4882 /* I suppose that the left size >= result size */
4888 else if (shCount >= (size * 8))
4890 aopPut (AOP (result), "!zero", size);
4896 genrshOne (result, left, shCount, sign);
4899 /* PENDING: sign support */
4900 genrshTwo (result, left, shCount, sign);
4903 wassertl (0, "Asked to shift right a long which should be a function call");
4906 wassertl (0, "Entered default case in right shift delegate");
4909 freeAsmop (left, NULL, ic);
4910 freeAsmop (result, NULL, ic);
4913 /*-----------------------------------------------------------------*/
4914 /* genRightShift - generate code for right shifting */
4915 /*-----------------------------------------------------------------*/
4917 genRightShift (iCode * ic)
4919 operand *right, *left, *result;
4921 int size, offset, first = 1;
4925 symbol *tlbl, *tlbl1;
4927 /* if signed then we do it the hard way preserve the
4928 sign bit moving it inwards */
4929 retype = getSpec (operandType (IC_RESULT (ic)));
4931 is_signed = !SPEC_USIGN (retype);
4933 /* signed & unsigned types are treated the same : i.e. the
4934 signed is NOT propagated inwards : quoting from the
4935 ANSI - standard : "for E1 >> E2, is equivalent to division
4936 by 2**E2 if unsigned or if it has a non-negative value,
4937 otherwise the result is implementation defined ", MY definition
4938 is that the sign does not get propagated */
4940 right = IC_RIGHT (ic);
4941 left = IC_LEFT (ic);
4942 result = IC_RESULT (ic);
4944 aopOp (right, ic, FALSE, FALSE);
4946 /* if the shift count is known then do it
4947 as efficiently as possible */
4948 if (AOP_TYPE (right) == AOP_LIT)
4950 genRightShiftLiteral (left, right, result, ic, is_signed);
4954 aopOp (left, ic, FALSE, FALSE);
4955 aopOp (result, ic, FALSE, FALSE);
4957 /* now move the left to the result if they are not the
4959 if (!sameRegs (AOP (left), AOP (result)) &&
4960 AOP_SIZE (result) > 1)
4963 size = AOP_SIZE (result);
4967 l = aopGet (AOP (left), offset, FALSE);
4968 aopPut (AOP (result), l, offset);
4973 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4975 freeAsmop (right, NULL, ic);
4977 tlbl = newiTempLabel (NULL);
4978 tlbl1 = newiTempLabel (NULL);
4979 size = AOP_SIZE (result);
4982 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4983 emitLabel (tlbl->key + 100);
4986 l = aopGet (AOP (result), offset--, FALSE);
4989 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4997 emitLabel (tlbl1->key + 100);
4999 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5001 freeAsmop (left, NULL, ic);
5002 freeAsmop (result, NULL, ic);
5005 /*-----------------------------------------------------------------*/
5006 /* genGenPointerGet - get value from generic pointer space */
5007 /*-----------------------------------------------------------------*/
5009 genGenPointerGet (operand * left,
5010 operand * result, iCode * ic)
5013 sym_link *retype = getSpec (operandType (result));
5019 aopOp (left, ic, FALSE, FALSE);
5020 aopOp (result, ic, FALSE, FALSE);
5022 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
5025 if (isPtrPair (AOP (left)))
5027 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
5028 aopPut (AOP (result), buffer, 0);
5032 emit2 ("ld a,!*pair", getPairName (AOP (left)));
5033 aopPut (AOP (result), "a", 0);
5035 freeAsmop (left, NULL, ic);
5039 /* For now we always load into IY */
5040 /* if this is remateriazable */
5041 fetchPair (pair, AOP (left));
5043 /* so iy now contains the address */
5044 freeAsmop (left, NULL, ic);
5046 /* if bit then unpack */
5047 if (IS_BITVAR (retype))
5053 size = AOP_SIZE (result);
5058 /* PENDING: make this better */
5059 if (!IS_GB && AOP (result)->type == AOP_REG)
5061 aopPut (AOP (result), "!*hl", offset++);
5065 emit2 ("ld a,!*pair", _pairs[pair].name);
5066 aopPut (AOP (result), "a", offset++);
5070 emit2 ("inc %s", _pairs[pair].name);
5071 _G.pairs[pair].offset++;
5077 freeAsmop (result, NULL, ic);
5080 /*-----------------------------------------------------------------*/
5081 /* genPointerGet - generate code for pointer get */
5082 /*-----------------------------------------------------------------*/
5084 genPointerGet (iCode * ic)
5086 operand *left, *result;
5087 sym_link *type, *etype;
5089 left = IC_LEFT (ic);
5090 result = IC_RESULT (ic);
5092 /* depending on the type of pointer we need to
5093 move it to the correct pointer register */
5094 type = operandType (left);
5095 etype = getSpec (type);
5097 genGenPointerGet (left, result, ic);
5101 isRegOrLit (asmop * aop)
5103 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
5108 /*-----------------------------------------------------------------*/
5109 /* genGenPointerSet - stores the value into a pointer location */
5110 /*-----------------------------------------------------------------*/
5112 genGenPointerSet (operand * right,
5113 operand * result, iCode * ic)
5116 sym_link *retype = getSpec (operandType (right));
5117 PAIR_ID pairId = PAIR_HL;
5119 aopOp (result, ic, FALSE, FALSE);
5120 aopOp (right, ic, FALSE, FALSE);
5125 /* Handle the exceptions first */
5126 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5129 const char *l = aopGet (AOP (right), 0, FALSE);
5130 const char *pair = getPairName (AOP (result));
5131 if (canAssignToPtr (l) && isPtr (pair))
5133 emit2 ("ld !*pair,%s", pair, l);
5138 emit2 ("ld !*pair,a", pair);
5143 /* if the operand is already in dptr
5144 then we do nothing else we move the value to dptr */
5145 if (AOP_TYPE (result) != AOP_STR)
5147 fetchPair (pairId, AOP (result));
5149 /* so hl know contains the address */
5150 freeAsmop (result, NULL, ic);
5152 /* if bit then unpack */
5153 if (IS_BITVAR (retype))
5159 size = AOP_SIZE (right);
5164 const char *l = aopGet (AOP (right), offset, FALSE);
5165 if (isRegOrLit (AOP (right)) && !IS_GB)
5167 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5172 emit2 ("ld !*pair,a", _pairs[pairId].name);
5176 emit2 ("inc %s", _pairs[pairId].name);
5177 _G.pairs[pairId].offset++;
5183 freeAsmop (right, NULL, ic);
5186 /*-----------------------------------------------------------------*/
5187 /* genPointerSet - stores the value into a pointer location */
5188 /*-----------------------------------------------------------------*/
5190 genPointerSet (iCode * ic)
5192 operand *right, *result;
5193 sym_link *type, *etype;
5195 right = IC_RIGHT (ic);
5196 result = IC_RESULT (ic);
5198 /* depending on the type of pointer we need to
5199 move it to the correct pointer register */
5200 type = operandType (result);
5201 etype = getSpec (type);
5203 genGenPointerSet (right, result, ic);
5206 /*-----------------------------------------------------------------*/
5207 /* genIfx - generate code for Ifx statement */
5208 /*-----------------------------------------------------------------*/
5210 genIfx (iCode * ic, iCode * popIc)
5212 operand *cond = IC_COND (ic);
5215 aopOp (cond, ic, FALSE, TRUE);
5217 /* get the value into acc */
5218 if (AOP_TYPE (cond) != AOP_CRY)
5222 /* the result is now in the accumulator */
5223 freeAsmop (cond, NULL, ic);
5225 /* if there was something to be popped then do it */
5229 /* if the condition is a bit variable */
5230 if (isbit && IS_ITEMP (cond) &&
5232 genIfxJump (ic, SPIL_LOC (cond)->rname);
5233 else if (isbit && !IS_ITEMP (cond))
5234 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5236 genIfxJump (ic, "a");
5241 /*-----------------------------------------------------------------*/
5242 /* genAddrOf - generates code for address of */
5243 /*-----------------------------------------------------------------*/
5245 genAddrOf (iCode * ic)
5247 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5249 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5251 /* if the operand is on the stack then we
5252 need to get the stack offset of this
5259 if (sym->stack <= 0)
5261 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5265 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5272 emit2 ("ld de,!hashedstr", sym->rname);
5274 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5275 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5282 /* if it has an offset then we need to compute it */
5284 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5286 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5287 emit2 ("add hl,sp");
5291 emit2 ("ld hl,#%s", sym->rname);
5293 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5294 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5296 freeAsmop (IC_RESULT (ic), NULL, ic);
5299 /*-----------------------------------------------------------------*/
5300 /* genAssign - generate code for assignment */
5301 /*-----------------------------------------------------------------*/
5303 genAssign (iCode * ic)
5305 operand *result, *right;
5307 unsigned long lit = 0L;
5309 result = IC_RESULT (ic);
5310 right = IC_RIGHT (ic);
5313 /* Dont bother assigning if they are the same */
5314 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5316 emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5321 aopOp (right, ic, FALSE, FALSE);
5322 aopOp (result, ic, TRUE, FALSE);
5324 /* if they are the same registers */
5325 if (sameRegs (AOP (right), AOP (result)))
5327 emitDebug ("; (registers are the same)");
5331 /* if the result is a bit */
5332 if (AOP_TYPE (result) == AOP_CRY)
5338 size = AOP_SIZE (result);
5341 if (AOP_TYPE (right) == AOP_LIT)
5342 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5343 if (isPair (AOP (result)))
5345 fetchPair (getPairId (AOP (result)), AOP (right));
5347 else if ((size > 1) &&
5348 (AOP_TYPE (result) != AOP_REG) &&
5349 (AOP_TYPE (right) == AOP_LIT) &&
5350 !IS_FLOAT (operandType (right)) &&
5353 bool fXored = FALSE;
5355 /* Work from the top down.
5356 Done this way so that we can use the cached copy of 0
5357 in A for a fast clear */
5360 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5362 if (!fXored && size > 1)
5369 aopPut (AOP (result), "a", offset);
5373 aopPut (AOP (result), "!zero", offset);
5377 aopPut (AOP (result),
5378 aopGet (AOP (right), offset, FALSE),
5383 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5385 /* Special case. Load into a and d, then load out. */
5386 _moveA (aopGet (AOP (right), 0, FALSE));
5387 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5388 aopPut (AOP (result), "a", 0);
5389 aopPut (AOP (result), "e", 1);
5395 /* PENDING: do this check better */
5396 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5398 _moveA (aopGet (AOP (right), offset, FALSE));
5399 aopPut (AOP (result), "a", offset);
5402 aopPut (AOP (result),
5403 aopGet (AOP (right), offset, FALSE),
5410 freeAsmop (right, NULL, ic);
5411 freeAsmop (result, NULL, ic);
5414 /*-----------------------------------------------------------------*/
5415 /* genJumpTab - genrates code for jump table */
5416 /*-----------------------------------------------------------------*/
5418 genJumpTab (iCode * ic)
5423 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5424 /* get the condition into accumulator */
5425 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5428 emit2 ("ld e,%s", l);
5429 emit2 ("ld d,!zero");
5430 jtab = newiTempLabel (NULL);
5432 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5433 emit2 ("add hl,de");
5434 emit2 ("add hl,de");
5435 emit2 ("add hl,de");
5436 freeAsmop (IC_JTCOND (ic), NULL, ic);
5440 emitLabel (jtab->key + 100);
5441 /* now generate the jump labels */
5442 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5443 jtab = setNextItem (IC_JTLABELS (ic)))
5444 emit2 ("jp !tlabel", jtab->key + 100);
5447 /*-----------------------------------------------------------------*/
5448 /* genCast - gen code for casting */
5449 /*-----------------------------------------------------------------*/
5451 genCast (iCode * ic)
5453 operand *result = IC_RESULT (ic);
5454 sym_link *ctype = operandType (IC_LEFT (ic));
5455 operand *right = IC_RIGHT (ic);
5458 /* if they are equivalent then do nothing */
5459 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5462 aopOp (right, ic, FALSE, FALSE);
5463 aopOp (result, ic, FALSE, FALSE);
5465 /* if the result is a bit */
5466 if (AOP_TYPE (result) == AOP_CRY)
5471 /* if they are the same size : or less */
5472 if (AOP_SIZE (result) <= AOP_SIZE (right))
5475 /* if they are in the same place */
5476 if (sameRegs (AOP (right), AOP (result)))
5479 /* if they in different places then copy */
5480 size = AOP_SIZE (result);
5484 aopPut (AOP (result),
5485 aopGet (AOP (right), offset, FALSE),
5492 /* PENDING: should be OK. */
5494 /* if the result is of type pointer */
5501 /* so we now know that the size of destination is greater
5502 than the size of the source */
5503 /* we move to result for the size of source */
5504 size = AOP_SIZE (right);
5508 aopPut (AOP (result),
5509 aopGet (AOP (right), offset, FALSE),
5514 /* now depending on the sign of the destination */
5515 size = AOP_SIZE (result) - AOP_SIZE (right);
5516 /* Unsigned or not an integral type - right fill with zeros */
5517 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5520 aopPut (AOP (result), "!zero", offset++);
5524 /* we need to extend the sign :{ */
5525 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5528 emitDebug ("; genCast: sign extend untested.");
5532 aopPut (AOP (result), "a", offset++);
5536 freeAsmop (right, NULL, ic);
5537 freeAsmop (result, NULL, ic);
5540 /*-----------------------------------------------------------------*/
5541 /* genReceive - generate code for a receive iCode */
5542 /*-----------------------------------------------------------------*/
5544 genReceive (iCode * ic)
5546 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5547 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5548 IS_TRUE_SYMOP (IC_RESULT (ic))))
5558 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5559 size = AOP_SIZE(IC_RESULT(ic));
5561 for (i = 0; i < size; i++) {
5562 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5566 freeAsmop (IC_RESULT (ic), NULL, ic);
5569 /*-----------------------------------------------------------------*/
5570 /* genZ80Code - generate code for Z80 based controllers */
5571 /*-----------------------------------------------------------------*/
5573 genZ80Code (iCode * lic)
5581 _fReturn = _gbz80_return;
5582 _fTmp = _gbz80_return;
5586 _fReturn = _z80_return;
5587 _fTmp = _z80_return;
5590 _G.lines.head = _G.lines.current = NULL;
5592 for (ic = lic; ic; ic = ic->next)
5595 if (cln != ic->lineno)
5597 emitDebug ("; %s %d", ic->filename, ic->lineno);
5600 /* if the result is marked as
5601 spilt and rematerializable or code for
5602 this has already been generated then
5604 if (resultRemat (ic) || ic->generated)
5607 /* depending on the operation */
5611 emitDebug ("; genNot");
5616 emitDebug ("; genCpl");
5621 emitDebug ("; genUminus");
5626 emitDebug ("; genIpush");
5631 /* IPOP happens only when trying to restore a
5632 spilt live range, if there is an ifx statement
5633 following this pop then the if statement might
5634 be using some of the registers being popped which
5635 would destory the contents of the register so
5636 we need to check for this condition and handle it */
5638 ic->next->op == IFX &&
5639 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5641 emitDebug ("; genIfx");
5642 genIfx (ic->next, ic);
5646 emitDebug ("; genIpop");
5652 emitDebug ("; genCall");
5657 emitDebug ("; genPcall");
5662 emitDebug ("; genFunction");
5667 emitDebug ("; genEndFunction");
5668 genEndFunction (ic);
5672 emitDebug ("; genRet");
5677 emitDebug ("; genLabel");
5682 emitDebug ("; genGoto");
5687 emitDebug ("; genPlus");
5692 emitDebug ("; genMinus");
5697 emitDebug ("; genMult");
5702 emitDebug ("; genDiv");
5707 emitDebug ("; genMod");
5712 emitDebug ("; genCmpGt");
5713 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5717 emitDebug ("; genCmpLt");
5718 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5725 /* note these two are xlated by algebraic equivalence
5726 during parsing SDCC.y */
5727 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5728 "got '>=' or '<=' shouldn't have come here");
5732 emitDebug ("; genCmpEq");
5733 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5737 emitDebug ("; genAndOp");
5742 emitDebug ("; genOrOp");
5747 emitDebug ("; genXor");
5748 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5752 emitDebug ("; genOr");
5753 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5757 emitDebug ("; genAnd");
5758 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5762 emitDebug ("; genInline");
5767 emitDebug ("; genRRC");
5772 emitDebug ("; genRLC");
5777 emitDebug ("; genGetHBIT");
5782 emitDebug ("; genLeftShift");
5787 emitDebug ("; genRightShift");
5791 case GET_VALUE_AT_ADDRESS:
5792 emitDebug ("; genPointerGet");
5798 if (POINTER_SET (ic))
5800 emitDebug ("; genAssign (pointer)");
5805 emitDebug ("; genAssign");
5811 emitDebug ("; genIfx");
5816 emitDebug ("; genAddrOf");
5821 emitDebug ("; genJumpTab");
5826 emitDebug ("; genCast");
5831 emitDebug ("; genReceive");
5836 emitDebug ("; addSet");
5837 addSet (&_G.sendSet, ic);
5842 /* piCode(ic,stdout); */
5848 /* now we are ready to call the
5849 peep hole optimizer */
5850 if (!options.nopeep)
5851 peepHole (&_G.lines.head);
5853 /* This is unfortunate */
5854 /* now do the actual printing */
5856 FILE *fp = codeOutFile;
5857 if (isInHome () && codeOutFile == code->oFile)
5858 codeOutFile = home->oFile;
5859 printLine (_G.lines.head, codeOutFile);
5860 if (_G.flushStatics)
5863 _G.flushStatics = 0;
5872 _isPairUsed (iCode * ic, PAIR_ID pairId)
5878 if (bitVectBitValue (ic->rMask, D_IDX))
5880 if (bitVectBitValue (ic->rMask, E_IDX))