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