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 **_fReturn;
100 extern FILE *codeOutFile;
120 } _pairs[NUM_PAIRS] = {
126 { "iy", "iy.l?", "iy.h?" },
127 { "ix", "ix.l?", "ix.h?" }
131 #define ACC_NAME _pairs[PAIR_AF].h
133 #define RESULTONSTACK(x) \
134 (IC_RESULT(x) && IC_RESULT(x)->aop && \
135 IC_RESULT(x)->aop->type == AOP_STK )
137 lineNode *lineHead = NULL;
138 lineNode *lineCurr = NULL;
140 static const unsigned char SLMask[] =
141 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
142 static const unsigned char SRMask[] =
143 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
176 const char *lastFunctionName;
180 static const char *aopGet (asmop * aop, int offset, bool bit16);
185 /* Clean up the line so that it is 'prettier' */
186 if (strchr (buf, ':'))
188 /* Is a label - cant do anything */
191 /* Change the first (and probably only) ' ' to a tab so
206 emit2 (const char *szFormat,...)
211 va_start (ap, szFormat);
213 tvsprintf (buffer, szFormat, ap);
216 lineCurr = (lineCurr ?
217 connectLine (lineCurr, newLineNode (buffer)) :
218 (lineHead = newLineNode (buffer)));
220 lineCurr->isInline = inLine;
221 lineCurr->isDebug = debugLine;
224 /*-----------------------------------------------------------------*/
225 /* emitcode - writes the code into a file : for now it is simple */
226 /*-----------------------------------------------------------------*/
228 emitcode (const char *inst, const char *fmt,...)
231 char lb[INITIAL_INLINEASM];
238 sprintf (lb, "%s\t", inst);
239 vsprintf (lb + (strlen (lb)), fmt, ap);
242 vsprintf (lb, fmt, ap);
244 while (isspace (*lbp))
248 lineCurr = (lineCurr ?
249 connectLine (lineCurr, newLineNode (lb)) :
250 (lineHead = newLineNode (lb)));
251 lineCurr->isInline = inLine;
252 lineCurr->isDebug = debugLine;
257 _emitMove(const char *to, const char *from)
259 if (strcasecmp(to, from) != 0) {
260 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 emitcode ("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 emitcode ("", "; 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 emitcode ("", "; AOP_SFR for %s", sym->rname);
451 /* only remaining is far space */
452 /* in which case DPTR gets the address */
455 emitcode ("", "; 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);
693 if (sym->accuse == ACCUSE_A)
695 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
696 aop->size = getSize (sym->type);
697 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
699 aop->aopu.aop_str[i] = _pairs[PAIR_AF].h;
701 else if (sym->accuse == ACCUSE_HL)
704 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
705 aop->size = getSize (sym->type);
706 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
707 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
708 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
720 aop = op->aop = sym->aop = newAsmop (AOP_STR);
721 aop->size = getSize (sym->type);
722 for (i = 0; i < 4; i++)
723 aop->aopu.aop_str[i] = _fReturn[i];
727 /* else spill location */
728 sym->aop = op->aop = aop =
729 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
730 aop->size = getSize (sym->type);
734 /* must be in a register */
735 sym->aop = op->aop = aop = newAsmop (AOP_REG);
736 aop->size = sym->nRegs;
737 for (i = 0; i < sym->nRegs; i++)
738 aop->aopu.aop_reg[i] = sym->regs[i];
741 /*-----------------------------------------------------------------*/
742 /* freeAsmop - free up the asmop given to an operand */
743 /*----------------------------------------------------------------*/
745 freeAsmop (operand * op, asmop * aaop, iCode * ic)
763 /* all other cases just dealloc */
769 OP_SYMBOL (op)->aop = NULL;
770 /* if the symbol has a spill */
772 SPIL_LOC (op)->aop = NULL;
778 isLitWord (asmop * aop)
780 /* if (aop->size != 2)
793 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
799 if (aop->size != 2 && aop->type != AOP_HL)
802 /* depending on type */
808 /* PENDING: for re-target */
810 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
812 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
813 rs = Safe_calloc (1, strlen (s) + 1);
818 value *val = aop->aopu.aop_lit;
819 /* if it is a float then it gets tricky */
820 /* otherwise it is fairly simple */
821 if (!IS_FLOAT (val->type))
823 unsigned long v = (unsigned long) floatFromVal (val);
829 tsprintf (buffer, "!immedword", v);
831 tsprintf (buffer, "!constword", v);
832 rs = Safe_calloc (1, strlen (buffer) + 1);
833 return strcpy (rs, buffer);
839 convertFloat (&f, floatFromVal (val));
841 tsprintf (buffer, "!immedword", f.w[offset / 2]);
843 tsprintf (buffer, "!constword", f.w[offset / 2]);
844 rs = Safe_calloc (1, strlen (buffer) + 1);
845 return strcpy (rs, buffer);
854 aopGetWord (asmop * aop, int offset)
856 return aopGetLitWordLong (aop, offset, TRUE);
860 isPtr (const char *s)
862 if (!strcmp (s, "hl"))
864 if (!strcmp (s, "ix"))
866 if (!strcmp (s, "iy"))
872 adjustPair (const char *pair, int *pold, int new)
878 emitcode ("inc", "%s", pair);
883 emitcode ("dec", "%s", pair);
889 spillPair (PAIR_ID pairId)
891 _G.pairs[pairId].last_type = AOP_INVALID;
892 _G.pairs[pairId].lit = NULL;
903 requiresHL (asmop * aop)
917 fetchLitSpecial (asmop * aop, bool negate, bool xor)
920 value *val = aop->aopu.aop_lit;
922 wassert (aop->type == AOP_LIT);
923 wassert (!IS_FLOAT (val->type));
925 v = (unsigned long) floatFromVal (val);
933 tsprintf (buffer, "!immedword", v);
934 return gc_strdup (buffer);
938 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
941 const char *pair = _pairs[pairId].name;
942 l = aopGetLitWordLong (left, 0, FALSE);
947 if (pairId == PAIR_HL || pairId == PAIR_IY)
949 if (_G.pairs[pairId].last_type == left->type)
951 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
953 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
955 adjustPair (pair, &_G.pairs[pairId].offset, offset);
958 if (pairId == PAIR_IY && abs (offset) < 127)
965 _G.pairs[pairId].last_type = left->type;
966 _G.pairs[pairId].lit = gc_strdup (l);
967 _G.pairs[pairId].offset = offset;
969 if (IS_GB && pairId == PAIR_DE && 0)
971 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
973 if (abs (_G.pairs[pairId].offset - offset) < 3)
975 adjustPair (pair, &_G.pairs[pairId].offset, offset);
979 _G.pairs[pairId].last_type = left->type;
980 _G.pairs[pairId].lit = gc_strdup (l);
981 _G.pairs[pairId].offset = offset;
983 /* Both a lit on the right and a true symbol on the left */
985 emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
987 emit2 ("ld %s,!hashedstr", pair, l);
991 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
993 /* if this is remateriazable */
994 if (isLitWord (aop)) {
995 fetchLitPair (pairId, aop, offset);
998 /* we need to get it byte by byte */
999 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1000 aopGet (aop, offset, FALSE);
1001 switch (aop->size) {
1003 emit2 ("ld l,!*hl");
1004 emit2 ("ld h,!immedbyte", 0);
1008 emit2 ("ld h,!*hl");
1012 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1015 else if (IS_Z80 && aop->type == AOP_IY) {
1016 /* Instead of fetching relative to IY, just grab directly
1017 from the address IY refers to */
1018 char *l = aopGetLitWordLong (aop, offset, FALSE);
1020 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1022 if (aop->size < 2) {
1023 emit2("ld %s,!zero", _pairs[pairId].h);
1027 emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1028 emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1030 /* PENDING: check? */
1031 if (pairId == PAIR_HL)
1032 spillPair (PAIR_HL);
1037 fetchPair (PAIR_ID pairId, asmop * aop)
1039 fetchPairLong (pairId, aop, 0);
1043 fetchHL (asmop * aop)
1045 fetchPair (PAIR_HL, aop);
1049 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1051 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1056 fetchLitPair (pairId, aop, 0);
1059 fetchLitPair (pairId, aop, offset);
1060 _G.pairs[pairId].offset = offset;
1064 /* Doesnt include _G.stack.pushed */
1065 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1066 if (aop->aopu.aop_stk > 0)
1068 abso += _G.stack.param_offset;
1070 assert (pairId == PAIR_HL);
1071 /* In some cases we can still inc or dec hl */
1072 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1074 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1078 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1080 _G.pairs[pairId].offset = abso;
1086 _G.pairs[pairId].last_type = aop->type;
1092 emit2 ("!tlabeldef", key);
1096 /*-----------------------------------------------------------------*/
1097 /* aopGet - for fetching value of the aop */
1098 /*-----------------------------------------------------------------*/
1100 aopGet (asmop * aop, int offset, bool bit16)
1105 /* offset is greater than size then zero */
1106 /* PENDING: this seems a bit screwed in some pointer cases. */
1107 if (offset > (aop->size - 1) &&
1108 aop->type != AOP_LIT)
1111 /* depending on type */
1115 /* PENDING: re-target */
1117 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1122 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1125 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1128 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1133 rs = Safe_calloc (1, strlen (s) + 1);
1139 emitcode ("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1141 rs = Safe_calloc (1, strlen (s) + 1);
1147 emitcode ("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1149 rs = Safe_calloc (1, strlen (s) + 1);
1154 return aop->aopu.aop_reg[offset]->name;
1158 setupPair (PAIR_HL, aop, offset);
1159 tsprintf (s, "!*hl");
1160 return gc_strdup (s);
1164 setupPair (PAIR_IY, aop, offset);
1165 tsprintf (s, "!*iyx", offset);
1166 rs = Safe_calloc (1, strlen (s) + 1);
1173 setupPair (PAIR_HL, aop, offset);
1174 tsprintf (s, "!*hl");
1178 if (aop->aopu.aop_stk >= 0)
1179 offset += _G.stack.param_offset;
1180 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1182 rs = Safe_calloc (1, strlen (s) + 1);
1197 wassert (offset < 2);
1198 return aop->aopu.aop_str[offset];
1201 return aopLiteral (aop->aopu.aop_lit, offset);
1205 return aop->aopu.aop_str[offset];
1209 wassertl (0, "aopget got unsupported aop->type");
1214 isRegString (const char *s)
1216 if (!strcmp (s, "b") ||
1228 isConstant (const char *s)
1230 /* This is a bit of a hack... */
1231 return (*s == '#' || *s == '$');
1235 canAssignToPtr (const char *s)
1237 if (isRegString (s))
1244 /*-----------------------------------------------------------------*/
1245 /* aopPut - puts a string for a aop */
1246 /*-----------------------------------------------------------------*/
1248 aopPut (asmop * aop, const char *s, int offset)
1250 if (aop->size && offset > (aop->size - 1))
1252 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1253 "aopPut got offset > aop->size");
1257 /* will assign value to value */
1258 /* depending on where it is ofcourse */
1264 if (strcmp (s, "a"))
1265 emitcode ("ld", "a,%s", s);
1266 emitcode ("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1271 if (strcmp (s, "a"))
1272 emitcode ("ld", "a,%s", s);
1273 emitcode ("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1277 if (!strcmp (s, "!*hl"))
1278 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1281 aop->aopu.aop_reg[offset]->name, s);
1286 setupPair (PAIR_IY, aop, offset);
1287 if (!canAssignToPtr (s))
1289 emit2 ("ld a,%s", s);
1290 emit2 ("ld !*iyx,a", offset);
1293 emit2 ("ld !*iyx,%s", offset, s);
1298 /* PENDING: for re-target */
1299 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1301 emit2 ("ld a,!*hl");
1304 setupPair (PAIR_HL, aop, offset);
1306 emit2 ("ld !*hl,%s", s);
1312 /* PENDING: re-target */
1313 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1315 emit2 ("ld a,!*hl");
1318 setupPair (PAIR_HL, aop, offset);
1319 if (!canAssignToPtr (s))
1321 emit2 ("ld a,%s", s);
1322 emit2 ("ld !*hl,a");
1325 emit2 ("ld !*hl,%s", s);
1329 if (aop->aopu.aop_stk >= 0)
1330 offset += _G.stack.param_offset;
1331 if (!canAssignToPtr (s))
1333 emit2 ("ld a,%s", s);
1334 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1337 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1342 /* if bit variable */
1343 if (!aop->aopu.aop_dir)
1350 /* In bit space but not in C - cant happen */
1357 if (strcmp (aop->aopu.aop_str[offset], s))
1359 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1365 if (!offset && (strcmp (s, "acc") == 0))
1370 emitcode ("", "; Error aopPut AOP_ACC");
1374 if (strcmp (aop->aopu.aop_str[offset], s))
1375 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1380 wassert (offset < 2);
1381 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1385 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1386 "aopPut got unsupported aop->type");
1391 #define AOP(op) op->aop
1392 #define AOP_TYPE(op) AOP(op)->type
1393 #define AOP_SIZE(op) AOP(op)->size
1394 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1397 commitPair (asmop * aop, PAIR_ID id)
1399 if (id == PAIR_HL && requiresHL (aop))
1403 aopPut (aop, "a", 0);
1404 aopPut (aop, "d", 1);
1408 aopPut (aop, _pairs[id].l, 0);
1409 aopPut (aop, _pairs[id].h, 1);
1413 /*-----------------------------------------------------------------*/
1414 /* getDataSize - get the operand data size */
1415 /*-----------------------------------------------------------------*/
1417 getDataSize (operand * op)
1420 size = AOP_SIZE (op);
1429 /*-----------------------------------------------------------------*/
1430 /* movLeft2Result - move byte from left to result */
1431 /*-----------------------------------------------------------------*/
1433 movLeft2Result (operand * left, int offl,
1434 operand * result, int offr, int sign)
1437 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1439 l = aopGet (AOP (left), offl, FALSE);
1443 aopPut (AOP (result), l, offr);
1453 /** Put Acc into a register set
1456 outAcc (operand * result)
1459 size = getDataSize (result);
1462 aopPut (AOP (result), "a", 0);
1465 /* unsigned or positive */
1468 aopPut (AOP (result), zero, offset++);
1473 /** Take the value in carry and put it into a register
1476 outBitCLong (operand * result, bool swap_sense)
1478 /* if the result is bit */
1479 if (AOP_TYPE (result) == AOP_CRY)
1481 emitcode ("", "; Note: outBitC form 1");
1482 aopPut (AOP (result), "blah", 0);
1486 emit2 ("ld a,!zero");
1489 emit2 ("xor a,!immedbyte", 1);
1495 outBitC (operand * result)
1497 outBitCLong (result, FALSE);
1500 /*-----------------------------------------------------------------*/
1501 /* toBoolean - emit code for orl a,operator(sizeop) */
1502 /*-----------------------------------------------------------------*/
1504 toBoolean (operand * oper)
1506 int size = AOP_SIZE (oper);
1510 emitcode ("ld", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1513 emitcode ("or", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1517 if (AOP (oper)->type != AOP_ACC)
1520 emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
1525 /*-----------------------------------------------------------------*/
1526 /* genNot - generate code for ! operation */
1527 /*-----------------------------------------------------------------*/
1531 sym_link *optype = operandType (IC_LEFT (ic));
1533 /* assign asmOps to operand & result */
1534 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1535 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1537 /* if in bit space then a special case */
1538 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1543 /* if type float then do float */
1544 if (IS_FLOAT (optype))
1549 toBoolean (IC_LEFT (ic));
1554 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1555 emit2 ("sub a,!one");
1556 outBitC (IC_RESULT (ic));
1558 /* release the aops */
1559 freeAsmop (IC_LEFT (ic), NULL, ic);
1560 freeAsmop (IC_RESULT (ic), NULL, ic);
1563 /*-----------------------------------------------------------------*/
1564 /* genCpl - generate code for complement */
1565 /*-----------------------------------------------------------------*/
1573 /* assign asmOps to operand & result */
1574 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1575 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1577 /* if both are in bit space then
1579 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1580 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1585 size = AOP_SIZE (IC_RESULT (ic));
1588 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1591 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1594 /* release the aops */
1595 freeAsmop (IC_LEFT (ic), NULL, ic);
1596 freeAsmop (IC_RESULT (ic), NULL, ic);
1599 /*-----------------------------------------------------------------*/
1600 /* genUminus - unary minus code generation */
1601 /*-----------------------------------------------------------------*/
1603 genUminus (iCode * ic)
1606 sym_link *optype, *rtype;
1609 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1612 /* if both in bit space then special
1614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1621 optype = operandType (IC_LEFT (ic));
1622 rtype = operandType (IC_RESULT (ic));
1624 /* if float then do float stuff */
1625 if (IS_FLOAT (optype))
1631 /* otherwise subtract from zero */
1632 size = AOP_SIZE (IC_LEFT (ic));
1637 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1638 emit2 ("ld a,!zero");
1639 emit2 ("sbc a,%s", l);
1640 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1643 /* if any remaining bytes in the result */
1644 /* we just need to propagate the sign */
1645 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1650 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1654 /* release the aops */
1655 freeAsmop (IC_LEFT (ic), NULL, ic);
1656 freeAsmop (IC_RESULT (ic), NULL, ic);
1660 _push (PAIR_ID pairId)
1662 emit2 ("push %s", _pairs[pairId].name);
1663 _G.stack.pushed += 2;
1667 _pop (PAIR_ID pairId)
1669 emit2 ("pop %s", _pairs[pairId].name);
1670 _G.stack.pushed -= 2;
1674 /*-----------------------------------------------------------------*/
1675 /* assignResultValue - */
1676 /*-----------------------------------------------------------------*/
1678 assignResultValue (operand * oper)
1680 int size = AOP_SIZE (oper);
1683 wassert (size <= 4);
1684 topInA = requiresHL (AOP (oper));
1688 wassert (size <= 2);
1690 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1692 /* We do it the hard way here. */
1694 aopPut (AOP (oper), _fReturn[0], 0);
1695 aopPut (AOP (oper), _fReturn[1], 1);
1696 emitcode ("pop", "de");
1697 _G.stack.pushed -= 2;
1698 aopPut (AOP (oper), _fReturn[0], 2);
1699 aopPut (AOP (oper), _fReturn[1], 3);
1705 aopPut (AOP (oper), _fReturn[size], size);
1710 /*-----------------------------------------------------------------*/
1711 /* genIpush - genrate code for pushing this gets a little complex */
1712 /*-----------------------------------------------------------------*/
1714 genIpush (iCode * ic)
1716 int size, offset = 0;
1719 /* if this is not a parm push : ie. it is spill push
1720 and spill push is always done on the local stack */
1723 /* and the item is spilt then do nothing */
1724 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1727 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1728 size = AOP_SIZE (IC_LEFT (ic));
1729 /* push it on the stack */
1730 if (isPair (AOP (IC_LEFT (ic))))
1732 emitcode ("push", getPairName (AOP (IC_LEFT (ic))));
1733 _G.stack.pushed += 2;
1740 /* Simple for now - load into A and PUSH AF */
1741 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1743 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1745 emit2 ("ld a,(%s)", l);
1749 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1750 emit2 ("ld a,%s", l);
1760 /* Hmmm... what about saving the currently used registers
1763 /* then do the push */
1764 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1766 size = AOP_SIZE (IC_LEFT (ic));
1768 if (isPair (AOP (IC_LEFT (ic))))
1770 _G.stack.pushed += 2;
1771 emitcode ("push", "%s", getPairName (AOP (IC_LEFT (ic))));
1777 fetchHL (AOP (IC_LEFT (ic)));
1778 emitcode ("push", "hl");
1779 spillPair (PAIR_HL);
1780 _G.stack.pushed += 2;
1785 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1786 emitcode ("push", "hl");
1787 spillPair (PAIR_HL);
1788 _G.stack.pushed += 2;
1789 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1790 emitcode ("push", "hl");
1791 spillPair (PAIR_HL);
1792 _G.stack.pushed += 2;
1798 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1800 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1802 emit2 ("ld a,(%s)", l);
1806 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1807 emit2 ("ld a,%s", l);
1809 emitcode ("push", "af");
1810 emitcode ("inc", "sp");
1815 freeAsmop (IC_LEFT (ic), NULL, ic);
1818 /*-----------------------------------------------------------------*/
1819 /* genIpop - recover the registers: can happen only for spilling */
1820 /*-----------------------------------------------------------------*/
1822 genIpop (iCode * ic)
1827 /* if the temp was not pushed then */
1828 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1831 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1832 size = AOP_SIZE (IC_LEFT (ic));
1833 offset = (size - 1);
1834 if (isPair (AOP (IC_LEFT (ic))))
1836 emitcode ("pop", getPairName (AOP (IC_LEFT (ic))));
1842 emitcode ("dec", "sp");
1843 emitcode ("pop", "hl");
1844 spillPair (PAIR_HL);
1845 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1849 freeAsmop (IC_LEFT (ic), NULL, ic);
1853 _isPairUsed (iCode * ic, PAIR_ID pairId)
1859 if (bitVectBitValue (ic->rMask, D_IDX))
1861 if (bitVectBitValue (ic->rMask, E_IDX))
1871 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1875 symbol *sym = OP_SYMBOL (op);
1877 if (sym->isspilt || sym->nRegs == 0)
1880 aopOp (op, ic, FALSE, FALSE);
1883 if (aop->type == AOP_REG)
1886 for (i = 0; i < aop->size; i++)
1888 if (pairId == PAIR_DE)
1890 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1891 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
1893 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
1903 freeAsmop (IC_LEFT (ic), NULL, ic);
1907 /* This is quite unfortunate */
1909 setArea (int inHome)
1912 static int lastArea = 0;
1914 if (_G.in_home != inHome) {
1916 const char *sz = port->mem.code_name;
1917 port->mem.code_name = "HOME";
1918 emit2("!area", CODE_NAME);
1919 port->mem.code_name = sz;
1922 emit2("!area", CODE_NAME); */
1923 _G.in_home = inHome;
1933 /** Emit the code for a call statement
1936 emitCall (iCode * ic, bool ispcall)
1939 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
1941 /* if caller saves & we have not saved then */
1947 /* if send set is not empty then assign */
1952 int n = elementsInSet (sendSet);
1953 if (IS_Z80 && n == 2 && _isPairUsed (ic, PAIR_DE))
1955 /* Only push de if it is used and if it's not used
1956 in the return value */
1957 /* Panic if partly used */
1958 if (_opUsesPair (IC_RESULT (ic), ic, PAIR_DE) == 1)
1960 emit2 ("; Warning: de crossover");
1962 else if (!_opUsesPair (IC_RESULT (ic), ic, PAIR_DE))
1970 if (IS_Z80 && n == 2)
1972 /* Want to load HL first, then DE as HL may = DE */
1973 sic = setFirstItem (sendSet);
1974 sic = setNextItem (sendSet);
1975 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1976 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
1978 freeAsmop (IC_LEFT (sic), NULL, sic);
1979 sic = setFirstItem (sendSet);
1980 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1981 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
1983 freeAsmop (IC_LEFT (sic), NULL, sic);
1987 for (sic = setFirstItem (sendSet); sic;
1988 sic = setNextItem (sendSet))
1991 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1992 size = AOP_SIZE (IC_LEFT (sic));
1993 wassert (size <= 2);
1994 /* Always send in pairs */
1998 if (IS_Z80 && n == 1)
1999 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2001 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
2004 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2007 /* Send set too big */
2011 freeAsmop (IC_LEFT (sic), NULL, sic);
2022 if (IS_BANKEDCALL (detype))
2024 werror (W_INDIR_BANKED);
2026 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2028 if (isLitWord (AOP (IC_LEFT (ic))))
2030 emitcode ("", "; Special case where the pCall is to a constant");
2032 emitcode ("call", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2036 symbol *rlbl = newiTempLabel (NULL);
2037 spillPair (PAIR_HL);
2038 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2039 emitcode ("push", "hl");
2040 _G.stack.pushed += 2;
2042 fetchHL (AOP (IC_LEFT (ic)));
2044 emit2 ("!tlabeldef", (rlbl->key + 100));
2045 _G.stack.pushed -= 2;
2047 freeAsmop (IC_LEFT (ic), NULL, ic);
2051 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2052 OP_SYMBOL (IC_LEFT (ic))->rname :
2053 OP_SYMBOL (IC_LEFT (ic))->name;
2054 if (IS_BANKEDCALL (detype))
2056 emit2 ("call banked_call");
2057 emit2 ("!dws", name);
2058 emit2 ("!dw !bankimmeds", name);
2063 emit2 ("call %s", name);
2068 /* if we need assign a result value */
2069 if ((IS_ITEMP (IC_RESULT (ic)) &&
2070 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2071 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2072 IS_TRUE_SYMOP (IC_RESULT (ic)))
2075 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2077 assignResultValue (IC_RESULT (ic));
2079 freeAsmop (IC_RESULT (ic), NULL, ic);
2082 /* adjust the stack for parameters if required */
2085 int i = ic->parmBytes;
2086 _G.stack.pushed -= i;
2089 emit2 ("!ldaspsp", i);
2096 emitcode ("ld", "hl,#%d", i);
2097 emitcode ("add", "hl,sp");
2098 emitcode ("ld", "sp,hl");
2104 emitcode ("pop", "hl");
2108 emitcode ("inc", "sp");
2117 /*-----------------------------------------------------------------*/
2118 /* genCall - generates a call statement */
2119 /*-----------------------------------------------------------------*/
2121 genCall (iCode * ic)
2123 emitCall (ic, FALSE);
2126 /*-----------------------------------------------------------------*/
2127 /* genPcall - generates a call by pointer statement */
2128 /*-----------------------------------------------------------------*/
2130 genPcall (iCode * ic)
2132 emitCall (ic, TRUE);
2135 /*-----------------------------------------------------------------*/
2136 /* resultRemat - result is rematerializable */
2137 /*-----------------------------------------------------------------*/
2139 resultRemat (iCode * ic)
2141 if (SKIP_IC (ic) || ic->op == IFX)
2144 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2146 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2147 if (sym->remat && !POINTER_SET (ic))
2154 extern set *publics;
2156 /*-----------------------------------------------------------------*/
2157 /* genFunction - generated code for function entry */
2158 /*-----------------------------------------------------------------*/
2160 genFunction (iCode * ic)
2162 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2167 _G.receiveOffset = 0;
2169 setArea (IS_NONBANKED (sym->etype));
2172 if (!IS_STATIC (sym->etype))
2174 addSetIfnotP (&publics, sym);
2177 _G.lastFunctionName = sym->rname;
2179 /* create the function header */
2180 emit2 ("!functionheader", sym->name);
2181 /* PENDING: portability. */
2182 emit2 ("__%s_start:", sym->rname);
2183 emit2 ("!functionlabeldef", sym->rname);
2185 fetype = getSpec (operandType (IC_LEFT (ic)));
2187 /* if critical function then turn interrupts off */
2188 if (SPEC_CRTCL (fetype))
2191 /* if this is an interrupt service routine then
2192 save acc, b, dpl, dph */
2193 if (IS_ISR (sym->etype))
2197 /* PENDING: callee-save etc */
2199 /* If BC or DE are used, then push */
2200 _G.stack.pushed_bc = 0;
2201 _G.stack.pushed_de = 0;
2202 _G.stack.param_offset = 0;
2204 /* PENDING: BUG: We don't detect if DE or BC are used in a send set.
2205 For now assume the worst and always save.
2207 _G.stack.pushed_bc = 1;
2208 _G.stack.pushed_de = 1;
2213 for (i = 0; i < sym->regsUsed->size; i++)
2215 if (bitVectBitValue (sym->regsUsed, i))
2221 _G.stack.pushed_bc = 1;
2226 _G.stack.pushed_de = 1;
2233 if (_G.stack.pushed_bc)
2236 _G.stack.param_offset += 2;
2238 if (_G.stack.pushed_de)
2241 _G.stack.param_offset += 2;
2244 /* adjust the stack for the function */
2245 _G.stack.last = sym->stack;
2248 emit2 ("!enterx", sym->stack);
2251 _G.stack.offset = sym->stack;
2254 /*-----------------------------------------------------------------*/
2255 /* genEndFunction - generates epilogue for functions */
2256 /*-----------------------------------------------------------------*/
2258 genEndFunction (iCode * ic)
2260 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2262 if (IS_ISR (sym->etype))
2268 if (SPEC_CRTCL (sym->etype))
2271 /* PENDING: calleeSave */
2273 /* if debug then send end of function */
2274 if (options.debug && currFunc)
2277 emitcode ("", "C$%s$%d$%d$%d ==.",
2278 FileBaseName (ic->filename), currFunc->lastLine,
2279 ic->level, ic->block);
2280 if (IS_STATIC (currFunc->etype))
2281 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2283 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2286 if (_G.stack.offset)
2287 emit2 ("!leavex", _G.stack.offset);
2291 if (_G.stack.pushed_de)
2293 if (_G.stack.pushed_bc)
2295 /* Both baned and non-banked just ret */
2298 /* PENDING: portability. */
2299 emit2 ("__%s_end:", sym->rname);
2301 _G.flush_statics = 1;
2302 _G.stack.pushed = 0;
2303 _G.stack.offset = 0;
2306 /*-----------------------------------------------------------------*/
2307 /* genRet - generate code for return statement */
2308 /*-----------------------------------------------------------------*/
2313 /* Errk. This is a hack until I can figure out how
2314 to cause dehl to spill on a call */
2315 int size, offset = 0;
2317 /* if we have no return value then
2318 just generate the "ret" */
2322 /* we have something to return then
2323 move the return value into place */
2324 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2325 size = AOP_SIZE (IC_LEFT (ic));
2327 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2331 emitcode ("ld", "de,%s", l);
2335 emitcode ("ld", "hl,%s", l);
2340 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2342 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2343 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2349 l = aopGet (AOP (IC_LEFT (ic)), offset,
2351 if (strcmp (_fReturn[offset], l))
2352 emitcode ("ld", "%s,%s", _fReturn[offset++], l);
2356 freeAsmop (IC_LEFT (ic), NULL, ic);
2359 /* generate a jump to the return label
2360 if the next is not the return statement */
2361 if (!(ic->next && ic->next->op == LABEL &&
2362 IC_LABEL (ic->next) == returnLabel))
2364 emit2 ("jp !tlabel", returnLabel->key + 100);
2367 /*-----------------------------------------------------------------*/
2368 /* genLabel - generates a label */
2369 /*-----------------------------------------------------------------*/
2371 genLabel (iCode * ic)
2373 /* special case never generate */
2374 if (IC_LABEL (ic) == entryLabel)
2377 emitLabel (IC_LABEL (ic)->key + 100);
2380 /*-----------------------------------------------------------------*/
2381 /* genGoto - generates a ljmp */
2382 /*-----------------------------------------------------------------*/
2384 genGoto (iCode * ic)
2386 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2389 /*-----------------------------------------------------------------*/
2390 /* genPlusIncr :- does addition with increment if possible */
2391 /*-----------------------------------------------------------------*/
2393 genPlusIncr (iCode * ic)
2395 unsigned int icount;
2396 unsigned int size = getDataSize (IC_RESULT (ic));
2397 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2399 /* will try to generate an increment */
2400 /* if the right side is not a literal
2402 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2405 emitcode ("", "; genPlusIncr");
2407 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2409 /* If result is a pair */
2410 if (resultId != PAIR_INVALID)
2412 if (isLitWord (AOP (IC_LEFT (ic))))
2414 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2417 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2419 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2420 emitcode ("add", "hl,%s", getPairName (AOP (IC_LEFT (ic))));
2426 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2430 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2431 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2435 emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
2440 /* if the literal value of the right hand side
2441 is greater than 4 then it is not worth it */
2445 /* if increment 16 bits in register */
2446 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2452 symbol *tlbl = NULL;
2453 tlbl = newiTempLabel (NULL);
2456 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2459 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2462 emitLabel (tlbl->key + 100);
2466 /* if the sizes are greater than 1 then we cannot */
2467 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2468 AOP_SIZE (IC_LEFT (ic)) > 1)
2471 /* we can if the aops of the left & result match or
2472 if they are in registers and the registers are the
2474 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2477 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2484 /*-----------------------------------------------------------------*/
2485 /* outBitAcc - output a bit in acc */
2486 /*-----------------------------------------------------------------*/
2488 outBitAcc (operand * result)
2490 symbol *tlbl = newiTempLabel (NULL);
2491 /* if the result is a bit */
2492 if (AOP_TYPE (result) == AOP_CRY)
2498 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2499 emit2 ("ld a,!one");
2500 emitLabel (tlbl->key + 100);
2505 /*-----------------------------------------------------------------*/
2506 /* genPlus - generates code for addition */
2507 /*-----------------------------------------------------------------*/
2509 genPlus (iCode * ic)
2511 int size, offset = 0;
2513 /* special cases :- */
2515 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2516 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2517 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2519 /* Swap the left and right operands if:
2521 if literal, literal on the right or
2522 if left requires ACC or right is already
2525 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2526 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2527 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2529 operand *t = IC_RIGHT (ic);
2530 IC_RIGHT (ic) = IC_LEFT (ic);
2534 /* if both left & right are in bit
2536 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2537 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2543 /* if left in bit space & right literal */
2544 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2545 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2547 /* Can happen I guess */
2551 /* if I can do an increment instead
2552 of add then GOOD for ME */
2553 if (genPlusIncr (ic) == TRUE)
2556 emit2 ("; genPlusIncr failed");
2558 size = getDataSize (IC_RESULT (ic));
2560 /* Special case when left and right are constant */
2561 if (isPair (AOP (IC_RESULT (ic))))
2565 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2566 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2572 sprintf (buffer, "#(%s + %s)", left, right);
2573 emitcode ("ld", "%s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2578 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2580 /* Fetch into HL then do the add */
2581 spillPair (PAIR_HL);
2582 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2583 emitcode ("add", "hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2588 ld hl,sp+n trashes C so we cant afford to do it during an
2589 add with stack based varibles. Worst case is:
2602 So you cant afford to load up hl if either left, right, or result
2603 is on the stack (*sigh*) The alt is:
2611 Combinations in here are:
2612 * If left or right are in bc then the loss is small - trap later
2613 * If the result is in bc then the loss is also small
2617 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2618 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2619 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2621 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2622 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2623 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2624 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2626 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2628 /* Swap left and right */
2629 operand *t = IC_RIGHT (ic);
2630 IC_RIGHT (ic) = IC_LEFT (ic);
2633 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2635 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2636 emit2 ("add hl,bc");
2640 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2641 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2642 emit2 ("add hl,de");
2644 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2649 emit2 ("; WARNING: This add is probably broken.\n");
2656 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2658 _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2661 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2664 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2668 _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2671 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2674 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2676 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2680 freeAsmop (IC_LEFT (ic), NULL, ic);
2681 freeAsmop (IC_RIGHT (ic), NULL, ic);
2682 freeAsmop (IC_RESULT (ic), NULL, ic);
2686 /*-----------------------------------------------------------------*/
2687 /* genMinusDec :- does subtraction with deccrement if possible */
2688 /*-----------------------------------------------------------------*/
2690 genMinusDec (iCode * ic)
2692 unsigned int icount;
2693 unsigned int size = getDataSize (IC_RESULT (ic));
2695 /* will try to generate an increment */
2696 /* if the right side is not a literal we cannot */
2697 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2700 /* if the literal value of the right hand side
2701 is greater than 4 then it is not worth it */
2702 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2705 size = getDataSize (IC_RESULT (ic));
2708 /* if increment 16 bits in register */
2709 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2713 symbol *tlbl = newiTempLabel (NULL);
2714 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2715 emitcode ("jp", "np," LABEL_STR, tlbl->key + 100);
2717 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2722 emitLabel (tlbl->key + 100);
2727 /* if decrement 16 bits in register */
2728 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2729 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2732 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2736 /* If result is a pair */
2737 if (isPair (AOP (IC_RESULT (ic))))
2739 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2740 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2742 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2746 /* if the sizes are greater than 1 then we cannot */
2747 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2748 AOP_SIZE (IC_LEFT (ic)) > 1)
2751 /* we can if the aops of the left & result match or if they are in
2752 registers and the registers are the same */
2753 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2756 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2763 /*-----------------------------------------------------------------*/
2764 /* genMinus - generates code for subtraction */
2765 /*-----------------------------------------------------------------*/
2767 genMinus (iCode * ic)
2769 int size, offset = 0;
2770 unsigned long lit = 0L;
2772 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2773 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2774 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2776 /* special cases :- */
2777 /* if both left & right are in bit space */
2778 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2779 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2785 /* if I can do an decrement instead of subtract then GOOD for ME */
2786 if (genMinusDec (ic) == TRUE)
2789 size = getDataSize (IC_RESULT (ic));
2791 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2796 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2800 /* Same logic as genPlus */
2803 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2804 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2805 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2807 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2808 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2809 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2810 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2812 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2813 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2815 if (left == PAIR_INVALID && right == PAIR_INVALID)
2820 else if (right == PAIR_INVALID)
2822 else if (left == PAIR_INVALID)
2825 fetchPair (left, AOP (IC_LEFT (ic)));
2826 /* Order is important. Right may be HL */
2827 fetchPair (right, AOP (IC_RIGHT (ic)));
2829 emit2 ("ld a,%s", _pairs[left].l);
2830 emit2 ("sub a,%s", _pairs[right].l);
2832 emit2 ("ld a,%s", _pairs[left].h);
2833 emit2 ("sbc a,%s", _pairs[right].h);
2835 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2836 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2841 emit2 ("; WARNING: This sub is probably broken.\n");
2846 /* if literal, add a,#-lit, else normal subb */
2849 _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2850 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2853 emitcode ("sub", "a,%s",
2854 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2856 emitcode ("sbc", "a,%s",
2857 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2861 /* first add without previous c */
2863 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2865 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2867 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2870 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2871 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2872 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2876 freeAsmop (IC_LEFT (ic), NULL, ic);
2877 freeAsmop (IC_RIGHT (ic), NULL, ic);
2878 freeAsmop (IC_RESULT (ic), NULL, ic);
2881 /*-----------------------------------------------------------------*/
2882 /* genMult - generates code for multiplication */
2883 /*-----------------------------------------------------------------*/
2885 genMult (iCode * ic)
2887 /* Shouldn't occur - all done through function calls */
2891 /*-----------------------------------------------------------------*/
2892 /* genDiv - generates code for division */
2893 /*-----------------------------------------------------------------*/
2897 /* Shouldn't occur - all done through function calls */
2901 /*-----------------------------------------------------------------*/
2902 /* genMod - generates code for division */
2903 /*-----------------------------------------------------------------*/
2907 /* Shouldn't occur - all done through function calls */
2911 /*-----------------------------------------------------------------*/
2912 /* genIfxJump :- will create a jump depending on the ifx */
2913 /*-----------------------------------------------------------------*/
2915 genIfxJump (iCode * ic, char *jval)
2920 /* if true label then we jump if condition
2924 jlbl = IC_TRUE (ic);
2925 if (!strcmp (jval, "a"))
2929 else if (!strcmp (jval, "c"))
2933 else if (!strcmp (jval, "nc"))
2939 /* The buffer contains the bit on A that we should test */
2945 /* false label is present */
2946 jlbl = IC_FALSE (ic);
2947 if (!strcmp (jval, "a"))
2951 else if (!strcmp (jval, "c"))
2955 else if (!strcmp (jval, "nc"))
2961 /* The buffer contains the bit on A that we should test */
2965 /* Z80 can do a conditional long jump */
2966 if (!strcmp (jval, "a"))
2968 emitcode ("or", "a,a");
2970 else if (!strcmp (jval, "c"))
2973 else if (!strcmp (jval, "nc"))
2978 emitcode ("bit", "%s,a", jval);
2980 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
2982 /* mark the icode as generated */
2987 _getPairIdName (PAIR_ID id)
2989 return _pairs[id].name;
2992 /** Generic compare for > or <
2995 genCmp (operand * left, operand * right,
2996 operand * result, iCode * ifx, int sign)
2998 int size, offset = 0;
2999 unsigned long lit = 0L;
3000 bool swap_sense = FALSE;
3002 /* if left & right are bit variables */
3003 if (AOP_TYPE (left) == AOP_CRY &&
3004 AOP_TYPE (right) == AOP_CRY)
3006 /* Cant happen on the Z80 */
3011 /* subtract right from left if at the
3012 end the carry flag is set then we know that
3013 left is greater than right */
3014 size = max (AOP_SIZE (left), AOP_SIZE (right));
3016 /* if unsigned char cmp with lit, just compare */
3018 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3020 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3023 emit2 ("xor a,!immedbyte", 0x80);
3024 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3027 emitcode ("cp", "%s", aopGet (AOP (right), offset, FALSE));
3033 If the left or the right is a lit:
3034 Load -lit into HL, add to right via, check sense.
3036 if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3038 PAIR_ID id = PAIR_DE;
3039 asmop *lit = AOP (right);
3040 asmop *op = AOP (left);
3043 if (AOP_TYPE (left) == AOP_LIT)
3051 emit2 ("ld e,%s", aopGet (op, 0, 0));
3052 emit2 ("ld a,%s", aopGet (op, 1, 0));
3053 emit2 ("xor a,!immedbyte", 0x80);
3058 id = getPairId (op);
3059 if (id == PAIR_INVALID)
3061 fetchPair (PAIR_DE, op);
3065 spillPair (PAIR_HL);
3066 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3067 emit2 ("add hl,%s", _getPairIdName (id));
3070 if (AOP_TYPE (right) == AOP_LIT)
3072 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3073 /* optimize if(x < 0) or if(x >= 0) */
3078 /* No sign so it's always false */
3083 /* Just load in the top most bit */
3084 _MoveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3085 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3087 genIfxJump (ifx, "7");
3091 emitcode ("rlc", "a");
3098 /* First setup h and l contaning the top most bytes XORed */
3099 bool fDidXor = FALSE;
3100 if (AOP_TYPE (left) == AOP_LIT)
3102 unsigned long lit = (unsigned long)
3103 floatFromVal (AOP (left)->aopu.aop_lit);
3104 emit2 ("ld %s,!immedbyte", _fTmp[0],
3105 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3109 emitcode ("ld", "a,%s", aopGet (AOP (left), size - 1, FALSE));
3110 emit2 ("xor a,!immedbyte", 0x80);
3111 emitcode ("ld", "%s,a", _fTmp[0]);
3114 if (AOP_TYPE (right) == AOP_LIT)
3116 unsigned long lit = (unsigned long)
3117 floatFromVal (AOP (right)->aopu.aop_lit);
3118 emit2 ("ld %s,!immedbyte", _fTmp[1],
3119 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3123 emitcode ("ld", "a,%s", aopGet (AOP (right), size - 1, FALSE));
3124 emit2 ("xor a,!immedbyte", 0x80);
3125 emitcode ("ld", "%s,a", _fTmp[1]);
3137 /* Do a long subtract */
3140 _MoveA (aopGet (AOP (left), offset, FALSE));
3142 if (sign && size == 0)
3144 emitcode ("ld", "a,%s", _fTmp[0]);
3145 emitcode ("sbc", "a,%s", _fTmp[1]);
3149 /* Subtract through, propagating the carry */
3150 emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3157 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3159 outBitCLong (result, swap_sense);
3163 /* if the result is used in the next
3164 ifx conditional branch then generate
3165 code a little differently */
3167 genIfxJump (ifx, swap_sense ? "nc" : "c");
3169 outBitCLong (result, swap_sense);
3170 /* leave the result in acc */
3174 /*-----------------------------------------------------------------*/
3175 /* genCmpGt :- greater than comparison */
3176 /*-----------------------------------------------------------------*/
3178 genCmpGt (iCode * ic, iCode * ifx)
3180 operand *left, *right, *result;
3181 sym_link *letype, *retype;
3184 left = IC_LEFT (ic);
3185 right = IC_RIGHT (ic);
3186 result = IC_RESULT (ic);
3188 letype = getSpec (operandType (left));
3189 retype = getSpec (operandType (right));
3190 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3191 /* assign the amsops */
3192 aopOp (left, ic, FALSE, FALSE);
3193 aopOp (right, ic, FALSE, FALSE);
3194 aopOp (result, ic, TRUE, FALSE);
3196 genCmp (right, left, result, ifx, sign);
3198 freeAsmop (left, NULL, ic);
3199 freeAsmop (right, NULL, ic);
3200 freeAsmop (result, NULL, ic);
3203 /*-----------------------------------------------------------------*/
3204 /* genCmpLt - less than comparisons */
3205 /*-----------------------------------------------------------------*/
3207 genCmpLt (iCode * ic, iCode * ifx)
3209 operand *left, *right, *result;
3210 sym_link *letype, *retype;
3213 left = IC_LEFT (ic);
3214 right = IC_RIGHT (ic);
3215 result = IC_RESULT (ic);
3217 letype = getSpec (operandType (left));
3218 retype = getSpec (operandType (right));
3219 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3221 /* assign the amsops */
3222 aopOp (left, ic, FALSE, FALSE);
3223 aopOp (right, ic, FALSE, FALSE);
3224 aopOp (result, ic, TRUE, FALSE);
3226 genCmp (left, right, result, ifx, sign);
3228 freeAsmop (left, NULL, ic);
3229 freeAsmop (right, NULL, ic);
3230 freeAsmop (result, NULL, ic);
3233 /*-----------------------------------------------------------------*/
3234 /* gencjneshort - compare and jump if not equal */
3235 /*-----------------------------------------------------------------*/
3237 gencjneshort (operand * left, operand * right, symbol * lbl)
3239 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3241 unsigned long lit = 0L;
3243 /* Swap the left and right if it makes the computation easier */
3244 if (AOP_TYPE (left) == AOP_LIT)
3251 if (AOP_TYPE (right) == AOP_LIT)
3252 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3254 /* if the right side is a literal then anything goes */
3255 if (AOP_TYPE (right) == AOP_LIT &&
3256 AOP_TYPE (left) != AOP_DIR)
3260 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3267 emitcode ("or", "a,%s", aopGet (AOP (left), offset, FALSE));
3272 emitcode ("or", "a,a");
3274 emit2 ("jp nz,!tlabel", lbl->key + 100);
3280 emitcode ("ld", "a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3281 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3282 emitcode ("or", "a,a");
3284 emitcode ("cp", "a,%s", aopGet (AOP (right), offset, FALSE));
3285 emit2 ("jp nz,!tlabel", lbl->key + 100);
3290 /* if the right side is in a register or in direct space or
3291 if the left is a pointer register & right is not */
3292 else if (AOP_TYPE (right) == AOP_REG ||
3293 AOP_TYPE (right) == AOP_DIR ||
3294 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3298 _MoveA (aopGet (AOP (left), offset, FALSE));
3299 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3300 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3302 emit2 ("jp nz,!tlabel", lbl->key + 100);
3305 emitcode ("cp", "%s ; 4", aopGet (AOP (right), offset, FALSE));
3306 emit2 ("jp nz,!tlabel", lbl->key + 100);
3313 /* right is a pointer reg need both a & b */
3314 /* PENDING: is this required? */
3317 _MoveA (aopGet (AOP (right), offset, FALSE));
3318 emitcode ("cp", "%s ; 5", aopGet (AOP (left), offset, FALSE));
3319 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3325 /*-----------------------------------------------------------------*/
3326 /* gencjne - compare and jump if not equal */
3327 /*-----------------------------------------------------------------*/
3329 gencjne (operand * left, operand * right, symbol * lbl)
3331 symbol *tlbl = newiTempLabel (NULL);
3333 gencjneshort (left, right, lbl);
3336 emit2 ("ld a,!one");
3337 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3338 emitLabel (lbl->key + 100);
3339 emitcode ("xor", "a,a");
3340 emitLabel (tlbl->key + 100);
3343 /*-----------------------------------------------------------------*/
3344 /* genCmpEq - generates code for equal to */
3345 /*-----------------------------------------------------------------*/
3347 genCmpEq (iCode * ic, iCode * ifx)
3349 operand *left, *right, *result;
3351 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3352 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3353 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3355 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3357 /* Swap operands if it makes the operation easier. ie if:
3358 1. Left is a literal.
3360 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3362 operand *t = IC_RIGHT (ic);
3363 IC_RIGHT (ic) = IC_LEFT (ic);
3367 if (ifx && !AOP_SIZE (result))
3370 /* if they are both bit variables */
3371 if (AOP_TYPE (left) == AOP_CRY &&
3372 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3378 tlbl = newiTempLabel (NULL);
3379 gencjneshort (left, right, tlbl);
3382 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3383 emitLabel (tlbl->key + 100);
3387 /* PENDING: do this better */
3388 symbol *lbl = newiTempLabel (NULL);
3389 emit2 ("!shortjp !tlabel", lbl->key + 100);
3390 emitLabel (tlbl->key + 100);
3391 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3392 emitLabel (lbl->key + 100);
3395 /* mark the icode as generated */
3400 /* if they are both bit variables */
3401 if (AOP_TYPE (left) == AOP_CRY &&
3402 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3408 gencjne (left, right, newiTempLabel (NULL));
3409 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3415 genIfxJump (ifx, "a");
3418 /* if the result is used in an arithmetic operation
3419 then put the result in place */
3420 if (AOP_TYPE (result) != AOP_CRY)
3424 /* leave the result in acc */
3428 freeAsmop (left, NULL, ic);
3429 freeAsmop (right, NULL, ic);
3430 freeAsmop (result, NULL, ic);
3433 /*-----------------------------------------------------------------*/
3434 /* ifxForOp - returns the icode containing the ifx for operand */
3435 /*-----------------------------------------------------------------*/
3437 ifxForOp (operand * op, iCode * ic)
3439 /* if true symbol then needs to be assigned */
3440 if (IS_TRUE_SYMOP (op))
3443 /* if this has register type condition and
3444 the next instruction is ifx with the same operand
3445 and live to of the operand is upto the ifx only then */
3447 ic->next->op == IFX &&
3448 IC_COND (ic->next)->key == op->key &&
3449 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3455 /*-----------------------------------------------------------------*/
3456 /* genAndOp - for && operation */
3457 /*-----------------------------------------------------------------*/
3459 genAndOp (iCode * ic)
3461 operand *left, *right, *result;
3464 /* note here that && operations that are in an if statement are
3465 taken away by backPatchLabels only those used in arthmetic
3466 operations remain */
3467 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3468 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3469 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3471 /* if both are bit variables */
3472 if (AOP_TYPE (left) == AOP_CRY &&
3473 AOP_TYPE (right) == AOP_CRY)
3479 tlbl = newiTempLabel (NULL);
3481 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3483 emitLabel (tlbl->key + 100);
3487 freeAsmop (left, NULL, ic);
3488 freeAsmop (right, NULL, ic);
3489 freeAsmop (result, NULL, ic);
3492 /*-----------------------------------------------------------------*/
3493 /* genOrOp - for || operation */
3494 /*-----------------------------------------------------------------*/
3496 genOrOp (iCode * ic)
3498 operand *left, *right, *result;
3501 /* note here that || operations that are in an
3502 if statement are taken away by backPatchLabels
3503 only those used in arthmetic operations remain */
3504 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3505 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3506 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3508 /* if both are bit variables */
3509 if (AOP_TYPE (left) == AOP_CRY &&
3510 AOP_TYPE (right) == AOP_CRY)
3516 tlbl = newiTempLabel (NULL);
3518 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3520 emitLabel (tlbl->key + 100);
3524 freeAsmop (left, NULL, ic);
3525 freeAsmop (right, NULL, ic);
3526 freeAsmop (result, NULL, ic);
3529 /*-----------------------------------------------------------------*/
3530 /* isLiteralBit - test if lit == 2^n */
3531 /*-----------------------------------------------------------------*/
3533 isLiteralBit (unsigned long lit)
3535 unsigned long pw[32] =
3536 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3537 0x100L, 0x200L, 0x400L, 0x800L,
3538 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3539 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3540 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3541 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3542 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3545 for (idx = 0; idx < 32; idx++)
3551 /*-----------------------------------------------------------------*/
3552 /* jmpTrueOrFalse - */
3553 /*-----------------------------------------------------------------*/
3555 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3557 // ugly but optimized by peephole
3560 symbol *nlbl = newiTempLabel (NULL);
3561 emit2 ("jp !tlabel", nlbl->key + 100);
3562 emitLabel (tlbl->key + 100);
3563 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3564 emitLabel (nlbl->key + 100);
3568 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3569 emitLabel (tlbl->key + 100);
3574 /*-----------------------------------------------------------------*/
3575 /* genAnd - code for and */
3576 /*-----------------------------------------------------------------*/
3578 genAnd (iCode * ic, iCode * ifx)
3580 operand *left, *right, *result;
3581 int size, offset = 0;
3582 unsigned long lit = 0L;
3585 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3586 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3587 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3590 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3592 AOP_TYPE (left), AOP_TYPE (right));
3593 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3595 AOP_SIZE (left), AOP_SIZE (right));
3598 /* if left is a literal & right is not then exchange them */
3599 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3600 AOP_NEEDSACC (left))
3602 operand *tmp = right;
3607 /* if result = right then exchange them */
3608 if (sameRegs (AOP (result), AOP (right)))
3610 operand *tmp = right;
3615 /* if right is bit then exchange them */
3616 if (AOP_TYPE (right) == AOP_CRY &&
3617 AOP_TYPE (left) != AOP_CRY)
3619 operand *tmp = right;
3623 if (AOP_TYPE (right) == AOP_LIT)
3624 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3626 size = AOP_SIZE (result);
3628 if (AOP_TYPE (left) == AOP_CRY)
3634 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3635 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3636 if ((AOP_TYPE (right) == AOP_LIT) &&
3637 (AOP_TYPE (result) == AOP_CRY) &&
3638 (AOP_TYPE (left) != AOP_CRY))
3640 int posbit = isLiteralBit (lit);
3645 _MoveA (aopGet (AOP (left), posbit >> 3, FALSE));
3650 emitcode ("mov", "c,acc.%d", posbit & 0x07);
3657 sprintf (buffer, "%d", posbit & 0x07);
3658 genIfxJump (ifx, buffer);
3669 symbol *tlbl = newiTempLabel (NULL);
3670 int sizel = AOP_SIZE (left);
3674 emitcode ("setb", "c");
3678 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3680 _MoveA (aopGet (AOP (left), offset, FALSE));
3682 if ((posbit = isLiteralBit (bytelit)) != 0)
3685 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3689 if (bytelit != 0x0FFL)
3690 emitcode ("and", "a,%s",
3691 aopGet (AOP (right), offset, FALSE));
3695 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3700 // bit = left & literal
3703 emitcode ("clr", "c");
3704 emit2 ("!tlabeldef", tlbl->key + 100);
3706 // if(left & literal)
3710 jmpTrueOrFalse (ifx, tlbl);
3718 /* if left is same as result */
3719 if (sameRegs (AOP (result), AOP (left)))
3721 for (; size--; offset++)
3723 if (AOP_TYPE (right) == AOP_LIT)
3725 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3730 aopPut (AOP (result), zero, offset);
3733 _MoveA (aopGet (AOP (left), offset, FALSE));
3734 emitcode ("and", "a,%s",
3735 aopGet (AOP (right), offset, FALSE));
3736 aopPut (AOP (left), "a", offset);
3743 if (AOP_TYPE (left) == AOP_ACC)
3749 _MoveA (aopGet (AOP (left), offset, FALSE));
3750 emitcode ("and", "a,%s",
3751 aopGet (AOP (right), offset, FALSE));
3752 aopPut (AOP (left), "a", offset);
3759 // left & result in different registers
3760 if (AOP_TYPE (result) == AOP_CRY)
3766 for (; (size--); offset++)
3769 // result = left & right
3770 if (AOP_TYPE (right) == AOP_LIT)
3772 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3774 aopPut (AOP (result),
3775 aopGet (AOP (left), offset, FALSE),
3779 else if (bytelit == 0)
3781 aopPut (AOP (result), zero, offset);
3785 // faster than result <- left, anl result,right
3786 // and better if result is SFR
3787 if (AOP_TYPE (left) == AOP_ACC)
3788 emitcode ("and", "a,%s", aopGet (AOP (right), offset, FALSE));
3791 _MoveA (aopGet (AOP (left), offset, FALSE));
3792 emitcode ("and", "a,%s",
3793 aopGet (AOP (right), offset, FALSE));
3795 aopPut (AOP (result), "a", offset);
3802 freeAsmop (left, NULL, ic);
3803 freeAsmop (right, NULL, ic);
3804 freeAsmop (result, NULL, ic);
3807 /*-----------------------------------------------------------------*/
3808 /* genOr - code for or */
3809 /*-----------------------------------------------------------------*/
3811 genOr (iCode * ic, iCode * ifx)
3813 operand *left, *right, *result;
3814 int size, offset = 0;
3815 unsigned long lit = 0L;
3817 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3818 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3819 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3822 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3824 AOP_TYPE (left), AOP_TYPE (right));
3825 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3827 AOP_SIZE (left), AOP_SIZE (right));
3830 /* if left is a literal & right is not then exchange them */
3831 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3832 AOP_NEEDSACC (left))
3834 operand *tmp = right;
3839 /* if result = right then exchange them */
3840 if (sameRegs (AOP (result), AOP (right)))
3842 operand *tmp = right;
3847 /* if right is bit then exchange them */
3848 if (AOP_TYPE (right) == AOP_CRY &&
3849 AOP_TYPE (left) != AOP_CRY)
3851 operand *tmp = right;
3855 if (AOP_TYPE (right) == AOP_LIT)
3856 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3858 size = AOP_SIZE (result);
3860 if (AOP_TYPE (left) == AOP_CRY)
3866 if ((AOP_TYPE (right) == AOP_LIT) &&
3867 (AOP_TYPE (result) == AOP_CRY) &&
3868 (AOP_TYPE (left) != AOP_CRY))
3874 /* if left is same as result */
3875 if (sameRegs (AOP (result), AOP (left)))
3877 for (; size--; offset++)
3879 if (AOP_TYPE (right) == AOP_LIT)
3881 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3885 _MoveA (aopGet (AOP (left), offset, FALSE));
3886 emitcode ("or", "a,%s",
3887 aopGet (AOP (right), offset, FALSE));
3888 aopPut (AOP (result), "a", offset);
3893 if (AOP_TYPE (left) == AOP_ACC)
3894 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3897 _MoveA (aopGet (AOP (left), offset, FALSE));
3898 emitcode ("or", "a,%s",
3899 aopGet (AOP (right), offset, FALSE));
3900 aopPut (AOP (result), "a", offset);
3907 // left & result in different registers
3908 if (AOP_TYPE (result) == AOP_CRY)
3913 for (; (size--); offset++)
3916 // result = left & right
3917 if (AOP_TYPE (right) == AOP_LIT)
3919 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3921 aopPut (AOP (result),
3922 aopGet (AOP (left), offset, FALSE),
3927 // faster than result <- left, anl result,right
3928 // and better if result is SFR
3929 if (AOP_TYPE (left) == AOP_ACC)
3930 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3933 _MoveA (aopGet (AOP (left), offset, FALSE));
3934 emitcode ("or", "a,%s",
3935 aopGet (AOP (right), offset, FALSE));
3937 aopPut (AOP (result), "a", offset);
3938 /* PENDING: something weird is going on here. Add exception. */
3939 if (AOP_TYPE (result) == AOP_ACC)
3945 freeAsmop (left, NULL, ic);
3946 freeAsmop (right, NULL, ic);
3947 freeAsmop (result, NULL, ic);
3950 /*-----------------------------------------------------------------*/
3951 /* genXor - code for xclusive or */
3952 /*-----------------------------------------------------------------*/
3954 genXor (iCode * ic, iCode * ifx)
3956 operand *left, *right, *result;
3957 int size, offset = 0;
3958 unsigned long lit = 0L;
3960 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3962 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3964 /* if left is a literal & right is not then exchange them */
3965 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3966 AOP_NEEDSACC (left))
3968 operand *tmp = right;
3973 /* if result = right then exchange them */
3974 if (sameRegs (AOP (result), AOP (right)))
3976 operand *tmp = right;
3981 /* if right is bit then exchange them */
3982 if (AOP_TYPE (right) == AOP_CRY &&
3983 AOP_TYPE (left) != AOP_CRY)
3985 operand *tmp = right;
3989 if (AOP_TYPE (right) == AOP_LIT)
3990 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3992 size = AOP_SIZE (result);
3994 if (AOP_TYPE (left) == AOP_CRY)
4000 if ((AOP_TYPE (right) == AOP_LIT) &&
4001 (AOP_TYPE (result) == AOP_CRY) &&
4002 (AOP_TYPE (left) != AOP_CRY))
4008 /* if left is same as result */
4009 if (sameRegs (AOP (result), AOP (left)))
4011 for (; size--; offset++)
4013 if (AOP_TYPE (right) == AOP_LIT)
4015 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4019 _MoveA (aopGet (AOP (right), offset, FALSE));
4020 emitcode ("xor", "a,%s",
4021 aopGet (AOP (left), offset, FALSE));
4022 aopPut (AOP (result), "a", 0);
4027 if (AOP_TYPE (left) == AOP_ACC)
4028 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4031 _MoveA (aopGet (AOP (right), offset, FALSE));
4032 emitcode ("xor", "a,%s",
4033 aopGet (AOP (left), offset, FALSE));
4034 aopPut (AOP (result), "a", 0);
4041 // left & result in different registers
4042 if (AOP_TYPE (result) == AOP_CRY)
4047 for (; (size--); offset++)
4050 // result = left & right
4051 if (AOP_TYPE (right) == AOP_LIT)
4053 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4055 aopPut (AOP (result),
4056 aopGet (AOP (left), offset, FALSE),
4061 // faster than result <- left, anl result,right
4062 // and better if result is SFR
4063 if (AOP_TYPE (left) == AOP_ACC)
4064 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4067 _MoveA (aopGet (AOP (right), offset, FALSE));
4068 emitcode ("xor", "a,%s",
4069 aopGet (AOP (left), offset, FALSE));
4070 aopPut (AOP (result), "a", 0);
4072 aopPut (AOP (result), "a", offset);
4077 freeAsmop (left, NULL, ic);
4078 freeAsmop (right, NULL, ic);
4079 freeAsmop (result, NULL, ic);
4082 /*-----------------------------------------------------------------*/
4083 /* genInline - write the inline code out */
4084 /*-----------------------------------------------------------------*/
4086 genInline (iCode * ic)
4088 char *buffer, *bp, *bp1;
4090 inLine += (!options.asmpeep);
4092 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4093 strcpy (buffer, IC_INLINE (ic));
4095 /* emit each line as a code */
4120 /* emitcode("",buffer); */
4121 inLine -= (!options.asmpeep);
4124 /*-----------------------------------------------------------------*/
4125 /* genRRC - rotate right with carry */
4126 /*-----------------------------------------------------------------*/
4133 /*-----------------------------------------------------------------*/
4134 /* genRLC - generate code for rotate left with carry */
4135 /*-----------------------------------------------------------------*/
4142 /*-----------------------------------------------------------------*/
4143 /* shiftR2Left2Result - shift right two bytes from left to result */
4144 /*-----------------------------------------------------------------*/
4146 shiftR2Left2Result (operand * left, int offl,
4147 operand * result, int offr,
4148 int shCount, int sign)
4150 movLeft2Result (left, offl, result, offr, 0);
4151 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4159 /* if (AOP(result)->type == AOP_REG) { */
4162 symbol *tlbl, *tlbl1;
4165 tlbl = newiTempLabel (NULL);
4166 tlbl1 = newiTempLabel (NULL);
4168 /* Left is already in result - so now do the shift */
4171 emit2 ("ld a,!immedbyte+1", shCount);
4172 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4173 emitLabel (tlbl->key + 100);
4176 emitcode ("or", "a,a");
4180 l = aopGet (AOP (result), --offset, FALSE);
4181 emitcode ("rr", "%s", l);
4185 emitLabel (tlbl1->key + 100);
4186 emitcode ("dec", "a");
4187 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4192 /*-----------------------------------------------------------------*/
4193 /* shiftL2Left2Result - shift left two bytes from left to result */
4194 /*-----------------------------------------------------------------*/
4196 shiftL2Left2Result (operand * left, int offl,
4197 operand * result, int offr, int shCount)
4199 if (sameRegs (AOP (result), AOP (left)) &&
4200 ((offl + MSB16) == offr))
4206 /* Copy left into result */
4207 movLeft2Result (left, offl, result, offr, 0);
4208 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4210 /* PENDING: for now just see if it'll work. */
4211 /*if (AOP(result)->type == AOP_REG) { */
4215 symbol *tlbl, *tlbl1;
4218 tlbl = newiTempLabel (NULL);
4219 tlbl1 = newiTempLabel (NULL);
4221 /* Left is already in result - so now do the shift */
4224 emit2 ("ld a,!immedbyte+1", shCount);
4225 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4226 emitLabel (tlbl->key + 100);
4229 emitcode ("or", "a,a");
4232 l = aopGet (AOP (result), offset++, FALSE);
4233 emitcode ("rl", "%s", l);
4237 emitLabel (tlbl1->key + 100);
4238 emitcode ("dec", "a");
4239 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4244 /*-----------------------------------------------------------------*/
4245 /* AccRol - rotate left accumulator by known count */
4246 /*-----------------------------------------------------------------*/
4248 AccRol (int shCount)
4250 shCount &= 0x0007; // shCount : 0..7
4257 emitcode ("rl", "a");
4260 emitcode ("rl", "a");
4261 emitcode ("rl", "a");
4264 emitcode ("rl", "a");
4265 emitcode ("rl", "a");
4266 emitcode ("rl", "a");
4269 emitcode ("rl", "a");
4270 emitcode ("rl", "a");
4271 emitcode ("rl", "a");
4272 emitcode ("rl", "a");
4275 emitcode ("rr", "a");
4276 emitcode ("rr", "a");
4277 emitcode ("rr", "a");
4280 emitcode ("rr", "a");
4281 emitcode ("rr", "a");
4284 emitcode ("rr", "a");
4289 /*-----------------------------------------------------------------*/
4290 /* AccLsh - left shift accumulator by known count */
4291 /*-----------------------------------------------------------------*/
4293 AccLsh (int shCount)
4299 emitcode ("add", "a,a");
4301 else if (shCount == 2)
4303 emitcode ("add", "a,a");
4304 emitcode ("add", "a,a");
4308 /* rotate left accumulator */
4310 /* and kill the lower order bits */
4311 emit2 ("and a,!immedbyte", SLMask[shCount]);
4316 /*-----------------------------------------------------------------*/
4317 /* shiftL1Left2Result - shift left one byte from left to result */
4318 /*-----------------------------------------------------------------*/
4320 shiftL1Left2Result (operand * left, int offl,
4321 operand * result, int offr, int shCount)
4324 l = aopGet (AOP (left), offl, FALSE);
4326 /* shift left accumulator */
4328 aopPut (AOP (result), "a", offr);
4332 /*-----------------------------------------------------------------*/
4333 /* genlshTwo - left shift two bytes by known amount != 0 */
4334 /*-----------------------------------------------------------------*/
4336 genlshTwo (operand * result, operand * left, int shCount)
4338 int size = AOP_SIZE (result);
4340 wassert (size == 2);
4342 /* if shCount >= 8 */
4350 movLeft2Result (left, LSB, result, MSB16, 0);
4351 aopPut (AOP (result), zero, 0);
4352 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4356 movLeft2Result (left, LSB, result, MSB16, 0);
4357 aopPut (AOP (result), zero, 0);
4362 aopPut (AOP (result), zero, LSB);
4365 /* 1 <= shCount <= 7 */
4374 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4379 /*-----------------------------------------------------------------*/
4380 /* genlshOne - left shift a one byte quantity by known count */
4381 /*-----------------------------------------------------------------*/
4383 genlshOne (operand * result, operand * left, int shCount)
4385 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4388 /*-----------------------------------------------------------------*/
4389 /* genLeftShiftLiteral - left shifting by known count */
4390 /*-----------------------------------------------------------------*/
4392 genLeftShiftLiteral (operand * left,
4397 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4400 freeAsmop (right, NULL, ic);
4402 aopOp (left, ic, FALSE, FALSE);
4403 aopOp (result, ic, FALSE, FALSE);
4405 size = getSize (operandType (result));
4408 emitcode ("; shift left ", "result %d, left %d", size,
4412 /* I suppose that the left size >= result size */
4418 else if (shCount >= (size * 8))
4420 aopPut (AOP (result), zero, size);
4426 genlshOne (result, left, shCount);
4429 genlshTwo (result, left, shCount);
4438 freeAsmop (left, NULL, ic);
4439 freeAsmop (result, NULL, ic);
4442 /*-----------------------------------------------------------------*/
4443 /* genLeftShift - generates code for left shifting */
4444 /*-----------------------------------------------------------------*/
4446 genLeftShift (iCode * ic)
4450 symbol *tlbl, *tlbl1;
4451 operand *left, *right, *result;
4453 right = IC_RIGHT (ic);
4454 left = IC_LEFT (ic);
4455 result = IC_RESULT (ic);
4457 aopOp (right, ic, FALSE, FALSE);
4459 /* if the shift count is known then do it
4460 as efficiently as possible */
4461 if (AOP_TYPE (right) == AOP_LIT)
4463 genLeftShiftLiteral (left, right, result, ic);
4467 /* shift count is unknown then we have to form a loop get the loop
4468 count in B : Note: we take only the lower order byte since
4469 shifting more that 32 bits make no sense anyway, ( the largest
4470 size of an object can be only 32 bits ) */
4471 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4472 emitcode ("inc", "a");
4473 freeAsmop (right, NULL, ic);
4474 aopOp (left, ic, FALSE, FALSE);
4475 aopOp (result, ic, FALSE, FALSE);
4477 /* now move the left to the result if they are not the
4480 if (!sameRegs (AOP (left), AOP (result)))
4483 size = AOP_SIZE (result);
4487 l = aopGet (AOP (left), offset, FALSE);
4488 aopPut (AOP (result), l, offset);
4493 size = AOP_SIZE (result);
4497 l = aopGet (AOP (left), offset, FALSE);
4498 aopPut (AOP (result), l, offset);
4504 tlbl = newiTempLabel (NULL);
4505 size = AOP_SIZE (result);
4507 tlbl1 = newiTempLabel (NULL);
4509 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4510 emitLabel (tlbl->key + 100);
4511 l = aopGet (AOP (result), offset, FALSE);
4512 emitcode ("or", "a,a");
4515 l = aopGet (AOP (result), offset++, FALSE);
4516 emitcode ("rl", "%s", l);
4518 emitLabel (tlbl1->key + 100);
4519 emitcode ("dec", "a");
4520 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4522 freeAsmop (left, NULL, ic);
4523 freeAsmop (result, NULL, ic);
4526 /*-----------------------------------------------------------------*/
4527 /* genrshOne - left shift two bytes by known amount != 0 */
4528 /*-----------------------------------------------------------------*/
4530 genrshOne (operand * result, operand * left, int shCount)
4533 int size = AOP_SIZE (result);
4536 wassert (size == 1);
4537 wassert (shCount < 8);
4539 l = aopGet (AOP (left), 0, FALSE);
4540 if (AOP (result)->type == AOP_REG)
4542 aopPut (AOP (result), l, 0);
4543 l = aopGet (AOP (result), 0, FALSE);
4545 emitcode ("srl", "%s", l);
4552 emitcode ("srl", "a");
4554 aopPut (AOP (result), "a", 0);
4558 /*-----------------------------------------------------------------*/
4559 /* AccRsh - right shift accumulator by known count */
4560 /*-----------------------------------------------------------------*/
4562 AccRsh (int shCount)
4566 /* rotate right accumulator */
4567 AccRol (8 - shCount);
4568 /* and kill the higher order bits */
4569 emit2 ("and a,!immedbyte", SRMask[shCount]);
4573 /*-----------------------------------------------------------------*/
4574 /* shiftR1Left2Result - shift right one byte from left to result */
4575 /*-----------------------------------------------------------------*/
4577 shiftR1Left2Result (operand * left, int offl,
4578 operand * result, int offr,
4579 int shCount, int sign)
4581 _MoveA (aopGet (AOP (left), offl, FALSE));
4590 aopPut (AOP (result), "a", offr);
4593 /*-----------------------------------------------------------------*/
4594 /* genrshTwo - right shift two bytes by known amount != 0 */
4595 /*-----------------------------------------------------------------*/
4597 genrshTwo (operand * result, operand * left,
4598 int shCount, int sign)
4600 /* if shCount >= 8 */
4606 shiftR1Left2Result (left, MSB16, result, LSB,
4611 movLeft2Result (left, MSB16, result, LSB, sign);
4613 aopPut (AOP (result), zero, 1);
4615 /* 1 <= shCount <= 7 */
4618 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4622 /*-----------------------------------------------------------------*/
4623 /* genRightShiftLiteral - left shifting by known count */
4624 /*-----------------------------------------------------------------*/
4626 genRightShiftLiteral (operand * left,
4631 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4634 freeAsmop (right, NULL, ic);
4636 aopOp (left, ic, FALSE, FALSE);
4637 aopOp (result, ic, FALSE, FALSE);
4639 size = getSize (operandType (result));
4641 emitcode ("; shift right ", "result %d, left %d", size,
4644 /* I suppose that the left size >= result size */
4650 else if (shCount >= (size * 8))
4652 aopPut (AOP (result), zero, size);
4658 genrshOne (result, left, shCount);
4661 /* PENDING: sign support */
4662 genrshTwo (result, left, shCount, FALSE);
4671 freeAsmop (left, NULL, ic);
4672 freeAsmop (result, NULL, ic);
4675 /*-----------------------------------------------------------------*/
4676 /* genRightShift - generate code for right shifting */
4677 /*-----------------------------------------------------------------*/
4679 genRightShift (iCode * ic)
4681 operand *right, *left, *result;
4683 int size, offset, first = 1;
4687 symbol *tlbl, *tlbl1;
4689 /* if signed then we do it the hard way preserve the
4690 sign bit moving it inwards */
4691 retype = getSpec (operandType (IC_RESULT (ic)));
4693 is_signed = !SPEC_USIGN (retype);
4695 /* signed & unsigned types are treated the same : i.e. the
4696 signed is NOT propagated inwards : quoting from the
4697 ANSI - standard : "for E1 >> E2, is equivalent to division
4698 by 2**E2 if unsigned or if it has a non-negative value,
4699 otherwise the result is implementation defined ", MY definition
4700 is that the sign does not get propagated */
4702 right = IC_RIGHT (ic);
4703 left = IC_LEFT (ic);
4704 result = IC_RESULT (ic);
4706 aopOp (right, ic, FALSE, FALSE);
4708 /* if the shift count is known then do it
4709 as efficiently as possible */
4710 if (AOP_TYPE (right) == AOP_LIT)
4712 genRightShiftLiteral (left, right, result, ic);
4716 aopOp (left, ic, FALSE, FALSE);
4717 aopOp (result, ic, FALSE, FALSE);
4719 /* now move the left to the result if they are not the
4721 if (!sameRegs (AOP (left), AOP (result)) &&
4722 AOP_SIZE (result) > 1)
4725 size = AOP_SIZE (result);
4729 l = aopGet (AOP (left), offset, FALSE);
4730 aopPut (AOP (result), l, offset);
4735 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4736 emitcode ("inc", "a");
4737 freeAsmop (right, NULL, ic);
4739 tlbl = newiTempLabel (NULL);
4740 tlbl1 = newiTempLabel (NULL);
4741 size = AOP_SIZE (result);
4744 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4745 emitLabel (tlbl->key + 100);
4748 l = aopGet (AOP (result), offset--, FALSE);
4752 emitcode ("sra", "%s", l);
4754 emitcode ("srl", "%s", l);
4758 emitcode ("rr", "%s", l);
4760 emitLabel (tlbl1->key + 100);
4761 emitcode ("dec", "a");
4762 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4764 freeAsmop (left, NULL, ic);
4765 freeAsmop (result, NULL, ic);
4768 /*-----------------------------------------------------------------*/
4769 /* genGenPointerGet - get value from generic pointer space */
4770 /*-----------------------------------------------------------------*/
4772 genGenPointerGet (operand * left,
4773 operand * result, iCode * ic)
4776 sym_link *retype = getSpec (operandType (result));
4782 aopOp (left, ic, FALSE, FALSE);
4783 aopOp (result, ic, FALSE, FALSE);
4785 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4788 if (isPtrPair (AOP (left)))
4790 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4791 aopPut (AOP (result), buffer, 0);
4795 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4796 aopPut (AOP (result), "a", 0);
4798 freeAsmop (left, NULL, ic);
4802 /* For now we always load into IY */
4803 /* if this is remateriazable */
4804 fetchPair (pair, AOP (left));
4806 /* so iy now contains the address */
4807 freeAsmop (left, NULL, ic);
4809 /* if bit then unpack */
4810 if (IS_BITVAR (retype))
4816 size = AOP_SIZE (result);
4821 /* PENDING: make this better */
4822 if (!IS_GB && AOP (result)->type == AOP_REG)
4824 aopPut (AOP (result), "!*hl", offset++);
4828 emit2 ("ld a,!*pair", _pairs[pair].name);
4829 aopPut (AOP (result), "a", offset++);
4833 emit2 ("inc %s", _pairs[pair].name);
4834 _G.pairs[pair].offset++;
4840 freeAsmop (result, NULL, ic);
4843 /*-----------------------------------------------------------------*/
4844 /* genPointerGet - generate code for pointer get */
4845 /*-----------------------------------------------------------------*/
4847 genPointerGet (iCode * ic)
4849 operand *left, *result;
4850 sym_link *type, *etype;
4852 left = IC_LEFT (ic);
4853 result = IC_RESULT (ic);
4855 /* depending on the type of pointer we need to
4856 move it to the correct pointer register */
4857 type = operandType (left);
4858 etype = getSpec (type);
4860 genGenPointerGet (left, result, ic);
4864 isRegOrLit (asmop * aop)
4866 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4871 /*-----------------------------------------------------------------*/
4872 /* genGenPointerSet - stores the value into a pointer location */
4873 /*-----------------------------------------------------------------*/
4875 genGenPointerSet (operand * right,
4876 operand * result, iCode * ic)
4879 sym_link *retype = getSpec (operandType (right));
4880 PAIR_ID pairId = PAIR_HL;
4882 aopOp (result, ic, FALSE, FALSE);
4883 aopOp (right, ic, FALSE, FALSE);
4888 /* Handle the exceptions first */
4889 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
4892 const char *l = aopGet (AOP (right), 0, FALSE);
4893 const char *pair = getPairName (AOP (result));
4894 if (canAssignToPtr (l) && isPtr (pair))
4896 emit2 ("ld !*pair,%s", pair, l);
4901 emit2 ("ld !*pair,a", pair);
4906 /* if the operand is already in dptr
4907 then we do nothing else we move the value to dptr */
4908 if (AOP_TYPE (result) != AOP_STR)
4910 fetchPair (pairId, AOP (result));
4912 /* so hl know contains the address */
4913 freeAsmop (result, NULL, ic);
4915 /* if bit then unpack */
4916 if (IS_BITVAR (retype))
4922 size = AOP_SIZE (right);
4927 const char *l = aopGet (AOP (right), offset, FALSE);
4928 if (isRegOrLit (AOP (right)) && !IS_GB)
4930 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
4935 emit2 ("ld !*pair,a", _pairs[pairId].name);
4939 emitcode ("inc", _pairs[pairId].name);
4940 _G.pairs[pairId].offset++;
4946 freeAsmop (right, NULL, ic);
4949 /*-----------------------------------------------------------------*/
4950 /* genPointerSet - stores the value into a pointer location */
4951 /*-----------------------------------------------------------------*/
4953 genPointerSet (iCode * ic)
4955 operand *right, *result;
4956 sym_link *type, *etype;
4958 right = IC_RIGHT (ic);
4959 result = IC_RESULT (ic);
4961 /* depending on the type of pointer we need to
4962 move it to the correct pointer register */
4963 type = operandType (result);
4964 etype = getSpec (type);
4966 genGenPointerSet (right, result, ic);
4969 /*-----------------------------------------------------------------*/
4970 /* genIfx - generate code for Ifx statement */
4971 /*-----------------------------------------------------------------*/
4973 genIfx (iCode * ic, iCode * popIc)
4975 operand *cond = IC_COND (ic);
4978 aopOp (cond, ic, FALSE, TRUE);
4980 /* get the value into acc */
4981 if (AOP_TYPE (cond) != AOP_CRY)
4985 /* the result is now in the accumulator */
4986 freeAsmop (cond, NULL, ic);
4988 /* if there was something to be popped then do it */
4992 /* if the condition is a bit variable */
4993 if (isbit && IS_ITEMP (cond) &&
4995 genIfxJump (ic, SPIL_LOC (cond)->rname);
4996 else if (isbit && !IS_ITEMP (cond))
4997 genIfxJump (ic, OP_SYMBOL (cond)->rname);
4999 genIfxJump (ic, "a");
5004 /*-----------------------------------------------------------------*/
5005 /* genAddrOf - generates code for address of */
5006 /*-----------------------------------------------------------------*/
5008 genAddrOf (iCode * ic)
5010 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5012 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5014 /* if the operand is on the stack then we
5015 need to get the stack offset of this
5022 if (sym->stack <= 0)
5024 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5028 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5030 emitcode ("ld", "d,h");
5031 emitcode ("ld", "e,l");
5035 emit2 ("ld de,!hashedstr", sym->rname);
5037 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5038 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5045 /* if it has an offset then we need to compute it */
5047 emitcode ("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5049 emitcode ("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5050 emitcode ("add", "hl,sp");
5054 emitcode ("ld", "hl,#%s", sym->rname);
5056 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5057 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5059 freeAsmop (IC_RESULT (ic), NULL, ic);
5062 /*-----------------------------------------------------------------*/
5063 /* genAssign - generate code for assignment */
5064 /*-----------------------------------------------------------------*/
5066 genAssign (iCode * ic)
5068 operand *result, *right;
5070 unsigned long lit = 0L;
5072 result = IC_RESULT (ic);
5073 right = IC_RIGHT (ic);
5076 /* Dont bother assigning if they are the same */
5077 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5079 emitcode ("", "; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5084 aopOp (right, ic, FALSE, FALSE);
5085 aopOp (result, ic, TRUE, FALSE);
5087 /* if they are the same registers */
5088 if (sameRegs (AOP (right), AOP (result)))
5090 emitcode ("", "; (registers are the same)");
5094 /* if the result is a bit */
5095 if (AOP_TYPE (result) == AOP_CRY)
5101 size = AOP_SIZE (result);
5104 if (AOP_TYPE (right) == AOP_LIT)
5105 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5106 if (isPair (AOP (result)))
5108 fetchPair (getPairId (AOP (result)), AOP (right));
5110 else if ((size > 1) &&
5111 (AOP_TYPE (result) != AOP_REG) &&
5112 (AOP_TYPE (right) == AOP_LIT) &&
5113 !IS_FLOAT (operandType (right)) &&
5116 bool fXored = FALSE;
5118 /* Work from the top down.
5119 Done this way so that we can use the cached copy of 0
5120 in A for a fast clear */
5123 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5125 if (!fXored && size > 1)
5127 emitcode ("xor", "a,a");
5132 aopPut (AOP (result), "a", offset);
5136 aopPut (AOP (result), zero, offset);
5140 aopPut (AOP (result),
5141 aopGet (AOP (right), offset, FALSE),
5146 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5148 /* Special case. Load into a and d, then load out. */
5149 _MoveA (aopGet (AOP (right), 0, FALSE));
5150 emitcode ("ld", "e,%s", aopGet (AOP (right), 1, FALSE));
5151 aopPut (AOP (result), "a", 0);
5152 aopPut (AOP (result), "e", 1);
5158 /* PENDING: do this check better */
5159 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5161 _MoveA (aopGet (AOP (right), offset, FALSE));
5162 aopPut (AOP (result), "a", offset);
5165 aopPut (AOP (result),
5166 aopGet (AOP (right), offset, FALSE),
5173 freeAsmop (right, NULL, ic);
5174 freeAsmop (result, NULL, ic);
5177 /*-----------------------------------------------------------------*/
5178 /* genJumpTab - genrates code for jump table */
5179 /*-----------------------------------------------------------------*/
5181 genJumpTab (iCode * ic)
5186 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5187 /* get the condition into accumulator */
5188 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5190 emitcode ("push", "de");
5191 emitcode ("ld", "e,%s", l);
5192 emit2 ("ld d,!zero");
5193 jtab = newiTempLabel (NULL);
5195 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5196 emitcode ("add", "hl,de");
5197 emitcode ("add", "hl,de");
5198 emitcode ("add", "hl,de");
5199 freeAsmop (IC_JTCOND (ic), NULL, ic);
5201 emitcode ("pop", "de");
5203 emitLabel (jtab->key + 100);
5204 /* now generate the jump labels */
5205 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5206 jtab = setNextItem (IC_JTLABELS (ic)))
5207 emit2 ("jp !tlabel", jtab->key + 100);
5210 /*-----------------------------------------------------------------*/
5211 /* genCast - gen code for casting */
5212 /*-----------------------------------------------------------------*/
5214 genCast (iCode * ic)
5216 operand *result = IC_RESULT (ic);
5217 sym_link *ctype = operandType (IC_LEFT (ic));
5218 operand *right = IC_RIGHT (ic);
5221 /* if they are equivalent then do nothing */
5222 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5225 aopOp (right, ic, FALSE, FALSE);
5226 aopOp (result, ic, FALSE, FALSE);
5228 /* if the result is a bit */
5229 if (AOP_TYPE (result) == AOP_CRY)
5234 /* if they are the same size : or less */
5235 if (AOP_SIZE (result) <= AOP_SIZE (right))
5238 /* if they are in the same place */
5239 if (sameRegs (AOP (right), AOP (result)))
5242 /* if they in different places then copy */
5243 size = AOP_SIZE (result);
5247 aopPut (AOP (result),
5248 aopGet (AOP (right), offset, FALSE),
5255 /* PENDING: should be OK. */
5257 /* if the result is of type pointer */
5264 /* so we now know that the size of destination is greater
5265 than the size of the source */
5266 /* we move to result for the size of source */
5267 size = AOP_SIZE (right);
5271 aopPut (AOP (result),
5272 aopGet (AOP (right), offset, FALSE),
5277 /* now depending on the sign of the destination */
5278 size = AOP_SIZE (result) - AOP_SIZE (right);
5279 /* Unsigned or not an integral type - right fill with zeros */
5280 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5283 aopPut (AOP (result), zero, offset++);
5287 /* we need to extend the sign :{ */
5288 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5291 emitcode ("", "; genCast: sign extend untested.");
5292 emitcode ("rla", "");
5293 emitcode ("sbc", "a,a");
5295 aopPut (AOP (result), "a", offset++);
5299 freeAsmop (right, NULL, ic);
5300 freeAsmop (result, NULL, ic);
5303 /*-----------------------------------------------------------------*/
5304 /* genReceive - generate code for a receive iCode */
5305 /*-----------------------------------------------------------------*/
5307 genReceive (iCode * ic)
5309 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5310 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5311 IS_TRUE_SYMOP (IC_RESULT (ic))))
5321 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5322 size = AOP_SIZE(IC_RESULT(ic));
5324 for (i = 0; i < size; i++) {
5325 aopPut(AOP(IC_RESULT(ic)), _fReturn[_G.receiveOffset++], i);
5329 freeAsmop (IC_RESULT (ic), NULL, ic);
5332 /*-----------------------------------------------------------------*/
5333 /* genZ80Code - generate code for Z80 based controllers */
5334 /*-----------------------------------------------------------------*/
5336 genZ80Code (iCode * lic)
5344 _fReturn = _gbz80_return;
5345 _fTmp = _gbz80_return;
5349 _fReturn = _z80_return;
5350 _fTmp = _z80_return;
5352 tsprintf (zero, "!zero");
5354 lineHead = lineCurr = NULL;
5356 /* if debug information required */
5357 if (options.debug && currFunc)
5359 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5361 if (IS_STATIC (currFunc->etype))
5362 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
5364 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
5368 for (ic = lic; ic; ic = ic->next)
5371 if (cln != ic->lineno)
5376 emitcode ("", "C$%s$%d$%d$%d ==.",
5377 FileBaseName (ic->filename), ic->lineno,
5378 ic->level, ic->block);
5381 emitcode (";", "%s %d", ic->filename, ic->lineno);
5384 /* if the result is marked as
5385 spilt and rematerializable or code for
5386 this has already been generated then
5388 if (resultRemat (ic) || ic->generated)
5391 /* depending on the operation */
5395 emitcode ("", "; genNot");
5400 emitcode ("", "; genCpl");
5405 emitcode ("", "; genUminus");
5410 emitcode ("", "; genIpush");
5415 /* IPOP happens only when trying to restore a
5416 spilt live range, if there is an ifx statement
5417 following this pop then the if statement might
5418 be using some of the registers being popped which
5419 would destory the contents of the register so
5420 we need to check for this condition and handle it */
5422 ic->next->op == IFX &&
5423 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5425 emitcode ("", "; genIfx");
5426 genIfx (ic->next, ic);
5430 emitcode ("", "; genIpop");
5436 emitcode ("", "; genCall");
5441 emitcode ("", "; genPcall");
5446 emitcode ("", "; genFunction");
5451 emitcode ("", "; genEndFunction");
5452 genEndFunction (ic);
5456 emitcode ("", "; genRet");
5461 emitcode ("", "; genLabel");
5466 emitcode ("", "; genGoto");
5471 emitcode ("", "; genPlus");
5476 emitcode ("", "; genMinus");
5481 emitcode ("", "; genMult");
5486 emitcode ("", "; genDiv");
5491 emitcode ("", "; genMod");
5496 emitcode ("", "; genCmpGt");
5497 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5501 emitcode ("", "; genCmpLt");
5502 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5509 /* note these two are xlated by algebraic equivalence
5510 during parsing SDCC.y */
5511 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5512 "got '>=' or '<=' shouldn't have come here");
5516 emitcode ("", "; genCmpEq");
5517 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5521 emitcode ("", "; genAndOp");
5526 emitcode ("", "; genOrOp");
5531 emitcode ("", "; genXor");
5532 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5536 emitcode ("", "; genOr");
5537 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5541 emitcode ("", "; genAnd");
5542 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5546 emitcode ("", "; genInline");
5551 emitcode ("", "; genRRC");
5556 emitcode ("", "; genRLC");
5561 emitcode ("", "; genHBIT");
5565 emitcode ("", "; genLeftShift");
5570 emitcode ("", "; genRightShift");
5574 case GET_VALUE_AT_ADDRESS:
5575 emitcode ("", "; genPointerGet");
5581 if (POINTER_SET (ic))
5583 emitcode ("", "; genAssign (pointer)");
5588 emitcode ("", "; genAssign");
5594 emitcode ("", "; genIfx");
5599 emitcode ("", "; genAddrOf");
5604 emitcode ("", "; genJumpTab");
5609 emitcode ("", "; genCast");
5614 emitcode ("", "; genReceive");
5619 emitcode ("", "; addSet");
5620 addSet (&sendSet, ic);
5625 /* piCode(ic,stdout); */
5631 /* now we are ready to call the
5632 peep hole optimizer */
5633 if (!options.nopeep)
5634 peepHole (&lineHead);
5636 /* This is unfortunate */
5637 /* now do the actual printing */
5639 FILE *fp = codeOutFile;
5640 if (isInHome () && codeOutFile == code->oFile)
5641 codeOutFile = home->oFile;
5642 printLine (lineHead, codeOutFile);
5643 if (_G.flush_statics)
5646 _G.flush_statics = 0;