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;
1746 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1748 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
1749 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
1751 deSending = (sendSetSize > 1);
1753 emit2 ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
1755 if (bcInUse && bcInRet == FALSE) {
1757 _G.stack.pushedBC = TRUE;
1759 if (deInUse && deInRet == FALSE) {
1761 _G.stack.pushedDE = TRUE;
1764 _G.saves.saved = TRUE;
1767 /* Already saved. */
1771 /*-----------------------------------------------------------------*/
1772 /* genIpush - genrate code for pushing this gets a little complex */
1773 /*-----------------------------------------------------------------*/
1775 genIpush (iCode * ic)
1777 int size, offset = 0;
1780 /* if this is not a parm push : ie. it is spill push
1781 and spill push is always done on the local stack */
1784 wassertl(0, "Encountered an unsupported spill push.");
1786 /* and the item is spilt then do nothing */
1787 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1790 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1791 size = AOP_SIZE (IC_LEFT (ic));
1792 /* push it on the stack */
1793 if (isPair (AOP (IC_LEFT (ic))))
1795 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1796 _G.stack.pushed += 2;
1803 /* Simple for now - load into A and PUSH AF */
1804 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1806 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1808 emit2 ("ld a,(%s)", l);
1812 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1813 emit2 ("ld a,%s", l);
1824 if (_G.saves.saved == FALSE) {
1825 /* Caller saves, and this is the first iPush. */
1826 /* Scan ahead until we find the function that we are pushing parameters to.
1827 Count the number of addSets on the way to figure out what registers
1828 are used in the send set.
1831 iCode *walk = ic->next;
1834 if (walk->op == SEND) {
1837 else if (walk->op == CALL || walk->op == PCALL) {
1846 _saveRegsForCall(walk, nAddSets);
1849 /* Already saved by another iPush. */
1852 /* then do the push */
1853 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1855 size = AOP_SIZE (IC_LEFT (ic));
1857 if (isPair (AOP (IC_LEFT (ic))))
1859 _G.stack.pushed += 2;
1860 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1866 fetchHL (AOP (IC_LEFT (ic)));
1868 spillPair (PAIR_HL);
1869 _G.stack.pushed += 2;
1874 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1876 spillPair (PAIR_HL);
1877 _G.stack.pushed += 2;
1878 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1880 spillPair (PAIR_HL);
1881 _G.stack.pushed += 2;
1887 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1889 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1891 emit2 ("ld a,(%s)", l);
1895 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1896 emit2 ("ld a,%s", l);
1904 freeAsmop (IC_LEFT (ic), NULL, ic);
1907 /*-----------------------------------------------------------------*/
1908 /* genIpop - recover the registers: can happen only for spilling */
1909 /*-----------------------------------------------------------------*/
1911 genIpop (iCode * ic)
1916 /* if the temp was not pushed then */
1917 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1920 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1921 size = AOP_SIZE (IC_LEFT (ic));
1922 offset = (size - 1);
1923 if (isPair (AOP (IC_LEFT (ic))))
1925 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
1933 spillPair (PAIR_HL);
1934 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1938 freeAsmop (IC_LEFT (ic), NULL, ic);
1941 /* This is quite unfortunate */
1943 setArea (int inHome)
1946 static int lastArea = 0;
1948 if (_G.in_home != inHome) {
1950 const char *sz = port->mem.code_name;
1951 port->mem.code_name = "HOME";
1952 emit2("!area", CODE_NAME);
1953 port->mem.code_name = sz;
1956 emit2("!area", CODE_NAME); */
1957 _G.in_home = inHome;
1967 /** Emit the code for a call statement
1970 emitCall (iCode * ic, bool ispcall)
1972 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
1974 /* if caller saves & we have not saved then */
1980 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
1982 /* if send set is not empty then assign */
1988 int _z80_sendOrder[] = {
1989 PAIR_BC, PAIR_DE, PAIR_INVALID
1992 for (sic = setFirstItem (_G.sendSet); sic;
1993 sic = setNextItem (_G.sendSet))
1996 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1998 size = AOP_SIZE (IC_LEFT (sic));
1999 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2000 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2002 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2005 freeAsmop (IC_LEFT (sic), NULL, sic);
2012 if (IS_BANKEDCALL (detype))
2014 werror (W_INDIR_BANKED);
2016 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2018 if (isLitWord (AOP (IC_LEFT (ic))))
2020 emit2 ("; Special case where the pCall is to a constant");
2021 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2025 symbol *rlbl = newiTempLabel (NULL);
2026 spillPair (PAIR_HL);
2027 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2029 _G.stack.pushed += 2;
2031 fetchHL (AOP (IC_LEFT (ic)));
2033 emit2 ("!tlabeldef", (rlbl->key + 100));
2034 _G.stack.pushed -= 2;
2036 freeAsmop (IC_LEFT (ic), NULL, ic);
2040 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2041 OP_SYMBOL (IC_LEFT (ic))->rname :
2042 OP_SYMBOL (IC_LEFT (ic))->name;
2043 if (IS_BANKEDCALL (detype))
2045 emit2 ("call banked_call");
2046 emit2 ("!dws", name);
2047 emit2 ("!dw !bankimmeds", name);
2052 emit2 ("call %s", name);
2057 /* Mark the regsiters as restored. */
2058 _G.saves.saved = FALSE;
2060 /* if we need assign a result value */
2061 if ((IS_ITEMP (IC_RESULT (ic)) &&
2062 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2063 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2064 IS_TRUE_SYMOP (IC_RESULT (ic)))
2067 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2069 assignResultValue (IC_RESULT (ic));
2071 freeAsmop (IC_RESULT (ic), NULL, ic);
2074 /* adjust the stack for parameters if required */
2077 int i = ic->parmBytes;
2078 _G.stack.pushed -= i;
2081 emit2 ("!ldaspsp", i);
2088 emit2 ("ld hl,#%d", i);
2089 emit2 ("add hl,sp");
2106 if (_G.stack.pushedDE)
2109 _G.stack.pushedDE = FALSE;
2112 if (_G.stack.pushedBC)
2115 _G.stack.pushedBC = FALSE;
2119 /*-----------------------------------------------------------------*/
2120 /* genCall - generates a call statement */
2121 /*-----------------------------------------------------------------*/
2123 genCall (iCode * ic)
2125 emitCall (ic, FALSE);
2128 /*-----------------------------------------------------------------*/
2129 /* genPcall - generates a call by pointer statement */
2130 /*-----------------------------------------------------------------*/
2132 genPcall (iCode * ic)
2134 emitCall (ic, TRUE);
2137 /*-----------------------------------------------------------------*/
2138 /* resultRemat - result is rematerializable */
2139 /*-----------------------------------------------------------------*/
2141 resultRemat (iCode * ic)
2143 if (SKIP_IC (ic) || ic->op == IFX)
2146 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2148 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2149 if (sym->remat && !POINTER_SET (ic))
2156 extern set *publics;
2160 o Check emitCall and clean up
2162 o Check return puller
2164 PENDING: Remove this.
2167 /*-----------------------------------------------------------------*/
2168 /* genFunction - generated code for function entry */
2169 /*-----------------------------------------------------------------*/
2171 genFunction (iCode * ic)
2173 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2177 bool bcInUse = FALSE;
2178 bool deInUse = FALSE;
2181 setArea (IS_NONBANKED (sym->etype));
2183 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2186 _G.receiveOffset = 0;
2190 if (!IS_STATIC (sym->etype))
2192 addSetIfnotP (&publics, sym);
2196 /* Record the last function name for debugging. */
2197 _G.lastFunctionName = sym->rname;
2199 /* Create the function header */
2200 emit2 ("!functionheader", sym->name);
2201 /* PENDING: portability. */
2202 emit2 ("__%s_start:", sym->rname);
2203 emit2 ("!functionlabeldef", sym->rname);
2205 fetype = getSpec (operandType (IC_LEFT (ic)));
2207 /* if critical function then turn interrupts off */
2208 if (SPEC_CRTCL (fetype))
2211 /* if this is an interrupt service routine then save all potentially used registers. */
2212 if (IS_ISR (sym->etype))
2217 /* PENDING: callee-save etc */
2219 _G.stack.param_offset = 0;
2222 /* Detect which registers are used. */
2226 for (i = 0; i < sym->regsUsed->size; i++)
2228 if (bitVectBitValue (sym->regsUsed, i))
2242 /* Other systems use DE as a temporary. */
2253 _G.stack.param_offset += 2;
2256 _G.stack.pushedBC = bcInUse;
2261 _G.stack.param_offset += 2;
2264 _G.stack.pushedDE = deInUse;
2267 /* adjust the stack for the function */
2268 _G.stack.last = sym->stack;
2271 emit2 ("!enterx", sym->stack);
2274 _G.stack.offset = sym->stack;
2277 /*-----------------------------------------------------------------*/
2278 /* genEndFunction - generates epilogue for functions */
2279 /*-----------------------------------------------------------------*/
2281 genEndFunction (iCode * ic)
2283 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2285 if (IS_ISR (sym->etype))
2291 if (SPEC_CRTCL (sym->etype))
2294 /* PENDING: calleeSave */
2296 if (_G.stack.offset)
2298 emit2 ("!leavex", _G.stack.offset);
2306 if (_G.stack.pushedDE)
2309 _G.stack.pushedDE = FALSE;
2312 if (_G.stack.pushedDE)
2315 _G.stack.pushedDE = FALSE;
2319 /* Both baned and non-banked just ret */
2322 /* PENDING: portability. */
2323 emit2 ("__%s_end:", sym->rname);
2325 _G.flushStatics = 1;
2326 _G.stack.pushed = 0;
2327 _G.stack.offset = 0;
2330 /*-----------------------------------------------------------------*/
2331 /* genRet - generate code for return statement */
2332 /*-----------------------------------------------------------------*/
2337 /* Errk. This is a hack until I can figure out how
2338 to cause dehl to spill on a call */
2339 int size, offset = 0;
2341 /* if we have no return value then
2342 just generate the "ret" */
2346 /* we have something to return then
2347 move the return value into place */
2348 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2349 size = AOP_SIZE (IC_LEFT (ic));
2351 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2355 emit2 ("ld de,%s", l);
2359 emit2 ("ld hl,%s", l);
2364 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2366 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2367 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2373 l = aopGet (AOP (IC_LEFT (ic)), offset,
2375 if (strcmp (_fReturn[offset], l))
2376 emit2 ("ld %s,%s", _fReturn[offset++], l);
2380 freeAsmop (IC_LEFT (ic), NULL, ic);
2383 /* generate a jump to the return label
2384 if the next is not the return statement */
2385 if (!(ic->next && ic->next->op == LABEL &&
2386 IC_LABEL (ic->next) == returnLabel))
2388 emit2 ("jp !tlabel", returnLabel->key + 100);
2391 /*-----------------------------------------------------------------*/
2392 /* genLabel - generates a label */
2393 /*-----------------------------------------------------------------*/
2395 genLabel (iCode * ic)
2397 /* special case never generate */
2398 if (IC_LABEL (ic) == entryLabel)
2401 emitLabel (IC_LABEL (ic)->key + 100);
2404 /*-----------------------------------------------------------------*/
2405 /* genGoto - generates a ljmp */
2406 /*-----------------------------------------------------------------*/
2408 genGoto (iCode * ic)
2410 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2413 /*-----------------------------------------------------------------*/
2414 /* genPlusIncr :- does addition with increment if possible */
2415 /*-----------------------------------------------------------------*/
2417 genPlusIncr (iCode * ic)
2419 unsigned int icount;
2420 unsigned int size = getDataSize (IC_RESULT (ic));
2421 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2423 /* will try to generate an increment */
2424 /* if the right side is not a literal
2426 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2429 emit2 ("; genPlusIncr");
2431 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2433 /* If result is a pair */
2434 if (resultId != PAIR_INVALID)
2436 if (isLitWord (AOP (IC_LEFT (ic))))
2438 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2441 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2443 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2444 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2450 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2454 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2455 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2459 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2464 /* if the literal value of the right hand side
2465 is greater than 4 then it is not worth it */
2469 /* if increment 16 bits in register */
2470 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2476 symbol *tlbl = NULL;
2477 tlbl = newiTempLabel (NULL);
2480 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2483 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2486 emitLabel (tlbl->key + 100);
2490 /* if the sizes are greater than 1 then we cannot */
2491 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2492 AOP_SIZE (IC_LEFT (ic)) > 1)
2495 /* we can if the aops of the left & result match or
2496 if they are in registers and the registers are the
2498 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2501 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2508 /*-----------------------------------------------------------------*/
2509 /* outBitAcc - output a bit in acc */
2510 /*-----------------------------------------------------------------*/
2512 outBitAcc (operand * result)
2514 symbol *tlbl = newiTempLabel (NULL);
2515 /* if the result is a bit */
2516 if (AOP_TYPE (result) == AOP_CRY)
2522 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2523 emit2 ("ld a,!one");
2524 emitLabel (tlbl->key + 100);
2529 /*-----------------------------------------------------------------*/
2530 /* genPlus - generates code for addition */
2531 /*-----------------------------------------------------------------*/
2533 genPlus (iCode * ic)
2535 int size, offset = 0;
2537 /* special cases :- */
2539 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2540 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2541 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2543 /* Swap the left and right operands if:
2545 if literal, literal on the right or
2546 if left requires ACC or right is already
2549 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2550 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2551 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2553 operand *t = IC_RIGHT (ic);
2554 IC_RIGHT (ic) = IC_LEFT (ic);
2558 /* if both left & right are in bit
2560 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2561 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2567 /* if left in bit space & right literal */
2568 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2569 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2571 /* Can happen I guess */
2575 /* if I can do an increment instead
2576 of add then GOOD for ME */
2577 if (genPlusIncr (ic) == TRUE)
2580 emit2 ("; genPlusIncr failed");
2582 size = getDataSize (IC_RESULT (ic));
2584 /* Special case when left and right are constant */
2585 if (isPair (AOP (IC_RESULT (ic))))
2589 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2590 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2596 sprintf (buffer, "#(%s + %s)", left, right);
2597 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2602 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2604 /* Fetch into HL then do the add */
2605 spillPair (PAIR_HL);
2606 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2607 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2612 ld hl,sp+n trashes C so we cant afford to do it during an
2613 add with stack based varibles. Worst case is:
2626 So you cant afford to load up hl if either left, right, or result
2627 is on the stack (*sigh*) The alt is:
2635 Combinations in here are:
2636 * If left or right are in bc then the loss is small - trap later
2637 * If the result is in bc then the loss is also small
2641 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2642 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2643 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2645 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2646 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2647 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2648 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2650 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2652 /* Swap left and right */
2653 operand *t = IC_RIGHT (ic);
2654 IC_RIGHT (ic) = IC_LEFT (ic);
2657 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2659 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2660 emit2 ("add hl,bc");
2664 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2665 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2666 emit2 ("add hl,de");
2668 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2673 emit2 ("; WARNING: This add is probably broken.\n");
2680 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2682 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2685 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2688 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2692 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2695 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2698 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2700 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2704 freeAsmop (IC_LEFT (ic), NULL, ic);
2705 freeAsmop (IC_RIGHT (ic), NULL, ic);
2706 freeAsmop (IC_RESULT (ic), NULL, ic);
2710 /*-----------------------------------------------------------------*/
2711 /* genMinusDec :- does subtraction with deccrement if possible */
2712 /*-----------------------------------------------------------------*/
2714 genMinusDec (iCode * ic)
2716 unsigned int icount;
2717 unsigned int size = getDataSize (IC_RESULT (ic));
2719 /* will try to generate an increment */
2720 /* if the right side is not a literal we cannot */
2721 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2724 /* if the literal value of the right hand side
2725 is greater than 4 then it is not worth it */
2726 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2729 size = getDataSize (IC_RESULT (ic));
2732 /* if increment 16 bits in register */
2733 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2737 symbol *tlbl = newiTempLabel (NULL);
2738 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2739 emit2 ("jp np," LABEL_STR, tlbl->key + 100);
2741 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2746 emitLabel (tlbl->key + 100);
2751 /* if decrement 16 bits in register */
2752 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2753 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2756 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2760 /* If result is a pair */
2761 if (isPair (AOP (IC_RESULT (ic))))
2763 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2764 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2766 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2770 /* if the sizes are greater than 1 then we cannot */
2771 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2772 AOP_SIZE (IC_LEFT (ic)) > 1)
2775 /* we can if the aops of the left & result match or if they are in
2776 registers and the registers are the same */
2777 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2780 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2787 /*-----------------------------------------------------------------*/
2788 /* genMinus - generates code for subtraction */
2789 /*-----------------------------------------------------------------*/
2791 genMinus (iCode * ic)
2793 int size, offset = 0;
2794 unsigned long lit = 0L;
2796 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2797 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2798 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2800 /* special cases :- */
2801 /* if both left & right are in bit space */
2802 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2803 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2809 /* if I can do an decrement instead of subtract then GOOD for ME */
2810 if (genMinusDec (ic) == TRUE)
2813 size = getDataSize (IC_RESULT (ic));
2815 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2820 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2824 /* Same logic as genPlus */
2827 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2828 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2829 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2831 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2832 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2833 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2834 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2836 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2837 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2839 if (left == PAIR_INVALID && right == PAIR_INVALID)
2844 else if (right == PAIR_INVALID)
2846 else if (left == PAIR_INVALID)
2849 fetchPair (left, AOP (IC_LEFT (ic)));
2850 /* Order is important. Right may be HL */
2851 fetchPair (right, AOP (IC_RIGHT (ic)));
2853 emit2 ("ld a,%s", _pairs[left].l);
2854 emit2 ("sub a,%s", _pairs[right].l);
2856 emit2 ("ld a,%s", _pairs[left].h);
2857 emit2 ("sbc a,%s", _pairs[right].h);
2859 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2860 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2865 emit2 ("; WARNING: This sub is probably broken.\n");
2870 /* if literal, add a,#-lit, else normal subb */
2873 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2874 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2878 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2881 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2885 /* first add without previous c */
2887 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2889 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2891 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2894 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2895 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2896 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2900 freeAsmop (IC_LEFT (ic), NULL, ic);
2901 freeAsmop (IC_RIGHT (ic), NULL, ic);
2902 freeAsmop (IC_RESULT (ic), NULL, ic);
2905 /*-----------------------------------------------------------------*/
2906 /* genMult - generates code for multiplication */
2907 /*-----------------------------------------------------------------*/
2909 genMult (iCode * ic)
2911 /* Shouldn't occur - all done through function calls */
2915 /*-----------------------------------------------------------------*/
2916 /* genDiv - generates code for division */
2917 /*-----------------------------------------------------------------*/
2921 /* Shouldn't occur - all done through function calls */
2925 /*-----------------------------------------------------------------*/
2926 /* genMod - generates code for division */
2927 /*-----------------------------------------------------------------*/
2931 /* Shouldn't occur - all done through function calls */
2935 /*-----------------------------------------------------------------*/
2936 /* genIfxJump :- will create a jump depending on the ifx */
2937 /*-----------------------------------------------------------------*/
2939 genIfxJump (iCode * ic, char *jval)
2944 /* if true label then we jump if condition
2948 jlbl = IC_TRUE (ic);
2949 if (!strcmp (jval, "a"))
2953 else if (!strcmp (jval, "c"))
2957 else if (!strcmp (jval, "nc"))
2963 /* The buffer contains the bit on A that we should test */
2969 /* false label is present */
2970 jlbl = IC_FALSE (ic);
2971 if (!strcmp (jval, "a"))
2975 else if (!strcmp (jval, "c"))
2979 else if (!strcmp (jval, "nc"))
2985 /* The buffer contains the bit on A that we should test */
2989 /* Z80 can do a conditional long jump */
2990 if (!strcmp (jval, "a"))
2994 else if (!strcmp (jval, "c"))
2997 else if (!strcmp (jval, "nc"))
3002 emit2 ("bit %s,a", jval);
3004 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3006 /* mark the icode as generated */
3011 _getPairIdName (PAIR_ID id)
3013 return _pairs[id].name;
3016 /** Generic compare for > or <
3019 genCmp (operand * left, operand * right,
3020 operand * result, iCode * ifx, int sign)
3022 int size, offset = 0;
3023 unsigned long lit = 0L;
3024 bool swap_sense = FALSE;
3026 /* if left & right are bit variables */
3027 if (AOP_TYPE (left) == AOP_CRY &&
3028 AOP_TYPE (right) == AOP_CRY)
3030 /* Cant happen on the Z80 */
3035 /* subtract right from left if at the
3036 end the carry flag is set then we know that
3037 left is greater than right */
3038 size = max (AOP_SIZE (left), AOP_SIZE (right));
3040 /* if unsigned char cmp with lit, just compare */
3042 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3044 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3047 emit2 ("xor a,!immedbyte", 0x80);
3048 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3051 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3057 If the left or the right is a lit:
3058 Load -lit into HL, add to right via, check sense.
3060 if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3062 PAIR_ID id = PAIR_DE;
3063 asmop *lit = AOP (right);
3064 asmop *op = AOP (left);
3067 if (AOP_TYPE (left) == AOP_LIT)
3075 emit2 ("ld e,%s", aopGet (op, 0, 0));
3076 emit2 ("ld a,%s", aopGet (op, 1, 0));
3077 emit2 ("xor a,!immedbyte", 0x80);
3082 id = getPairId (op);
3083 if (id == PAIR_INVALID)
3085 fetchPair (PAIR_DE, op);
3089 spillPair (PAIR_HL);
3090 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3091 emit2 ("add hl,%s", _getPairIdName (id));
3094 if (AOP_TYPE (right) == AOP_LIT)
3096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3097 /* optimize if(x < 0) or if(x >= 0) */
3102 /* No sign so it's always false */
3107 /* Just load in the top most bit */
3108 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3109 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3111 genIfxJump (ifx, "7");
3122 /* First setup h and l contaning the top most bytes XORed */
3123 bool fDidXor = FALSE;
3124 if (AOP_TYPE (left) == AOP_LIT)
3126 unsigned long lit = (unsigned long)
3127 floatFromVal (AOP (left)->aopu.aop_lit);
3128 emit2 ("ld %s,!immedbyte", _fTmp[0],
3129 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3133 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3134 emit2 ("xor a,!immedbyte", 0x80);
3135 emit2 ("ld %s,a", _fTmp[0]);
3138 if (AOP_TYPE (right) == AOP_LIT)
3140 unsigned long lit = (unsigned long)
3141 floatFromVal (AOP (right)->aopu.aop_lit);
3142 emit2 ("ld %s,!immedbyte", _fTmp[1],
3143 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3147 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3148 emit2 ("xor a,!immedbyte", 0x80);
3149 emit2 ("ld %s,a", _fTmp[1]);
3161 /* Do a long subtract */
3164 _moveA (aopGet (AOP (left), offset, FALSE));
3166 if (sign && size == 0)
3168 emit2 ("ld a,%s", _fTmp[0]);
3169 emit2 ("sbc a,%s", _fTmp[1]);
3173 /* Subtract through, propagating the carry */
3174 emit2 ("sbc a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3181 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3183 outBitCLong (result, swap_sense);
3187 /* if the result is used in the next
3188 ifx conditional branch then generate
3189 code a little differently */
3191 genIfxJump (ifx, swap_sense ? "nc" : "c");
3193 outBitCLong (result, swap_sense);
3194 /* leave the result in acc */
3198 /*-----------------------------------------------------------------*/
3199 /* genCmpGt :- greater than comparison */
3200 /*-----------------------------------------------------------------*/
3202 genCmpGt (iCode * ic, iCode * ifx)
3204 operand *left, *right, *result;
3205 sym_link *letype, *retype;
3208 left = IC_LEFT (ic);
3209 right = IC_RIGHT (ic);
3210 result = IC_RESULT (ic);
3212 letype = getSpec (operandType (left));
3213 retype = getSpec (operandType (right));
3214 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3215 /* assign the amsops */
3216 aopOp (left, ic, FALSE, FALSE);
3217 aopOp (right, ic, FALSE, FALSE);
3218 aopOp (result, ic, TRUE, FALSE);
3220 genCmp (right, left, result, ifx, sign);
3222 freeAsmop (left, NULL, ic);
3223 freeAsmop (right, NULL, ic);
3224 freeAsmop (result, NULL, ic);
3227 /*-----------------------------------------------------------------*/
3228 /* genCmpLt - less than comparisons */
3229 /*-----------------------------------------------------------------*/
3231 genCmpLt (iCode * ic, iCode * ifx)
3233 operand *left, *right, *result;
3234 sym_link *letype, *retype;
3237 left = IC_LEFT (ic);
3238 right = IC_RIGHT (ic);
3239 result = IC_RESULT (ic);
3241 letype = getSpec (operandType (left));
3242 retype = getSpec (operandType (right));
3243 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3245 /* assign the amsops */
3246 aopOp (left, ic, FALSE, FALSE);
3247 aopOp (right, ic, FALSE, FALSE);
3248 aopOp (result, ic, TRUE, FALSE);
3250 genCmp (left, right, result, ifx, sign);
3252 freeAsmop (left, NULL, ic);
3253 freeAsmop (right, NULL, ic);
3254 freeAsmop (result, NULL, ic);
3257 /*-----------------------------------------------------------------*/
3258 /* gencjneshort - compare and jump if not equal */
3259 /*-----------------------------------------------------------------*/
3261 gencjneshort (operand * left, operand * right, symbol * lbl)
3263 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3265 unsigned long lit = 0L;
3267 /* Swap the left and right if it makes the computation easier */
3268 if (AOP_TYPE (left) == AOP_LIT)
3275 if (AOP_TYPE (right) == AOP_LIT)
3276 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3278 /* if the right side is a literal then anything goes */
3279 if (AOP_TYPE (right) == AOP_LIT &&
3280 AOP_TYPE (left) != AOP_DIR)
3284 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3291 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
3298 emit2 ("jp nz,!tlabel", lbl->key + 100);
3304 emit2 ("ld a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3305 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3308 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3309 emit2 ("jp nz,!tlabel", lbl->key + 100);
3314 /* if the right side is in a register or in direct space or
3315 if the left is a pointer register & right is not */
3316 else if (AOP_TYPE (right) == AOP_REG ||
3317 AOP_TYPE (right) == AOP_DIR ||
3318 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3322 _moveA (aopGet (AOP (left), offset, FALSE));
3323 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3324 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3326 emit2 ("jp nz,!tlabel", lbl->key + 100);
3329 emit2 ("cp %s ; 4", aopGet (AOP (right), offset, FALSE));
3330 emit2 ("jp nz,!tlabel", lbl->key + 100);
3337 /* right is a pointer reg need both a & b */
3338 /* PENDING: is this required? */
3341 _moveA (aopGet (AOP (right), offset, FALSE));
3342 emit2 ("cp %s ; 5", aopGet (AOP (left), offset, FALSE));
3343 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3349 /*-----------------------------------------------------------------*/
3350 /* gencjne - compare and jump if not equal */
3351 /*-----------------------------------------------------------------*/
3353 gencjne (operand * left, operand * right, symbol * lbl)
3355 symbol *tlbl = newiTempLabel (NULL);
3357 gencjneshort (left, right, lbl);
3360 emit2 ("ld a,!one");
3361 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3362 emitLabel (lbl->key + 100);
3364 emitLabel (tlbl->key + 100);
3367 /*-----------------------------------------------------------------*/
3368 /* genCmpEq - generates code for equal to */
3369 /*-----------------------------------------------------------------*/
3371 genCmpEq (iCode * ic, iCode * ifx)
3373 operand *left, *right, *result;
3375 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3376 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3377 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3379 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3381 /* Swap operands if it makes the operation easier. ie if:
3382 1. Left is a literal.
3384 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3386 operand *t = IC_RIGHT (ic);
3387 IC_RIGHT (ic) = IC_LEFT (ic);
3391 if (ifx && !AOP_SIZE (result))
3394 /* if they are both bit variables */
3395 if (AOP_TYPE (left) == AOP_CRY &&
3396 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3402 tlbl = newiTempLabel (NULL);
3403 gencjneshort (left, right, tlbl);
3406 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3407 emitLabel (tlbl->key + 100);
3411 /* PENDING: do this better */
3412 symbol *lbl = newiTempLabel (NULL);
3413 emit2 ("!shortjp !tlabel", lbl->key + 100);
3414 emitLabel (tlbl->key + 100);
3415 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3416 emitLabel (lbl->key + 100);
3419 /* mark the icode as generated */
3424 /* if they are both bit variables */
3425 if (AOP_TYPE (left) == AOP_CRY &&
3426 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3432 gencjne (left, right, newiTempLabel (NULL));
3433 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3439 genIfxJump (ifx, "a");
3442 /* if the result is used in an arithmetic operation
3443 then put the result in place */
3444 if (AOP_TYPE (result) != AOP_CRY)
3448 /* leave the result in acc */
3452 freeAsmop (left, NULL, ic);
3453 freeAsmop (right, NULL, ic);
3454 freeAsmop (result, NULL, ic);
3457 /*-----------------------------------------------------------------*/
3458 /* ifxForOp - returns the icode containing the ifx for operand */
3459 /*-----------------------------------------------------------------*/
3461 ifxForOp (operand * op, iCode * ic)
3463 /* if true symbol then needs to be assigned */
3464 if (IS_TRUE_SYMOP (op))
3467 /* if this has register type condition and
3468 the next instruction is ifx with the same operand
3469 and live to of the operand is upto the ifx only then */
3471 ic->next->op == IFX &&
3472 IC_COND (ic->next)->key == op->key &&
3473 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3479 /*-----------------------------------------------------------------*/
3480 /* genAndOp - for && operation */
3481 /*-----------------------------------------------------------------*/
3483 genAndOp (iCode * ic)
3485 operand *left, *right, *result;
3488 /* note here that && operations that are in an if statement are
3489 taken away by backPatchLabels only those used in arthmetic
3490 operations remain */
3491 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3492 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3493 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3495 /* if both are bit variables */
3496 if (AOP_TYPE (left) == AOP_CRY &&
3497 AOP_TYPE (right) == AOP_CRY)
3503 tlbl = newiTempLabel (NULL);
3505 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3507 emitLabel (tlbl->key + 100);
3511 freeAsmop (left, NULL, ic);
3512 freeAsmop (right, NULL, ic);
3513 freeAsmop (result, NULL, ic);
3516 /*-----------------------------------------------------------------*/
3517 /* genOrOp - for || operation */
3518 /*-----------------------------------------------------------------*/
3520 genOrOp (iCode * ic)
3522 operand *left, *right, *result;
3525 /* note here that || operations that are in an
3526 if statement are taken away by backPatchLabels
3527 only those used in arthmetic operations remain */
3528 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3529 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3530 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3532 /* if both are bit variables */
3533 if (AOP_TYPE (left) == AOP_CRY &&
3534 AOP_TYPE (right) == AOP_CRY)
3540 tlbl = newiTempLabel (NULL);
3542 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3544 emitLabel (tlbl->key + 100);
3548 freeAsmop (left, NULL, ic);
3549 freeAsmop (right, NULL, ic);
3550 freeAsmop (result, NULL, ic);
3553 /*-----------------------------------------------------------------*/
3554 /* isLiteralBit - test if lit == 2^n */
3555 /*-----------------------------------------------------------------*/
3557 isLiteralBit (unsigned long lit)
3559 unsigned long pw[32] =
3560 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3561 0x100L, 0x200L, 0x400L, 0x800L,
3562 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3563 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3564 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3565 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3566 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3569 for (idx = 0; idx < 32; idx++)
3575 /*-----------------------------------------------------------------*/
3576 /* jmpTrueOrFalse - */
3577 /*-----------------------------------------------------------------*/
3579 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3581 // ugly but optimized by peephole
3584 symbol *nlbl = newiTempLabel (NULL);
3585 emit2 ("jp !tlabel", nlbl->key + 100);
3586 emitLabel (tlbl->key + 100);
3587 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3588 emitLabel (nlbl->key + 100);
3592 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3593 emitLabel (tlbl->key + 100);
3598 /*-----------------------------------------------------------------*/
3599 /* genAnd - code for and */
3600 /*-----------------------------------------------------------------*/
3602 genAnd (iCode * ic, iCode * ifx)
3604 operand *left, *right, *result;
3605 int size, offset = 0;
3606 unsigned long lit = 0L;
3609 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3610 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3611 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3614 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3616 AOP_TYPE (left), AOP_TYPE (right));
3617 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3619 AOP_SIZE (left), AOP_SIZE (right));
3622 /* if left is a literal & right is not then exchange them */
3623 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3624 AOP_NEEDSACC (left))
3626 operand *tmp = right;
3631 /* if result = right then exchange them */
3632 if (sameRegs (AOP (result), AOP (right)))
3634 operand *tmp = right;
3639 /* if right is bit then exchange them */
3640 if (AOP_TYPE (right) == AOP_CRY &&
3641 AOP_TYPE (left) != AOP_CRY)
3643 operand *tmp = right;
3647 if (AOP_TYPE (right) == AOP_LIT)
3648 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3650 size = AOP_SIZE (result);
3652 if (AOP_TYPE (left) == AOP_CRY)
3658 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3659 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3660 if ((AOP_TYPE (right) == AOP_LIT) &&
3661 (AOP_TYPE (result) == AOP_CRY) &&
3662 (AOP_TYPE (left) != AOP_CRY))
3664 int posbit = isLiteralBit (lit);
3669 _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
3674 emit2 ("mov c,acc.%d", posbit & 0x07);
3681 sprintf (buffer, "%d", posbit & 0x07);
3682 genIfxJump (ifx, buffer);
3693 symbol *tlbl = newiTempLabel (NULL);
3694 int sizel = AOP_SIZE (left);
3702 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3704 _moveA (aopGet (AOP (left), offset, FALSE));
3706 if ((posbit = isLiteralBit (bytelit)) != 0)
3709 emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3713 if (bytelit != 0x0FFL)
3715 aopGet (AOP (right), offset, FALSE));
3719 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3724 // bit = left & literal
3728 emit2 ("!tlabeldef", tlbl->key + 100);
3730 // if(left & literal)
3734 jmpTrueOrFalse (ifx, tlbl);
3742 /* if left is same as result */
3743 if (sameRegs (AOP (result), AOP (left)))
3745 for (; size--; offset++)
3747 if (AOP_TYPE (right) == AOP_LIT)
3749 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3754 aopPut (AOP (result), "!zero", offset);
3757 _moveA (aopGet (AOP (left), offset, FALSE));
3759 aopGet (AOP (right), offset, FALSE));
3760 aopPut (AOP (left), "a", offset);
3767 if (AOP_TYPE (left) == AOP_ACC)
3773 _moveA (aopGet (AOP (left), offset, FALSE));
3775 aopGet (AOP (right), offset, FALSE));
3776 aopPut (AOP (left), "a", offset);
3783 // left & result in different registers
3784 if (AOP_TYPE (result) == AOP_CRY)
3790 for (; (size--); offset++)
3793 // result = left & right
3794 if (AOP_TYPE (right) == AOP_LIT)
3796 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3798 aopPut (AOP (result),
3799 aopGet (AOP (left), offset, FALSE),
3803 else if (bytelit == 0)
3805 aopPut (AOP (result), "!zero", offset);
3809 // faster than result <- left, anl result,right
3810 // and better if result is SFR
3811 if (AOP_TYPE (left) == AOP_ACC)
3812 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
3815 _moveA (aopGet (AOP (left), offset, FALSE));
3817 aopGet (AOP (right), offset, FALSE));
3819 aopPut (AOP (result), "a", offset);
3826 freeAsmop (left, NULL, ic);
3827 freeAsmop (right, NULL, ic);
3828 freeAsmop (result, NULL, ic);
3831 /*-----------------------------------------------------------------*/
3832 /* genOr - code for or */
3833 /*-----------------------------------------------------------------*/
3835 genOr (iCode * ic, iCode * ifx)
3837 operand *left, *right, *result;
3838 int size, offset = 0;
3839 unsigned long lit = 0L;
3841 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3842 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3843 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3846 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3848 AOP_TYPE (left), AOP_TYPE (right));
3849 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3851 AOP_SIZE (left), AOP_SIZE (right));
3854 /* if left is a literal & right is not then exchange them */
3855 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3856 AOP_NEEDSACC (left))
3858 operand *tmp = right;
3863 /* if result = right then exchange them */
3864 if (sameRegs (AOP (result), AOP (right)))
3866 operand *tmp = right;
3871 /* if right is bit then exchange them */
3872 if (AOP_TYPE (right) == AOP_CRY &&
3873 AOP_TYPE (left) != AOP_CRY)
3875 operand *tmp = right;
3879 if (AOP_TYPE (right) == AOP_LIT)
3880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3882 size = AOP_SIZE (result);
3884 if (AOP_TYPE (left) == AOP_CRY)
3890 if ((AOP_TYPE (right) == AOP_LIT) &&
3891 (AOP_TYPE (result) == AOP_CRY) &&
3892 (AOP_TYPE (left) != AOP_CRY))
3898 /* if left is same as result */
3899 if (sameRegs (AOP (result), AOP (left)))
3901 for (; size--; offset++)
3903 if (AOP_TYPE (right) == AOP_LIT)
3905 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3909 _moveA (aopGet (AOP (left), offset, FALSE));
3911 aopGet (AOP (right), offset, FALSE));
3912 aopPut (AOP (result), "a", offset);
3917 if (AOP_TYPE (left) == AOP_ACC)
3918 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
3921 _moveA (aopGet (AOP (left), offset, FALSE));
3923 aopGet (AOP (right), offset, FALSE));
3924 aopPut (AOP (result), "a", offset);
3931 // left & result in different registers
3932 if (AOP_TYPE (result) == AOP_CRY)
3937 for (; (size--); offset++)
3940 // result = left & right
3941 if (AOP_TYPE (right) == AOP_LIT)
3943 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3945 aopPut (AOP (result),
3946 aopGet (AOP (left), offset, FALSE),
3951 // faster than result <- left, anl result,right
3952 // and better if result is SFR
3953 if (AOP_TYPE (left) == AOP_ACC)
3954 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
3957 _moveA (aopGet (AOP (left), offset, FALSE));
3959 aopGet (AOP (right), offset, FALSE));
3961 aopPut (AOP (result), "a", offset);
3962 /* PENDING: something weird is going on here. Add exception. */
3963 if (AOP_TYPE (result) == AOP_ACC)
3969 freeAsmop (left, NULL, ic);
3970 freeAsmop (right, NULL, ic);
3971 freeAsmop (result, NULL, ic);
3974 /*-----------------------------------------------------------------*/
3975 /* genXor - code for xclusive or */
3976 /*-----------------------------------------------------------------*/
3978 genXor (iCode * ic, iCode * ifx)
3980 operand *left, *right, *result;
3981 int size, offset = 0;
3982 unsigned long lit = 0L;
3984 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3985 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3986 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3988 /* if left is a literal & right is not then exchange them */
3989 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3990 AOP_NEEDSACC (left))
3992 operand *tmp = right;
3997 /* if result = right then exchange them */
3998 if (sameRegs (AOP (result), AOP (right)))
4000 operand *tmp = right;
4005 /* if right is bit then exchange them */
4006 if (AOP_TYPE (right) == AOP_CRY &&
4007 AOP_TYPE (left) != AOP_CRY)
4009 operand *tmp = right;
4013 if (AOP_TYPE (right) == AOP_LIT)
4014 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4016 size = AOP_SIZE (result);
4018 if (AOP_TYPE (left) == AOP_CRY)
4024 if ((AOP_TYPE (right) == AOP_LIT) &&
4025 (AOP_TYPE (result) == AOP_CRY) &&
4026 (AOP_TYPE (left) != AOP_CRY))
4032 /* if left is same as result */
4033 if (sameRegs (AOP (result), AOP (left)))
4035 for (; size--; offset++)
4037 if (AOP_TYPE (right) == AOP_LIT)
4039 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4043 _moveA (aopGet (AOP (right), offset, FALSE));
4045 aopGet (AOP (left), offset, FALSE));
4046 aopPut (AOP (result), "a", 0);
4051 if (AOP_TYPE (left) == AOP_ACC)
4052 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4055 _moveA (aopGet (AOP (right), offset, FALSE));
4057 aopGet (AOP (left), offset, FALSE));
4058 aopPut (AOP (result), "a", 0);
4065 // left & result in different registers
4066 if (AOP_TYPE (result) == AOP_CRY)
4071 for (; (size--); offset++)
4074 // result = left & right
4075 if (AOP_TYPE (right) == AOP_LIT)
4077 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4079 aopPut (AOP (result),
4080 aopGet (AOP (left), offset, FALSE),
4085 // faster than result <- left, anl result,right
4086 // and better if result is SFR
4087 if (AOP_TYPE (left) == AOP_ACC)
4088 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4091 _moveA (aopGet (AOP (right), offset, FALSE));
4093 aopGet (AOP (left), offset, FALSE));
4094 aopPut (AOP (result), "a", 0);
4096 aopPut (AOP (result), "a", offset);
4101 freeAsmop (left, NULL, ic);
4102 freeAsmop (right, NULL, ic);
4103 freeAsmop (result, NULL, ic);
4106 /*-----------------------------------------------------------------*/
4107 /* genInline - write the inline code out */
4108 /*-----------------------------------------------------------------*/
4110 genInline (iCode * ic)
4112 char *buffer, *bp, *bp1;
4114 _G.lines.isInline += (!options.asmpeep);
4116 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4117 strcpy (buffer, IC_INLINE (ic));
4119 /* emit each line as a code */
4144 _G.lines.isInline -= (!options.asmpeep);
4148 /*-----------------------------------------------------------------*/
4149 /* genRRC - rotate right with carry */
4150 /*-----------------------------------------------------------------*/
4157 /*-----------------------------------------------------------------*/
4158 /* genRLC - generate code for rotate left with carry */
4159 /*-----------------------------------------------------------------*/
4166 /*-----------------------------------------------------------------*/
4167 /* shiftR2Left2Result - shift right two bytes from left to result */
4168 /*-----------------------------------------------------------------*/
4170 shiftR2Left2Result (operand * left, int offl,
4171 operand * result, int offr,
4172 int shCount, int sign)
4174 movLeft2Result (left, offl, result, offr, 0);
4175 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4183 /* if (AOP(result)->type == AOP_REG) { */
4186 symbol *tlbl, *tlbl1;
4189 tlbl = newiTempLabel (NULL);
4190 tlbl1 = newiTempLabel (NULL);
4192 /* Left is already in result - so now do the shift */
4195 emit2 ("ld a,!immedbyte+1", shCount);
4196 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4197 emitLabel (tlbl->key + 100);
4204 l = aopGet (AOP (result), --offset, FALSE);
4209 emitLabel (tlbl1->key + 100);
4211 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4216 /*-----------------------------------------------------------------*/
4217 /* shiftL2Left2Result - shift left two bytes from left to result */
4218 /*-----------------------------------------------------------------*/
4220 shiftL2Left2Result (operand * left, int offl,
4221 operand * result, int offr, int shCount)
4223 if (sameRegs (AOP (result), AOP (left)) &&
4224 ((offl + MSB16) == offr))
4230 /* Copy left into result */
4231 movLeft2Result (left, offl, result, offr, 0);
4232 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4234 /* PENDING: for now just see if it'll work. */
4235 /*if (AOP(result)->type == AOP_REG) { */
4239 symbol *tlbl, *tlbl1;
4242 tlbl = newiTempLabel (NULL);
4243 tlbl1 = newiTempLabel (NULL);
4245 /* Left is already in result - so now do the shift */
4248 emit2 ("ld a,!immedbyte+1", shCount);
4249 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4250 emitLabel (tlbl->key + 100);
4256 l = aopGet (AOP (result), offset++, FALSE);
4261 emitLabel (tlbl1->key + 100);
4263 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4268 /*-----------------------------------------------------------------*/
4269 /* AccRol - rotate left accumulator by known count */
4270 /*-----------------------------------------------------------------*/
4272 AccRol (int shCount)
4274 shCount &= 0x0007; // shCount : 0..7
4313 /*-----------------------------------------------------------------*/
4314 /* AccLsh - left shift accumulator by known count */
4315 /*-----------------------------------------------------------------*/
4317 AccLsh (int shCount)
4319 static const unsigned char SLMask[] =
4321 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4330 else if (shCount == 2)
4337 /* rotate left accumulator */
4339 /* and kill the lower order bits */
4340 emit2 ("and a,!immedbyte", SLMask[shCount]);
4345 /*-----------------------------------------------------------------*/
4346 /* shiftL1Left2Result - shift left one byte from left to result */
4347 /*-----------------------------------------------------------------*/
4349 shiftL1Left2Result (operand * left, int offl,
4350 operand * result, int offr, int shCount)
4353 l = aopGet (AOP (left), offl, FALSE);
4355 /* shift left accumulator */
4357 aopPut (AOP (result), "a", offr);
4361 /*-----------------------------------------------------------------*/
4362 /* genlshTwo - left shift two bytes by known amount != 0 */
4363 /*-----------------------------------------------------------------*/
4365 genlshTwo (operand * result, operand * left, int shCount)
4367 int size = AOP_SIZE (result);
4369 wassert (size == 2);
4371 /* if shCount >= 8 */
4379 movLeft2Result (left, LSB, result, MSB16, 0);
4380 aopPut (AOP (result), "!zero", 0);
4381 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4385 movLeft2Result (left, LSB, result, MSB16, 0);
4386 aopPut (AOP (result), "!zero", 0);
4391 aopPut (AOP (result), "!zero", LSB);
4394 /* 1 <= shCount <= 7 */
4403 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4408 /*-----------------------------------------------------------------*/
4409 /* genlshOne - left shift a one byte quantity by known count */
4410 /*-----------------------------------------------------------------*/
4412 genlshOne (operand * result, operand * left, int shCount)
4414 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4417 /*-----------------------------------------------------------------*/
4418 /* genLeftShiftLiteral - left shifting by known count */
4419 /*-----------------------------------------------------------------*/
4421 genLeftShiftLiteral (operand * left,
4426 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4429 freeAsmop (right, NULL, ic);
4431 aopOp (left, ic, FALSE, FALSE);
4432 aopOp (result, ic, FALSE, FALSE);
4434 size = getSize (operandType (result));
4437 emit2 ("; shift left result %d, left %d", size,
4441 /* I suppose that the left size >= result size */
4447 else if (shCount >= (size * 8))
4449 aopPut (AOP (result), "!zero", size);
4455 genlshOne (result, left, shCount);
4458 genlshTwo (result, left, shCount);
4467 freeAsmop (left, NULL, ic);
4468 freeAsmop (result, NULL, ic);
4471 /*-----------------------------------------------------------------*/
4472 /* genLeftShift - generates code for left shifting */
4473 /*-----------------------------------------------------------------*/
4475 genLeftShift (iCode * ic)
4479 symbol *tlbl, *tlbl1;
4480 operand *left, *right, *result;
4482 right = IC_RIGHT (ic);
4483 left = IC_LEFT (ic);
4484 result = IC_RESULT (ic);
4486 aopOp (right, ic, FALSE, FALSE);
4488 /* if the shift count is known then do it
4489 as efficiently as possible */
4490 if (AOP_TYPE (right) == AOP_LIT)
4492 genLeftShiftLiteral (left, right, result, ic);
4496 /* shift count is unknown then we have to form a loop get the loop
4497 count in B : Note: we take only the lower order byte since
4498 shifting more that 32 bits make no sense anyway, ( the largest
4499 size of an object can be only 32 bits ) */
4500 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4502 freeAsmop (right, NULL, ic);
4503 aopOp (left, ic, FALSE, FALSE);
4504 aopOp (result, ic, FALSE, FALSE);
4506 /* now move the left to the result if they are not the
4509 if (!sameRegs (AOP (left), AOP (result)))
4512 size = AOP_SIZE (result);
4516 l = aopGet (AOP (left), offset, FALSE);
4517 aopPut (AOP (result), l, offset);
4522 size = AOP_SIZE (result);
4526 l = aopGet (AOP (left), offset, FALSE);
4527 aopPut (AOP (result), l, offset);
4533 tlbl = newiTempLabel (NULL);
4534 size = AOP_SIZE (result);
4536 tlbl1 = newiTempLabel (NULL);
4538 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4539 emitLabel (tlbl->key + 100);
4540 l = aopGet (AOP (result), offset, FALSE);
4544 l = aopGet (AOP (result), offset++, FALSE);
4547 emitLabel (tlbl1->key + 100);
4549 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4551 freeAsmop (left, NULL, ic);
4552 freeAsmop (result, NULL, ic);
4555 /*-----------------------------------------------------------------*/
4556 /* genrshOne - left shift two bytes by known amount != 0 */
4557 /*-----------------------------------------------------------------*/
4559 genrshOne (operand * result, operand * left, int shCount)
4562 int size = AOP_SIZE (result);
4565 wassert (size == 1);
4566 wassert (shCount < 8);
4568 l = aopGet (AOP (left), 0, FALSE);
4569 if (AOP (result)->type == AOP_REG)
4571 aopPut (AOP (result), l, 0);
4572 l = aopGet (AOP (result), 0, FALSE);
4574 emit2 ("srl %s", l);
4583 aopPut (AOP (result), "a", 0);
4587 /*-----------------------------------------------------------------*/
4588 /* AccRsh - right shift accumulator by known count */
4589 /*-----------------------------------------------------------------*/
4591 AccRsh (int shCount)
4593 static const unsigned char SRMask[] =
4595 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4600 /* rotate right accumulator */
4601 AccRol (8 - shCount);
4602 /* and kill the higher order bits */
4603 emit2 ("and a,!immedbyte", SRMask[shCount]);
4607 /*-----------------------------------------------------------------*/
4608 /* shiftR1Left2Result - shift right one byte from left to result */
4609 /*-----------------------------------------------------------------*/
4611 shiftR1Left2Result (operand * left, int offl,
4612 operand * result, int offr,
4613 int shCount, int sign)
4615 _moveA (aopGet (AOP (left), offl, FALSE));
4624 aopPut (AOP (result), "a", offr);
4627 /*-----------------------------------------------------------------*/
4628 /* genrshTwo - right shift two bytes by known amount != 0 */
4629 /*-----------------------------------------------------------------*/
4631 genrshTwo (operand * result, operand * left,
4632 int shCount, int sign)
4634 /* if shCount >= 8 */
4640 shiftR1Left2Result (left, MSB16, result, LSB,
4645 movLeft2Result (left, MSB16, result, LSB, sign);
4647 aopPut (AOP (result), "!zero", 1);
4649 /* 1 <= shCount <= 7 */
4652 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4656 /*-----------------------------------------------------------------*/
4657 /* genRightShiftLiteral - left shifting by known count */
4658 /*-----------------------------------------------------------------*/
4660 genRightShiftLiteral (operand * left,
4665 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4668 freeAsmop (right, NULL, ic);
4670 aopOp (left, ic, FALSE, FALSE);
4671 aopOp (result, ic, FALSE, FALSE);
4673 size = getSize (operandType (result));
4675 emit2 ("; shift right result %d, left %d", size,
4678 /* I suppose that the left size >= result size */
4684 else if (shCount >= (size * 8))
4686 aopPut (AOP (result), "!zero", size);
4692 genrshOne (result, left, shCount);
4695 /* PENDING: sign support */
4696 genrshTwo (result, left, shCount, FALSE);
4705 freeAsmop (left, NULL, ic);
4706 freeAsmop (result, NULL, ic);
4709 /*-----------------------------------------------------------------*/
4710 /* genRightShift - generate code for right shifting */
4711 /*-----------------------------------------------------------------*/
4713 genRightShift (iCode * ic)
4715 operand *right, *left, *result;
4717 int size, offset, first = 1;
4721 symbol *tlbl, *tlbl1;
4723 /* if signed then we do it the hard way preserve the
4724 sign bit moving it inwards */
4725 retype = getSpec (operandType (IC_RESULT (ic)));
4727 is_signed = !SPEC_USIGN (retype);
4729 /* signed & unsigned types are treated the same : i.e. the
4730 signed is NOT propagated inwards : quoting from the
4731 ANSI - standard : "for E1 >> E2, is equivalent to division
4732 by 2**E2 if unsigned or if it has a non-negative value,
4733 otherwise the result is implementation defined ", MY definition
4734 is that the sign does not get propagated */
4736 right = IC_RIGHT (ic);
4737 left = IC_LEFT (ic);
4738 result = IC_RESULT (ic);
4740 aopOp (right, ic, FALSE, FALSE);
4742 /* if the shift count is known then do it
4743 as efficiently as possible */
4744 if (AOP_TYPE (right) == AOP_LIT)
4746 genRightShiftLiteral (left, right, result, ic);
4750 aopOp (left, ic, FALSE, FALSE);
4751 aopOp (result, ic, FALSE, FALSE);
4753 /* now move the left to the result if they are not the
4755 if (!sameRegs (AOP (left), AOP (result)) &&
4756 AOP_SIZE (result) > 1)
4759 size = AOP_SIZE (result);
4763 l = aopGet (AOP (left), offset, FALSE);
4764 aopPut (AOP (result), l, offset);
4769 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4771 freeAsmop (right, NULL, ic);
4773 tlbl = newiTempLabel (NULL);
4774 tlbl1 = newiTempLabel (NULL);
4775 size = AOP_SIZE (result);
4778 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4779 emitLabel (tlbl->key + 100);
4782 l = aopGet (AOP (result), offset--, FALSE);
4786 emit2 ("sra %s", l);
4788 emit2 ("srl %s", l);
4794 emitLabel (tlbl1->key + 100);
4796 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4798 freeAsmop (left, NULL, ic);
4799 freeAsmop (result, NULL, ic);
4802 /*-----------------------------------------------------------------*/
4803 /* genGenPointerGet - get value from generic pointer space */
4804 /*-----------------------------------------------------------------*/
4806 genGenPointerGet (operand * left,
4807 operand * result, iCode * ic)
4810 sym_link *retype = getSpec (operandType (result));
4816 aopOp (left, ic, FALSE, FALSE);
4817 aopOp (result, ic, FALSE, FALSE);
4819 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4822 if (isPtrPair (AOP (left)))
4824 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4825 aopPut (AOP (result), buffer, 0);
4829 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4830 aopPut (AOP (result), "a", 0);
4832 freeAsmop (left, NULL, ic);
4836 /* For now we always load into IY */
4837 /* if this is remateriazable */
4838 fetchPair (pair, AOP (left));
4840 /* so iy now contains the address */
4841 freeAsmop (left, NULL, ic);
4843 /* if bit then unpack */
4844 if (IS_BITVAR (retype))
4850 size = AOP_SIZE (result);
4855 /* PENDING: make this better */
4856 if (!IS_GB && AOP (result)->type == AOP_REG)
4858 aopPut (AOP (result), "!*hl", offset++);
4862 emit2 ("ld a,!*pair", _pairs[pair].name);
4863 aopPut (AOP (result), "a", offset++);
4867 emit2 ("inc %s", _pairs[pair].name);
4868 _G.pairs[pair].offset++;
4874 freeAsmop (result, NULL, ic);
4877 /*-----------------------------------------------------------------*/
4878 /* genPointerGet - generate code for pointer get */
4879 /*-----------------------------------------------------------------*/
4881 genPointerGet (iCode * ic)
4883 operand *left, *result;
4884 sym_link *type, *etype;
4886 left = IC_LEFT (ic);
4887 result = IC_RESULT (ic);
4889 /* depending on the type of pointer we need to
4890 move it to the correct pointer register */
4891 type = operandType (left);
4892 etype = getSpec (type);
4894 genGenPointerGet (left, result, ic);
4898 isRegOrLit (asmop * aop)
4900 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4905 /*-----------------------------------------------------------------*/
4906 /* genGenPointerSet - stores the value into a pointer location */
4907 /*-----------------------------------------------------------------*/
4909 genGenPointerSet (operand * right,
4910 operand * result, iCode * ic)
4913 sym_link *retype = getSpec (operandType (right));
4914 PAIR_ID pairId = PAIR_HL;
4916 aopOp (result, ic, FALSE, FALSE);
4917 aopOp (right, ic, FALSE, FALSE);
4922 /* Handle the exceptions first */
4923 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
4926 const char *l = aopGet (AOP (right), 0, FALSE);
4927 const char *pair = getPairName (AOP (result));
4928 if (canAssignToPtr (l) && isPtr (pair))
4930 emit2 ("ld !*pair,%s", pair, l);
4935 emit2 ("ld !*pair,a", pair);
4940 /* if the operand is already in dptr
4941 then we do nothing else we move the value to dptr */
4942 if (AOP_TYPE (result) != AOP_STR)
4944 fetchPair (pairId, AOP (result));
4946 /* so hl know contains the address */
4947 freeAsmop (result, NULL, ic);
4949 /* if bit then unpack */
4950 if (IS_BITVAR (retype))
4956 size = AOP_SIZE (right);
4961 const char *l = aopGet (AOP (right), offset, FALSE);
4962 if (isRegOrLit (AOP (right)) && !IS_GB)
4964 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
4969 emit2 ("ld !*pair,a", _pairs[pairId].name);
4973 emit2 ("inc %s", _pairs[pairId].name);
4974 _G.pairs[pairId].offset++;
4980 freeAsmop (right, NULL, ic);
4983 /*-----------------------------------------------------------------*/
4984 /* genPointerSet - stores the value into a pointer location */
4985 /*-----------------------------------------------------------------*/
4987 genPointerSet (iCode * ic)
4989 operand *right, *result;
4990 sym_link *type, *etype;
4992 right = IC_RIGHT (ic);
4993 result = IC_RESULT (ic);
4995 /* depending on the type of pointer we need to
4996 move it to the correct pointer register */
4997 type = operandType (result);
4998 etype = getSpec (type);
5000 genGenPointerSet (right, result, ic);
5003 /*-----------------------------------------------------------------*/
5004 /* genIfx - generate code for Ifx statement */
5005 /*-----------------------------------------------------------------*/
5007 genIfx (iCode * ic, iCode * popIc)
5009 operand *cond = IC_COND (ic);
5012 aopOp (cond, ic, FALSE, TRUE);
5014 /* get the value into acc */
5015 if (AOP_TYPE (cond) != AOP_CRY)
5019 /* the result is now in the accumulator */
5020 freeAsmop (cond, NULL, ic);
5022 /* if there was something to be popped then do it */
5026 /* if the condition is a bit variable */
5027 if (isbit && IS_ITEMP (cond) &&
5029 genIfxJump (ic, SPIL_LOC (cond)->rname);
5030 else if (isbit && !IS_ITEMP (cond))
5031 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5033 genIfxJump (ic, "a");
5038 /*-----------------------------------------------------------------*/
5039 /* genAddrOf - generates code for address of */
5040 /*-----------------------------------------------------------------*/
5042 genAddrOf (iCode * ic)
5044 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5046 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5048 /* if the operand is on the stack then we
5049 need to get the stack offset of this
5056 if (sym->stack <= 0)
5058 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5062 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5069 emit2 ("ld de,!hashedstr", sym->rname);
5071 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5072 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5079 /* if it has an offset then we need to compute it */
5081 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5083 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5084 emit2 ("add hl,sp");
5088 emit2 ("ld hl,#%s", sym->rname);
5090 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5091 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5093 freeAsmop (IC_RESULT (ic), NULL, ic);
5096 /*-----------------------------------------------------------------*/
5097 /* genAssign - generate code for assignment */
5098 /*-----------------------------------------------------------------*/
5100 genAssign (iCode * ic)
5102 operand *result, *right;
5104 unsigned long lit = 0L;
5106 result = IC_RESULT (ic);
5107 right = IC_RIGHT (ic);
5110 /* Dont bother assigning if they are the same */
5111 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5113 emit2 ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5118 aopOp (right, ic, FALSE, FALSE);
5119 aopOp (result, ic, TRUE, FALSE);
5121 /* if they are the same registers */
5122 if (sameRegs (AOP (right), AOP (result)))
5124 emit2 ("; (registers are the same)");
5128 /* if the result is a bit */
5129 if (AOP_TYPE (result) == AOP_CRY)
5135 size = AOP_SIZE (result);
5138 if (AOP_TYPE (right) == AOP_LIT)
5139 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5140 if (isPair (AOP (result)))
5142 fetchPair (getPairId (AOP (result)), AOP (right));
5144 else if ((size > 1) &&
5145 (AOP_TYPE (result) != AOP_REG) &&
5146 (AOP_TYPE (right) == AOP_LIT) &&
5147 !IS_FLOAT (operandType (right)) &&
5150 bool fXored = FALSE;
5152 /* Work from the top down.
5153 Done this way so that we can use the cached copy of 0
5154 in A for a fast clear */
5157 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5159 if (!fXored && size > 1)
5166 aopPut (AOP (result), "a", offset);
5170 aopPut (AOP (result), "!zero", offset);
5174 aopPut (AOP (result),
5175 aopGet (AOP (right), offset, FALSE),
5180 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5182 /* Special case. Load into a and d, then load out. */
5183 _moveA (aopGet (AOP (right), 0, FALSE));
5184 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5185 aopPut (AOP (result), "a", 0);
5186 aopPut (AOP (result), "e", 1);
5192 /* PENDING: do this check better */
5193 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5195 _moveA (aopGet (AOP (right), offset, FALSE));
5196 aopPut (AOP (result), "a", offset);
5199 aopPut (AOP (result),
5200 aopGet (AOP (right), offset, FALSE),
5207 freeAsmop (right, NULL, ic);
5208 freeAsmop (result, NULL, ic);
5211 /*-----------------------------------------------------------------*/
5212 /* genJumpTab - genrates code for jump table */
5213 /*-----------------------------------------------------------------*/
5215 genJumpTab (iCode * ic)
5220 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5221 /* get the condition into accumulator */
5222 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5225 emit2 ("ld e,%s", l);
5226 emit2 ("ld d,!zero");
5227 jtab = newiTempLabel (NULL);
5229 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5230 emit2 ("add hl,de");
5231 emit2 ("add hl,de");
5232 emit2 ("add hl,de");
5233 freeAsmop (IC_JTCOND (ic), NULL, ic);
5237 emitLabel (jtab->key + 100);
5238 /* now generate the jump labels */
5239 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5240 jtab = setNextItem (IC_JTLABELS (ic)))
5241 emit2 ("jp !tlabel", jtab->key + 100);
5244 /*-----------------------------------------------------------------*/
5245 /* genCast - gen code for casting */
5246 /*-----------------------------------------------------------------*/
5248 genCast (iCode * ic)
5250 operand *result = IC_RESULT (ic);
5251 sym_link *ctype = operandType (IC_LEFT (ic));
5252 operand *right = IC_RIGHT (ic);
5255 /* if they are equivalent then do nothing */
5256 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5259 aopOp (right, ic, FALSE, FALSE);
5260 aopOp (result, ic, FALSE, FALSE);
5262 /* if the result is a bit */
5263 if (AOP_TYPE (result) == AOP_CRY)
5268 /* if they are the same size : or less */
5269 if (AOP_SIZE (result) <= AOP_SIZE (right))
5272 /* if they are in the same place */
5273 if (sameRegs (AOP (right), AOP (result)))
5276 /* if they in different places then copy */
5277 size = AOP_SIZE (result);
5281 aopPut (AOP (result),
5282 aopGet (AOP (right), offset, FALSE),
5289 /* PENDING: should be OK. */
5291 /* if the result is of type pointer */
5298 /* so we now know that the size of destination is greater
5299 than the size of the source */
5300 /* we move to result for the size of source */
5301 size = AOP_SIZE (right);
5305 aopPut (AOP (result),
5306 aopGet (AOP (right), offset, FALSE),
5311 /* now depending on the sign of the destination */
5312 size = AOP_SIZE (result) - AOP_SIZE (right);
5313 /* Unsigned or not an integral type - right fill with zeros */
5314 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5317 aopPut (AOP (result), "!zero", offset++);
5321 /* we need to extend the sign :{ */
5322 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5325 emit2 ("; genCast: sign extend untested.");
5329 aopPut (AOP (result), "a", offset++);
5333 freeAsmop (right, NULL, ic);
5334 freeAsmop (result, NULL, ic);
5337 /*-----------------------------------------------------------------*/
5338 /* genReceive - generate code for a receive iCode */
5339 /*-----------------------------------------------------------------*/
5341 genReceive (iCode * ic)
5343 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5344 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5345 IS_TRUE_SYMOP (IC_RESULT (ic))))
5355 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5356 size = AOP_SIZE(IC_RESULT(ic));
5358 for (i = 0; i < size; i++) {
5359 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5363 freeAsmop (IC_RESULT (ic), NULL, ic);
5366 /*-----------------------------------------------------------------*/
5367 /* genZ80Code - generate code for Z80 based controllers */
5368 /*-----------------------------------------------------------------*/
5370 genZ80Code (iCode * lic)
5378 _fReturn = _gbz80_return;
5379 _fTmp = _gbz80_return;
5383 _fReturn = _z80_return;
5384 _fTmp = _z80_return;
5387 _G.lines.head = _G.lines.current = NULL;
5389 for (ic = lic; ic; ic = ic->next)
5392 if (cln != ic->lineno)
5394 emit2 ("; %s %d", ic->filename, ic->lineno);
5397 /* if the result is marked as
5398 spilt and rematerializable or code for
5399 this has already been generated then
5401 if (resultRemat (ic) || ic->generated)
5404 /* depending on the operation */
5418 emit2 ("; genUminus");
5423 emit2 ("; genIpush");
5428 /* IPOP happens only when trying to restore a
5429 spilt live range, if there is an ifx statement
5430 following this pop then the if statement might
5431 be using some of the registers being popped which
5432 would destory the contents of the register so
5433 we need to check for this condition and handle it */
5435 ic->next->op == IFX &&
5436 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5439 genIfx (ic->next, ic);
5443 emit2 ("; genIpop");
5449 emit2 ("; genCall");
5454 emit2 ("; genPcall");
5459 emit2 ("; genFunction");
5464 emit2 ("; genEndFunction");
5465 genEndFunction (ic);
5474 emit2 ("; genLabel");
5479 emit2 ("; genGoto");
5484 emit2 ("; genPlus");
5489 emit2 ("; genMinus");
5494 emit2 ("; genMult");
5509 emit2 ("; genCmpGt");
5510 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5514 emit2 ("; genCmpLt");
5515 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5522 /* note these two are xlated by algebraic equivalence
5523 during parsing SDCC.y */
5524 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5525 "got '>=' or '<=' shouldn't have come here");
5529 emit2 ("; genCmpEq");
5530 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5534 emit2 ("; genAndOp");
5539 emit2 ("; genOrOp");
5545 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5550 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5555 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5559 emit2 ("; genInline");
5574 emit2 ("; genHBIT");
5578 emit2 ("; genLeftShift");
5583 emit2 ("; genRightShift");
5587 case GET_VALUE_AT_ADDRESS:
5588 emit2 ("; genPointerGet");
5594 if (POINTER_SET (ic))
5596 emit2 ("; genAssign (pointer)");
5601 emit2 ("; genAssign");
5612 emit2 ("; genAddrOf");
5617 emit2 ("; genJumpTab");
5622 emit2 ("; genCast");
5627 emit2 ("; genReceive");
5633 addSet (&_G.sendSet, ic);
5638 /* piCode(ic,stdout); */
5644 /* now we are ready to call the
5645 peep hole optimizer */
5646 if (!options.nopeep)
5647 peepHole (&_G.lines.head);
5649 /* This is unfortunate */
5650 /* now do the actual printing */
5652 FILE *fp = codeOutFile;
5653 if (isInHome () && codeOutFile == code->oFile)
5654 codeOutFile = home->oFile;
5655 printLine (_G.lines.head, codeOutFile);
5656 if (_G.flushStatics)
5659 _G.flushStatics = 0;
5668 _isPairUsed (iCode * ic, PAIR_ID pairId)
5674 if (bitVectBitValue (ic->rMask, D_IDX))
5676 if (bitVectBitValue (ic->rMask, E_IDX))
5686 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
5690 symbol *sym = OP_SYMBOL (op);
5692 if (sym->isspilt || sym->nRegs == 0)
5695 aopOp (op, ic, FALSE, FALSE);
5698 if (aop->type == AOP_REG)
5701 for (i = 0; i < aop->size; i++)
5703 if (pairId == PAIR_DE)
5705 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
5706 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
5708 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
5718 freeAsmop (IC_LEFT (ic), NULL, ic);