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)
797 /* depending on type */
803 /* PENDING: for re-target */
805 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
807 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
813 value *val = aop->aopu.aop_lit;
814 /* if it is a float then it gets tricky */
815 /* otherwise it is fairly simple */
816 if (!IS_FLOAT (val->type))
818 unsigned long v = (unsigned long) floatFromVal (val);
824 else if (offset == 0)
830 wassertl(0, "Encountered an invalid offset while fetching a literal");
834 tsprintf (buffer, "!immedword", v);
836 tsprintf (buffer, "!constword", v);
838 return gc_strdup(buffer);
844 convertFloat (&f, floatFromVal (val));
846 tsprintf (buffer, "!immedword", f.w[offset / 2]);
848 tsprintf (buffer, "!constword", f.w[offset / 2]);
849 rs = Safe_calloc (1, strlen (buffer) + 1);
850 return strcpy (rs, buffer);
859 aopGetWord (asmop * aop, int offset)
861 return aopGetLitWordLong (aop, offset, TRUE);
865 isPtr (const char *s)
867 if (!strcmp (s, "hl"))
869 if (!strcmp (s, "ix"))
871 if (!strcmp (s, "iy"))
877 adjustPair (const char *pair, int *pold, int new)
883 emit2 ("inc %s", pair);
888 emit2 ("dec %s", pair);
894 spillPair (PAIR_ID pairId)
896 _G.pairs[pairId].last_type = AOP_INVALID;
897 _G.pairs[pairId].lit = NULL;
908 requiresHL (asmop * aop)
922 fetchLitSpecial (asmop * aop, bool negate, bool xor)
925 value *val = aop->aopu.aop_lit;
927 wassert (aop->type == AOP_LIT);
928 wassert (!IS_FLOAT (val->type));
930 v = (unsigned long) floatFromVal (val);
938 tsprintf (buffer, "!immedword", v);
939 return gc_strdup (buffer);
943 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
946 const char *pair = _pairs[pairId].name;
947 l = aopGetLitWordLong (left, offset, FALSE);
952 if (pairId == PAIR_HL || pairId == PAIR_IY)
954 if (_G.pairs[pairId].last_type == left->type)
956 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
958 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
960 adjustPair (pair, &_G.pairs[pairId].offset, offset);
963 if (pairId == PAIR_IY && abs (offset) < 127)
970 _G.pairs[pairId].last_type = left->type;
971 _G.pairs[pairId].lit = gc_strdup (l);
972 _G.pairs[pairId].offset = offset;
974 if (IS_GB && pairId == PAIR_DE && 0)
976 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
978 if (abs (_G.pairs[pairId].offset - offset) < 3)
980 adjustPair (pair, &_G.pairs[pairId].offset, offset);
984 _G.pairs[pairId].last_type = left->type;
985 _G.pairs[pairId].lit = gc_strdup (l);
986 _G.pairs[pairId].offset = offset;
988 /* Both a lit on the right and a true symbol on the left */
989 emit2 ("ld %s,!hashedstr", pair, l);
993 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
995 /* if this is remateriazable */
996 if (isLitWord (aop)) {
997 fetchLitPair (pairId, aop, offset);
1000 /* we need to get it byte by byte */
1001 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1002 aopGet (aop, offset, FALSE);
1003 switch (aop->size) {
1005 emit2 ("ld l,!*hl");
1006 emit2 ("ld h,!immedbyte", 0);
1010 emit2 ("ld h,!*hl");
1014 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1017 else if (IS_Z80 && aop->type == AOP_IY) {
1018 /* Instead of fetching relative to IY, just grab directly
1019 from the address IY refers to */
1020 char *l = aopGetLitWordLong (aop, offset, FALSE);
1022 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1024 if (aop->size < 2) {
1025 emit2("ld %s,!zero", _pairs[pairId].h);
1029 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1030 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1032 /* PENDING: check? */
1033 if (pairId == PAIR_HL)
1034 spillPair (PAIR_HL);
1039 fetchPair (PAIR_ID pairId, asmop * aop)
1041 fetchPairLong (pairId, aop, 0);
1045 fetchHL (asmop * aop)
1047 fetchPair (PAIR_HL, aop);
1051 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1053 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1058 fetchLitPair (pairId, aop, 0);
1061 fetchLitPair (pairId, aop, offset);
1062 _G.pairs[pairId].offset = offset;
1066 /* Doesnt include _G.stack.pushed */
1067 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1068 if (aop->aopu.aop_stk > 0)
1070 abso += _G.stack.param_offset;
1072 assert (pairId == PAIR_HL);
1073 /* In some cases we can still inc or dec hl */
1074 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1076 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1080 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1082 _G.pairs[pairId].offset = abso;
1088 _G.pairs[pairId].last_type = aop->type;
1094 emit2 ("!tlabeldef", key);
1098 /*-----------------------------------------------------------------*/
1099 /* aopGet - for fetching value of the aop */
1100 /*-----------------------------------------------------------------*/
1102 aopGet (asmop * aop, int offset, bool bit16)
1106 /* offset is greater than size then zero */
1107 /* PENDING: this seems a bit screwed in some pointer cases. */
1108 if (offset > (aop->size - 1) &&
1109 aop->type != AOP_LIT)
1111 tsprintf (s, "!zero");
1112 return gc_strdup(s);
1115 /* depending on type */
1119 /* PENDING: re-target */
1121 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1126 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1129 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1132 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1138 return gc_strdup(s);
1142 emit2 ("ld a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1145 return gc_strdup(s);
1149 emit2 ("ldh a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1152 return gc_strdup(s);
1155 return aop->aopu.aop_reg[offset]->name;
1159 setupPair (PAIR_HL, aop, offset);
1160 tsprintf (s, "!*hl");
1162 return gc_strdup (s);
1166 setupPair (PAIR_IY, aop, offset);
1167 tsprintf (s, "!*iyx", offset);
1169 return gc_strdup(s);
1174 setupPair (PAIR_HL, aop, offset);
1175 tsprintf (s, "!*hl");
1179 if (aop->aopu.aop_stk >= 0)
1180 offset += _G.stack.param_offset;
1181 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1184 return gc_strdup(s);
1196 tsprintf(s, "!zero");
1197 return gc_strdup(s);
1201 wassert (offset < 2);
1202 return aop->aopu.aop_str[offset];
1205 return aopLiteral (aop->aopu.aop_lit, offset);
1209 return aop->aopu.aop_str[offset];
1214 wassertl (0, "aopget got unsupported aop->type");
1219 isRegString (const char *s)
1221 if (!strcmp (s, "b") ||
1233 isConstant (const char *s)
1235 /* This is a bit of a hack... */
1236 return (*s == '#' || *s == '$');
1240 canAssignToPtr (const char *s)
1242 if (isRegString (s))
1249 /*-----------------------------------------------------------------*/
1250 /* aopPut - puts a string for a aop */
1251 /*-----------------------------------------------------------------*/
1253 aopPut (asmop * aop, const char *s, int offset)
1257 if (aop->size && offset > (aop->size - 1))
1259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260 "aopPut got offset > aop->size");
1265 tsprintf(buffer2, s);
1268 /* will assign value to value */
1269 /* depending on where it is ofcourse */
1275 if (strcmp (s, "a"))
1276 emit2 ("ld a,%s", s);
1277 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1282 if (strcmp (s, "a"))
1283 emit2 ("ld a,%s", s);
1284 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1288 if (!strcmp (s, "!*hl"))
1289 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1292 aop->aopu.aop_reg[offset]->name, s);
1297 setupPair (PAIR_IY, aop, offset);
1298 if (!canAssignToPtr (s))
1300 emit2 ("ld a,%s", s);
1301 emit2 ("ld !*iyx,a", offset);
1304 emit2 ("ld !*iyx,%s", offset, s);
1309 /* PENDING: for re-target */
1310 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1312 emit2 ("ld a,!*hl");
1315 setupPair (PAIR_HL, aop, offset);
1317 emit2 ("ld !*hl,%s", s);
1323 /* PENDING: re-target */
1324 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1326 emit2 ("ld a,!*hl");
1329 setupPair (PAIR_HL, aop, offset);
1330 if (!canAssignToPtr (s))
1332 emit2 ("ld a,%s", s);
1333 emit2 ("ld !*hl,a");
1336 emit2 ("ld !*hl,%s", s);
1340 if (aop->aopu.aop_stk >= 0)
1341 offset += _G.stack.param_offset;
1342 if (!canAssignToPtr (s))
1344 emit2 ("ld a,%s", s);
1345 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1348 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1353 /* if bit variable */
1354 if (!aop->aopu.aop_dir)
1361 /* In bit space but not in C - cant happen */
1368 if (strcmp (aop->aopu.aop_str[offset], s))
1370 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1376 if (!offset && (strcmp (s, "acc") == 0))
1381 emit2 ("; Error aopPut AOP_ACC");
1385 if (strcmp (aop->aopu.aop_str[offset], s))
1386 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1391 wassert (offset < 2);
1392 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1396 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1397 "aopPut got unsupported aop->type");
1402 #define AOP(op) op->aop
1403 #define AOP_TYPE(op) AOP(op)->type
1404 #define AOP_SIZE(op) AOP(op)->size
1405 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1408 commitPair (asmop * aop, PAIR_ID id)
1410 if (id == PAIR_HL && requiresHL (aop))
1414 aopPut (aop, "a", 0);
1415 aopPut (aop, "d", 1);
1419 aopPut (aop, _pairs[id].l, 0);
1420 aopPut (aop, _pairs[id].h, 1);
1424 /*-----------------------------------------------------------------*/
1425 /* getDataSize - get the operand data size */
1426 /*-----------------------------------------------------------------*/
1428 getDataSize (operand * op)
1431 size = AOP_SIZE (op);
1440 /*-----------------------------------------------------------------*/
1441 /* movLeft2Result - move byte from left to result */
1442 /*-----------------------------------------------------------------*/
1444 movLeft2Result (operand * left, int offl,
1445 operand * result, int offr, int sign)
1448 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1450 l = aopGet (AOP (left), offl, FALSE);
1454 aopPut (AOP (result), l, offr);
1464 /** Put Acc into a register set
1467 outAcc (operand * result)
1470 size = getDataSize (result);
1473 aopPut (AOP (result), "a", 0);
1476 /* unsigned or positive */
1479 aopPut (AOP (result), "!zero", offset++);
1484 /** Take the value in carry and put it into a register
1487 outBitCLong (operand * result, bool swap_sense)
1489 /* if the result is bit */
1490 if (AOP_TYPE (result) == AOP_CRY)
1492 emit2 ("; Note: outBitC form 1");
1493 aopPut (AOP (result), "blah", 0);
1497 emit2 ("ld a,!zero");
1500 emit2 ("xor a,!immedbyte", 1);
1506 outBitC (operand * result)
1508 outBitCLong (result, FALSE);
1511 /*-----------------------------------------------------------------*/
1512 /* toBoolean - emit code for orl a,operator(sizeop) */
1513 /*-----------------------------------------------------------------*/
1515 toBoolean (operand * oper)
1517 int size = AOP_SIZE (oper);
1521 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1524 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1528 if (AOP (oper)->type != AOP_ACC)
1531 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1536 /*-----------------------------------------------------------------*/
1537 /* genNot - generate code for ! operation */
1538 /*-----------------------------------------------------------------*/
1542 sym_link *optype = operandType (IC_LEFT (ic));
1544 /* assign asmOps to operand & result */
1545 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1546 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1548 /* if in bit space then a special case */
1549 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1554 /* if type float then do float */
1555 if (IS_FLOAT (optype))
1560 toBoolean (IC_LEFT (ic));
1565 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1566 emit2 ("sub a,!one");
1567 outBitC (IC_RESULT (ic));
1569 /* release the aops */
1570 freeAsmop (IC_LEFT (ic), NULL, ic);
1571 freeAsmop (IC_RESULT (ic), NULL, ic);
1574 /*-----------------------------------------------------------------*/
1575 /* genCpl - generate code for complement */
1576 /*-----------------------------------------------------------------*/
1584 /* assign asmOps to operand & result */
1585 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1586 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1588 /* if both are in bit space then
1590 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1591 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1596 size = AOP_SIZE (IC_RESULT (ic));
1599 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1602 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1605 /* release the aops */
1606 freeAsmop (IC_LEFT (ic), NULL, ic);
1607 freeAsmop (IC_RESULT (ic), NULL, ic);
1610 /*-----------------------------------------------------------------*/
1611 /* genUminus - unary minus code generation */
1612 /*-----------------------------------------------------------------*/
1614 genUminus (iCode * ic)
1617 sym_link *optype, *rtype;
1620 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1621 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1623 /* if both in bit space then special
1625 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1626 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1632 optype = operandType (IC_LEFT (ic));
1633 rtype = operandType (IC_RESULT (ic));
1635 /* if float then do float stuff */
1636 if (IS_FLOAT (optype))
1642 /* otherwise subtract from zero */
1643 size = AOP_SIZE (IC_LEFT (ic));
1648 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1649 emit2 ("ld a,!zero");
1650 emit2 ("sbc a,%s", l);
1651 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1654 /* if any remaining bytes in the result */
1655 /* we just need to propagate the sign */
1656 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1661 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1665 /* release the aops */
1666 freeAsmop (IC_LEFT (ic), NULL, ic);
1667 freeAsmop (IC_RESULT (ic), NULL, ic);
1671 _push (PAIR_ID pairId)
1673 emit2 ("push %s", _pairs[pairId].name);
1674 _G.stack.pushed += 2;
1678 _pop (PAIR_ID pairId)
1680 emit2 ("pop %s", _pairs[pairId].name);
1681 _G.stack.pushed -= 2;
1685 /*-----------------------------------------------------------------*/
1686 /* assignResultValue - */
1687 /*-----------------------------------------------------------------*/
1689 assignResultValue (operand * oper)
1691 int size = AOP_SIZE (oper);
1694 wassert (size <= 4);
1695 topInA = requiresHL (AOP (oper));
1699 wassert (size <= 2);
1701 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1703 /* We do it the hard way here. */
1705 aopPut (AOP (oper), _fReturn[0], 0);
1706 aopPut (AOP (oper), _fReturn[1], 1);
1708 _G.stack.pushed -= 2;
1709 aopPut (AOP (oper), _fReturn[0], 2);
1710 aopPut (AOP (oper), _fReturn[1], 3);
1716 aopPut (AOP (oper), _fReturn[size], size);
1722 _saveRegsForCall(iCode *ic, int sendSetSize)
1725 o Stack parameters are pushed before this function enters
1726 o DE and BC may be used in this function.
1727 o HL and DE may be used to return the result.
1728 o HL and DE may be used to send variables.
1729 o DE and BC may be used to store the result value.
1730 o HL may be used in computing the sent value of DE
1731 o The iPushes for other parameters occur before any addSets
1733 Logic: (to be run inside the first iPush or if none, before sending)
1734 o Compute if DE and/or BC are in use over the call
1735 o Compute if DE is used in the send set
1736 o Compute if DE and/or BC are used to hold the result value
1737 o If (DE is used, or in the send set) and is not used in the result, push.
1738 o If BC is used and is not in the result, push
1740 o If DE is used in the send set, fetch
1741 o If HL is used in the send set, fetch
1745 if (_G.saves.saved == FALSE) {
1746 bool deInUse, bcInUse;
1748 bool bcInRet = FALSE, deInRet = FALSE;
1752 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1756 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
1760 /* Has no result, so in use is all of in use */
1765 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
1766 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
1768 deSending = (sendSetSize > 1);
1770 emit2 ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
1772 if (bcInUse && bcInRet == FALSE) {
1774 _G.stack.pushedBC = TRUE;
1776 if (deInUse && deInRet == FALSE) {
1778 _G.stack.pushedDE = TRUE;
1781 _G.saves.saved = TRUE;
1784 /* Already saved. */
1788 /*-----------------------------------------------------------------*/
1789 /* genIpush - genrate code for pushing this gets a little complex */
1790 /*-----------------------------------------------------------------*/
1792 genIpush (iCode * ic)
1794 int size, offset = 0;
1797 /* if this is not a parm push : ie. it is spill push
1798 and spill push is always done on the local stack */
1801 wassertl(0, "Encountered an unsupported spill push.");
1805 if (_G.saves.saved == FALSE) {
1806 /* Caller saves, and this is the first iPush. */
1807 /* Scan ahead until we find the function that we are pushing parameters to.
1808 Count the number of addSets on the way to figure out what registers
1809 are used in the send set.
1812 iCode *walk = ic->next;
1815 if (walk->op == SEND) {
1818 else if (walk->op == CALL || walk->op == PCALL) {
1827 _saveRegsForCall(walk, nAddSets);
1830 /* Already saved by another iPush. */
1833 /* then do the push */
1834 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1836 size = AOP_SIZE (IC_LEFT (ic));
1838 if (isPair (AOP (IC_LEFT (ic))))
1840 _G.stack.pushed += 2;
1841 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1847 fetchHL (AOP (IC_LEFT (ic)));
1849 spillPair (PAIR_HL);
1850 _G.stack.pushed += 2;
1855 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1857 spillPair (PAIR_HL);
1858 _G.stack.pushed += 2;
1859 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1861 spillPair (PAIR_HL);
1862 _G.stack.pushed += 2;
1868 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1870 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1872 emit2 ("ld a,(%s)", l);
1876 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1877 emit2 ("ld a,%s", l);
1885 freeAsmop (IC_LEFT (ic), NULL, ic);
1888 /*-----------------------------------------------------------------*/
1889 /* genIpop - recover the registers: can happen only for spilling */
1890 /*-----------------------------------------------------------------*/
1892 genIpop (iCode * ic)
1897 /* if the temp was not pushed then */
1898 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1901 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1902 size = AOP_SIZE (IC_LEFT (ic));
1903 offset = (size - 1);
1904 if (isPair (AOP (IC_LEFT (ic))))
1906 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
1914 spillPair (PAIR_HL);
1915 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1919 freeAsmop (IC_LEFT (ic), NULL, ic);
1922 /* This is quite unfortunate */
1924 setArea (int inHome)
1927 static int lastArea = 0;
1929 if (_G.in_home != inHome) {
1931 const char *sz = port->mem.code_name;
1932 port->mem.code_name = "HOME";
1933 emit2("!area", CODE_NAME);
1934 port->mem.code_name = sz;
1937 emit2("!area", CODE_NAME); */
1938 _G.in_home = inHome;
1949 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1953 symbol *sym = OP_SYMBOL (op);
1955 if (sym->isspilt || sym->nRegs == 0)
1958 aopOp (op, ic, FALSE, FALSE);
1961 if (aop->type == AOP_REG)
1964 for (i = 0; i < aop->size; i++)
1966 if (pairId == PAIR_DE)
1968 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1969 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
1971 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
1974 else if (pairId == PAIR_BC)
1976 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1977 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
1979 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
1989 freeAsmop (IC_LEFT (ic), NULL, ic);
1993 /** Emit the code for a call statement
1996 emitCall (iCode * ic, bool ispcall)
1998 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
2000 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2002 /* if caller saves & we have not saved then */
2008 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2010 /* if send set is not empty then assign */
2015 int nSend = elementsInSet(_G.sendSet);
2016 bool swapped = FALSE;
2018 int _z80_sendOrder[] = {
2023 /* Check if the parameters are swapped. If so route through hl instead. */
2024 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2026 sic = setFirstItem(_G.sendSet);
2027 sic = setNextItem(_G.sendSet);
2029 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2030 /* The second send value is loaded from one the one that holds the first
2031 send, i.e. it is overwritten. */
2032 /* Cache the first in HL, and load the second from HL instead. */
2033 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2034 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2040 for (sic = setFirstItem (_G.sendSet); sic;
2041 sic = setNextItem (_G.sendSet))
2044 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2046 size = AOP_SIZE (IC_LEFT (sic));
2047 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2048 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2050 // PENDING: Mild hack
2051 if (swapped == TRUE && send == 1) {
2053 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2056 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2058 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2061 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2065 freeAsmop (IC_LEFT (sic), NULL, sic);
2072 if (IS_BANKEDCALL (detype))
2074 werror (W_INDIR_BANKED);
2076 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2078 if (isLitWord (AOP (IC_LEFT (ic))))
2080 emit2 ("; Special case where the pCall is to a constant");
2081 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2085 symbol *rlbl = newiTempLabel (NULL);
2086 spillPair (PAIR_HL);
2087 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2089 _G.stack.pushed += 2;
2091 fetchHL (AOP (IC_LEFT (ic)));
2093 emit2 ("!tlabeldef", (rlbl->key + 100));
2094 _G.stack.pushed -= 2;
2096 freeAsmop (IC_LEFT (ic), NULL, ic);
2100 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2101 OP_SYMBOL (IC_LEFT (ic))->rname :
2102 OP_SYMBOL (IC_LEFT (ic))->name;
2103 if (IS_BANKEDCALL (detype))
2105 emit2 ("call banked_call");
2106 emit2 ("!dws", name);
2107 emit2 ("!dw !bankimmeds", name);
2112 emit2 ("call %s", name);
2117 /* Mark the regsiters as restored. */
2118 _G.saves.saved = FALSE;
2120 /* if we need assign a result value */
2121 if ((IS_ITEMP (IC_RESULT (ic)) &&
2122 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2123 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2124 IS_TRUE_SYMOP (IC_RESULT (ic)))
2127 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2129 assignResultValue (IC_RESULT (ic));
2131 freeAsmop (IC_RESULT (ic), NULL, ic);
2134 /* adjust the stack for parameters if required */
2137 int i = ic->parmBytes;
2139 _G.stack.pushed -= i;
2142 emit2 ("!ldaspsp", i);
2149 emit2 ("ld hl,#%d", i);
2150 emit2 ("add hl,sp");
2167 if (_G.stack.pushedDE)
2169 bool dInUse = bitVectBitValue(rInUse, D_IDX);
2170 bool eInUse = bitVectBitValue(rInUse, E_IDX);
2172 if (dInUse && eInUse)
2188 wassertl (0, "Neither D or E were in use but it was pushed.");
2190 _G.stack.pushedDE = FALSE;
2193 if (_G.stack.pushedBC)
2195 bool bInUse = bitVectBitValue(rInUse, B_IDX);
2196 bool cInUse = bitVectBitValue(rInUse, C_IDX);
2198 // If both B and C are used in the return value, then we won't get
2200 if (bInUse && cInUse)
2216 wassertl (0, "Neither B or C were in use but it was pushed.");
2218 _G.stack.pushedBC = FALSE;
2222 /*-----------------------------------------------------------------*/
2223 /* genCall - generates a call statement */
2224 /*-----------------------------------------------------------------*/
2226 genCall (iCode * ic)
2228 emitCall (ic, FALSE);
2231 /*-----------------------------------------------------------------*/
2232 /* genPcall - generates a call by pointer statement */
2233 /*-----------------------------------------------------------------*/
2235 genPcall (iCode * ic)
2237 emitCall (ic, TRUE);
2240 /*-----------------------------------------------------------------*/
2241 /* resultRemat - result is rematerializable */
2242 /*-----------------------------------------------------------------*/
2244 resultRemat (iCode * ic)
2246 if (SKIP_IC (ic) || ic->op == IFX)
2249 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2251 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2252 if (sym->remat && !POINTER_SET (ic))
2259 extern set *publics;
2263 o Check emitCall and clean up
2265 o Check return puller
2267 PENDING: Remove this.
2270 /*-----------------------------------------------------------------*/
2271 /* genFunction - generated code for function entry */
2272 /*-----------------------------------------------------------------*/
2274 genFunction (iCode * ic)
2276 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2280 bool bcInUse = FALSE;
2281 bool deInUse = FALSE;
2284 setArea (IS_NONBANKED (sym->etype));
2286 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2289 _G.receiveOffset = 0;
2293 if (!IS_STATIC (sym->etype))
2295 addSetIfnotP (&publics, sym);
2299 /* Record the last function name for debugging. */
2300 _G.lastFunctionName = sym->rname;
2302 /* Create the function header */
2303 emit2 ("!functionheader", sym->name);
2304 /* PENDING: portability. */
2305 emit2 ("__%s_start:", sym->rname);
2306 emit2 ("!functionlabeldef", sym->rname);
2308 fetype = getSpec (operandType (IC_LEFT (ic)));
2310 /* if critical function then turn interrupts off */
2311 if (SPEC_CRTCL (fetype))
2314 /* if this is an interrupt service routine then save all potentially used registers. */
2315 if (IS_ISR (sym->etype))
2320 /* PENDING: callee-save etc */
2322 _G.stack.param_offset = 0;
2325 /* Detect which registers are used. */
2329 for (i = 0; i < sym->regsUsed->size; i++)
2331 if (bitVectBitValue (sym->regsUsed, i))
2345 /* Other systems use DE as a temporary. */
2356 _G.stack.param_offset += 2;
2359 _G.stack.pushedBC = bcInUse;
2364 _G.stack.param_offset += 2;
2367 _G.stack.pushedDE = deInUse;
2370 /* adjust the stack for the function */
2371 _G.stack.last = sym->stack;
2374 emit2 ("!enterx", sym->stack);
2377 _G.stack.offset = sym->stack;
2380 /*-----------------------------------------------------------------*/
2381 /* genEndFunction - generates epilogue for functions */
2382 /*-----------------------------------------------------------------*/
2384 genEndFunction (iCode * ic)
2386 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2388 if (IS_ISR (sym->etype))
2394 if (SPEC_CRTCL (sym->etype))
2397 /* PENDING: calleeSave */
2399 if (_G.stack.offset)
2401 emit2 ("!leavex", _G.stack.offset);
2409 if (_G.stack.pushedDE)
2412 _G.stack.pushedDE = FALSE;
2415 if (_G.stack.pushedDE)
2418 _G.stack.pushedDE = FALSE;
2422 /* Both baned and non-banked just ret */
2425 /* PENDING: portability. */
2426 emit2 ("__%s_end:", sym->rname);
2428 _G.flushStatics = 1;
2429 _G.stack.pushed = 0;
2430 _G.stack.offset = 0;
2433 /*-----------------------------------------------------------------*/
2434 /* genRet - generate code for return statement */
2435 /*-----------------------------------------------------------------*/
2440 /* Errk. This is a hack until I can figure out how
2441 to cause dehl to spill on a call */
2442 int size, offset = 0;
2444 /* if we have no return value then
2445 just generate the "ret" */
2449 /* we have something to return then
2450 move the return value into place */
2451 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2452 size = AOP_SIZE (IC_LEFT (ic));
2454 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2458 emit2 ("ld de,%s", l);
2462 emit2 ("ld hl,%s", l);
2467 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2469 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2470 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2476 l = aopGet (AOP (IC_LEFT (ic)), offset,
2478 if (strcmp (_fReturn[offset], l))
2479 emit2 ("ld %s,%s", _fReturn[offset++], l);
2483 freeAsmop (IC_LEFT (ic), NULL, ic);
2486 /* generate a jump to the return label
2487 if the next is not the return statement */
2488 if (!(ic->next && ic->next->op == LABEL &&
2489 IC_LABEL (ic->next) == returnLabel))
2491 emit2 ("jp !tlabel", returnLabel->key + 100);
2494 /*-----------------------------------------------------------------*/
2495 /* genLabel - generates a label */
2496 /*-----------------------------------------------------------------*/
2498 genLabel (iCode * ic)
2500 /* special case never generate */
2501 if (IC_LABEL (ic) == entryLabel)
2504 emitLabel (IC_LABEL (ic)->key + 100);
2507 /*-----------------------------------------------------------------*/
2508 /* genGoto - generates a ljmp */
2509 /*-----------------------------------------------------------------*/
2511 genGoto (iCode * ic)
2513 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2516 /*-----------------------------------------------------------------*/
2517 /* genPlusIncr :- does addition with increment if possible */
2518 /*-----------------------------------------------------------------*/
2520 genPlusIncr (iCode * ic)
2522 unsigned int icount;
2523 unsigned int size = getDataSize (IC_RESULT (ic));
2524 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2526 /* will try to generate an increment */
2527 /* if the right side is not a literal
2529 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2532 emit2 ("; genPlusIncr");
2534 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2536 /* If result is a pair */
2537 if (resultId != PAIR_INVALID)
2539 if (isLitWord (AOP (IC_LEFT (ic))))
2541 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2544 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2546 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2547 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2553 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2557 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2558 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2562 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2567 /* if the literal value of the right hand side
2568 is greater than 4 then it is not worth it */
2572 /* if increment 16 bits in register */
2573 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2579 symbol *tlbl = NULL;
2580 tlbl = newiTempLabel (NULL);
2583 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2586 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2589 emitLabel (tlbl->key + 100);
2593 /* if the sizes are greater than 1 then we cannot */
2594 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2595 AOP_SIZE (IC_LEFT (ic)) > 1)
2598 /* we can if the aops of the left & result match or
2599 if they are in registers and the registers are the
2601 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2604 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2611 /*-----------------------------------------------------------------*/
2612 /* outBitAcc - output a bit in acc */
2613 /*-----------------------------------------------------------------*/
2615 outBitAcc (operand * result)
2617 symbol *tlbl = newiTempLabel (NULL);
2618 /* if the result is a bit */
2619 if (AOP_TYPE (result) == AOP_CRY)
2625 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2626 emit2 ("ld a,!one");
2627 emitLabel (tlbl->key + 100);
2632 /*-----------------------------------------------------------------*/
2633 /* genPlus - generates code for addition */
2634 /*-----------------------------------------------------------------*/
2636 genPlus (iCode * ic)
2638 int size, offset = 0;
2640 /* special cases :- */
2642 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2643 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2644 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2646 /* Swap the left and right operands if:
2648 if literal, literal on the right or
2649 if left requires ACC or right is already
2652 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2653 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2654 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2656 operand *t = IC_RIGHT (ic);
2657 IC_RIGHT (ic) = IC_LEFT (ic);
2661 /* if both left & right are in bit
2663 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2664 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2670 /* if left in bit space & right literal */
2671 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2672 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2674 /* Can happen I guess */
2678 /* if I can do an increment instead
2679 of add then GOOD for ME */
2680 if (genPlusIncr (ic) == TRUE)
2683 emit2 ("; genPlusIncr failed");
2685 size = getDataSize (IC_RESULT (ic));
2687 /* Special case when left and right are constant */
2688 if (isPair (AOP (IC_RESULT (ic))))
2692 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2693 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2699 sprintf (buffer, "#(%s + %s)", left, right);
2700 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2705 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2707 /* Fetch into HL then do the add */
2708 spillPair (PAIR_HL);
2709 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2710 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2715 ld hl,sp+n trashes C so we cant afford to do it during an
2716 add with stack based varibles. Worst case is:
2729 So you cant afford to load up hl if either left, right, or result
2730 is on the stack (*sigh*) The alt is:
2738 Combinations in here are:
2739 * If left or right are in bc then the loss is small - trap later
2740 * If the result is in bc then the loss is also small
2744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2745 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2746 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2748 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2749 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2750 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2751 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2753 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2755 /* Swap left and right */
2756 operand *t = IC_RIGHT (ic);
2757 IC_RIGHT (ic) = IC_LEFT (ic);
2760 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2762 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2763 emit2 ("add hl,bc");
2767 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2768 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2769 emit2 ("add hl,de");
2771 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2776 emit2 ("; WARNING: This add is probably broken.\n");
2783 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2785 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2788 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2791 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2795 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2798 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2801 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2803 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2807 freeAsmop (IC_LEFT (ic), NULL, ic);
2808 freeAsmop (IC_RIGHT (ic), NULL, ic);
2809 freeAsmop (IC_RESULT (ic), NULL, ic);
2813 /*-----------------------------------------------------------------*/
2814 /* genMinusDec :- does subtraction with deccrement if possible */
2815 /*-----------------------------------------------------------------*/
2817 genMinusDec (iCode * ic)
2819 unsigned int icount;
2820 unsigned int size = getDataSize (IC_RESULT (ic));
2822 /* will try to generate an increment */
2823 /* if the right side is not a literal we cannot */
2824 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2827 /* if the literal value of the right hand side
2828 is greater than 4 then it is not worth it */
2829 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2832 size = getDataSize (IC_RESULT (ic));
2835 /* if increment 16 bits in register */
2836 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2840 symbol *tlbl = newiTempLabel (NULL);
2841 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2842 emit2 ("jp np," LABEL_STR, tlbl->key + 100);
2844 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2849 emitLabel (tlbl->key + 100);
2854 /* if decrement 16 bits in register */
2855 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2856 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2859 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2863 /* If result is a pair */
2864 if (isPair (AOP (IC_RESULT (ic))))
2866 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2867 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2869 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2873 /* if the sizes are greater than 1 then we cannot */
2874 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2875 AOP_SIZE (IC_LEFT (ic)) > 1)
2878 /* we can if the aops of the left & result match or if they are in
2879 registers and the registers are the same */
2880 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2883 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2890 /*-----------------------------------------------------------------*/
2891 /* genMinus - generates code for subtraction */
2892 /*-----------------------------------------------------------------*/
2894 genMinus (iCode * ic)
2896 int size, offset = 0;
2897 unsigned long lit = 0L;
2899 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2900 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2901 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2903 /* special cases :- */
2904 /* if both left & right are in bit space */
2905 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2906 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2912 /* if I can do an decrement instead of subtract then GOOD for ME */
2913 if (genMinusDec (ic) == TRUE)
2916 size = getDataSize (IC_RESULT (ic));
2918 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2923 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2927 /* Same logic as genPlus */
2930 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2931 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2932 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2934 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2935 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2936 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2937 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2939 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2940 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2942 if (left == PAIR_INVALID && right == PAIR_INVALID)
2947 else if (right == PAIR_INVALID)
2949 else if (left == PAIR_INVALID)
2952 fetchPair (left, AOP (IC_LEFT (ic)));
2953 /* Order is important. Right may be HL */
2954 fetchPair (right, AOP (IC_RIGHT (ic)));
2956 emit2 ("ld a,%s", _pairs[left].l);
2957 emit2 ("sub a,%s", _pairs[right].l);
2959 emit2 ("ld a,%s", _pairs[left].h);
2960 emit2 ("sbc a,%s", _pairs[right].h);
2962 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2963 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2968 emit2 ("; WARNING: This sub is probably broken.\n");
2973 /* if literal, add a,#-lit, else normal subb */
2976 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2977 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2981 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2984 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2988 /* first add without previous c */
2990 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2992 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2994 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2997 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2998 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2999 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3003 freeAsmop (IC_LEFT (ic), NULL, ic);
3004 freeAsmop (IC_RIGHT (ic), NULL, ic);
3005 freeAsmop (IC_RESULT (ic), NULL, ic);
3008 /*-----------------------------------------------------------------*/
3009 /* genMult - generates code for multiplication */
3010 /*-----------------------------------------------------------------*/
3012 genMult (iCode * ic)
3014 /* Shouldn't occur - all done through function calls */
3018 /*-----------------------------------------------------------------*/
3019 /* genDiv - generates code for division */
3020 /*-----------------------------------------------------------------*/
3024 /* Shouldn't occur - all done through function calls */
3028 /*-----------------------------------------------------------------*/
3029 /* genMod - generates code for division */
3030 /*-----------------------------------------------------------------*/
3034 /* Shouldn't occur - all done through function calls */
3038 /*-----------------------------------------------------------------*/
3039 /* genIfxJump :- will create a jump depending on the ifx */
3040 /*-----------------------------------------------------------------*/
3042 genIfxJump (iCode * ic, char *jval)
3047 /* if true label then we jump if condition
3051 jlbl = IC_TRUE (ic);
3052 if (!strcmp (jval, "a"))
3056 else if (!strcmp (jval, "c"))
3060 else if (!strcmp (jval, "nc"))
3066 /* The buffer contains the bit on A that we should test */
3072 /* false label is present */
3073 jlbl = IC_FALSE (ic);
3074 if (!strcmp (jval, "a"))
3078 else if (!strcmp (jval, "c"))
3082 else if (!strcmp (jval, "nc"))
3088 /* The buffer contains the bit on A that we should test */
3092 /* Z80 can do a conditional long jump */
3093 if (!strcmp (jval, "a"))
3097 else if (!strcmp (jval, "c"))
3100 else if (!strcmp (jval, "nc"))
3105 emit2 ("bit %s,a", jval);
3107 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3109 /* mark the icode as generated */
3114 _getPairIdName (PAIR_ID id)
3116 return _pairs[id].name;
3119 /** Generic compare for > or <
3122 genCmp (operand * left, operand * right,
3123 operand * result, iCode * ifx, int sign)
3125 int size, offset = 0;
3126 unsigned long lit = 0L;
3127 bool swap_sense = FALSE;
3129 /* if left & right are bit variables */
3130 if (AOP_TYPE (left) == AOP_CRY &&
3131 AOP_TYPE (right) == AOP_CRY)
3133 /* Cant happen on the Z80 */
3138 /* subtract right from left if at the
3139 end the carry flag is set then we know that
3140 left is greater than right */
3141 size = max (AOP_SIZE (left), AOP_SIZE (right));
3143 /* if unsigned char cmp with lit, just compare */
3145 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3147 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3150 emit2 ("xor a,!immedbyte", 0x80);
3151 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3154 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3160 If the left or the right is a lit:
3161 Load -lit into HL, add to right via, check sense.
3163 if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3165 PAIR_ID id = PAIR_DE;
3166 asmop *lit = AOP (right);
3167 asmop *op = AOP (left);
3170 if (AOP_TYPE (left) == AOP_LIT)
3178 emit2 ("ld e,%s", aopGet (op, 0, 0));
3179 emit2 ("ld a,%s", aopGet (op, 1, 0));
3180 emit2 ("xor a,!immedbyte", 0x80);
3185 id = getPairId (op);
3186 if (id == PAIR_INVALID)
3188 fetchPair (PAIR_DE, op);
3192 spillPair (PAIR_HL);
3193 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3194 emit2 ("add hl,%s", _getPairIdName (id));
3197 if (AOP_TYPE (right) == AOP_LIT)
3199 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3200 /* optimize if(x < 0) or if(x >= 0) */
3205 /* No sign so it's always false */
3210 /* Just load in the top most bit */
3211 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3212 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3214 genIfxJump (ifx, "7");
3225 /* First setup h and l contaning the top most bytes XORed */
3226 bool fDidXor = FALSE;
3227 if (AOP_TYPE (left) == AOP_LIT)
3229 unsigned long lit = (unsigned long)
3230 floatFromVal (AOP (left)->aopu.aop_lit);
3231 emit2 ("ld %s,!immedbyte", _fTmp[0],
3232 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3236 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3237 emit2 ("xor a,!immedbyte", 0x80);
3238 emit2 ("ld %s,a", _fTmp[0]);
3241 if (AOP_TYPE (right) == AOP_LIT)
3243 unsigned long lit = (unsigned long)
3244 floatFromVal (AOP (right)->aopu.aop_lit);
3245 emit2 ("ld %s,!immedbyte", _fTmp[1],
3246 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3250 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3251 emit2 ("xor a,!immedbyte", 0x80);
3252 emit2 ("ld %s,a", _fTmp[1]);
3264 /* Do a long subtract */
3267 _moveA (aopGet (AOP (left), offset, FALSE));
3269 if (sign && size == 0)
3271 emit2 ("ld a,%s", _fTmp[0]);
3272 emit2 ("sbc a,%s", _fTmp[1]);
3276 /* Subtract through, propagating the carry */
3277 emit2 ("sbc a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3284 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3286 outBitCLong (result, swap_sense);
3290 /* if the result is used in the next
3291 ifx conditional branch then generate
3292 code a little differently */
3294 genIfxJump (ifx, swap_sense ? "nc" : "c");
3296 outBitCLong (result, swap_sense);
3297 /* leave the result in acc */
3301 /*-----------------------------------------------------------------*/
3302 /* genCmpGt :- greater than comparison */
3303 /*-----------------------------------------------------------------*/
3305 genCmpGt (iCode * ic, iCode * ifx)
3307 operand *left, *right, *result;
3308 sym_link *letype, *retype;
3311 left = IC_LEFT (ic);
3312 right = IC_RIGHT (ic);
3313 result = IC_RESULT (ic);
3315 letype = getSpec (operandType (left));
3316 retype = getSpec (operandType (right));
3317 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3318 /* assign the amsops */
3319 aopOp (left, ic, FALSE, FALSE);
3320 aopOp (right, ic, FALSE, FALSE);
3321 aopOp (result, ic, TRUE, FALSE);
3323 genCmp (right, left, result, ifx, sign);
3325 freeAsmop (left, NULL, ic);
3326 freeAsmop (right, NULL, ic);
3327 freeAsmop (result, NULL, ic);
3330 /*-----------------------------------------------------------------*/
3331 /* genCmpLt - less than comparisons */
3332 /*-----------------------------------------------------------------*/
3334 genCmpLt (iCode * ic, iCode * ifx)
3336 operand *left, *right, *result;
3337 sym_link *letype, *retype;
3340 left = IC_LEFT (ic);
3341 right = IC_RIGHT (ic);
3342 result = IC_RESULT (ic);
3344 letype = getSpec (operandType (left));
3345 retype = getSpec (operandType (right));
3346 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3348 /* assign the amsops */
3349 aopOp (left, ic, FALSE, FALSE);
3350 aopOp (right, ic, FALSE, FALSE);
3351 aopOp (result, ic, TRUE, FALSE);
3353 genCmp (left, right, result, ifx, sign);
3355 freeAsmop (left, NULL, ic);
3356 freeAsmop (right, NULL, ic);
3357 freeAsmop (result, NULL, ic);
3360 /*-----------------------------------------------------------------*/
3361 /* gencjneshort - compare and jump if not equal */
3362 /*-----------------------------------------------------------------*/
3364 gencjneshort (operand * left, operand * right, symbol * lbl)
3366 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3368 unsigned long lit = 0L;
3370 /* Swap the left and right if it makes the computation easier */
3371 if (AOP_TYPE (left) == AOP_LIT)
3378 if (AOP_TYPE (right) == AOP_LIT)
3379 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3381 /* if the right side is a literal then anything goes */
3382 if (AOP_TYPE (right) == AOP_LIT &&
3383 AOP_TYPE (left) != AOP_DIR)
3387 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3394 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
3401 emit2 ("jp nz,!tlabel", lbl->key + 100);
3407 emit2 ("ld a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3408 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3411 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3412 emit2 ("jp nz,!tlabel", lbl->key + 100);
3417 /* if the right side is in a register or in direct space or
3418 if the left is a pointer register & right is not */
3419 else if (AOP_TYPE (right) == AOP_REG ||
3420 AOP_TYPE (right) == AOP_DIR ||
3421 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3425 _moveA (aopGet (AOP (left), offset, FALSE));
3426 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3427 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3429 emit2 ("jp nz,!tlabel", lbl->key + 100);
3432 emit2 ("cp %s ; 4", aopGet (AOP (right), offset, FALSE));
3433 emit2 ("jp nz,!tlabel", lbl->key + 100);
3440 /* right is a pointer reg need both a & b */
3441 /* PENDING: is this required? */
3444 _moveA (aopGet (AOP (right), offset, FALSE));
3445 emit2 ("cp %s ; 5", aopGet (AOP (left), offset, FALSE));
3446 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3452 /*-----------------------------------------------------------------*/
3453 /* gencjne - compare and jump if not equal */
3454 /*-----------------------------------------------------------------*/
3456 gencjne (operand * left, operand * right, symbol * lbl)
3458 symbol *tlbl = newiTempLabel (NULL);
3460 gencjneshort (left, right, lbl);
3463 emit2 ("ld a,!one");
3464 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3465 emitLabel (lbl->key + 100);
3467 emitLabel (tlbl->key + 100);
3470 /*-----------------------------------------------------------------*/
3471 /* genCmpEq - generates code for equal to */
3472 /*-----------------------------------------------------------------*/
3474 genCmpEq (iCode * ic, iCode * ifx)
3476 operand *left, *right, *result;
3478 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3479 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3480 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3482 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3484 /* Swap operands if it makes the operation easier. ie if:
3485 1. Left is a literal.
3487 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3489 operand *t = IC_RIGHT (ic);
3490 IC_RIGHT (ic) = IC_LEFT (ic);
3494 if (ifx && !AOP_SIZE (result))
3497 /* if they are both bit variables */
3498 if (AOP_TYPE (left) == AOP_CRY &&
3499 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3505 tlbl = newiTempLabel (NULL);
3506 gencjneshort (left, right, tlbl);
3509 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3510 emitLabel (tlbl->key + 100);
3514 /* PENDING: do this better */
3515 symbol *lbl = newiTempLabel (NULL);
3516 emit2 ("!shortjp !tlabel", lbl->key + 100);
3517 emitLabel (tlbl->key + 100);
3518 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3519 emitLabel (lbl->key + 100);
3522 /* mark the icode as generated */
3527 /* if they are both bit variables */
3528 if (AOP_TYPE (left) == AOP_CRY &&
3529 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3535 gencjne (left, right, newiTempLabel (NULL));
3536 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3542 genIfxJump (ifx, "a");
3545 /* if the result is used in an arithmetic operation
3546 then put the result in place */
3547 if (AOP_TYPE (result) != AOP_CRY)
3551 /* leave the result in acc */
3555 freeAsmop (left, NULL, ic);
3556 freeAsmop (right, NULL, ic);
3557 freeAsmop (result, NULL, ic);
3560 /*-----------------------------------------------------------------*/
3561 /* ifxForOp - returns the icode containing the ifx for operand */
3562 /*-----------------------------------------------------------------*/
3564 ifxForOp (operand * op, iCode * ic)
3566 /* if true symbol then needs to be assigned */
3567 if (IS_TRUE_SYMOP (op))
3570 /* if this has register type condition and
3571 the next instruction is ifx with the same operand
3572 and live to of the operand is upto the ifx only then */
3574 ic->next->op == IFX &&
3575 IC_COND (ic->next)->key == op->key &&
3576 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3582 /*-----------------------------------------------------------------*/
3583 /* genAndOp - for && operation */
3584 /*-----------------------------------------------------------------*/
3586 genAndOp (iCode * ic)
3588 operand *left, *right, *result;
3591 /* note here that && operations that are in an if statement are
3592 taken away by backPatchLabels only those used in arthmetic
3593 operations remain */
3594 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3595 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3596 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3598 /* if both are bit variables */
3599 if (AOP_TYPE (left) == AOP_CRY &&
3600 AOP_TYPE (right) == AOP_CRY)
3606 tlbl = newiTempLabel (NULL);
3608 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3610 emitLabel (tlbl->key + 100);
3614 freeAsmop (left, NULL, ic);
3615 freeAsmop (right, NULL, ic);
3616 freeAsmop (result, NULL, ic);
3619 /*-----------------------------------------------------------------*/
3620 /* genOrOp - for || operation */
3621 /*-----------------------------------------------------------------*/
3623 genOrOp (iCode * ic)
3625 operand *left, *right, *result;
3628 /* note here that || operations that are in an
3629 if statement are taken away by backPatchLabels
3630 only those used in arthmetic operations remain */
3631 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3632 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3633 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3635 /* if both are bit variables */
3636 if (AOP_TYPE (left) == AOP_CRY &&
3637 AOP_TYPE (right) == AOP_CRY)
3643 tlbl = newiTempLabel (NULL);
3645 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3647 emitLabel (tlbl->key + 100);
3651 freeAsmop (left, NULL, ic);
3652 freeAsmop (right, NULL, ic);
3653 freeAsmop (result, NULL, ic);
3656 /*-----------------------------------------------------------------*/
3657 /* isLiteralBit - test if lit == 2^n */
3658 /*-----------------------------------------------------------------*/
3660 isLiteralBit (unsigned long lit)
3662 unsigned long pw[32] =
3663 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3664 0x100L, 0x200L, 0x400L, 0x800L,
3665 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3666 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3667 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3668 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3669 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3672 for (idx = 0; idx < 32; idx++)
3678 /*-----------------------------------------------------------------*/
3679 /* jmpTrueOrFalse - */
3680 /*-----------------------------------------------------------------*/
3682 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3684 // ugly but optimized by peephole
3687 symbol *nlbl = newiTempLabel (NULL);
3688 emit2 ("jp !tlabel", nlbl->key + 100);
3689 emitLabel (tlbl->key + 100);
3690 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3691 emitLabel (nlbl->key + 100);
3695 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3696 emitLabel (tlbl->key + 100);
3701 /*-----------------------------------------------------------------*/
3702 /* genAnd - code for and */
3703 /*-----------------------------------------------------------------*/
3705 genAnd (iCode * ic, iCode * ifx)
3707 operand *left, *right, *result;
3708 int size, offset = 0;
3709 unsigned long lit = 0L;
3712 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3713 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3714 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3717 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3719 AOP_TYPE (left), AOP_TYPE (right));
3720 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3722 AOP_SIZE (left), AOP_SIZE (right));
3725 /* if left is a literal & right is not then exchange them */
3726 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3727 AOP_NEEDSACC (left))
3729 operand *tmp = right;
3734 /* if result = right then exchange them */
3735 if (sameRegs (AOP (result), AOP (right)))
3737 operand *tmp = right;
3742 /* if right is bit then exchange them */
3743 if (AOP_TYPE (right) == AOP_CRY &&
3744 AOP_TYPE (left) != AOP_CRY)
3746 operand *tmp = right;
3750 if (AOP_TYPE (right) == AOP_LIT)
3751 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3753 size = AOP_SIZE (result);
3755 if (AOP_TYPE (left) == AOP_CRY)
3761 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3762 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3763 if ((AOP_TYPE (right) == AOP_LIT) &&
3764 (AOP_TYPE (result) == AOP_CRY) &&
3765 (AOP_TYPE (left) != AOP_CRY))
3767 int posbit = isLiteralBit (lit);
3772 _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
3777 emit2 ("mov c,acc.%d", posbit & 0x07);
3784 sprintf (buffer, "%d", posbit & 0x07);
3785 genIfxJump (ifx, buffer);
3796 symbol *tlbl = newiTempLabel (NULL);
3797 int sizel = AOP_SIZE (left);
3805 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3807 _moveA (aopGet (AOP (left), offset, FALSE));
3809 if ((posbit = isLiteralBit (bytelit)) != 0)
3812 emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3816 if (bytelit != 0x0FFL)
3818 aopGet (AOP (right), offset, FALSE));
3822 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3827 // bit = left & literal
3831 emit2 ("!tlabeldef", tlbl->key + 100);
3833 // if(left & literal)
3837 jmpTrueOrFalse (ifx, tlbl);
3845 /* if left is same as result */
3846 if (sameRegs (AOP (result), AOP (left)))
3848 for (; size--; offset++)
3850 if (AOP_TYPE (right) == AOP_LIT)
3852 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3857 aopPut (AOP (result), "!zero", offset);
3860 _moveA (aopGet (AOP (left), offset, FALSE));
3862 aopGet (AOP (right), offset, FALSE));
3863 aopPut (AOP (left), "a", offset);
3870 if (AOP_TYPE (left) == AOP_ACC)
3876 _moveA (aopGet (AOP (left), offset, FALSE));
3878 aopGet (AOP (right), offset, FALSE));
3879 aopPut (AOP (left), "a", offset);
3886 // left & result in different registers
3887 if (AOP_TYPE (result) == AOP_CRY)
3893 for (; (size--); offset++)
3896 // result = left & right
3897 if (AOP_TYPE (right) == AOP_LIT)
3899 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3901 aopPut (AOP (result),
3902 aopGet (AOP (left), offset, FALSE),
3906 else if (bytelit == 0)
3908 aopPut (AOP (result), "!zero", offset);
3912 // faster than result <- left, anl result,right
3913 // and better if result is SFR
3914 if (AOP_TYPE (left) == AOP_ACC)
3915 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
3918 _moveA (aopGet (AOP (left), offset, FALSE));
3920 aopGet (AOP (right), offset, FALSE));
3922 aopPut (AOP (result), "a", offset);
3929 freeAsmop (left, NULL, ic);
3930 freeAsmop (right, NULL, ic);
3931 freeAsmop (result, NULL, ic);
3934 /*-----------------------------------------------------------------*/
3935 /* genOr - code for or */
3936 /*-----------------------------------------------------------------*/
3938 genOr (iCode * ic, iCode * ifx)
3940 operand *left, *right, *result;
3941 int size, offset = 0;
3942 unsigned long lit = 0L;
3944 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3945 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3946 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3949 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3951 AOP_TYPE (left), AOP_TYPE (right));
3952 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3954 AOP_SIZE (left), AOP_SIZE (right));
3957 /* if left is a literal & right is not then exchange them */
3958 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3959 AOP_NEEDSACC (left))
3961 operand *tmp = right;
3966 /* if result = right then exchange them */
3967 if (sameRegs (AOP (result), AOP (right)))
3969 operand *tmp = right;
3974 /* if right is bit then exchange them */
3975 if (AOP_TYPE (right) == AOP_CRY &&
3976 AOP_TYPE (left) != AOP_CRY)
3978 operand *tmp = right;
3982 if (AOP_TYPE (right) == AOP_LIT)
3983 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3985 size = AOP_SIZE (result);
3987 if (AOP_TYPE (left) == AOP_CRY)
3993 if ((AOP_TYPE (right) == AOP_LIT) &&
3994 (AOP_TYPE (result) == AOP_CRY) &&
3995 (AOP_TYPE (left) != AOP_CRY))
4001 /* if left is same as result */
4002 if (sameRegs (AOP (result), AOP (left)))
4004 for (; size--; offset++)
4006 if (AOP_TYPE (right) == AOP_LIT)
4008 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4012 _moveA (aopGet (AOP (left), offset, FALSE));
4014 aopGet (AOP (right), offset, FALSE));
4015 aopPut (AOP (result), "a", offset);
4020 if (AOP_TYPE (left) == AOP_ACC)
4021 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4024 _moveA (aopGet (AOP (left), offset, FALSE));
4026 aopGet (AOP (right), offset, FALSE));
4027 aopPut (AOP (result), "a", offset);
4034 // left & result in different registers
4035 if (AOP_TYPE (result) == AOP_CRY)
4040 for (; (size--); offset++)
4043 // result = left & right
4044 if (AOP_TYPE (right) == AOP_LIT)
4046 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4048 aopPut (AOP (result),
4049 aopGet (AOP (left), offset, FALSE),
4054 // faster than result <- left, anl result,right
4055 // and better if result is SFR
4056 if (AOP_TYPE (left) == AOP_ACC)
4057 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4060 _moveA (aopGet (AOP (left), offset, FALSE));
4062 aopGet (AOP (right), offset, FALSE));
4064 aopPut (AOP (result), "a", offset);
4065 /* PENDING: something weird is going on here. Add exception. */
4066 if (AOP_TYPE (result) == AOP_ACC)
4072 freeAsmop (left, NULL, ic);
4073 freeAsmop (right, NULL, ic);
4074 freeAsmop (result, NULL, ic);
4077 /*-----------------------------------------------------------------*/
4078 /* genXor - code for xclusive or */
4079 /*-----------------------------------------------------------------*/
4081 genXor (iCode * ic, iCode * ifx)
4083 operand *left, *right, *result;
4084 int size, offset = 0;
4085 unsigned long lit = 0L;
4087 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4088 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4089 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4091 /* if left is a literal & right is not then exchange them */
4092 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4093 AOP_NEEDSACC (left))
4095 operand *tmp = right;
4100 /* if result = right then exchange them */
4101 if (sameRegs (AOP (result), AOP (right)))
4103 operand *tmp = right;
4108 /* if right is bit then exchange them */
4109 if (AOP_TYPE (right) == AOP_CRY &&
4110 AOP_TYPE (left) != AOP_CRY)
4112 operand *tmp = right;
4116 if (AOP_TYPE (right) == AOP_LIT)
4117 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4119 size = AOP_SIZE (result);
4121 if (AOP_TYPE (left) == AOP_CRY)
4127 if ((AOP_TYPE (right) == AOP_LIT) &&
4128 (AOP_TYPE (result) == AOP_CRY) &&
4129 (AOP_TYPE (left) != AOP_CRY))
4135 /* if left is same as result */
4136 if (sameRegs (AOP (result), AOP (left)))
4138 for (; size--; offset++)
4140 if (AOP_TYPE (right) == AOP_LIT)
4142 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4146 _moveA (aopGet (AOP (right), offset, FALSE));
4148 aopGet (AOP (left), offset, FALSE));
4149 aopPut (AOP (result), "a", offset);
4154 if (AOP_TYPE (left) == AOP_ACC)
4156 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4160 _moveA (aopGet (AOP (right), offset, FALSE));
4162 aopGet (AOP (left), offset, FALSE));
4163 aopPut (AOP (result), "a", 0);
4170 // left & result in different registers
4171 if (AOP_TYPE (result) == AOP_CRY)
4176 for (; (size--); offset++)
4179 // result = left & right
4180 if (AOP_TYPE (right) == AOP_LIT)
4182 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4184 aopPut (AOP (result),
4185 aopGet (AOP (left), offset, FALSE),
4190 // faster than result <- left, anl result,right
4191 // and better if result is SFR
4192 if (AOP_TYPE (left) == AOP_ACC)
4194 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4198 _moveA (aopGet (AOP (right), offset, FALSE));
4200 aopGet (AOP (left), offset, FALSE));
4202 aopPut (AOP (result), "a", offset);
4207 freeAsmop (left, NULL, ic);
4208 freeAsmop (right, NULL, ic);
4209 freeAsmop (result, NULL, ic);
4212 /*-----------------------------------------------------------------*/
4213 /* genInline - write the inline code out */
4214 /*-----------------------------------------------------------------*/
4216 genInline (iCode * ic)
4218 char *buffer, *bp, *bp1;
4220 _G.lines.isInline += (!options.asmpeep);
4222 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4223 strcpy (buffer, IC_INLINE (ic));
4225 /* emit each line as a code */
4250 _G.lines.isInline -= (!options.asmpeep);
4254 /*-----------------------------------------------------------------*/
4255 /* genRRC - rotate right with carry */
4256 /*-----------------------------------------------------------------*/
4263 /*-----------------------------------------------------------------*/
4264 /* genRLC - generate code for rotate left with carry */
4265 /*-----------------------------------------------------------------*/
4272 /*-----------------------------------------------------------------*/
4273 /* genGetHbit - generates code get highest order bit */
4274 /*-----------------------------------------------------------------*/
4276 genGetHbit (iCode * ic)
4278 operand *left, *result;
4279 left = IC_LEFT (ic);
4280 result = IC_RESULT (ic);
4281 aopOp (left, ic, FALSE, FALSE);
4282 aopOp (result, ic, FALSE, FALSE);
4284 /* get the highest order byte into a */
4285 emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4287 if (AOP_TYPE (result) == AOP_CRY)
4295 /* PENDING: For re-target. */
4301 freeAsmop (left, NULL, ic);
4302 freeAsmop (result, NULL, ic);
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 is_signed)
4315 symbol *tlbl, *tlbl1;
4318 movLeft2Result (left, offl, result, offr, 0);
4319 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4321 /* if (AOP(result)->type == AOP_REG) { */
4323 tlbl = newiTempLabel (NULL);
4324 tlbl1 = newiTempLabel (NULL);
4326 /* Left is already in result - so now do the shift */
4329 emit2 ("ld a,!immedbyte+1", shCount);
4330 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4331 emitLabel (tlbl->key + 100);
4337 l = aopGet (AOP (result), size, FALSE);
4340 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4350 emitLabel (tlbl1->key + 100);
4352 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4356 /*-----------------------------------------------------------------*/
4357 /* shiftL2Left2Result - shift left two bytes from left to result */
4358 /*-----------------------------------------------------------------*/
4360 shiftL2Left2Result (operand * left, int offl,
4361 operand * result, int offr, int shCount)
4363 if (sameRegs (AOP (result), AOP (left)) &&
4364 ((offl + MSB16) == offr))
4370 /* Copy left into result */
4371 movLeft2Result (left, offl, result, offr, 0);
4372 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4374 /* PENDING: for now just see if it'll work. */
4375 /*if (AOP(result)->type == AOP_REG) { */
4379 symbol *tlbl, *tlbl1;
4382 tlbl = newiTempLabel (NULL);
4383 tlbl1 = newiTempLabel (NULL);
4385 /* Left is already in result - so now do the shift */
4388 emit2 ("ld a,!immedbyte+1", shCount);
4389 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4390 emitLabel (tlbl->key + 100);
4396 l = aopGet (AOP (result), offset, FALSE);
4404 emitLabel (tlbl1->key + 100);
4406 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4411 /*-----------------------------------------------------------------*/
4412 /* AccRol - rotate left accumulator by known count */
4413 /*-----------------------------------------------------------------*/
4415 AccRol (int shCount)
4417 shCount &= 0x0007; // shCount : 0..7
4456 /*-----------------------------------------------------------------*/
4457 /* AccLsh - left shift accumulator by known count */
4458 /*-----------------------------------------------------------------*/
4460 AccLsh (int shCount)
4462 static const unsigned char SLMask[] =
4464 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4473 else if (shCount == 2)
4480 /* rotate left accumulator */
4482 /* and kill the lower order bits */
4483 emit2 ("and a,!immedbyte", SLMask[shCount]);
4488 /*-----------------------------------------------------------------*/
4489 /* shiftL1Left2Result - shift left one byte from left to result */
4490 /*-----------------------------------------------------------------*/
4492 shiftL1Left2Result (operand * left, int offl,
4493 operand * result, int offr, int shCount)
4496 l = aopGet (AOP (left), offl, FALSE);
4498 /* shift left accumulator */
4500 aopPut (AOP (result), "a", offr);
4504 /*-----------------------------------------------------------------*/
4505 /* genlshTwo - left shift two bytes by known amount != 0 */
4506 /*-----------------------------------------------------------------*/
4508 genlshTwo (operand * result, operand * left, int shCount)
4510 int size = AOP_SIZE (result);
4512 wassert (size == 2);
4514 /* if shCount >= 8 */
4522 movLeft2Result (left, LSB, result, MSB16, 0);
4523 aopPut (AOP (result), "!zero", 0);
4524 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4528 movLeft2Result (left, LSB, result, MSB16, 0);
4529 aopPut (AOP (result), "!zero", 0);
4534 aopPut (AOP (result), "!zero", LSB);
4537 /* 1 <= shCount <= 7 */
4546 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4551 /*-----------------------------------------------------------------*/
4552 /* genlshOne - left shift a one byte quantity by known count */
4553 /*-----------------------------------------------------------------*/
4555 genlshOne (operand * result, operand * left, int shCount)
4557 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4560 /*-----------------------------------------------------------------*/
4561 /* genLeftShiftLiteral - left shifting by known count */
4562 /*-----------------------------------------------------------------*/
4564 genLeftShiftLiteral (operand * left,
4569 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4572 freeAsmop (right, NULL, ic);
4574 aopOp (left, ic, FALSE, FALSE);
4575 aopOp (result, ic, FALSE, FALSE);
4577 size = getSize (operandType (result));
4580 emit2 ("; shift left result %d, left %d", size,
4584 /* I suppose that the left size >= result size */
4590 else if (shCount >= (size * 8))
4594 aopPut (AOP (result), "!zero", size);
4602 genlshOne (result, left, shCount);
4605 genlshTwo (result, left, shCount);
4608 wassertl (0, "Shifting of longs is currently unsupported");
4614 freeAsmop (left, NULL, ic);
4615 freeAsmop (result, NULL, ic);
4618 /*-----------------------------------------------------------------*/
4619 /* genLeftShift - generates code for left shifting */
4620 /*-----------------------------------------------------------------*/
4622 genLeftShift (iCode * ic)
4626 symbol *tlbl, *tlbl1;
4627 operand *left, *right, *result;
4629 right = IC_RIGHT (ic);
4630 left = IC_LEFT (ic);
4631 result = IC_RESULT (ic);
4633 aopOp (right, ic, FALSE, FALSE);
4635 /* if the shift count is known then do it
4636 as efficiently as possible */
4637 if (AOP_TYPE (right) == AOP_LIT)
4639 genLeftShiftLiteral (left, right, result, ic);
4643 /* shift count is unknown then we have to form a loop get the loop
4644 count in B : Note: we take only the lower order byte since
4645 shifting more that 32 bits make no sense anyway, ( the largest
4646 size of an object can be only 32 bits ) */
4647 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4649 freeAsmop (right, NULL, ic);
4650 aopOp (left, ic, FALSE, FALSE);
4651 aopOp (result, ic, FALSE, FALSE);
4653 /* now move the left to the result if they are not the
4656 if (!sameRegs (AOP (left), AOP (result)))
4659 size = AOP_SIZE (result);
4663 l = aopGet (AOP (left), offset, FALSE);
4664 aopPut (AOP (result), l, offset);
4669 size = AOP_SIZE (result);
4673 l = aopGet (AOP (left), offset, FALSE);
4674 aopPut (AOP (result), l, offset);
4680 tlbl = newiTempLabel (NULL);
4681 size = AOP_SIZE (result);
4683 tlbl1 = newiTempLabel (NULL);
4685 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4686 emitLabel (tlbl->key + 100);
4687 l = aopGet (AOP (result), offset, FALSE);
4693 l = aopGet (AOP (result), offset++, FALSE);
4696 emitLabel (tlbl1->key + 100);
4698 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4700 freeAsmop (left, NULL, ic);
4701 freeAsmop (result, NULL, ic);
4704 /*-----------------------------------------------------------------*/
4705 /* genrshOne - left shift two bytes by known amount != 0 */
4706 /*-----------------------------------------------------------------*/
4708 genrshOne (operand * result, operand * left, int shCount, int is_signed)
4711 int size = AOP_SIZE (result);
4714 wassert (size == 1);
4715 wassert (shCount < 8);
4717 l = aopGet (AOP (left), 0, FALSE);
4721 if (AOP (result)->type == AOP_REG)
4723 aopPut (AOP (result), l, 0);
4724 l = aopGet (AOP (result), 0, FALSE);
4727 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4735 emit2 ("%s a", is_signed ? "sra" : "srl");
4737 aopPut (AOP (result), "a", 0);
4741 /*-----------------------------------------------------------------*/
4742 /* AccRsh - right shift accumulator by known count */
4743 /*-----------------------------------------------------------------*/
4745 AccRsh (int shCount)
4747 static const unsigned char SRMask[] =
4749 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4754 /* rotate right accumulator */
4755 AccRol (8 - shCount);
4756 /* and kill the higher order bits */
4757 emit2 ("and a,!immedbyte", SRMask[shCount]);
4761 /*-----------------------------------------------------------------*/
4762 /* shiftR1Left2Result - shift right one byte from left to result */
4763 /*-----------------------------------------------------------------*/
4765 shiftR1Left2Result (operand * left, int offl,
4766 operand * result, int offr,
4767 int shCount, int sign)
4769 _moveA (aopGet (AOP (left), offl, FALSE));
4778 aopPut (AOP (result), "a", offr);
4781 /*-----------------------------------------------------------------*/
4782 /* genrshTwo - right shift two bytes by known amount != 0 */
4783 /*-----------------------------------------------------------------*/
4785 genrshTwo (operand * result, operand * left,
4786 int shCount, int sign)
4788 /* if shCount >= 8 */
4794 shiftR1Left2Result (left, MSB16, result, LSB,
4799 movLeft2Result (left, MSB16, result, LSB, sign);
4801 aopPut (AOP (result), "!zero", 1);
4803 /* 1 <= shCount <= 7 */
4806 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4810 /*-----------------------------------------------------------------*/
4811 /* genRightShiftLiteral - left shifting by known count */
4812 /*-----------------------------------------------------------------*/
4814 genRightShiftLiteral (operand * left,
4820 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4823 freeAsmop (right, NULL, ic);
4825 aopOp (left, ic, FALSE, FALSE);
4826 aopOp (result, ic, FALSE, FALSE);
4828 size = getSize (operandType (result));
4830 emit2 ("; shift right result %d, left %d", size,
4833 /* I suppose that the left size >= result size */
4839 else if (shCount >= (size * 8))
4841 aopPut (AOP (result), "!zero", size);
4847 genrshOne (result, left, shCount, sign);
4850 /* PENDING: sign support */
4851 genrshTwo (result, left, shCount, sign);
4854 wassertl (0, "Asked to shift right a long which should be a function call");
4857 wassertl (0, "Entered default case in right shift delegate");
4860 freeAsmop (left, NULL, ic);
4861 freeAsmop (result, NULL, ic);
4864 /*-----------------------------------------------------------------*/
4865 /* genRightShift - generate code for right shifting */
4866 /*-----------------------------------------------------------------*/
4868 genRightShift (iCode * ic)
4870 operand *right, *left, *result;
4872 int size, offset, first = 1;
4876 symbol *tlbl, *tlbl1;
4878 /* if signed then we do it the hard way preserve the
4879 sign bit moving it inwards */
4880 retype = getSpec (operandType (IC_RESULT (ic)));
4882 is_signed = !SPEC_USIGN (retype);
4884 /* signed & unsigned types are treated the same : i.e. the
4885 signed is NOT propagated inwards : quoting from the
4886 ANSI - standard : "for E1 >> E2, is equivalent to division
4887 by 2**E2 if unsigned or if it has a non-negative value,
4888 otherwise the result is implementation defined ", MY definition
4889 is that the sign does not get propagated */
4891 right = IC_RIGHT (ic);
4892 left = IC_LEFT (ic);
4893 result = IC_RESULT (ic);
4895 aopOp (right, ic, FALSE, FALSE);
4897 /* if the shift count is known then do it
4898 as efficiently as possible */
4899 if (AOP_TYPE (right) == AOP_LIT)
4901 genRightShiftLiteral (left, right, result, ic, is_signed);
4905 aopOp (left, ic, FALSE, FALSE);
4906 aopOp (result, ic, FALSE, FALSE);
4908 /* now move the left to the result if they are not the
4910 if (!sameRegs (AOP (left), AOP (result)) &&
4911 AOP_SIZE (result) > 1)
4914 size = AOP_SIZE (result);
4918 l = aopGet (AOP (left), offset, FALSE);
4919 aopPut (AOP (result), l, offset);
4924 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4926 freeAsmop (right, NULL, ic);
4928 tlbl = newiTempLabel (NULL);
4929 tlbl1 = newiTempLabel (NULL);
4930 size = AOP_SIZE (result);
4933 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4934 emitLabel (tlbl->key + 100);
4937 l = aopGet (AOP (result), offset--, FALSE);
4940 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4948 emitLabel (tlbl1->key + 100);
4950 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4952 freeAsmop (left, NULL, ic);
4953 freeAsmop (result, NULL, ic);
4956 /*-----------------------------------------------------------------*/
4957 /* genGenPointerGet - get value from generic pointer space */
4958 /*-----------------------------------------------------------------*/
4960 genGenPointerGet (operand * left,
4961 operand * result, iCode * ic)
4964 sym_link *retype = getSpec (operandType (result));
4970 aopOp (left, ic, FALSE, FALSE);
4971 aopOp (result, ic, FALSE, FALSE);
4973 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4976 if (isPtrPair (AOP (left)))
4978 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4979 aopPut (AOP (result), buffer, 0);
4983 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4984 aopPut (AOP (result), "a", 0);
4986 freeAsmop (left, NULL, ic);
4990 /* For now we always load into IY */
4991 /* if this is remateriazable */
4992 fetchPair (pair, AOP (left));
4994 /* so iy now contains the address */
4995 freeAsmop (left, NULL, ic);
4997 /* if bit then unpack */
4998 if (IS_BITVAR (retype))
5004 size = AOP_SIZE (result);
5009 /* PENDING: make this better */
5010 if (!IS_GB && AOP (result)->type == AOP_REG)
5012 aopPut (AOP (result), "!*hl", offset++);
5016 emit2 ("ld a,!*pair", _pairs[pair].name);
5017 aopPut (AOP (result), "a", offset++);
5021 emit2 ("inc %s", _pairs[pair].name);
5022 _G.pairs[pair].offset++;
5028 freeAsmop (result, NULL, ic);
5031 /*-----------------------------------------------------------------*/
5032 /* genPointerGet - generate code for pointer get */
5033 /*-----------------------------------------------------------------*/
5035 genPointerGet (iCode * ic)
5037 operand *left, *result;
5038 sym_link *type, *etype;
5040 left = IC_LEFT (ic);
5041 result = IC_RESULT (ic);
5043 /* depending on the type of pointer we need to
5044 move it to the correct pointer register */
5045 type = operandType (left);
5046 etype = getSpec (type);
5048 genGenPointerGet (left, result, ic);
5052 isRegOrLit (asmop * aop)
5054 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
5059 /*-----------------------------------------------------------------*/
5060 /* genGenPointerSet - stores the value into a pointer location */
5061 /*-----------------------------------------------------------------*/
5063 genGenPointerSet (operand * right,
5064 operand * result, iCode * ic)
5067 sym_link *retype = getSpec (operandType (right));
5068 PAIR_ID pairId = PAIR_HL;
5070 aopOp (result, ic, FALSE, FALSE);
5071 aopOp (right, ic, FALSE, FALSE);
5076 /* Handle the exceptions first */
5077 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5080 const char *l = aopGet (AOP (right), 0, FALSE);
5081 const char *pair = getPairName (AOP (result));
5082 if (canAssignToPtr (l) && isPtr (pair))
5084 emit2 ("ld !*pair,%s", pair, l);
5089 emit2 ("ld !*pair,a", pair);
5094 /* if the operand is already in dptr
5095 then we do nothing else we move the value to dptr */
5096 if (AOP_TYPE (result) != AOP_STR)
5098 fetchPair (pairId, AOP (result));
5100 /* so hl know contains the address */
5101 freeAsmop (result, NULL, ic);
5103 /* if bit then unpack */
5104 if (IS_BITVAR (retype))
5110 size = AOP_SIZE (right);
5115 const char *l = aopGet (AOP (right), offset, FALSE);
5116 if (isRegOrLit (AOP (right)) && !IS_GB)
5118 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5123 emit2 ("ld !*pair,a", _pairs[pairId].name);
5127 emit2 ("inc %s", _pairs[pairId].name);
5128 _G.pairs[pairId].offset++;
5134 freeAsmop (right, NULL, ic);
5137 /*-----------------------------------------------------------------*/
5138 /* genPointerSet - stores the value into a pointer location */
5139 /*-----------------------------------------------------------------*/
5141 genPointerSet (iCode * ic)
5143 operand *right, *result;
5144 sym_link *type, *etype;
5146 right = IC_RIGHT (ic);
5147 result = IC_RESULT (ic);
5149 /* depending on the type of pointer we need to
5150 move it to the correct pointer register */
5151 type = operandType (result);
5152 etype = getSpec (type);
5154 genGenPointerSet (right, result, ic);
5157 /*-----------------------------------------------------------------*/
5158 /* genIfx - generate code for Ifx statement */
5159 /*-----------------------------------------------------------------*/
5161 genIfx (iCode * ic, iCode * popIc)
5163 operand *cond = IC_COND (ic);
5166 aopOp (cond, ic, FALSE, TRUE);
5168 /* get the value into acc */
5169 if (AOP_TYPE (cond) != AOP_CRY)
5173 /* the result is now in the accumulator */
5174 freeAsmop (cond, NULL, ic);
5176 /* if there was something to be popped then do it */
5180 /* if the condition is a bit variable */
5181 if (isbit && IS_ITEMP (cond) &&
5183 genIfxJump (ic, SPIL_LOC (cond)->rname);
5184 else if (isbit && !IS_ITEMP (cond))
5185 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5187 genIfxJump (ic, "a");
5192 /*-----------------------------------------------------------------*/
5193 /* genAddrOf - generates code for address of */
5194 /*-----------------------------------------------------------------*/
5196 genAddrOf (iCode * ic)
5198 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5200 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5202 /* if the operand is on the stack then we
5203 need to get the stack offset of this
5210 if (sym->stack <= 0)
5212 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5216 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5223 emit2 ("ld de,!hashedstr", sym->rname);
5225 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5226 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5233 /* if it has an offset then we need to compute it */
5235 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5237 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5238 emit2 ("add hl,sp");
5242 emit2 ("ld hl,#%s", sym->rname);
5244 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5245 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5247 freeAsmop (IC_RESULT (ic), NULL, ic);
5250 /*-----------------------------------------------------------------*/
5251 /* genAssign - generate code for assignment */
5252 /*-----------------------------------------------------------------*/
5254 genAssign (iCode * ic)
5256 operand *result, *right;
5258 unsigned long lit = 0L;
5260 result = IC_RESULT (ic);
5261 right = IC_RIGHT (ic);
5264 /* Dont bother assigning if they are the same */
5265 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5267 emit2 ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5272 aopOp (right, ic, FALSE, FALSE);
5273 aopOp (result, ic, TRUE, FALSE);
5275 /* if they are the same registers */
5276 if (sameRegs (AOP (right), AOP (result)))
5278 emit2 ("; (registers are the same)");
5282 /* if the result is a bit */
5283 if (AOP_TYPE (result) == AOP_CRY)
5289 size = AOP_SIZE (result);
5292 if (AOP_TYPE (right) == AOP_LIT)
5293 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5294 if (isPair (AOP (result)))
5296 fetchPair (getPairId (AOP (result)), AOP (right));
5298 else if ((size > 1) &&
5299 (AOP_TYPE (result) != AOP_REG) &&
5300 (AOP_TYPE (right) == AOP_LIT) &&
5301 !IS_FLOAT (operandType (right)) &&
5304 bool fXored = FALSE;
5306 /* Work from the top down.
5307 Done this way so that we can use the cached copy of 0
5308 in A for a fast clear */
5311 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5313 if (!fXored && size > 1)
5320 aopPut (AOP (result), "a", offset);
5324 aopPut (AOP (result), "!zero", offset);
5328 aopPut (AOP (result),
5329 aopGet (AOP (right), offset, FALSE),
5334 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5336 /* Special case. Load into a and d, then load out. */
5337 _moveA (aopGet (AOP (right), 0, FALSE));
5338 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5339 aopPut (AOP (result), "a", 0);
5340 aopPut (AOP (result), "e", 1);
5346 /* PENDING: do this check better */
5347 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5349 _moveA (aopGet (AOP (right), offset, FALSE));
5350 aopPut (AOP (result), "a", offset);
5353 aopPut (AOP (result),
5354 aopGet (AOP (right), offset, FALSE),
5361 freeAsmop (right, NULL, ic);
5362 freeAsmop (result, NULL, ic);
5365 /*-----------------------------------------------------------------*/
5366 /* genJumpTab - genrates code for jump table */
5367 /*-----------------------------------------------------------------*/
5369 genJumpTab (iCode * ic)
5374 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5375 /* get the condition into accumulator */
5376 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5379 emit2 ("ld e,%s", l);
5380 emit2 ("ld d,!zero");
5381 jtab = newiTempLabel (NULL);
5383 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5384 emit2 ("add hl,de");
5385 emit2 ("add hl,de");
5386 emit2 ("add hl,de");
5387 freeAsmop (IC_JTCOND (ic), NULL, ic);
5391 emitLabel (jtab->key + 100);
5392 /* now generate the jump labels */
5393 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5394 jtab = setNextItem (IC_JTLABELS (ic)))
5395 emit2 ("jp !tlabel", jtab->key + 100);
5398 /*-----------------------------------------------------------------*/
5399 /* genCast - gen code for casting */
5400 /*-----------------------------------------------------------------*/
5402 genCast (iCode * ic)
5404 operand *result = IC_RESULT (ic);
5405 sym_link *ctype = operandType (IC_LEFT (ic));
5406 operand *right = IC_RIGHT (ic);
5409 /* if they are equivalent then do nothing */
5410 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5413 aopOp (right, ic, FALSE, FALSE);
5414 aopOp (result, ic, FALSE, FALSE);
5416 /* if the result is a bit */
5417 if (AOP_TYPE (result) == AOP_CRY)
5422 /* if they are the same size : or less */
5423 if (AOP_SIZE (result) <= AOP_SIZE (right))
5426 /* if they are in the same place */
5427 if (sameRegs (AOP (right), AOP (result)))
5430 /* if they in different places then copy */
5431 size = AOP_SIZE (result);
5435 aopPut (AOP (result),
5436 aopGet (AOP (right), offset, FALSE),
5443 /* PENDING: should be OK. */
5445 /* if the result is of type pointer */
5452 /* so we now know that the size of destination is greater
5453 than the size of the source */
5454 /* we move to result for the size of source */
5455 size = AOP_SIZE (right);
5459 aopPut (AOP (result),
5460 aopGet (AOP (right), offset, FALSE),
5465 /* now depending on the sign of the destination */
5466 size = AOP_SIZE (result) - AOP_SIZE (right);
5467 /* Unsigned or not an integral type - right fill with zeros */
5468 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5471 aopPut (AOP (result), "!zero", offset++);
5475 /* we need to extend the sign :{ */
5476 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5479 emit2 ("; genCast: sign extend untested.");
5483 aopPut (AOP (result), "a", offset++);
5487 freeAsmop (right, NULL, ic);
5488 freeAsmop (result, NULL, ic);
5491 /*-----------------------------------------------------------------*/
5492 /* genReceive - generate code for a receive iCode */
5493 /*-----------------------------------------------------------------*/
5495 genReceive (iCode * ic)
5497 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5498 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5499 IS_TRUE_SYMOP (IC_RESULT (ic))))
5509 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5510 size = AOP_SIZE(IC_RESULT(ic));
5512 for (i = 0; i < size; i++) {
5513 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5517 freeAsmop (IC_RESULT (ic), NULL, ic);
5520 /*-----------------------------------------------------------------*/
5521 /* genZ80Code - generate code for Z80 based controllers */
5522 /*-----------------------------------------------------------------*/
5524 genZ80Code (iCode * lic)
5532 _fReturn = _gbz80_return;
5533 _fTmp = _gbz80_return;
5537 _fReturn = _z80_return;
5538 _fTmp = _z80_return;
5541 _G.lines.head = _G.lines.current = NULL;
5543 for (ic = lic; ic; ic = ic->next)
5546 if (cln != ic->lineno)
5548 emit2 ("; %s %d", ic->filename, ic->lineno);
5551 /* if the result is marked as
5552 spilt and rematerializable or code for
5553 this has already been generated then
5555 if (resultRemat (ic) || ic->generated)
5558 /* depending on the operation */
5572 emit2 ("; genUminus");
5577 emit2 ("; genIpush");
5582 /* IPOP happens only when trying to restore a
5583 spilt live range, if there is an ifx statement
5584 following this pop then the if statement might
5585 be using some of the registers being popped which
5586 would destory the contents of the register so
5587 we need to check for this condition and handle it */
5589 ic->next->op == IFX &&
5590 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5593 genIfx (ic->next, ic);
5597 emit2 ("; genIpop");
5603 emit2 ("; genCall");
5608 emit2 ("; genPcall");
5613 emit2 ("; genFunction");
5618 emit2 ("; genEndFunction");
5619 genEndFunction (ic);
5628 emit2 ("; genLabel");
5633 emit2 ("; genGoto");
5638 emit2 ("; genPlus");
5643 emit2 ("; genMinus");
5648 emit2 ("; genMult");
5663 emit2 ("; genCmpGt");
5664 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5668 emit2 ("; genCmpLt");
5669 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5676 /* note these two are xlated by algebraic equivalence
5677 during parsing SDCC.y */
5678 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5679 "got '>=' or '<=' shouldn't have come here");
5683 emit2 ("; genCmpEq");
5684 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5688 emit2 ("; genAndOp");
5693 emit2 ("; genOrOp");
5699 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5704 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5709 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5713 emit2 ("; genInline");
5728 emit2 ("; genGetHBIT");
5733 emit2 ("; genLeftShift");
5738 emit2 ("; genRightShift");
5742 case GET_VALUE_AT_ADDRESS:
5743 emit2 ("; genPointerGet");
5749 if (POINTER_SET (ic))
5751 emit2 ("; genAssign (pointer)");
5756 emit2 ("; genAssign");
5767 emit2 ("; genAddrOf");
5772 emit2 ("; genJumpTab");
5777 emit2 ("; genCast");
5782 emit2 ("; genReceive");
5788 addSet (&_G.sendSet, ic);
5793 /* piCode(ic,stdout); */
5799 /* now we are ready to call the
5800 peep hole optimizer */
5801 if (!options.nopeep)
5802 peepHole (&_G.lines.head);
5804 /* This is unfortunate */
5805 /* now do the actual printing */
5807 FILE *fp = codeOutFile;
5808 if (isInHome () && codeOutFile == code->oFile)
5809 codeOutFile = home->oFile;
5810 printLine (_G.lines.head, codeOutFile);
5811 if (_G.flushStatics)
5814 _G.flushStatics = 0;
5823 _isPairUsed (iCode * ic, PAIR_ID pairId)
5829 if (bitVectBitValue (ic->rMask, D_IDX))
5831 if (bitVectBitValue (ic->rMask, E_IDX))