1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 With reg params for mul and div 16234 202 162D
22 Michael Hope <michaelh@earthling.net> 2000
23 Based on the mcs51 generator -
24 Sandeep Dutta . sandeep.dutta@usa.net (1998)
25 and - Jean-Louis VERN.jlvern@writeme.com (1999)
27 This program is free software; you can redistribute it and/or modify it
28 under the terms of the GNU General Public License as published by the
29 Free Software Foundation; either version 2, or (at your option) any
32 This program is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 In other words, you are welcome to use, share and improve this program.
43 You are forbidden to forbid anyone else to use, share and improve
44 what you give them. Help stamp out software-hoarding!
46 -------------------------------------------------------------------------*/
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
64 /* this is the down and dirty file with all kinds of kludgy & hacky
65 stuff. This is what it is all about CODE GENERATION for a specific MCU.
66 Some of the routines may be reusable, will have to see */
68 /* Z80 calling convention description.
69 Parameters are passed right to left. As the stack grows downwards,
70 the parameters are arranged in left to right in memory.
71 Parameters may be passed in the HL and DE registers with one
73 PENDING: What if the parameter is a long?
74 Everything is caller saves. i.e. the caller must save any registers
75 that it wants to preserve over the call.
76 The return value is returned in DEHL. DE is normally used as a
77 working register pair. Caller saves allows it to be used for a
79 va args functions do not use register parameters. All arguments
80 are passed on the stack.
81 IX is used as an index register to the top of the local variable
82 area. ix-0 is the top most local variable.
84 static char *_z80_return[] =
86 static char *_gbz80_return[] =
88 static char *_fReceive[] =
89 { "c", "b", "e", "d" };
91 static char **_fReturn;
94 extern FILE *codeOutFile;
113 } _pairs[NUM_PAIRS] = {
114 { "??1", "?2", "?3" },
119 { "iy", "iy.l?", "iy.h?" },
120 { "ix", "ix.l?", "ix.h?" }
124 #define ACC_NAME _pairs[PAIR_AF].h
126 #define RESULTONSTACK(x) \
127 (IC_RESULT(x) && IC_RESULT(x)->aop && \
128 IC_RESULT(x)->aop->type == AOP_STK )
159 const char *lastFunctionName;
165 /** TRUE if the registers have already been saved. */
178 static const char *aopGet (asmop * aop, int offset, bool bit16);
183 /* Clean up the line so that it is 'prettier' */
184 if (strchr (buf, ':'))
186 /* Is a label - cant do anything */
189 /* Change the first (and probably only) ' ' to a tab so
204 emit2 (const char *szFormat,...)
209 va_start (ap, szFormat);
211 tvsprintf (buffer, szFormat, ap);
214 _G.lines.current = (_G.lines.current ?
215 connectLine (_G.lines.current, newLineNode (buffer)) :
216 (_G.lines.head = newLineNode (buffer)));
218 _G.lines.current->isInline = _G.lines.isInline;
221 /*-----------------------------------------------------------------*/
222 /* emit2 - writes the code into a file : for now it is simple */
223 /*-----------------------------------------------------------------*/
225 _emit2 (const char *inst, const char *fmt,...)
228 char lb[INITIAL_INLINEASM];
235 sprintf (lb, "%s\t", inst);
236 vsprintf (lb + (strlen (lb)), fmt, ap);
239 vsprintf (lb, fmt, ap);
241 while (isspace (*lbp))
246 _G.lines.current = (_G.lines.current ?
247 connectLine (_G.lines.current, newLineNode (lb)) :
248 (_G.lines.head = newLineNode (lb)));
250 _G.lines.current->isInline = _G.lines.isInline;
255 _emitMove(const char *to, const char *from)
257 if (strcasecmp(to, from) != 0)
259 emit2("ld %s,%s", to, from);
264 // Could leave this to the peephole, but sometimes the peephole is inhibited.
269 _moveA(const char *moveFrom)
271 // Let the peephole optimiser take care of redundent loads
272 _emitMove(ACC_NAME, moveFrom);
282 getPairName (asmop * aop)
284 if (aop->type == AOP_REG)
286 switch (aop->aopu.aop_reg[0]->rIdx)
299 else if (aop->type == AOP_STR)
301 switch (*aop->aopu.aop_str[0])
319 getPairId (asmop * aop)
323 if (aop->type == AOP_REG)
325 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
329 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
333 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
338 if (aop->type == AOP_STR)
340 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
344 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
348 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
357 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
361 return (getPairId (aop) != PAIR_INVALID);
365 isPtrPair (asmop * aop)
367 PAIR_ID pairId = getPairId (aop);
378 /** Push a register pair onto the stack */
380 genPairPush (asmop * aop)
382 emit2 ("push %s", getPairName (aop));
386 /*-----------------------------------------------------------------*/
387 /* newAsmop - creates a new asmOp */
388 /*-----------------------------------------------------------------*/
390 newAsmop (short type)
394 aop = Safe_calloc (1, sizeof (asmop));
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol */
401 /*-----------------------------------------------------------------*/
403 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
410 wassert (sym->etype);
412 space = SPEC_OCLS (sym->etype);
414 /* if already has one */
418 /* Assign depending on the storage class */
419 if (sym->onStack || sym->iaccess)
421 emit2 ("; AOP_STK for %s", sym->rname);
422 sym->aop = aop = newAsmop (AOP_STK);
423 aop->size = getSize (sym->type);
424 aop->aopu.aop_stk = sym->stack;
428 /* special case for a function */
429 if (IS_FUNC (sym->type))
431 sym->aop = aop = newAsmop (AOP_IMMD);
432 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
433 strcpy (aop->aopu.aop_immd, sym->rname);
440 /* if it is in direct space */
441 if (IN_REGSP (space) && !requires_a)
443 sym->aop = aop = newAsmop (AOP_SFR);
444 aop->aopu.aop_dir = sym->rname;
445 aop->size = getSize (sym->type);
446 emit2 ("; AOP_SFR for %s", sym->rname);
451 /* only remaining is far space */
452 /* in which case DPTR gets the address */
455 emit2 ("; AOP_HL for %s", sym->rname);
456 sym->aop = aop = newAsmop (AOP_HL);
460 sym->aop = aop = newAsmop (AOP_IY);
462 aop->size = getSize (sym->type);
463 aop->aopu.aop_dir = sym->rname;
465 /* if it is in code space */
466 if (IN_CODESPACE (space))
472 /*-----------------------------------------------------------------*/
473 /* aopForRemat - rematerialzes an object */
474 /*-----------------------------------------------------------------*/
476 aopForRemat (symbol * sym)
479 iCode *ic = sym->rematiCode;
480 asmop *aop = newAsmop (AOP_IMMD);
484 /* if plus or minus print the right hand side */
485 if (ic->op == '+' || ic->op == '-')
487 /* PENDING: for re-target */
488 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
491 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
494 /* we reached the end */
495 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
500 strcpy (aop->aopu.aop_immd, buffer);
504 /*-----------------------------------------------------------------*/
505 /* regsInCommon - two operands have some registers in common */
506 /*-----------------------------------------------------------------*/
508 regsInCommon (operand * op1, operand * op2)
513 /* if they have registers in common */
514 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
517 sym1 = OP_SYMBOL (op1);
518 sym2 = OP_SYMBOL (op2);
520 if (sym1->nRegs == 0 || sym2->nRegs == 0)
523 for (i = 0; i < sym1->nRegs; i++)
529 for (j = 0; j < sym2->nRegs; j++)
534 if (sym2->regs[j] == sym1->regs[i])
542 /*-----------------------------------------------------------------*/
543 /* operandsEqu - equivalent */
544 /*-----------------------------------------------------------------*/
546 operandsEqu (operand * op1, operand * op2)
550 /* if they not symbols */
551 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
554 sym1 = OP_SYMBOL (op1);
555 sym2 = OP_SYMBOL (op2);
557 /* if both are itemps & one is spilt
558 and the other is not then false */
559 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
560 sym1->isspilt != sym2->isspilt)
563 /* if they are the same */
567 if (strcmp (sym1->rname, sym2->rname) == 0)
571 /* if left is a tmp & right is not */
572 if (IS_ITEMP (op1) &&
575 (sym1->usl.spillLoc == sym2))
578 if (IS_ITEMP (op2) &&
582 (sym2->usl.spillLoc == sym1))
588 /*-----------------------------------------------------------------*/
589 /* sameRegs - two asmops have the same registers */
590 /*-----------------------------------------------------------------*/
592 sameRegs (asmop * aop1, asmop * aop2)
596 if (aop1->type == AOP_SFR ||
597 aop2->type == AOP_SFR)
603 if (aop1->type != AOP_REG ||
604 aop2->type != AOP_REG)
607 if (aop1->size != aop2->size)
610 for (i = 0; i < aop1->size; i++)
611 if (aop1->aopu.aop_reg[i] !=
612 aop2->aopu.aop_reg[i])
618 /*-----------------------------------------------------------------*/
619 /* aopOp - allocates an asmop for an operand : */
620 /*-----------------------------------------------------------------*/
622 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
631 /* if this a literal */
632 if (IS_OP_LITERAL (op))
634 op->aop = aop = newAsmop (AOP_LIT);
635 aop->aopu.aop_lit = op->operand.valOperand;
636 aop->size = getSize (operandType (op));
640 /* if already has a asmop then continue */
644 /* if the underlying symbol has a aop */
645 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
647 op->aop = OP_SYMBOL (op)->aop;
651 /* if this is a true symbol */
652 if (IS_TRUE_SYMOP (op))
654 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
658 /* this is a temporary : this has
664 e) can be a return use only */
666 sym = OP_SYMBOL (op);
668 /* if the type is a conditional */
669 if (sym->regType == REG_CND)
671 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
676 /* if it is spilt then two situations
678 b) has a spill location */
679 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
692 if (sym->accuse == ACCUSE_A)
694 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
695 aop->size = getSize (sym->type);
696 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
698 aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
700 else if (sym->accuse == ACCUSE_HL)
703 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
704 aop->size = getSize (sym->type);
705 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
706 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
707 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
719 aop = op->aop = sym->aop = newAsmop (AOP_STR);
720 aop->size = getSize (sym->type);
721 for (i = 0; i < 4; i++)
722 aop->aopu.aop_str[i] = _fReturn[i];
726 /* else spill location */
727 sym->aop = op->aop = aop =
728 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
729 aop->size = getSize (sym->type);
733 /* must be in a register */
734 sym->aop = op->aop = aop = newAsmop (AOP_REG);
735 aop->size = sym->nRegs;
736 for (i = 0; i < sym->nRegs; i++)
737 aop->aopu.aop_reg[i] = sym->regs[i];
740 /*-----------------------------------------------------------------*/
741 /* freeAsmop - free up the asmop given to an operand */
742 /*----------------------------------------------------------------*/
744 freeAsmop (operand * op, asmop * aaop, iCode * ic)
762 /* all other cases just dealloc */
768 OP_SYMBOL (op)->aop = NULL;
769 /* if the symbol has a spill */
771 SPIL_LOC (op)->aop = NULL;
777 isLitWord (asmop * aop)
779 /* if (aop->size != 2)
792 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
798 if (aop->size != 2 && aop->type != AOP_HL)
801 /* depending on type */
807 /* PENDING: for re-target */
809 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
811 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
812 rs = Safe_calloc (1, strlen (s) + 1);
817 value *val = aop->aopu.aop_lit;
818 /* if it is a float then it gets tricky */
819 /* otherwise it is fairly simple */
820 if (!IS_FLOAT (val->type))
822 unsigned long v = (unsigned long) floatFromVal (val);
828 tsprintf (buffer, "!immedword", v);
830 tsprintf (buffer, "!constword", v);
831 rs = Safe_calloc (1, strlen (buffer) + 1);
832 return strcpy (rs, buffer);
838 convertFloat (&f, floatFromVal (val));
840 tsprintf (buffer, "!immedword", f.w[offset / 2]);
842 tsprintf (buffer, "!constword", f.w[offset / 2]);
843 rs = Safe_calloc (1, strlen (buffer) + 1);
844 return strcpy (rs, buffer);
853 aopGetWord (asmop * aop, int offset)
855 return aopGetLitWordLong (aop, offset, TRUE);
859 isPtr (const char *s)
861 if (!strcmp (s, "hl"))
863 if (!strcmp (s, "ix"))
865 if (!strcmp (s, "iy"))
871 adjustPair (const char *pair, int *pold, int new)
877 emit2 ("inc %s", pair);
882 emit2 ("dec %s", pair);
888 spillPair (PAIR_ID pairId)
890 _G.pairs[pairId].last_type = AOP_INVALID;
891 _G.pairs[pairId].lit = NULL;
902 requiresHL (asmop * aop)
916 fetchLitSpecial (asmop * aop, bool negate, bool xor)
919 value *val = aop->aopu.aop_lit;
921 wassert (aop->type == AOP_LIT);
922 wassert (!IS_FLOAT (val->type));
924 v = (unsigned long) floatFromVal (val);
932 tsprintf (buffer, "!immedword", v);
933 return gc_strdup (buffer);
937 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
940 const char *pair = _pairs[pairId].name;
941 l = aopGetLitWordLong (left, 0, FALSE);
946 if (pairId == PAIR_HL || pairId == PAIR_IY)
948 if (_G.pairs[pairId].last_type == left->type)
950 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
952 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
954 adjustPair (pair, &_G.pairs[pairId].offset, offset);
957 if (pairId == PAIR_IY && abs (offset) < 127)
964 _G.pairs[pairId].last_type = left->type;
965 _G.pairs[pairId].lit = gc_strdup (l);
966 _G.pairs[pairId].offset = offset;
968 if (IS_GB && pairId == PAIR_DE && 0)
970 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
972 if (abs (_G.pairs[pairId].offset - offset) < 3)
974 adjustPair (pair, &_G.pairs[pairId].offset, offset);
978 _G.pairs[pairId].last_type = left->type;
979 _G.pairs[pairId].lit = gc_strdup (l);
980 _G.pairs[pairId].offset = offset;
982 /* Both a lit on the right and a true symbol on the left */
984 emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
986 emit2 ("ld %s,!hashedstr", pair, l);
990 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
992 /* if this is remateriazable */
993 if (isLitWord (aop)) {
994 fetchLitPair (pairId, aop, offset);
997 /* we need to get it byte by byte */
998 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
999 aopGet (aop, offset, FALSE);
1000 switch (aop->size) {
1002 emit2 ("ld l,!*hl");
1003 emit2 ("ld h,!immedbyte", 0);
1007 emit2 ("ld h,!*hl");
1011 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1014 else if (IS_Z80 && aop->type == AOP_IY) {
1015 /* Instead of fetching relative to IY, just grab directly
1016 from the address IY refers to */
1017 char *l = aopGetLitWordLong (aop, offset, FALSE);
1019 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1021 if (aop->size < 2) {
1022 emit2("ld %s,!zero", _pairs[pairId].h);
1026 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1027 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1029 /* PENDING: check? */
1030 if (pairId == PAIR_HL)
1031 spillPair (PAIR_HL);
1036 fetchPair (PAIR_ID pairId, asmop * aop)
1038 fetchPairLong (pairId, aop, 0);
1042 fetchHL (asmop * aop)
1044 fetchPair (PAIR_HL, aop);
1048 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1050 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1055 fetchLitPair (pairId, aop, 0);
1058 fetchLitPair (pairId, aop, offset);
1059 _G.pairs[pairId].offset = offset;
1063 /* Doesnt include _G.stack.pushed */
1064 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1065 if (aop->aopu.aop_stk > 0)
1067 abso += _G.stack.param_offset;
1069 assert (pairId == PAIR_HL);
1070 /* In some cases we can still inc or dec hl */
1071 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1073 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1077 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1079 _G.pairs[pairId].offset = abso;
1085 _G.pairs[pairId].last_type = aop->type;
1091 emit2 ("!tlabeldef", key);
1095 /*-----------------------------------------------------------------*/
1096 /* aopGet - for fetching value of the aop */
1097 /*-----------------------------------------------------------------*/
1099 aopGet (asmop * aop, int offset, bool bit16)
1103 /* offset is greater than size then zero */
1104 /* PENDING: this seems a bit screwed in some pointer cases. */
1105 if (offset > (aop->size - 1) &&
1106 aop->type != AOP_LIT)
1108 tsprintf (s, "!zero");
1109 return gc_strdup(s);
1112 /* depending on type */
1116 /* PENDING: re-target */
1118 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1123 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1126 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1129 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1135 return gc_strdup(s);
1139 emit2 ("ld a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1142 return gc_strdup(s);
1146 emit2 ("ldh a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1149 return gc_strdup(s);
1152 return aop->aopu.aop_reg[offset]->name;
1156 setupPair (PAIR_HL, aop, offset);
1157 tsprintf (s, "!*hl");
1159 return gc_strdup (s);
1163 setupPair (PAIR_IY, aop, offset);
1164 tsprintf (s, "!*iyx", offset);
1166 return gc_strdup(s);
1171 setupPair (PAIR_HL, aop, offset);
1172 tsprintf (s, "!*hl");
1176 if (aop->aopu.aop_stk >= 0)
1177 offset += _G.stack.param_offset;
1178 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1181 return gc_strdup(s);
1193 tsprintf(s, "!zero");
1194 return gc_strdup(s);
1198 wassert (offset < 2);
1199 return aop->aopu.aop_str[offset];
1202 return aopLiteral (aop->aopu.aop_lit, offset);
1206 return aop->aopu.aop_str[offset];
1211 wassertl (0, "aopget got unsupported aop->type");
1216 isRegString (const char *s)
1218 if (!strcmp (s, "b") ||
1230 isConstant (const char *s)
1232 /* This is a bit of a hack... */
1233 return (*s == '#' || *s == '$');
1237 canAssignToPtr (const char *s)
1239 if (isRegString (s))
1246 /*-----------------------------------------------------------------*/
1247 /* aopPut - puts a string for a aop */
1248 /*-----------------------------------------------------------------*/
1250 aopPut (asmop * aop, const char *s, int offset)
1254 if (aop->size && offset > (aop->size - 1))
1256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1257 "aopPut got offset > aop->size");
1262 tsprintf(buffer2, s);
1265 /* will assign value to value */
1266 /* depending on where it is ofcourse */
1272 if (strcmp (s, "a"))
1273 emit2 ("ld a,%s", s);
1274 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1279 if (strcmp (s, "a"))
1280 emit2 ("ld a,%s", s);
1281 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1285 if (!strcmp (s, "!*hl"))
1286 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1289 aop->aopu.aop_reg[offset]->name, s);
1294 setupPair (PAIR_IY, aop, offset);
1295 if (!canAssignToPtr (s))
1297 emit2 ("ld a,%s", s);
1298 emit2 ("ld !*iyx,a", offset);
1301 emit2 ("ld !*iyx,%s", offset, s);
1306 /* PENDING: for re-target */
1307 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1309 emit2 ("ld a,!*hl");
1312 setupPair (PAIR_HL, aop, offset);
1314 emit2 ("ld !*hl,%s", s);
1320 /* PENDING: re-target */
1321 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1323 emit2 ("ld a,!*hl");
1326 setupPair (PAIR_HL, aop, offset);
1327 if (!canAssignToPtr (s))
1329 emit2 ("ld a,%s", s);
1330 emit2 ("ld !*hl,a");
1333 emit2 ("ld !*hl,%s", s);
1337 if (aop->aopu.aop_stk >= 0)
1338 offset += _G.stack.param_offset;
1339 if (!canAssignToPtr (s))
1341 emit2 ("ld a,%s", s);
1342 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1345 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1350 /* if bit variable */
1351 if (!aop->aopu.aop_dir)
1358 /* In bit space but not in C - cant happen */
1365 if (strcmp (aop->aopu.aop_str[offset], s))
1367 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1373 if (!offset && (strcmp (s, "acc") == 0))
1378 emit2 ("; Error aopPut AOP_ACC");
1382 if (strcmp (aop->aopu.aop_str[offset], s))
1383 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1388 wassert (offset < 2);
1389 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1393 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1394 "aopPut got unsupported aop->type");
1399 #define AOP(op) op->aop
1400 #define AOP_TYPE(op) AOP(op)->type
1401 #define AOP_SIZE(op) AOP(op)->size
1402 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1405 commitPair (asmop * aop, PAIR_ID id)
1407 if (id == PAIR_HL && requiresHL (aop))
1411 aopPut (aop, "a", 0);
1412 aopPut (aop, "d", 1);
1416 aopPut (aop, _pairs[id].l, 0);
1417 aopPut (aop, _pairs[id].h, 1);
1421 /*-----------------------------------------------------------------*/
1422 /* getDataSize - get the operand data size */
1423 /*-----------------------------------------------------------------*/
1425 getDataSize (operand * op)
1428 size = AOP_SIZE (op);
1437 /*-----------------------------------------------------------------*/
1438 /* movLeft2Result - move byte from left to result */
1439 /*-----------------------------------------------------------------*/
1441 movLeft2Result (operand * left, int offl,
1442 operand * result, int offr, int sign)
1445 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1447 l = aopGet (AOP (left), offl, FALSE);
1451 aopPut (AOP (result), l, offr);
1461 /** Put Acc into a register set
1464 outAcc (operand * result)
1467 size = getDataSize (result);
1470 aopPut (AOP (result), "a", 0);
1473 /* unsigned or positive */
1476 aopPut (AOP (result), "!zero", offset++);
1481 /** Take the value in carry and put it into a register
1484 outBitCLong (operand * result, bool swap_sense)
1486 /* if the result is bit */
1487 if (AOP_TYPE (result) == AOP_CRY)
1489 emit2 ("; Note: outBitC form 1");
1490 aopPut (AOP (result), "blah", 0);
1494 emit2 ("ld a,!zero");
1497 emit2 ("xor a,!immedbyte", 1);
1503 outBitC (operand * result)
1505 outBitCLong (result, FALSE);
1508 /*-----------------------------------------------------------------*/
1509 /* toBoolean - emit code for orl a,operator(sizeop) */
1510 /*-----------------------------------------------------------------*/
1512 toBoolean (operand * oper)
1514 int size = AOP_SIZE (oper);
1518 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1521 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1525 if (AOP (oper)->type != AOP_ACC)
1528 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1539 sym_link *optype = operandType (IC_LEFT (ic));
1541 /* assign asmOps to operand & result */
1542 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1543 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1545 /* if in bit space then a special case */
1546 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1551 /* if type float then do float */
1552 if (IS_FLOAT (optype))
1557 toBoolean (IC_LEFT (ic));
1562 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1563 emit2 ("sub a,!one");
1564 outBitC (IC_RESULT (ic));
1566 /* release the aops */
1567 freeAsmop (IC_LEFT (ic), NULL, ic);
1568 freeAsmop (IC_RESULT (ic), NULL, ic);
1571 /*-----------------------------------------------------------------*/
1572 /* genCpl - generate code for complement */
1573 /*-----------------------------------------------------------------*/
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1585 /* if both are in bit space then
1587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1588 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593 size = AOP_SIZE (IC_RESULT (ic));
1596 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1599 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1602 /* release the aops */
1603 freeAsmop (IC_LEFT (ic), NULL, ic);
1604 freeAsmop (IC_RESULT (ic), NULL, ic);
1607 /*-----------------------------------------------------------------*/
1608 /* genUminus - unary minus code generation */
1609 /*-----------------------------------------------------------------*/
1611 genUminus (iCode * ic)
1614 sym_link *optype, *rtype;
1617 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1618 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1620 /* if both in bit space then special
1622 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1623 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1629 optype = operandType (IC_LEFT (ic));
1630 rtype = operandType (IC_RESULT (ic));
1632 /* if float then do float stuff */
1633 if (IS_FLOAT (optype))
1639 /* otherwise subtract from zero */
1640 size = AOP_SIZE (IC_LEFT (ic));
1645 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1646 emit2 ("ld a,!zero");
1647 emit2 ("sbc a,%s", l);
1648 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1651 /* if any remaining bytes in the result */
1652 /* we just need to propagate the sign */
1653 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1658 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1662 /* release the aops */
1663 freeAsmop (IC_LEFT (ic), NULL, ic);
1664 freeAsmop (IC_RESULT (ic), NULL, ic);
1668 _push (PAIR_ID pairId)
1670 emit2 ("push %s", _pairs[pairId].name);
1671 _G.stack.pushed += 2;
1675 _pop (PAIR_ID pairId)
1677 emit2 ("pop %s", _pairs[pairId].name);
1678 _G.stack.pushed -= 2;
1682 /*-----------------------------------------------------------------*/
1683 /* assignResultValue - */
1684 /*-----------------------------------------------------------------*/
1686 assignResultValue (operand * oper)
1688 int size = AOP_SIZE (oper);
1691 wassert (size <= 4);
1692 topInA = requiresHL (AOP (oper));
1696 wassert (size <= 2);
1698 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1700 /* We do it the hard way here. */
1702 aopPut (AOP (oper), _fReturn[0], 0);
1703 aopPut (AOP (oper), _fReturn[1], 1);
1705 _G.stack.pushed -= 2;
1706 aopPut (AOP (oper), _fReturn[0], 2);
1707 aopPut (AOP (oper), _fReturn[1], 3);
1713 aopPut (AOP (oper), _fReturn[size], size);
1719 _saveRegsForCall(iCode *ic, int sendSetSize)
1722 o Stack parameters are pushed before this function enters
1723 o DE and BC may be used in this function.
1724 o HL and DE may be used to return the result.
1725 o HL and DE may be used to send variables.
1726 o DE and BC may be used to store the result value.
1727 o HL may be used in computing the sent value of DE
1728 o The iPushes for other parameters occur before any addSets
1730 Logic: (to be run inside the first iPush or if none, before sending)
1731 o Compute if DE and/or BC are in use over the call
1732 o Compute if DE is used in the send set
1733 o Compute if DE and/or BC are used to hold the result value
1734 o If (DE is used, or in the send set) and is not used in the result, push.
1735 o If BC is used and is not in the result, push
1737 o If DE is used in the send set, fetch
1738 o If HL is used in the send set, fetch
1742 if (_G.saves.saved == FALSE) {
1743 bool deInUse, bcInUse;
1745 bool bcInRet = FALSE, deInRet = FALSE;
1750 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
1754 /* Has no result, so in use is all of in use */
1758 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
1759 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
1761 deSending = (sendSetSize > 1);
1763 emit2 ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
1765 if (bcInUse && bcInRet == FALSE) {
1767 _G.stack.pushedBC = TRUE;
1769 if (deInUse && deInRet == FALSE) {
1771 _G.stack.pushedDE = TRUE;
1774 _G.saves.saved = TRUE;
1777 /* Already saved. */
1781 /*-----------------------------------------------------------------*/
1782 /* genIpush - genrate code for pushing this gets a little complex */
1783 /*-----------------------------------------------------------------*/
1785 genIpush (iCode * ic)
1787 int size, offset = 0;
1790 /* if this is not a parm push : ie. it is spill push
1791 and spill push is always done on the local stack */
1794 wassertl(0, "Encountered an unsupported spill push.");
1796 /* and the item is spilt then do nothing */
1797 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1800 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1801 size = AOP_SIZE (IC_LEFT (ic));
1802 /* push it on the stack */
1803 if (isPair (AOP (IC_LEFT (ic))))
1805 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1806 _G.stack.pushed += 2;
1813 /* Simple for now - load into A and PUSH AF */
1814 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1816 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1818 emit2 ("ld a,(%s)", l);
1822 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1823 emit2 ("ld a,%s", l);
1834 if (_G.saves.saved == FALSE) {
1835 /* Caller saves, and this is the first iPush. */
1836 /* Scan ahead until we find the function that we are pushing parameters to.
1837 Count the number of addSets on the way to figure out what registers
1838 are used in the send set.
1841 iCode *walk = ic->next;
1844 if (walk->op == SEND) {
1847 else if (walk->op == CALL || walk->op == PCALL) {
1856 _saveRegsForCall(walk, nAddSets);
1859 /* Already saved by another iPush. */
1862 /* then do the push */
1863 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1865 size = AOP_SIZE (IC_LEFT (ic));
1867 if (isPair (AOP (IC_LEFT (ic))))
1869 _G.stack.pushed += 2;
1870 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
1876 fetchHL (AOP (IC_LEFT (ic)));
1878 spillPair (PAIR_HL);
1879 _G.stack.pushed += 2;
1884 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1886 spillPair (PAIR_HL);
1887 _G.stack.pushed += 2;
1888 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1890 spillPair (PAIR_HL);
1891 _G.stack.pushed += 2;
1897 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1899 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1901 emit2 ("ld a,(%s)", l);
1905 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1906 emit2 ("ld a,%s", l);
1914 freeAsmop (IC_LEFT (ic), NULL, ic);
1917 /*-----------------------------------------------------------------*/
1918 /* genIpop - recover the registers: can happen only for spilling */
1919 /*-----------------------------------------------------------------*/
1921 genIpop (iCode * ic)
1926 /* if the temp was not pushed then */
1927 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1930 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931 size = AOP_SIZE (IC_LEFT (ic));
1932 offset = (size - 1);
1933 if (isPair (AOP (IC_LEFT (ic))))
1935 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
1943 spillPair (PAIR_HL);
1944 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1948 freeAsmop (IC_LEFT (ic), NULL, ic);
1951 /* This is quite unfortunate */
1953 setArea (int inHome)
1956 static int lastArea = 0;
1958 if (_G.in_home != inHome) {
1960 const char *sz = port->mem.code_name;
1961 port->mem.code_name = "HOME";
1962 emit2("!area", CODE_NAME);
1963 port->mem.code_name = sz;
1966 emit2("!area", CODE_NAME); */
1967 _G.in_home = inHome;
1978 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1982 symbol *sym = OP_SYMBOL (op);
1984 if (sym->isspilt || sym->nRegs == 0)
1987 aopOp (op, ic, FALSE, FALSE);
1990 if (aop->type == AOP_REG)
1993 for (i = 0; i < aop->size; i++)
1995 if (pairId == PAIR_DE)
1997 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1998 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2000 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2003 else if (pairId == PAIR_BC)
2005 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
2006 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2008 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2018 freeAsmop (IC_LEFT (ic), NULL, ic);
2022 /** Emit the code for a call statement
2025 emitCall (iCode * ic, bool ispcall)
2027 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
2029 /* if caller saves & we have not saved then */
2035 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2037 /* if send set is not empty then assign */
2042 int nSend = elementsInSet(_G.sendSet);
2043 bool swapped = FALSE;
2045 int _z80_sendOrder[] = {
2050 /* Check if the parameters are swapped. If so route through hl instead. */
2051 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2053 sic = setFirstItem(_G.sendSet);
2054 sic = setNextItem(_G.sendSet);
2056 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2057 /* The second send value is loaded from one the one that holds the first
2058 send, i.e. it is overwritten. */
2059 /* Cache the first in HL, and load the second from HL instead. */
2060 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2061 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2067 for (sic = setFirstItem (_G.sendSet); sic;
2068 sic = setNextItem (_G.sendSet))
2071 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2073 size = AOP_SIZE (IC_LEFT (sic));
2074 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2075 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2077 // PENDING: Mild hack
2078 if (swapped == TRUE && send == 1) {
2080 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2083 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2085 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2088 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2092 freeAsmop (IC_LEFT (sic), NULL, sic);
2099 if (IS_BANKEDCALL (detype))
2101 werror (W_INDIR_BANKED);
2103 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2105 if (isLitWord (AOP (IC_LEFT (ic))))
2107 emit2 ("; Special case where the pCall is to a constant");
2108 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2112 symbol *rlbl = newiTempLabel (NULL);
2113 spillPair (PAIR_HL);
2114 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2116 _G.stack.pushed += 2;
2118 fetchHL (AOP (IC_LEFT (ic)));
2120 emit2 ("!tlabeldef", (rlbl->key + 100));
2121 _G.stack.pushed -= 2;
2123 freeAsmop (IC_LEFT (ic), NULL, ic);
2127 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2128 OP_SYMBOL (IC_LEFT (ic))->rname :
2129 OP_SYMBOL (IC_LEFT (ic))->name;
2130 if (IS_BANKEDCALL (detype))
2132 emit2 ("call banked_call");
2133 emit2 ("!dws", name);
2134 emit2 ("!dw !bankimmeds", name);
2139 emit2 ("call %s", name);
2144 /* Mark the regsiters as restored. */
2145 _G.saves.saved = FALSE;
2147 /* if we need assign a result value */
2148 if ((IS_ITEMP (IC_RESULT (ic)) &&
2149 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2150 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2151 IS_TRUE_SYMOP (IC_RESULT (ic)))
2154 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2156 assignResultValue (IC_RESULT (ic));
2158 freeAsmop (IC_RESULT (ic), NULL, ic);
2161 /* adjust the stack for parameters if required */
2164 int i = ic->parmBytes;
2166 _G.stack.pushed -= i;
2169 emit2 ("!ldaspsp", i);
2176 emit2 ("ld hl,#%d", i);
2177 emit2 ("add hl,sp");
2194 if (_G.stack.pushedDE)
2197 _G.stack.pushedDE = FALSE;
2200 if (_G.stack.pushedBC)
2203 _G.stack.pushedBC = FALSE;
2207 /*-----------------------------------------------------------------*/
2208 /* genCall - generates a call statement */
2209 /*-----------------------------------------------------------------*/
2211 genCall (iCode * ic)
2213 emitCall (ic, FALSE);
2216 /*-----------------------------------------------------------------*/
2217 /* genPcall - generates a call by pointer statement */
2218 /*-----------------------------------------------------------------*/
2220 genPcall (iCode * ic)
2222 emitCall (ic, TRUE);
2225 /*-----------------------------------------------------------------*/
2226 /* resultRemat - result is rematerializable */
2227 /*-----------------------------------------------------------------*/
2229 resultRemat (iCode * ic)
2231 if (SKIP_IC (ic) || ic->op == IFX)
2234 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2236 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2237 if (sym->remat && !POINTER_SET (ic))
2244 extern set *publics;
2248 o Check emitCall and clean up
2250 o Check return puller
2252 PENDING: Remove this.
2255 /*-----------------------------------------------------------------*/
2256 /* genFunction - generated code for function entry */
2257 /*-----------------------------------------------------------------*/
2259 genFunction (iCode * ic)
2261 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2265 bool bcInUse = FALSE;
2266 bool deInUse = FALSE;
2269 setArea (IS_NONBANKED (sym->etype));
2271 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2274 _G.receiveOffset = 0;
2278 if (!IS_STATIC (sym->etype))
2280 addSetIfnotP (&publics, sym);
2284 /* Record the last function name for debugging. */
2285 _G.lastFunctionName = sym->rname;
2287 /* Create the function header */
2288 emit2 ("!functionheader", sym->name);
2289 /* PENDING: portability. */
2290 emit2 ("__%s_start:", sym->rname);
2291 emit2 ("!functionlabeldef", sym->rname);
2293 fetype = getSpec (operandType (IC_LEFT (ic)));
2295 /* if critical function then turn interrupts off */
2296 if (SPEC_CRTCL (fetype))
2299 /* if this is an interrupt service routine then save all potentially used registers. */
2300 if (IS_ISR (sym->etype))
2305 /* PENDING: callee-save etc */
2307 _G.stack.param_offset = 0;
2310 /* Detect which registers are used. */
2314 for (i = 0; i < sym->regsUsed->size; i++)
2316 if (bitVectBitValue (sym->regsUsed, i))
2330 /* Other systems use DE as a temporary. */
2341 _G.stack.param_offset += 2;
2344 _G.stack.pushedBC = bcInUse;
2349 _G.stack.param_offset += 2;
2352 _G.stack.pushedDE = deInUse;
2355 /* adjust the stack for the function */
2356 _G.stack.last = sym->stack;
2359 emit2 ("!enterx", sym->stack);
2362 _G.stack.offset = sym->stack;
2365 /*-----------------------------------------------------------------*/
2366 /* genEndFunction - generates epilogue for functions */
2367 /*-----------------------------------------------------------------*/
2369 genEndFunction (iCode * ic)
2371 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2373 if (IS_ISR (sym->etype))
2379 if (SPEC_CRTCL (sym->etype))
2382 /* PENDING: calleeSave */
2384 if (_G.stack.offset)
2386 emit2 ("!leavex", _G.stack.offset);
2394 if (_G.stack.pushedDE)
2397 _G.stack.pushedDE = FALSE;
2400 if (_G.stack.pushedDE)
2403 _G.stack.pushedDE = FALSE;
2407 /* Both baned and non-banked just ret */
2410 /* PENDING: portability. */
2411 emit2 ("__%s_end:", sym->rname);
2413 _G.flushStatics = 1;
2414 _G.stack.pushed = 0;
2415 _G.stack.offset = 0;
2418 /*-----------------------------------------------------------------*/
2419 /* genRet - generate code for return statement */
2420 /*-----------------------------------------------------------------*/
2425 /* Errk. This is a hack until I can figure out how
2426 to cause dehl to spill on a call */
2427 int size, offset = 0;
2429 /* if we have no return value then
2430 just generate the "ret" */
2434 /* we have something to return then
2435 move the return value into place */
2436 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2437 size = AOP_SIZE (IC_LEFT (ic));
2439 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2443 emit2 ("ld de,%s", l);
2447 emit2 ("ld hl,%s", l);
2452 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2454 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2455 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2461 l = aopGet (AOP (IC_LEFT (ic)), offset,
2463 if (strcmp (_fReturn[offset], l))
2464 emit2 ("ld %s,%s", _fReturn[offset++], l);
2468 freeAsmop (IC_LEFT (ic), NULL, ic);
2471 /* generate a jump to the return label
2472 if the next is not the return statement */
2473 if (!(ic->next && ic->next->op == LABEL &&
2474 IC_LABEL (ic->next) == returnLabel))
2476 emit2 ("jp !tlabel", returnLabel->key + 100);
2479 /*-----------------------------------------------------------------*/
2480 /* genLabel - generates a label */
2481 /*-----------------------------------------------------------------*/
2483 genLabel (iCode * ic)
2485 /* special case never generate */
2486 if (IC_LABEL (ic) == entryLabel)
2489 emitLabel (IC_LABEL (ic)->key + 100);
2492 /*-----------------------------------------------------------------*/
2493 /* genGoto - generates a ljmp */
2494 /*-----------------------------------------------------------------*/
2496 genGoto (iCode * ic)
2498 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2501 /*-----------------------------------------------------------------*/
2502 /* genPlusIncr :- does addition with increment if possible */
2503 /*-----------------------------------------------------------------*/
2505 genPlusIncr (iCode * ic)
2507 unsigned int icount;
2508 unsigned int size = getDataSize (IC_RESULT (ic));
2509 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2511 /* will try to generate an increment */
2512 /* if the right side is not a literal
2514 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2517 emit2 ("; genPlusIncr");
2519 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2521 /* If result is a pair */
2522 if (resultId != PAIR_INVALID)
2524 if (isLitWord (AOP (IC_LEFT (ic))))
2526 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2529 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2531 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2532 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2538 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2542 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2543 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2547 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2552 /* if the literal value of the right hand side
2553 is greater than 4 then it is not worth it */
2557 /* if increment 16 bits in register */
2558 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2564 symbol *tlbl = NULL;
2565 tlbl = newiTempLabel (NULL);
2568 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2571 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2574 emitLabel (tlbl->key + 100);
2578 /* if the sizes are greater than 1 then we cannot */
2579 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2580 AOP_SIZE (IC_LEFT (ic)) > 1)
2583 /* we can if the aops of the left & result match or
2584 if they are in registers and the registers are the
2586 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2589 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2596 /*-----------------------------------------------------------------*/
2597 /* outBitAcc - output a bit in acc */
2598 /*-----------------------------------------------------------------*/
2600 outBitAcc (operand * result)
2602 symbol *tlbl = newiTempLabel (NULL);
2603 /* if the result is a bit */
2604 if (AOP_TYPE (result) == AOP_CRY)
2610 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2611 emit2 ("ld a,!one");
2612 emitLabel (tlbl->key + 100);
2617 /*-----------------------------------------------------------------*/
2618 /* genPlus - generates code for addition */
2619 /*-----------------------------------------------------------------*/
2621 genPlus (iCode * ic)
2623 int size, offset = 0;
2625 /* special cases :- */
2627 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2628 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2629 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2631 /* Swap the left and right operands if:
2633 if literal, literal on the right or
2634 if left requires ACC or right is already
2637 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2638 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2639 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2641 operand *t = IC_RIGHT (ic);
2642 IC_RIGHT (ic) = IC_LEFT (ic);
2646 /* if both left & right are in bit
2648 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2649 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2655 /* if left in bit space & right literal */
2656 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2657 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2659 /* Can happen I guess */
2663 /* if I can do an increment instead
2664 of add then GOOD for ME */
2665 if (genPlusIncr (ic) == TRUE)
2668 emit2 ("; genPlusIncr failed");
2670 size = getDataSize (IC_RESULT (ic));
2672 /* Special case when left and right are constant */
2673 if (isPair (AOP (IC_RESULT (ic))))
2677 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2678 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2684 sprintf (buffer, "#(%s + %s)", left, right);
2685 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2690 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2692 /* Fetch into HL then do the add */
2693 spillPair (PAIR_HL);
2694 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2695 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2700 ld hl,sp+n trashes C so we cant afford to do it during an
2701 add with stack based varibles. Worst case is:
2714 So you cant afford to load up hl if either left, right, or result
2715 is on the stack (*sigh*) The alt is:
2723 Combinations in here are:
2724 * If left or right are in bc then the loss is small - trap later
2725 * If the result is in bc then the loss is also small
2729 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2730 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2731 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2733 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2734 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2735 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2736 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2738 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2740 /* Swap left and right */
2741 operand *t = IC_RIGHT (ic);
2742 IC_RIGHT (ic) = IC_LEFT (ic);
2745 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2747 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2748 emit2 ("add hl,bc");
2752 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2753 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2754 emit2 ("add hl,de");
2756 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2761 emit2 ("; WARNING: This add is probably broken.\n");
2768 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2770 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2773 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2776 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2780 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2783 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2786 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2788 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2792 freeAsmop (IC_LEFT (ic), NULL, ic);
2793 freeAsmop (IC_RIGHT (ic), NULL, ic);
2794 freeAsmop (IC_RESULT (ic), NULL, ic);
2798 /*-----------------------------------------------------------------*/
2799 /* genMinusDec :- does subtraction with deccrement if possible */
2800 /*-----------------------------------------------------------------*/
2802 genMinusDec (iCode * ic)
2804 unsigned int icount;
2805 unsigned int size = getDataSize (IC_RESULT (ic));
2807 /* will try to generate an increment */
2808 /* if the right side is not a literal we cannot */
2809 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2812 /* if the literal value of the right hand side
2813 is greater than 4 then it is not worth it */
2814 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2817 size = getDataSize (IC_RESULT (ic));
2820 /* if increment 16 bits in register */
2821 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2825 symbol *tlbl = newiTempLabel (NULL);
2826 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2827 emit2 ("jp np," LABEL_STR, tlbl->key + 100);
2829 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2834 emitLabel (tlbl->key + 100);
2839 /* if decrement 16 bits in register */
2840 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2841 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2844 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2848 /* If result is a pair */
2849 if (isPair (AOP (IC_RESULT (ic))))
2851 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2852 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2854 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
2858 /* if the sizes are greater than 1 then we cannot */
2859 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2860 AOP_SIZE (IC_LEFT (ic)) > 1)
2863 /* we can if the aops of the left & result match or if they are in
2864 registers and the registers are the same */
2865 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2868 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2875 /*-----------------------------------------------------------------*/
2876 /* genMinus - generates code for subtraction */
2877 /*-----------------------------------------------------------------*/
2879 genMinus (iCode * ic)
2881 int size, offset = 0;
2882 unsigned long lit = 0L;
2884 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2885 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2886 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2888 /* special cases :- */
2889 /* if both left & right are in bit space */
2890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2891 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2897 /* if I can do an decrement instead of subtract then GOOD for ME */
2898 if (genMinusDec (ic) == TRUE)
2901 size = getDataSize (IC_RESULT (ic));
2903 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2908 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2912 /* Same logic as genPlus */
2915 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2916 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2917 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2919 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2920 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2921 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2922 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2924 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2925 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2927 if (left == PAIR_INVALID && right == PAIR_INVALID)
2932 else if (right == PAIR_INVALID)
2934 else if (left == PAIR_INVALID)
2937 fetchPair (left, AOP (IC_LEFT (ic)));
2938 /* Order is important. Right may be HL */
2939 fetchPair (right, AOP (IC_RIGHT (ic)));
2941 emit2 ("ld a,%s", _pairs[left].l);
2942 emit2 ("sub a,%s", _pairs[right].l);
2944 emit2 ("ld a,%s", _pairs[left].h);
2945 emit2 ("sbc a,%s", _pairs[right].h);
2947 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2948 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2953 emit2 ("; WARNING: This sub is probably broken.\n");
2958 /* if literal, add a,#-lit, else normal subb */
2961 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2962 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2966 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2969 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2973 /* first add without previous c */
2975 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2977 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2979 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2982 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2983 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2984 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2988 freeAsmop (IC_LEFT (ic), NULL, ic);
2989 freeAsmop (IC_RIGHT (ic), NULL, ic);
2990 freeAsmop (IC_RESULT (ic), NULL, ic);
2993 /*-----------------------------------------------------------------*/
2994 /* genMult - generates code for multiplication */
2995 /*-----------------------------------------------------------------*/
2997 genMult (iCode * ic)
2999 /* Shouldn't occur - all done through function calls */
3003 /*-----------------------------------------------------------------*/
3004 /* genDiv - generates code for division */
3005 /*-----------------------------------------------------------------*/
3009 /* Shouldn't occur - all done through function calls */
3013 /*-----------------------------------------------------------------*/
3014 /* genMod - generates code for division */
3015 /*-----------------------------------------------------------------*/
3019 /* Shouldn't occur - all done through function calls */
3023 /*-----------------------------------------------------------------*/
3024 /* genIfxJump :- will create a jump depending on the ifx */
3025 /*-----------------------------------------------------------------*/
3027 genIfxJump (iCode * ic, char *jval)
3032 /* if true label then we jump if condition
3036 jlbl = IC_TRUE (ic);
3037 if (!strcmp (jval, "a"))
3041 else if (!strcmp (jval, "c"))
3045 else if (!strcmp (jval, "nc"))
3051 /* The buffer contains the bit on A that we should test */
3057 /* false label is present */
3058 jlbl = IC_FALSE (ic);
3059 if (!strcmp (jval, "a"))
3063 else if (!strcmp (jval, "c"))
3067 else if (!strcmp (jval, "nc"))
3073 /* The buffer contains the bit on A that we should test */
3077 /* Z80 can do a conditional long jump */
3078 if (!strcmp (jval, "a"))
3082 else if (!strcmp (jval, "c"))
3085 else if (!strcmp (jval, "nc"))
3090 emit2 ("bit %s,a", jval);
3092 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3094 /* mark the icode as generated */
3099 _getPairIdName (PAIR_ID id)
3101 return _pairs[id].name;
3104 /** Generic compare for > or <
3107 genCmp (operand * left, operand * right,
3108 operand * result, iCode * ifx, int sign)
3110 int size, offset = 0;
3111 unsigned long lit = 0L;
3112 bool swap_sense = FALSE;
3114 /* if left & right are bit variables */
3115 if (AOP_TYPE (left) == AOP_CRY &&
3116 AOP_TYPE (right) == AOP_CRY)
3118 /* Cant happen on the Z80 */
3123 /* subtract right from left if at the
3124 end the carry flag is set then we know that
3125 left is greater than right */
3126 size = max (AOP_SIZE (left), AOP_SIZE (right));
3128 /* if unsigned char cmp with lit, just compare */
3130 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3132 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3135 emit2 ("xor a,!immedbyte", 0x80);
3136 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3139 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3145 If the left or the right is a lit:
3146 Load -lit into HL, add to right via, check sense.
3148 if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3150 PAIR_ID id = PAIR_DE;
3151 asmop *lit = AOP (right);
3152 asmop *op = AOP (left);
3155 if (AOP_TYPE (left) == AOP_LIT)
3163 emit2 ("ld e,%s", aopGet (op, 0, 0));
3164 emit2 ("ld a,%s", aopGet (op, 1, 0));
3165 emit2 ("xor a,!immedbyte", 0x80);
3170 id = getPairId (op);
3171 if (id == PAIR_INVALID)
3173 fetchPair (PAIR_DE, op);
3177 spillPair (PAIR_HL);
3178 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3179 emit2 ("add hl,%s", _getPairIdName (id));
3182 if (AOP_TYPE (right) == AOP_LIT)
3184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3185 /* optimize if(x < 0) or if(x >= 0) */
3190 /* No sign so it's always false */
3195 /* Just load in the top most bit */
3196 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3197 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3199 genIfxJump (ifx, "7");
3210 /* First setup h and l contaning the top most bytes XORed */
3211 bool fDidXor = FALSE;
3212 if (AOP_TYPE (left) == AOP_LIT)
3214 unsigned long lit = (unsigned long)
3215 floatFromVal (AOP (left)->aopu.aop_lit);
3216 emit2 ("ld %s,!immedbyte", _fTmp[0],
3217 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3221 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3222 emit2 ("xor a,!immedbyte", 0x80);
3223 emit2 ("ld %s,a", _fTmp[0]);
3226 if (AOP_TYPE (right) == AOP_LIT)
3228 unsigned long lit = (unsigned long)
3229 floatFromVal (AOP (right)->aopu.aop_lit);
3230 emit2 ("ld %s,!immedbyte", _fTmp[1],
3231 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3235 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3236 emit2 ("xor a,!immedbyte", 0x80);
3237 emit2 ("ld %s,a", _fTmp[1]);
3249 /* Do a long subtract */
3252 _moveA (aopGet (AOP (left), offset, FALSE));
3254 if (sign && size == 0)
3256 emit2 ("ld a,%s", _fTmp[0]);
3257 emit2 ("sbc a,%s", _fTmp[1]);
3261 /* Subtract through, propagating the carry */
3262 emit2 ("sbc a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3269 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3271 outBitCLong (result, swap_sense);
3275 /* if the result is used in the next
3276 ifx conditional branch then generate
3277 code a little differently */
3279 genIfxJump (ifx, swap_sense ? "nc" : "c");
3281 outBitCLong (result, swap_sense);
3282 /* leave the result in acc */
3286 /*-----------------------------------------------------------------*/
3287 /* genCmpGt :- greater than comparison */
3288 /*-----------------------------------------------------------------*/
3290 genCmpGt (iCode * ic, iCode * ifx)
3292 operand *left, *right, *result;
3293 sym_link *letype, *retype;
3296 left = IC_LEFT (ic);
3297 right = IC_RIGHT (ic);
3298 result = IC_RESULT (ic);
3300 letype = getSpec (operandType (left));
3301 retype = getSpec (operandType (right));
3302 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3303 /* assign the amsops */
3304 aopOp (left, ic, FALSE, FALSE);
3305 aopOp (right, ic, FALSE, FALSE);
3306 aopOp (result, ic, TRUE, FALSE);
3308 genCmp (right, left, result, ifx, sign);
3310 freeAsmop (left, NULL, ic);
3311 freeAsmop (right, NULL, ic);
3312 freeAsmop (result, NULL, ic);
3315 /*-----------------------------------------------------------------*/
3316 /* genCmpLt - less than comparisons */
3317 /*-----------------------------------------------------------------*/
3319 genCmpLt (iCode * ic, iCode * ifx)
3321 operand *left, *right, *result;
3322 sym_link *letype, *retype;
3325 left = IC_LEFT (ic);
3326 right = IC_RIGHT (ic);
3327 result = IC_RESULT (ic);
3329 letype = getSpec (operandType (left));
3330 retype = getSpec (operandType (right));
3331 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3333 /* assign the amsops */
3334 aopOp (left, ic, FALSE, FALSE);
3335 aopOp (right, ic, FALSE, FALSE);
3336 aopOp (result, ic, TRUE, FALSE);
3338 genCmp (left, right, result, ifx, sign);
3340 freeAsmop (left, NULL, ic);
3341 freeAsmop (right, NULL, ic);
3342 freeAsmop (result, NULL, ic);
3345 /*-----------------------------------------------------------------*/
3346 /* gencjneshort - compare and jump if not equal */
3347 /*-----------------------------------------------------------------*/
3349 gencjneshort (operand * left, operand * right, symbol * lbl)
3351 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3353 unsigned long lit = 0L;
3355 /* Swap the left and right if it makes the computation easier */
3356 if (AOP_TYPE (left) == AOP_LIT)
3363 if (AOP_TYPE (right) == AOP_LIT)
3364 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3366 /* if the right side is a literal then anything goes */
3367 if (AOP_TYPE (right) == AOP_LIT &&
3368 AOP_TYPE (left) != AOP_DIR)
3372 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3379 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
3386 emit2 ("jp nz,!tlabel", lbl->key + 100);
3392 emit2 ("ld a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3393 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3396 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3397 emit2 ("jp nz,!tlabel", lbl->key + 100);
3402 /* if the right side is in a register or in direct space or
3403 if the left is a pointer register & right is not */
3404 else if (AOP_TYPE (right) == AOP_REG ||
3405 AOP_TYPE (right) == AOP_DIR ||
3406 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3410 _moveA (aopGet (AOP (left), offset, FALSE));
3411 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3412 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3414 emit2 ("jp nz,!tlabel", lbl->key + 100);
3417 emit2 ("cp %s ; 4", aopGet (AOP (right), offset, FALSE));
3418 emit2 ("jp nz,!tlabel", lbl->key + 100);
3425 /* right is a pointer reg need both a & b */
3426 /* PENDING: is this required? */
3429 _moveA (aopGet (AOP (right), offset, FALSE));
3430 emit2 ("cp %s ; 5", aopGet (AOP (left), offset, FALSE));
3431 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3437 /*-----------------------------------------------------------------*/
3438 /* gencjne - compare and jump if not equal */
3439 /*-----------------------------------------------------------------*/
3441 gencjne (operand * left, operand * right, symbol * lbl)
3443 symbol *tlbl = newiTempLabel (NULL);
3445 gencjneshort (left, right, lbl);
3448 emit2 ("ld a,!one");
3449 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3450 emitLabel (lbl->key + 100);
3452 emitLabel (tlbl->key + 100);
3455 /*-----------------------------------------------------------------*/
3456 /* genCmpEq - generates code for equal to */
3457 /*-----------------------------------------------------------------*/
3459 genCmpEq (iCode * ic, iCode * ifx)
3461 operand *left, *right, *result;
3463 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3464 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3465 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3467 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3469 /* Swap operands if it makes the operation easier. ie if:
3470 1. Left is a literal.
3472 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3474 operand *t = IC_RIGHT (ic);
3475 IC_RIGHT (ic) = IC_LEFT (ic);
3479 if (ifx && !AOP_SIZE (result))
3482 /* if they are both bit variables */
3483 if (AOP_TYPE (left) == AOP_CRY &&
3484 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3490 tlbl = newiTempLabel (NULL);
3491 gencjneshort (left, right, tlbl);
3494 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3495 emitLabel (tlbl->key + 100);
3499 /* PENDING: do this better */
3500 symbol *lbl = newiTempLabel (NULL);
3501 emit2 ("!shortjp !tlabel", lbl->key + 100);
3502 emitLabel (tlbl->key + 100);
3503 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3504 emitLabel (lbl->key + 100);
3507 /* mark the icode as generated */
3512 /* if they are both bit variables */
3513 if (AOP_TYPE (left) == AOP_CRY &&
3514 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3520 gencjne (left, right, newiTempLabel (NULL));
3521 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3527 genIfxJump (ifx, "a");
3530 /* if the result is used in an arithmetic operation
3531 then put the result in place */
3532 if (AOP_TYPE (result) != AOP_CRY)
3536 /* leave the result in acc */
3540 freeAsmop (left, NULL, ic);
3541 freeAsmop (right, NULL, ic);
3542 freeAsmop (result, NULL, ic);
3545 /*-----------------------------------------------------------------*/
3546 /* ifxForOp - returns the icode containing the ifx for operand */
3547 /*-----------------------------------------------------------------*/
3549 ifxForOp (operand * op, iCode * ic)
3551 /* if true symbol then needs to be assigned */
3552 if (IS_TRUE_SYMOP (op))
3555 /* if this has register type condition and
3556 the next instruction is ifx with the same operand
3557 and live to of the operand is upto the ifx only then */
3559 ic->next->op == IFX &&
3560 IC_COND (ic->next)->key == op->key &&
3561 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3567 /*-----------------------------------------------------------------*/
3568 /* genAndOp - for && operation */
3569 /*-----------------------------------------------------------------*/
3571 genAndOp (iCode * ic)
3573 operand *left, *right, *result;
3576 /* note here that && operations that are in an if statement are
3577 taken away by backPatchLabels only those used in arthmetic
3578 operations remain */
3579 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3580 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3581 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3583 /* if both are bit variables */
3584 if (AOP_TYPE (left) == AOP_CRY &&
3585 AOP_TYPE (right) == AOP_CRY)
3591 tlbl = newiTempLabel (NULL);
3593 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3595 emitLabel (tlbl->key + 100);
3599 freeAsmop (left, NULL, ic);
3600 freeAsmop (right, NULL, ic);
3601 freeAsmop (result, NULL, ic);
3604 /*-----------------------------------------------------------------*/
3605 /* genOrOp - for || operation */
3606 /*-----------------------------------------------------------------*/
3608 genOrOp (iCode * ic)
3610 operand *left, *right, *result;
3613 /* note here that || operations that are in an
3614 if statement are taken away by backPatchLabels
3615 only those used in arthmetic operations remain */
3616 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3617 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3618 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3620 /* if both are bit variables */
3621 if (AOP_TYPE (left) == AOP_CRY &&
3622 AOP_TYPE (right) == AOP_CRY)
3628 tlbl = newiTempLabel (NULL);
3630 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3632 emitLabel (tlbl->key + 100);
3636 freeAsmop (left, NULL, ic);
3637 freeAsmop (right, NULL, ic);
3638 freeAsmop (result, NULL, ic);
3641 /*-----------------------------------------------------------------*/
3642 /* isLiteralBit - test if lit == 2^n */
3643 /*-----------------------------------------------------------------*/
3645 isLiteralBit (unsigned long lit)
3647 unsigned long pw[32] =
3648 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3649 0x100L, 0x200L, 0x400L, 0x800L,
3650 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3651 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3652 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3653 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3654 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3657 for (idx = 0; idx < 32; idx++)
3663 /*-----------------------------------------------------------------*/
3664 /* jmpTrueOrFalse - */
3665 /*-----------------------------------------------------------------*/
3667 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3669 // ugly but optimized by peephole
3672 symbol *nlbl = newiTempLabel (NULL);
3673 emit2 ("jp !tlabel", nlbl->key + 100);
3674 emitLabel (tlbl->key + 100);
3675 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3676 emitLabel (nlbl->key + 100);
3680 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3681 emitLabel (tlbl->key + 100);
3686 /*-----------------------------------------------------------------*/
3687 /* genAnd - code for and */
3688 /*-----------------------------------------------------------------*/
3690 genAnd (iCode * ic, iCode * ifx)
3692 operand *left, *right, *result;
3693 int size, offset = 0;
3694 unsigned long lit = 0L;
3697 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3698 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3699 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3702 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3704 AOP_TYPE (left), AOP_TYPE (right));
3705 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3707 AOP_SIZE (left), AOP_SIZE (right));
3710 /* if left is a literal & right is not then exchange them */
3711 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3712 AOP_NEEDSACC (left))
3714 operand *tmp = right;
3719 /* if result = right then exchange them */
3720 if (sameRegs (AOP (result), AOP (right)))
3722 operand *tmp = right;
3727 /* if right is bit then exchange them */
3728 if (AOP_TYPE (right) == AOP_CRY &&
3729 AOP_TYPE (left) != AOP_CRY)
3731 operand *tmp = right;
3735 if (AOP_TYPE (right) == AOP_LIT)
3736 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3738 size = AOP_SIZE (result);
3740 if (AOP_TYPE (left) == AOP_CRY)
3746 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3747 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3748 if ((AOP_TYPE (right) == AOP_LIT) &&
3749 (AOP_TYPE (result) == AOP_CRY) &&
3750 (AOP_TYPE (left) != AOP_CRY))
3752 int posbit = isLiteralBit (lit);
3757 _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
3762 emit2 ("mov c,acc.%d", posbit & 0x07);
3769 sprintf (buffer, "%d", posbit & 0x07);
3770 genIfxJump (ifx, buffer);
3781 symbol *tlbl = newiTempLabel (NULL);
3782 int sizel = AOP_SIZE (left);
3790 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3792 _moveA (aopGet (AOP (left), offset, FALSE));
3794 if ((posbit = isLiteralBit (bytelit)) != 0)
3797 emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3801 if (bytelit != 0x0FFL)
3803 aopGet (AOP (right), offset, FALSE));
3807 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3812 // bit = left & literal
3816 emit2 ("!tlabeldef", tlbl->key + 100);
3818 // if(left & literal)
3822 jmpTrueOrFalse (ifx, tlbl);
3830 /* if left is same as result */
3831 if (sameRegs (AOP (result), AOP (left)))
3833 for (; size--; offset++)
3835 if (AOP_TYPE (right) == AOP_LIT)
3837 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3842 aopPut (AOP (result), "!zero", offset);
3845 _moveA (aopGet (AOP (left), offset, FALSE));
3847 aopGet (AOP (right), offset, FALSE));
3848 aopPut (AOP (left), "a", offset);
3855 if (AOP_TYPE (left) == AOP_ACC)
3861 _moveA (aopGet (AOP (left), offset, FALSE));
3863 aopGet (AOP (right), offset, FALSE));
3864 aopPut (AOP (left), "a", offset);
3871 // left & result in different registers
3872 if (AOP_TYPE (result) == AOP_CRY)
3878 for (; (size--); offset++)
3881 // result = left & right
3882 if (AOP_TYPE (right) == AOP_LIT)
3884 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3886 aopPut (AOP (result),
3887 aopGet (AOP (left), offset, FALSE),
3891 else if (bytelit == 0)
3893 aopPut (AOP (result), "!zero", offset);
3897 // faster than result <- left, anl result,right
3898 // and better if result is SFR
3899 if (AOP_TYPE (left) == AOP_ACC)
3900 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
3903 _moveA (aopGet (AOP (left), offset, FALSE));
3905 aopGet (AOP (right), offset, FALSE));
3907 aopPut (AOP (result), "a", offset);
3914 freeAsmop (left, NULL, ic);
3915 freeAsmop (right, NULL, ic);
3916 freeAsmop (result, NULL, ic);
3919 /*-----------------------------------------------------------------*/
3920 /* genOr - code for or */
3921 /*-----------------------------------------------------------------*/
3923 genOr (iCode * ic, iCode * ifx)
3925 operand *left, *right, *result;
3926 int size, offset = 0;
3927 unsigned long lit = 0L;
3929 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3930 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3931 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3934 emit2 ("; Type res[%d] = l[%d]&r[%d]",
3936 AOP_TYPE (left), AOP_TYPE (right));
3937 emit2 ("; Size res[%d] = l[%d]&r[%d]",
3939 AOP_SIZE (left), AOP_SIZE (right));
3942 /* if left is a literal & right is not then exchange them */
3943 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3944 AOP_NEEDSACC (left))
3946 operand *tmp = right;
3951 /* if result = right then exchange them */
3952 if (sameRegs (AOP (result), AOP (right)))
3954 operand *tmp = right;
3959 /* if right is bit then exchange them */
3960 if (AOP_TYPE (right) == AOP_CRY &&
3961 AOP_TYPE (left) != AOP_CRY)
3963 operand *tmp = right;
3967 if (AOP_TYPE (right) == AOP_LIT)
3968 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3970 size = AOP_SIZE (result);
3972 if (AOP_TYPE (left) == AOP_CRY)
3978 if ((AOP_TYPE (right) == AOP_LIT) &&
3979 (AOP_TYPE (result) == AOP_CRY) &&
3980 (AOP_TYPE (left) != AOP_CRY))
3986 /* if left is same as result */
3987 if (sameRegs (AOP (result), AOP (left)))
3989 for (; size--; offset++)
3991 if (AOP_TYPE (right) == AOP_LIT)
3993 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3997 _moveA (aopGet (AOP (left), offset, FALSE));
3999 aopGet (AOP (right), offset, FALSE));
4000 aopPut (AOP (result), "a", offset);
4005 if (AOP_TYPE (left) == AOP_ACC)
4006 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4009 _moveA (aopGet (AOP (left), offset, FALSE));
4011 aopGet (AOP (right), offset, FALSE));
4012 aopPut (AOP (result), "a", offset);
4019 // left & result in different registers
4020 if (AOP_TYPE (result) == AOP_CRY)
4025 for (; (size--); offset++)
4028 // result = left & right
4029 if (AOP_TYPE (right) == AOP_LIT)
4031 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4033 aopPut (AOP (result),
4034 aopGet (AOP (left), offset, FALSE),
4039 // faster than result <- left, anl result,right
4040 // and better if result is SFR
4041 if (AOP_TYPE (left) == AOP_ACC)
4042 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4045 _moveA (aopGet (AOP (left), offset, FALSE));
4047 aopGet (AOP (right), offset, FALSE));
4049 aopPut (AOP (result), "a", offset);
4050 /* PENDING: something weird is going on here. Add exception. */
4051 if (AOP_TYPE (result) == AOP_ACC)
4057 freeAsmop (left, NULL, ic);
4058 freeAsmop (right, NULL, ic);
4059 freeAsmop (result, NULL, ic);
4062 /*-----------------------------------------------------------------*/
4063 /* genXor - code for xclusive or */
4064 /*-----------------------------------------------------------------*/
4066 genXor (iCode * ic, iCode * ifx)
4068 operand *left, *right, *result;
4069 int size, offset = 0;
4070 unsigned long lit = 0L;
4072 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4073 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4074 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4076 /* if left is a literal & right is not then exchange them */
4077 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4078 AOP_NEEDSACC (left))
4080 operand *tmp = right;
4085 /* if result = right then exchange them */
4086 if (sameRegs (AOP (result), AOP (right)))
4088 operand *tmp = right;
4093 /* if right is bit then exchange them */
4094 if (AOP_TYPE (right) == AOP_CRY &&
4095 AOP_TYPE (left) != AOP_CRY)
4097 operand *tmp = right;
4101 if (AOP_TYPE (right) == AOP_LIT)
4102 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4104 size = AOP_SIZE (result);
4106 if (AOP_TYPE (left) == AOP_CRY)
4112 if ((AOP_TYPE (right) == AOP_LIT) &&
4113 (AOP_TYPE (result) == AOP_CRY) &&
4114 (AOP_TYPE (left) != AOP_CRY))
4120 /* if left is same as result */
4121 if (sameRegs (AOP (result), AOP (left)))
4123 for (; size--; offset++)
4125 if (AOP_TYPE (right) == AOP_LIT)
4127 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4131 _moveA (aopGet (AOP (right), offset, FALSE));
4133 aopGet (AOP (left), offset, FALSE));
4134 aopPut (AOP (result), "a", 0);
4139 if (AOP_TYPE (left) == AOP_ACC)
4140 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4143 _moveA (aopGet (AOP (right), offset, FALSE));
4145 aopGet (AOP (left), offset, FALSE));
4146 aopPut (AOP (result), "a", 0);
4153 // left & result in different registers
4154 if (AOP_TYPE (result) == AOP_CRY)
4159 for (; (size--); offset++)
4162 // result = left & right
4163 if (AOP_TYPE (right) == AOP_LIT)
4165 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4167 aopPut (AOP (result),
4168 aopGet (AOP (left), offset, FALSE),
4173 // faster than result <- left, anl result,right
4174 // and better if result is SFR
4175 if (AOP_TYPE (left) == AOP_ACC)
4176 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4179 _moveA (aopGet (AOP (right), offset, FALSE));
4181 aopGet (AOP (left), offset, FALSE));
4182 aopPut (AOP (result), "a", 0);
4184 aopPut (AOP (result), "a", offset);
4189 freeAsmop (left, NULL, ic);
4190 freeAsmop (right, NULL, ic);
4191 freeAsmop (result, NULL, ic);
4194 /*-----------------------------------------------------------------*/
4195 /* genInline - write the inline code out */
4196 /*-----------------------------------------------------------------*/
4198 genInline (iCode * ic)
4200 char *buffer, *bp, *bp1;
4202 _G.lines.isInline += (!options.asmpeep);
4204 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4205 strcpy (buffer, IC_INLINE (ic));
4207 /* emit each line as a code */
4232 _G.lines.isInline -= (!options.asmpeep);
4236 /*-----------------------------------------------------------------*/
4237 /* genRRC - rotate right with carry */
4238 /*-----------------------------------------------------------------*/
4245 /*-----------------------------------------------------------------*/
4246 /* genRLC - generate code for rotate left with carry */
4247 /*-----------------------------------------------------------------*/
4254 /*-----------------------------------------------------------------*/
4255 /* shiftR2Left2Result - shift right two bytes from left to result */
4256 /*-----------------------------------------------------------------*/
4258 shiftR2Left2Result (operand * left, int offl,
4259 operand * result, int offr,
4260 int shCount, int sign)
4262 movLeft2Result (left, offl, result, offr, 0);
4263 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4271 /* if (AOP(result)->type == AOP_REG) { */
4274 symbol *tlbl, *tlbl1;
4277 tlbl = newiTempLabel (NULL);
4278 tlbl1 = newiTempLabel (NULL);
4280 /* Left is already in result - so now do the shift */
4283 emit2 ("ld a,!immedbyte+1", shCount);
4284 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4285 emitLabel (tlbl->key + 100);
4292 l = aopGet (AOP (result), --offset, FALSE);
4297 emitLabel (tlbl1->key + 100);
4299 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4304 /*-----------------------------------------------------------------*/
4305 /* shiftL2Left2Result - shift left two bytes from left to result */
4306 /*-----------------------------------------------------------------*/
4308 shiftL2Left2Result (operand * left, int offl,
4309 operand * result, int offr, int shCount)
4311 if (sameRegs (AOP (result), AOP (left)) &&
4312 ((offl + MSB16) == offr))
4318 /* Copy left into result */
4319 movLeft2Result (left, offl, result, offr, 0);
4320 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4322 /* PENDING: for now just see if it'll work. */
4323 /*if (AOP(result)->type == AOP_REG) { */
4327 symbol *tlbl, *tlbl1;
4330 tlbl = newiTempLabel (NULL);
4331 tlbl1 = newiTempLabel (NULL);
4333 /* Left is already in result - so now do the shift */
4336 emit2 ("ld a,!immedbyte+1", shCount);
4337 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4338 emitLabel (tlbl->key + 100);
4344 l = aopGet (AOP (result), offset++, FALSE);
4349 emitLabel (tlbl1->key + 100);
4351 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4356 /*-----------------------------------------------------------------*/
4357 /* AccRol - rotate left accumulator by known count */
4358 /*-----------------------------------------------------------------*/
4360 AccRol (int shCount)
4362 shCount &= 0x0007; // shCount : 0..7
4401 /*-----------------------------------------------------------------*/
4402 /* AccLsh - left shift accumulator by known count */
4403 /*-----------------------------------------------------------------*/
4405 AccLsh (int shCount)
4407 static const unsigned char SLMask[] =
4409 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4418 else if (shCount == 2)
4425 /* rotate left accumulator */
4427 /* and kill the lower order bits */
4428 emit2 ("and a,!immedbyte", SLMask[shCount]);
4433 /*-----------------------------------------------------------------*/
4434 /* shiftL1Left2Result - shift left one byte from left to result */
4435 /*-----------------------------------------------------------------*/
4437 shiftL1Left2Result (operand * left, int offl,
4438 operand * result, int offr, int shCount)
4441 l = aopGet (AOP (left), offl, FALSE);
4443 /* shift left accumulator */
4445 aopPut (AOP (result), "a", offr);
4449 /*-----------------------------------------------------------------*/
4450 /* genlshTwo - left shift two bytes by known amount != 0 */
4451 /*-----------------------------------------------------------------*/
4453 genlshTwo (operand * result, operand * left, int shCount)
4455 int size = AOP_SIZE (result);
4457 wassert (size == 2);
4459 /* if shCount >= 8 */
4467 movLeft2Result (left, LSB, result, MSB16, 0);
4468 aopPut (AOP (result), "!zero", 0);
4469 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4473 movLeft2Result (left, LSB, result, MSB16, 0);
4474 aopPut (AOP (result), "!zero", 0);
4479 aopPut (AOP (result), "!zero", LSB);
4482 /* 1 <= shCount <= 7 */
4491 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4496 /*-----------------------------------------------------------------*/
4497 /* genlshOne - left shift a one byte quantity by known count */
4498 /*-----------------------------------------------------------------*/
4500 genlshOne (operand * result, operand * left, int shCount)
4502 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4505 /*-----------------------------------------------------------------*/
4506 /* genLeftShiftLiteral - left shifting by known count */
4507 /*-----------------------------------------------------------------*/
4509 genLeftShiftLiteral (operand * left,
4514 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4517 freeAsmop (right, NULL, ic);
4519 aopOp (left, ic, FALSE, FALSE);
4520 aopOp (result, ic, FALSE, FALSE);
4522 size = getSize (operandType (result));
4525 emit2 ("; shift left result %d, left %d", size,
4529 /* I suppose that the left size >= result size */
4535 else if (shCount >= (size * 8))
4537 aopPut (AOP (result), "!zero", size);
4543 genlshOne (result, left, shCount);
4546 genlshTwo (result, left, shCount);
4555 freeAsmop (left, NULL, ic);
4556 freeAsmop (result, NULL, ic);
4559 /*-----------------------------------------------------------------*/
4560 /* genLeftShift - generates code for left shifting */
4561 /*-----------------------------------------------------------------*/
4563 genLeftShift (iCode * ic)
4567 symbol *tlbl, *tlbl1;
4568 operand *left, *right, *result;
4570 right = IC_RIGHT (ic);
4571 left = IC_LEFT (ic);
4572 result = IC_RESULT (ic);
4574 aopOp (right, ic, FALSE, FALSE);
4576 /* if the shift count is known then do it
4577 as efficiently as possible */
4578 if (AOP_TYPE (right) == AOP_LIT)
4580 genLeftShiftLiteral (left, right, result, ic);
4584 /* shift count is unknown then we have to form a loop get the loop
4585 count in B : Note: we take only the lower order byte since
4586 shifting more that 32 bits make no sense anyway, ( the largest
4587 size of an object can be only 32 bits ) */
4588 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4590 freeAsmop (right, NULL, ic);
4591 aopOp (left, ic, FALSE, FALSE);
4592 aopOp (result, ic, FALSE, FALSE);
4594 /* now move the left to the result if they are not the
4597 if (!sameRegs (AOP (left), AOP (result)))
4600 size = AOP_SIZE (result);
4604 l = aopGet (AOP (left), offset, FALSE);
4605 aopPut (AOP (result), l, offset);
4610 size = AOP_SIZE (result);
4614 l = aopGet (AOP (left), offset, FALSE);
4615 aopPut (AOP (result), l, offset);
4621 tlbl = newiTempLabel (NULL);
4622 size = AOP_SIZE (result);
4624 tlbl1 = newiTempLabel (NULL);
4626 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4627 emitLabel (tlbl->key + 100);
4628 l = aopGet (AOP (result), offset, FALSE);
4632 l = aopGet (AOP (result), offset++, FALSE);
4635 emitLabel (tlbl1->key + 100);
4637 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4639 freeAsmop (left, NULL, ic);
4640 freeAsmop (result, NULL, ic);
4643 /*-----------------------------------------------------------------*/
4644 /* genrshOne - left shift two bytes by known amount != 0 */
4645 /*-----------------------------------------------------------------*/
4647 genrshOne (operand * result, operand * left, int shCount)
4650 int size = AOP_SIZE (result);
4653 wassert (size == 1);
4654 wassert (shCount < 8);
4656 l = aopGet (AOP (left), 0, FALSE);
4657 if (AOP (result)->type == AOP_REG)
4659 aopPut (AOP (result), l, 0);
4660 l = aopGet (AOP (result), 0, FALSE);
4662 emit2 ("srl %s", l);
4671 aopPut (AOP (result), "a", 0);
4675 /*-----------------------------------------------------------------*/
4676 /* AccRsh - right shift accumulator by known count */
4677 /*-----------------------------------------------------------------*/
4679 AccRsh (int shCount)
4681 static const unsigned char SRMask[] =
4683 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
4688 /* rotate right accumulator */
4689 AccRol (8 - shCount);
4690 /* and kill the higher order bits */
4691 emit2 ("and a,!immedbyte", SRMask[shCount]);
4695 /*-----------------------------------------------------------------*/
4696 /* shiftR1Left2Result - shift right one byte from left to result */
4697 /*-----------------------------------------------------------------*/
4699 shiftR1Left2Result (operand * left, int offl,
4700 operand * result, int offr,
4701 int shCount, int sign)
4703 _moveA (aopGet (AOP (left), offl, FALSE));
4712 aopPut (AOP (result), "a", offr);
4715 /*-----------------------------------------------------------------*/
4716 /* genrshTwo - right shift two bytes by known amount != 0 */
4717 /*-----------------------------------------------------------------*/
4719 genrshTwo (operand * result, operand * left,
4720 int shCount, int sign)
4722 /* if shCount >= 8 */
4728 shiftR1Left2Result (left, MSB16, result, LSB,
4733 movLeft2Result (left, MSB16, result, LSB, sign);
4735 aopPut (AOP (result), "!zero", 1);
4737 /* 1 <= shCount <= 7 */
4740 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4744 /*-----------------------------------------------------------------*/
4745 /* genRightShiftLiteral - left shifting by known count */
4746 /*-----------------------------------------------------------------*/
4748 genRightShiftLiteral (operand * left,
4753 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4756 freeAsmop (right, NULL, ic);
4758 aopOp (left, ic, FALSE, FALSE);
4759 aopOp (result, ic, FALSE, FALSE);
4761 size = getSize (operandType (result));
4763 emit2 ("; shift right result %d, left %d", size,
4766 /* I suppose that the left size >= result size */
4772 else if (shCount >= (size * 8))
4774 aopPut (AOP (result), "!zero", size);
4780 genrshOne (result, left, shCount);
4783 /* PENDING: sign support */
4784 genrshTwo (result, left, shCount, FALSE);
4793 freeAsmop (left, NULL, ic);
4794 freeAsmop (result, NULL, ic);
4797 /*-----------------------------------------------------------------*/
4798 /* genRightShift - generate code for right shifting */
4799 /*-----------------------------------------------------------------*/
4801 genRightShift (iCode * ic)
4803 operand *right, *left, *result;
4805 int size, offset, first = 1;
4809 symbol *tlbl, *tlbl1;
4811 /* if signed then we do it the hard way preserve the
4812 sign bit moving it inwards */
4813 retype = getSpec (operandType (IC_RESULT (ic)));
4815 is_signed = !SPEC_USIGN (retype);
4817 /* signed & unsigned types are treated the same : i.e. the
4818 signed is NOT propagated inwards : quoting from the
4819 ANSI - standard : "for E1 >> E2, is equivalent to division
4820 by 2**E2 if unsigned or if it has a non-negative value,
4821 otherwise the result is implementation defined ", MY definition
4822 is that the sign does not get propagated */
4824 right = IC_RIGHT (ic);
4825 left = IC_LEFT (ic);
4826 result = IC_RESULT (ic);
4828 aopOp (right, ic, FALSE, FALSE);
4830 /* if the shift count is known then do it
4831 as efficiently as possible */
4832 if (AOP_TYPE (right) == AOP_LIT)
4834 genRightShiftLiteral (left, right, result, ic);
4838 aopOp (left, ic, FALSE, FALSE);
4839 aopOp (result, ic, FALSE, FALSE);
4841 /* now move the left to the result if they are not the
4843 if (!sameRegs (AOP (left), AOP (result)) &&
4844 AOP_SIZE (result) > 1)
4847 size = AOP_SIZE (result);
4851 l = aopGet (AOP (left), offset, FALSE);
4852 aopPut (AOP (result), l, offset);
4857 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
4859 freeAsmop (right, NULL, ic);
4861 tlbl = newiTempLabel (NULL);
4862 tlbl1 = newiTempLabel (NULL);
4863 size = AOP_SIZE (result);
4866 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4867 emitLabel (tlbl->key + 100);
4870 l = aopGet (AOP (result), offset--, FALSE);
4874 emit2 ("sra %s", l);
4876 emit2 ("srl %s", l);
4882 emitLabel (tlbl1->key + 100);
4884 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4886 freeAsmop (left, NULL, ic);
4887 freeAsmop (result, NULL, ic);
4890 /*-----------------------------------------------------------------*/
4891 /* genGenPointerGet - get value from generic pointer space */
4892 /*-----------------------------------------------------------------*/
4894 genGenPointerGet (operand * left,
4895 operand * result, iCode * ic)
4898 sym_link *retype = getSpec (operandType (result));
4904 aopOp (left, ic, FALSE, FALSE);
4905 aopOp (result, ic, FALSE, FALSE);
4907 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4910 if (isPtrPair (AOP (left)))
4912 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4913 aopPut (AOP (result), buffer, 0);
4917 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4918 aopPut (AOP (result), "a", 0);
4920 freeAsmop (left, NULL, ic);
4924 /* For now we always load into IY */
4925 /* if this is remateriazable */
4926 fetchPair (pair, AOP (left));
4928 /* so iy now contains the address */
4929 freeAsmop (left, NULL, ic);
4931 /* if bit then unpack */
4932 if (IS_BITVAR (retype))
4938 size = AOP_SIZE (result);
4943 /* PENDING: make this better */
4944 if (!IS_GB && AOP (result)->type == AOP_REG)
4946 aopPut (AOP (result), "!*hl", offset++);
4950 emit2 ("ld a,!*pair", _pairs[pair].name);
4951 aopPut (AOP (result), "a", offset++);
4955 emit2 ("inc %s", _pairs[pair].name);
4956 _G.pairs[pair].offset++;
4962 freeAsmop (result, NULL, ic);
4965 /*-----------------------------------------------------------------*/
4966 /* genPointerGet - generate code for pointer get */
4967 /*-----------------------------------------------------------------*/
4969 genPointerGet (iCode * ic)
4971 operand *left, *result;
4972 sym_link *type, *etype;
4974 left = IC_LEFT (ic);
4975 result = IC_RESULT (ic);
4977 /* depending on the type of pointer we need to
4978 move it to the correct pointer register */
4979 type = operandType (left);
4980 etype = getSpec (type);
4982 genGenPointerGet (left, result, ic);
4986 isRegOrLit (asmop * aop)
4988 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4993 /*-----------------------------------------------------------------*/
4994 /* genGenPointerSet - stores the value into a pointer location */
4995 /*-----------------------------------------------------------------*/
4997 genGenPointerSet (operand * right,
4998 operand * result, iCode * ic)
5001 sym_link *retype = getSpec (operandType (right));
5002 PAIR_ID pairId = PAIR_HL;
5004 aopOp (result, ic, FALSE, FALSE);
5005 aopOp (right, ic, FALSE, FALSE);
5010 /* Handle the exceptions first */
5011 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5014 const char *l = aopGet (AOP (right), 0, FALSE);
5015 const char *pair = getPairName (AOP (result));
5016 if (canAssignToPtr (l) && isPtr (pair))
5018 emit2 ("ld !*pair,%s", pair, l);
5023 emit2 ("ld !*pair,a", pair);
5028 /* if the operand is already in dptr
5029 then we do nothing else we move the value to dptr */
5030 if (AOP_TYPE (result) != AOP_STR)
5032 fetchPair (pairId, AOP (result));
5034 /* so hl know contains the address */
5035 freeAsmop (result, NULL, ic);
5037 /* if bit then unpack */
5038 if (IS_BITVAR (retype))
5044 size = AOP_SIZE (right);
5049 const char *l = aopGet (AOP (right), offset, FALSE);
5050 if (isRegOrLit (AOP (right)) && !IS_GB)
5052 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5057 emit2 ("ld !*pair,a", _pairs[pairId].name);
5061 emit2 ("inc %s", _pairs[pairId].name);
5062 _G.pairs[pairId].offset++;
5068 freeAsmop (right, NULL, ic);
5071 /*-----------------------------------------------------------------*/
5072 /* genPointerSet - stores the value into a pointer location */
5073 /*-----------------------------------------------------------------*/
5075 genPointerSet (iCode * ic)
5077 operand *right, *result;
5078 sym_link *type, *etype;
5080 right = IC_RIGHT (ic);
5081 result = IC_RESULT (ic);
5083 /* depending on the type of pointer we need to
5084 move it to the correct pointer register */
5085 type = operandType (result);
5086 etype = getSpec (type);
5088 genGenPointerSet (right, result, ic);
5091 /*-----------------------------------------------------------------*/
5092 /* genIfx - generate code for Ifx statement */
5093 /*-----------------------------------------------------------------*/
5095 genIfx (iCode * ic, iCode * popIc)
5097 operand *cond = IC_COND (ic);
5100 aopOp (cond, ic, FALSE, TRUE);
5102 /* get the value into acc */
5103 if (AOP_TYPE (cond) != AOP_CRY)
5107 /* the result is now in the accumulator */
5108 freeAsmop (cond, NULL, ic);
5110 /* if there was something to be popped then do it */
5114 /* if the condition is a bit variable */
5115 if (isbit && IS_ITEMP (cond) &&
5117 genIfxJump (ic, SPIL_LOC (cond)->rname);
5118 else if (isbit && !IS_ITEMP (cond))
5119 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5121 genIfxJump (ic, "a");
5126 /*-----------------------------------------------------------------*/
5127 /* genAddrOf - generates code for address of */
5128 /*-----------------------------------------------------------------*/
5130 genAddrOf (iCode * ic)
5132 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5134 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5136 /* if the operand is on the stack then we
5137 need to get the stack offset of this
5144 if (sym->stack <= 0)
5146 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5150 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5157 emit2 ("ld de,!hashedstr", sym->rname);
5159 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5160 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5167 /* if it has an offset then we need to compute it */
5169 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5171 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5172 emit2 ("add hl,sp");
5176 emit2 ("ld hl,#%s", sym->rname);
5178 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5179 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5181 freeAsmop (IC_RESULT (ic), NULL, ic);
5184 /*-----------------------------------------------------------------*/
5185 /* genAssign - generate code for assignment */
5186 /*-----------------------------------------------------------------*/
5188 genAssign (iCode * ic)
5190 operand *result, *right;
5192 unsigned long lit = 0L;
5194 result = IC_RESULT (ic);
5195 right = IC_RIGHT (ic);
5198 /* Dont bother assigning if they are the same */
5199 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5201 emit2 ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5206 aopOp (right, ic, FALSE, FALSE);
5207 aopOp (result, ic, TRUE, FALSE);
5209 /* if they are the same registers */
5210 if (sameRegs (AOP (right), AOP (result)))
5212 emit2 ("; (registers are the same)");
5216 /* if the result is a bit */
5217 if (AOP_TYPE (result) == AOP_CRY)
5223 size = AOP_SIZE (result);
5226 if (AOP_TYPE (right) == AOP_LIT)
5227 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5228 if (isPair (AOP (result)))
5230 fetchPair (getPairId (AOP (result)), AOP (right));
5232 else if ((size > 1) &&
5233 (AOP_TYPE (result) != AOP_REG) &&
5234 (AOP_TYPE (right) == AOP_LIT) &&
5235 !IS_FLOAT (operandType (right)) &&
5238 bool fXored = FALSE;
5240 /* Work from the top down.
5241 Done this way so that we can use the cached copy of 0
5242 in A for a fast clear */
5245 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5247 if (!fXored && size > 1)
5254 aopPut (AOP (result), "a", offset);
5258 aopPut (AOP (result), "!zero", offset);
5262 aopPut (AOP (result),
5263 aopGet (AOP (right), offset, FALSE),
5268 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5270 /* Special case. Load into a and d, then load out. */
5271 _moveA (aopGet (AOP (right), 0, FALSE));
5272 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5273 aopPut (AOP (result), "a", 0);
5274 aopPut (AOP (result), "e", 1);
5280 /* PENDING: do this check better */
5281 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5283 _moveA (aopGet (AOP (right), offset, FALSE));
5284 aopPut (AOP (result), "a", offset);
5287 aopPut (AOP (result),
5288 aopGet (AOP (right), offset, FALSE),
5295 freeAsmop (right, NULL, ic);
5296 freeAsmop (result, NULL, ic);
5299 /*-----------------------------------------------------------------*/
5300 /* genJumpTab - genrates code for jump table */
5301 /*-----------------------------------------------------------------*/
5303 genJumpTab (iCode * ic)
5308 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5309 /* get the condition into accumulator */
5310 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5313 emit2 ("ld e,%s", l);
5314 emit2 ("ld d,!zero");
5315 jtab = newiTempLabel (NULL);
5317 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5318 emit2 ("add hl,de");
5319 emit2 ("add hl,de");
5320 emit2 ("add hl,de");
5321 freeAsmop (IC_JTCOND (ic), NULL, ic);
5325 emitLabel (jtab->key + 100);
5326 /* now generate the jump labels */
5327 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5328 jtab = setNextItem (IC_JTLABELS (ic)))
5329 emit2 ("jp !tlabel", jtab->key + 100);
5332 /*-----------------------------------------------------------------*/
5333 /* genCast - gen code for casting */
5334 /*-----------------------------------------------------------------*/
5336 genCast (iCode * ic)
5338 operand *result = IC_RESULT (ic);
5339 sym_link *ctype = operandType (IC_LEFT (ic));
5340 operand *right = IC_RIGHT (ic);
5343 /* if they are equivalent then do nothing */
5344 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5347 aopOp (right, ic, FALSE, FALSE);
5348 aopOp (result, ic, FALSE, FALSE);
5350 /* if the result is a bit */
5351 if (AOP_TYPE (result) == AOP_CRY)
5356 /* if they are the same size : or less */
5357 if (AOP_SIZE (result) <= AOP_SIZE (right))
5360 /* if they are in the same place */
5361 if (sameRegs (AOP (right), AOP (result)))
5364 /* if they in different places then copy */
5365 size = AOP_SIZE (result);
5369 aopPut (AOP (result),
5370 aopGet (AOP (right), offset, FALSE),
5377 /* PENDING: should be OK. */
5379 /* if the result is of type pointer */
5386 /* so we now know that the size of destination is greater
5387 than the size of the source */
5388 /* we move to result for the size of source */
5389 size = AOP_SIZE (right);
5393 aopPut (AOP (result),
5394 aopGet (AOP (right), offset, FALSE),
5399 /* now depending on the sign of the destination */
5400 size = AOP_SIZE (result) - AOP_SIZE (right);
5401 /* Unsigned or not an integral type - right fill with zeros */
5402 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5405 aopPut (AOP (result), "!zero", offset++);
5409 /* we need to extend the sign :{ */
5410 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5413 emit2 ("; genCast: sign extend untested.");
5417 aopPut (AOP (result), "a", offset++);
5421 freeAsmop (right, NULL, ic);
5422 freeAsmop (result, NULL, ic);
5425 /*-----------------------------------------------------------------*/
5426 /* genReceive - generate code for a receive iCode */
5427 /*-----------------------------------------------------------------*/
5429 genReceive (iCode * ic)
5431 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5432 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5433 IS_TRUE_SYMOP (IC_RESULT (ic))))
5443 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5444 size = AOP_SIZE(IC_RESULT(ic));
5446 for (i = 0; i < size; i++) {
5447 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
5451 freeAsmop (IC_RESULT (ic), NULL, ic);
5454 /*-----------------------------------------------------------------*/
5455 /* genZ80Code - generate code for Z80 based controllers */
5456 /*-----------------------------------------------------------------*/
5458 genZ80Code (iCode * lic)
5466 _fReturn = _gbz80_return;
5467 _fTmp = _gbz80_return;
5471 _fReturn = _z80_return;
5472 _fTmp = _z80_return;
5475 _G.lines.head = _G.lines.current = NULL;
5477 for (ic = lic; ic; ic = ic->next)
5480 if (cln != ic->lineno)
5482 emit2 ("; %s %d", ic->filename, ic->lineno);
5485 /* if the result is marked as
5486 spilt and rematerializable or code for
5487 this has already been generated then
5489 if (resultRemat (ic) || ic->generated)
5492 /* depending on the operation */
5506 emit2 ("; genUminus");
5511 emit2 ("; genIpush");
5516 /* IPOP happens only when trying to restore a
5517 spilt live range, if there is an ifx statement
5518 following this pop then the if statement might
5519 be using some of the registers being popped which
5520 would destory the contents of the register so
5521 we need to check for this condition and handle it */
5523 ic->next->op == IFX &&
5524 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5527 genIfx (ic->next, ic);
5531 emit2 ("; genIpop");
5537 emit2 ("; genCall");
5542 emit2 ("; genPcall");
5547 emit2 ("; genFunction");
5552 emit2 ("; genEndFunction");
5553 genEndFunction (ic);
5562 emit2 ("; genLabel");
5567 emit2 ("; genGoto");
5572 emit2 ("; genPlus");
5577 emit2 ("; genMinus");
5582 emit2 ("; genMult");
5597 emit2 ("; genCmpGt");
5598 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5602 emit2 ("; genCmpLt");
5603 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5610 /* note these two are xlated by algebraic equivalence
5611 during parsing SDCC.y */
5612 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5613 "got '>=' or '<=' shouldn't have come here");
5617 emit2 ("; genCmpEq");
5618 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5622 emit2 ("; genAndOp");
5627 emit2 ("; genOrOp");
5633 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5638 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5643 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5647 emit2 ("; genInline");
5662 emit2 ("; genHBIT");
5666 emit2 ("; genLeftShift");
5671 emit2 ("; genRightShift");
5675 case GET_VALUE_AT_ADDRESS:
5676 emit2 ("; genPointerGet");
5682 if (POINTER_SET (ic))
5684 emit2 ("; genAssign (pointer)");
5689 emit2 ("; genAssign");
5700 emit2 ("; genAddrOf");
5705 emit2 ("; genJumpTab");
5710 emit2 ("; genCast");
5715 emit2 ("; genReceive");
5721 addSet (&_G.sendSet, ic);
5726 /* piCode(ic,stdout); */
5732 /* now we are ready to call the
5733 peep hole optimizer */
5734 if (!options.nopeep)
5735 peepHole (&_G.lines.head);
5737 /* This is unfortunate */
5738 /* now do the actual printing */
5740 FILE *fp = codeOutFile;
5741 if (isInHome () && codeOutFile == code->oFile)
5742 codeOutFile = home->oFile;
5743 printLine (_G.lines.head, codeOutFile);
5744 if (_G.flushStatics)
5747 _G.flushStatics = 0;
5756 _isPairUsed (iCode * ic, PAIR_ID pairId)
5762 if (bitVectBitValue (ic->rMask, D_IDX))
5764 if (bitVectBitValue (ic->rMask, E_IDX))