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 */
69 static char *_z80_return[] =
71 static char *_gbz80_return[] =
73 static char **_fReturn;
79 static char *accUse[] =
81 static char *hlUse[] =
90 extern FILE *codeOutFile;
130 "iy", "iy.l?", "iy.h?"
134 "ix", "ix.l?", "ix.h?"
138 #define RESULTONSTACK(x) \
139 (IC_RESULT(x) && IC_RESULT(x)->aop && \
140 IC_RESULT(x)->aop->type == AOP_STK )
142 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
143 #define CLRC emitcode("xor","a,a");
145 lineNode *lineHead = NULL;
146 lineNode *lineCurr = NULL;
148 static const unsigned char SLMask[] =
149 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
150 static const unsigned char SRMask[] =
151 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
187 static char *aopGet (asmop * aop, int offset, bool bit16);
192 /* Clean up the line so that it is 'prettier' */
193 if (strchr (buf, ':'))
195 /* Is a label - cant do anything */
198 /* Change the first (and probably only) ' ' to a tab so
213 emit2 (const char *szFormat,...)
218 va_start (ap, szFormat);
220 tvsprintf (buffer, szFormat, ap);
223 lineCurr = (lineCurr ?
224 connectLine (lineCurr, newLineNode (buffer)) :
225 (lineHead = newLineNode (buffer)));
227 lineCurr->isInline = inLine;
228 lineCurr->isDebug = debugLine;
231 /*-----------------------------------------------------------------*/
232 /* emitcode - writes the code into a file : for now it is simple */
233 /*-----------------------------------------------------------------*/
235 emitcode (const char *inst, const char *fmt,...)
238 char lb[INITIAL_INLINEASM];
245 sprintf (lb, "%s\t", inst);
246 vsprintf (lb + (strlen (lb)), fmt, ap);
249 vsprintf (lb, fmt, ap);
251 while (isspace (*lbp))
255 lineCurr = (lineCurr ?
256 connectLine (lineCurr, newLineNode (lb)) :
257 (lineHead = newLineNode (lb)));
258 lineCurr->isInline = inLine;
259 lineCurr->isDebug = debugLine;
276 emitcode("ld", "sp,ix");
277 emitcode("pop", "ix");
278 emitcode("pop", "de");
284 getPairName (asmop * aop)
286 if (aop->type == AOP_REG)
288 switch (aop->aopu.aop_reg[0]->rIdx)
301 else if (aop->type == AOP_STR)
303 switch (*aop->aopu.aop_str[0])
321 getPairId (asmop * aop)
325 if (aop->type == AOP_REG)
327 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
331 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
335 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
340 if (aop->type == AOP_STR)
342 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
346 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
350 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
359 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
363 return (getPairId (aop) != PAIR_INVALID);
367 isPtrPair (asmop * aop)
369 PAIR_ID pairId = getPairId (aop);
380 /** Push a register pair onto the stack */
382 genPairPush (asmop * aop)
384 emitcode ("push", "%s", getPairName (aop));
388 /*-----------------------------------------------------------------*/
389 /* newAsmop - creates a new asmOp */
390 /*-----------------------------------------------------------------*/
392 newAsmop (short type)
396 aop = Safe_calloc (1, sizeof (asmop));
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol */
403 /*-----------------------------------------------------------------*/
405 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
412 wassert (sym->etype);
414 space = SPEC_OCLS (sym->etype);
416 /* if already has one */
420 /* Assign depending on the storage class */
421 if (sym->onStack || sym->iaccess)
423 emitcode ("", "; AOP_STK for %s", sym->rname);
424 sym->aop = aop = newAsmop (AOP_STK);
425 aop->size = getSize (sym->type);
426 aop->aopu.aop_stk = sym->stack;
430 /* special case for a function */
431 if (IS_FUNC (sym->type))
433 sym->aop = aop = newAsmop (AOP_IMMD);
434 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
435 strcpy (aop->aopu.aop_immd, sym->rname);
442 /* if it is in direct space */
443 if (IN_REGSP (space) && !requires_a)
445 sym->aop = aop = newAsmop (AOP_SFR);
446 aop->aopu.aop_dir = sym->rname;
447 aop->size = getSize (sym->type);
448 emitcode ("", "; AOP_SFR for %s", sym->rname);
453 /* only remaining is far space */
454 /* in which case DPTR gets the address */
457 emitcode ("", "; AOP_HL for %s", sym->rname);
458 sym->aop = aop = newAsmop (AOP_HL);
462 sym->aop = aop = newAsmop (AOP_IY);
464 aop->size = getSize (sym->type);
465 aop->aopu.aop_dir = sym->rname;
467 /* if it is in code space */
468 if (IN_CODESPACE (space))
474 /*-----------------------------------------------------------------*/
475 /* aopForRemat - rematerialzes an object */
476 /*-----------------------------------------------------------------*/
478 aopForRemat (symbol * sym)
481 iCode *ic = sym->rematiCode;
482 asmop *aop = newAsmop (AOP_IMMD);
486 /* if plus or minus print the right hand side */
487 if (ic->op == '+' || ic->op == '-')
489 /* PENDING: for re-target */
490 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
493 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
496 /* we reached the end */
497 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
501 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
502 strcpy (aop->aopu.aop_immd, buffer);
506 /*-----------------------------------------------------------------*/
507 /* regsInCommon - two operands have some registers in common */
508 /*-----------------------------------------------------------------*/
510 regsInCommon (operand * op1, operand * op2)
515 /* if they have registers in common */
516 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
519 sym1 = OP_SYMBOL (op1);
520 sym2 = OP_SYMBOL (op2);
522 if (sym1->nRegs == 0 || sym2->nRegs == 0)
525 for (i = 0; i < sym1->nRegs; i++)
531 for (j = 0; j < sym2->nRegs; j++)
536 if (sym2->regs[j] == sym1->regs[i])
544 /*-----------------------------------------------------------------*/
545 /* operandsEqu - equivalent */
546 /*-----------------------------------------------------------------*/
548 operandsEqu (operand * op1, operand * op2)
552 /* if they not symbols */
553 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
556 sym1 = OP_SYMBOL (op1);
557 sym2 = OP_SYMBOL (op2);
559 /* if both are itemps & one is spilt
560 and the other is not then false */
561 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
562 sym1->isspilt != sym2->isspilt)
565 /* if they are the same */
569 if (strcmp (sym1->rname, sym2->rname) == 0)
573 /* if left is a tmp & right is not */
574 if (IS_ITEMP (op1) &&
577 (sym1->usl.spillLoc == sym2))
580 if (IS_ITEMP (op2) &&
584 (sym2->usl.spillLoc == sym1))
590 /*-----------------------------------------------------------------*/
591 /* sameRegs - two asmops have the same registers */
592 /*-----------------------------------------------------------------*/
594 sameRegs (asmop * aop1, asmop * aop2)
598 if (aop1->type == AOP_SFR ||
599 aop2->type == AOP_SFR)
605 if (aop1->type != AOP_REG ||
606 aop2->type != AOP_REG)
609 if (aop1->size != aop2->size)
612 for (i = 0; i < aop1->size; i++)
613 if (aop1->aopu.aop_reg[i] !=
614 aop2->aopu.aop_reg[i])
620 /*-----------------------------------------------------------------*/
621 /* aopOp - allocates an asmop for an operand : */
622 /*-----------------------------------------------------------------*/
624 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
633 /* if this a literal */
634 if (IS_OP_LITERAL (op))
636 op->aop = aop = newAsmop (AOP_LIT);
637 aop->aopu.aop_lit = op->operand.valOperand;
638 aop->size = getSize (operandType (op));
642 /* if already has a asmop then continue */
646 /* if the underlying symbol has a aop */
647 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
649 op->aop = OP_SYMBOL (op)->aop;
653 /* if this is a true symbol */
654 if (IS_TRUE_SYMOP (op))
656 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
660 /* this is a temporary : this has
666 e) can be a return use only */
668 sym = OP_SYMBOL (op);
670 /* if the type is a conditional */
671 if (sym->regType == REG_CND)
673 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
678 /* if it is spilt then two situations
680 b) has a spill location */
681 if (sym->isspilt || sym->nRegs == 0)
683 /* rematerialize it NOW */
686 sym->aop = op->aop = aop =
688 aop->size = getSize (sym->type);
695 if (sym->accuse == ACCUSE_A)
697 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
698 aop->size = getSize (sym->type);
699 for (i = 0; i < 2; i++)
700 aop->aopu.aop_str[i] = accUse[i];
702 else if (sym->accuse == ACCUSE_HL)
705 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
706 aop->size = getSize (sym->type);
707 for (i = 0; i < 2; i++)
708 aop->aopu.aop_str[i] = hlUse[i];
718 aop = op->aop = sym->aop = newAsmop (AOP_STR);
719 aop->size = getSize (sym->type);
720 for (i = 0; i < 4; i++)
721 aop->aopu.aop_str[i] = _fReturn[i];
725 /* else spill location */
726 sym->aop = op->aop = aop =
727 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
728 aop->size = getSize (sym->type);
732 /* must be in a register */
733 sym->aop = op->aop = aop = newAsmop (AOP_REG);
734 aop->size = sym->nRegs;
735 for (i = 0; i < sym->nRegs; i++)
736 aop->aopu.aop_reg[i] = sym->regs[i];
739 /*-----------------------------------------------------------------*/
740 /* freeAsmop - free up the asmop given to an operand */
741 /*----------------------------------------------------------------*/
743 freeAsmop (operand * op, asmop * aaop, iCode * ic)
761 /* all other cases just dealloc */
767 OP_SYMBOL (op)->aop = NULL;
768 /* if the symbol has a spill */
770 SPIL_LOC (op)->aop = NULL;
776 isLitWord (asmop * aop)
778 /* if (aop->size != 2)
791 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
797 if (aop->size != 2 && aop->type != AOP_HL)
800 /* depending on type */
806 /* PENDING: for re-target */
808 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
810 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
811 rs = Safe_calloc (1, strlen (s) + 1);
816 value *val = aop->aopu.aop_lit;
817 /* if it is a float then it gets tricky */
818 /* otherwise it is fairly simple */
819 if (!IS_FLOAT (val->type))
821 unsigned long v = (unsigned long) floatFromVal (val);
827 tsprintf (buffer, "!immedword", v);
829 tsprintf (buffer, "!constword", v);
830 rs = Safe_calloc (1, strlen (buffer) + 1);
831 return strcpy (rs, buffer);
837 convertFloat (&f, floatFromVal (val));
839 tsprintf (buffer, "!immedword", f.w[offset / 2]);
841 tsprintf (buffer, "!constword", f.w[offset / 2]);
842 rs = Safe_calloc (1, strlen (buffer) + 1);
843 return strcpy (rs, buffer);
852 aopGetWord (asmop * aop, int offset)
854 return aopGetLitWordLong (aop, offset, TRUE);
858 isPtr (const char *s)
860 if (!strcmp (s, "hl"))
862 if (!strcmp (s, "ix"))
864 if (!strcmp (s, "iy"))
870 adjustPair (const char *pair, int *pold, int new)
876 emitcode ("inc", "%s", pair);
881 emitcode ("dec", "%s", pair);
887 spillPair (PAIR_ID pairId)
889 _G.pairs[pairId].last_type = AOP_INVALID;
890 _G.pairs[pairId].lit = NULL;
901 requiresHL (asmop * aop)
915 fetchLitSpecial (asmop * aop, bool negate, bool xor)
918 value *val = aop->aopu.aop_lit;
920 wassert (aop->type == AOP_LIT);
921 wassert (!IS_FLOAT (val->type));
923 v = (unsigned long) floatFromVal (val);
931 tsprintf (buffer, "!immedword", v);
932 return gc_strdup (buffer);
936 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
939 const char *pair = _pairs[pairId].name;
940 l = aopGetLitWordLong (left, 0, FALSE);
945 if (pairId == PAIR_HL || pairId == PAIR_IY)
947 if (_G.pairs[pairId].last_type == left->type)
949 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
951 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
953 adjustPair (pair, &_G.pairs[pairId].offset, offset);
956 if (pairId == PAIR_IY && abs (offset) < 127)
963 _G.pairs[pairId].last_type = left->type;
964 _G.pairs[pairId].lit = gc_strdup (l);
965 _G.pairs[pairId].offset = offset;
967 if (IS_GB && pairId == PAIR_DE && 0)
969 if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
971 if (abs (_G.pairs[pairId].offset - offset) < 3)
973 adjustPair (pair, &_G.pairs[pairId].offset, offset);
977 _G.pairs[pairId].last_type = left->type;
978 _G.pairs[pairId].lit = gc_strdup (l);
979 _G.pairs[pairId].offset = offset;
981 /* Both a lit on the right and a true symbol on the left */
983 emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
985 emit2 ("ld %s,!hashedstr", pair, l);
989 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
991 /* if this is remateriazable */
992 if (isLitWord (aop)) {
993 fetchLitPair (pairId, aop, offset);
996 /* we need to get it byte by byte */
997 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
998 aopGet (aop, offset, FALSE);
1001 emit2 ("ld l,!*hl");
1002 emit2 ("ld h,!immedbyte", 0);
1006 emit2 ("ld h,!*hl");
1010 emit2 ("; WARNING: mlh woosed out. This code is invalid.");
1013 else if (IS_Z80 && aop->type == AOP_IY) {
1014 /* Instead of fetching relative to IY, just grab directly
1015 from the address IY refers to */
1016 char *l = aopGetLitWordLong (aop, offset, FALSE);
1018 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1020 if (aop->size < 2) {
1021 emit2("ld %s,!zero", _pairs[pairId].h);
1025 emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1026 emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1028 /* PENDING: check? */
1029 if (pairId == PAIR_HL)
1030 spillPair (PAIR_HL);
1035 fetchPair (PAIR_ID pairId, asmop * aop)
1037 fetchPairLong (pairId, aop, 0);
1041 fetchHL (asmop * aop)
1043 fetchPair (PAIR_HL, aop);
1047 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1049 assert (pairId == PAIR_HL || pairId == PAIR_IY);
1054 fetchLitPair (pairId, aop, 0);
1057 fetchLitPair (pairId, aop, offset);
1058 _G.pairs[pairId].offset = offset;
1062 /* Doesnt include _G.stack.pushed */
1063 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1064 if (aop->aopu.aop_stk > 0)
1066 abso += _G.stack.param_offset;
1068 assert (pairId == PAIR_HL);
1069 /* In some cases we can still inc or dec hl */
1070 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1072 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1076 emit2 ("!ldahlsp", abso + _G.stack.pushed);
1078 _G.pairs[pairId].offset = abso;
1084 _G.pairs[pairId].last_type = aop->type;
1090 emit2 ("!tlabeldef", key);
1094 /*-----------------------------------------------------------------*/
1095 /* aopGet - for fetching value of the aop */
1096 /*-----------------------------------------------------------------*/
1098 aopGet (asmop * aop, int offset, bool bit16)
1103 /* offset is greater than size then zero */
1104 /* PENDING: this seems a bit screwed in some pointer cases. */
1105 if (offset > (aop->size - 1) &&
1106 aop->type != AOP_LIT)
1109 /* depending on type */
1113 /* PENDING: re-target */
1115 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1120 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1123 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1126 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1131 rs = Safe_calloc (1, strlen (s) + 1);
1137 emitcode ("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1139 rs = Safe_calloc (1, strlen (s) + 1);
1145 emitcode ("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1147 rs = Safe_calloc (1, strlen (s) + 1);
1152 return aop->aopu.aop_reg[offset]->name;
1156 setupPair (PAIR_HL, aop, offset);
1157 tsprintf (s, "!*hl");
1158 return gc_strdup (s);
1162 setupPair (PAIR_IY, aop, offset);
1163 tsprintf (s, "!*iyx", offset);
1164 rs = Safe_calloc (1, strlen (s) + 1);
1171 setupPair (PAIR_HL, aop, offset);
1172 tsprintf (s, "!*hl");
1176 if (aop->aopu.aop_stk >= 0)
1177 offset += _G.stack.param_offset;
1178 tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1180 rs = Safe_calloc (1, strlen (s) + 1);
1195 wassert (offset < 2);
1196 return aop->aopu.aop_str[offset];
1199 return aopLiteral (aop->aopu.aop_lit, offset);
1203 return aop->aopu.aop_str[offset];
1207 wassertl (0, "aopget got unsupported aop->type");
1212 isRegString (const char *s)
1214 if (!strcmp (s, "b") ||
1226 isConstant (const char *s)
1228 /* This is a bit of a hack... */
1229 return (*s == '#' || *s == '$');
1233 canAssignToPtr (const char *s)
1235 if (isRegString (s))
1242 /*-----------------------------------------------------------------*/
1243 /* aopPut - puts a string for a aop */
1244 /*-----------------------------------------------------------------*/
1246 aopPut (asmop * aop, const char *s, int offset)
1248 if (aop->size && offset > (aop->size - 1))
1250 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1251 "aopPut got offset > aop->size");
1255 /* will assign value to value */
1256 /* depending on where it is ofcourse */
1262 if (strcmp (s, "a"))
1263 emitcode ("ld", "a,%s", s);
1264 emitcode ("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1269 if (strcmp (s, "a"))
1270 emitcode ("ld", "a,%s", s);
1271 emitcode ("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1275 if (!strcmp (s, "!*hl"))
1276 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1279 aop->aopu.aop_reg[offset]->name, s);
1284 setupPair (PAIR_IY, aop, offset);
1285 if (!canAssignToPtr (s))
1287 emit2 ("ld a,%s", s);
1288 emit2 ("ld !*iyx,a", offset);
1291 emit2 ("ld !*iyx,%s", offset, s);
1296 /* PENDING: for re-target */
1297 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1299 emit2 ("ld a,!*hl");
1302 setupPair (PAIR_HL, aop, offset);
1304 emit2 ("ld !*hl,%s", s);
1310 /* PENDING: re-target */
1311 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1313 emit2 ("ld a,!*hl");
1316 setupPair (PAIR_HL, aop, offset);
1317 if (!canAssignToPtr (s))
1319 emit2 ("ld a,%s", s);
1320 emit2 ("ld !*hl,a");
1323 emit2 ("ld !*hl,%s", s);
1327 if (aop->aopu.aop_stk >= 0)
1328 offset += _G.stack.param_offset;
1329 if (!canAssignToPtr (s))
1331 emit2 ("ld a,%s", s);
1332 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1335 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1340 /* if bit variable */
1341 if (!aop->aopu.aop_dir)
1348 /* In bit space but not in C - cant happen */
1355 if (strcmp (aop->aopu.aop_str[offset], s))
1357 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1363 if (!offset && (strcmp (s, "acc") == 0))
1368 emitcode ("", "; Error aopPut AOP_ACC");
1372 if (strcmp (aop->aopu.aop_str[offset], s))
1373 emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1378 wassert (offset < 2);
1379 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1383 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1384 "aopPut got unsupported aop->type");
1389 #define AOP(op) op->aop
1390 #define AOP_TYPE(op) AOP(op)->type
1391 #define AOP_SIZE(op) AOP(op)->size
1392 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1395 commitPair (asmop * aop, PAIR_ID id)
1397 if (id == PAIR_HL && requiresHL (aop))
1401 aopPut (aop, "a", 0);
1402 aopPut (aop, "d", 1);
1406 aopPut (aop, _pairs[id].l, 0);
1407 aopPut (aop, _pairs[id].h, 1);
1411 /*-----------------------------------------------------------------*/
1412 /* getDataSize - get the operand data size */
1413 /*-----------------------------------------------------------------*/
1415 getDataSize (operand * op)
1418 size = AOP_SIZE (op);
1427 /*-----------------------------------------------------------------*/
1428 /* movLeft2Result - move byte from left to result */
1429 /*-----------------------------------------------------------------*/
1431 movLeft2Result (operand * left, int offl,
1432 operand * result, int offr, int sign)
1435 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1437 l = aopGet (AOP (left), offl, FALSE);
1441 aopPut (AOP (result), l, offr);
1451 /** Put Acc into a register set
1454 outAcc (operand * result)
1457 size = getDataSize (result);
1460 aopPut (AOP (result), "a", 0);
1463 /* unsigned or positive */
1466 aopPut (AOP (result), zero, offset++);
1471 /** Take the value in carry and put it into a register
1474 outBitCLong (operand * result, bool swap_sense)
1476 /* if the result is bit */
1477 if (AOP_TYPE (result) == AOP_CRY)
1479 emitcode ("", "; Note: outBitC form 1");
1480 aopPut (AOP (result), "blah", 0);
1484 emit2 ("ld a,!zero");
1487 emit2 ("xor a,!immedbyte", 1);
1493 outBitC (operand * result)
1495 outBitCLong (result, FALSE);
1498 /*-----------------------------------------------------------------*/
1499 /* toBoolean - emit code for orl a,operator(sizeop) */
1500 /*-----------------------------------------------------------------*/
1502 toBoolean (operand * oper)
1504 int size = AOP_SIZE (oper);
1508 emitcode ("ld", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1511 emitcode ("or", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1515 if (AOP (oper)->type != AOP_ACC)
1518 emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
1523 /*-----------------------------------------------------------------*/
1524 /* genNot - generate code for ! operation */
1525 /*-----------------------------------------------------------------*/
1529 sym_link *optype = operandType (IC_LEFT (ic));
1531 /* assign asmOps to operand & result */
1532 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1533 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1535 /* if in bit space then a special case */
1536 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1541 /* if type float then do float */
1542 if (IS_FLOAT (optype))
1547 toBoolean (IC_LEFT (ic));
1552 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1553 emit2 ("sub a,!one");
1554 outBitC (IC_RESULT (ic));
1556 /* release the aops */
1557 freeAsmop (IC_LEFT (ic), NULL, ic);
1558 freeAsmop (IC_RESULT (ic), NULL, ic);
1561 /*-----------------------------------------------------------------*/
1562 /* genCpl - generate code for complement */
1563 /*-----------------------------------------------------------------*/
1571 /* assign asmOps to operand & result */
1572 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1573 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1575 /* if both are in bit space then
1577 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1578 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1583 size = AOP_SIZE (IC_RESULT (ic));
1586 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1588 emitcode ("cpl", "");
1589 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1592 /* release the aops */
1593 freeAsmop (IC_LEFT (ic), NULL, ic);
1594 freeAsmop (IC_RESULT (ic), NULL, ic);
1597 /*-----------------------------------------------------------------*/
1598 /* genUminus - unary minus code generation */
1599 /*-----------------------------------------------------------------*/
1601 genUminus (iCode * ic)
1604 sym_link *optype, *rtype;
1607 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1608 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1610 /* if both in bit space then special
1612 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1613 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1619 optype = operandType (IC_LEFT (ic));
1620 rtype = operandType (IC_RESULT (ic));
1622 /* if float then do float stuff */
1623 if (IS_FLOAT (optype))
1629 /* otherwise subtract from zero */
1630 size = AOP_SIZE (IC_LEFT (ic));
1635 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1636 emit2 ("ld a,!zero");
1637 emit2 ("sbc a,%s", l);
1638 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1641 /* if any remaining bytes in the result */
1642 /* we just need to propagate the sign */
1643 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1648 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1652 /* release the aops */
1653 freeAsmop (IC_LEFT (ic), NULL, ic);
1654 freeAsmop (IC_RESULT (ic), NULL, ic);
1658 _push (PAIR_ID pairId)
1660 emit2 ("push %s", _pairs[pairId].name);
1661 _G.stack.pushed += 2;
1665 _pop (PAIR_ID pairId)
1667 emit2 ("pop %s", _pairs[pairId].name);
1668 _G.stack.pushed -= 2;
1672 /*-----------------------------------------------------------------*/
1673 /* assignResultValue - */
1674 /*-----------------------------------------------------------------*/
1676 assignResultValue (operand * oper)
1678 int size = AOP_SIZE (oper);
1681 wassert (size <= 4);
1682 topInA = requiresHL (AOP (oper));
1686 wassert (size <= 2);
1688 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1690 /* We do it the hard way here. */
1692 aopPut (AOP (oper), _fReturn[0], 0);
1693 aopPut (AOP (oper), _fReturn[1], 1);
1694 emitcode ("pop", "de");
1695 _G.stack.pushed -= 2;
1696 aopPut (AOP (oper), _fReturn[0], 2);
1697 aopPut (AOP (oper), _fReturn[1], 3);
1703 aopPut (AOP (oper), _fReturn[size], size);
1708 /*-----------------------------------------------------------------*/
1709 /* genIpush - genrate code for pushing this gets a little complex */
1710 /*-----------------------------------------------------------------*/
1712 genIpush (iCode * ic)
1714 int size, offset = 0;
1717 /* if this is not a parm push : ie. it is spill push
1718 and spill push is always done on the local stack */
1721 /* and the item is spilt then do nothing */
1722 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1725 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1726 size = AOP_SIZE (IC_LEFT (ic));
1727 /* push it on the stack */
1728 if (isPair (AOP (IC_LEFT (ic))))
1730 emitcode ("push", getPairName (AOP (IC_LEFT (ic))));
1731 _G.stack.pushed += 2;
1738 /* Simple for now - load into A and PUSH AF */
1739 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1741 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1743 emit2 ("ld a,(%s)", l);
1747 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1748 emit2 ("ld a,%s", l);
1758 /* Hmmm... what about saving the currently used registers
1761 /* then do the push */
1762 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764 size = AOP_SIZE (IC_LEFT (ic));
1766 if (isPair (AOP (IC_LEFT (ic))))
1768 _G.stack.pushed += 2;
1769 emitcode ("push", "%s", getPairName (AOP (IC_LEFT (ic))));
1775 fetchHL (AOP (IC_LEFT (ic)));
1776 emitcode ("push", "hl");
1777 spillPair (PAIR_HL);
1778 _G.stack.pushed += 2;
1783 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1784 emitcode ("push", "hl");
1785 spillPair (PAIR_HL);
1786 _G.stack.pushed += 2;
1787 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1788 emitcode ("push", "hl");
1789 spillPair (PAIR_HL);
1790 _G.stack.pushed += 2;
1796 if (AOP (IC_LEFT (ic))->type == AOP_IY)
1798 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1800 emit2 ("ld a,(%s)", l);
1804 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1805 emit2 ("ld a,%s", l);
1807 emitcode ("push", "af");
1808 emitcode ("inc", "sp");
1813 freeAsmop (IC_LEFT (ic), NULL, ic);
1816 /*-----------------------------------------------------------------*/
1817 /* genIpop - recover the registers: can happen only for spilling */
1818 /*-----------------------------------------------------------------*/
1820 genIpop (iCode * ic)
1825 /* if the temp was not pushed then */
1826 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1829 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1830 size = AOP_SIZE (IC_LEFT (ic));
1831 offset = (size - 1);
1832 if (isPair (AOP (IC_LEFT (ic))))
1834 emitcode ("pop", getPairName (AOP (IC_LEFT (ic))));
1840 emitcode ("dec", "sp");
1841 emitcode ("pop", "hl");
1842 spillPair (PAIR_HL);
1843 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1847 freeAsmop (IC_LEFT (ic), NULL, ic);
1851 _isPairUsed (iCode * ic, PAIR_ID pairId)
1857 if (bitVectBitValue (ic->rMask, D_IDX))
1859 if (bitVectBitValue (ic->rMask, E_IDX))
1869 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1873 symbol *sym = OP_SYMBOL (op);
1875 if (sym->isspilt || sym->nRegs == 0)
1878 aopOp (op, ic, FALSE, FALSE);
1881 if (aop->type == AOP_REG)
1884 for (i = 0; i < aop->size; i++)
1886 if (pairId == PAIR_DE)
1888 emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1889 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
1891 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
1901 freeAsmop (IC_LEFT (ic), NULL, ic);
1905 /* This is quite unfortunate */
1907 setArea (int inHome)
1910 static int lastArea = 0;
1912 if (_G.in_home != inHome) {
1914 const char *sz = port->mem.code_name;
1915 port->mem.code_name = "HOME";
1916 emit2("!area", CODE_NAME);
1917 port->mem.code_name = sz;
1920 emit2("!area", CODE_NAME); */
1921 _G.in_home = inHome;
1931 /** Emit the code for a call statement
1934 emitCall (iCode * ic, bool ispcall)
1937 sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
1939 /* if caller saves & we have not saved then */
1945 /* if send set is not empty then assign */
1950 int n = elementsInSet (sendSet);
1951 if (IS_Z80 && n == 2 && _isPairUsed (ic, PAIR_DE))
1953 /* Only push de if it is used and if it's not used
1954 in the return value */
1955 /* Panic if partly used */
1956 if (_opUsesPair (IC_RESULT (ic), ic, PAIR_DE) == 1)
1958 emit2 ("; Warning: de crossover");
1960 else if (!_opUsesPair (IC_RESULT (ic), ic, PAIR_DE))
1968 if (IS_Z80 && n == 2)
1970 /* Want to load HL first, then DE as HL may = DE */
1971 sic = setFirstItem (sendSet);
1972 sic = setNextItem (sendSet);
1973 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1974 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
1976 freeAsmop (IC_LEFT (sic), NULL, sic);
1977 sic = setFirstItem (sendSet);
1978 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1979 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
1981 freeAsmop (IC_LEFT (sic), NULL, sic);
1985 for (sic = setFirstItem (sendSet); sic;
1986 sic = setNextItem (sendSet))
1989 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1990 size = AOP_SIZE (IC_LEFT (sic));
1991 wassert (size <= 2);
1992 /* Always send in pairs */
1996 if (IS_Z80 && n == 1)
1997 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
1999 fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
2002 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2005 /* Send set too big */
2009 freeAsmop (IC_LEFT (sic), NULL, sic);
2020 if (IS_BANKEDCALL (detype))
2022 werror (W_INDIR_BANKED);
2024 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2026 if (isLitWord (AOP (IC_LEFT (ic))))
2028 emitcode ("", "; Special case where the pCall is to a constant");
2029 emitcode ("call", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2033 symbol *rlbl = newiTempLabel (NULL);
2034 spillPair (PAIR_HL);
2035 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2036 emitcode ("push", "hl");
2037 _G.stack.pushed += 2;
2039 fetchHL (AOP (IC_LEFT (ic)));
2041 emit2 ("!tlabeldef", (rlbl->key + 100));
2042 _G.stack.pushed -= 2;
2044 freeAsmop (IC_LEFT (ic), NULL, ic);
2048 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2049 OP_SYMBOL (IC_LEFT (ic))->rname :
2050 OP_SYMBOL (IC_LEFT (ic))->name;
2051 if (IS_BANKEDCALL (detype))
2053 emit2 ("call banked_call");
2054 emit2 ("!dws", name);
2055 emit2 ("!dw !bankimmeds", name);
2060 emit2 ("call %s", name);
2065 /* if we need assign a result value */
2066 if ((IS_ITEMP (IC_RESULT (ic)) &&
2067 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2068 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2069 IS_TRUE_SYMOP (IC_RESULT (ic)))
2073 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2076 assignResultValue (IC_RESULT (ic));
2078 freeAsmop (IC_RESULT (ic), NULL, ic);
2081 /* adjust the stack for parameters if required */
2084 int i = ic->parmBytes;
2085 _G.stack.pushed -= i;
2088 emit2 ("!ldaspsp", i);
2095 emitcode ("ld", "hl,#%d", i);
2096 emitcode ("add", "hl,sp");
2097 emitcode ("ld", "sp,hl");
2103 emitcode ("pop", "hl");
2107 emitcode ("inc", "sp");
2116 /*-----------------------------------------------------------------*/
2117 /* genCall - generates a call statement */
2118 /*-----------------------------------------------------------------*/
2120 genCall (iCode * ic)
2122 emitCall (ic, FALSE);
2125 /*-----------------------------------------------------------------*/
2126 /* genPcall - generates a call by pointer statement */
2127 /*-----------------------------------------------------------------*/
2129 genPcall (iCode * ic)
2131 emitCall (ic, TRUE);
2134 /*-----------------------------------------------------------------*/
2135 /* resultRemat - result is rematerializable */
2136 /*-----------------------------------------------------------------*/
2138 resultRemat (iCode * ic)
2140 if (SKIP_IC (ic) || ic->op == IFX)
2143 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2145 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2146 if (sym->remat && !POINTER_SET (ic))
2153 extern set *publics;
2155 /*-----------------------------------------------------------------*/
2156 /* genFunction - generated code for function entry */
2157 /*-----------------------------------------------------------------*/
2159 genFunction (iCode * ic)
2161 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2166 _G.receiveOffset = 0;
2168 setArea (IS_NONBANKED (sym->etype));
2171 if (!IS_STATIC (sym->etype))
2173 addSetIfnotP (&publics, sym);
2176 /* create the function header */
2177 emit2 ("!functionheader", sym->name);
2178 /* PENDING: portability. */
2179 emit2 ("__%s_start:", sym->rname);
2180 emit2 ("!functionlabeldef", sym->rname);
2182 fetype = getSpec (operandType (IC_LEFT (ic)));
2184 /* if critical function then turn interrupts off */
2185 if (SPEC_CRTCL (fetype))
2188 /* if this is an interrupt service routine then
2189 save acc, b, dpl, dph */
2190 if (IS_ISR (sym->etype))
2194 /* PENDING: callee-save etc */
2196 /* If BC or DE are used, then push */
2197 _G.stack.pushed_bc = 0;
2198 _G.stack.pushed_de = 0;
2199 _G.stack.param_offset = 0;
2201 /* PENDING: BUG: We don't detect if DE or BC are used in a send set.
2202 For now assume the worst and always save.
2204 _G.stack.pushed_bc = 1;
2205 _G.stack.pushed_de = 1;
2210 for (i = 0; i < sym->regsUsed->size; i++)
2212 if (bitVectBitValue (sym->regsUsed, i))
2218 _G.stack.pushed_bc = 1;
2223 _G.stack.pushed_de = 1;
2230 if (_G.stack.pushed_bc)
2233 _G.stack.param_offset += 2;
2235 if (_G.stack.pushed_de)
2238 _G.stack.param_offset += 2;
2241 /* adjust the stack for the function */
2242 _G.stack.last = sym->stack;
2245 emit2 ("!enterx", sym->stack);
2248 _G.stack.offset = sym->stack;
2251 /*-----------------------------------------------------------------*/
2252 /* genEndFunction - generates epilogue for functions */
2253 /*-----------------------------------------------------------------*/
2255 genEndFunction (iCode * ic)
2257 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2259 if (IS_ISR (sym->etype))
2265 if (SPEC_CRTCL (sym->etype))
2268 /* PENDING: calleeSave */
2270 /* if debug then send end of function */
2271 if (options.debug && currFunc)
2274 emitcode ("", "C$%s$%d$%d$%d ==.",
2275 FileBaseName (ic->filename), currFunc->lastLine,
2276 ic->level, ic->block);
2277 if (IS_STATIC (currFunc->etype))
2278 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2280 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2283 if (_G.stack.offset)
2284 emit2 ("!leavex", _G.stack.offset);
2288 if (_G.stack.pushed_de)
2290 if (_G.stack.pushed_bc)
2292 /* Both baned and non-banked just ret */
2295 /* PENDING: portability. */
2296 emit2 ("__%s_end:", sym->rname);
2298 _G.flush_statics = 1;
2299 _G.stack.pushed = 0;
2300 _G.stack.offset = 0;
2303 /*-----------------------------------------------------------------*/
2304 /* genRet - generate code for return statement */
2305 /*-----------------------------------------------------------------*/
2310 /* Errk. This is a hack until I can figure out how
2311 to cause dehl to spill on a call */
2312 int size, offset = 0;
2314 /* if we have no return value then
2315 just generate the "ret" */
2319 /* we have something to return then
2320 move the return value into place */
2321 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2322 size = AOP_SIZE (IC_LEFT (ic));
2324 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2328 emitcode ("ld", "de,%s", l);
2332 emitcode ("ld", "hl,%s", l);
2337 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2339 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2340 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2346 l = aopGet (AOP (IC_LEFT (ic)), offset,
2348 if (strcmp (_fReturn[offset], l))
2349 emitcode ("ld", "%s,%s", _fReturn[offset++], l);
2353 freeAsmop (IC_LEFT (ic), NULL, ic);
2356 /* generate a jump to the return label
2357 if the next is not the return statement */
2358 if (!(ic->next && ic->next->op == LABEL &&
2359 IC_LABEL (ic->next) == returnLabel))
2361 emit2 ("jp !tlabel", returnLabel->key + 100);
2364 /*-----------------------------------------------------------------*/
2365 /* genLabel - generates a label */
2366 /*-----------------------------------------------------------------*/
2368 genLabel (iCode * ic)
2370 /* special case never generate */
2371 if (IC_LABEL (ic) == entryLabel)
2374 emitLabel (IC_LABEL (ic)->key + 100);
2377 /*-----------------------------------------------------------------*/
2378 /* genGoto - generates a ljmp */
2379 /*-----------------------------------------------------------------*/
2381 genGoto (iCode * ic)
2383 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2386 /*-----------------------------------------------------------------*/
2387 /* genPlusIncr :- does addition with increment if possible */
2388 /*-----------------------------------------------------------------*/
2390 genPlusIncr (iCode * ic)
2392 unsigned int icount;
2393 unsigned int size = getDataSize (IC_RESULT (ic));
2394 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2396 /* will try to generate an increment */
2397 /* if the right side is not a literal
2399 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2402 emitcode ("", "; genPlusIncr");
2404 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2406 /* If result is a pair */
2407 if (resultId != PAIR_INVALID)
2409 if (isLitWord (AOP (IC_LEFT (ic))))
2411 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2414 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2416 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2417 emitcode ("add", "hl,%s", getPairName (AOP (IC_LEFT (ic))));
2423 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2427 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2428 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2432 emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
2437 /* if the literal value of the right hand side
2438 is greater than 4 then it is not worth it */
2442 /* if increment 16 bits in register */
2443 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2449 symbol *tlbl = NULL;
2450 tlbl = newiTempLabel (NULL);
2453 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2456 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2459 emitLabel (tlbl->key + 100);
2463 /* if the sizes are greater than 1 then we cannot */
2464 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2465 AOP_SIZE (IC_LEFT (ic)) > 1)
2468 /* we can if the aops of the left & result match or
2469 if they are in registers and the registers are the
2471 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2474 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2481 /*-----------------------------------------------------------------*/
2482 /* outBitAcc - output a bit in acc */
2483 /*-----------------------------------------------------------------*/
2485 outBitAcc (operand * result)
2487 symbol *tlbl = newiTempLabel (NULL);
2488 /* if the result is a bit */
2489 if (AOP_TYPE (result) == AOP_CRY)
2495 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2496 emit2 ("ld a,!one");
2497 emitLabel (tlbl->key + 100);
2502 /*-----------------------------------------------------------------*/
2503 /* genPlus - generates code for addition */
2504 /*-----------------------------------------------------------------*/
2506 genPlus (iCode * ic)
2508 int size, offset = 0;
2510 /* special cases :- */
2512 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2513 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2514 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2516 /* Swap the left and right operands if:
2518 if literal, literal on the right or
2519 if left requires ACC or right is already
2522 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2523 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2524 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2526 operand *t = IC_RIGHT (ic);
2527 IC_RIGHT (ic) = IC_LEFT (ic);
2531 /* if both left & right are in bit
2533 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2534 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2540 /* if left in bit space & right literal */
2541 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2542 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2544 /* Can happen I guess */
2548 /* if I can do an increment instead
2549 of add then GOOD for ME */
2550 if (genPlusIncr (ic) == TRUE)
2553 emit2 ("; genPlusIncr failed");
2555 size = getDataSize (IC_RESULT (ic));
2557 /* Special case when left and right are constant */
2558 if (isPair (AOP (IC_RESULT (ic))))
2562 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2563 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2569 sprintf (buffer, "#(%s + %s)", left, right);
2570 emitcode ("ld", "%s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2575 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2577 /* Fetch into HL then do the add */
2578 spillPair (PAIR_HL);
2579 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2580 emitcode ("add", "hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2585 ld hl,sp+n trashes C so we cant afford to do it during an
2586 add with stack based varibles. Worst case is:
2599 So you cant afford to load up hl if either left, right, or result
2600 is on the stack (*sigh*) The alt is:
2608 Combinations in here are:
2609 * If left or right are in bc then the loss is small - trap later
2610 * If the result is in bc then the loss is also small
2614 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2615 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2616 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2618 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2619 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2620 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2621 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2623 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2625 /* Swap left and right */
2626 operand *t = IC_RIGHT (ic);
2627 IC_RIGHT (ic) = IC_LEFT (ic);
2630 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2632 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2633 emit2 ("add hl,bc");
2637 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2638 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2639 emit2 ("add hl,de");
2641 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2646 emit2 ("; WARNING: This add is probably broken.\n");
2653 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2655 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2658 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2661 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2665 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2668 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2671 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2673 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2677 freeAsmop (IC_LEFT (ic), NULL, ic);
2678 freeAsmop (IC_RIGHT (ic), NULL, ic);
2679 freeAsmop (IC_RESULT (ic), NULL, ic);
2683 /*-----------------------------------------------------------------*/
2684 /* genMinusDec :- does subtraction with deccrement if possible */
2685 /*-----------------------------------------------------------------*/
2687 genMinusDec (iCode * ic)
2689 unsigned int icount;
2690 unsigned int size = getDataSize (IC_RESULT (ic));
2692 /* will try to generate an increment */
2693 /* if the right side is not a literal we cannot */
2694 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2697 /* if the literal value of the right hand side
2698 is greater than 4 then it is not worth it */
2699 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2702 size = getDataSize (IC_RESULT (ic));
2705 /* if increment 16 bits in register */
2706 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2710 symbol *tlbl = newiTempLabel (NULL);
2711 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2712 emitcode ("jp", "np," LABEL_STR, tlbl->key + 100);
2714 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2719 emitLabel (tlbl->key + 100);
2724 /* if decrement 16 bits in register */
2725 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2726 (size > 1) && isPair (AOP (IC_RESULT (ic))))
2729 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2733 /* If result is a pair */
2734 if (isPair (AOP (IC_RESULT (ic))))
2736 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2737 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2739 emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2743 /* if the sizes are greater than 1 then we cannot */
2744 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2745 AOP_SIZE (IC_LEFT (ic)) > 1)
2748 /* we can if the aops of the left & result match or if they are in
2749 registers and the registers are the same */
2750 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2753 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2760 /*-----------------------------------------------------------------*/
2761 /* genMinus - generates code for subtraction */
2762 /*-----------------------------------------------------------------*/
2764 genMinus (iCode * ic)
2766 int size, offset = 0;
2767 unsigned long lit = 0L;
2769 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2770 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2771 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2773 /* special cases :- */
2774 /* if both left & right are in bit space */
2775 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2776 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2782 /* if I can do an decrement instead of subtract then GOOD for ME */
2783 if (genMinusDec (ic) == TRUE)
2786 size = getDataSize (IC_RESULT (ic));
2788 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2793 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2797 /* Same logic as genPlus */
2800 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2801 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2802 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2804 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2805 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2806 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2807 AOP_SIZE (IC_RIGHT (ic)) <= 2))
2809 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2810 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2812 if (left == PAIR_INVALID && right == PAIR_INVALID)
2817 else if (right == PAIR_INVALID)
2819 else if (left == PAIR_INVALID)
2822 fetchPair (left, AOP (IC_LEFT (ic)));
2823 /* Order is important. Right may be HL */
2824 fetchPair (right, AOP (IC_RIGHT (ic)));
2826 emit2 ("ld a,%s", _pairs[left].l);
2827 emit2 ("sub a,%s", _pairs[right].l);
2829 emit2 ("ld a,%s", _pairs[left].h);
2830 emit2 ("sbc a,%s", _pairs[right].h);
2832 aopPut (AOP (IC_RESULT (ic)), "a", 1);
2833 aopPut (AOP (IC_RESULT (ic)), "e", 0);
2838 emit2 ("; WARNING: This sub is probably broken.\n");
2843 /* if literal, add a,#-lit, else normal subb */
2846 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2847 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2850 emitcode ("sub", "a,%s",
2851 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2853 emitcode ("sbc", "a,%s",
2854 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2858 /* first add without previous c */
2860 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2862 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2864 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2867 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2868 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2869 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2873 freeAsmop (IC_LEFT (ic), NULL, ic);
2874 freeAsmop (IC_RIGHT (ic), NULL, ic);
2875 freeAsmop (IC_RESULT (ic), NULL, ic);
2878 /*-----------------------------------------------------------------*/
2879 /* genMult - generates code for multiplication */
2880 /*-----------------------------------------------------------------*/
2882 genMult (iCode * ic)
2884 /* Shouldn't occur - all done through function calls */
2888 /*-----------------------------------------------------------------*/
2889 /* genDiv - generates code for division */
2890 /*-----------------------------------------------------------------*/
2894 /* Shouldn't occur - all done through function calls */
2898 /*-----------------------------------------------------------------*/
2899 /* genMod - generates code for division */
2900 /*-----------------------------------------------------------------*/
2904 /* Shouldn't occur - all done through function calls */
2908 /*-----------------------------------------------------------------*/
2909 /* genIfxJump :- will create a jump depending on the ifx */
2910 /*-----------------------------------------------------------------*/
2912 genIfxJump (iCode * ic, char *jval)
2917 /* if true label then we jump if condition
2921 jlbl = IC_TRUE (ic);
2922 if (!strcmp (jval, "a"))
2926 else if (!strcmp (jval, "c"))
2930 else if (!strcmp (jval, "nc"))
2936 /* The buffer contains the bit on A that we should test */
2942 /* false label is present */
2943 jlbl = IC_FALSE (ic);
2944 if (!strcmp (jval, "a"))
2948 else if (!strcmp (jval, "c"))
2952 else if (!strcmp (jval, "nc"))
2958 /* The buffer contains the bit on A that we should test */
2962 /* Z80 can do a conditional long jump */
2963 if (!strcmp (jval, "a"))
2965 emitcode ("or", "a,a");
2967 else if (!strcmp (jval, "c"))
2970 else if (!strcmp (jval, "nc"))
2975 emitcode ("bit", "%s,a", jval);
2977 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
2979 /* mark the icode as generated */
2984 _getPairIdName (PAIR_ID id)
2986 return _pairs[id].name;
2989 /** Generic compare for > or <
2992 genCmp (operand * left, operand * right,
2993 operand * result, iCode * ifx, int sign)
2995 int size, offset = 0;
2996 unsigned long lit = 0L;
2997 bool swap_sense = FALSE;
2999 /* if left & right are bit variables */
3000 if (AOP_TYPE (left) == AOP_CRY &&
3001 AOP_TYPE (right) == AOP_CRY)
3003 /* Cant happen on the Z80 */
3008 /* subtract right from left if at the
3009 end the carry flag is set then we know that
3010 left is greater than right */
3011 size = max (AOP_SIZE (left), AOP_SIZE (right));
3013 /* if unsigned char cmp with lit, just compare */
3015 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3017 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3020 emit2 ("xor a,!immedbyte", 0x80);
3021 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3024 emitcode ("cp", "%s", aopGet (AOP (right), offset, FALSE));
3030 If the left or the right is a lit:
3031 Load -lit into HL, add to right via, check sense.
3033 if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3035 PAIR_ID id = PAIR_DE;
3036 asmop *lit = AOP (right);
3037 asmop *op = AOP (left);
3040 if (AOP_TYPE (left) == AOP_LIT)
3048 emit2 ("ld e,%s", aopGet (op, 0, 0));
3049 emit2 ("ld a,%s", aopGet (op, 1, 0));
3050 emit2 ("xor a,!immedbyte", 0x80);
3055 id = getPairId (op);
3056 if (id == PAIR_INVALID)
3058 fetchPair (PAIR_DE, op);
3062 spillPair (PAIR_HL);
3063 emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3064 emit2 ("add hl,%s", _getPairIdName (id));
3067 if (AOP_TYPE (right) == AOP_LIT)
3069 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3070 /* optimize if(x < 0) or if(x >= 0) */
3075 /* No sign so it's always false */
3080 /* Just load in the top most bit */
3081 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3082 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3084 genIfxJump (ifx, "7");
3088 emitcode ("rlc", "a");
3095 /* First setup h and l contaning the top most bytes XORed */
3096 bool fDidXor = FALSE;
3097 if (AOP_TYPE (left) == AOP_LIT)
3099 unsigned long lit = (unsigned long)
3100 floatFromVal (AOP (left)->aopu.aop_lit);
3101 emit2 ("ld %s,!immedbyte", _fTmp[0],
3102 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3106 emitcode ("ld", "a,%s", aopGet (AOP (left), size - 1, FALSE));
3107 emit2 ("xor a,!immedbyte", 0x80);
3108 emitcode ("ld", "%s,a", _fTmp[0]);
3111 if (AOP_TYPE (right) == AOP_LIT)
3113 unsigned long lit = (unsigned long)
3114 floatFromVal (AOP (right)->aopu.aop_lit);
3115 emit2 ("ld %s,!immedbyte", _fTmp[1],
3116 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3120 emitcode ("ld", "a,%s", aopGet (AOP (right), size - 1, FALSE));
3121 emit2 ("xor a,!immedbyte", 0x80);
3122 emitcode ("ld", "%s,a", _fTmp[1]);
3134 /* Do a long subtract */
3137 MOVA (aopGet (AOP (left), offset, FALSE));
3139 if (sign && size == 0)
3141 emitcode ("ld", "a,%s", _fTmp[0]);
3142 emitcode ("sbc", "a,%s", _fTmp[1]);
3146 /* Subtract through, propagating the carry */
3147 emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3154 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3156 outBitCLong (result, swap_sense);
3160 /* if the result is used in the next
3161 ifx conditional branch then generate
3162 code a little differently */
3164 genIfxJump (ifx, swap_sense ? "nc" : "c");
3166 outBitCLong (result, swap_sense);
3167 /* leave the result in acc */
3171 /*-----------------------------------------------------------------*/
3172 /* genCmpGt :- greater than comparison */
3173 /*-----------------------------------------------------------------*/
3175 genCmpGt (iCode * ic, iCode * ifx)
3177 operand *left, *right, *result;
3178 sym_link *letype, *retype;
3181 left = IC_LEFT (ic);
3182 right = IC_RIGHT (ic);
3183 result = IC_RESULT (ic);
3185 letype = getSpec (operandType (left));
3186 retype = getSpec (operandType (right));
3187 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3188 /* assign the amsops */
3189 aopOp (left, ic, FALSE, FALSE);
3190 aopOp (right, ic, FALSE, FALSE);
3191 aopOp (result, ic, TRUE, FALSE);
3193 genCmp (right, left, result, ifx, sign);
3195 freeAsmop (left, NULL, ic);
3196 freeAsmop (right, NULL, ic);
3197 freeAsmop (result, NULL, ic);
3200 /*-----------------------------------------------------------------*/
3201 /* genCmpLt - less than comparisons */
3202 /*-----------------------------------------------------------------*/
3204 genCmpLt (iCode * ic, iCode * ifx)
3206 operand *left, *right, *result;
3207 sym_link *letype, *retype;
3210 left = IC_LEFT (ic);
3211 right = IC_RIGHT (ic);
3212 result = IC_RESULT (ic);
3214 letype = getSpec (operandType (left));
3215 retype = getSpec (operandType (right));
3216 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3218 /* assign the amsops */
3219 aopOp (left, ic, FALSE, FALSE);
3220 aopOp (right, ic, FALSE, FALSE);
3221 aopOp (result, ic, TRUE, FALSE);
3223 genCmp (left, right, result, ifx, sign);
3225 freeAsmop (left, NULL, ic);
3226 freeAsmop (right, NULL, ic);
3227 freeAsmop (result, NULL, ic);
3230 /*-----------------------------------------------------------------*/
3231 /* gencjneshort - compare and jump if not equal */
3232 /*-----------------------------------------------------------------*/
3234 gencjneshort (operand * left, operand * right, symbol * lbl)
3236 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3238 unsigned long lit = 0L;
3240 /* Swap the left and right if it makes the computation easier */
3241 if (AOP_TYPE (left) == AOP_LIT)
3248 if (AOP_TYPE (right) == AOP_LIT)
3249 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3251 /* if the right side is a literal then anything goes */
3252 if (AOP_TYPE (right) == AOP_LIT &&
3253 AOP_TYPE (left) != AOP_DIR)
3257 emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3264 emitcode ("or", "a,%s", aopGet (AOP (left), offset, FALSE));
3269 emitcode ("or", "a,a");
3271 emit2 ("jp nz,!tlabel", lbl->key + 100);
3277 emitcode ("ld", "a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3278 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3279 emitcode ("or", "a,a");
3281 emitcode ("cp", "a,%s", aopGet (AOP (right), offset, FALSE));
3282 emit2 ("jp nz,!tlabel", lbl->key + 100);
3287 /* if the right side is in a register or in direct space or
3288 if the left is a pointer register & right is not */
3289 else if (AOP_TYPE (right) == AOP_REG ||
3290 AOP_TYPE (right) == AOP_DIR ||
3291 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3295 MOVA (aopGet (AOP (left), offset, FALSE));
3296 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3297 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3299 emit2 ("jp nz,!tlabel", lbl->key + 100);
3302 emitcode ("cp", "%s ; 4", aopGet (AOP (right), offset, FALSE));
3303 emit2 ("jp nz,!tlabel", lbl->key + 100);
3310 /* right is a pointer reg need both a & b */
3311 /* PENDING: is this required? */
3314 MOVA (aopGet (AOP (right), offset, FALSE));
3315 emitcode ("cp", "%s ; 5", aopGet (AOP (left), offset, FALSE));
3316 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3322 /*-----------------------------------------------------------------*/
3323 /* gencjne - compare and jump if not equal */
3324 /*-----------------------------------------------------------------*/
3326 gencjne (operand * left, operand * right, symbol * lbl)
3328 symbol *tlbl = newiTempLabel (NULL);
3330 gencjneshort (left, right, lbl);
3333 emit2 ("ld a,!one");
3334 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3335 emitLabel (lbl->key + 100);
3336 emitcode ("xor", "a,a");
3337 emitLabel (tlbl->key + 100);
3340 /*-----------------------------------------------------------------*/
3341 /* genCmpEq - generates code for equal to */
3342 /*-----------------------------------------------------------------*/
3344 genCmpEq (iCode * ic, iCode * ifx)
3346 operand *left, *right, *result;
3348 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3349 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3350 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3352 emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3354 /* Swap operands if it makes the operation easier. ie if:
3355 1. Left is a literal.
3357 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3359 operand *t = IC_RIGHT (ic);
3360 IC_RIGHT (ic) = IC_LEFT (ic);
3364 if (ifx && !AOP_SIZE (result))
3367 /* if they are both bit variables */
3368 if (AOP_TYPE (left) == AOP_CRY &&
3369 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3375 tlbl = newiTempLabel (NULL);
3376 gencjneshort (left, right, tlbl);
3379 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3380 emitLabel (tlbl->key + 100);
3384 /* PENDING: do this better */
3385 symbol *lbl = newiTempLabel (NULL);
3386 emit2 ("!shortjp !tlabel", lbl->key + 100);
3387 emitLabel (tlbl->key + 100);
3388 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3389 emitLabel (lbl->key + 100);
3392 /* mark the icode as generated */
3397 /* if they are both bit variables */
3398 if (AOP_TYPE (left) == AOP_CRY &&
3399 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3405 gencjne (left, right, newiTempLabel (NULL));
3406 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3412 genIfxJump (ifx, "a");
3415 /* if the result is used in an arithmetic operation
3416 then put the result in place */
3417 if (AOP_TYPE (result) != AOP_CRY)
3421 /* leave the result in acc */
3425 freeAsmop (left, NULL, ic);
3426 freeAsmop (right, NULL, ic);
3427 freeAsmop (result, NULL, ic);
3430 /*-----------------------------------------------------------------*/
3431 /* ifxForOp - returns the icode containing the ifx for operand */
3432 /*-----------------------------------------------------------------*/
3434 ifxForOp (operand * op, iCode * ic)
3436 /* if true symbol then needs to be assigned */
3437 if (IS_TRUE_SYMOP (op))
3440 /* if this has register type condition and
3441 the next instruction is ifx with the same operand
3442 and live to of the operand is upto the ifx only then */
3444 ic->next->op == IFX &&
3445 IC_COND (ic->next)->key == op->key &&
3446 OP_SYMBOL (op)->liveTo <= ic->next->seq)
3452 /*-----------------------------------------------------------------*/
3453 /* genAndOp - for && operation */
3454 /*-----------------------------------------------------------------*/
3456 genAndOp (iCode * ic)
3458 operand *left, *right, *result;
3461 /* note here that && operations that are in an if statement are
3462 taken away by backPatchLabels only those used in arthmetic
3463 operations remain */
3464 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3465 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3466 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3468 /* if both are bit variables */
3469 if (AOP_TYPE (left) == AOP_CRY &&
3470 AOP_TYPE (right) == AOP_CRY)
3476 tlbl = newiTempLabel (NULL);
3478 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3480 emitLabel (tlbl->key + 100);
3484 freeAsmop (left, NULL, ic);
3485 freeAsmop (right, NULL, ic);
3486 freeAsmop (result, NULL, ic);
3489 /*-----------------------------------------------------------------*/
3490 /* genOrOp - for || operation */
3491 /*-----------------------------------------------------------------*/
3493 genOrOp (iCode * ic)
3495 operand *left, *right, *result;
3498 /* note here that || operations that are in an
3499 if statement are taken away by backPatchLabels
3500 only those used in arthmetic operations remain */
3501 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3502 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3503 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3505 /* if both are bit variables */
3506 if (AOP_TYPE (left) == AOP_CRY &&
3507 AOP_TYPE (right) == AOP_CRY)
3513 tlbl = newiTempLabel (NULL);
3515 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3517 emitLabel (tlbl->key + 100);
3521 freeAsmop (left, NULL, ic);
3522 freeAsmop (right, NULL, ic);
3523 freeAsmop (result, NULL, ic);
3526 /*-----------------------------------------------------------------*/
3527 /* isLiteralBit - test if lit == 2^n */
3528 /*-----------------------------------------------------------------*/
3530 isLiteralBit (unsigned long lit)
3532 unsigned long pw[32] =
3533 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3534 0x100L, 0x200L, 0x400L, 0x800L,
3535 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3536 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3537 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3538 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3539 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3542 for (idx = 0; idx < 32; idx++)
3548 /*-----------------------------------------------------------------*/
3549 /* jmpTrueOrFalse - */
3550 /*-----------------------------------------------------------------*/
3552 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3554 // ugly but optimized by peephole
3557 symbol *nlbl = newiTempLabel (NULL);
3558 emit2 ("jp !tlabel", nlbl->key + 100);
3559 emitLabel (tlbl->key + 100);
3560 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3561 emitLabel (nlbl->key + 100);
3565 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3566 emitLabel (tlbl->key + 100);
3571 /*-----------------------------------------------------------------*/
3572 /* genAnd - code for and */
3573 /*-----------------------------------------------------------------*/
3575 genAnd (iCode * ic, iCode * ifx)
3577 operand *left, *right, *result;
3578 int size, offset = 0;
3579 unsigned long lit = 0L;
3582 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3583 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3584 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3587 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3589 AOP_TYPE (left), AOP_TYPE (right));
3590 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3592 AOP_SIZE (left), AOP_SIZE (right));
3595 /* if left is a literal & right is not then exchange them */
3596 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3597 AOP_NEEDSACC (left))
3599 operand *tmp = right;
3604 /* if result = right then exchange them */
3605 if (sameRegs (AOP (result), AOP (right)))
3607 operand *tmp = right;
3612 /* if right is bit then exchange them */
3613 if (AOP_TYPE (right) == AOP_CRY &&
3614 AOP_TYPE (left) != AOP_CRY)
3616 operand *tmp = right;
3620 if (AOP_TYPE (right) == AOP_LIT)
3621 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3623 size = AOP_SIZE (result);
3625 if (AOP_TYPE (left) == AOP_CRY)
3631 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3632 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3633 if ((AOP_TYPE (right) == AOP_LIT) &&
3634 (AOP_TYPE (result) == AOP_CRY) &&
3635 (AOP_TYPE (left) != AOP_CRY))
3637 int posbit = isLiteralBit (lit);
3642 MOVA (aopGet (AOP (left), posbit >> 3, FALSE));
3647 emitcode ("mov", "c,acc.%d", posbit & 0x07);
3654 sprintf (buffer, "%d", posbit & 0x07);
3655 genIfxJump (ifx, buffer);
3666 symbol *tlbl = newiTempLabel (NULL);
3667 int sizel = AOP_SIZE (left);
3671 emitcode ("setb", "c");
3675 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3677 MOVA (aopGet (AOP (left), offset, FALSE));
3679 if ((posbit = isLiteralBit (bytelit)) != 0)
3682 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3686 if (bytelit != 0x0FFL)
3687 emitcode ("and", "a,%s",
3688 aopGet (AOP (right), offset, FALSE));
3692 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3697 // bit = left & literal
3700 emitcode ("clr", "c");
3701 emit2 ("!tlabeldef", tlbl->key + 100);
3703 // if(left & literal)
3707 jmpTrueOrFalse (ifx, tlbl);
3715 /* if left is same as result */
3716 if (sameRegs (AOP (result), AOP (left)))
3718 for (; size--; offset++)
3720 if (AOP_TYPE (right) == AOP_LIT)
3722 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3727 aopPut (AOP (result), zero, offset);
3730 MOVA (aopGet (AOP (left), offset, FALSE));
3731 emitcode ("and", "a,%s",
3732 aopGet (AOP (right), offset, FALSE));
3733 aopPut (AOP (left), "a", offset);
3740 if (AOP_TYPE (left) == AOP_ACC)
3746 MOVA (aopGet (AOP (left), offset, FALSE));
3747 emitcode ("and", "a,%s",
3748 aopGet (AOP (right), offset, FALSE));
3749 aopPut (AOP (left), "a", offset);
3756 // left & result in different registers
3757 if (AOP_TYPE (result) == AOP_CRY)
3763 for (; (size--); offset++)
3766 // result = left & right
3767 if (AOP_TYPE (right) == AOP_LIT)
3769 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3771 aopPut (AOP (result),
3772 aopGet (AOP (left), offset, FALSE),
3776 else if (bytelit == 0)
3778 aopPut (AOP (result), zero, offset);
3782 // faster than result <- left, anl result,right
3783 // and better if result is SFR
3784 if (AOP_TYPE (left) == AOP_ACC)
3785 emitcode ("and", "a,%s", aopGet (AOP (right), offset, FALSE));
3788 MOVA (aopGet (AOP (left), offset, FALSE));
3789 emitcode ("and", "a,%s",
3790 aopGet (AOP (right), offset, FALSE));
3792 aopPut (AOP (result), "a", offset);
3799 freeAsmop (left, NULL, ic);
3800 freeAsmop (right, NULL, ic);
3801 freeAsmop (result, NULL, ic);
3804 /*-----------------------------------------------------------------*/
3805 /* genOr - code for or */
3806 /*-----------------------------------------------------------------*/
3808 genOr (iCode * ic, iCode * ifx)
3810 operand *left, *right, *result;
3811 int size, offset = 0;
3812 unsigned long lit = 0L;
3814 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3815 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3816 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3819 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3821 AOP_TYPE (left), AOP_TYPE (right));
3822 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3824 AOP_SIZE (left), AOP_SIZE (right));
3827 /* if left is a literal & right is not then exchange them */
3828 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3829 AOP_NEEDSACC (left))
3831 operand *tmp = right;
3836 /* if result = right then exchange them */
3837 if (sameRegs (AOP (result), AOP (right)))
3839 operand *tmp = right;
3844 /* if right is bit then exchange them */
3845 if (AOP_TYPE (right) == AOP_CRY &&
3846 AOP_TYPE (left) != AOP_CRY)
3848 operand *tmp = right;
3852 if (AOP_TYPE (right) == AOP_LIT)
3853 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3855 size = AOP_SIZE (result);
3857 if (AOP_TYPE (left) == AOP_CRY)
3863 if ((AOP_TYPE (right) == AOP_LIT) &&
3864 (AOP_TYPE (result) == AOP_CRY) &&
3865 (AOP_TYPE (left) != AOP_CRY))
3871 /* if left is same as result */
3872 if (sameRegs (AOP (result), AOP (left)))
3874 for (; size--; offset++)
3876 if (AOP_TYPE (right) == AOP_LIT)
3878 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3882 MOVA (aopGet (AOP (left), offset, FALSE));
3883 emitcode ("or", "a,%s",
3884 aopGet (AOP (right), offset, FALSE));
3885 aopPut (AOP (result), "a", offset);
3890 if (AOP_TYPE (left) == AOP_ACC)
3891 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3894 MOVA (aopGet (AOP (left), offset, FALSE));
3895 emitcode ("or", "a,%s",
3896 aopGet (AOP (right), offset, FALSE));
3897 aopPut (AOP (result), "a", offset);
3904 // left & result in different registers
3905 if (AOP_TYPE (result) == AOP_CRY)
3910 for (; (size--); offset++)
3913 // result = left & right
3914 if (AOP_TYPE (right) == AOP_LIT)
3916 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3918 aopPut (AOP (result),
3919 aopGet (AOP (left), offset, FALSE),
3924 // faster than result <- left, anl result,right
3925 // and better if result is SFR
3926 if (AOP_TYPE (left) == AOP_ACC)
3927 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3930 MOVA (aopGet (AOP (left), offset, FALSE));
3931 emitcode ("or", "a,%s",
3932 aopGet (AOP (right), offset, FALSE));
3934 aopPut (AOP (result), "a", offset);
3935 /* PENDING: something weird is going on here. Add exception. */
3936 if (AOP_TYPE (result) == AOP_ACC)
3942 freeAsmop (left, NULL, ic);
3943 freeAsmop (right, NULL, ic);
3944 freeAsmop (result, NULL, ic);
3947 /*-----------------------------------------------------------------*/
3948 /* genXor - code for xclusive or */
3949 /*-----------------------------------------------------------------*/
3951 genXor (iCode * ic, iCode * ifx)
3953 operand *left, *right, *result;
3954 int size, offset = 0;
3955 unsigned long lit = 0L;
3957 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3958 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3959 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3961 /* if left is a literal & right is not then exchange them */
3962 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3963 AOP_NEEDSACC (left))
3965 operand *tmp = right;
3970 /* if result = right then exchange them */
3971 if (sameRegs (AOP (result), AOP (right)))
3973 operand *tmp = right;
3978 /* if right is bit then exchange them */
3979 if (AOP_TYPE (right) == AOP_CRY &&
3980 AOP_TYPE (left) != AOP_CRY)
3982 operand *tmp = right;
3986 if (AOP_TYPE (right) == AOP_LIT)
3987 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3989 size = AOP_SIZE (result);
3991 if (AOP_TYPE (left) == AOP_CRY)
3997 if ((AOP_TYPE (right) == AOP_LIT) &&
3998 (AOP_TYPE (result) == AOP_CRY) &&
3999 (AOP_TYPE (left) != AOP_CRY))
4005 /* if left is same as result */
4006 if (sameRegs (AOP (result), AOP (left)))
4008 for (; size--; offset++)
4010 if (AOP_TYPE (right) == AOP_LIT)
4012 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4016 MOVA (aopGet (AOP (right), offset, FALSE));
4017 emitcode ("xor", "a,%s",
4018 aopGet (AOP (left), offset, FALSE));
4019 aopPut (AOP (result), "a", 0);
4024 if (AOP_TYPE (left) == AOP_ACC)
4025 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4028 MOVA (aopGet (AOP (right), offset, FALSE));
4029 emitcode ("xor", "a,%s",
4030 aopGet (AOP (left), offset, FALSE));
4031 aopPut (AOP (result), "a", 0);
4038 // left & result in different registers
4039 if (AOP_TYPE (result) == AOP_CRY)
4044 for (; (size--); offset++)
4047 // result = left & right
4048 if (AOP_TYPE (right) == AOP_LIT)
4050 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4052 aopPut (AOP (result),
4053 aopGet (AOP (left), offset, FALSE),
4058 // faster than result <- left, anl result,right
4059 // and better if result is SFR
4060 if (AOP_TYPE (left) == AOP_ACC)
4061 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4064 MOVA (aopGet (AOP (right), offset, FALSE));
4065 emitcode ("xor", "a,%s",
4066 aopGet (AOP (left), offset, FALSE));
4067 aopPut (AOP (result), "a", 0);
4069 aopPut (AOP (result), "a", offset);
4074 freeAsmop (left, NULL, ic);
4075 freeAsmop (right, NULL, ic);
4076 freeAsmop (result, NULL, ic);
4079 /*-----------------------------------------------------------------*/
4080 /* genInline - write the inline code out */
4081 /*-----------------------------------------------------------------*/
4083 genInline (iCode * ic)
4085 char *buffer, *bp, *bp1;
4087 inLine += (!options.asmpeep);
4089 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4090 strcpy (buffer, IC_INLINE (ic));
4092 /* emit each line as a code */
4117 /* emitcode("",buffer); */
4118 inLine -= (!options.asmpeep);
4121 /*-----------------------------------------------------------------*/
4122 /* genRRC - rotate right with carry */
4123 /*-----------------------------------------------------------------*/
4130 /*-----------------------------------------------------------------*/
4131 /* genRLC - generate code for rotate left with carry */
4132 /*-----------------------------------------------------------------*/
4139 /*-----------------------------------------------------------------*/
4140 /* shiftR2Left2Result - shift right two bytes from left to result */
4141 /*-----------------------------------------------------------------*/
4143 shiftR2Left2Result (operand * left, int offl,
4144 operand * result, int offr,
4145 int shCount, int sign)
4147 movLeft2Result (left, offl, result, offr, 0);
4148 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4156 /* if (AOP(result)->type == AOP_REG) { */
4159 symbol *tlbl, *tlbl1;
4162 tlbl = newiTempLabel (NULL);
4163 tlbl1 = newiTempLabel (NULL);
4165 /* Left is already in result - so now do the shift */
4168 emit2 ("ld a,!immedbyte+1", shCount);
4169 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4170 emitLabel (tlbl->key + 100);
4173 emitcode ("or", "a,a");
4177 l = aopGet (AOP (result), --offset, FALSE);
4178 emitcode ("rr", "%s", l);
4182 emitLabel (tlbl1->key + 100);
4183 emitcode ("dec", "a");
4184 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4189 /*-----------------------------------------------------------------*/
4190 /* shiftL2Left2Result - shift left two bytes from left to result */
4191 /*-----------------------------------------------------------------*/
4193 shiftL2Left2Result (operand * left, int offl,
4194 operand * result, int offr, int shCount)
4196 if (sameRegs (AOP (result), AOP (left)) &&
4197 ((offl + MSB16) == offr))
4203 /* Copy left into result */
4204 movLeft2Result (left, offl, result, offr, 0);
4205 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4207 /* PENDING: for now just see if it'll work. */
4208 /*if (AOP(result)->type == AOP_REG) { */
4212 symbol *tlbl, *tlbl1;
4215 tlbl = newiTempLabel (NULL);
4216 tlbl1 = newiTempLabel (NULL);
4218 /* Left is already in result - so now do the shift */
4221 emit2 ("ld a,!immedbyte+1", shCount);
4222 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4223 emitLabel (tlbl->key + 100);
4226 emitcode ("or", "a,a");
4229 l = aopGet (AOP (result), offset++, FALSE);
4230 emitcode ("rl", "%s", l);
4234 emitLabel (tlbl1->key + 100);
4235 emitcode ("dec", "a");
4236 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4241 /*-----------------------------------------------------------------*/
4242 /* AccRol - rotate left accumulator by known count */
4243 /*-----------------------------------------------------------------*/
4245 AccRol (int shCount)
4247 shCount &= 0x0007; // shCount : 0..7
4254 emitcode ("rl", "a");
4257 emitcode ("rl", "a");
4258 emitcode ("rl", "a");
4261 emitcode ("rl", "a");
4262 emitcode ("rl", "a");
4263 emitcode ("rl", "a");
4266 emitcode ("rl", "a");
4267 emitcode ("rl", "a");
4268 emitcode ("rl", "a");
4269 emitcode ("rl", "a");
4272 emitcode ("rr", "a");
4273 emitcode ("rr", "a");
4274 emitcode ("rr", "a");
4277 emitcode ("rr", "a");
4278 emitcode ("rr", "a");
4281 emitcode ("rr", "a");
4286 /*-----------------------------------------------------------------*/
4287 /* AccLsh - left shift accumulator by known count */
4288 /*-----------------------------------------------------------------*/
4290 AccLsh (int shCount)
4296 emitcode ("add", "a,a");
4298 else if (shCount == 2)
4300 emitcode ("add", "a,a");
4301 emitcode ("add", "a,a");
4305 /* rotate left accumulator */
4307 /* and kill the lower order bits */
4308 emit2 ("and a,!immedbyte", SLMask[shCount]);
4313 /*-----------------------------------------------------------------*/
4314 /* shiftL1Left2Result - shift left one byte from left to result */
4315 /*-----------------------------------------------------------------*/
4317 shiftL1Left2Result (operand * left, int offl,
4318 operand * result, int offr, int shCount)
4321 l = aopGet (AOP (left), offl, FALSE);
4323 /* shift left accumulator */
4325 aopPut (AOP (result), "a", offr);
4329 /*-----------------------------------------------------------------*/
4330 /* genlshTwo - left shift two bytes by known amount != 0 */
4331 /*-----------------------------------------------------------------*/
4333 genlshTwo (operand * result, operand * left, int shCount)
4335 int size = AOP_SIZE (result);
4337 wassert (size == 2);
4339 /* if shCount >= 8 */
4347 movLeft2Result (left, LSB, result, MSB16, 0);
4348 aopPut (AOP (result), zero, 0);
4349 shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4353 movLeft2Result (left, LSB, result, MSB16, 0);
4354 aopPut (AOP (result), zero, 0);
4359 aopPut (AOP (result), zero, LSB);
4362 /* 1 <= shCount <= 7 */
4371 shiftL2Left2Result (left, LSB, result, LSB, shCount);
4376 /*-----------------------------------------------------------------*/
4377 /* genlshOne - left shift a one byte quantity by known count */
4378 /*-----------------------------------------------------------------*/
4380 genlshOne (operand * result, operand * left, int shCount)
4382 shiftL1Left2Result (left, LSB, result, LSB, shCount);
4385 /*-----------------------------------------------------------------*/
4386 /* genLeftShiftLiteral - left shifting by known count */
4387 /*-----------------------------------------------------------------*/
4389 genLeftShiftLiteral (operand * left,
4394 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4397 freeAsmop (right, NULL, ic);
4399 aopOp (left, ic, FALSE, FALSE);
4400 aopOp (result, ic, FALSE, FALSE);
4402 size = getSize (operandType (result));
4405 emitcode ("; shift left ", "result %d, left %d", size,
4409 /* I suppose that the left size >= result size */
4415 else if (shCount >= (size * 8))
4417 aopPut (AOP (result), zero, size);
4423 genlshOne (result, left, shCount);
4426 genlshTwo (result, left, shCount);
4435 freeAsmop (left, NULL, ic);
4436 freeAsmop (result, NULL, ic);
4439 /*-----------------------------------------------------------------*/
4440 /* genLeftShift - generates code for left shifting */
4441 /*-----------------------------------------------------------------*/
4443 genLeftShift (iCode * ic)
4447 symbol *tlbl, *tlbl1;
4448 operand *left, *right, *result;
4450 right = IC_RIGHT (ic);
4451 left = IC_LEFT (ic);
4452 result = IC_RESULT (ic);
4454 aopOp (right, ic, FALSE, FALSE);
4456 /* if the shift count is known then do it
4457 as efficiently as possible */
4458 if (AOP_TYPE (right) == AOP_LIT)
4460 genLeftShiftLiteral (left, right, result, ic);
4464 /* shift count is unknown then we have to form a loop get the loop
4465 count in B : Note: we take only the lower order byte since
4466 shifting more that 32 bits make no sense anyway, ( the largest
4467 size of an object can be only 32 bits ) */
4468 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4469 emitcode ("inc", "a");
4470 freeAsmop (right, NULL, ic);
4471 aopOp (left, ic, FALSE, FALSE);
4472 aopOp (result, ic, FALSE, FALSE);
4474 /* now move the left to the result if they are not the
4477 if (!sameRegs (AOP (left), AOP (result)))
4480 size = AOP_SIZE (result);
4484 l = aopGet (AOP (left), offset, FALSE);
4485 aopPut (AOP (result), l, offset);
4490 size = AOP_SIZE (result);
4494 l = aopGet (AOP (left), offset, FALSE);
4495 aopPut (AOP (result), l, offset);
4501 tlbl = newiTempLabel (NULL);
4502 size = AOP_SIZE (result);
4504 tlbl1 = newiTempLabel (NULL);
4506 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4507 emitLabel (tlbl->key + 100);
4508 l = aopGet (AOP (result), offset, FALSE);
4509 emitcode ("or", "a,a");
4512 l = aopGet (AOP (result), offset++, FALSE);
4513 emitcode ("rl", "%s", l);
4515 emitLabel (tlbl1->key + 100);
4516 emitcode ("dec", "a");
4517 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4519 freeAsmop (left, NULL, ic);
4520 freeAsmop (result, NULL, ic);
4523 /*-----------------------------------------------------------------*/
4524 /* genrshOne - left shift two bytes by known amount != 0 */
4525 /*-----------------------------------------------------------------*/
4527 genrshOne (operand * result, operand * left, int shCount)
4530 int size = AOP_SIZE (result);
4533 wassert (size == 1);
4534 wassert (shCount < 8);
4536 l = aopGet (AOP (left), 0, FALSE);
4537 if (AOP (result)->type == AOP_REG)
4539 aopPut (AOP (result), l, 0);
4540 l = aopGet (AOP (result), 0, FALSE);
4542 emitcode ("srl", "%s", l);
4549 emitcode ("srl", "a");
4551 aopPut (AOP (result), "a", 0);
4555 /*-----------------------------------------------------------------*/
4556 /* AccRsh - right shift accumulator by known count */
4557 /*-----------------------------------------------------------------*/
4559 AccRsh (int shCount)
4563 /* rotate right accumulator */
4564 AccRol (8 - shCount);
4565 /* and kill the higher order bits */
4566 emit2 ("and a,!immedbyte", SRMask[shCount]);
4570 /*-----------------------------------------------------------------*/
4571 /* shiftR1Left2Result - shift right one byte from left to result */
4572 /*-----------------------------------------------------------------*/
4574 shiftR1Left2Result (operand * left, int offl,
4575 operand * result, int offr,
4576 int shCount, int sign)
4578 MOVA (aopGet (AOP (left), offl, FALSE));
4587 aopPut (AOP (result), "a", offr);
4590 /*-----------------------------------------------------------------*/
4591 /* genrshTwo - right shift two bytes by known amount != 0 */
4592 /*-----------------------------------------------------------------*/
4594 genrshTwo (operand * result, operand * left,
4595 int shCount, int sign)
4597 /* if shCount >= 8 */
4603 shiftR1Left2Result (left, MSB16, result, LSB,
4608 movLeft2Result (left, MSB16, result, LSB, sign);
4610 aopPut (AOP (result), zero, 1);
4612 /* 1 <= shCount <= 7 */
4615 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4619 /*-----------------------------------------------------------------*/
4620 /* genRightShiftLiteral - left shifting by known count */
4621 /*-----------------------------------------------------------------*/
4623 genRightShiftLiteral (operand * left,
4628 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4631 freeAsmop (right, NULL, ic);
4633 aopOp (left, ic, FALSE, FALSE);
4634 aopOp (result, ic, FALSE, FALSE);
4636 size = getSize (operandType (result));
4638 emitcode ("; shift right ", "result %d, left %d", size,
4641 /* I suppose that the left size >= result size */
4647 else if (shCount >= (size * 8))
4649 aopPut (AOP (result), zero, size);
4655 genrshOne (result, left, shCount);
4658 /* PENDING: sign support */
4659 genrshTwo (result, left, shCount, FALSE);
4668 freeAsmop (left, NULL, ic);
4669 freeAsmop (result, NULL, ic);
4672 /*-----------------------------------------------------------------*/
4673 /* genRightShift - generate code for right shifting */
4674 /*-----------------------------------------------------------------*/
4676 genRightShift (iCode * ic)
4678 operand *right, *left, *result;
4680 int size, offset, first = 1;
4684 symbol *tlbl, *tlbl1;
4686 /* if signed then we do it the hard way preserve the
4687 sign bit moving it inwards */
4688 retype = getSpec (operandType (IC_RESULT (ic)));
4690 is_signed = !SPEC_USIGN (retype);
4692 /* signed & unsigned types are treated the same : i.e. the
4693 signed is NOT propagated inwards : quoting from the
4694 ANSI - standard : "for E1 >> E2, is equivalent to division
4695 by 2**E2 if unsigned or if it has a non-negative value,
4696 otherwise the result is implementation defined ", MY definition
4697 is that the sign does not get propagated */
4699 right = IC_RIGHT (ic);
4700 left = IC_LEFT (ic);
4701 result = IC_RESULT (ic);
4703 aopOp (right, ic, FALSE, FALSE);
4705 /* if the shift count is known then do it
4706 as efficiently as possible */
4707 if (AOP_TYPE (right) == AOP_LIT)
4709 genRightShiftLiteral (left, right, result, ic);
4713 aopOp (left, ic, FALSE, FALSE);
4714 aopOp (result, ic, FALSE, FALSE);
4716 /* now move the left to the result if they are not the
4718 if (!sameRegs (AOP (left), AOP (result)) &&
4719 AOP_SIZE (result) > 1)
4722 size = AOP_SIZE (result);
4726 l = aopGet (AOP (left), offset, FALSE);
4727 aopPut (AOP (result), l, offset);
4732 emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4733 emitcode ("inc", "a");
4734 freeAsmop (right, NULL, ic);
4736 tlbl = newiTempLabel (NULL);
4737 tlbl1 = newiTempLabel (NULL);
4738 size = AOP_SIZE (result);
4741 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4742 emitLabel (tlbl->key + 100);
4745 l = aopGet (AOP (result), offset--, FALSE);
4749 emitcode ("sra", "%s", l);
4751 emitcode ("srl", "%s", l);
4755 emitcode ("rr", "%s", l);
4757 emitLabel (tlbl1->key + 100);
4758 emitcode ("dec", "a");
4759 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4761 freeAsmop (left, NULL, ic);
4762 freeAsmop (result, NULL, ic);
4765 /*-----------------------------------------------------------------*/
4766 /* genGenPointerGet - get value from generic pointer space */
4767 /*-----------------------------------------------------------------*/
4769 genGenPointerGet (operand * left,
4770 operand * result, iCode * ic)
4773 sym_link *retype = getSpec (operandType (result));
4779 aopOp (left, ic, FALSE, FALSE);
4780 aopOp (result, ic, FALSE, FALSE);
4782 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4785 if (isPtrPair (AOP (left)))
4787 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4788 aopPut (AOP (result), buffer, 0);
4792 emit2 ("ld a,!*pair", getPairName (AOP (left)));
4793 aopPut (AOP (result), "a", 0);
4795 freeAsmop (left, NULL, ic);
4799 /* For now we always load into IY */
4800 /* if this is remateriazable */
4801 fetchPair (pair, AOP (left));
4803 /* so iy now contains the address */
4804 freeAsmop (left, NULL, ic);
4806 /* if bit then unpack */
4807 if (IS_BITVAR (retype))
4813 size = AOP_SIZE (result);
4818 /* PENDING: make this better */
4819 if (!IS_GB && AOP (result)->type == AOP_REG)
4821 aopPut (AOP (result), "!*hl", offset++);
4825 emit2 ("ld a,!*pair", _pairs[pair].name);
4826 aopPut (AOP (result), "a", offset++);
4830 emit2 ("inc %s", _pairs[pair].name);
4831 _G.pairs[pair].offset++;
4837 freeAsmop (result, NULL, ic);
4840 /*-----------------------------------------------------------------*/
4841 /* genPointerGet - generate code for pointer get */
4842 /*-----------------------------------------------------------------*/
4844 genPointerGet (iCode * ic)
4846 operand *left, *result;
4847 sym_link *type, *etype;
4849 left = IC_LEFT (ic);
4850 result = IC_RESULT (ic);
4852 /* depending on the type of pointer we need to
4853 move it to the correct pointer register */
4854 type = operandType (left);
4855 etype = getSpec (type);
4857 genGenPointerGet (left, result, ic);
4861 isRegOrLit (asmop * aop)
4863 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4868 /*-----------------------------------------------------------------*/
4869 /* genGenPointerSet - stores the value into a pointer location */
4870 /*-----------------------------------------------------------------*/
4872 genGenPointerSet (operand * right,
4873 operand * result, iCode * ic)
4876 sym_link *retype = getSpec (operandType (right));
4877 PAIR_ID pairId = PAIR_HL;
4879 aopOp (result, ic, FALSE, FALSE);
4880 aopOp (right, ic, FALSE, FALSE);
4885 /* Handle the exceptions first */
4886 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
4889 char *l = aopGet (AOP (right), 0, FALSE);
4890 const char *pair = getPairName (AOP (result));
4891 if (canAssignToPtr (l) && isPtr (pair))
4893 emit2 ("ld !*pair,%s", pair, l);
4898 emit2 ("ld !*pair,a", pair);
4903 /* if the operand is already in dptr
4904 then we do nothing else we move the value to dptr */
4905 if (AOP_TYPE (result) != AOP_STR)
4907 fetchPair (pairId, AOP (result));
4909 /* so hl know contains the address */
4910 freeAsmop (result, NULL, ic);
4912 /* if bit then unpack */
4913 if (IS_BITVAR (retype))
4919 size = AOP_SIZE (right);
4924 char *l = aopGet (AOP (right), offset, FALSE);
4925 if (isRegOrLit (AOP (right)) && !IS_GB)
4927 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
4932 emit2 ("ld !*pair,a", _pairs[pairId].name);
4936 emitcode ("inc", _pairs[pairId].name);
4937 _G.pairs[pairId].offset++;
4943 freeAsmop (right, NULL, ic);
4946 /*-----------------------------------------------------------------*/
4947 /* genPointerSet - stores the value into a pointer location */
4948 /*-----------------------------------------------------------------*/
4950 genPointerSet (iCode * ic)
4952 operand *right, *result;
4953 sym_link *type, *etype;
4955 right = IC_RIGHT (ic);
4956 result = IC_RESULT (ic);
4958 /* depending on the type of pointer we need to
4959 move it to the correct pointer register */
4960 type = operandType (result);
4961 etype = getSpec (type);
4963 genGenPointerSet (right, result, ic);
4966 /*-----------------------------------------------------------------*/
4967 /* genIfx - generate code for Ifx statement */
4968 /*-----------------------------------------------------------------*/
4970 genIfx (iCode * ic, iCode * popIc)
4972 operand *cond = IC_COND (ic);
4975 aopOp (cond, ic, FALSE, TRUE);
4977 /* get the value into acc */
4978 if (AOP_TYPE (cond) != AOP_CRY)
4982 /* the result is now in the accumulator */
4983 freeAsmop (cond, NULL, ic);
4985 /* if there was something to be popped then do it */
4989 /* if the condition is a bit variable */
4990 if (isbit && IS_ITEMP (cond) &&
4992 genIfxJump (ic, SPIL_LOC (cond)->rname);
4993 else if (isbit && !IS_ITEMP (cond))
4994 genIfxJump (ic, OP_SYMBOL (cond)->rname);
4996 genIfxJump (ic, "a");
5001 /*-----------------------------------------------------------------*/
5002 /* genAddrOf - generates code for address of */
5003 /*-----------------------------------------------------------------*/
5005 genAddrOf (iCode * ic)
5007 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5009 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5011 /* if the operand is on the stack then we
5012 need to get the stack offset of this
5019 if (sym->stack <= 0)
5021 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5025 emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5027 emitcode ("ld", "d,h");
5028 emitcode ("ld", "e,l");
5032 emit2 ("ld de,!hashedstr", sym->rname);
5034 aopPut (AOP (IC_RESULT (ic)), "e", 0);
5035 aopPut (AOP (IC_RESULT (ic)), "d", 1);
5042 /* if it has an offset then we need to compute it */
5044 emitcode ("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5046 emitcode ("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5047 emitcode ("add", "hl,sp");
5051 emitcode ("ld", "hl,#%s", sym->rname);
5053 aopPut (AOP (IC_RESULT (ic)), "l", 0);
5054 aopPut (AOP (IC_RESULT (ic)), "h", 1);
5056 freeAsmop (IC_RESULT (ic), NULL, ic);
5059 /*-----------------------------------------------------------------*/
5060 /* genAssign - generate code for assignment */
5061 /*-----------------------------------------------------------------*/
5063 genAssign (iCode * ic)
5065 operand *result, *right;
5067 unsigned long lit = 0L;
5069 result = IC_RESULT (ic);
5070 right = IC_RIGHT (ic);
5073 /* Dont bother assigning if they are the same */
5074 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5076 emitcode ("", "; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5081 aopOp (right, ic, FALSE, FALSE);
5082 aopOp (result, ic, TRUE, FALSE);
5084 /* if they are the same registers */
5085 if (sameRegs (AOP (right), AOP (result)))
5087 emitcode ("", "; (registers are the same)");
5091 /* if the result is a bit */
5092 if (AOP_TYPE (result) == AOP_CRY)
5098 size = AOP_SIZE (result);
5101 if (AOP_TYPE (right) == AOP_LIT)
5102 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5103 if (isPair (AOP (result)))
5105 fetchPair (getPairId (AOP (result)), AOP (right));
5107 else if ((size > 1) &&
5108 (AOP_TYPE (result) != AOP_REG) &&
5109 (AOP_TYPE (right) == AOP_LIT) &&
5110 !IS_FLOAT (operandType (right)) &&
5113 bool fXored = FALSE;
5115 /* Work from the top down.
5116 Done this way so that we can use the cached copy of 0
5117 in A for a fast clear */
5120 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5122 if (!fXored && size > 1)
5124 emitcode ("xor", "a,a");
5129 aopPut (AOP (result), "a", offset);
5133 aopPut (AOP (result), zero, offset);
5137 aopPut (AOP (result),
5138 aopGet (AOP (right), offset, FALSE),
5143 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5145 /* Special case. Load into a and d, then load out. */
5146 MOVA (aopGet (AOP (right), 0, FALSE));
5147 emitcode ("ld", "e,%s", aopGet (AOP (right), 1, FALSE));
5148 aopPut (AOP (result), "a", 0);
5149 aopPut (AOP (result), "e", 1);
5155 /* PENDING: do this check better */
5156 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5158 MOVA (aopGet (AOP (right), offset, FALSE));
5159 aopPut (AOP (result), "a", offset);
5162 aopPut (AOP (result),
5163 aopGet (AOP (right), offset, FALSE),
5170 freeAsmop (right, NULL, ic);
5171 freeAsmop (result, NULL, ic);
5174 /*-----------------------------------------------------------------*/
5175 /* genJumpTab - genrates code for jump table */
5176 /*-----------------------------------------------------------------*/
5178 genJumpTab (iCode * ic)
5183 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5184 /* get the condition into accumulator */
5185 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5187 emitcode ("push", "de");
5188 emitcode ("ld", "e,%s", l);
5189 emit2 ("ld d,!zero");
5190 jtab = newiTempLabel (NULL);
5192 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5193 emitcode ("add", "hl,de");
5194 emitcode ("add", "hl,de");
5195 emitcode ("add", "hl,de");
5196 freeAsmop (IC_JTCOND (ic), NULL, ic);
5198 emitcode ("pop", "de");
5200 emitLabel (jtab->key + 100);
5201 /* now generate the jump labels */
5202 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5203 jtab = setNextItem (IC_JTLABELS (ic)))
5204 emit2 ("jp !tlabel", jtab->key + 100);
5207 /*-----------------------------------------------------------------*/
5208 /* genCast - gen code for casting */
5209 /*-----------------------------------------------------------------*/
5211 genCast (iCode * ic)
5213 operand *result = IC_RESULT (ic);
5214 sym_link *ctype = operandType (IC_LEFT (ic));
5215 operand *right = IC_RIGHT (ic);
5218 /* if they are equivalent then do nothing */
5219 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5222 aopOp (right, ic, FALSE, FALSE);
5223 aopOp (result, ic, FALSE, FALSE);
5225 /* if the result is a bit */
5226 if (AOP_TYPE (result) == AOP_CRY)
5231 /* if they are the same size : or less */
5232 if (AOP_SIZE (result) <= AOP_SIZE (right))
5235 /* if they are in the same place */
5236 if (sameRegs (AOP (right), AOP (result)))
5239 /* if they in different places then copy */
5240 size = AOP_SIZE (result);
5244 aopPut (AOP (result),
5245 aopGet (AOP (right), offset, FALSE),
5252 /* PENDING: should be OK. */
5254 /* if the result is of type pointer */
5261 /* so we now know that the size of destination is greater
5262 than the size of the source */
5263 /* we move to result for the size of source */
5264 size = AOP_SIZE (right);
5268 aopPut (AOP (result),
5269 aopGet (AOP (right), offset, FALSE),
5274 /* now depending on the sign of the destination */
5275 size = AOP_SIZE (result) - AOP_SIZE (right);
5276 /* Unsigned or not an integral type - right fill with zeros */
5277 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5280 aopPut (AOP (result), zero, offset++);
5284 /* we need to extend the sign :{ */
5285 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5288 emitcode ("", "; genCast: sign extend untested.");
5289 emitcode ("rla", "");
5290 emitcode ("sbc", "a,a");
5292 aopPut (AOP (result), "a", offset++);
5296 freeAsmop (right, NULL, ic);
5297 freeAsmop (result, NULL, ic);
5300 /*-----------------------------------------------------------------*/
5301 /* genReceive - generate code for a receive iCode */
5302 /*-----------------------------------------------------------------*/
5304 genReceive (iCode * ic)
5306 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5307 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5308 IS_TRUE_SYMOP (IC_RESULT (ic))))
5318 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5319 size = AOP_SIZE(IC_RESULT(ic));
5321 for (i = 0; i < size; i++) {
5322 aopPut(AOP(IC_RESULT(ic)), _fReturn[_G.receiveOffset++], i);
5326 freeAsmop (IC_RESULT (ic), NULL, ic);
5329 /*-----------------------------------------------------------------*/
5330 /* genZ80Code - generate code for Z80 based controllers */
5331 /*-----------------------------------------------------------------*/
5333 genZ80Code (iCode * lic)
5341 _fReturn = _gbz80_return;
5342 _fTmp = _gbz80_return;
5346 _fReturn = _z80_return;
5347 _fTmp = _z80_return;
5349 tsprintf (zero, "!zero");
5351 lineHead = lineCurr = NULL;
5353 /* if debug information required */
5354 if (options.debug && currFunc)
5356 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5358 if (IS_STATIC (currFunc->etype))
5359 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
5361 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
5364 /* stack pointer 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;