1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Michael Hope <michaelh@juju.net.nz> 2000
5 Based on the mcs51 generator -
6 Sandeep Dutta . sandeep.dutta@usa.net (1998)
7 and - Jean-Louis VERN.jlvern@writeme.com (1999)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
28 -------------------------------------------------------------------------*/
31 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
33 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
34 Improved WORD push 22784 144 19AE
35 With label1 on 22694 144 197E
36 With label2 on 22743 144 198A
37 With label3 on 22776 144 1999
38 With label4 on 22776 144 1999
39 With all 'label' on 22661 144 196F
40 With loopInvariant on 20919 156 19AB
41 With loopInduction on Breaks 198B
42 With all working on 20796 158 196C
43 Slightly better genCmp(signed) 20597 159 195B
44 Better reg packing, first peephole 20038 163 1873
45 With assign packing 19281 165 1849
47 With reg params for mul and div 16234 202 162D
49 1. Starting again at 3 Aug 01 34965 93 219C
51 Includes long mul/div in code
52 2. Optimised memcpy for acc use 32102 102 226B
53 3. Optimised strcpy for acc use 27819 117 2237
54 3a Optimised memcpy fun
55 4. Optimised strcmp fun 21999 149 2294
56 5. Optimised strcmp further 21660 151 228C
57 6. Optimised memcpy by unroling 20885 157 2201
58 7. After turning loop induction on 19862 165 236D
59 8. Same as 7 but with more info
60 9. With asm optimised strings 17030 192 2223
62 10 and below are with asm strings off.
64 Apparent advantage of turning on regparams:
66 Decent case is push of a constant
67 - ld hl,#n; push hl: (10+11)*nargs
68 2. Cost of pull from stack
69 Using asm with ld hl, etc
70 - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
72 3. Cost of fixing stack
76 So cost is (10+11+7+6+7+10)*nargs+10+11
78 = 123 for mul, div, strcmp, strcpy
79 Saving of (98298+32766+32766+32766)*123 = 24181308
80 At 192 d/s for 682411768t, speed up to 199. Hmm.
88 #ifdef HAVE_SYS_ISA_DEFS_H
89 #include <sys/isa_defs.h>
93 #include "SDCCglobl.h"
94 #include "SDCCpeeph.h"
99 /* This is the down and dirty file with all kinds of kludgy & hacky
100 stuff. This is what it is all about CODE GENERATION for a specific MCU.
101 Some of the routines may be reusable, will have to see */
103 /* Z80 calling convention description.
104 Parameters are passed right to left. As the stack grows downwards,
105 the parameters are arranged in left to right in memory.
106 Parameters may be passed in the HL and DE registers with one
108 PENDING: What if the parameter is a long?
109 Everything is caller saves. i.e. the caller must save any registers
110 that it wants to preserve over the call.
111 GB: The return value is returned in DEHL. DE is normally used as a
112 working register pair. Caller saves allows it to be used for a
114 va args functions do not use register parameters. All arguments
115 are passed on the stack.
116 IX is used as an index register to the top of the local variable
117 area. ix-0 is the top most local variable.
122 /* Set to enable debugging trace statements in the output assembly code. */
126 static char *_z80_return[] =
127 {"l", "h", "e", "d"};
128 static char *_gbz80_return[] =
129 {"e", "d", "l", "h"};
130 static char *_fReceive[] =
131 { "c", "b", "e", "d" };
133 static char **_fReturn;
136 extern FILE *codeOutFile;
144 /** Enum covering all the possible register pairs.
163 } _pairs[NUM_PAIRS] = {
164 { "??1", "?2", "?3" },
169 { "iy", "iyl", "iyh" },
170 { "ix", "ixl", "ixh" }
174 #define ACC_NAME _pairs[PAIR_AF].h
184 /** Code generator persistent data.
188 /** Used to optimised setting up of a pair by remebering what it
189 contains and adjusting instead of reloading where possible.
210 const char *lastFunctionName;
216 /** TRUE if the registers have already been saved. */
234 static const char *aopGet (asmop * aop, int offset, bool bit16);
250 _getTempPairName(void)
252 return _pairs[_getTempPairId()].name;
256 getFreePairId (iCode *ic)
258 if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
262 else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
275 /* Clean up the line so that it is 'prettier' */
276 if (strchr (buf, ':'))
278 /* Is a label - cant do anything */
281 /* Change the first (and probably only) ' ' to a tab so
296 _newLineNode (char *line)
300 pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
301 pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
307 _vemit2 (const char *szFormat, va_list ap)
311 tvsprintf (buffer, szFormat, ap);
314 _G.lines.current = (_G.lines.current ?
315 connectLine (_G.lines.current, _newLineNode (buffer)) :
316 (_G.lines.head = _newLineNode (buffer)));
318 _G.lines.current->isInline = _G.lines.isInline;
322 emit2 (const char *szFormat,...)
326 va_start (ap, szFormat);
328 _vemit2 (szFormat, ap);
334 emitDebug (const char *szFormat,...)
340 va_start (ap, szFormat);
342 _vemit2 (szFormat, ap);
348 /*-----------------------------------------------------------------*/
349 /* emit2 - writes the code into a file : for now it is simple */
350 /*-----------------------------------------------------------------*/
352 _emit2 (const char *inst, const char *fmt,...)
355 char lb[INITIAL_INLINEASM];
362 sprintf (lb, "%s\t", inst);
363 vsprintf (lb + (strlen (lb)), fmt, ap);
366 vsprintf (lb, fmt, ap);
368 while (isspace (*lbp))
373 _G.lines.current = (_G.lines.current ?
374 connectLine (_G.lines.current, _newLineNode (lb)) :
375 (_G.lines.head = _newLineNode (lb)));
377 _G.lines.current->isInline = _G.lines.isInline;
382 _emitMove(const char *to, const char *from)
384 if (strcasecmp(to, from) != 0)
386 emit2("ld %s,%s", to, from);
391 // Could leave this to the peephole, but sometimes the peephole is inhibited.
396 _moveA(const char *moveFrom)
398 // Let the peephole optimiser take care of redundent loads
399 _emitMove(ACC_NAME, moveFrom);
409 getPairName (asmop * aop)
411 if (aop->type == AOP_REG)
413 switch (aop->aopu.aop_reg[0]->rIdx)
426 else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
429 for (i = 0; i < NUM_PAIRS; i++)
431 if (strcmp(aop->aopu.aop_str[0], _pairs[i].l) == 0)
433 return _pairs[i].name;
437 wassertl (0, "Tried to get the pair name of something that isn't a pair");
442 getPairId (asmop * aop)
446 if (aop->type == AOP_REG)
448 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
452 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
456 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
461 else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
464 for (i = 0; i < NUM_PAIRS; i++)
466 if (!strcmp (aop->aopu.aop_str[0], _pairs[i].l) && !strcmp (aop->aopu.aop_str[1], _pairs[i].h))
476 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
480 return (getPairId (aop) != PAIR_INVALID);
484 isPtrPair (asmop * aop)
486 PAIR_ID pairId = getPairId (aop);
499 spillPair (PAIR_ID pairId)
501 _G.pairs[pairId].last_type = AOP_INVALID;
502 _G.pairs[pairId].base = NULL;
505 /** Push a register pair onto the stack */
507 genPairPush (asmop * aop)
509 emit2 ("push %s", getPairName (aop));
513 _push (PAIR_ID pairId)
515 emit2 ("push %s", _pairs[pairId].name);
516 _G.stack.pushed += 2;
520 _pop (PAIR_ID pairId)
522 emit2 ("pop %s", _pairs[pairId].name);
523 _G.stack.pushed -= 2;
527 /*-----------------------------------------------------------------*/
528 /* newAsmop - creates a new asmOp */
529 /*-----------------------------------------------------------------*/
531 newAsmop (short type)
535 aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
540 /*-----------------------------------------------------------------*/
541 /* aopForSym - for a true symbol */
542 /*-----------------------------------------------------------------*/
544 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
551 wassert (sym->etype);
553 space = SPEC_OCLS (sym->etype);
555 /* if already has one */
559 /* Assign depending on the storage class */
560 if (sym->onStack || sym->iaccess)
562 /* The pointer that is used depends on how big the offset is.
563 Normally everything is AOP_STK, but for offsets of < -128 or
564 > 127 on the Z80 an extended stack pointer is used.
566 if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
568 emitDebug ("; AOP_EXSTK for %s", sym->rname);
569 sym->aop = aop = newAsmop (AOP_EXSTK);
573 emitDebug ("; AOP_STK for %s", sym->rname);
574 sym->aop = aop = newAsmop (AOP_STK);
577 aop->size = getSize (sym->type);
578 aop->aopu.aop_stk = sym->stack;
582 /* special case for a function */
583 if (IS_FUNC (sym->type))
585 sym->aop = aop = newAsmop (AOP_IMMD);
586 aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
593 /* if it is in direct space */
594 if (IN_REGSP (space) && !requires_a)
596 sym->aop = aop = newAsmop (AOP_SFR);
597 aop->aopu.aop_dir = sym->rname;
598 aop->size = getSize (sym->type);
599 emitDebug ("; AOP_SFR for %s", sym->rname);
604 /* only remaining is far space */
605 /* in which case DPTR gets the address */
608 emitDebug ("; AOP_HL for %s", sym->rname);
609 sym->aop = aop = newAsmop (AOP_HL);
613 sym->aop = aop = newAsmop (AOP_IY);
615 aop->size = getSize (sym->type);
616 aop->aopu.aop_dir = sym->rname;
618 /* if it is in code space */
619 if (IN_CODESPACE (space))
625 /*-----------------------------------------------------------------*/
626 /* aopForRemat - rematerialzes an object */
627 /*-----------------------------------------------------------------*/
629 aopForRemat (symbol * sym)
632 iCode *ic = sym->rematiCode;
633 asmop *aop = newAsmop (AOP_IMMD);
637 /* if plus or minus print the right hand side */
638 if (ic->op == '+' || ic->op == '-')
640 /* PENDING: for re-target */
641 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
644 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
647 /* we reached the end */
648 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
652 aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
656 /*-----------------------------------------------------------------*/
657 /* regsInCommon - two operands have some registers in common */
658 /*-----------------------------------------------------------------*/
660 regsInCommon (operand * op1, operand * op2)
665 /* if they have registers in common */
666 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
669 sym1 = OP_SYMBOL (op1);
670 sym2 = OP_SYMBOL (op2);
672 if (sym1->nRegs == 0 || sym2->nRegs == 0)
675 for (i = 0; i < sym1->nRegs; i++)
681 for (j = 0; j < sym2->nRegs; j++)
686 if (sym2->regs[j] == sym1->regs[i])
694 /*-----------------------------------------------------------------*/
695 /* operandsEqu - equivalent */
696 /*-----------------------------------------------------------------*/
698 operandsEqu (operand * op1, operand * op2)
702 /* if they not symbols */
703 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
706 sym1 = OP_SYMBOL (op1);
707 sym2 = OP_SYMBOL (op2);
709 /* if both are itemps & one is spilt
710 and the other is not then false */
711 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
712 sym1->isspilt != sym2->isspilt)
715 /* if they are the same */
719 if (strcmp (sym1->rname, sym2->rname) == 0)
723 /* if left is a tmp & right is not */
724 if (IS_ITEMP (op1) &&
727 (sym1->usl.spillLoc == sym2))
730 if (IS_ITEMP (op2) &&
734 (sym2->usl.spillLoc == sym1))
740 /*-----------------------------------------------------------------*/
741 /* sameRegs - two asmops have the same registers */
742 /*-----------------------------------------------------------------*/
744 sameRegs (asmop * aop1, asmop * aop2)
748 if (aop1->type == AOP_SFR ||
749 aop2->type == AOP_SFR)
755 if (aop1->type != AOP_REG ||
756 aop2->type != AOP_REG)
759 if (aop1->size != aop2->size)
762 for (i = 0; i < aop1->size; i++)
763 if (aop1->aopu.aop_reg[i] !=
764 aop2->aopu.aop_reg[i])
770 /*-----------------------------------------------------------------*/
771 /* aopOp - allocates an asmop for an operand : */
772 /*-----------------------------------------------------------------*/
774 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
783 /* if this a literal */
784 if (IS_OP_LITERAL (op))
786 op->aop = aop = newAsmop (AOP_LIT);
787 aop->aopu.aop_lit = op->operand.valOperand;
788 aop->size = getSize (operandType (op));
792 /* if already has a asmop then continue */
796 /* if the underlying symbol has a aop */
797 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
799 op->aop = OP_SYMBOL (op)->aop;
803 /* if this is a true symbol */
804 if (IS_TRUE_SYMOP (op))
806 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
810 /* this is a temporary : this has
816 e) can be a return use only */
818 sym = OP_SYMBOL (op);
820 /* if the type is a conditional */
821 if (sym->regType == REG_CND)
823 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
828 /* if it is spilt then two situations
830 b) has a spill location */
831 if (sym->isspilt || sym->nRegs == 0)
833 /* rematerialize it NOW */
836 sym->aop = op->aop = aop =
838 aop->size = getSize (sym->type);
845 aop = op->aop = sym->aop = newAsmop (AOP_STR);
846 aop->size = getSize (sym->type);
847 for (i = 0; i < 4; i++)
848 aop->aopu.aop_str[i] = _fReturn[i];
854 if (sym->accuse == ACCUSE_A)
856 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
857 aop->size = getSize (sym->type);
858 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
860 aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
862 else if (sym->accuse == ACCUSE_SCRATCH)
864 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
865 aop->size = getSize (sym->type);
866 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
867 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
868 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
870 else if (sym->accuse == ACCUSE_IY)
872 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
873 aop->size = getSize (sym->type);
874 wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY");
875 aop->aopu.aop_str[0] = _pairs[PAIR_IY].l;
876 aop->aopu.aop_str[1] = _pairs[PAIR_IY].h;
880 wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
885 /* else spill location */
886 sym->aop = op->aop = aop =
887 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
888 aop->size = getSize (sym->type);
892 /* must be in a register */
893 sym->aop = op->aop = aop = newAsmop (AOP_REG);
894 aop->size = sym->nRegs;
895 for (i = 0; i < sym->nRegs; i++)
896 aop->aopu.aop_reg[i] = sym->regs[i];
899 /*-----------------------------------------------------------------*/
900 /* freeAsmop - free up the asmop given to an operand */
901 /*----------------------------------------------------------------*/
903 freeAsmop (operand * op, asmop * aaop, iCode * ic)
920 if (aop->type == AOP_PAIRPTR && IS_Z80 && aop->aopu.aop_pairId == PAIR_DE)
922 _pop (aop->aopu.aop_pairId);
926 /* all other cases just dealloc */
932 OP_SYMBOL (op)->aop = NULL;
933 /* if the symbol has a spill */
935 SPIL_LOC (op)->aop = NULL;
942 isLitWord (asmop * aop)
944 /* if (aop->size != 2)
957 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
961 /* depending on type */
967 /* PENDING: for re-target */
970 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
972 else if (offset == 0)
974 tsprintf (s, "%s", aop->aopu.aop_immd);
978 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
980 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
984 value *val = aop->aopu.aop_lit;
985 /* if it is a float then it gets tricky */
986 /* otherwise it is fairly simple */
987 if (!IS_FLOAT (val->type))
989 unsigned long v = (unsigned long) floatFromVal (val);
995 else if (offset == 0)
1001 wassertl(0, "Encountered an invalid offset while fetching a literal");
1005 tsprintf (buffer, "!immedword", v);
1007 tsprintf (buffer, "!constword", v);
1009 return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1020 /* it is type float */
1021 fl.f = (float) floatFromVal (val);
1024 i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
1026 i = fl.c[offset] | (fl.c[offset+1]<<8);
1029 tsprintf (buffer, "!immedword", i);
1031 tsprintf (buffer, "!constword", i);
1033 return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1042 aopGetWord (asmop * aop, int offset)
1044 return aopGetLitWordLong (aop, offset, TRUE);
1048 isPtr (const char *s)
1050 if (!strcmp (s, "hl"))
1052 if (!strcmp (s, "ix"))
1054 if (!strcmp (s, "iy"))
1060 adjustPair (const char *pair, int *pold, int new)
1066 emit2 ("inc %s", pair);
1071 emit2 ("dec %s", pair);
1079 spillPair (PAIR_HL);
1080 spillPair (PAIR_IY);
1084 requiresHL (asmop * aop)
1100 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
1102 const char *l, *base;
1103 const char *pair = _pairs[pairId].name;
1104 l = aopGetLitWordLong (left, offset, FALSE);
1105 base = aopGetLitWordLong (left, 0, FALSE);
1106 wassert (l && pair && base);
1110 if (pairId == PAIR_HL || pairId == PAIR_IY)
1112 if (_G.pairs[pairId].last_type == left->type)
1114 if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
1116 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
1118 adjustPair (pair, &_G.pairs[pairId].offset, offset);
1121 if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
1128 _G.pairs[pairId].last_type = left->type;
1129 _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
1130 _G.pairs[pairId].offset = offset;
1132 /* Both a lit on the right and a true symbol on the left */
1133 emit2 ("ld %s,!hashedstr", pair, l);
1137 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
1139 /* if this is remateriazable */
1140 if (isLitWord (aop)) {
1141 fetchLitPair (pairId, aop, offset);
1145 if (getPairId (aop) == pairId)
1149 /* we need to get it byte by byte */
1150 else if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1151 aopGet (aop, offset, FALSE);
1152 switch (aop->size - offset) {
1154 emit2 ("ld l,!*hl");
1155 emit2 ("ld h,!immedbyte", 0);
1158 // PENDING: Requires that you are only fetching two bytes.
1161 emit2 ("ld h,!*hl");
1165 wassertl (0, "Attempted to fetch too much data into HL");
1169 else if (IS_Z80 && aop->type == AOP_IY) {
1170 /* Instead of fetching relative to IY, just grab directly
1171 from the address IY refers to */
1172 char *l = aopGetLitWordLong (aop, offset, FALSE);
1174 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1176 if (aop->size < 2) {
1177 emit2("ld %s,!zero", _pairs[pairId].h);
1180 else if (pairId == PAIR_IY)
1184 emit2 ("push %s", _pairs[getPairId(aop)].name);
1190 /* Can't load into parts, so load into HL then exchange. */
1191 emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
1192 emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
1199 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1200 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1202 /* PENDING: check? */
1203 if (pairId == PAIR_HL)
1204 spillPair (PAIR_HL);
1209 fetchPair (PAIR_ID pairId, asmop * aop)
1211 fetchPairLong (pairId, aop, 0);
1215 fetchHL (asmop * aop)
1217 fetchPair (PAIR_HL, aop);
1221 setupPairFromSP (PAIR_ID id, int offset)
1223 wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
1225 if (offset < INT8MIN || offset > INT8MAX)
1227 emit2 ("ld hl,!immedword", offset);
1228 emit2 ("add hl,sp");
1232 emit2 ("!ldahlsp", offset);
1237 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1242 wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
1243 fetchLitPair (pairId, aop, 0);
1247 wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
1249 fetchLitPair (pairId, aop, offset);
1250 _G.pairs[pairId].offset = offset;
1254 wassertl (IS_Z80, "Only the Z80 has an extended stack");
1255 wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
1258 int offset = aop->aopu.aop_stk + _G.stack.offset;
1260 if (_G.pairs[pairId].last_type == aop->type &&
1261 _G.pairs[pairId].offset == offset)
1267 /* PENDING: Do this better. */
1268 sprintf (buffer, "%d", offset + _G.stack.pushed);
1269 emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
1270 emit2 ("add %s,sp", _pairs[pairId].name);
1271 _G.pairs[pairId].last_type = aop->type;
1272 _G.pairs[pairId].offset = offset;
1279 /* Doesnt include _G.stack.pushed */
1280 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1281 if (aop->aopu.aop_stk > 0)
1283 abso += _G.stack.param_offset;
1285 assert (pairId == PAIR_HL);
1286 /* In some cases we can still inc or dec hl */
1287 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1289 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1293 setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
1295 _G.pairs[pairId].offset = abso;
1300 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
1306 _G.pairs[pairId].last_type = aop->type;
1312 emit2 ("!tlabeldef", key);
1316 /*-----------------------------------------------------------------*/
1317 /* aopGet - for fetching value of the aop */
1318 /*-----------------------------------------------------------------*/
1320 aopGet (asmop * aop, int offset, bool bit16)
1324 /* offset is greater than size then zero */
1325 /* PENDING: this seems a bit screwed in some pointer cases. */
1326 if (offset > (aop->size - 1) &&
1327 aop->type != AOP_LIT)
1329 tsprintf (s, "!zero");
1330 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1333 /* depending on type */
1337 /* PENDING: re-target */
1339 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1344 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1347 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1350 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1353 wassertl (0, "Fetching from beyond the limits of an immediate value.");
1356 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1360 emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
1363 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1367 emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
1370 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1373 return aop->aopu.aop_reg[offset]->name;
1377 setupPair (PAIR_HL, aop, offset);
1378 tsprintf (s, "!*hl");
1380 return traceAlloc(&_G.trace.aops, Safe_strdup (s));
1384 setupPair (PAIR_IY, aop, offset);
1385 tsprintf (s, "!*iyx", offset);
1387 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1391 setupPair (PAIR_IY, aop, offset);
1392 tsprintf (s, "!*iyx", offset, offset);
1394 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1399 setupPair (PAIR_HL, aop, offset);
1400 tsprintf (s, "!*hl");
1404 if (aop->aopu.aop_stk >= 0)
1405 offset += _G.stack.param_offset;
1406 tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
1409 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1412 wassertl (0, "Tried to fetch from a bit variable");
1421 tsprintf(s, "!zero");
1422 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1426 wassert (offset < 2);
1427 return aop->aopu.aop_str[offset];
1430 return aopLiteral (aop->aopu.aop_lit, offset);
1434 unsigned long v = aop->aopu.aop_simplelit;
1437 tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
1439 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1443 return aop->aopu.aop_str[offset];
1446 setupPair (aop->aopu.aop_pairId, aop, offset);
1447 sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
1449 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1454 wassertl (0, "aopget got unsupported aop->type");
1459 isRegString (const char *s)
1461 if (!strcmp (s, "b") ||
1473 isConstant (const char *s)
1475 /* This is a bit of a hack... */
1476 return (*s == '#' || *s == '$');
1480 canAssignToPtr (const char *s)
1482 if (isRegString (s))
1489 /*-----------------------------------------------------------------*/
1490 /* aopPut - puts a string for a aop */
1491 /*-----------------------------------------------------------------*/
1493 aopPut (asmop * aop, const char *s, int offset)
1497 if (aop->size && offset > (aop->size - 1))
1499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1500 "aopPut got offset > aop->size");
1505 tsprintf(buffer2, s);
1508 /* will assign value to value */
1509 /* depending on where it is ofcourse */
1515 if (strcmp (s, "a"))
1516 emit2 ("ld a,%s", s);
1517 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1522 if (strcmp (s, "a"))
1523 emit2 ("ld a,%s", s);
1524 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1528 if (!strcmp (s, "!*hl"))
1529 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1532 aop->aopu.aop_reg[offset]->name, s);
1537 if (!canAssignToPtr (s))
1539 emit2 ("ld a,%s", s);
1540 setupPair (PAIR_IY, aop, offset);
1541 emit2 ("ld !*iyx,a", offset);
1545 setupPair (PAIR_IY, aop, offset);
1546 emit2 ("ld !*iyx,%s", offset, s);
1552 /* PENDING: for re-target */
1553 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1555 emit2 ("ld a,!*hl");
1558 setupPair (PAIR_HL, aop, offset);
1560 emit2 ("ld !*hl,%s", s);
1565 if (!canAssignToPtr (s))
1567 emit2 ("ld a,%s", s);
1568 setupPair (PAIR_IY, aop, offset);
1569 emit2 ("ld !*iyx,a", offset);
1573 setupPair (PAIR_IY, aop, offset);
1574 emit2 ("ld !*iyx,%s", offset, s);
1581 /* PENDING: re-target */
1582 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1584 emit2 ("ld a,!*hl");
1587 setupPair (PAIR_HL, aop, offset);
1588 if (!canAssignToPtr (s))
1590 emit2 ("ld a,%s", s);
1591 emit2 ("ld !*hl,a");
1594 emit2 ("ld !*hl,%s", s);
1598 if (aop->aopu.aop_stk >= 0)
1599 offset += _G.stack.param_offset;
1600 if (!canAssignToPtr (s))
1602 emit2 ("ld a,%s", s);
1603 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1607 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1613 /* if bit variable */
1614 if (!aop->aopu.aop_dir)
1621 /* In bit space but not in C - cant happen */
1622 wassertl (0, "Tried to write into a bit variable");
1628 if (strcmp (aop->aopu.aop_str[offset], s))
1630 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1636 if (!offset && (strcmp (s, "acc") == 0))
1640 wassertl (0, "Tried to access past the end of A");
1644 if (strcmp (aop->aopu.aop_str[offset], s))
1645 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1650 wassert (offset < 2);
1651 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1655 setupPair (aop->aopu.aop_pairId, aop, offset);
1656 emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
1660 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1661 "aopPut got unsupported aop->type");
1666 #define AOP(op) op->aop
1667 #define AOP_TYPE(op) AOP(op)->type
1668 #define AOP_SIZE(op) AOP(op)->size
1669 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1672 commitPair (asmop * aop, PAIR_ID id)
1674 /* PENDING: Verify this. */
1675 if (id == PAIR_HL && requiresHL (aop) && IS_GB)
1679 aopPut (aop, "a", 0);
1680 aopPut (aop, "d", 1);
1685 if (id == PAIR_HL && aop->type == AOP_IY && aop->size == 2)
1687 char *l = aopGetLitWordLong (aop, 0, FALSE);
1690 emit2 ("ld (%s),%s", l, _pairs[id].name);
1694 aopPut (aop, _pairs[id].l, 0);
1695 aopPut (aop, _pairs[id].h, 1);
1700 /*-----------------------------------------------------------------*/
1701 /* getDataSize - get the operand data size */
1702 /*-----------------------------------------------------------------*/
1704 getDataSize (operand * op)
1707 size = AOP_SIZE (op);
1711 wassertl (0, "Somehow got a three byte data pointer");
1716 /*-----------------------------------------------------------------*/
1717 /* movLeft2Result - move byte from left to result */
1718 /*-----------------------------------------------------------------*/
1720 movLeft2Result (operand * left, int offl,
1721 operand * result, int offr, int sign)
1725 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1727 l = aopGet (AOP (left), offl, FALSE);
1731 aopPut (AOP (result), l, offr);
1735 if (getDataSize (left) == offl + 1)
1737 emit2 ("ld a,%s", l);
1738 aopPut (AOP (result), "a", offr);
1745 movLeft2ResultLong (operand * left, int offl,
1746 operand * result, int offr, int sign,
1751 movLeft2Result (left, offl, result, offr, sign);
1755 wassertl (offl == 0 && offr == 0, "Only implemented for zero offset");
1756 wassertl (size == 2, "Only implemented for two bytes or one");
1758 if ( IS_GB && requiresHL ( AOP (left)) && getPairId ( AOP (result)) == PAIR_HL)
1760 emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
1761 emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
1764 else if ( getPairId ( AOP (result)) == PAIR_IY)
1766 PAIR_ID id = getPairId (AOP (left));
1767 if (id != PAIR_INVALID)
1769 emit2("push %s", _pairs[id].name);
1780 movLeft2Result (left, offl, result, offr, sign);
1781 movLeft2Result (left, offl+1, result, offr+1, sign);
1786 /** Put Acc into a register set
1789 outAcc (operand * result)
1792 size = getDataSize (result);
1795 aopPut (AOP (result), "a", 0);
1798 /* unsigned or positive */
1801 aopPut (AOP (result), "!zero", offset++);
1806 /** Take the value in carry and put it into a register
1809 outBitCLong (operand * result, bool swap_sense)
1811 /* if the result is bit */
1812 if (AOP_TYPE (result) == AOP_CRY)
1814 wassertl (0, "Tried to write carry to a bit");
1818 emit2 ("ld a,!zero");
1821 emit2 ("xor a,!immedbyte", 1);
1827 outBitC (operand * result)
1829 outBitCLong (result, FALSE);
1832 /*-----------------------------------------------------------------*/
1833 /* toBoolean - emit code for orl a,operator(sizeop) */
1834 /*-----------------------------------------------------------------*/
1836 _toBoolean (operand * oper)
1838 int size = AOP_SIZE (oper);
1842 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1845 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1849 if (AOP (oper)->type != AOP_ACC)
1852 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1857 /*-----------------------------------------------------------------*/
1858 /* genNotFloat - generates not for float operations */
1859 /*-----------------------------------------------------------------*/
1861 genNotFloat (operand * op, operand * res)
1866 emitDebug ("; genNotFloat");
1868 /* we will put 127 in the first byte of
1870 aopPut (AOP (res), "!immedbyte", 0x7F);
1871 size = AOP_SIZE (op) - 1;
1874 _moveA (aopGet (op->aop, offset++, FALSE));
1878 emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE));
1881 tlbl = newiTempLabel (NULL);
1882 aopPut (res->aop, "!one", 1);
1883 emit2 ("!shortjp z !tlabel", tlbl->key + 100);
1884 aopPut (res->aop, "!zero", 1);
1886 emitLabel(tlbl->key + 100);
1888 size = res->aop->size - 2;
1890 /* put zeros in the rest */
1892 aopPut (res->aop, "!zero", offset++);
1895 /*-----------------------------------------------------------------*/
1896 /* genNot - generate code for ! operation */
1897 /*-----------------------------------------------------------------*/
1901 sym_link *optype = operandType (IC_LEFT (ic));
1903 /* assign asmOps to operand & result */
1904 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1905 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1907 /* if in bit space then a special case */
1908 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1910 wassertl (0, "Tried to negate a bit");
1913 /* if type float then do float */
1914 if (IS_FLOAT (optype))
1916 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1920 _toBoolean (IC_LEFT (ic));
1925 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1926 emit2 ("sub a,!one");
1927 outBitC (IC_RESULT (ic));
1930 /* release the aops */
1931 freeAsmop (IC_LEFT (ic), NULL, ic);
1932 freeAsmop (IC_RESULT (ic), NULL, ic);
1935 /*-----------------------------------------------------------------*/
1936 /* genCpl - generate code for complement */
1937 /*-----------------------------------------------------------------*/
1945 /* assign asmOps to operand & result */
1946 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1947 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1949 /* if both are in bit space then
1951 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1952 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1954 wassertl (0, "Left and the result are in bit space");
1957 size = AOP_SIZE (IC_RESULT (ic));
1960 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1963 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1966 /* release the aops */
1967 freeAsmop (IC_LEFT (ic), NULL, ic);
1968 freeAsmop (IC_RESULT (ic), NULL, ic);
1972 _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
1979 store de into result
1984 store de into result
1986 const char *first = isAdd ? "add" : "sub";
1987 const char *later = isAdd ? "adc" : "sbc";
1989 wassertl (IS_GB, "Code is only relevent to the gbz80");
1990 wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
1992 fetchPair (PAIR_DE, left);
1995 emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
1998 emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
2001 aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
2002 aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
2004 fetchPairLong (PAIR_DE, left, MSB24);
2005 aopGet (right, MSB24, FALSE);
2009 emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
2012 emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
2014 aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
2015 aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
2019 _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
2021 _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
2024 /*-----------------------------------------------------------------*/
2025 /* genUminusFloat - unary minus for floating points */
2026 /*-----------------------------------------------------------------*/
2028 genUminusFloat (operand * op, operand * result)
2030 int size, offset = 0;
2032 emitDebug("; genUminusFloat");
2034 /* for this we just need to flip the
2035 first it then copy the rest in place */
2036 size = AOP_SIZE (op) - 1;
2038 _moveA(aopGet (AOP (op), MSB32, FALSE));
2040 emit2("xor a,!immedbyte", 0x80);
2041 aopPut (AOP (result), "a", MSB32);
2045 aopPut (AOP (result), aopGet (AOP (op), offset, FALSE), offset);
2050 /*-----------------------------------------------------------------*/
2051 /* genUminus - unary minus code generation */
2052 /*-----------------------------------------------------------------*/
2054 genUminus (iCode * ic)
2057 sym_link *optype, *rtype;
2060 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2061 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2063 /* if both in bit space then special
2065 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2066 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2068 wassertl (0, "Left and right are in bit space");
2072 optype = operandType (IC_LEFT (ic));
2073 rtype = operandType (IC_RESULT (ic));
2075 /* if float then do float stuff */
2076 if (IS_FLOAT (optype))
2078 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2082 /* otherwise subtract from zero */
2083 size = AOP_SIZE (IC_LEFT (ic));
2085 if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
2087 /* Create a new asmop with value zero */
2088 asmop *azero = newAsmop (AOP_SIMPLELIT);
2089 azero->aopu.aop_simplelit = 0;
2091 _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
2099 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2100 emit2 ("ld a,!zero");
2101 emit2 ("sbc a,%s", l);
2102 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2105 /* if any remaining bytes in the result */
2106 /* we just need to propagate the sign */
2107 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2112 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2116 /* release the aops */
2117 freeAsmop (IC_LEFT (ic), NULL, ic);
2118 freeAsmop (IC_RESULT (ic), NULL, ic);
2121 /*-----------------------------------------------------------------*/
2122 /* assignResultValue - */
2123 /*-----------------------------------------------------------------*/
2125 assignResultValue (operand * oper)
2127 int size = AOP_SIZE (oper);
2130 wassertl (size <= 4, "Got a result that is bigger than four bytes");
2131 topInA = requiresHL (AOP (oper));
2133 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
2135 /* We do it the hard way here. */
2137 aopPut (AOP (oper), _fReturn[0], 0);
2138 aopPut (AOP (oper), _fReturn[1], 1);
2140 aopPut (AOP (oper), _fReturn[0], 2);
2141 aopPut (AOP (oper), _fReturn[1], 3);
2147 aopPut (AOP (oper), _fReturn[size], size);
2152 /** Simple restore that doesn't take into account what is used in the
2156 _restoreRegsAfterCall(void)
2158 if (_G.stack.pushedDE)
2161 _G.stack.pushedDE = FALSE;
2163 if (_G.stack.pushedBC)
2166 _G.stack.pushedBC = FALSE;
2168 _G.saves.saved = FALSE;
2172 _saveRegsForCall(iCode *ic, int sendSetSize)
2175 o Stack parameters are pushed before this function enters
2176 o DE and BC may be used in this function.
2177 o HL and DE may be used to return the result.
2178 o HL and DE may be used to send variables.
2179 o DE and BC may be used to store the result value.
2180 o HL may be used in computing the sent value of DE
2181 o The iPushes for other parameters occur before any addSets
2183 Logic: (to be run inside the first iPush or if none, before sending)
2184 o Compute if DE and/or BC are in use over the call
2185 o Compute if DE is used in the send set
2186 o Compute if DE and/or BC are used to hold the result value
2187 o If (DE is used, or in the send set) and is not used in the result, push.
2188 o If BC is used and is not in the result, push
2190 o If DE is used in the send set, fetch
2191 o If HL is used in the send set, fetch
2195 if (_G.saves.saved == FALSE) {
2196 bool deInUse, bcInUse;
2198 bool bcInRet = FALSE, deInRet = FALSE;
2201 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2203 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
2204 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
2206 deSending = (sendSetSize > 1);
2208 emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
2210 if (bcInUse && bcInRet == FALSE) {
2212 _G.stack.pushedBC = TRUE;
2214 if (deInUse && deInRet == FALSE) {
2216 _G.stack.pushedDE = TRUE;
2219 _G.saves.saved = TRUE;
2222 /* Already saved. */
2226 /*-----------------------------------------------------------------*/
2227 /* genIpush - genrate code for pushing this gets a little complex */
2228 /*-----------------------------------------------------------------*/
2230 genIpush (iCode * ic)
2232 int size, offset = 0;
2235 /* if this is not a parm push : ie. it is spill push
2236 and spill push is always done on the local stack */
2239 wassertl(0, "Encountered an unsupported spill push.");
2243 if (_G.saves.saved == FALSE) {
2244 /* Caller saves, and this is the first iPush. */
2245 /* Scan ahead until we find the function that we are pushing parameters to.
2246 Count the number of addSets on the way to figure out what registers
2247 are used in the send set.
2250 iCode *walk = ic->next;
2253 if (walk->op == SEND) {
2256 else if (walk->op == CALL || walk->op == PCALL) {
2265 _saveRegsForCall(walk, nAddSets);
2268 /* Already saved by another iPush. */
2271 /* then do the push */
2272 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2274 size = AOP_SIZE (IC_LEFT (ic));
2276 if (isPair (AOP (IC_LEFT (ic))) && size == 2)
2278 _G.stack.pushed += 2;
2279 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
2285 fetchHL (AOP (IC_LEFT (ic)));
2287 spillPair (PAIR_HL);
2288 _G.stack.pushed += 2;
2293 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2295 spillPair (PAIR_HL);
2296 _G.stack.pushed += 2;
2297 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
2299 spillPair (PAIR_HL);
2300 _G.stack.pushed += 2;
2306 if (AOP (IC_LEFT (ic))->type == AOP_IY)
2308 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
2310 emit2 ("ld a,(%s)", l);
2314 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
2315 emit2 ("ld a,%s", l);
2323 freeAsmop (IC_LEFT (ic), NULL, ic);
2326 /*-----------------------------------------------------------------*/
2327 /* genIpop - recover the registers: can happen only for spilling */
2328 /*-----------------------------------------------------------------*/
2330 genIpop (iCode * ic)
2335 /* if the temp was not pushed then */
2336 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2339 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2340 size = AOP_SIZE (IC_LEFT (ic));
2341 offset = (size - 1);
2342 if (isPair (AOP (IC_LEFT (ic))))
2344 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
2352 spillPair (PAIR_HL);
2353 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
2357 freeAsmop (IC_LEFT (ic), NULL, ic);
2360 /* This is quite unfortunate */
2362 setArea (int inHome)
2365 static int lastArea = 0;
2367 if (_G.in_home != inHome) {
2369 const char *sz = port->mem.code_name;
2370 port->mem.code_name = "HOME";
2371 emit2("!area", CODE_NAME);
2372 port->mem.code_name = sz;
2375 emit2("!area", CODE_NAME); */
2376 _G.in_home = inHome;
2387 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
2391 symbol *sym = OP_SYMBOL (op);
2393 if (sym->isspilt || sym->nRegs == 0)
2396 aopOp (op, ic, FALSE, FALSE);
2399 if (aop->type == AOP_REG)
2402 for (i = 0; i < aop->size; i++)
2404 if (pairId == PAIR_DE)
2406 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2407 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2409 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2412 else if (pairId == PAIR_BC)
2414 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2415 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2417 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2427 freeAsmop (IC_LEFT (ic), NULL, ic);
2431 /** Emit the code for a call statement
2434 emitCall (iCode * ic, bool ispcall)
2436 sym_link *dtype = operandType (IC_LEFT (ic));
2438 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2440 /* if caller saves & we have not saved then */
2446 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2448 /* if send set is not empty then assign */
2453 int nSend = elementsInSet(_G.sendSet);
2454 bool swapped = FALSE;
2456 int _z80_sendOrder[] = {
2461 /* Check if the parameters are swapped. If so route through hl instead. */
2462 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2464 sic = setFirstItem(_G.sendSet);
2465 sic = setNextItem(_G.sendSet);
2467 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2468 /* The second send value is loaded from one the one that holds the first
2469 send, i.e. it is overwritten. */
2470 /* Cache the first in HL, and load the second from HL instead. */
2471 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2472 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2478 for (sic = setFirstItem (_G.sendSet); sic;
2479 sic = setNextItem (_G.sendSet))
2482 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2484 size = AOP_SIZE (IC_LEFT (sic));
2485 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2486 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2488 // PENDING: Mild hack
2489 if (swapped == TRUE && send == 1) {
2491 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2494 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2496 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2499 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2503 freeAsmop (IC_LEFT (sic), NULL, sic);
2510 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2512 werror (W_INDIR_BANKED);
2514 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2516 if (isLitWord (AOP (IC_LEFT (ic))))
2518 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2522 symbol *rlbl = newiTempLabel (NULL);
2523 spillPair (PAIR_HL);
2524 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2526 _G.stack.pushed += 2;
2528 fetchHL (AOP (IC_LEFT (ic)));
2530 emit2 ("!tlabeldef", (rlbl->key + 100));
2531 _G.stack.pushed -= 2;
2533 freeAsmop (IC_LEFT (ic), NULL, ic);
2537 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2538 OP_SYMBOL (IC_LEFT (ic))->rname :
2539 OP_SYMBOL (IC_LEFT (ic))->name;
2540 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2542 emit2 ("call banked_call");
2543 emit2 ("!dws", name);
2544 emit2 ("!dw !bankimmeds", name);
2549 emit2 ("call %s", name);
2554 /* Mark the regsiters as restored. */
2555 _G.saves.saved = FALSE;
2557 /* if we need assign a result value */
2558 if ((IS_ITEMP (IC_RESULT (ic)) &&
2559 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2560 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2561 IS_TRUE_SYMOP (IC_RESULT (ic)))
2564 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2566 assignResultValue (IC_RESULT (ic));
2568 freeAsmop (IC_RESULT (ic), NULL, ic);
2571 /* adjust the stack for parameters if required */
2574 int i = ic->parmBytes;
2576 _G.stack.pushed -= i;
2579 emit2 ("!ldaspsp", i);
2586 emit2 ("ld hl,#%d", i);
2587 emit2 ("add hl,sp");
2605 if (_G.stack.pushedDE)
2607 bool dInUse = bitVectBitValue(rInUse, D_IDX);
2608 bool eInUse = bitVectBitValue(rInUse, E_IDX);
2610 if (dInUse && eInUse)
2626 wassertl (0, "Neither D or E were in use but it was pushed.");
2628 _G.stack.pushedDE = FALSE;
2631 if (_G.stack.pushedBC)
2633 bool bInUse = bitVectBitValue(rInUse, B_IDX);
2634 bool cInUse = bitVectBitValue(rInUse, C_IDX);
2636 // If both B and C are used in the return value, then we won't get
2638 if (bInUse && cInUse)
2654 wassertl (0, "Neither B or C were in use but it was pushed.");
2656 _G.stack.pushedBC = FALSE;
2660 /*-----------------------------------------------------------------*/
2661 /* genCall - generates a call statement */
2662 /*-----------------------------------------------------------------*/
2664 genCall (iCode * ic)
2666 emitCall (ic, FALSE);
2669 /*-----------------------------------------------------------------*/
2670 /* genPcall - generates a call by pointer statement */
2671 /*-----------------------------------------------------------------*/
2673 genPcall (iCode * ic)
2675 emitCall (ic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* resultRemat - result is rematerializable */
2680 /*-----------------------------------------------------------------*/
2682 resultRemat (iCode * ic)
2684 if (SKIP_IC (ic) || ic->op == IFX)
2687 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2689 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2690 if (sym->remat && !POINTER_SET (ic))
2697 extern set *publics;
2699 /*-----------------------------------------------------------------*/
2700 /* genFunction - generated code for function entry */
2701 /*-----------------------------------------------------------------*/
2703 genFunction (iCode * ic)
2705 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2709 bool bcInUse = FALSE;
2710 bool deInUse = FALSE;
2713 setArea (IFFUNC_NONBANKED (sym->type));
2715 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2718 _G.receiveOffset = 0;
2720 /* Record the last function name for debugging. */
2721 _G.lastFunctionName = sym->rname;
2723 /* Create the function header */
2724 emit2 ("!functionheader", sym->name);
2725 /* PENDING: portability. */
2726 emit2 ("__%s_start:", sym->rname);
2727 emit2 ("!functionlabeldef", sym->rname);
2729 if (options.profile)
2731 emit2 ("!profileenter");
2734 ftype = operandType (IC_LEFT (ic));
2736 /* if critical function then turn interrupts off */
2737 if (IFFUNC_ISCRITICAL (ftype))
2740 /* if this is an interrupt service routine then save all potentially used registers. */
2741 if (IFFUNC_ISISR (sym->type))
2746 /* PENDING: callee-save etc */
2748 _G.stack.param_offset = 0;
2751 /* Detect which registers are used. */
2755 for (i = 0; i < sym->regsUsed->size; i++)
2757 if (bitVectBitValue (sym->regsUsed, i))
2771 /* Other systems use DE as a temporary. */
2782 _G.stack.param_offset += 2;
2785 _G.stack.pushedBC = bcInUse;
2790 _G.stack.param_offset += 2;
2793 _G.stack.pushedDE = deInUse;
2796 /* adjust the stack for the function */
2797 _G.stack.last = sym->stack;
2799 if (sym->stack && IS_GB && sym->stack > -INT8MIN)
2800 emit2 ("!enterxl", sym->stack);
2801 else if (sym->stack)
2802 emit2 ("!enterx", sym->stack);
2805 _G.stack.offset = sym->stack;
2808 /*-----------------------------------------------------------------*/
2809 /* genEndFunction - generates epilogue for functions */
2810 /*-----------------------------------------------------------------*/
2812 genEndFunction (iCode * ic)
2814 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2816 if (IFFUNC_ISISR (sym->type))
2818 wassertl (0, "Tried to close an interrupt support function");
2822 if (IFFUNC_ISCRITICAL (sym->type))
2825 /* PENDING: calleeSave */
2827 if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
2829 emit2 ("!leavexl", _G.stack.offset);
2831 else if (_G.stack.offset)
2833 emit2 ("!leavex", _G.stack.offset);
2841 if (_G.stack.pushedDE)
2844 _G.stack.pushedDE = FALSE;
2847 if (_G.stack.pushedDE)
2850 _G.stack.pushedDE = FALSE;
2854 if (options.profile)
2856 emit2 ("!profileexit");
2860 /* Both baned and non-banked just ret */
2863 /* PENDING: portability. */
2864 emit2 ("__%s_end:", sym->rname);
2866 _G.flushStatics = 1;
2867 _G.stack.pushed = 0;
2868 _G.stack.offset = 0;
2871 /*-----------------------------------------------------------------*/
2872 /* genRet - generate code for return statement */
2873 /*-----------------------------------------------------------------*/
2878 /* Errk. This is a hack until I can figure out how
2879 to cause dehl to spill on a call */
2880 int size, offset = 0;
2882 /* if we have no return value then
2883 just generate the "ret" */
2887 /* we have something to return then
2888 move the return value into place */
2889 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2890 size = AOP_SIZE (IC_LEFT (ic));
2892 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2896 emit2 ("ld de,%s", l);
2900 emit2 ("ld hl,%s", l);
2905 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2907 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2908 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2914 l = aopGet (AOP (IC_LEFT (ic)), offset,
2916 if (strcmp (_fReturn[offset], l))
2917 emit2 ("ld %s,%s", _fReturn[offset++], l);
2921 freeAsmop (IC_LEFT (ic), NULL, ic);
2924 /* generate a jump to the return label
2925 if the next is not the return statement */
2926 if (!(ic->next && ic->next->op == LABEL &&
2927 IC_LABEL (ic->next) == returnLabel))
2929 emit2 ("jp !tlabel", returnLabel->key + 100);
2932 /*-----------------------------------------------------------------*/
2933 /* genLabel - generates a label */
2934 /*-----------------------------------------------------------------*/
2936 genLabel (iCode * ic)
2938 /* special case never generate */
2939 if (IC_LABEL (ic) == entryLabel)
2942 emitLabel (IC_LABEL (ic)->key + 100);
2945 /*-----------------------------------------------------------------*/
2946 /* genGoto - generates a ljmp */
2947 /*-----------------------------------------------------------------*/
2949 genGoto (iCode * ic)
2951 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2954 /*-----------------------------------------------------------------*/
2955 /* genPlusIncr :- does addition with increment if possible */
2956 /*-----------------------------------------------------------------*/
2958 genPlusIncr (iCode * ic)
2960 unsigned int icount;
2961 unsigned int size = getDataSize (IC_RESULT (ic));
2962 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2964 /* will try to generate an increment */
2965 /* if the right side is not a literal
2967 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2970 emitDebug ("; genPlusIncr");
2972 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2974 /* If result is a pair */
2975 if (resultId != PAIR_INVALID)
2977 if (isLitWord (AOP (IC_LEFT (ic))))
2979 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2982 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2984 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
2986 PAIR_ID freep = getFreePairId (ic);
2987 if (freep != PAIR_INVALID)
2989 fetchPair (freep, AOP (IC_RIGHT (ic)));
2990 emit2 ("add hl,%s", _pairs[freep].name);
2996 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2997 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3004 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3008 movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3012 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
3017 if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
3019 fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
3020 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3024 /* if the literal value of the right hand side
3025 is greater than 4 then it is not worth it */
3029 /* if increment 16 bits in register */
3030 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3036 symbol *tlbl = NULL;
3037 tlbl = newiTempLabel (NULL);
3040 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
3043 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3046 emitLabel (tlbl->key + 100);
3050 /* if the sizes are greater than 1 then we cannot */
3051 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3052 AOP_SIZE (IC_LEFT (ic)) > 1)
3055 /* If the result is in a register then we can load then increment.
3057 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG)
3059 aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), LSB, FALSE), LSB);
3062 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
3067 /* we can if the aops of the left & result match or
3068 if they are in registers and the registers are the
3070 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3074 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
3082 /*-----------------------------------------------------------------*/
3083 /* outBitAcc - output a bit in acc */
3084 /*-----------------------------------------------------------------*/
3086 outBitAcc (operand * result)
3088 symbol *tlbl = newiTempLabel (NULL);
3089 /* if the result is a bit */
3090 if (AOP_TYPE (result) == AOP_CRY)
3092 wassertl (0, "Tried to write A into a bit");
3096 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3097 emit2 ("ld a,!one");
3098 emitLabel (tlbl->key + 100);
3104 couldDestroyCarry (asmop *aop)
3108 if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
3117 shiftIntoPair (int idx, asmop *aop)
3119 PAIR_ID id = PAIR_INVALID;
3121 wassertl (IS_Z80, "Only implemented for the Z80");
3122 // wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
3134 wassertl (0, "Internal error - hit default case");
3137 emitDebug ("; Shift into pair idx %u", idx);
3141 setupPair (PAIR_HL, aop, 0);
3145 setupPair (PAIR_IY, aop, 0);
3147 emit2 ("pop %s", _pairs[id].name);
3150 aop->type = AOP_PAIRPTR;
3151 aop->aopu.aop_pairId = id;
3152 _G.pairs[id].offset = 0;
3153 _G.pairs[id].last_type = aop->type;
3157 setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
3159 wassert (left && right);
3163 if (couldDestroyCarry (right) && couldDestroyCarry (result))
3165 shiftIntoPair (0, right);
3166 shiftIntoPair (1, result);
3168 else if (couldDestroyCarry (right))
3170 shiftIntoPair (0, right);
3172 else if (couldDestroyCarry (result))
3174 shiftIntoPair (0, result);
3183 /*-----------------------------------------------------------------*/
3184 /* genPlus - generates code for addition */
3185 /*-----------------------------------------------------------------*/
3187 genPlus (iCode * ic)
3189 int size, offset = 0;
3191 /* special cases :- */
3193 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3194 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3195 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3197 /* Swap the left and right operands if:
3199 if literal, literal on the right or
3200 if left requires ACC or right is already
3203 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3204 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3205 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3207 operand *t = IC_RIGHT (ic);
3208 IC_RIGHT (ic) = IC_LEFT (ic);
3212 /* if both left & right are in bit
3214 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3215 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3218 wassertl (0, "Tried to add two bits");
3221 /* if left in bit space & right literal */
3222 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3223 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3225 /* Can happen I guess */
3226 wassertl (0, "Tried to add a bit to a literal");
3229 /* if I can do an increment instead
3230 of add then GOOD for ME */
3231 if (genPlusIncr (ic) == TRUE)
3234 emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
3236 size = getDataSize (IC_RESULT (ic));
3238 /* Special case when left and right are constant */
3239 if (isPair (AOP (IC_RESULT (ic))))
3242 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
3243 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
3245 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
3251 sprintf (buffer, "#(%s + %s)", left, right);
3252 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
3257 if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
3259 /* Fetch into HL then do the add */
3260 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3261 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3263 spillPair (PAIR_HL);
3265 if (left == PAIR_HL && right != PAIR_INVALID)
3267 emit2 ("add hl,%s", _pairs[right].name);
3270 else if (right == PAIR_HL && left != PAIR_INVALID)
3272 emit2 ("add hl,%s", _pairs[left].name);
3275 else if (right != PAIR_INVALID)
3277 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3278 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3281 else if (left != PAIR_INVALID)
3283 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3284 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3293 if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
3295 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3296 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3298 commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3303 ld hl,sp+n trashes C so we cant afford to do it during an
3304 add with stack based varibles. Worst case is:
3317 So you cant afford to load up hl if either left, right, or result
3318 is on the stack (*sigh*) The alt is:
3326 Combinations in here are:
3327 * If left or right are in bc then the loss is small - trap later
3328 * If the result is in bc then the loss is also small
3332 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3333 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3334 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3336 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3337 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3338 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3339 AOP_SIZE (IC_RIGHT (ic)) <= 2))
3341 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
3343 /* Swap left and right */
3344 operand *t = IC_RIGHT (ic);
3345 IC_RIGHT (ic) = IC_LEFT (ic);
3348 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
3350 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3351 emit2 ("add hl,bc");
3355 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3356 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3357 emit2 ("add hl,de");
3359 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3365 /* Be paranoid on the GB with 4 byte variables due to how C
3366 can be trashed by lda hl,n(sp).
3368 _gbz80_emitAddSubLong (ic, TRUE);
3373 setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3377 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3379 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3382 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3385 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3389 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3392 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3395 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3397 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3401 freeAsmop (IC_LEFT (ic), NULL, ic);
3402 freeAsmop (IC_RIGHT (ic), NULL, ic);
3403 freeAsmop (IC_RESULT (ic), NULL, ic);
3407 /*-----------------------------------------------------------------*/
3408 /* genMinusDec :- does subtraction with deccrement if possible */
3409 /*-----------------------------------------------------------------*/
3411 genMinusDec (iCode * ic)
3413 unsigned int icount;
3414 unsigned int size = getDataSize (IC_RESULT (ic));
3416 /* will try to generate an increment */
3417 /* if the right side is not a literal we cannot */
3418 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3421 /* if the literal value of the right hand side
3422 is greater than 4 then it is not worth it */
3423 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
3426 size = getDataSize (IC_RESULT (ic));
3428 /* if decrement 16 bits in register */
3429 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3430 (size > 1) && isPair (AOP (IC_RESULT (ic))))
3433 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3437 /* If result is a pair */
3438 if (isPair (AOP (IC_RESULT (ic))))
3440 movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3442 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3446 /* if increment 16 bits in register */
3447 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3451 fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
3454 emit2 ("dec %s", _getTempPairName());
3457 commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
3463 /* if the sizes are greater than 1 then we cannot */
3464 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3465 AOP_SIZE (IC_LEFT (ic)) > 1)
3468 /* we can if the aops of the left & result match or if they are in
3469 registers and the registers are the same */
3470 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3473 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
3480 /*-----------------------------------------------------------------*/
3481 /* genMinus - generates code for subtraction */
3482 /*-----------------------------------------------------------------*/
3484 genMinus (iCode * ic)
3486 int size, offset = 0;
3487 unsigned long lit = 0L;
3489 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3490 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3491 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3493 /* special cases :- */
3494 /* if both left & right are in bit space */
3495 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3496 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3498 wassertl (0, "Tried to subtract two bits");
3502 /* if I can do an decrement instead of subtract then GOOD for ME */
3503 if (genMinusDec (ic) == TRUE)
3506 size = getDataSize (IC_RESULT (ic));
3508 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3513 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3517 /* Same logic as genPlus */
3520 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3521 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3522 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3524 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3525 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3526 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3527 AOP_SIZE (IC_RIGHT (ic)) <= 2))
3529 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3530 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3532 if (left == PAIR_INVALID && right == PAIR_INVALID)
3537 else if (right == PAIR_INVALID)
3539 else if (left == PAIR_INVALID)
3542 fetchPair (left, AOP (IC_LEFT (ic)));
3543 /* Order is important. Right may be HL */
3544 fetchPair (right, AOP (IC_RIGHT (ic)));
3546 emit2 ("ld a,%s", _pairs[left].l);
3547 emit2 ("sub a,%s", _pairs[right].l);
3549 emit2 ("ld a,%s", _pairs[left].h);
3550 emit2 ("sbc a,%s", _pairs[right].h);
3552 if ( AOP_SIZE (IC_RESULT (ic)) > 1)
3554 aopPut (AOP (IC_RESULT (ic)), "a", 1);
3556 aopPut (AOP (IC_RESULT (ic)), "e", 0);
3562 /* Be paranoid on the GB with 4 byte variables due to how C
3563 can be trashed by lda hl,n(sp).
3565 _gbz80_emitAddSubLong (ic, FALSE);
3570 setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3572 /* if literal, add a,#-lit, else normal subb */
3575 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3576 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3580 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3583 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3587 /* first add without previous c */
3589 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
3591 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3593 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3596 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3597 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3598 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3600 wassertl (0, "Tried to subtract on a long pointer");
3604 freeAsmop (IC_LEFT (ic), NULL, ic);
3605 freeAsmop (IC_RIGHT (ic), NULL, ic);
3606 freeAsmop (IC_RESULT (ic), NULL, ic);
3609 /*-----------------------------------------------------------------*/
3610 /* genMult - generates code for multiplication */
3611 /*-----------------------------------------------------------------*/
3613 genMult (iCode * ic)
3617 /* If true then the final operation should be a subtract */
3618 bool active = FALSE;
3620 /* Shouldn't occur - all done through function calls */
3621 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3622 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3623 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3625 if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
3626 AOP_SIZE (IC_RIGHT (ic)) > 2 ||
3627 AOP_SIZE (IC_RESULT (ic)) > 2)
3629 wassertl (0, "Multiplication is handled through support function calls");
3632 /* Swap left and right such that right is a literal */
3633 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
3635 operand *t = IC_RIGHT (ic);
3636 IC_RIGHT (ic) = IC_LEFT (ic);
3640 wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
3642 val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
3643 // wassertl (val > 0, "Multiply must be positive");
3644 wassertl (val != 1, "Can't multiply by 1");
3650 if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
3652 emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
3660 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3665 /* Fully unroled version of mul.s. Not the most efficient.
3667 for (count = 0; count < 16; count++)
3669 if (count != 0 && active)
3671 emit2 ("add hl,hl");
3675 if (active == FALSE)
3682 emit2 ("add hl,de");
3696 commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3698 freeAsmop (IC_LEFT (ic), NULL, ic);
3699 freeAsmop (IC_RIGHT (ic), NULL, ic);
3700 freeAsmop (IC_RESULT (ic), NULL, ic);
3703 /*-----------------------------------------------------------------*/
3704 /* genDiv - generates code for division */
3705 /*-----------------------------------------------------------------*/
3709 /* Shouldn't occur - all done through function calls */
3710 wassertl (0, "Division is handled through support function calls");
3713 /*-----------------------------------------------------------------*/
3714 /* genMod - generates code for division */
3715 /*-----------------------------------------------------------------*/
3719 /* Shouldn't occur - all done through function calls */
3723 /*-----------------------------------------------------------------*/
3724 /* genIfxJump :- will create a jump depending on the ifx */
3725 /*-----------------------------------------------------------------*/
3727 genIfxJump (iCode * ic, char *jval)
3732 /* if true label then we jump if condition
3736 jlbl = IC_TRUE (ic);
3737 if (!strcmp (jval, "a"))
3741 else if (!strcmp (jval, "c"))
3745 else if (!strcmp (jval, "nc"))
3749 else if (!strcmp (jval, "m"))
3753 else if (!strcmp (jval, "p"))
3759 /* The buffer contains the bit on A that we should test */
3765 /* false label is present */
3766 jlbl = IC_FALSE (ic);
3767 if (!strcmp (jval, "a"))
3771 else if (!strcmp (jval, "c"))
3775 else if (!strcmp (jval, "nc"))
3779 else if (!strcmp (jval, "m"))
3783 else if (!strcmp (jval, "p"))
3789 /* The buffer contains the bit on A that we should test */
3793 /* Z80 can do a conditional long jump */
3794 if (!strcmp (jval, "a"))
3798 else if (!strcmp (jval, "c"))
3801 else if (!strcmp (jval, "nc"))
3804 else if (!strcmp (jval, "m"))
3807 else if (!strcmp (jval, "p"))
3812 emit2 ("bit %s,a", jval);
3814 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3816 /* mark the icode as generated */
3822 _getPairIdName (PAIR_ID id)
3824 return _pairs[id].name;
3829 /* if unsigned char cmp with lit, just compare */
3831 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3833 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3836 emit2 ("xor a,!immedbyte", 0x80);
3837 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3840 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3842 else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
3844 // On the Gameboy we can't afford to adjust HL as it may trash the carry.
3845 // Pull left into DE and right into HL
3846 aopGet (AOP(left), LSB, FALSE);
3849 aopGet (AOP(right), LSB, FALSE);
3853 if (size == 0 && sign)
3855 // Highest byte when signed needs the bits flipped
3858 emit2 ("ld a,(de)");
3859 emit2 ("xor #0x80");
3861 emit2 ("ld a,(hl)");
3862 emit2 ("xor #0x80");
3866 emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
3870 emit2 ("ld a,(de)");
3871 emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
3881 spillPair (PAIR_HL);
3883 else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
3885 setupPair (PAIR_HL, AOP (left), 0);
3886 aopGet (AOP(right), LSB, FALSE);
3890 if (size == 0 && sign)
3892 // Highest byte when signed needs the bits flipped
3895 emit2 ("ld a,(hl)");
3896 emit2 ("xor #0x80");
3898 emit2 ("ld a,%d(iy)", offset);
3899 emit2 ("xor #0x80");
3903 emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
3907 emit2 ("ld a,(hl)");
3908 emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
3917 spillPair (PAIR_HL);
3918 spillPair (PAIR_IY);
3922 if (AOP_TYPE (right) == AOP_LIT)
3924 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3925 /* optimize if(x < 0) or if(x >= 0) */
3930 /* No sign so it's always false */
3935 /* Just load in the top most bit */
3936 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3937 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3939 genIfxJump (ifx, "7");
3951 /* First setup h and l contaning the top most bytes XORed */
3952 bool fDidXor = FALSE;
3953 if (AOP_TYPE (left) == AOP_LIT)
3955 unsigned long lit = (unsigned long)
3956 floatFromVal (AOP (left)->aopu.aop_lit);
3957 emit2 ("ld %s,!immedbyte", _fTmp[0],
3958 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3962 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3963 emit2 ("xor a,!immedbyte", 0x80);
3964 emit2 ("ld %s,a", _fTmp[0]);
3967 if (AOP_TYPE (right) == AOP_LIT)
3969 unsigned long lit = (unsigned long)
3970 floatFromVal (AOP (right)->aopu.aop_lit);
3971 emit2 ("ld %s,!immedbyte", _fTmp[1],
3972 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3976 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3977 emit2 ("xor a,!immedbyte", 0x80);
3978 emit2 ("ld %s,a", _fTmp[1]);
3984 /* Do a long subtract */
3987 _moveA (aopGet (AOP (left), offset, FALSE));
3989 if (sign && size == 0)
3991 emit2 ("ld a,%s", _fTmp[0]);
3992 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
3996 /* Subtract through, propagating the carry */
3997 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4005 /** Generic compare for > or <
4008 genCmp (operand * left, operand * right,
4009 operand * result, iCode * ifx, int sign)
4011 int size, offset = 0;
4012 unsigned long lit = 0L;
4013 bool swap_sense = FALSE;
4015 /* if left & right are bit variables */
4016 if (AOP_TYPE (left) == AOP_CRY &&
4017 AOP_TYPE (right) == AOP_CRY)
4019 /* Cant happen on the Z80 */
4020 wassertl (0, "Tried to compare two bits");
4024 /* Do a long subtract of right from left. */
4025 size = max (AOP_SIZE (left), AOP_SIZE (right));
4027 if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4029 // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4030 // Pull left into DE and right into HL
4031 aopGet (AOP(left), LSB, FALSE);
4034 aopGet (AOP(right), LSB, FALSE);
4038 emit2 ("ld a,(de)");
4039 emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4048 spillPair (PAIR_HL);
4052 if (AOP_TYPE (right) == AOP_LIT)
4054 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4055 /* optimize if(x < 0) or if(x >= 0) */
4060 /* No sign so it's always false */
4065 /* Just load in the top most bit */
4066 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4067 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4069 genIfxJump (ifx, "7");
4080 genIfxJump (ifx, swap_sense ? "c" : "nc");
4091 _moveA (aopGet (AOP (left), offset, FALSE));
4092 /* Subtract through, propagating the carry */
4093 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4099 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4103 /* Shift the sign bit up into carry */
4106 outBitCLong (result, swap_sense);
4110 /* if the result is used in the next
4111 ifx conditional branch then generate
4112 code a little differently */
4118 genIfxJump (ifx, swap_sense ? "nc" : "c");
4122 genIfxJump (ifx, swap_sense ? "p" : "m");
4129 /* Shift the sign bit up into carry */
4132 outBitCLong (result, swap_sense);
4134 /* leave the result in acc */
4138 /*-----------------------------------------------------------------*/
4139 /* genCmpGt :- greater than comparison */
4140 /*-----------------------------------------------------------------*/
4142 genCmpGt (iCode * ic, iCode * ifx)
4144 operand *left, *right, *result;
4145 sym_link *letype, *retype;
4148 left = IC_LEFT (ic);
4149 right = IC_RIGHT (ic);
4150 result = IC_RESULT (ic);
4152 letype = getSpec (operandType (left));
4153 retype = getSpec (operandType (right));
4154 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4155 /* assign the amsops */
4156 aopOp (left, ic, FALSE, FALSE);
4157 aopOp (right, ic, FALSE, FALSE);
4158 aopOp (result, ic, TRUE, FALSE);
4160 genCmp (right, left, result, ifx, sign);
4162 freeAsmop (left, NULL, ic);
4163 freeAsmop (right, NULL, ic);
4164 freeAsmop (result, NULL, ic);
4167 /*-----------------------------------------------------------------*/
4168 /* genCmpLt - less than comparisons */
4169 /*-----------------------------------------------------------------*/
4171 genCmpLt (iCode * ic, iCode * ifx)
4173 operand *left, *right, *result;
4174 sym_link *letype, *retype;
4177 left = IC_LEFT (ic);
4178 right = IC_RIGHT (ic);
4179 result = IC_RESULT (ic);
4181 letype = getSpec (operandType (left));
4182 retype = getSpec (operandType (right));
4183 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4185 /* assign the amsops */
4186 aopOp (left, ic, FALSE, FALSE);
4187 aopOp (right, ic, FALSE, FALSE);
4188 aopOp (result, ic, TRUE, FALSE);
4190 genCmp (left, right, result, ifx, sign);
4192 freeAsmop (left, NULL, ic);
4193 freeAsmop (right, NULL, ic);
4194 freeAsmop (result, NULL, ic);
4197 /*-----------------------------------------------------------------*/
4198 /* gencjneshort - compare and jump if not equal */
4199 /*-----------------------------------------------------------------*/
4201 gencjneshort (operand * left, operand * right, symbol * lbl)
4203 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4205 unsigned long lit = 0L;
4207 /* Swap the left and right if it makes the computation easier */
4208 if (AOP_TYPE (left) == AOP_LIT)
4215 if (AOP_TYPE (right) == AOP_LIT)
4216 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4218 /* if the right side is a literal then anything goes */
4219 if (AOP_TYPE (right) == AOP_LIT &&
4220 AOP_TYPE (left) != AOP_DIR)
4224 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4229 emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
4236 emit2 ("jp nz,!tlabel", lbl->key + 100);
4242 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4243 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
4246 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
4247 emit2 ("jp nz,!tlabel", lbl->key + 100);
4252 /* if the right side is in a register or in direct space or
4253 if the left is a pointer register & right is not */
4254 else if (AOP_TYPE (right) == AOP_REG ||
4255 AOP_TYPE (right) == AOP_DIR ||
4256 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
4260 _moveA (aopGet (AOP (left), offset, FALSE));
4261 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4262 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4264 emit2 ("jp nz,!tlabel", lbl->key + 100);
4267 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4268 emit2 ("jp nz,!tlabel", lbl->key + 100);
4275 /* right is a pointer reg need both a & b */
4276 /* PENDING: is this required? */
4279 _moveA (aopGet (AOP (right), offset, FALSE));
4280 emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
4281 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
4287 /*-----------------------------------------------------------------*/
4288 /* gencjne - compare and jump if not equal */
4289 /*-----------------------------------------------------------------*/
4291 gencjne (operand * left, operand * right, symbol * lbl)
4293 symbol *tlbl = newiTempLabel (NULL);
4295 gencjneshort (left, right, lbl);
4298 emit2 ("ld a,!one");
4299 emit2 ("!shortjp !tlabel", tlbl->key + 100);
4300 emitLabel (lbl->key + 100);
4302 emitLabel (tlbl->key + 100);
4305 /*-----------------------------------------------------------------*/
4306 /* genCmpEq - generates code for equal to */
4307 /*-----------------------------------------------------------------*/
4309 genCmpEq (iCode * ic, iCode * ifx)
4311 operand *left, *right, *result;
4313 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4314 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4315 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4317 emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
4319 /* Swap operands if it makes the operation easier. ie if:
4320 1. Left is a literal.
4322 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4324 operand *t = IC_RIGHT (ic);
4325 IC_RIGHT (ic) = IC_LEFT (ic);
4329 if (ifx && !AOP_SIZE (result))
4332 /* if they are both bit variables */
4333 if (AOP_TYPE (left) == AOP_CRY &&
4334 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4336 wassertl (0, "Tried to compare two bits");
4340 tlbl = newiTempLabel (NULL);
4342 gencjneshort (left, right, tlbl);
4346 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
4347 emitLabel (tlbl->key + 100);
4351 /* PENDING: do this better */
4352 symbol *lbl = newiTempLabel (NULL);
4354 emit2 ("!shortjp !tlabel", lbl->key + 100);
4355 emitLabel (tlbl->key + 100);
4356 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
4357 emitLabel (lbl->key + 100);
4360 /* mark the icode as generated */
4365 /* if they are both bit variables */
4366 if (AOP_TYPE (left) == AOP_CRY &&
4367 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4369 wassertl (0, "Tried to compare a bit to either a literal or another bit");
4375 gencjne (left, right, newiTempLabel (NULL));
4376 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4383 genIfxJump (ifx, "a");
4386 /* if the result is used in an arithmetic operation
4387 then put the result in place */
4388 if (AOP_TYPE (result) != AOP_CRY)
4393 /* leave the result in acc */
4397 freeAsmop (left, NULL, ic);
4398 freeAsmop (right, NULL, ic);
4399 freeAsmop (result, NULL, ic);
4402 /*-----------------------------------------------------------------*/
4403 /* ifxForOp - returns the icode containing the ifx for operand */
4404 /*-----------------------------------------------------------------*/
4406 ifxForOp (operand * op, iCode * ic)
4408 /* if true symbol then needs to be assigned */
4409 if (IS_TRUE_SYMOP (op))
4412 /* if this has register type condition and
4413 the next instruction is ifx with the same operand
4414 and live to of the operand is upto the ifx only then */
4416 ic->next->op == IFX &&
4417 IC_COND (ic->next)->key == op->key &&
4418 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4424 /*-----------------------------------------------------------------*/
4425 /* genAndOp - for && operation */
4426 /*-----------------------------------------------------------------*/
4428 genAndOp (iCode * ic)
4430 operand *left, *right, *result;
4433 /* note here that && operations that are in an if statement are
4434 taken away by backPatchLabels only those used in arthmetic
4435 operations remain */
4436 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4437 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4438 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4440 /* if both are bit variables */
4441 if (AOP_TYPE (left) == AOP_CRY &&
4442 AOP_TYPE (right) == AOP_CRY)
4444 wassertl (0, "Tried to and two bits");
4448 tlbl = newiTempLabel (NULL);
4450 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
4452 emitLabel (tlbl->key + 100);
4456 freeAsmop (left, NULL, ic);
4457 freeAsmop (right, NULL, ic);
4458 freeAsmop (result, NULL, ic);
4461 /*-----------------------------------------------------------------*/
4462 /* genOrOp - for || operation */
4463 /*-----------------------------------------------------------------*/
4465 genOrOp (iCode * ic)
4467 operand *left, *right, *result;
4470 /* note here that || operations that are in an
4471 if statement are taken away by backPatchLabels
4472 only those used in arthmetic operations remain */
4473 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4474 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4475 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4477 /* if both are bit variables */
4478 if (AOP_TYPE (left) == AOP_CRY &&
4479 AOP_TYPE (right) == AOP_CRY)
4481 wassertl (0, "Tried to OR two bits");
4485 tlbl = newiTempLabel (NULL);
4487 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4489 emitLabel (tlbl->key + 100);
4493 freeAsmop (left, NULL, ic);
4494 freeAsmop (right, NULL, ic);
4495 freeAsmop (result, NULL, ic);
4498 /*-----------------------------------------------------------------*/
4499 /* isLiteralBit - test if lit == 2^n */
4500 /*-----------------------------------------------------------------*/
4502 isLiteralBit (unsigned long lit)
4504 unsigned long pw[32] =
4505 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4506 0x100L, 0x200L, 0x400L, 0x800L,
4507 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4508 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4509 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4510 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4511 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4514 for (idx = 0; idx < 32; idx++)
4520 /*-----------------------------------------------------------------*/
4521 /* jmpTrueOrFalse - */
4522 /*-----------------------------------------------------------------*/
4524 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4526 // ugly but optimized by peephole
4529 symbol *nlbl = newiTempLabel (NULL);
4530 emit2 ("jp !tlabel", nlbl->key + 100);
4531 emitLabel (tlbl->key + 100);
4532 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
4533 emitLabel (nlbl->key + 100);
4537 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
4538 emitLabel (tlbl->key + 100);
4543 /*-----------------------------------------------------------------*/
4544 /* genAnd - code for and */
4545 /*-----------------------------------------------------------------*/
4547 genAnd (iCode * ic, iCode * ifx)
4549 operand *left, *right, *result;
4550 int size, offset = 0;
4551 unsigned long lit = 0L;
4554 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4556 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4558 /* if left is a literal & right is not then exchange them */
4559 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4560 AOP_NEEDSACC (left))
4562 operand *tmp = right;
4567 /* if result = right then exchange them */
4568 if (sameRegs (AOP (result), AOP (right)))
4570 operand *tmp = right;
4575 /* if right is bit then exchange them */
4576 if (AOP_TYPE (right) == AOP_CRY &&
4577 AOP_TYPE (left) != AOP_CRY)
4579 operand *tmp = right;
4583 if (AOP_TYPE (right) == AOP_LIT)
4584 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4586 size = AOP_SIZE (result);
4588 if (AOP_TYPE (left) == AOP_CRY)
4590 wassertl (0, "Tried to perform an AND with a bit as an operand");
4594 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4595 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4596 if ((AOP_TYPE (right) == AOP_LIT) &&
4597 (AOP_TYPE (result) == AOP_CRY) &&
4598 (AOP_TYPE (left) != AOP_CRY))
4600 symbol *tlbl = newiTempLabel (NULL);
4601 int sizel = AOP_SIZE (left);
4604 /* PENDING: Test case for this. */
4609 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4611 _moveA (aopGet (AOP (left), offset, FALSE));
4612 if (bytelit != 0x0FFL)
4614 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
4621 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4625 // bit = left & literal
4629 emit2 ("!tlabeldef", tlbl->key + 100);
4631 // if(left & literal)
4636 jmpTrueOrFalse (ifx, tlbl);
4644 /* if left is same as result */
4645 if (sameRegs (AOP (result), AOP (left)))
4647 for (; size--; offset++)
4649 if (AOP_TYPE (right) == AOP_LIT)
4651 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4656 aopPut (AOP (result), "!zero", offset);
4659 _moveA (aopGet (AOP (left), offset, FALSE));
4661 aopGet (AOP (right), offset, FALSE));
4662 aopPut (AOP (left), "a", offset);
4669 if (AOP_TYPE (left) == AOP_ACC)
4671 wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
4675 _moveA (aopGet (AOP (left), offset, FALSE));
4677 aopGet (AOP (right), offset, FALSE));
4678 aopPut (AOP (left), "a", offset);
4685 // left & result in different registers
4686 if (AOP_TYPE (result) == AOP_CRY)
4688 wassertl (0, "Tried to AND where the result is in carry");
4692 for (; (size--); offset++)
4695 // result = left & right
4696 if (AOP_TYPE (right) == AOP_LIT)
4698 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4700 aopPut (AOP (result),
4701 aopGet (AOP (left), offset, FALSE),
4705 else if (bytelit == 0)
4707 aopPut (AOP (result), "!zero", offset);
4711 // faster than result <- left, anl result,right
4712 // and better if result is SFR
4713 if (AOP_TYPE (left) == AOP_ACC)
4714 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
4717 _moveA (aopGet (AOP (left), offset, FALSE));
4719 aopGet (AOP (right), offset, FALSE));
4721 aopPut (AOP (result), "a", offset);
4728 freeAsmop (left, NULL, ic);
4729 freeAsmop (right, NULL, ic);
4730 freeAsmop (result, NULL, ic);
4733 /*-----------------------------------------------------------------*/
4734 /* genOr - code for or */
4735 /*-----------------------------------------------------------------*/
4737 genOr (iCode * ic, iCode * ifx)
4739 operand *left, *right, *result;
4740 int size, offset = 0;
4741 unsigned long lit = 0L;
4744 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4745 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4746 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4748 /* if left is a literal & right is not then exchange them */
4749 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4750 AOP_NEEDSACC (left))
4752 operand *tmp = right;
4757 /* if result = right then exchange them */
4758 if (sameRegs (AOP (result), AOP (right)))
4760 operand *tmp = right;
4765 /* if right is bit then exchange them */
4766 if (AOP_TYPE (right) == AOP_CRY &&
4767 AOP_TYPE (left) != AOP_CRY)
4769 operand *tmp = right;
4773 if (AOP_TYPE (right) == AOP_LIT)
4774 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4776 size = AOP_SIZE (result);
4778 if (AOP_TYPE (left) == AOP_CRY)
4780 wassertl (0, "Tried to OR where left is a bit");
4784 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4785 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4786 if ((AOP_TYPE (right) == AOP_LIT) &&
4787 (AOP_TYPE (result) == AOP_CRY) &&
4788 (AOP_TYPE (left) != AOP_CRY))
4790 symbol *tlbl = newiTempLabel (NULL);
4791 int sizel = AOP_SIZE (left);
4795 wassertl (0, "Result is assigned to a bit");
4797 /* PENDING: Modeled after the AND code which is inefficent. */
4800 bytelit = (lit >> (offset * 8)) & 0x0FFL;
4802 _moveA (aopGet (AOP (left), offset, FALSE));
4803 /* OR with any literal is the same as OR with itself. */
4805 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4811 jmpTrueOrFalse (ifx, tlbl);
4816 /* if left is same as result */
4817 if (sameRegs (AOP (result), AOP (left)))
4819 for (; size--; offset++)
4821 if (AOP_TYPE (right) == AOP_LIT)
4823 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4827 _moveA (aopGet (AOP (left), offset, FALSE));
4829 aopGet (AOP (right), offset, FALSE));
4830 aopPut (AOP (result), "a", offset);
4835 if (AOP_TYPE (left) == AOP_ACC)
4836 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4839 _moveA (aopGet (AOP (left), offset, FALSE));
4841 aopGet (AOP (right), offset, FALSE));
4842 aopPut (AOP (result), "a", offset);
4849 // left & result in different registers
4850 if (AOP_TYPE (result) == AOP_CRY)
4852 wassertl (0, "Result of OR is in a bit");
4855 for (; (size--); offset++)
4858 // result = left & right
4859 if (AOP_TYPE (right) == AOP_LIT)
4861 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4863 aopPut (AOP (result),
4864 aopGet (AOP (left), offset, FALSE),
4869 // faster than result <- left, anl result,right
4870 // and better if result is SFR
4871 if (AOP_TYPE (left) == AOP_ACC)
4872 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4875 _moveA (aopGet (AOP (left), offset, FALSE));
4877 aopGet (AOP (right), offset, FALSE));
4879 aopPut (AOP (result), "a", offset);
4880 /* PENDING: something weird is going on here. Add exception. */
4881 if (AOP_TYPE (result) == AOP_ACC)
4887 freeAsmop (left, NULL, ic);
4888 freeAsmop (right, NULL, ic);
4889 freeAsmop (result, NULL, ic);
4892 /*-----------------------------------------------------------------*/
4893 /* genXor - code for xclusive or */
4894 /*-----------------------------------------------------------------*/
4896 genXor (iCode * ic, iCode * ifx)
4898 operand *left, *right, *result;
4899 int size, offset = 0;
4900 unsigned long lit = 0L;
4902 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4903 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4904 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4906 /* if left is a literal & right is not then exchange them */
4907 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4908 AOP_NEEDSACC (left))
4910 operand *tmp = right;
4915 /* if result = right then exchange them */
4916 if (sameRegs (AOP (result), AOP (right)))
4918 operand *tmp = right;
4923 /* if right is bit then exchange them */
4924 if (AOP_TYPE (right) == AOP_CRY &&
4925 AOP_TYPE (left) != AOP_CRY)
4927 operand *tmp = right;
4931 if (AOP_TYPE (right) == AOP_LIT)
4932 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4934 size = AOP_SIZE (result);
4936 if (AOP_TYPE (left) == AOP_CRY)
4938 wassertl (0, "Tried to XOR a bit");
4942 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4943 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4944 if ((AOP_TYPE (right) == AOP_LIT) &&
4945 (AOP_TYPE (result) == AOP_CRY) &&
4946 (AOP_TYPE (left) != AOP_CRY))
4948 symbol *tlbl = newiTempLabel (NULL);
4949 int sizel = AOP_SIZE (left);
4953 /* PENDING: Test case for this. */
4954 wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
4958 _moveA (aopGet (AOP (left), offset, FALSE));
4959 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4960 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4965 jmpTrueOrFalse (ifx, tlbl);
4969 wassertl (0, "Result of XOR was destined for a bit");
4974 /* if left is same as result */
4975 if (sameRegs (AOP (result), AOP (left)))
4977 for (; size--; offset++)
4979 if (AOP_TYPE (right) == AOP_LIT)
4981 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4985 _moveA (aopGet (AOP (right), offset, FALSE));
4987 aopGet (AOP (left), offset, FALSE));
4988 aopPut (AOP (result), "a", offset);
4993 if (AOP_TYPE (left) == AOP_ACC)
4995 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4999 _moveA (aopGet (AOP (right), offset, FALSE));
5001 aopGet (AOP (left), offset, FALSE));
5002 aopPut (AOP (result), "a", 0);
5009 // left & result in different registers
5010 if (AOP_TYPE (result) == AOP_CRY)
5012 wassertl (0, "Result of XOR is in a bit");
5015 for (; (size--); offset++)
5018 // result = left & right
5019 if (AOP_TYPE (right) == AOP_LIT)
5021 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5023 aopPut (AOP (result),
5024 aopGet (AOP (left), offset, FALSE),
5029 // faster than result <- left, anl result,right
5030 // and better if result is SFR
5031 if (AOP_TYPE (left) == AOP_ACC)
5033 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5037 _moveA (aopGet (AOP (right), offset, FALSE));
5039 aopGet (AOP (left), offset, FALSE));
5041 aopPut (AOP (result), "a", offset);
5046 freeAsmop (left, NULL, ic);
5047 freeAsmop (right, NULL, ic);
5048 freeAsmop (result, NULL, ic);
5051 /*-----------------------------------------------------------------*/
5052 /* genInline - write the inline code out */
5053 /*-----------------------------------------------------------------*/
5055 genInline (iCode * ic)
5057 char *buffer, *bp, *bp1;
5059 _G.lines.isInline += (!options.asmpeep);
5061 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5062 strcpy (buffer, IC_INLINE (ic));
5064 /* emit each line as a code */
5089 _G.lines.isInline -= (!options.asmpeep);
5093 /*-----------------------------------------------------------------*/
5094 /* genRRC - rotate right with carry */
5095 /*-----------------------------------------------------------------*/
5102 /*-----------------------------------------------------------------*/
5103 /* genRLC - generate code for rotate left with carry */
5104 /*-----------------------------------------------------------------*/
5111 /*-----------------------------------------------------------------*/
5112 /* genGetHbit - generates code get highest order bit */
5113 /*-----------------------------------------------------------------*/
5115 genGetHbit (iCode * ic)
5117 operand *left, *result;
5118 left = IC_LEFT (ic);
5119 result = IC_RESULT (ic);
5120 aopOp (left, ic, FALSE, FALSE);
5121 aopOp (result, ic, FALSE, FALSE);
5123 /* get the highest order byte into a */
5124 emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5126 if (AOP_TYPE (result) == AOP_CRY)
5134 /* PENDING: For re-target. */
5140 freeAsmop (left, NULL, ic);
5141 freeAsmop (result, NULL, ic);
5145 emitRsh2 (asmop *aop, int size, int is_signed)
5151 const char *l = aopGet (aop, size, FALSE);
5154 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5164 /*-----------------------------------------------------------------*/
5165 /* shiftR2Left2Result - shift right two bytes from left to result */
5166 /*-----------------------------------------------------------------*/
5168 shiftR2Left2Result (operand * left, int offl,
5169 operand * result, int offr,
5170 int shCount, int is_signed)
5173 symbol *tlbl, *tlbl1;
5175 movLeft2Result (left, offl, result, offr, 0);
5176 movLeft2Result (left, offl + 1, result, offr + 1, 0);
5178 /* if (AOP(result)->type == AOP_REG) { */
5180 tlbl = newiTempLabel (NULL);
5181 tlbl1 = newiTempLabel (NULL);
5183 /* Left is already in result - so now do the shift */
5188 emitRsh2 (AOP (result), size, is_signed);
5193 emit2 ("ld a,!immedbyte+1", shCount);
5194 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5195 emitLabel (tlbl->key + 100);
5197 emitRsh2 (AOP (result), size, is_signed);
5199 emitLabel (tlbl1->key + 100);
5201 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5205 /*-----------------------------------------------------------------*/
5206 /* shiftL2Left2Result - shift left two bytes from left to result */
5207 /*-----------------------------------------------------------------*/
5209 shiftL2Left2Result (operand * left, int offl,
5210 operand * result, int offr, int shCount)
5212 if (sameRegs (AOP (result), AOP (left)) &&
5213 ((offl + MSB16) == offr))
5219 /* Copy left into result */
5220 movLeft2Result (left, offl, result, offr, 0);
5221 movLeft2Result (left, offl + 1, result, offr + 1, 0);
5223 /* PENDING: for now just see if it'll work. */
5224 /*if (AOP(result)->type == AOP_REG) { */
5228 symbol *tlbl, *tlbl1;
5231 tlbl = newiTempLabel (NULL);
5232 tlbl1 = newiTempLabel (NULL);
5234 /* Left is already in result - so now do the shift */
5237 emit2 ("ld a,!immedbyte+1", shCount);
5238 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5239 emitLabel (tlbl->key + 100);
5244 l = aopGet (AOP (result), offset, FALSE);
5248 emit2 ("sla %s", l);
5259 emitLabel (tlbl1->key + 100);
5261 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5266 /*-----------------------------------------------------------------*/
5267 /* AccRol - rotate left accumulator by known count */
5268 /*-----------------------------------------------------------------*/
5270 AccRol (int shCount)
5272 shCount &= 0x0007; // shCount : 0..7
5311 /*-----------------------------------------------------------------*/
5312 /* AccLsh - left shift accumulator by known count */
5313 /*-----------------------------------------------------------------*/
5315 AccLsh (int shCount)
5317 static const unsigned char SLMask[] =
5319 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5328 else if (shCount == 2)
5335 /* rotate left accumulator */
5337 /* and kill the lower order bits */
5338 emit2 ("and a,!immedbyte", SLMask[shCount]);
5343 /*-----------------------------------------------------------------*/
5344 /* shiftL1Left2Result - shift left one byte from left to result */
5345 /*-----------------------------------------------------------------*/
5347 shiftL1Left2Result (operand * left, int offl,
5348 operand * result, int offr, int shCount)
5351 l = aopGet (AOP (left), offl, FALSE);
5353 /* shift left accumulator */
5355 aopPut (AOP (result), "a", offr);
5359 /*-----------------------------------------------------------------*/
5360 /* genlshTwo - left shift two bytes by known amount != 0 */
5361 /*-----------------------------------------------------------------*/
5363 genlshTwo (operand * result, operand * left, int shCount)
5365 int size = AOP_SIZE (result);
5367 wassert (size == 2);
5369 /* if shCount >= 8 */
5377 movLeft2Result (left, LSB, result, MSB16, 0);
5378 aopPut (AOP (result), "!zero", 0);
5379 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5383 movLeft2Result (left, LSB, result, MSB16, 0);
5384 aopPut (AOP (result), "!zero", 0);
5389 aopPut (AOP (result), "!zero", LSB);
5392 /* 1 <= shCount <= 7 */
5401 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5406 /*-----------------------------------------------------------------*/
5407 /* genlshOne - left shift a one byte quantity by known count */
5408 /*-----------------------------------------------------------------*/
5410 genlshOne (operand * result, operand * left, int shCount)
5412 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5415 /*-----------------------------------------------------------------*/
5416 /* genLeftShiftLiteral - left shifting by known count */
5417 /*-----------------------------------------------------------------*/
5419 genLeftShiftLiteral (operand * left,
5424 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5427 freeAsmop (right, NULL, ic);
5429 aopOp (left, ic, FALSE, FALSE);
5430 aopOp (result, ic, FALSE, FALSE);
5432 size = getSize (operandType (result));
5434 /* I suppose that the left size >= result size */
5440 else if (shCount >= (size * 8))
5444 aopPut (AOP (result), "!zero", size);
5452 genlshOne (result, left, shCount);
5455 genlshTwo (result, left, shCount);
5458 wassertl (0, "Shifting of longs is currently unsupported");
5464 freeAsmop (left, NULL, ic);
5465 freeAsmop (result, NULL, ic);
5468 /*-----------------------------------------------------------------*/
5469 /* genLeftShift - generates code for left shifting */
5470 /*-----------------------------------------------------------------*/
5472 genLeftShift (iCode * ic)
5476 symbol *tlbl, *tlbl1;
5477 operand *left, *right, *result;
5479 right = IC_RIGHT (ic);
5480 left = IC_LEFT (ic);
5481 result = IC_RESULT (ic);
5483 aopOp (right, ic, FALSE, FALSE);
5485 /* if the shift count is known then do it
5486 as efficiently as possible */
5487 if (AOP_TYPE (right) == AOP_LIT)
5489 genLeftShiftLiteral (left, right, result, ic);
5493 /* shift count is unknown then we have to form a loop get the loop
5494 count in B : Note: we take only the lower order byte since
5495 shifting more that 32 bits make no sense anyway, ( the largest
5496 size of an object can be only 32 bits ) */
5497 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
5499 freeAsmop (right, NULL, ic);
5500 aopOp (left, ic, FALSE, FALSE);
5501 aopOp (result, ic, FALSE, FALSE);
5503 /* now move the left to the result if they are not the
5506 if (!sameRegs (AOP (left), AOP (result)))
5509 size = AOP_SIZE (result);
5513 l = aopGet (AOP (left), offset, FALSE);
5514 aopPut (AOP (result), l, offset);
5519 tlbl = newiTempLabel (NULL);
5520 size = AOP_SIZE (result);
5522 tlbl1 = newiTempLabel (NULL);
5524 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5525 emitLabel (tlbl->key + 100);
5526 l = aopGet (AOP (result), offset, FALSE);
5530 l = aopGet (AOP (result), offset, FALSE);
5534 emit2 ("sla %s", l);
5542 emitLabel (tlbl1->key + 100);
5544 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5546 freeAsmop (left, NULL, ic);
5547 freeAsmop (result, NULL, ic);
5550 /*-----------------------------------------------------------------*/
5551 /* genrshOne - left shift two bytes by known amount != 0 */
5552 /*-----------------------------------------------------------------*/
5554 genrshOne (operand * result, operand * left, int shCount, int is_signed)
5557 int size = AOP_SIZE (result);
5560 wassert (size == 1);
5561 wassert (shCount < 8);
5563 l = aopGet (AOP (left), 0, FALSE);
5565 if (AOP (result)->type == AOP_REG)
5567 aopPut (AOP (result), l, 0);
5568 l = aopGet (AOP (result), 0, FALSE);
5571 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5579 emit2 ("%s a", is_signed ? "sra" : "srl");
5581 aopPut (AOP (result), "a", 0);
5585 /*-----------------------------------------------------------------*/
5586 /* AccRsh - right shift accumulator by known count */
5587 /*-----------------------------------------------------------------*/
5589 AccRsh (int shCount)
5591 static const unsigned char SRMask[] =
5593 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
5598 /* rotate right accumulator */
5599 AccRol (8 - shCount);
5600 /* and kill the higher order bits */
5601 emit2 ("and a,!immedbyte", SRMask[shCount]);
5605 /*-----------------------------------------------------------------*/
5606 /* shiftR1Left2Result - shift right one byte from left to result */
5607 /*-----------------------------------------------------------------*/
5609 shiftR1Left2Result (operand * left, int offl,
5610 operand * result, int offr,
5611 int shCount, int sign)
5613 _moveA (aopGet (AOP (left), offl, FALSE));
5618 emit2 ("%s a", sign ? "sra" : "srl");
5625 aopPut (AOP (result), "a", offr);
5628 /*-----------------------------------------------------------------*/
5629 /* genrshTwo - right shift two bytes by known amount != 0 */
5630 /*-----------------------------------------------------------------*/
5632 genrshTwo (operand * result, operand * left,
5633 int shCount, int sign)
5635 /* if shCount >= 8 */
5641 shiftR1Left2Result (left, MSB16, result, LSB,
5646 movLeft2Result (left, MSB16, result, LSB, sign);
5650 /* Sign extend the result */
5651 _moveA(aopGet (AOP (result), 0, FALSE));
5655 aopPut (AOP (result), ACC_NAME, MSB16);
5659 aopPut (AOP (result), "!zero", 1);
5662 /* 1 <= shCount <= 7 */
5665 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
5669 /*-----------------------------------------------------------------*/
5670 /* genRightShiftLiteral - left shifting by known count */
5671 /*-----------------------------------------------------------------*/
5673 genRightShiftLiteral (operand * left,
5679 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5682 freeAsmop (right, NULL, ic);
5684 aopOp (left, ic, FALSE, FALSE);
5685 aopOp (result, ic, FALSE, FALSE);
5687 size = getSize (operandType (result));
5689 /* I suppose that the left size >= result size */
5695 else if (shCount >= (size * 8))
5697 aopPut (AOP (result), "!zero", size);
5703 genrshOne (result, left, shCount, sign);
5706 genrshTwo (result, left, shCount, sign);
5709 wassertl (0, "Asked to shift right a long which should be a function call");
5712 wassertl (0, "Entered default case in right shift delegate");
5715 freeAsmop (left, NULL, ic);
5716 freeAsmop (result, NULL, ic);
5719 /*-----------------------------------------------------------------*/
5720 /* genRightShift - generate code for right shifting */
5721 /*-----------------------------------------------------------------*/
5723 genRightShift (iCode * ic)
5725 operand *right, *left, *result;
5727 int size, offset, first = 1;
5731 symbol *tlbl, *tlbl1;
5733 /* if signed then we do it the hard way preserve the
5734 sign bit moving it inwards */
5735 retype = getSpec (operandType (IC_RESULT (ic)));
5737 is_signed = !SPEC_USIGN (retype);
5739 /* signed & unsigned types are treated the same : i.e. the
5740 signed is NOT propagated inwards : quoting from the
5741 ANSI - standard : "for E1 >> E2, is equivalent to division
5742 by 2**E2 if unsigned or if it has a non-negative value,
5743 otherwise the result is implementation defined ", MY definition
5744 is that the sign does not get propagated */
5746 right = IC_RIGHT (ic);
5747 left = IC_LEFT (ic);
5748 result = IC_RESULT (ic);
5750 aopOp (right, ic, FALSE, FALSE);
5752 /* if the shift count is known then do it
5753 as efficiently as possible */
5754 if (AOP_TYPE (right) == AOP_LIT)
5756 genRightShiftLiteral (left, right, result, ic, is_signed);
5760 aopOp (left, ic, FALSE, FALSE);
5761 aopOp (result, ic, FALSE, FALSE);
5763 /* now move the left to the result if they are not the
5765 if (!sameRegs (AOP (left), AOP (result)) &&
5766 AOP_SIZE (result) > 1)
5769 size = AOP_SIZE (result);
5773 l = aopGet (AOP (left), offset, FALSE);
5774 aopPut (AOP (result), l, offset);
5779 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
5781 freeAsmop (right, NULL, ic);
5783 tlbl = newiTempLabel (NULL);
5784 tlbl1 = newiTempLabel (NULL);
5785 size = AOP_SIZE (result);
5788 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5789 emitLabel (tlbl->key + 100);
5792 l = aopGet (AOP (result), offset--, FALSE);
5795 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5803 emitLabel (tlbl1->key + 100);
5805 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5807 freeAsmop (left, NULL, ic);
5808 freeAsmop (result, NULL, ic);
5811 /*-----------------------------------------------------------------*/
5812 /* genGenPointerGet - get value from generic pointer space */
5813 /*-----------------------------------------------------------------*/
5815 genGenPointerGet (operand * left,
5816 operand * result, iCode * ic)
5819 sym_link *retype = getSpec (operandType (result));
5825 aopOp (left, ic, FALSE, FALSE);
5826 aopOp (result, ic, FALSE, FALSE);
5828 size = AOP_SIZE (result);
5830 if (isPair (AOP (left)) && size == 1)
5833 if (isPtrPair (AOP (left)))
5835 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
5836 aopPut (AOP (result), buffer, 0);
5840 emit2 ("ld a,!*pair", getPairName (AOP (left)));
5841 aopPut (AOP (result), "a", 0);
5843 freeAsmop (left, NULL, ic);
5847 if ( getPairId( AOP (left)) == PAIR_IY)
5854 tsprintf (at, "!*iyx", offset);
5855 aopPut (AOP (result), at, offset);
5861 /* For now we always load into IY */
5862 /* if this is remateriazable */
5863 fetchPair (pair, AOP (left));
5865 freeAsmop (left, NULL, ic);
5867 /* if bit then unpack */
5868 if (IS_BITVAR (retype))
5872 else if ( getPairId( AOP (result)) == PAIR_HL)
5874 wassertl (size == 2, "HL must be of size 2");
5875 emit2 ("ld a,!*hl");
5877 emit2 ("ld h,!*hl");
5882 size = AOP_SIZE (result);
5887 /* PENDING: make this better */
5888 if (!IS_GB && AOP (result)->type == AOP_REG)
5890 aopPut (AOP (result), "!*hl", offset++);
5894 emit2 ("ld a,!*pair", _pairs[pair].name);
5895 aopPut (AOP (result), "a", offset++);
5899 emit2 ("inc %s", _pairs[pair].name);
5900 _G.pairs[pair].offset++;
5906 freeAsmop (result, NULL, ic);
5909 /*-----------------------------------------------------------------*/
5910 /* genPointerGet - generate code for pointer get */
5911 /*-----------------------------------------------------------------*/
5913 genPointerGet (iCode * ic)
5915 operand *left, *result;
5916 sym_link *type, *etype;
5918 left = IC_LEFT (ic);
5919 result = IC_RESULT (ic);
5921 /* depending on the type of pointer we need to
5922 move it to the correct pointer register */
5923 type = operandType (left);
5924 etype = getSpec (type);
5926 genGenPointerGet (left, result, ic);
5930 isRegOrLit (asmop * aop)
5932 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
5937 /*-----------------------------------------------------------------*/
5938 /* genGenPointerSet - stores the value into a pointer location */
5939 /*-----------------------------------------------------------------*/
5941 genGenPointerSet (operand * right,
5942 operand * result, iCode * ic)
5945 sym_link *retype = getSpec (operandType (right));
5946 PAIR_ID pairId = PAIR_HL;
5948 aopOp (result, ic, FALSE, FALSE);
5949 aopOp (right, ic, FALSE, FALSE);
5954 size = AOP_SIZE (right);
5956 /* Handle the exceptions first */
5957 if (isPair (AOP (result)) && size == 1)
5960 const char *l = aopGet (AOP (right), 0, FALSE);
5961 const char *pair = getPairName (AOP (result));
5962 if (canAssignToPtr (l) && isPtr (pair))
5964 emit2 ("ld !*pair,%s", pair, l);
5969 emit2 ("ld !*pair,a", pair);
5974 if ( getPairId( AOP (result)) == PAIR_IY)
5977 const char *l = aopGet (AOP (right), 0, FALSE);
5982 if (canAssignToPtr (l))
5984 emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
5988 _moveA (aopGet (AOP (right), offset, FALSE));
5989 emit2 ("ld !*iyx,a", offset);
5996 /* if the operand is already in dptr
5997 then we do nothing else we move the value to dptr */
5998 if (AOP_TYPE (result) != AOP_STR)
6000 fetchPair (pairId, AOP (result));
6002 /* so hl know contains the address */
6003 freeAsmop (result, NULL, ic);
6005 /* if bit then unpack */
6006 if (IS_BITVAR (retype))
6016 const char *l = aopGet (AOP (right), offset, FALSE);
6017 if (isRegOrLit (AOP (right)) && !IS_GB)
6019 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
6024 emit2 ("ld !*pair,a", _pairs[pairId].name);
6028 emit2 ("inc %s", _pairs[pairId].name);
6029 _G.pairs[pairId].offset++;
6035 freeAsmop (right, NULL, ic);
6038 /*-----------------------------------------------------------------*/
6039 /* genPointerSet - stores the value into a pointer location */
6040 /*-----------------------------------------------------------------*/
6042 genPointerSet (iCode * ic)
6044 operand *right, *result;
6045 sym_link *type, *etype;
6047 right = IC_RIGHT (ic);
6048 result = IC_RESULT (ic);
6050 /* depending on the type of pointer we need to
6051 move it to the correct pointer register */
6052 type = operandType (result);
6053 etype = getSpec (type);
6055 genGenPointerSet (right, result, ic);
6058 /*-----------------------------------------------------------------*/
6059 /* genIfx - generate code for Ifx statement */
6060 /*-----------------------------------------------------------------*/
6062 genIfx (iCode * ic, iCode * popIc)
6064 operand *cond = IC_COND (ic);
6067 aopOp (cond, ic, FALSE, TRUE);
6069 /* get the value into acc */
6070 if (AOP_TYPE (cond) != AOP_CRY)
6074 /* the result is now in the accumulator */
6075 freeAsmop (cond, NULL, ic);
6077 /* if there was something to be popped then do it */
6081 /* if the condition is a bit variable */
6082 if (isbit && IS_ITEMP (cond) &&
6084 genIfxJump (ic, SPIL_LOC (cond)->rname);
6085 else if (isbit && !IS_ITEMP (cond))
6086 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6088 genIfxJump (ic, "a");
6093 /*-----------------------------------------------------------------*/
6094 /* genAddrOf - generates code for address of */
6095 /*-----------------------------------------------------------------*/
6097 genAddrOf (iCode * ic)
6099 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6101 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
6103 /* if the operand is on the stack then we
6104 need to get the stack offset of this
6111 if (sym->stack <= 0)
6113 setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
6117 setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
6119 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
6123 emit2 ("ld de,!hashedstr", sym->rname);
6124 commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
6132 /* if it has an offset then we need to compute it */
6134 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
6136 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
6137 emit2 ("add hl,sp");
6141 emit2 ("ld hl,#%s", sym->rname);
6143 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
6145 freeAsmop (IC_RESULT (ic), NULL, ic);
6148 /*-----------------------------------------------------------------*/
6149 /* genAssign - generate code for assignment */
6150 /*-----------------------------------------------------------------*/
6152 genAssign (iCode * ic)
6154 operand *result, *right;
6156 unsigned long lit = 0L;
6158 result = IC_RESULT (ic);
6159 right = IC_RIGHT (ic);
6161 /* Dont bother assigning if they are the same */
6162 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
6164 emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
6168 aopOp (right, ic, FALSE, FALSE);
6169 aopOp (result, ic, TRUE, FALSE);
6171 /* if they are the same registers */
6172 if (sameRegs (AOP (right), AOP (result)))
6174 emitDebug ("; (registers are the same)");
6178 /* if the result is a bit */
6179 if (AOP_TYPE (result) == AOP_CRY)
6181 wassertl (0, "Tried to assign to a bit");
6185 size = AOP_SIZE (result);
6188 if (AOP_TYPE (right) == AOP_LIT)
6190 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6193 if (isPair (AOP (result)))
6195 fetchPair (getPairId (AOP (result)), AOP (right));
6197 else if ((size > 1) &&
6198 (AOP_TYPE (result) != AOP_REG) &&
6199 (AOP_TYPE (right) == AOP_LIT) &&
6200 !IS_FLOAT (operandType (right)) &&
6203 bool fXored = FALSE;
6205 /* Work from the top down.
6206 Done this way so that we can use the cached copy of 0
6207 in A for a fast clear */
6210 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
6212 if (!fXored && size > 1)
6219 aopPut (AOP (result), "a", offset);
6223 aopPut (AOP (result), "!zero", offset);
6227 aopPut (AOP (result),
6228 aopGet (AOP (right), offset, FALSE),
6233 else if (size == 2 && AOP_TYPE (right) == AOP_IY)
6235 emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
6236 aopPut (AOP (result), "l", LSB);
6237 aopPut (AOP (result), "h", MSB16);
6239 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
6241 /* Special case. Load into a and d, then load out. */
6242 _moveA (aopGet (AOP (right), 0, FALSE));
6243 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
6244 aopPut (AOP (result), "a", 0);
6245 aopPut (AOP (result), "e", 1);
6247 else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
6249 /* Special case - simple memcpy */
6250 aopGet (AOP (right), LSB, FALSE);
6253 aopGet (AOP (result), LSB, FALSE);
6257 emit2 ("ld a,(de)");
6258 /* Peephole will optimise this. */
6259 emit2 ("ld (hl),a");
6267 spillPair (PAIR_HL);
6273 /* PENDING: do this check better */
6274 if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
6276 _moveA (aopGet (AOP (right), offset, FALSE));
6277 aopPut (AOP (result), "a", offset);
6280 aopPut (AOP (result),
6281 aopGet (AOP (right), offset, FALSE),
6288 freeAsmop (right, NULL, ic);
6289 freeAsmop (result, NULL, ic);
6292 /*-----------------------------------------------------------------*/
6293 /* genJumpTab - genrates code for jump table */
6294 /*-----------------------------------------------------------------*/
6296 genJumpTab (iCode * ic)
6301 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
6302 /* get the condition into accumulator */
6303 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
6306 emit2 ("ld e,%s", l);
6307 emit2 ("ld d,!zero");
6308 jtab = newiTempLabel (NULL);
6310 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
6311 emit2 ("add hl,de");
6312 emit2 ("add hl,de");
6313 emit2 ("add hl,de");
6314 freeAsmop (IC_JTCOND (ic), NULL, ic);
6318 emitLabel (jtab->key + 100);
6319 /* now generate the jump labels */
6320 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
6321 jtab = setNextItem (IC_JTLABELS (ic)))
6322 emit2 ("jp !tlabel", jtab->key + 100);
6325 /*-----------------------------------------------------------------*/
6326 /* genCast - gen code for casting */
6327 /*-----------------------------------------------------------------*/
6329 genCast (iCode * ic)
6331 operand *result = IC_RESULT (ic);
6332 sym_link *ctype = operandType (IC_LEFT (ic));
6333 operand *right = IC_RIGHT (ic);
6336 /* if they are equivalent then do nothing */
6337 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
6340 aopOp (right, ic, FALSE, FALSE);
6341 aopOp (result, ic, FALSE, FALSE);
6343 /* if the result is a bit */
6344 if (AOP_TYPE (result) == AOP_CRY)
6346 wassertl (0, "Tried to cast to a bit");
6349 /* if they are the same size : or less */
6350 if (AOP_SIZE (result) <= AOP_SIZE (right))
6353 /* if they are in the same place */
6354 if (sameRegs (AOP (right), AOP (result)))
6357 /* if they in different places then copy */
6358 size = AOP_SIZE (result);
6362 aopPut (AOP (result),
6363 aopGet (AOP (right), offset, FALSE),
6370 /* So we now know that the size of destination is greater
6371 than the size of the source */
6372 /* we move to result for the size of source */
6373 size = AOP_SIZE (right);
6377 aopPut (AOP (result),
6378 aopGet (AOP (right), offset, FALSE),
6383 /* now depending on the sign of the destination */
6384 size = AOP_SIZE (result) - AOP_SIZE (right);
6385 /* Unsigned or not an integral type - right fill with zeros */
6386 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
6389 aopPut (AOP (result), "!zero", offset++);
6393 /* we need to extend the sign :{ */
6394 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
6400 aopPut (AOP (result), "a", offset++);
6404 freeAsmop (right, NULL, ic);
6405 freeAsmop (result, NULL, ic);
6408 /*-----------------------------------------------------------------*/
6409 /* genReceive - generate code for a receive iCode */
6410 /*-----------------------------------------------------------------*/
6412 genReceive (iCode * ic)
6414 if (isOperandInFarSpace (IC_RESULT (ic)) &&
6415 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
6416 IS_TRUE_SYMOP (IC_RESULT (ic))))
6426 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
6427 size = AOP_SIZE(IC_RESULT(ic));
6429 for (i = 0; i < size; i++) {
6430 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
6434 freeAsmop (IC_RESULT (ic), NULL, ic);
6439 /** Maximum number of bytes to emit per line. */
6443 /** Context for the byte output chunker. */
6446 unsigned char buffer[DBEMIT_MAX_RUN];
6451 /** Flushes a byte chunker by writing out all in the buffer and
6455 _dbFlush(DBEMITCTX *self)
6462 sprintf(line, ".db 0x%02X", self->buffer[0]);
6464 for (i = 1; i < self->pos; i++)
6466 sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
6473 /** Write out another byte, buffering until a decent line is
6477 _dbEmit(DBEMITCTX *self, int c)
6479 if (self->pos == DBEMIT_MAX_RUN)
6483 self->buffer[self->pos++] = c;
6486 /** Context for a simple run length encoder. */
6490 unsigned char buffer[128];
6492 /** runLen may be equivalent to pos. */
6498 RLE_CHANGE_COST = 4,
6502 /** Flush the buffer of a run length encoder by writing out the run or
6503 data that it currently contains.
6506 _rleCommit(RLECTX *self)
6512 memset(&db, 0, sizeof(db));
6514 emit2(".db %u", self->pos);
6516 for (i = 0; i < self->pos; i++)
6518 _dbEmit(&db, self->buffer[i]);
6527 Can get either a run or a block of random stuff.
6528 Only want to change state if a good run comes in or a run ends.
6529 Detecting run end is easy.
6532 Say initial state is in run, len zero, last zero. Then if you get a
6533 few zeros then something else then a short run will be output.
6534 Seems OK. While in run mode, keep counting. While in random mode,
6535 keep a count of the run. If run hits margin, output all up to run,
6536 restart, enter run mode.
6539 /** Add another byte into the run length encoder, flushing as
6540 required. The run length encoder uses the Amiga IFF style, where
6541 a block is prefixed by its run length. A positive length means
6542 the next n bytes pass straight through. A negative length means
6543 that the next byte is repeated -n times. A zero terminates the
6547 _rleAppend(RLECTX *self, int c)
6551 if (c != self->last)
6553 /* The run has stopped. See if it is worthwhile writing it out
6554 as a run. Note that the random data comes in as runs of
6557 if (self->runLen > RLE_CHANGE_COST)
6559 /* Yes, worthwhile. */
6560 /* Commit whatever was in the buffer. */
6562 emit2(".db -%u,0x%02X", self->runLen, self->last);
6566 /* Not worthwhile. Append to the end of the random list. */
6567 for (i = 0; i < self->runLen; i++)
6569 if (self->pos >= RLE_MAX_BLOCK)
6574 self->buffer[self->pos++] = self->last;
6582 if (self->runLen >= RLE_MAX_BLOCK)
6584 /* Commit whatever was in the buffer. */
6587 emit2 (".db -%u,0x%02X", self->runLen, self->last);
6595 _rleFlush(RLECTX *self)
6597 _rleAppend(self, -1);
6604 /** genArrayInit - Special code for initialising an array with constant
6608 genArrayInit (iCode * ic)
6612 int elementSize = 0, eIndex, i;
6613 unsigned val, lastVal;
6617 memset(&rle, 0, sizeof(rle));
6619 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
6621 _saveRegsForCall(ic, 0);
6623 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
6624 emit2 ("call __initrleblock");
6626 type = operandType(IC_LEFT(ic));
6628 if (type && type->next)
6630 elementSize = getSize(type->next);
6634 wassertl (0, "Can't determine element size in genArrayInit.");
6637 iLoop = IC_ARRAYILIST(ic);
6638 lastVal = (unsigned)-1;
6640 /* Feed all the bytes into the run length encoder which will handle
6642 This works well for mixed char data, and for random int and long
6651 for (i = 0; i < ix; i++)
6653 for (eIndex = 0; eIndex < elementSize; eIndex++)
6655 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
6656 _rleAppend(&rle, val);
6661 iLoop = iLoop->next;
6665 /* Mark the end of the run. */
6668 _restoreRegsAfterCall();
6672 freeAsmop (IC_LEFT(ic), NULL, ic);
6675 /*-----------------------------------------------------------------*/
6676 /* genZ80Code - generate code for Z80 based controllers */
6677 /*-----------------------------------------------------------------*/
6679 genZ80Code (iCode * lic)
6687 _fReturn = _gbz80_return;
6688 _fTmp = _gbz80_return;
6692 _fReturn = _z80_return;
6693 _fTmp = _z80_return;
6696 _G.lines.head = _G.lines.current = NULL;
6698 for (ic = lic; ic; ic = ic->next)
6701 if (cln != ic->lineno)
6703 emit2 ("; %s %d", ic->filename, ic->lineno);
6706 /* if the result is marked as
6707 spilt and rematerializable or code for
6708 this has already been generated then
6710 if (resultRemat (ic) || ic->generated)
6713 /* depending on the operation */
6717 emitDebug ("; genNot");
6722 emitDebug ("; genCpl");
6727 emitDebug ("; genUminus");
6732 emitDebug ("; genIpush");
6737 /* IPOP happens only when trying to restore a
6738 spilt live range, if there is an ifx statement
6739 following this pop then the if statement might
6740 be using some of the registers being popped which
6741 would destory the contents of the register so
6742 we need to check for this condition and handle it */
6744 ic->next->op == IFX &&
6745 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
6747 emitDebug ("; genIfx");
6748 genIfx (ic->next, ic);
6752 emitDebug ("; genIpop");
6758 emitDebug ("; genCall");
6763 emitDebug ("; genPcall");
6768 emitDebug ("; genFunction");
6773 emitDebug ("; genEndFunction");
6774 genEndFunction (ic);
6778 emitDebug ("; genRet");
6783 emitDebug ("; genLabel");
6788 emitDebug ("; genGoto");
6793 emitDebug ("; genPlus");
6798 emitDebug ("; genMinus");
6803 emitDebug ("; genMult");
6808 emitDebug ("; genDiv");
6813 emitDebug ("; genMod");
6818 emitDebug ("; genCmpGt");
6819 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
6823 emitDebug ("; genCmpLt");
6824 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
6831 /* note these two are xlated by algebraic equivalence
6832 during parsing SDCC.y */
6833 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6834 "got '>=' or '<=' shouldn't have come here");
6838 emitDebug ("; genCmpEq");
6839 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
6843 emitDebug ("; genAndOp");
6848 emitDebug ("; genOrOp");
6853 emitDebug ("; genXor");
6854 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
6858 emitDebug ("; genOr");
6859 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
6863 emitDebug ("; genAnd");
6864 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
6868 emitDebug ("; genInline");
6873 emitDebug ("; genRRC");
6878 emitDebug ("; genRLC");
6883 emitDebug ("; genGetHBIT");
6888 emitDebug ("; genLeftShift");
6893 emitDebug ("; genRightShift");
6897 case GET_VALUE_AT_ADDRESS:
6898 emitDebug ("; genPointerGet");
6904 if (POINTER_SET (ic))
6906 emitDebug ("; genAssign (pointer)");
6911 emitDebug ("; genAssign");
6917 emitDebug ("; genIfx");
6922 emitDebug ("; genAddrOf");
6927 emitDebug ("; genJumpTab");
6932 emitDebug ("; genCast");
6937 emitDebug ("; genReceive");
6942 emitDebug ("; addSet");
6943 addSet (&_G.sendSet, ic);
6947 emitDebug ("; genArrayInit");
6957 /* now we are ready to call the
6958 peep hole optimizer */
6959 if (!options.nopeep)
6960 peepHole (&_G.lines.head);
6962 /* This is unfortunate */
6963 /* now do the actual printing */
6965 FILE *fp = codeOutFile;
6966 if (isInHome () && codeOutFile == code->oFile)
6967 codeOutFile = home->oFile;
6968 printLine (_G.lines.head, codeOutFile);
6969 if (_G.flushStatics)
6972 _G.flushStatics = 0;
6977 freeTrace(&_G.lines.trace);
6978 freeTrace(&_G.trace.aops);
6984 _isPairUsed (iCode * ic, PAIR_ID pairId)
6990 if (bitVectBitValue (ic->rMask, D_IDX))
6992 if (bitVectBitValue (ic->rMask, E_IDX))
7002 fetchLitSpecial (asmop * aop, bool negate, bool xor)
7005 value *val = aop->aopu.aop_lit;
7007 wassert (aop->type == AOP_LIT);
7008 wassert (!IS_FLOAT (val->type));
7010 v = (unsigned long) floatFromVal (val);
7018 tsprintf (buffer, "!immedword", v);
7019 return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));