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))
4590 aopPut (AOP (result), "!zero", size);
4598 genlshOne (result, left, shCount);
4601 genlshTwo (result, left, shCount);
4604 wassertl (0, "Shifting of longs is currently unsupported");
4610 freeAsmop (left, NULL, ic);
4611 freeAsmop (result, NULL, ic);
4614 /*-----------------------------------------------------------------*/
4615 /* genLeftShift - generates code for left shifting */
4616 /*-----------------------------------------------------------------*/
4618 genLeftShift (iCode * ic)
4622 symbol *tlbl, *tlbl1;
4623 operand *left, *right, *result;
4625 right = IC_RIGHT (ic);
4626 left = IC_LEFT (ic);
4627 result = IC_RESULT (ic);
4629 aopOp (right, ic, FALSE, FALSE);
4631 /* if the shift count is known then do it
4632 as efficiently as possible */
4633 if (AOP_TYPE (right) == AOP_LIT)
4635 genLeftShiftLiteral (left, right, result, ic);
4639 /* shift count is unknown then we have to form a loop get the loop
4640 count in B : Note: we take only the lower order byte since
4641 shifting more that 32 bits make no sense anyway, ( the largest
4642 size of an object can be only 32 bits ) */
4643 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4645 freeAsmop (right, NULL, ic);
4646 aopOp (left, ic, FALSE, FALSE);
4647 aopOp (result, ic, FALSE, FALSE);
4649 /* now move the left to the result if they are not the
4652 if (!sameRegs (AOP (left), AOP (result)))
4655 size = AOP_SIZE (result);
4659 l = aopGet (AOP (left), offset, FALSE);
4660 aopPut (AOP (result), l, offset);
4665 size = AOP_SIZE (result);
4669 l = aopGet (AOP (left), offset, FALSE);
4670 aopPut (AOP (result), l, offset);
4676 tlbl = newiTempLabel (NULL);
4677 size = AOP_SIZE (result);
4679 tlbl1 = newiTempLabel (NULL);
4681 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4682 emitLabel (tlbl->key + 100);
4683 l = aopGet (AOP (result), offset, FALSE);
4687 l = aopGet (AOP (result), offset++, FALSE);
4690 emitLabel (tlbl1->key + 100);
4692 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4694 freeAsmop (left, NULL, ic);
4695 freeAsmop (result, NULL, ic);
4698 /*-----------------------------------------------------------------*/
4699 /* genrshOne - left shift two bytes by known amount != 0 */
4700 /*-----------------------------------------------------------------*/
4702 genrshOne (operand * result, operand * left, int shCount)
4705 int size = AOP_SIZE (result);
4708 wassert (size == 1);
4709 wassert (shCount < 8);
4711 l = aopGet (AOP (left), 0, FALSE);
4712 if (AOP (result)->type == AOP_REG)
4714 aopPut (AOP (result), l, 0);
4715 l = aopGet (AOP (result), 0, FALSE);
4717 emit2 ("srl %s", l);
4726 aopPut (AOP (result), "a", 0);
4730 /*-----------------------------------------------------------------*/
4731 /* AccRsh - right shift accumulator by known count */
4732 /*-----------------------------------------------------------------*/
4734 AccRsh (int shCount)
4736 static const unsigned char SRMask[] =
4738 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4743 /* rotate right accumulator */
4744 AccRol (8 - shCount);
4745 /* and kill the higher order bits */
4746 emit2 ("and a,!immedbyte", SRMask[shCount]);
4750 /*-----------------------------------------------------------------*/
4751 /* shiftR1Left2Result - shift right one byte from left to result */
4752 /*-----------------------------------------------------------------*/
4754 shiftR1Left2Result (operand * left, int offl,
4755 operand * result, int offr,
4756 int shCount, int sign)
4758 _moveA (aopGet (AOP (left), offl, FALSE));
4767 aopPut (AOP (result), "a", offr);
4770 /*-----------------------------------------------------------------*/
4771 /* genrshTwo - right shift two bytes by known amount != 0 */
4772 /*-----------------------------------------------------------------*/
4774 genrshTwo (operand * result, operand * left,
4775 int shCount, int sign)
4777 /* if shCount >= 8 */
4783 shiftR1Left2Result (left, MSB16, result, LSB,
4788 movLeft2Result (left, MSB16, result, LSB, sign);
4790 aopPut (AOP (result), "!zero", 1);
4792 /* 1 <= shCount <= 7 */
4795 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4799 /*-----------------------------------------------------------------*/
4800 /* genRightShiftLiteral - left shifting by known count */
4801 /*-----------------------------------------------------------------*/
4803 genRightShiftLiteral (operand * left,
4808 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4811 freeAsmop (right, NULL, ic);
4813 aopOp (left, ic, FALSE, FALSE);
4814 aopOp (result, ic, FALSE, FALSE);
4816 size = getSize (operandType (result));
4818 emit2 ("; shift right result %d, left %d", size,
4821 /* I suppose that the left size >= result size */
4827 else if (shCount >= (size * 8))
4829 aopPut (AOP (result), "!zero", size);
4835 genrshOne (result, left, shCount);
4838 /* PENDING: sign support */
4839 genrshTwo (result, left, shCount, FALSE);
4848 freeAsmop (left, NULL, ic);
4849 freeAsmop (result, NULL, ic);
4852 /*-----------------------------------------------------------------*/
4853 /* genRightShift - generate code for right shifting */
4854 /*-----------------------------------------------------------------*/
4856 genRightShift (iCode * ic)
4858 operand *right, *left, *result;
4860 int size, offset, first = 1;
4864 symbol *tlbl, *tlbl1;
4866 /* if signed then we do it the hard way preserve the
4867 sign bit moving it inwards */
4868 retype = getSpec (operandType (IC_RESULT (ic)));
4870 is_signed = !SPEC_USIGN (retype);
4872 /* signed & unsigned types are treated the same : i.e. the
4873 signed is NOT propagated inwards : quoting from the
4874 ANSI - standard : "for E1 >> E2, is equivalent to division
4875 by 2**E2 if unsigned or if it has a non-negative value,
4876 otherwise the result is implementation defined ", MY definition
4877 is that the sign does not get propagated */
4879 right = IC_RIGHT (ic);
4880 left = IC_LEFT (ic);
4881 result = IC_RESULT (ic);
4883 aopOp (right, ic, FALSE, FALSE);
4885 /* if the shift count is known then do it
4886 as efficiently as possible */
4887 if (AOP_TYPE (right) == AOP_LIT)
4889 genRightShiftLiteral (left, right, result, ic);
4893 aopOp (left, ic, FALSE, FALSE);
4894 aopOp (result, ic, FALSE, FALSE);
4896 /* now move the left to the result if they are not the
4898 if (!sameRegs (AOP (left), AOP (result)) &&
4899 AOP_SIZE (result) > 1)
4902 size = AOP_SIZE (result);
4906 l = aopGet (AOP (left), offset, FALSE);
4907 aopPut (AOP (result), l, offset);
4912 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4914 freeAsmop (right, NULL, ic);
4916 tlbl = newiTempLabel (NULL);
4917 tlbl1 = newiTempLabel (NULL);
4918 size = AOP_SIZE (result);
4921 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4922 emitLabel (tlbl->key + 100);
4925 l = aopGet (AOP (result), offset--, FALSE);
4929 emit2 ("sra %s", l);
4931 emit2 ("srl %s", l);
4937 emitLabel (tlbl1->key + 100);
4939 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4941 freeAsmop (left, NULL, ic);
4942 freeAsmop (result, NULL, ic);
4945 /*-----------------------------------------------------------------*/
4946 /* genGenPointerGet - get value from generic pointer space */
4947 /*-----------------------------------------------------------------*/
4949 genGenPointerGet (operand * left,
4950 operand * result, iCode * ic)
4953 sym_link *retype = getSpec (operandType (result));
4959 aopOp (left, ic, FALSE, FALSE);
4960 aopOp (result, ic, FALSE, FALSE);
4962 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4965 if (isPtrPair (AOP (left)))
4967 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4968 aopPut (AOP (result), buffer, 0);
4972 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4973 aopPut (AOP (result), "a", 0);
4975 freeAsmop (left, NULL, ic);
4979 /* For now we always load into IY */
4980 /* if this is remateriazable */
4981 fetchPair (pair, AOP (left));
4983 /* so iy now contains the address */
4984 freeAsmop (left, NULL, ic);
4986 /* if bit then unpack */
4987 if (IS_BITVAR (retype))
4993 size = AOP_SIZE (result);
4998 /* PENDING: make this better */
4999 if (!IS_GB && AOP (result)->type == AOP_REG)
5001 aopPut (AOP (result), "!*hl", offset++);
5005 emit2 ("ld a,!*pair", _pairs[pair].name);
5006 aopPut (AOP (result), "a", offset++);
5010 emit2 ("inc %s", _pairs[pair].name);
5011 _G.pairs[pair].offset++;
5017 freeAsmop (result, NULL, ic);
5020 /*-----------------------------------------------------------------*/
5021 /* genPointerGet - generate code for pointer get */
5022 /*-----------------------------------------------------------------*/
5024 genPointerGet (iCode * ic)
5026 operand *left, *result;
5027 sym_link *type, *etype;
5029 left = IC_LEFT (ic);
5030 result = IC_RESULT (ic);
5032 /* depending on the type of pointer we need to
5033 move it to the correct pointer register */
5034 type = operandType (left);
5035 etype = getSpec (type);
5037 genGenPointerGet (left, result, ic);
5041 isRegOrLit (asmop * aop)
5043 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
5048 /*-----------------------------------------------------------------*/
5049 /* genGenPointerSet - stores the value into a pointer location */
5050 /*-----------------------------------------------------------------*/
5052 genGenPointerSet (operand * right,
5053 operand * result, iCode * ic)
5056 sym_link *retype = getSpec (operandType (right));
5057 PAIR_ID pairId = PAIR_HL;
5059 aopOp (result, ic, FALSE, FALSE);
5060 aopOp (right, ic, FALSE, FALSE);
5065 /* Handle the exceptions first */
5066 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5069 const char *l = aopGet (AOP (right), 0, FALSE);
5070 const char *pair = getPairName (AOP (result));
5071 if (canAssignToPtr (l) && isPtr (pair))
5073 emit2 ("ld !*pair,%s", pair, l);
5078 emit2 ("ld !*pair,a", pair);
5083 /* if the operand is already in dptr
5084 then we do nothing else we move the value to dptr */
5085 if (AOP_TYPE (result) != AOP_STR)
5087 fetchPair (pairId, AOP (result));
5089 /* so hl know contains the address */
5090 freeAsmop (result, NULL, ic);
5092 /* if bit then unpack */
5093 if (IS_BITVAR (retype))
5099 size = AOP_SIZE (right);
5104 const char *l = aopGet (AOP (right), offset, FALSE);
5105 if (isRegOrLit (AOP (right)) && !IS_GB)
5107 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5112 emit2 ("ld !*pair,a", _pairs[pairId].name);
5116 emit2 ("inc %s", _pairs[pairId].name);
5117 _G.pairs[pairId].offset++;
5123 freeAsmop (right, NULL, ic);
5126 /*-----------------------------------------------------------------*/
5127 /* genPointerSet - stores the value into a pointer location */
5128 /*-----------------------------------------------------------------*/
5130 genPointerSet (iCode * ic)
5132 operand *right, *result;
5133 sym_link *type, *etype;
5135 right = IC_RIGHT (ic);
5136 result = IC_RESULT (ic);
5138 /* depending on the type of pointer we need to
5139 move it to the correct pointer register */
5140 type = operandType (result);
5141 etype = getSpec (type);
5143 genGenPointerSet (right, result, ic);
5146 /*-----------------------------------------------------------------*/
5147 /* genIfx - generate code for Ifx statement */
5148 /*-----------------------------------------------------------------*/
5150 genIfx (iCode * ic, iCode * popIc)
5152 operand *cond = IC_COND (ic);
5155 aopOp (cond, ic, FALSE, TRUE);
5157 /* get the value into acc */
5158 if (AOP_TYPE (cond) != AOP_CRY)
5162 /* the result is now in the accumulator */
5163 freeAsmop (cond, NULL, ic);
5165 /* if there was something to be popped then do it */
5169 /* if the condition is a bit variable */
5170 if (isbit && IS_ITEMP (cond) &&
5172 genIfxJump (ic, SPIL_LOC (cond)->rname);
5173 else if (isbit && !IS_ITEMP (cond))
5174 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5176 genIfxJump (ic, "a");
5181 /*-----------------------------------------------------------------*/
5182 /* genAddrOf - generates code for address of */
5183 /*-----------------------------------------------------------------*/
5185 genAddrOf (iCode * ic)
5187 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5189 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5191 /* if the operand is on the stack then we
5192 need to get the stack offset of this
5199 if (sym->stack <= 0)
5201 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5205 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5212 emit2 ("ld de,!hashedstr", sym->rname);
5214 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5215 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5222 /* if it has an offset then we need to compute it */
5224 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5226 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5227 emit2 ("add hl,sp");
5231 emit2 ("ld hl,#%s", sym->rname);
5233 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5234 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5236 freeAsmop (IC_RESULT (ic), NULL, ic);
5239 /*-----------------------------------------------------------------*/
5240 /* genAssign - generate code for assignment */
5241 /*-----------------------------------------------------------------*/
5243 genAssign (iCode * ic)
5245 operand *result, *right;
5247 unsigned long lit = 0L;
5249 result = IC_RESULT (ic);
5250 right = IC_RIGHT (ic);
5253 /* Dont bother assigning if they are the same */
5254 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5256 emit2 ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5261 aopOp (right, ic, FALSE, FALSE);
5262 aopOp (result, ic, TRUE, FALSE);
5264 /* if they are the same registers */
5265 if (sameRegs (AOP (right), AOP (result)))
5267 emit2 ("; (registers are the same)");
5271 /* if the result is a bit */
5272 if (AOP_TYPE (result) == AOP_CRY)
5278 size = AOP_SIZE (result);
5281 if (AOP_TYPE (right) == AOP_LIT)
5282 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5283 if (isPair (AOP (result)))
5285 fetchPair (getPairId (AOP (result)), AOP (right));
5287 else if ((size > 1) &&
5288 (AOP_TYPE (result) != AOP_REG) &&
5289 (AOP_TYPE (right) == AOP_LIT) &&
5290 !IS_FLOAT (operandType (right)) &&
5293 bool fXored = FALSE;
5295 /* Work from the top down.
5296 Done this way so that we can use the cached copy of 0
5297 in A for a fast clear */
5300 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5302 if (!fXored && size > 1)
5309 aopPut (AOP (result), "a", offset);
5313 aopPut (AOP (result), "!zero", offset);
5317 aopPut (AOP (result),
5318 aopGet (AOP (right), offset, FALSE),
5323 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5325 /* Special case. Load into a and d, then load out. */
5326 _moveA (aopGet (AOP (right), 0, FALSE));
5327 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5328 aopPut (AOP (result), "a", 0);
5329 aopPut (AOP (result), "e", 1);
5335 /* PENDING: do this check better */
5336 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5338 _moveA (aopGet (AOP (right), offset, FALSE));
5339 aopPut (AOP (result), "a", offset);
5342 aopPut (AOP (result),
5343 aopGet (AOP (right), offset, FALSE),
5350 freeAsmop (right, NULL, ic);
5351 freeAsmop (result, NULL, ic);
5354 /*-----------------------------------------------------------------*/
5355 /* genJumpTab - genrates code for jump table */
5356 /*-----------------------------------------------------------------*/
5358 genJumpTab (iCode * ic)
5363 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5364 /* get the condition into accumulator */
5365 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5368 emit2 ("ld e,%s", l);
5369 emit2 ("ld d,!zero");
5370 jtab = newiTempLabel (NULL);
5372 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5373 emit2 ("add hl,de");
5374 emit2 ("add hl,de");
5375 emit2 ("add hl,de");
5376 freeAsmop (IC_JTCOND (ic), NULL, ic);
5380 emitLabel (jtab->key + 100);
5381 /* now generate the jump labels */
5382 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5383 jtab = setNextItem (IC_JTLABELS (ic)))
5384 emit2 ("jp !tlabel", jtab->key + 100);
5387 /*-----------------------------------------------------------------*/
5388 /* genCast - gen code for casting */
5389 /*-----------------------------------------------------------------*/
5391 genCast (iCode * ic)
5393 operand *result = IC_RESULT (ic);
5394 sym_link *ctype = operandType (IC_LEFT (ic));
5395 operand *right = IC_RIGHT (ic);
5398 /* if they are equivalent then do nothing */
5399 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5402 aopOp (right, ic, FALSE, FALSE);
5403 aopOp (result, ic, FALSE, FALSE);
5405 /* if the result is a bit */
5406 if (AOP_TYPE (result) == AOP_CRY)
5411 /* if they are the same size : or less */
5412 if (AOP_SIZE (result) <= AOP_SIZE (right))
5415 /* if they are in the same place */
5416 if (sameRegs (AOP (right), AOP (result)))
5419 /* if they in different places then copy */
5420 size = AOP_SIZE (result);
5424 aopPut (AOP (result),
5425 aopGet (AOP (right), offset, FALSE),
5432 /* PENDING: should be OK. */
5434 /* if the result is of type pointer */
5441 /* so we now know that the size of destination is greater
5442 than the size of the source */
5443 /* we move to result for the size of source */
5444 size = AOP_SIZE (right);
5448 aopPut (AOP (result),
5449 aopGet (AOP (right), offset, FALSE),
5454 /* now depending on the sign of the destination */
5455 size = AOP_SIZE (result) - AOP_SIZE (right);
5456 /* Unsigned or not an integral type - right fill with zeros */
5457 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5460 aopPut (AOP (result), "!zero", offset++);
5464 /* we need to extend the sign :{ */
5465 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5468 emit2 ("; genCast: sign extend untested.");
5472 aopPut (AOP (result), "a", offset++);
5476 freeAsmop (right, NULL, ic);
5477 freeAsmop (result, NULL, ic);
5480 /*-----------------------------------------------------------------*/
5481 /* genReceive - generate code for a receive iCode */
5482 /*-----------------------------------------------------------------*/
5484 genReceive (iCode * ic)
5486 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5487 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5488 IS_TRUE_SYMOP (IC_RESULT (ic))))
5498 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5499 size = AOP_SIZE(IC_RESULT(ic));
5501 for (i = 0; i < size; i++) {
5502 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5506 freeAsmop (IC_RESULT (ic), NULL, ic);
5509 /*-----------------------------------------------------------------*/
5510 /* genZ80Code - generate code for Z80 based controllers */
5511 /*-----------------------------------------------------------------*/
5513 genZ80Code (iCode * lic)
5521 _fReturn = _gbz80_return;
5522 _fTmp = _gbz80_return;
5526 _fReturn = _z80_return;
5527 _fTmp = _z80_return;
5530 _G.lines.head = _G.lines.current = NULL;
5532 for (ic = lic; ic; ic = ic->next)
5535 if (cln != ic->lineno)
5537 emit2 ("; %s %d", ic->filename, ic->lineno);
5540 /* if the result is marked as
5541 spilt and rematerializable or code for
5542 this has already been generated then
5544 if (resultRemat (ic) || ic->generated)
5547 /* depending on the operation */
5561 emit2 ("; genUminus");
5566 emit2 ("; genIpush");
5571 /* IPOP happens only when trying to restore a
5572 spilt live range, if there is an ifx statement
5573 following this pop then the if statement might
5574 be using some of the registers being popped which
5575 would destory the contents of the register so
5576 we need to check for this condition and handle it */
5578 ic->next->op == IFX &&
5579 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5582 genIfx (ic->next, ic);
5586 emit2 ("; genIpop");
5592 emit2 ("; genCall");
5597 emit2 ("; genPcall");
5602 emit2 ("; genFunction");
5607 emit2 ("; genEndFunction");
5608 genEndFunction (ic);
5617 emit2 ("; genLabel");
5622 emit2 ("; genGoto");
5627 emit2 ("; genPlus");
5632 emit2 ("; genMinus");
5637 emit2 ("; genMult");
5652 emit2 ("; genCmpGt");
5653 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5657 emit2 ("; genCmpLt");
5658 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5665 /* note these two are xlated by algebraic equivalence
5666 during parsing SDCC.y */
5667 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5668 "got '>=' or '<=' shouldn't have come here");
5672 emit2 ("; genCmpEq");
5673 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5677 emit2 ("; genAndOp");
5682 emit2 ("; genOrOp");
5688 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5693 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5698 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5702 emit2 ("; genInline");
5717 emit2 ("; genHBIT");
5721 emit2 ("; genLeftShift");
5726 emit2 ("; genRightShift");
5730 case GET_VALUE_AT_ADDRESS:
5731 emit2 ("; genPointerGet");
5737 if (POINTER_SET (ic))
5739 emit2 ("; genAssign (pointer)");
5744 emit2 ("; genAssign");
5755 emit2 ("; genAddrOf");
5760 emit2 ("; genJumpTab");
5765 emit2 ("; genCast");
5770 emit2 ("; genReceive");
5776 addSet (&_G.sendSet, ic);
5781 /* piCode(ic,stdout); */
5787 /* now we are ready to call the
5788 peep hole optimizer */
5789 if (!options.nopeep)
5790 peepHole (&_G.lines.head);
5792 /* This is unfortunate */
5793 /* now do the actual printing */
5795 FILE *fp = codeOutFile;
5796 if (isInHome () && codeOutFile == code->oFile)
5797 codeOutFile = home->oFile;
5798 printLine (_G.lines.head, codeOutFile);
5799 if (_G.flushStatics)
5802 _G.flushStatics = 0;
5811 _isPairUsed (iCode * ic, PAIR_ID pairId)
5817 if (bitVectBitValue (ic->rMask, D_IDX))
5819 if (bitVectBitValue (ic->rMask, E_IDX))