1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 With reg params for mul and div 16234 202 162D
22 Michael Hope <michaelh@earthling.net> 2000
23 Based on the mcs51 generator -
24 Sandeep Dutta . sandeep.dutta@usa.net (1998)
25 and - Jean-Louis VERN.jlvern@writeme.com (1999)
27 This program is free software; you can redistribute it and/or modify it
28 under the terms of the GNU General Public License as published by the
29 Free Software Foundation; either version 2, or (at your option) any
32 This program is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 In other words, you are welcome to use, share and improve this program.
43 You are forbidden to forbid anyone else to use, share and improve
44 what you give them. Help stamp out software-hoarding!
46 -------------------------------------------------------------------------*/
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
64 /* this is the down and dirty file with all kinds of kludgy & hacky
65 stuff. This is what it is all about CODE GENERATION for a specific MCU.
66 Some of the routines may be reusable, will have to see */
68 /* Z80 calling convention description.
69 Parameters are passed right to left. As the stack grows downwards,
70 the parameters are arranged in left to right in memory.
71 Parameters may be passed in the HL and DE registers with one
73 PENDING: What if the parameter is a long?
74 Everything is caller saves. i.e. the caller must save any registers
75 that it wants to preserve over the call.
76 The return value is returned in DEHL. DE is normally used as a
77 working register pair. Caller saves allows it to be used for a
79 va args functions do not use register parameters. All arguments
80 are passed on the stack.
81 IX is used as an index register to the top of the local variable
82 area. ix-0 is the top most local variable.
84 static char *_z80_return[] =
86 static char *_gbz80_return[] =
88 static char *_fReceive[] =
89 { "c", "b", "e", "d" };
91 static char **_fReturn;
94 extern FILE *codeOutFile;
113 } _pairs[NUM_PAIRS] = {
114 { "??1", "?2", "?3" },
119 { "iy", "iy.l?", "iy.h?" },
120 { "ix", "ix.l?", "ix.h?" }
124 #define ACC_NAME _pairs[PAIR_AF].h
126 #define RESULTONSTACK(x) \
127 (IC_RESULT(x) && IC_RESULT(x)->aop && \
128 IC_RESULT(x)->aop->type == AOP_STK )
159 const char *lastFunctionName;
165 /** TRUE if the registers have already been saved. */
178 static const char *aopGet (asmop * aop, int offset, bool bit16);
183 /* Clean up the line so that it is 'prettier' */
184 if (strchr (buf, ':'))
186 /* Is a label - cant do anything */
189 /* Change the first (and probably only) ' ' to a tab so
204 emit2 (const char *szFormat,...)
209 va_start (ap, szFormat);
211 tvsprintf (buffer, szFormat, ap);
214 _G.lines.current = (_G.lines.current ?
215 connectLine (_G.lines.current, newLineNode (buffer)) :
216 (_G.lines.head = newLineNode (buffer)));
218 _G.lines.current->isInline = _G.lines.isInline;
221 /*-----------------------------------------------------------------*/
222 /* emit2 - writes the code into a file : for now it is simple */
223 /*-----------------------------------------------------------------*/
225 _emit2 (const char *inst, const char *fmt,...)
228 char lb[INITIAL_INLINEASM];
235 sprintf (lb, "%s\t", inst);
236 vsprintf (lb + (strlen (lb)), fmt, ap);
239 vsprintf (lb, fmt, ap);
241 while (isspace (*lbp))
246 _G.lines.current = (_G.lines.current ?
247 connectLine (_G.lines.current, newLineNode (lb)) :
248 (_G.lines.head = newLineNode (lb)));
250 _G.lines.current->isInline = _G.lines.isInline;
255 _emitMove(const char *to, const char *from)
257 if (strcasecmp(to, from) != 0)
259 emit2("ld %s,%s", to, from);
264 // Could leave this to the peephole, but sometimes the peephole is inhibited.
269 _moveA(const char *moveFrom)
271 // Let the peephole optimiser take care of redundent loads
272 _emitMove(ACC_NAME, moveFrom);
282 getPairName (asmop * aop)
284 if (aop->type == AOP_REG)
286 switch (aop->aopu.aop_reg[0]->rIdx)
299 else if (aop->type == AOP_STR)
301 switch (*aop->aopu.aop_str[0])
319 getPairId (asmop * aop)
323 if (aop->type == AOP_REG)
325 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
329 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
333 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
338 if (aop->type == AOP_STR)
340 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
344 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
348 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
357 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
361 return (getPairId (aop) != PAIR_INVALID);
365 isPtrPair (asmop * aop)
367 PAIR_ID pairId = getPairId (aop);
378 /** Push a register pair onto the stack */
380 genPairPush (asmop * aop)
382 emit2 ("push %s", getPairName (aop));
386 /*-----------------------------------------------------------------*/
387 /* newAsmop - creates a new asmOp */
388 /*-----------------------------------------------------------------*/
390 newAsmop (short type)
394 aop = Safe_calloc (1, sizeof (asmop));
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol */
401 /*-----------------------------------------------------------------*/
403 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
410 wassert (sym->etype);
412 space = SPEC_OCLS (sym->etype);
414 /* if already has one */
418 /* Assign depending on the storage class */
419 if (sym->onStack || sym->iaccess)
421 emit2 ("; AOP_STK for %s", sym->rname);
422 sym->aop = aop = newAsmop (AOP_STK);
423 aop->size = getSize (sym->type);
424 aop->aopu.aop_stk = sym->stack;
428 /* special case for a function */
429 if (IS_FUNC (sym->type))
431 sym->aop = aop = newAsmop (AOP_IMMD);
432 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
433 strcpy (aop->aopu.aop_immd, sym->rname);
440 /* if it is in direct space */
441 if (IN_REGSP (space) && !requires_a)
443 sym->aop = aop = newAsmop (AOP_SFR);
444 aop->aopu.aop_dir = sym->rname;
445 aop->size = getSize (sym->type);
446 emit2 ("; AOP_SFR for %s", sym->rname);
451 /* only remaining is far space */
452 /* in which case DPTR gets the address */
455 emit2 ("; AOP_HL for %s", sym->rname);
456 sym->aop = aop = newAsmop (AOP_HL);
460 sym->aop = aop = newAsmop (AOP_IY);
462 aop->size = getSize (sym->type);
463 aop->aopu.aop_dir = sym->rname;
465 /* if it is in code space */
466 if (IN_CODESPACE (space))
472 /*-----------------------------------------------------------------*/
473 /* aopForRemat - rematerialzes an object */
474 /*-----------------------------------------------------------------*/
476 aopForRemat (symbol * sym)
479 iCode *ic = sym->rematiCode;
480 asmop *aop = newAsmop (AOP_IMMD);
484 /* if plus or minus print the right hand side */
485 if (ic->op == '+' || ic->op == '-')
487 /* PENDING: for re-target */
488 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
491 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
494 /* we reached the end */
495 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
500 strcpy (aop->aopu.aop_immd, buffer);
504 /*-----------------------------------------------------------------*/
505 /* regsInCommon - two operands have some registers in common */
506 /*-----------------------------------------------------------------*/
508 regsInCommon (operand * op1, operand * op2)
513 /* if they have registers in common */
514 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
517 sym1 = OP_SYMBOL (op1);
518 sym2 = OP_SYMBOL (op2);
520 if (sym1->nRegs == 0 || sym2->nRegs == 0)
523 for (i = 0; i < sym1->nRegs; i++)
529 for (j = 0; j < sym2->nRegs; j++)
534 if (sym2->regs[j] == sym1->regs[i])
542 /*-----------------------------------------------------------------*/
543 /* operandsEqu - equivalent */
544 /*-----------------------------------------------------------------*/
546 operandsEqu (operand * op1, operand * op2)
550 /* if they not symbols */
551 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
554 sym1 = OP_SYMBOL (op1);
555 sym2 = OP_SYMBOL (op2);
557 /* if both are itemps & one is spilt
558 and the other is not then false */
559 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
560 sym1->isspilt != sym2->isspilt)
563 /* if they are the same */
567 if (strcmp (sym1->rname, sym2->rname) == 0)
571 /* if left is a tmp & right is not */
572 if (IS_ITEMP (op1) &&
575 (sym1->usl.spillLoc == sym2))
578 if (IS_ITEMP (op2) &&
582 (sym2->usl.spillLoc == sym1))
588 /*-----------------------------------------------------------------*/
589 /* sameRegs - two asmops have the same registers */
590 /*-----------------------------------------------------------------*/
592 sameRegs (asmop * aop1, asmop * aop2)
596 if (aop1->type == AOP_SFR ||
597 aop2->type == AOP_SFR)
603 if (aop1->type != AOP_REG ||
604 aop2->type != AOP_REG)
607 if (aop1->size != aop2->size)
610 for (i = 0; i < aop1->size; i++)
611 if (aop1->aopu.aop_reg[i] !=
612 aop2->aopu.aop_reg[i])
618 /*-----------------------------------------------------------------*/
619 /* aopOp - allocates an asmop for an operand : */
620 /*-----------------------------------------------------------------*/
622 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
631 /* if this a literal */
632 if (IS_OP_LITERAL (op))
634 op->aop = aop = newAsmop (AOP_LIT);
635 aop->aopu.aop_lit = op->operand.valOperand;
636 aop->size = getSize (operandType (op));
640 /* if already has a asmop then continue */
644 /* if the underlying symbol has a aop */
645 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
647 op->aop = OP_SYMBOL (op)->aop;
651 /* if this is a true symbol */
652 if (IS_TRUE_SYMOP (op))
654 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
658 /* this is a temporary : this has
664 e) can be a return use only */
666 sym = OP_SYMBOL (op);
668 /* if the type is a conditional */
669 if (sym->regType == REG_CND)
671 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
676 /* if it is spilt then two situations
678 b) has a spill location */
679 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
692 if (sym->accuse == ACCUSE_A)
694 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
695 aop->size = getSize (sym->type);
696 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
698 aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
700 else if (sym->accuse == ACCUSE_HL)
703 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
704 aop->size = getSize (sym->type);
705 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
706 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
707 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
719 aop = op->aop = sym->aop = newAsmop (AOP_STR);
720 aop->size = getSize (sym->type);
721 for (i = 0; i < 4; i++)
722 aop->aopu.aop_str[i] = _fReturn[i];
726 /* else spill location */
727 sym->aop = op->aop = aop =
728 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
729 aop->size = getSize (sym->type);
733 /* must be in a register */
734 sym->aop = op->aop = aop = newAsmop (AOP_REG);
735 aop->size = sym->nRegs;
736 for (i = 0; i < sym->nRegs; i++)
737 aop->aopu.aop_reg[i] = sym->regs[i];
740 /*-----------------------------------------------------------------*/
741 /* freeAsmop - free up the asmop given to an operand */
742 /*----------------------------------------------------------------*/
744 freeAsmop (operand * op, asmop * aaop, iCode * ic)
762 /* all other cases just dealloc */
768 OP_SYMBOL (op)->aop = NULL;
769 /* if the symbol has a spill */
771 SPIL_LOC (op)->aop = NULL;
777 isLitWord (asmop * aop)
779 /* if (aop->size != 2)
792 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
798 if (aop->size != 2 && aop->type != AOP_HL)
801 /* depending on type */
807 /* PENDING: for re-target */
809 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
811 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
812 rs = Safe_calloc (1, strlen (s) + 1);
817 value *val = aop->aopu.aop_lit;
818 /* if it is a float then it gets tricky */
819 /* otherwise it is fairly simple */
820 if (!IS_FLOAT (val->type))
822 unsigned long v = (unsigned long) floatFromVal (val);
828 tsprintf (buffer, "!immedword", v);
830 tsprintf (buffer, "!constword", v);
831 rs = Safe_calloc (1, strlen (buffer) + 1);
832 return strcpy (rs, buffer);
838 convertFloat (&f, floatFromVal (val));
840 tsprintf (buffer, "!immedword", f.w[offset / 2]);
842 tsprintf (buffer, "!constword", f.w[offset / 2]);
843 rs = Safe_calloc (1, strlen (buffer) + 1);
844 return strcpy (rs, buffer);
853 aopGetWord (asmop * aop, int offset)
855 return aopGetLitWordLong (aop, offset, TRUE);
859 isPtr (const char *s)
861 if (!strcmp (s, "hl"))
863 if (!strcmp (s, "ix"))
865 if (!strcmp (s, "iy"))
871 adjustPair (const char *pair, int *pold, int new)
877 emit2 ("inc %s", pair);
882 emit2 ("dec %s", pair);
888 spillPair (PAIR_ID pairId)
890 _G.pairs[pairId].last_type = AOP_INVALID;
891 _G.pairs[pairId].lit = NULL;
902 requiresHL (asmop * aop)
916 fetchLitSpecial (asmop * aop, bool negate, bool xor)
919 value *val = aop->aopu.aop_lit;
921 wassert (aop->type == AOP_LIT);
922 wassert (!IS_FLOAT (val->type));
924 v = (unsigned long) floatFromVal (val);
932 tsprintf (buffer, "!immedword", v);
933 return gc_strdup (buffer);
937 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
940 const char *pair = _pairs[pairId].name;
941 l = aopGetLitWordLong (left, 0, FALSE);
946 if (pairId == PAIR_HL || pairId == PAIR_IY)
948 if (_G.pairs[pairId].last_type == left->type)
950 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
952 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
954 adjustPair (pair, &_G.pairs[pairId].offset, offset);
957 if (pairId == PAIR_IY && abs (offset) < 127)
964 _G.pairs[pairId].last_type = left->type;
965 _G.pairs[pairId].lit = gc_strdup (l);
966 _G.pairs[pairId].offset = offset;
968 if (IS_GB && pairId == PAIR_DE && 0)
970 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
972 if (abs (_G.pairs[pairId].offset - offset) < 3)
974 adjustPair (pair, &_G.pairs[pairId].offset, offset);
978 _G.pairs[pairId].last_type = left->type;
979 _G.pairs[pairId].lit = gc_strdup (l);
980 _G.pairs[pairId].offset = offset;
982 /* Both a lit on the right and a true symbol on the left */
984 emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
986 emit2 ("ld %s,!hashedstr", pair, l);
990 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
992 /* if this is remateriazable */
993 if (isLitWord (aop)) {
994 fetchLitPair (pairId, aop, offset);
997 /* we need to get it byte by byte */
998 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
999 aopGet (aop, offset, FALSE);
1000 switch (aop->size) {
1002 emit2 ("ld l,!*hl");
1003 emit2 ("ld h,!immedbyte", 0);
1007 emit2 ("ld h,!*hl");
1011 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1014 else if (IS_Z80 && aop->type == AOP_IY) {
1015 /* Instead of fetching relative to IY, just grab directly
1016 from the address IY refers to */
1017 char *l = aopGetLitWordLong (aop, offset, FALSE);
1019 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1021 if (aop->size < 2) {
1022 emit2("ld %s,!zero", _pairs[pairId].h);
1026 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1027 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1029 /* PENDING: check? */
1030 if (pairId == PAIR_HL)
1031 spillPair (PAIR_HL);
1036 fetchPair (PAIR_ID pairId, asmop * aop)
1038 fetchPairLong (pairId, aop, 0);
1042 fetchHL (asmop * aop)
1044 fetchPair (PAIR_HL, aop);
1048 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1050 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1055 fetchLitPair (pairId, aop, 0);
1058 fetchLitPair (pairId, aop, offset);
1059 _G.pairs[pairId].offset = offset;
1063 /* Doesnt include _G.stack.pushed */
1064 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1065 if (aop->aopu.aop_stk > 0)
1067 abso += _G.stack.param_offset;
1069 assert (pairId == PAIR_HL);
1070 /* In some cases we can still inc or dec hl */
1071 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1073 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1077 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1079 _G.pairs[pairId].offset = abso;
1085 _G.pairs[pairId].last_type = aop->type;
1091 emit2 ("!tlabeldef", key);
1095 /*-----------------------------------------------------------------*/
1096 /* aopGet - for fetching value of the aop */
1097 /*-----------------------------------------------------------------*/
1099 aopGet (asmop * aop, int offset, bool bit16)
1103 /* offset is greater than size then zero */
1104 /* PENDING: this seems a bit screwed in some pointer cases. */
1105 if (offset > (aop->size - 1) &&
1106 aop->type != AOP_LIT)
1108 tsprintf (s, "!zero");
1109 return gc_strdup(s);
1112 /* depending on type */
1116 /* PENDING: re-target */
1118 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1123 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1126 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1129 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1135 return gc_strdup(s);
1139 emit2 ("ld a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1142 return gc_strdup(s);
1146 emit2 ("ldh a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1149 return gc_strdup(s);
1152 return aop->aopu.aop_reg[offset]->name;
1156 setupPair (PAIR_HL, aop, offset);
1157 tsprintf (s, "!*hl");
1159 return gc_strdup (s);
1163 setupPair (PAIR_IY, aop, offset);
1164 tsprintf (s, "!*iyx", offset);
1166 return gc_strdup(s);
1171 setupPair (PAIR_HL, aop, offset);
1172 tsprintf (s, "!*hl");
1176 if (aop->aopu.aop_stk >= 0)
1177 offset += _G.stack.param_offset;
1178 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1181 return gc_strdup(s);
1193 tsprintf(s, "!zero");
1194 return gc_strdup(s);
1198 wassert (offset < 2);
1199 return aop->aopu.aop_str[offset];
1202 return aopLiteral (aop->aopu.aop_lit, offset);
1206 return aop->aopu.aop_str[offset];
1211 wassertl (0, "aopget got unsupported aop->type");
1216 isRegString (const char *s)
1218 if (!strcmp (s, "b") ||
1230 isConstant (const char *s)
1232 /* This is a bit of a hack... */
1233 return (*s == '#' || *s == '$');
1237 canAssignToPtr (const char *s)
1239 if (isRegString (s))
1246 /*-----------------------------------------------------------------*/
1247 /* aopPut - puts a string for a aop */
1248 /*-----------------------------------------------------------------*/
1250 aopPut (asmop * aop, const char *s, int offset)
1254 if (aop->size && offset > (aop->size - 1))
1256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1257 "aopPut got offset > aop->size");
1262 tsprintf(buffer2, s);
1265 /* will assign value to value */
1266 /* depending on where it is ofcourse */
1272 if (strcmp (s, "a"))
1273 emit2 ("ld a,%s", s);
1274 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1279 if (strcmp (s, "a"))
1280 emit2 ("ld a,%s", s);
1281 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1285 if (!strcmp (s, "!*hl"))
1286 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1289 aop->aopu.aop_reg[offset]->name, s);
1294 setupPair (PAIR_IY, aop, offset);
1295 if (!canAssignToPtr (s))
1297 emit2 ("ld a,%s", s);
1298 emit2 ("ld !*iyx,a", offset);
1301 emit2 ("ld !*iyx,%s", offset, s);
1306 /* PENDING: for re-target */
1307 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1309 emit2 ("ld a,!*hl");
1312 setupPair (PAIR_HL, aop, offset);
1314 emit2 ("ld !*hl,%s", s);
1320 /* PENDING: re-target */
1321 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1323 emit2 ("ld a,!*hl");
1326 setupPair (PAIR_HL, aop, offset);
1327 if (!canAssignToPtr (s))
1329 emit2 ("ld a,%s", s);
1330 emit2 ("ld !*hl,a");
1333 emit2 ("ld !*hl,%s", s);
1337 if (aop->aopu.aop_stk >= 0)
1338 offset += _G.stack.param_offset;
1339 if (!canAssignToPtr (s))
1341 emit2 ("ld a,%s", s);
1342 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1345 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1350 /* if bit variable */
1351 if (!aop->aopu.aop_dir)
1358 /* In bit space but not in C - cant happen */
1365 if (strcmp (aop->aopu.aop_str[offset], s))
1367 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1373 if (!offset && (strcmp (s, "acc") == 0))
1378 emit2 ("; Error aopPut AOP_ACC");
1382 if (strcmp (aop->aopu.aop_str[offset], s))
1383 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1388 wassert (offset < 2);
1389 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1393 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1394 "aopPut got unsupported aop->type");
1399 #define AOP(op) op->aop
1400 #define AOP_TYPE(op) AOP(op)->type
1401 #define AOP_SIZE(op) AOP(op)->size
1402 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1405 commitPair (asmop * aop, PAIR_ID id)
1407 if (id == PAIR_HL && requiresHL (aop))
1411 aopPut (aop, "a", 0);
1412 aopPut (aop, "d", 1);
1416 aopPut (aop, _pairs[id].l, 0);
1417 aopPut (aop, _pairs[id].h, 1);
1421 /*-----------------------------------------------------------------*/
1422 /* getDataSize - get the operand data size */
1423 /*-----------------------------------------------------------------*/
1425 getDataSize (operand * op)
1428 size = AOP_SIZE (op);
1437 /*-----------------------------------------------------------------*/
1438 /* movLeft2Result - move byte from left to result */
1439 /*-----------------------------------------------------------------*/
1441 movLeft2Result (operand * left, int offl,
1442 operand * result, int offr, int sign)
1445 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1447 l = aopGet (AOP (left), offl, FALSE);
1451 aopPut (AOP (result), l, offr);
1461 /** Put Acc into a register set
1464 outAcc (operand * result)
1467 size = getDataSize (result);
1470 aopPut (AOP (result), "a", 0);
1473 /* unsigned or positive */
1476 aopPut (AOP (result), "!zero", offset++);
1481 /** Take the value in carry and put it into a register
1484 outBitCLong (operand * result, bool swap_sense)
1486 /* if the result is bit */
1487 if (AOP_TYPE (result) == AOP_CRY)
1489 emit2 ("; Note: outBitC form 1");
1490 aopPut (AOP (result), "blah", 0);
1494 emit2 ("ld a,!zero");
1497 emit2 ("xor a,!immedbyte", 1);
1503 outBitC (operand * result)
1505 outBitCLong (result, FALSE);
1508 /*-----------------------------------------------------------------*/
1509 /* toBoolean - emit code for orl a,operator(sizeop) */
1510 /*-----------------------------------------------------------------*/
1512 toBoolean (operand * oper)
1514 int size = AOP_SIZE (oper);
1518 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1521 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1525 if (AOP (oper)->type != AOP_ACC)
1528 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1539 sym_link *optype = operandType (IC_LEFT (ic));
1541 /* assign asmOps to operand & result */
1542 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1543 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1545 /* if in bit space then a special case */
1546 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1551 /* if type float then do float */
1552 if (IS_FLOAT (optype))
1557 toBoolean (IC_LEFT (ic));
1562 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1563 emit2 ("sub a,!one");
1564 outBitC (IC_RESULT (ic));
1566 /* release the aops */
1567 freeAsmop (IC_LEFT (ic), NULL, ic);
1568 freeAsmop (IC_RESULT (ic), NULL, ic);
1571 /*-----------------------------------------------------------------*/
1572 /* genCpl - generate code for complement */
1573 /*-----------------------------------------------------------------*/
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1585 /* if both are in bit space then
1587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1588 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593 size = AOP_SIZE (IC_RESULT (ic));
1596 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1599 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1602 /* release the aops */
1603 freeAsmop (IC_LEFT (ic), NULL, ic);
1604 freeAsmop (IC_RESULT (ic), NULL, ic);
1607 /*-----------------------------------------------------------------*/
1608 /* genUminus - unary minus code generation */
1609 /*-----------------------------------------------------------------*/
1611 genUminus (iCode * ic)
1614 sym_link *optype, *rtype;
1617 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1618 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1620 /* if both in bit space then special
1622 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1623 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1629 optype = operandType (IC_LEFT (ic));
1630 rtype = operandType (IC_RESULT (ic));
1632 /* if float then do float stuff */
1633 if (IS_FLOAT (optype))
1639 /* otherwise subtract from zero */
1640 size = AOP_SIZE (IC_LEFT (ic));
1645 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1646 emit2 ("ld a,!zero");
1647 emit2 ("sbc a,%s", l);
1648 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1651 /* if any remaining bytes in the result */
1652 /* we just need to propagate the sign */
1653 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1658 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1662 /* release the aops */
1663 freeAsmop (IC_LEFT (ic), NULL, ic);
1664 freeAsmop (IC_RESULT (ic), NULL, ic);
1668 _push (PAIR_ID pairId)
1670 emit2 ("push %s", _pairs[pairId].name);
1671 _G.stack.pushed += 2;
1675 _pop (PAIR_ID pairId)
1677 emit2 ("pop %s", _pairs[pairId].name);
1678 _G.stack.pushed -= 2;
1682 /*-----------------------------------------------------------------*/
1683 /* assignResultValue - */
1684 /*-----------------------------------------------------------------*/
1686 assignResultValue (operand * oper)
1688 int size = AOP_SIZE (oper);
1691 wassert (size <= 4);
1692 topInA = requiresHL (AOP (oper));
1696 wassert (size <= 2);
1698 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1700 /* We do it the hard way here. */
1702 aopPut (AOP (oper), _fReturn[0], 0);
1703 aopPut (AOP (oper), _fReturn[1], 1);
1705 _G.stack.pushed -= 2;
1706 aopPut (AOP (oper), _fReturn[0], 2);
1707 aopPut (AOP (oper), _fReturn[1], 3);
1713 aopPut (AOP (oper), _fReturn[size], size);
1719 _saveRegsForCall(iCode *ic, int sendSetSize)
1722 o Stack parameters are pushed before this function enters
1723 o DE and BC may be used in this function.
1724 o HL and DE may be used to return the result.
1725 o HL and DE may be used to send variables.
1726 o DE and BC may be used to store the result value.
1727 o HL may be used in computing the sent value of DE
1728 o The iPushes for other parameters occur before any addSets
1730 Logic: (to be run inside the first iPush or if none, before sending)
1731 o Compute if DE and/or BC are in use over the call
1732 o Compute if DE is used in the send set
1733 o Compute if DE and/or BC are used to hold the result value
1734 o If (DE is used, or in the send set) and is not used in the result, push.
1735 o If BC is used and is not in the result, push
1737 o If DE is used in the send set, fetch
1738 o If HL is used in the send set, fetch
1742 if (_G.saves.saved == FALSE) {
1743 bool deInUse, bcInUse;
1745 bool bcInRet = FALSE, deInRet = FALSE;
1749 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1753 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
1757 /* Has no result, so in use is all of in use */
1762 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
1763 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
1765 deSending = (sendSetSize > 1);
1767 emit2 ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
1769 if (bcInUse && bcInRet == FALSE) {
1771 _G.stack.pushedBC = TRUE;
1773 if (deInUse && deInRet == FALSE) {
1775 _G.stack.pushedDE = TRUE;
1778 _G.saves.saved = TRUE;
1781 /* Already saved. */
1785 /*-----------------------------------------------------------------*/
1786 /* genIpush - genrate code for pushing this gets a little complex */
1787 /*-----------------------------------------------------------------*/
1789 genIpush (iCode * ic)
1791 int size, offset = 0;
1794 /* if this is not a parm push : ie. it is spill push
1795 and spill push is always done on the local stack */
1798 wassertl(0, "Encountered an unsupported spill push.");
1800 /* and the item is spilt then do nothing */
1801 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1804 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1805 size = AOP_SIZE (IC_LEFT (ic));
1806 /* push it on the stack */
1807 if (isPair (AOP (IC_LEFT (ic))))
1809 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1810 _G.stack.pushed += 2;
1817 /* Simple for now - load into A and PUSH AF */
1818 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1820 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1822 emit2 ("ld a,(%s)", l);
1826 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1827 emit2 ("ld a,%s", l);
1838 if (_G.saves.saved == FALSE) {
1839 /* Caller saves, and this is the first iPush. */
1840 /* Scan ahead until we find the function that we are pushing parameters to.
1841 Count the number of addSets on the way to figure out what registers
1842 are used in the send set.
1845 iCode *walk = ic->next;
1848 if (walk->op == SEND) {
1851 else if (walk->op == CALL || walk->op == PCALL) {
1860 _saveRegsForCall(walk, nAddSets);
1863 /* Already saved by another iPush. */
1866 /* then do the push */
1867 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1869 size = AOP_SIZE (IC_LEFT (ic));
1871 if (isPair (AOP (IC_LEFT (ic))))
1873 _G.stack.pushed += 2;
1874 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1880 fetchHL (AOP (IC_LEFT (ic)));
1882 spillPair (PAIR_HL);
1883 _G.stack.pushed += 2;
1888 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1890 spillPair (PAIR_HL);
1891 _G.stack.pushed += 2;
1892 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1894 spillPair (PAIR_HL);
1895 _G.stack.pushed += 2;
1901 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1903 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1905 emit2 ("ld a,(%s)", l);
1909 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1910 emit2 ("ld a,%s", l);
1918 freeAsmop (IC_LEFT (ic), NULL, ic);
1921 /*-----------------------------------------------------------------*/
1922 /* genIpop - recover the registers: can happen only for spilling */
1923 /*-----------------------------------------------------------------*/
1925 genIpop (iCode * ic)
1930 /* if the temp was not pushed then */
1931 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1934 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1935 size = AOP_SIZE (IC_LEFT (ic));
1936 offset = (size - 1);
1937 if (isPair (AOP (IC_LEFT (ic))))
1939 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
1947 spillPair (PAIR_HL);
1948 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1952 freeAsmop (IC_LEFT (ic), NULL, ic);
1955 /* This is quite unfortunate */
1957 setArea (int inHome)
1960 static int lastArea = 0;
1962 if (_G.in_home != inHome) {
1964 const char *sz = port->mem.code_name;
1965 port->mem.code_name = "HOME";
1966 emit2("!area", CODE_NAME);
1967 port->mem.code_name = sz;
1970 emit2("!area", CODE_NAME); */
1971 _G.in_home = inHome;
1982 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1986 symbol *sym = OP_SYMBOL (op);
1988 if (sym->isspilt || sym->nRegs == 0)
1991 aopOp (op, ic, FALSE, FALSE);
1994 if (aop->type == AOP_REG)
1997 for (i = 0; i < aop->size; i++)
1999 if (pairId == PAIR_DE)
2001 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
2002 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2004 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2007 else if (pairId == PAIR_BC)
2009 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
2010 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2012 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2022 freeAsmop (IC_LEFT (ic), NULL, ic);
2026 /** Emit the code for a call statement
2029 emitCall (iCode * ic, bool ispcall)
2031 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
2033 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2035 /* if caller saves & we have not saved then */
2041 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2043 /* if send set is not empty then assign */
2048 int nSend = elementsInSet(_G.sendSet);
2049 bool swapped = FALSE;
2051 int _z80_sendOrder[] = {
2056 /* Check if the parameters are swapped. If so route through hl instead. */
2057 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2059 sic = setFirstItem(_G.sendSet);
2060 sic = setNextItem(_G.sendSet);
2062 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2063 /* The second send value is loaded from one the one that holds the first
2064 send, i.e. it is overwritten. */
2065 /* Cache the first in HL, and load the second from HL instead. */
2066 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2067 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2073 for (sic = setFirstItem (_G.sendSet); sic;
2074 sic = setNextItem (_G.sendSet))
2077 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2079 size = AOP_SIZE (IC_LEFT (sic));
2080 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2081 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2083 // PENDING: Mild hack
2084 if (swapped == TRUE && send == 1) {
2086 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2089 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2091 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2094 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2098 freeAsmop (IC_LEFT (sic), NULL, sic);
2105 if (IS_BANKEDCALL (detype))
2107 werror (W_INDIR_BANKED);
2109 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2111 if (isLitWord (AOP (IC_LEFT (ic))))
2113 emit2 ("; Special case where the pCall is to a constant");
2114 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2118 symbol *rlbl = newiTempLabel (NULL);
2119 spillPair (PAIR_HL);
2120 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2122 _G.stack.pushed += 2;
2124 fetchHL (AOP (IC_LEFT (ic)));
2126 emit2 ("!tlabeldef", (rlbl->key + 100));
2127 _G.stack.pushed -= 2;
2129 freeAsmop (IC_LEFT (ic), NULL, ic);
2133 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2134 OP_SYMBOL (IC_LEFT (ic))->rname :
2135 OP_SYMBOL (IC_LEFT (ic))->name;
2136 if (IS_BANKEDCALL (detype))
2138 emit2 ("call banked_call");
2139 emit2 ("!dws", name);
2140 emit2 ("!dw !bankimmeds", name);
2145 emit2 ("call %s", name);
2150 /* Mark the regsiters as restored. */
2151 _G.saves.saved = FALSE;
2153 /* if we need assign a result value */
2154 if ((IS_ITEMP (IC_RESULT (ic)) &&
2155 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2156 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2157 IS_TRUE_SYMOP (IC_RESULT (ic)))
2160 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2162 assignResultValue (IC_RESULT (ic));
2164 freeAsmop (IC_RESULT (ic), NULL, ic);
2167 /* adjust the stack for parameters if required */
2170 int i = ic->parmBytes;
2172 _G.stack.pushed -= i;
2175 emit2 ("!ldaspsp", i);
2182 emit2 ("ld hl,#%d", i);
2183 emit2 ("add hl,sp");
2200 if (_G.stack.pushedDE)
2202 bool dInUse = bitVectBitValue(rInUse, D_IDX);
2203 bool eInUse = bitVectBitValue(rInUse, E_IDX);
2205 if (dInUse && eInUse)
2221 wassertl (0, "Neither D or E were in use but it was pushed.");
2223 _G.stack.pushedDE = FALSE;
2226 if (_G.stack.pushedBC)
2228 bool bInUse = bitVectBitValue(rInUse, B_IDX);
2229 bool cInUse = bitVectBitValue(rInUse, C_IDX);
2231 // If both B and C are used in the return value, then we won't get
2233 if (bInUse && cInUse)
2249 wassertl (0, "Neither B or C were in use but it was pushed.");
2251 _G.stack.pushedBC = FALSE;
2255 /*-----------------------------------------------------------------*/
2256 /* genCall - generates a call statement */
2257 /*-----------------------------------------------------------------*/
2259 genCall (iCode * ic)
2261 emitCall (ic, FALSE);
2264 /*-----------------------------------------------------------------*/
2265 /* genPcall - generates a call by pointer statement */
2266 /*-----------------------------------------------------------------*/
2268 genPcall (iCode * ic)
2270 emitCall (ic, TRUE);
2273 /*-----------------------------------------------------------------*/
2274 /* resultRemat - result is rematerializable */
2275 /*-----------------------------------------------------------------*/
2277 resultRemat (iCode * ic)
2279 if (SKIP_IC (ic) || ic->op == IFX)
2282 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2284 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2285 if (sym->remat && !POINTER_SET (ic))
2292 extern set *publics;
2296 o Check emitCall and clean up
2298 o Check return puller
2300 PENDING: Remove this.
2303 /*-----------------------------------------------------------------*/
2304 /* genFunction - generated code for function entry */
2305 /*-----------------------------------------------------------------*/
2307 genFunction (iCode * ic)
2309 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2313 bool bcInUse = FALSE;
2314 bool deInUse = FALSE;
2317 setArea (IS_NONBANKED (sym->etype));
2319 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2322 _G.receiveOffset = 0;
2326 if (!IS_STATIC (sym->etype))
2328 addSetIfnotP (&publics, sym);
2332 /* Record the last function name for debugging. */
2333 _G.lastFunctionName = sym->rname;
2335 /* Create the function header */
2336 emit2 ("!functionheader", sym->name);
2337 /* PENDING: portability. */
2338 emit2 ("__%s_start:", sym->rname);
2339 emit2 ("!functionlabeldef", sym->rname);
2341 fetype = getSpec (operandType (IC_LEFT (ic)));
2343 /* if critical function then turn interrupts off */
2344 if (SPEC_CRTCL (fetype))
2347 /* if this is an interrupt service routine then save all potentially used registers. */
2348 if (IS_ISR (sym->etype))
2353 /* PENDING: callee-save etc */
2355 _G.stack.param_offset = 0;
2358 /* Detect which registers are used. */
2362 for (i = 0; i < sym->regsUsed->size; i++)
2364 if (bitVectBitValue (sym->regsUsed, i))
2378 /* Other systems use DE as a temporary. */
2389 _G.stack.param_offset += 2;
2392 _G.stack.pushedBC = bcInUse;
2397 _G.stack.param_offset += 2;
2400 _G.stack.pushedDE = deInUse;
2403 /* adjust the stack for the function */
2404 _G.stack.last = sym->stack;
2407 emit2 ("!enterx", sym->stack);
2410 _G.stack.offset = sym->stack;
2413 /*-----------------------------------------------------------------*/
2414 /* genEndFunction - generates epilogue for functions */
2415 /*-----------------------------------------------------------------*/
2417 genEndFunction (iCode * ic)
2419 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2421 if (IS_ISR (sym->etype))
2427 if (SPEC_CRTCL (sym->etype))
2430 /* PENDING: calleeSave */
2432 if (_G.stack.offset)
2434 emit2 ("!leavex", _G.stack.offset);
2442 if (_G.stack.pushedDE)
2445 _G.stack.pushedDE = FALSE;
2448 if (_G.stack.pushedDE)
2451 _G.stack.pushedDE = FALSE;
2455 /* Both baned and non-banked just ret */
2458 /* PENDING: portability. */
2459 emit2 ("__%s_end:", sym->rname);
2461 _G.flushStatics = 1;
2462 _G.stack.pushed = 0;
2463 _G.stack.offset = 0;
2466 /*-----------------------------------------------------------------*/
2467 /* genRet - generate code for return statement */
2468 /*-----------------------------------------------------------------*/
2473 /* Errk. This is a hack until I can figure out how
2474 to cause dehl to spill on a call */
2475 int size, offset = 0;
2477 /* if we have no return value then
2478 just generate the "ret" */
2482 /* we have something to return then
2483 move the return value into place */
2484 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2485 size = AOP_SIZE (IC_LEFT (ic));
2487 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2491 emit2 ("ld de,%s", l);
2495 emit2 ("ld hl,%s", l);
2500 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2502 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2503 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2509 l = aopGet (AOP (IC_LEFT (ic)), offset,
2511 if (strcmp (_fReturn[offset], l))
2512 emit2 ("ld %s,%s", _fReturn[offset++], l);
2516 freeAsmop (IC_LEFT (ic), NULL, ic);
2519 /* generate a jump to the return label
2520 if the next is not the return statement */
2521 if (!(ic->next && ic->next->op == LABEL &&
2522 IC_LABEL (ic->next) == returnLabel))
2524 emit2 ("jp !tlabel", returnLabel->key + 100);
2527 /*-----------------------------------------------------------------*/
2528 /* genLabel - generates a label */
2529 /*-----------------------------------------------------------------*/
2531 genLabel (iCode * ic)
2533 /* special case never generate */
2534 if (IC_LABEL (ic) == entryLabel)
2537 emitLabel (IC_LABEL (ic)->key + 100);
2540 /*-----------------------------------------------------------------*/
2541 /* genGoto - generates a ljmp */
2542 /*-----------------------------------------------------------------*/
2544 genGoto (iCode * ic)
2546 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2549 /*-----------------------------------------------------------------*/
2550 /* genPlusIncr :- does addition with increment if possible */
2551 /*-----------------------------------------------------------------*/
2553 genPlusIncr (iCode * ic)
2555 unsigned int icount;
2556 unsigned int size = getDataSize (IC_RESULT (ic));
2557 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2559 /* will try to generate an increment */
2560 /* if the right side is not a literal
2562 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2565 emit2 ("; genPlusIncr");
2567 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2569 /* If result is a pair */
2570 if (resultId != PAIR_INVALID)
2572 if (isLitWord (AOP (IC_LEFT (ic))))
2574 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2577 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2579 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2580 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2586 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2590 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2591 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2595 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2600 /* if the literal value of the right hand side
2601 is greater than 4 then it is not worth it */
2605 /* if increment 16 bits in register */
2606 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2612 symbol *tlbl = NULL;
2613 tlbl = newiTempLabel (NULL);
2616 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2619 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2622 emitLabel (tlbl->key + 100);
2626 /* if the sizes are greater than 1 then we cannot */
2627 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2628 AOP_SIZE (IC_LEFT (ic)) > 1)
2631 /* we can if the aops of the left & result match or
2632 if they are in registers and the registers are the
2634 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2637 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2644 /*-----------------------------------------------------------------*/
2645 /* outBitAcc - output a bit in acc */
2646 /*-----------------------------------------------------------------*/
2648 outBitAcc (operand * result)
2650 symbol *tlbl = newiTempLabel (NULL);
2651 /* if the result is a bit */
2652 if (AOP_TYPE (result) == AOP_CRY)
2658 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2659 emit2 ("ld a,!one");
2660 emitLabel (tlbl->key + 100);
2665 /*-----------------------------------------------------------------*/
2666 /* genPlus - generates code for addition */
2667 /*-----------------------------------------------------------------*/
2669 genPlus (iCode * ic)
2671 int size, offset = 0;
2673 /* special cases :- */
2675 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2676 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2677 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2679 /* Swap the left and right operands if:
2681 if literal, literal on the right or
2682 if left requires ACC or right is already
2685 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2686 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2687 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2689 operand *t = IC_RIGHT (ic);
2690 IC_RIGHT (ic) = IC_LEFT (ic);
2694 /* if both left & right are in bit
2696 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2697 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2703 /* if left in bit space & right literal */
2704 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2705 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2707 /* Can happen I guess */
2711 /* if I can do an increment instead
2712 of add then GOOD for ME */
2713 if (genPlusIncr (ic) == TRUE)
2716 emit2 ("; genPlusIncr failed");
2718 size = getDataSize (IC_RESULT (ic));
2720 /* Special case when left and right are constant */
2721 if (isPair (AOP (IC_RESULT (ic))))
2725 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2726 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2732 sprintf (buffer, "#(%s + %s)", left, right);
2733 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2738 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2740 /* Fetch into HL then do the add */
2741 spillPair (PAIR_HL);
2742 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2743 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2748 ld hl,sp+n trashes C so we cant afford to do it during an
2749 add with stack based varibles. Worst case is:
2762 So you cant afford to load up hl if either left, right, or result
2763 is on the stack (*sigh*) The alt is:
2771 Combinations in here are:
2772 * If left or right are in bc then the loss is small - trap later
2773 * If the result is in bc then the loss is also small
2777 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2778 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2779 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2781 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2782 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2783 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2784 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2786 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2788 /* Swap left and right */
2789 operand *t = IC_RIGHT (ic);
2790 IC_RIGHT (ic) = IC_LEFT (ic);
2793 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2795 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2796 emit2 ("add hl,bc");
2800 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2801 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2802 emit2 ("add hl,de");
2804 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2809 emit2 ("; WARNING: This add is probably broken.\n");
2816 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2818 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2821 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2824 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
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));
2836 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2840 freeAsmop (IC_LEFT (ic), NULL, ic);
2841 freeAsmop (IC_RIGHT (ic), NULL, ic);
2842 freeAsmop (IC_RESULT (ic), NULL, ic);
2846 /*-----------------------------------------------------------------*/
2847 /* genMinusDec :- does subtraction with deccrement if possible */
2848 /*-----------------------------------------------------------------*/
2850 genMinusDec (iCode * ic)
2852 unsigned int icount;
2853 unsigned int size = getDataSize (IC_RESULT (ic));
2855 /* will try to generate an increment */
2856 /* if the right side is not a literal we cannot */
2857 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2860 /* if the literal value of the right hand side
2861 is greater than 4 then it is not worth it */
2862 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2865 size = getDataSize (IC_RESULT (ic));
2868 /* if increment 16 bits in register */
2869 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2873 symbol *tlbl = newiTempLabel (NULL);
2874 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2875 emit2 ("jp np," LABEL_STR, tlbl->key + 100);
2877 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2882 emitLabel (tlbl->key + 100);
2887 /* if decrement 16 bits in register */
2888 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2889 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2892 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2896 /* If result is a pair */
2897 if (isPair (AOP (IC_RESULT (ic))))
2899 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2900 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2902 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2906 /* if the sizes are greater than 1 then we cannot */
2907 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2908 AOP_SIZE (IC_LEFT (ic)) > 1)
2911 /* we can if the aops of the left & result match or if they are in
2912 registers and the registers are the same */
2913 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2916 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2923 /*-----------------------------------------------------------------*/
2924 /* genMinus - generates code for subtraction */
2925 /*-----------------------------------------------------------------*/
2927 genMinus (iCode * ic)
2929 int size, offset = 0;
2930 unsigned long lit = 0L;
2932 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2933 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2934 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2936 /* special cases :- */
2937 /* if both left & right are in bit space */
2938 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2939 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2945 /* if I can do an decrement instead of subtract then GOOD for ME */
2946 if (genMinusDec (ic) == TRUE)
2949 size = getDataSize (IC_RESULT (ic));
2951 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2956 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2960 /* Same logic as genPlus */
2963 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2964 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2965 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2967 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2968 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2969 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2970 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2972 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2973 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2975 if (left == PAIR_INVALID && right == PAIR_INVALID)
2980 else if (right == PAIR_INVALID)
2982 else if (left == PAIR_INVALID)
2985 fetchPair (left, AOP (IC_LEFT (ic)));
2986 /* Order is important. Right may be HL */
2987 fetchPair (right, AOP (IC_RIGHT (ic)));
2989 emit2 ("ld a,%s", _pairs[left].l);
2990 emit2 ("sub a,%s", _pairs[right].l);
2992 emit2 ("ld a,%s", _pairs[left].h);
2993 emit2 ("sbc a,%s", _pairs[right].h);
2995 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2996 aopPut (AOP (IC_RESULT (ic)), "e", 0);
3001 emit2 ("; WARNING: This sub is probably broken.\n");
3006 /* if literal, add a,#-lit, else normal subb */
3009 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3010 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3014 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3017 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3021 /* first add without previous c */
3023 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
3025 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3027 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3030 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3031 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3032 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3036 freeAsmop (IC_LEFT (ic), NULL, ic);
3037 freeAsmop (IC_RIGHT (ic), NULL, ic);
3038 freeAsmop (IC_RESULT (ic), NULL, ic);
3041 /*-----------------------------------------------------------------*/
3042 /* genMult - generates code for multiplication */
3043 /*-----------------------------------------------------------------*/
3045 genMult (iCode * ic)
3047 /* Shouldn't occur - all done through function calls */
3051 /*-----------------------------------------------------------------*/
3052 /* genDiv - generates code for division */
3053 /*-----------------------------------------------------------------*/
3057 /* Shouldn't occur - all done through function calls */
3061 /*-----------------------------------------------------------------*/
3062 /* genMod - generates code for division */
3063 /*-----------------------------------------------------------------*/
3067 /* Shouldn't occur - all done through function calls */
3071 /*-----------------------------------------------------------------*/
3072 /* genIfxJump :- will create a jump depending on the ifx */
3073 /*-----------------------------------------------------------------*/
3075 genIfxJump (iCode * ic, char *jval)
3080 /* if true label then we jump if condition
3084 jlbl = IC_TRUE (ic);
3085 if (!strcmp (jval, "a"))
3089 else if (!strcmp (jval, "c"))
3093 else if (!strcmp (jval, "nc"))
3099 /* The buffer contains the bit on A that we should test */
3105 /* false label is present */
3106 jlbl = IC_FALSE (ic);
3107 if (!strcmp (jval, "a"))
3111 else if (!strcmp (jval, "c"))
3115 else if (!strcmp (jval, "nc"))
3121 /* The buffer contains the bit on A that we should test */
3125 /* Z80 can do a conditional long jump */
3126 if (!strcmp (jval, "a"))
3130 else if (!strcmp (jval, "c"))
3133 else if (!strcmp (jval, "nc"))
3138 emit2 ("bit %s,a", jval);
3140 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3142 /* mark the icode as generated */
3147 _getPairIdName (PAIR_ID id)
3149 return _pairs[id].name;
3152 /** Generic compare for > or <
3155 genCmp (operand * left, operand * right,
3156 operand * result, iCode * ifx, int sign)
3158 int size, offset = 0;
3159 unsigned long lit = 0L;
3160 bool swap_sense = FALSE;
3162 /* if left & right are bit variables */
3163 if (AOP_TYPE (left) == AOP_CRY &&
3164 AOP_TYPE (right) == AOP_CRY)
3166 /* Cant happen on the Z80 */
3171 /* subtract right from left if at the
3172 end the carry flag is set then we know that
3173 left is greater than right */
3174 size = max (AOP_SIZE (left), AOP_SIZE (right));
3176 /* if unsigned char cmp with lit, just compare */
3178 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3180 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3183 emit2 ("xor a,!immedbyte", 0x80);
3184 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3187 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3193 If the left or the right is a lit:
3194 Load -lit into HL, add to right via, check sense.
3196 if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3198 PAIR_ID id = PAIR_DE;
3199 asmop *lit = AOP (right);
3200 asmop *op = AOP (left);
3203 if (AOP_TYPE (left) == AOP_LIT)
3211 emit2 ("ld e,%s", aopGet (op, 0, 0));
3212 emit2 ("ld a,%s", aopGet (op, 1, 0));
3213 emit2 ("xor a,!immedbyte", 0x80);
3218 id = getPairId (op);
3219 if (id == PAIR_INVALID)
3221 fetchPair (PAIR_DE, op);
3225 spillPair (PAIR_HL);
3226 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3227 emit2 ("add hl,%s", _getPairIdName (id));
3230 if (AOP_TYPE (right) == AOP_LIT)
3232 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3233 /* optimize if(x < 0) or if(x >= 0) */
3238 /* No sign so it's always false */
3243 /* Just load in the top most bit */
3244 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3245 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3247 genIfxJump (ifx, "7");
3258 /* First setup h and l contaning the top most bytes XORed */
3259 bool fDidXor = FALSE;
3260 if (AOP_TYPE (left) == AOP_LIT)
3262 unsigned long lit = (unsigned long)
3263 floatFromVal (AOP (left)->aopu.aop_lit);
3264 emit2 ("ld %s,!immedbyte", _fTmp[0],
3265 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3269 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3270 emit2 ("xor a,!immedbyte", 0x80);
3271 emit2 ("ld %s,a", _fTmp[0]);
3274 if (AOP_TYPE (right) == AOP_LIT)
3276 unsigned long lit = (unsigned long)
3277 floatFromVal (AOP (right)->aopu.aop_lit);
3278 emit2 ("ld %s,!immedbyte", _fTmp[1],
3279 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3283 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3284 emit2 ("xor a,!immedbyte", 0x80);
3285 emit2 ("ld %s,a", _fTmp[1]);
3297 /* Do a long subtract */
3300 _moveA (aopGet (AOP (left), offset, FALSE));
3302 if (sign && size == 0)
3304 emit2 ("ld a,%s", _fTmp[0]);
3305 emit2 ("sbc a,%s", _fTmp[1]);
3309 /* Subtract through, propagating the carry */
3310 emit2 ("sbc a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3317 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3319 outBitCLong (result, swap_sense);
3323 /* if the result is used in the next
3324 ifx conditional branch then generate
3325 code a little differently */
3327 genIfxJump (ifx, swap_sense ? "nc" : "c");
3329 outBitCLong (result, swap_sense);
3330 /* leave the result in acc */
3334 /*-----------------------------------------------------------------*/
3335 /* genCmpGt :- greater than comparison */
3336 /*-----------------------------------------------------------------*/
3338 genCmpGt (iCode * ic, iCode * ifx)
3340 operand *left, *right, *result;
3341 sym_link *letype, *retype;
3344 left = IC_LEFT (ic);
3345 right = IC_RIGHT (ic);
3346 result = IC_RESULT (ic);
3348 letype = getSpec (operandType (left));
3349 retype = getSpec (operandType (right));
3350 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3351 /* assign the amsops */
3352 aopOp (left, ic, FALSE, FALSE);
3353 aopOp (right, ic, FALSE, FALSE);
3354 aopOp (result, ic, TRUE, FALSE);
3356 genCmp (right, left, result, ifx, sign);
3358 freeAsmop (left, NULL, ic);
3359 freeAsmop (right, NULL, ic);
3360 freeAsmop (result, NULL, ic);
3363 /*-----------------------------------------------------------------*/
3364 /* genCmpLt - less than comparisons */
3365 /*-----------------------------------------------------------------*/
3367 genCmpLt (iCode * ic, iCode * ifx)
3369 operand *left, *right, *result;
3370 sym_link *letype, *retype;
3373 left = IC_LEFT (ic);
3374 right = IC_RIGHT (ic);
3375 result = IC_RESULT (ic);
3377 letype = getSpec (operandType (left));
3378 retype = getSpec (operandType (right));
3379 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3381 /* assign the amsops */
3382 aopOp (left, ic, FALSE, FALSE);
3383 aopOp (right, ic, FALSE, FALSE);
3384 aopOp (result, ic, TRUE, FALSE);
3386 genCmp (left, right, result, ifx, sign);
3388 freeAsmop (left, NULL, ic);
3389 freeAsmop (right, NULL, ic);
3390 freeAsmop (result, NULL, ic);
3393 /*-----------------------------------------------------------------*/
3394 /* gencjneshort - compare and jump if not equal */
3395 /*-----------------------------------------------------------------*/
3397 gencjneshort (operand * left, operand * right, symbol * lbl)
3399 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3401 unsigned long lit = 0L;
3403 /* Swap the left and right if it makes the computation easier */
3404 if (AOP_TYPE (left) == AOP_LIT)
3411 if (AOP_TYPE (right) == AOP_LIT)
3412 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3414 /* if the right side is a literal then anything goes */
3415 if (AOP_TYPE (right) == AOP_LIT &&
3416 AOP_TYPE (left) != AOP_DIR)
3420 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3427 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
3434 emit2 ("jp nz,!tlabel", lbl->key + 100);
3440 emit2 ("ld a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3441 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3444 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3445 emit2 ("jp nz,!tlabel", lbl->key + 100);
3450 /* if the right side is in a register or in direct space or
3451 if the left is a pointer register & right is not */
3452 else if (AOP_TYPE (right) == AOP_REG ||
3453 AOP_TYPE (right) == AOP_DIR ||
3454 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3458 _moveA (aopGet (AOP (left), offset, FALSE));
3459 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3460 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3462 emit2 ("jp nz,!tlabel", lbl->key + 100);
3465 emit2 ("cp %s ; 4", aopGet (AOP (right), offset, FALSE));
3466 emit2 ("jp nz,!tlabel", lbl->key + 100);
3473 /* right is a pointer reg need both a & b */
3474 /* PENDING: is this required? */
3477 _moveA (aopGet (AOP (right), offset, FALSE));
3478 emit2 ("cp %s ; 5", aopGet (AOP (left), offset, FALSE));
3479 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3485 /*-----------------------------------------------------------------*/
3486 /* gencjne - compare and jump if not equal */
3487 /*-----------------------------------------------------------------*/
3489 gencjne (operand * left, operand * right, symbol * lbl)
3491 symbol *tlbl = newiTempLabel (NULL);
3493 gencjneshort (left, right, lbl);
3496 emit2 ("ld a,!one");
3497 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3498 emitLabel (lbl->key + 100);
3500 emitLabel (tlbl->key + 100);
3503 /*-----------------------------------------------------------------*/
3504 /* genCmpEq - generates code for equal to */
3505 /*-----------------------------------------------------------------*/
3507 genCmpEq (iCode * ic, iCode * ifx)
3509 operand *left, *right, *result;
3511 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3512 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3513 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3515 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3517 /* Swap operands if it makes the operation easier. ie if:
3518 1. Left is a literal.
3520 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3522 operand *t = IC_RIGHT (ic);
3523 IC_RIGHT (ic) = IC_LEFT (ic);
3527 if (ifx && !AOP_SIZE (result))
3530 /* if they are both bit variables */
3531 if (AOP_TYPE (left) == AOP_CRY &&
3532 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3538 tlbl = newiTempLabel (NULL);
3539 gencjneshort (left, right, tlbl);
3542 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3543 emitLabel (tlbl->key + 100);
3547 /* PENDING: do this better */
3548 symbol *lbl = newiTempLabel (NULL);
3549 emit2 ("!shortjp !tlabel", lbl->key + 100);
3550 emitLabel (tlbl->key + 100);
3551 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3552 emitLabel (lbl->key + 100);
3555 /* mark the icode as generated */
3560 /* if they are both bit variables */
3561 if (AOP_TYPE (left) == AOP_CRY &&
3562 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3568 gencjne (left, right, newiTempLabel (NULL));
3569 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3575 genIfxJump (ifx, "a");
3578 /* if the result is used in an arithmetic operation
3579 then put the result in place */
3580 if (AOP_TYPE (result) != AOP_CRY)
3584 /* leave the result in acc */
3588 freeAsmop (left, NULL, ic);
3589 freeAsmop (right, NULL, ic);
3590 freeAsmop (result, NULL, ic);
3593 /*-----------------------------------------------------------------*/
3594 /* ifxForOp - returns the icode containing the ifx for operand */
3595 /*-----------------------------------------------------------------*/
3597 ifxForOp (operand * op, iCode * ic)
3599 /* if true symbol then needs to be assigned */
3600 if (IS_TRUE_SYMOP (op))
3603 /* if this has register type condition and
3604 the next instruction is ifx with the same operand
3605 and live to of the operand is upto the ifx only then */
3607 ic->next->op == IFX &&
3608 IC_COND (ic->next)->key == op->key &&
3609 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3615 /*-----------------------------------------------------------------*/
3616 /* genAndOp - for && operation */
3617 /*-----------------------------------------------------------------*/
3619 genAndOp (iCode * ic)
3621 operand *left, *right, *result;
3624 /* note here that && operations that are in an if statement are
3625 taken away by backPatchLabels only those used in arthmetic
3626 operations remain */
3627 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3628 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3629 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3631 /* if both are bit variables */
3632 if (AOP_TYPE (left) == AOP_CRY &&
3633 AOP_TYPE (right) == AOP_CRY)
3639 tlbl = newiTempLabel (NULL);
3641 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3643 emitLabel (tlbl->key + 100);
3647 freeAsmop (left, NULL, ic);
3648 freeAsmop (right, NULL, ic);
3649 freeAsmop (result, NULL, ic);
3652 /*-----------------------------------------------------------------*/
3653 /* genOrOp - for || operation */
3654 /*-----------------------------------------------------------------*/
3656 genOrOp (iCode * ic)
3658 operand *left, *right, *result;
3661 /* note here that || operations that are in an
3662 if statement are taken away by backPatchLabels
3663 only those used in arthmetic operations remain */
3664 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3665 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3666 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3668 /* if both are bit variables */
3669 if (AOP_TYPE (left) == AOP_CRY &&
3670 AOP_TYPE (right) == AOP_CRY)
3676 tlbl = newiTempLabel (NULL);
3678 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3680 emitLabel (tlbl->key + 100);
3684 freeAsmop (left, NULL, ic);
3685 freeAsmop (right, NULL, ic);
3686 freeAsmop (result, NULL, ic);
3689 /*-----------------------------------------------------------------*/
3690 /* isLiteralBit - test if lit == 2^n */
3691 /*-----------------------------------------------------------------*/
3693 isLiteralBit (unsigned long lit)
3695 unsigned long pw[32] =
3696 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3697 0x100L, 0x200L, 0x400L, 0x800L,
3698 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3699 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3700 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3701 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3702 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3705 for (idx = 0; idx < 32; idx++)
3711 /*-----------------------------------------------------------------*/
3712 /* jmpTrueOrFalse - */
3713 /*-----------------------------------------------------------------*/
3715 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3717 // ugly but optimized by peephole
3720 symbol *nlbl = newiTempLabel (NULL);
3721 emit2 ("jp !tlabel", nlbl->key + 100);
3722 emitLabel (tlbl->key + 100);
3723 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3724 emitLabel (nlbl->key + 100);
3728 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3729 emitLabel (tlbl->key + 100);
3734 /*-----------------------------------------------------------------*/
3735 /* genAnd - code for and */
3736 /*-----------------------------------------------------------------*/
3738 genAnd (iCode * ic, iCode * ifx)
3740 operand *left, *right, *result;
3741 int size, offset = 0;
3742 unsigned long lit = 0L;
3745 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3746 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3747 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3750 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3752 AOP_TYPE (left), AOP_TYPE (right));
3753 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3755 AOP_SIZE (left), AOP_SIZE (right));
3758 /* if left is a literal & right is not then exchange them */
3759 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3760 AOP_NEEDSACC (left))
3762 operand *tmp = right;
3767 /* if result = right then exchange them */
3768 if (sameRegs (AOP (result), AOP (right)))
3770 operand *tmp = right;
3775 /* if right is bit then exchange them */
3776 if (AOP_TYPE (right) == AOP_CRY &&
3777 AOP_TYPE (left) != AOP_CRY)
3779 operand *tmp = right;
3783 if (AOP_TYPE (right) == AOP_LIT)
3784 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3786 size = AOP_SIZE (result);
3788 if (AOP_TYPE (left) == AOP_CRY)
3794 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3795 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3796 if ((AOP_TYPE (right) == AOP_LIT) &&
3797 (AOP_TYPE (result) == AOP_CRY) &&
3798 (AOP_TYPE (left) != AOP_CRY))
3800 int posbit = isLiteralBit (lit);
3805 _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
3810 emit2 ("mov c,acc.%d", posbit & 0x07);
3817 sprintf (buffer, "%d", posbit & 0x07);
3818 genIfxJump (ifx, buffer);
3829 symbol *tlbl = newiTempLabel (NULL);
3830 int sizel = AOP_SIZE (left);
3838 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3840 _moveA (aopGet (AOP (left), offset, FALSE));
3842 if ((posbit = isLiteralBit (bytelit)) != 0)
3845 emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3849 if (bytelit != 0x0FFL)
3851 aopGet (AOP (right), offset, FALSE));
3855 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3860 // bit = left & literal
3864 emit2 ("!tlabeldef", tlbl->key + 100);
3866 // if(left & literal)
3870 jmpTrueOrFalse (ifx, tlbl);
3878 /* if left is same as result */
3879 if (sameRegs (AOP (result), AOP (left)))
3881 for (; size--; offset++)
3883 if (AOP_TYPE (right) == AOP_LIT)
3885 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3890 aopPut (AOP (result), "!zero", offset);
3893 _moveA (aopGet (AOP (left), offset, FALSE));
3895 aopGet (AOP (right), offset, FALSE));
3896 aopPut (AOP (left), "a", offset);
3903 if (AOP_TYPE (left) == AOP_ACC)
3909 _moveA (aopGet (AOP (left), offset, FALSE));
3911 aopGet (AOP (right), offset, FALSE));
3912 aopPut (AOP (left), "a", offset);
3919 // left & result in different registers
3920 if (AOP_TYPE (result) == AOP_CRY)
3926 for (; (size--); offset++)
3929 // result = left & right
3930 if (AOP_TYPE (right) == AOP_LIT)
3932 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3934 aopPut (AOP (result),
3935 aopGet (AOP (left), offset, FALSE),
3939 else if (bytelit == 0)
3941 aopPut (AOP (result), "!zero", offset);
3945 // faster than result <- left, anl result,right
3946 // and better if result is SFR
3947 if (AOP_TYPE (left) == AOP_ACC)
3948 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
3951 _moveA (aopGet (AOP (left), offset, FALSE));
3953 aopGet (AOP (right), offset, FALSE));
3955 aopPut (AOP (result), "a", offset);
3962 freeAsmop (left, NULL, ic);
3963 freeAsmop (right, NULL, ic);
3964 freeAsmop (result, NULL, ic);
3967 /*-----------------------------------------------------------------*/
3968 /* genOr - code for or */
3969 /*-----------------------------------------------------------------*/
3971 genOr (iCode * ic, iCode * ifx)
3973 operand *left, *right, *result;
3974 int size, offset = 0;
3975 unsigned long lit = 0L;
3977 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3978 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3979 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3982 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3984 AOP_TYPE (left), AOP_TYPE (right));
3985 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3987 AOP_SIZE (left), AOP_SIZE (right));
3990 /* if left is a literal & right is not then exchange them */
3991 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3992 AOP_NEEDSACC (left))
3994 operand *tmp = right;
3999 /* if result = right then exchange them */
4000 if (sameRegs (AOP (result), AOP (right)))
4002 operand *tmp = right;
4007 /* if right is bit then exchange them */
4008 if (AOP_TYPE (right) == AOP_CRY &&
4009 AOP_TYPE (left) != AOP_CRY)
4011 operand *tmp = right;
4015 if (AOP_TYPE (right) == AOP_LIT)
4016 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4018 size = AOP_SIZE (result);
4020 if (AOP_TYPE (left) == AOP_CRY)
4026 if ((AOP_TYPE (right) == AOP_LIT) &&
4027 (AOP_TYPE (result) == AOP_CRY) &&
4028 (AOP_TYPE (left) != AOP_CRY))
4034 /* if left is same as result */
4035 if (sameRegs (AOP (result), AOP (left)))
4037 for (; size--; offset++)
4039 if (AOP_TYPE (right) == AOP_LIT)
4041 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4045 _moveA (aopGet (AOP (left), offset, FALSE));
4047 aopGet (AOP (right), offset, FALSE));
4048 aopPut (AOP (result), "a", offset);
4053 if (AOP_TYPE (left) == AOP_ACC)
4054 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4057 _moveA (aopGet (AOP (left), offset, FALSE));
4059 aopGet (AOP (right), offset, FALSE));
4060 aopPut (AOP (result), "a", offset);
4067 // left & result in different registers
4068 if (AOP_TYPE (result) == AOP_CRY)
4073 for (; (size--); offset++)
4076 // result = left & right
4077 if (AOP_TYPE (right) == AOP_LIT)
4079 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4081 aopPut (AOP (result),
4082 aopGet (AOP (left), offset, FALSE),
4087 // faster than result <- left, anl result,right
4088 // and better if result is SFR
4089 if (AOP_TYPE (left) == AOP_ACC)
4090 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4093 _moveA (aopGet (AOP (left), offset, FALSE));
4095 aopGet (AOP (right), offset, FALSE));
4097 aopPut (AOP (result), "a", offset);
4098 /* PENDING: something weird is going on here. Add exception. */
4099 if (AOP_TYPE (result) == AOP_ACC)
4105 freeAsmop (left, NULL, ic);
4106 freeAsmop (right, NULL, ic);
4107 freeAsmop (result, NULL, ic);
4110 /*-----------------------------------------------------------------*/
4111 /* genXor - code for xclusive or */
4112 /*-----------------------------------------------------------------*/
4114 genXor (iCode * ic, iCode * ifx)
4116 operand *left, *right, *result;
4117 int size, offset = 0;
4118 unsigned long lit = 0L;
4120 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4121 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4122 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4124 /* if left is a literal & right is not then exchange them */
4125 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4126 AOP_NEEDSACC (left))
4128 operand *tmp = right;
4133 /* if result = right then exchange them */
4134 if (sameRegs (AOP (result), AOP (right)))
4136 operand *tmp = right;
4141 /* if right is bit then exchange them */
4142 if (AOP_TYPE (right) == AOP_CRY &&
4143 AOP_TYPE (left) != AOP_CRY)
4145 operand *tmp = right;
4149 if (AOP_TYPE (right) == AOP_LIT)
4150 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4152 size = AOP_SIZE (result);
4154 if (AOP_TYPE (left) == AOP_CRY)
4160 if ((AOP_TYPE (right) == AOP_LIT) &&
4161 (AOP_TYPE (result) == AOP_CRY) &&
4162 (AOP_TYPE (left) != AOP_CRY))
4168 /* if left is same as result */
4169 if (sameRegs (AOP (result), AOP (left)))
4171 for (; size--; offset++)
4173 if (AOP_TYPE (right) == AOP_LIT)
4175 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4179 _moveA (aopGet (AOP (right), offset, FALSE));
4181 aopGet (AOP (left), offset, FALSE));
4182 aopPut (AOP (result), "a", 0);
4187 if (AOP_TYPE (left) == AOP_ACC)
4188 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4191 _moveA (aopGet (AOP (right), offset, FALSE));
4193 aopGet (AOP (left), offset, FALSE));
4194 aopPut (AOP (result), "a", 0);
4201 // left & result in different registers
4202 if (AOP_TYPE (result) == AOP_CRY)
4207 for (; (size--); offset++)
4210 // result = left & right
4211 if (AOP_TYPE (right) == AOP_LIT)
4213 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4215 aopPut (AOP (result),
4216 aopGet (AOP (left), offset, FALSE),
4221 // faster than result <- left, anl result,right
4222 // and better if result is SFR
4223 if (AOP_TYPE (left) == AOP_ACC)
4224 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4227 _moveA (aopGet (AOP (right), offset, FALSE));
4229 aopGet (AOP (left), offset, FALSE));
4230 aopPut (AOP (result), "a", 0);
4232 aopPut (AOP (result), "a", offset);
4237 freeAsmop (left, NULL, ic);
4238 freeAsmop (right, NULL, ic);
4239 freeAsmop (result, NULL, ic);
4242 /*-----------------------------------------------------------------*/
4243 /* genInline - write the inline code out */
4244 /*-----------------------------------------------------------------*/
4246 genInline (iCode * ic)
4248 char *buffer, *bp, *bp1;
4250 _G.lines.isInline += (!options.asmpeep);
4252 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4253 strcpy (buffer, IC_INLINE (ic));
4255 /* emit each line as a code */
4280 _G.lines.isInline -= (!options.asmpeep);
4284 /*-----------------------------------------------------------------*/
4285 /* genRRC - rotate right with carry */
4286 /*-----------------------------------------------------------------*/
4293 /*-----------------------------------------------------------------*/
4294 /* genRLC - generate code for rotate left with carry */
4295 /*-----------------------------------------------------------------*/
4302 /*-----------------------------------------------------------------*/
4303 /* shiftR2Left2Result - shift right two bytes from left to result */
4304 /*-----------------------------------------------------------------*/
4306 shiftR2Left2Result (operand * left, int offl,
4307 operand * result, int offr,
4308 int shCount, int sign)
4310 movLeft2Result (left, offl, result, offr, 0);
4311 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4319 /* if (AOP(result)->type == AOP_REG) { */
4322 symbol *tlbl, *tlbl1;
4325 tlbl = newiTempLabel (NULL);
4326 tlbl1 = newiTempLabel (NULL);
4328 /* Left is already in result - so now do the shift */
4331 emit2 ("ld a,!immedbyte+1", shCount);
4332 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4333 emitLabel (tlbl->key + 100);
4340 l = aopGet (AOP (result), --offset, FALSE);
4345 emitLabel (tlbl1->key + 100);
4347 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4352 /*-----------------------------------------------------------------*/
4353 /* shiftL2Left2Result - shift left two bytes from left to result */
4354 /*-----------------------------------------------------------------*/
4356 shiftL2Left2Result (operand * left, int offl,
4357 operand * result, int offr, int shCount)
4359 if (sameRegs (AOP (result), AOP (left)) &&
4360 ((offl + MSB16) == offr))
4366 /* Copy left into result */
4367 movLeft2Result (left, offl, result, offr, 0);
4368 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4370 /* PENDING: for now just see if it'll work. */
4371 /*if (AOP(result)->type == AOP_REG) { */
4375 symbol *tlbl, *tlbl1;
4378 tlbl = newiTempLabel (NULL);
4379 tlbl1 = newiTempLabel (NULL);
4381 /* Left is already in result - so now do the shift */
4384 emit2 ("ld a,!immedbyte+1", shCount);
4385 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4386 emitLabel (tlbl->key + 100);
4392 l = aopGet (AOP (result), offset++, FALSE);
4397 emitLabel (tlbl1->key + 100);
4399 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4404 /*-----------------------------------------------------------------*/
4405 /* AccRol - rotate left accumulator by known count */
4406 /*-----------------------------------------------------------------*/
4408 AccRol (int shCount)
4410 shCount &= 0x0007; // shCount : 0..7
4449 /*-----------------------------------------------------------------*/
4450 /* AccLsh - left shift accumulator by known count */
4451 /*-----------------------------------------------------------------*/
4453 AccLsh (int shCount)
4455 static const unsigned char SLMask[] =
4457 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4466 else if (shCount == 2)
4473 /* rotate left accumulator */
4475 /* and kill the lower order bits */
4476 emit2 ("and a,!immedbyte", SLMask[shCount]);
4481 /*-----------------------------------------------------------------*/
4482 /* shiftL1Left2Result - shift left one byte from left to result */
4483 /*-----------------------------------------------------------------*/
4485 shiftL1Left2Result (operand * left, int offl,
4486 operand * result, int offr, int shCount)
4489 l = aopGet (AOP (left), offl, FALSE);
4491 /* shift left accumulator */
4493 aopPut (AOP (result), "a", offr);
4497 /*-----------------------------------------------------------------*/
4498 /* genlshTwo - left shift two bytes by known amount != 0 */
4499 /*-----------------------------------------------------------------*/
4501 genlshTwo (operand * result, operand * left, int shCount)
4503 int size = AOP_SIZE (result);
4505 wassert (size == 2);
4507 /* if shCount >= 8 */
4515 movLeft2Result (left, LSB, result, MSB16, 0);
4516 aopPut (AOP (result), "!zero", 0);
4517 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4521 movLeft2Result (left, LSB, result, MSB16, 0);
4522 aopPut (AOP (result), "!zero", 0);
4527 aopPut (AOP (result), "!zero", LSB);
4530 /* 1 <= shCount <= 7 */
4539 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4544 /*-----------------------------------------------------------------*/
4545 /* genlshOne - left shift a one byte quantity by known count */
4546 /*-----------------------------------------------------------------*/
4548 genlshOne (operand * result, operand * left, int shCount)
4550 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4553 /*-----------------------------------------------------------------*/
4554 /* genLeftShiftLiteral - left shifting by known count */
4555 /*-----------------------------------------------------------------*/
4557 genLeftShiftLiteral (operand * left,
4562 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4565 freeAsmop (right, NULL, ic);
4567 aopOp (left, ic, FALSE, FALSE);
4568 aopOp (result, ic, FALSE, FALSE);
4570 size = getSize (operandType (result));
4573 emit2 ("; shift left result %d, left %d", size,
4577 /* I suppose that the left size >= result size */
4583 else if (shCount >= (size * 8))
4585 aopPut (AOP (result), "!zero", size);
4591 genlshOne (result, left, shCount);
4594 genlshTwo (result, left, shCount);
4603 freeAsmop (left, NULL, ic);
4604 freeAsmop (result, NULL, ic);
4607 /*-----------------------------------------------------------------*/
4608 /* genLeftShift - generates code for left shifting */
4609 /*-----------------------------------------------------------------*/
4611 genLeftShift (iCode * ic)
4615 symbol *tlbl, *tlbl1;
4616 operand *left, *right, *result;
4618 right = IC_RIGHT (ic);
4619 left = IC_LEFT (ic);
4620 result = IC_RESULT (ic);
4622 aopOp (right, ic, FALSE, FALSE);
4624 /* if the shift count is known then do it
4625 as efficiently as possible */
4626 if (AOP_TYPE (right) == AOP_LIT)
4628 genLeftShiftLiteral (left, right, result, ic);
4632 /* shift count is unknown then we have to form a loop get the loop
4633 count in B : Note: we take only the lower order byte since
4634 shifting more that 32 bits make no sense anyway, ( the largest
4635 size of an object can be only 32 bits ) */
4636 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4638 freeAsmop (right, NULL, ic);
4639 aopOp (left, ic, FALSE, FALSE);
4640 aopOp (result, ic, FALSE, FALSE);
4642 /* now move the left to the result if they are not the
4645 if (!sameRegs (AOP (left), AOP (result)))
4648 size = AOP_SIZE (result);
4652 l = aopGet (AOP (left), offset, FALSE);
4653 aopPut (AOP (result), l, offset);
4658 size = AOP_SIZE (result);
4662 l = aopGet (AOP (left), offset, FALSE);
4663 aopPut (AOP (result), l, offset);
4669 tlbl = newiTempLabel (NULL);
4670 size = AOP_SIZE (result);
4672 tlbl1 = newiTempLabel (NULL);
4674 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4675 emitLabel (tlbl->key + 100);
4676 l = aopGet (AOP (result), offset, FALSE);
4680 l = aopGet (AOP (result), offset++, FALSE);
4683 emitLabel (tlbl1->key + 100);
4685 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4687 freeAsmop (left, NULL, ic);
4688 freeAsmop (result, NULL, ic);
4691 /*-----------------------------------------------------------------*/
4692 /* genrshOne - left shift two bytes by known amount != 0 */
4693 /*-----------------------------------------------------------------*/
4695 genrshOne (operand * result, operand * left, int shCount)
4698 int size = AOP_SIZE (result);
4701 wassert (size == 1);
4702 wassert (shCount < 8);
4704 l = aopGet (AOP (left), 0, FALSE);
4705 if (AOP (result)->type == AOP_REG)
4707 aopPut (AOP (result), l, 0);
4708 l = aopGet (AOP (result), 0, FALSE);
4710 emit2 ("srl %s", l);
4719 aopPut (AOP (result), "a", 0);
4723 /*-----------------------------------------------------------------*/
4724 /* AccRsh - right shift accumulator by known count */
4725 /*-----------------------------------------------------------------*/
4727 AccRsh (int shCount)
4729 static const unsigned char SRMask[] =
4731 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4736 /* rotate right accumulator */
4737 AccRol (8 - shCount);
4738 /* and kill the higher order bits */
4739 emit2 ("and a,!immedbyte", SRMask[shCount]);
4743 /*-----------------------------------------------------------------*/
4744 /* shiftR1Left2Result - shift right one byte from left to result */
4745 /*-----------------------------------------------------------------*/
4747 shiftR1Left2Result (operand * left, int offl,
4748 operand * result, int offr,
4749 int shCount, int sign)
4751 _moveA (aopGet (AOP (left), offl, FALSE));
4760 aopPut (AOP (result), "a", offr);
4763 /*-----------------------------------------------------------------*/
4764 /* genrshTwo - right shift two bytes by known amount != 0 */
4765 /*-----------------------------------------------------------------*/
4767 genrshTwo (operand * result, operand * left,
4768 int shCount, int sign)
4770 /* if shCount >= 8 */
4776 shiftR1Left2Result (left, MSB16, result, LSB,
4781 movLeft2Result (left, MSB16, result, LSB, sign);
4783 aopPut (AOP (result), "!zero", 1);
4785 /* 1 <= shCount <= 7 */
4788 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4792 /*-----------------------------------------------------------------*/
4793 /* genRightShiftLiteral - left shifting by known count */
4794 /*-----------------------------------------------------------------*/
4796 genRightShiftLiteral (operand * left,
4801 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4804 freeAsmop (right, NULL, ic);
4806 aopOp (left, ic, FALSE, FALSE);
4807 aopOp (result, ic, FALSE, FALSE);
4809 size = getSize (operandType (result));
4811 emit2 ("; shift right result %d, left %d", size,
4814 /* I suppose that the left size >= result size */
4820 else if (shCount >= (size * 8))
4822 aopPut (AOP (result), "!zero", size);
4828 genrshOne (result, left, shCount);
4831 /* PENDING: sign support */
4832 genrshTwo (result, left, shCount, FALSE);
4841 freeAsmop (left, NULL, ic);
4842 freeAsmop (result, NULL, ic);
4845 /*-----------------------------------------------------------------*/
4846 /* genRightShift - generate code for right shifting */
4847 /*-----------------------------------------------------------------*/
4849 genRightShift (iCode * ic)
4851 operand *right, *left, *result;
4853 int size, offset, first = 1;
4857 symbol *tlbl, *tlbl1;
4859 /* if signed then we do it the hard way preserve the
4860 sign bit moving it inwards */
4861 retype = getSpec (operandType (IC_RESULT (ic)));
4863 is_signed = !SPEC_USIGN (retype);
4865 /* signed & unsigned types are treated the same : i.e. the
4866 signed is NOT propagated inwards : quoting from the
4867 ANSI - standard : "for E1 >> E2, is equivalent to division
4868 by 2**E2 if unsigned or if it has a non-negative value,
4869 otherwise the result is implementation defined ", MY definition
4870 is that the sign does not get propagated */
4872 right = IC_RIGHT (ic);
4873 left = IC_LEFT (ic);
4874 result = IC_RESULT (ic);
4876 aopOp (right, ic, FALSE, FALSE);
4878 /* if the shift count is known then do it
4879 as efficiently as possible */
4880 if (AOP_TYPE (right) == AOP_LIT)
4882 genRightShiftLiteral (left, right, result, ic);
4886 aopOp (left, ic, FALSE, FALSE);
4887 aopOp (result, ic, FALSE, FALSE);
4889 /* now move the left to the result if they are not the
4891 if (!sameRegs (AOP (left), AOP (result)) &&
4892 AOP_SIZE (result) > 1)
4895 size = AOP_SIZE (result);
4899 l = aopGet (AOP (left), offset, FALSE);
4900 aopPut (AOP (result), l, offset);
4905 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4907 freeAsmop (right, NULL, ic);
4909 tlbl = newiTempLabel (NULL);
4910 tlbl1 = newiTempLabel (NULL);
4911 size = AOP_SIZE (result);
4914 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4915 emitLabel (tlbl->key + 100);
4918 l = aopGet (AOP (result), offset--, FALSE);
4922 emit2 ("sra %s", l);
4924 emit2 ("srl %s", l);
4930 emitLabel (tlbl1->key + 100);
4932 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4934 freeAsmop (left, NULL, ic);
4935 freeAsmop (result, NULL, ic);
4938 /*-----------------------------------------------------------------*/
4939 /* genGenPointerGet - get value from generic pointer space */
4940 /*-----------------------------------------------------------------*/
4942 genGenPointerGet (operand * left,
4943 operand * result, iCode * ic)
4946 sym_link *retype = getSpec (operandType (result));
4952 aopOp (left, ic, FALSE, FALSE);
4953 aopOp (result, ic, FALSE, FALSE);
4955 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4958 if (isPtrPair (AOP (left)))
4960 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4961 aopPut (AOP (result), buffer, 0);
4965 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4966 aopPut (AOP (result), "a", 0);
4968 freeAsmop (left, NULL, ic);
4972 /* For now we always load into IY */
4973 /* if this is remateriazable */
4974 fetchPair (pair, AOP (left));
4976 /* so iy now contains the address */
4977 freeAsmop (left, NULL, ic);
4979 /* if bit then unpack */
4980 if (IS_BITVAR (retype))
4986 size = AOP_SIZE (result);
4991 /* PENDING: make this better */
4992 if (!IS_GB && AOP (result)->type == AOP_REG)
4994 aopPut (AOP (result), "!*hl", offset++);
4998 emit2 ("ld a,!*pair", _pairs[pair].name);
4999 aopPut (AOP (result), "a", offset++);
5003 emit2 ("inc %s", _pairs[pair].name);
5004 _G.pairs[pair].offset++;
5010 freeAsmop (result, NULL, ic);
5013 /*-----------------------------------------------------------------*/
5014 /* genPointerGet - generate code for pointer get */
5015 /*-----------------------------------------------------------------*/
5017 genPointerGet (iCode * ic)
5019 operand *left, *result;
5020 sym_link *type, *etype;
5022 left = IC_LEFT (ic);
5023 result = IC_RESULT (ic);
5025 /* depending on the type of pointer we need to
5026 move it to the correct pointer register */
5027 type = operandType (left);
5028 etype = getSpec (type);
5030 genGenPointerGet (left, result, ic);
5034 isRegOrLit (asmop * aop)
5036 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
5041 /*-----------------------------------------------------------------*/
5042 /* genGenPointerSet - stores the value into a pointer location */
5043 /*-----------------------------------------------------------------*/
5045 genGenPointerSet (operand * right,
5046 operand * result, iCode * ic)
5049 sym_link *retype = getSpec (operandType (right));
5050 PAIR_ID pairId = PAIR_HL;
5052 aopOp (result, ic, FALSE, FALSE);
5053 aopOp (right, ic, FALSE, FALSE);
5058 /* Handle the exceptions first */
5059 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5062 const char *l = aopGet (AOP (right), 0, FALSE);
5063 const char *pair = getPairName (AOP (result));
5064 if (canAssignToPtr (l) && isPtr (pair))
5066 emit2 ("ld !*pair,%s", pair, l);
5071 emit2 ("ld !*pair,a", pair);
5076 /* if the operand is already in dptr
5077 then we do nothing else we move the value to dptr */
5078 if (AOP_TYPE (result) != AOP_STR)
5080 fetchPair (pairId, AOP (result));
5082 /* so hl know contains the address */
5083 freeAsmop (result, NULL, ic);
5085 /* if bit then unpack */
5086 if (IS_BITVAR (retype))
5092 size = AOP_SIZE (right);
5097 const char *l = aopGet (AOP (right), offset, FALSE);
5098 if (isRegOrLit (AOP (right)) && !IS_GB)
5100 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5105 emit2 ("ld !*pair,a", _pairs[pairId].name);
5109 emit2 ("inc %s", _pairs[pairId].name);
5110 _G.pairs[pairId].offset++;
5116 freeAsmop (right, NULL, ic);
5119 /*-----------------------------------------------------------------*/
5120 /* genPointerSet - stores the value into a pointer location */
5121 /*-----------------------------------------------------------------*/
5123 genPointerSet (iCode * ic)
5125 operand *right, *result;
5126 sym_link *type, *etype;
5128 right = IC_RIGHT (ic);
5129 result = IC_RESULT (ic);
5131 /* depending on the type of pointer we need to
5132 move it to the correct pointer register */
5133 type = operandType (result);
5134 etype = getSpec (type);
5136 genGenPointerSet (right, result, ic);
5139 /*-----------------------------------------------------------------*/
5140 /* genIfx - generate code for Ifx statement */
5141 /*-----------------------------------------------------------------*/
5143 genIfx (iCode * ic, iCode * popIc)
5145 operand *cond = IC_COND (ic);
5148 aopOp (cond, ic, FALSE, TRUE);
5150 /* get the value into acc */
5151 if (AOP_TYPE (cond) != AOP_CRY)
5155 /* the result is now in the accumulator */
5156 freeAsmop (cond, NULL, ic);
5158 /* if there was something to be popped then do it */
5162 /* if the condition is a bit variable */
5163 if (isbit && IS_ITEMP (cond) &&
5165 genIfxJump (ic, SPIL_LOC (cond)->rname);
5166 else if (isbit && !IS_ITEMP (cond))
5167 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5169 genIfxJump (ic, "a");
5174 /*-----------------------------------------------------------------*/
5175 /* genAddrOf - generates code for address of */
5176 /*-----------------------------------------------------------------*/
5178 genAddrOf (iCode * ic)
5180 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5182 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5184 /* if the operand is on the stack then we
5185 need to get the stack offset of this
5192 if (sym->stack <= 0)
5194 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5198 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5205 emit2 ("ld de,!hashedstr", sym->rname);
5207 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5208 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5215 /* if it has an offset then we need to compute it */
5217 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5219 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5220 emit2 ("add hl,sp");
5224 emit2 ("ld hl,#%s", sym->rname);
5226 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5227 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5229 freeAsmop (IC_RESULT (ic), NULL, ic);
5232 /*-----------------------------------------------------------------*/
5233 /* genAssign - generate code for assignment */
5234 /*-----------------------------------------------------------------*/
5236 genAssign (iCode * ic)
5238 operand *result, *right;
5240 unsigned long lit = 0L;
5242 result = IC_RESULT (ic);
5243 right = IC_RIGHT (ic);
5246 /* Dont bother assigning if they are the same */
5247 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5249 emit2 ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5254 aopOp (right, ic, FALSE, FALSE);
5255 aopOp (result, ic, TRUE, FALSE);
5257 /* if they are the same registers */
5258 if (sameRegs (AOP (right), AOP (result)))
5260 emit2 ("; (registers are the same)");
5264 /* if the result is a bit */
5265 if (AOP_TYPE (result) == AOP_CRY)
5271 size = AOP_SIZE (result);
5274 if (AOP_TYPE (right) == AOP_LIT)
5275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5276 if (isPair (AOP (result)))
5278 fetchPair (getPairId (AOP (result)), AOP (right));
5280 else if ((size > 1) &&
5281 (AOP_TYPE (result) != AOP_REG) &&
5282 (AOP_TYPE (right) == AOP_LIT) &&
5283 !IS_FLOAT (operandType (right)) &&
5286 bool fXored = FALSE;
5288 /* Work from the top down.
5289 Done this way so that we can use the cached copy of 0
5290 in A for a fast clear */
5293 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5295 if (!fXored && size > 1)
5302 aopPut (AOP (result), "a", offset);
5306 aopPut (AOP (result), "!zero", offset);
5310 aopPut (AOP (result),
5311 aopGet (AOP (right), offset, FALSE),
5316 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5318 /* Special case. Load into a and d, then load out. */
5319 _moveA (aopGet (AOP (right), 0, FALSE));
5320 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5321 aopPut (AOP (result), "a", 0);
5322 aopPut (AOP (result), "e", 1);
5328 /* PENDING: do this check better */
5329 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5331 _moveA (aopGet (AOP (right), offset, FALSE));
5332 aopPut (AOP (result), "a", offset);
5335 aopPut (AOP (result),
5336 aopGet (AOP (right), offset, FALSE),
5343 freeAsmop (right, NULL, ic);
5344 freeAsmop (result, NULL, ic);
5347 /*-----------------------------------------------------------------*/
5348 /* genJumpTab - genrates code for jump table */
5349 /*-----------------------------------------------------------------*/
5351 genJumpTab (iCode * ic)
5356 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5357 /* get the condition into accumulator */
5358 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5361 emit2 ("ld e,%s", l);
5362 emit2 ("ld d,!zero");
5363 jtab = newiTempLabel (NULL);
5365 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5366 emit2 ("add hl,de");
5367 emit2 ("add hl,de");
5368 emit2 ("add hl,de");
5369 freeAsmop (IC_JTCOND (ic), NULL, ic);
5373 emitLabel (jtab->key + 100);
5374 /* now generate the jump labels */
5375 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5376 jtab = setNextItem (IC_JTLABELS (ic)))
5377 emit2 ("jp !tlabel", jtab->key + 100);
5380 /*-----------------------------------------------------------------*/
5381 /* genCast - gen code for casting */
5382 /*-----------------------------------------------------------------*/
5384 genCast (iCode * ic)
5386 operand *result = IC_RESULT (ic);
5387 sym_link *ctype = operandType (IC_LEFT (ic));
5388 operand *right = IC_RIGHT (ic);
5391 /* if they are equivalent then do nothing */
5392 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5395 aopOp (right, ic, FALSE, FALSE);
5396 aopOp (result, ic, FALSE, FALSE);
5398 /* if the result is a bit */
5399 if (AOP_TYPE (result) == AOP_CRY)
5404 /* if they are the same size : or less */
5405 if (AOP_SIZE (result) <= AOP_SIZE (right))
5408 /* if they are in the same place */
5409 if (sameRegs (AOP (right), AOP (result)))
5412 /* if they in different places then copy */
5413 size = AOP_SIZE (result);
5417 aopPut (AOP (result),
5418 aopGet (AOP (right), offset, FALSE),
5425 /* PENDING: should be OK. */
5427 /* if the result is of type pointer */
5434 /* so we now know that the size of destination is greater
5435 than the size of the source */
5436 /* we move to result for the size of source */
5437 size = AOP_SIZE (right);
5441 aopPut (AOP (result),
5442 aopGet (AOP (right), offset, FALSE),
5447 /* now depending on the sign of the destination */
5448 size = AOP_SIZE (result) - AOP_SIZE (right);
5449 /* Unsigned or not an integral type - right fill with zeros */
5450 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5453 aopPut (AOP (result), "!zero", offset++);
5457 /* we need to extend the sign :{ */
5458 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5461 emit2 ("; genCast: sign extend untested.");
5465 aopPut (AOP (result), "a", offset++);
5469 freeAsmop (right, NULL, ic);
5470 freeAsmop (result, NULL, ic);
5473 /*-----------------------------------------------------------------*/
5474 /* genReceive - generate code for a receive iCode */
5475 /*-----------------------------------------------------------------*/
5477 genReceive (iCode * ic)
5479 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5480 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5481 IS_TRUE_SYMOP (IC_RESULT (ic))))
5491 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5492 size = AOP_SIZE(IC_RESULT(ic));
5494 for (i = 0; i < size; i++) {
5495 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5499 freeAsmop (IC_RESULT (ic), NULL, ic);
5502 /*-----------------------------------------------------------------*/
5503 /* genZ80Code - generate code for Z80 based controllers */
5504 /*-----------------------------------------------------------------*/
5506 genZ80Code (iCode * lic)
5514 _fReturn = _gbz80_return;
5515 _fTmp = _gbz80_return;
5519 _fReturn = _z80_return;
5520 _fTmp = _z80_return;
5523 _G.lines.head = _G.lines.current = NULL;
5525 for (ic = lic; ic; ic = ic->next)
5528 if (cln != ic->lineno)
5530 emit2 ("; %s %d", ic->filename, ic->lineno);
5533 /* if the result is marked as
5534 spilt and rematerializable or code for
5535 this has already been generated then
5537 if (resultRemat (ic) || ic->generated)
5540 /* depending on the operation */
5554 emit2 ("; genUminus");
5559 emit2 ("; genIpush");
5564 /* IPOP happens only when trying to restore a
5565 spilt live range, if there is an ifx statement
5566 following this pop then the if statement might
5567 be using some of the registers being popped which
5568 would destory the contents of the register so
5569 we need to check for this condition and handle it */
5571 ic->next->op == IFX &&
5572 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5575 genIfx (ic->next, ic);
5579 emit2 ("; genIpop");
5585 emit2 ("; genCall");
5590 emit2 ("; genPcall");
5595 emit2 ("; genFunction");
5600 emit2 ("; genEndFunction");
5601 genEndFunction (ic);
5610 emit2 ("; genLabel");
5615 emit2 ("; genGoto");
5620 emit2 ("; genPlus");
5625 emit2 ("; genMinus");
5630 emit2 ("; genMult");
5645 emit2 ("; genCmpGt");
5646 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5650 emit2 ("; genCmpLt");
5651 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5658 /* note these two are xlated by algebraic equivalence
5659 during parsing SDCC.y */
5660 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5661 "got '>=' or '<=' shouldn't have come here");
5665 emit2 ("; genCmpEq");
5666 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5670 emit2 ("; genAndOp");
5675 emit2 ("; genOrOp");
5681 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5686 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5691 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5695 emit2 ("; genInline");
5710 emit2 ("; genHBIT");
5714 emit2 ("; genLeftShift");
5719 emit2 ("; genRightShift");
5723 case GET_VALUE_AT_ADDRESS:
5724 emit2 ("; genPointerGet");
5730 if (POINTER_SET (ic))
5732 emit2 ("; genAssign (pointer)");
5737 emit2 ("; genAssign");
5748 emit2 ("; genAddrOf");
5753 emit2 ("; genJumpTab");
5758 emit2 ("; genCast");
5763 emit2 ("; genReceive");
5769 addSet (&_G.sendSet, ic);
5774 /* piCode(ic,stdout); */
5780 /* now we are ready to call the
5781 peep hole optimizer */
5782 if (!options.nopeep)
5783 peepHole (&_G.lines.head);
5785 /* This is unfortunate */
5786 /* now do the actual printing */
5788 FILE *fp = codeOutFile;
5789 if (isInHome () && codeOutFile == code->oFile)
5790 codeOutFile = home->oFile;
5791 printLine (_G.lines.head, codeOutFile);
5792 if (_G.flushStatics)
5795 _G.flushStatics = 0;
5804 _isPairUsed (iCode * ic, PAIR_ID pairId)
5810 if (bitVectBitValue (ic->rMask, D_IDX))
5812 if (bitVectBitValue (ic->rMask, E_IDX))