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", "iy.l?", "iy.h?" },
170 { "ix", "ix.l?", "ix.h?" }
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;
258 /* Clean up the line so that it is 'prettier' */
259 if (strchr (buf, ':'))
261 /* Is a label - cant do anything */
264 /* Change the first (and probably only) ' ' to a tab so
279 _newLineNode (char *line)
283 pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
284 pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
290 _vemit2 (const char *szFormat, va_list ap)
294 tvsprintf (buffer, szFormat, ap);
297 _G.lines.current = (_G.lines.current ?
298 connectLine (_G.lines.current, _newLineNode (buffer)) :
299 (_G.lines.head = _newLineNode (buffer)));
301 _G.lines.current->isInline = _G.lines.isInline;
305 emit2 (const char *szFormat,...)
309 va_start (ap, szFormat);
311 _vemit2 (szFormat, ap);
317 emitDebug (const char *szFormat,...)
323 va_start (ap, szFormat);
325 _vemit2 (szFormat, ap);
331 /*-----------------------------------------------------------------*/
332 /* emit2 - writes the code into a file : for now it is simple */
333 /*-----------------------------------------------------------------*/
335 _emit2 (const char *inst, const char *fmt,...)
338 char lb[INITIAL_INLINEASM];
345 sprintf (lb, "%s\t", inst);
346 vsprintf (lb + (strlen (lb)), fmt, ap);
349 vsprintf (lb, fmt, ap);
351 while (isspace (*lbp))
356 _G.lines.current = (_G.lines.current ?
357 connectLine (_G.lines.current, _newLineNode (lb)) :
358 (_G.lines.head = _newLineNode (lb)));
360 _G.lines.current->isInline = _G.lines.isInline;
365 _emitMove(const char *to, const char *from)
367 if (strcasecmp(to, from) != 0)
369 emit2("ld %s,%s", to, from);
374 // Could leave this to the peephole, but sometimes the peephole is inhibited.
379 _moveA(const char *moveFrom)
381 // Let the peephole optimiser take care of redundent loads
382 _emitMove(ACC_NAME, moveFrom);
392 getPairName (asmop * aop)
394 if (aop->type == AOP_REG)
396 switch (aop->aopu.aop_reg[0]->rIdx)
409 else if (aop->type == AOP_STR)
411 switch (*aop->aopu.aop_str[0])
424 wassertl (0, "Tried to get the pair name of something that isn't a pair");
429 getPairId (asmop * aop)
433 if (aop->type == AOP_REG)
435 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
439 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
443 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
448 if (aop->type == AOP_STR)
450 if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
454 if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
458 if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
467 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
471 return (getPairId (aop) != PAIR_INVALID);
475 isPtrPair (asmop * aop)
477 PAIR_ID pairId = getPairId (aop);
490 spillPair (PAIR_ID pairId)
492 _G.pairs[pairId].last_type = AOP_INVALID;
493 _G.pairs[pairId].base = NULL;
496 /** Push a register pair onto the stack */
498 genPairPush (asmop * aop)
500 emit2 ("push %s", getPairName (aop));
504 _push (PAIR_ID pairId)
506 emit2 ("push %s", _pairs[pairId].name);
507 _G.stack.pushed += 2;
511 _pop (PAIR_ID pairId)
513 emit2 ("pop %s", _pairs[pairId].name);
514 _G.stack.pushed -= 2;
518 /*-----------------------------------------------------------------*/
519 /* newAsmop - creates a new asmOp */
520 /*-----------------------------------------------------------------*/
522 newAsmop (short type)
526 aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
531 /*-----------------------------------------------------------------*/
532 /* aopForSym - for a true symbol */
533 /*-----------------------------------------------------------------*/
535 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
542 wassert (sym->etype);
544 space = SPEC_OCLS (sym->etype);
546 /* if already has one */
550 /* Assign depending on the storage class */
551 if (sym->onStack || sym->iaccess)
553 /* The pointer that is used depends on how big the offset is.
554 Normally everything is AOP_STK, but for offsets of < -128 or
555 > 127 on the Z80 an extended stack pointer is used.
557 if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
559 emitDebug ("; AOP_EXSTK for %s", sym->rname);
560 sym->aop = aop = newAsmop (AOP_EXSTK);
564 emitDebug ("; AOP_STK for %s", sym->rname);
565 sym->aop = aop = newAsmop (AOP_STK);
568 aop->size = getSize (sym->type);
569 aop->aopu.aop_stk = sym->stack;
573 /* special case for a function */
574 if (IS_FUNC (sym->type))
576 sym->aop = aop = newAsmop (AOP_IMMD);
577 aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
584 /* if it is in direct space */
585 if (IN_REGSP (space) && !requires_a)
587 sym->aop = aop = newAsmop (AOP_SFR);
588 aop->aopu.aop_dir = sym->rname;
589 aop->size = getSize (sym->type);
590 emitDebug ("; AOP_SFR for %s", sym->rname);
595 /* only remaining is far space */
596 /* in which case DPTR gets the address */
599 emitDebug ("; AOP_HL for %s", sym->rname);
600 sym->aop = aop = newAsmop (AOP_HL);
604 sym->aop = aop = newAsmop (AOP_IY);
606 aop->size = getSize (sym->type);
607 aop->aopu.aop_dir = sym->rname;
609 /* if it is in code space */
610 if (IN_CODESPACE (space))
616 /*-----------------------------------------------------------------*/
617 /* aopForRemat - rematerialzes an object */
618 /*-----------------------------------------------------------------*/
620 aopForRemat (symbol * sym)
623 iCode *ic = sym->rematiCode;
624 asmop *aop = newAsmop (AOP_IMMD);
628 /* if plus or minus print the right hand side */
629 if (ic->op == '+' || ic->op == '-')
631 /* PENDING: for re-target */
632 sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
635 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
638 /* we reached the end */
639 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
643 aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
647 /*-----------------------------------------------------------------*/
648 /* regsInCommon - two operands have some registers in common */
649 /*-----------------------------------------------------------------*/
651 regsInCommon (operand * op1, operand * op2)
656 /* if they have registers in common */
657 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
660 sym1 = OP_SYMBOL (op1);
661 sym2 = OP_SYMBOL (op2);
663 if (sym1->nRegs == 0 || sym2->nRegs == 0)
666 for (i = 0; i < sym1->nRegs; i++)
672 for (j = 0; j < sym2->nRegs; j++)
677 if (sym2->regs[j] == sym1->regs[i])
685 /*-----------------------------------------------------------------*/
686 /* operandsEqu - equivalent */
687 /*-----------------------------------------------------------------*/
689 operandsEqu (operand * op1, operand * op2)
693 /* if they not symbols */
694 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
697 sym1 = OP_SYMBOL (op1);
698 sym2 = OP_SYMBOL (op2);
700 /* if both are itemps & one is spilt
701 and the other is not then false */
702 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
703 sym1->isspilt != sym2->isspilt)
706 /* if they are the same */
710 if (strcmp (sym1->rname, sym2->rname) == 0)
714 /* if left is a tmp & right is not */
715 if (IS_ITEMP (op1) &&
718 (sym1->usl.spillLoc == sym2))
721 if (IS_ITEMP (op2) &&
725 (sym2->usl.spillLoc == sym1))
731 /*-----------------------------------------------------------------*/
732 /* sameRegs - two asmops have the same registers */
733 /*-----------------------------------------------------------------*/
735 sameRegs (asmop * aop1, asmop * aop2)
739 if (aop1->type == AOP_SFR ||
740 aop2->type == AOP_SFR)
746 if (aop1->type != AOP_REG ||
747 aop2->type != AOP_REG)
750 if (aop1->size != aop2->size)
753 for (i = 0; i < aop1->size; i++)
754 if (aop1->aopu.aop_reg[i] !=
755 aop2->aopu.aop_reg[i])
761 /*-----------------------------------------------------------------*/
762 /* aopOp - allocates an asmop for an operand : */
763 /*-----------------------------------------------------------------*/
765 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
774 /* if this a literal */
775 if (IS_OP_LITERAL (op))
777 op->aop = aop = newAsmop (AOP_LIT);
778 aop->aopu.aop_lit = op->operand.valOperand;
779 aop->size = getSize (operandType (op));
783 /* if already has a asmop then continue */
787 /* if the underlying symbol has a aop */
788 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
790 op->aop = OP_SYMBOL (op)->aop;
794 /* if this is a true symbol */
795 if (IS_TRUE_SYMOP (op))
797 op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
801 /* this is a temporary : this has
807 e) can be a return use only */
809 sym = OP_SYMBOL (op);
811 /* if the type is a conditional */
812 if (sym->regType == REG_CND)
814 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
819 /* if it is spilt then two situations
821 b) has a spill location */
822 if (sym->isspilt || sym->nRegs == 0)
824 /* rematerialize it NOW */
827 sym->aop = op->aop = aop =
829 aop->size = getSize (sym->type);
835 if (sym->accuse == ACCUSE_A)
837 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
838 aop->size = getSize (sym->type);
839 wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
841 aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
843 else if (sym->accuse == ACCUSE_HL)
846 aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
847 aop->size = getSize (sym->type);
848 wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
849 aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
850 aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
854 wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
862 aop = op->aop = sym->aop = newAsmop (AOP_STR);
863 aop->size = getSize (sym->type);
864 for (i = 0; i < 4; i++)
865 aop->aopu.aop_str[i] = _fReturn[i];
869 /* else spill location */
870 sym->aop = op->aop = aop =
871 aopForSym (ic, sym->usl.spillLoc, result, requires_a);
872 aop->size = getSize (sym->type);
876 /* must be in a register */
877 sym->aop = op->aop = aop = newAsmop (AOP_REG);
878 aop->size = sym->nRegs;
879 for (i = 0; i < sym->nRegs; i++)
880 aop->aopu.aop_reg[i] = sym->regs[i];
883 /*-----------------------------------------------------------------*/
884 /* freeAsmop - free up the asmop given to an operand */
885 /*----------------------------------------------------------------*/
887 freeAsmop (operand * op, asmop * aaop, iCode * ic)
904 if (aop->type == AOP_PAIRPTR && IS_Z80 && aop->aopu.aop_pairId == PAIR_DE)
906 _pop (aop->aopu.aop_pairId);
910 /* all other cases just dealloc */
916 OP_SYMBOL (op)->aop = NULL;
917 /* if the symbol has a spill */
919 SPIL_LOC (op)->aop = NULL;
926 isLitWord (asmop * aop)
928 /* if (aop->size != 2)
941 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
946 /* depending on type */
952 /* PENDING: for re-target */
955 tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
957 else if (offset == 0)
959 tsprintf (s, "%s", aop->aopu.aop_immd);
963 tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
965 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
969 value *val = aop->aopu.aop_lit;
970 /* if it is a float then it gets tricky */
971 /* otherwise it is fairly simple */
972 if (!IS_FLOAT (val->type))
974 unsigned long v = (unsigned long) floatFromVal (val);
980 else if (offset == 0)
986 wassertl(0, "Encountered an invalid offset while fetching a literal");
990 tsprintf (buffer, "!immedword", v);
992 tsprintf (buffer, "!constword", v);
994 return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1000 convertFloat (&f, floatFromVal (val));
1002 tsprintf (buffer, "!immedword", f.w[offset / 2]);
1004 tsprintf (buffer, "!constword", f.w[offset / 2]);
1005 rs = Safe_calloc (1, strlen (buffer) + 1);
1006 return strcpy (rs, buffer);
1015 aopGetWord (asmop * aop, int offset)
1017 return aopGetLitWordLong (aop, offset, TRUE);
1021 isPtr (const char *s)
1023 if (!strcmp (s, "hl"))
1025 if (!strcmp (s, "ix"))
1027 if (!strcmp (s, "iy"))
1033 adjustPair (const char *pair, int *pold, int new)
1039 emit2 ("inc %s", pair);
1044 emit2 ("dec %s", pair);
1052 spillPair (PAIR_HL);
1053 spillPair (PAIR_IY);
1057 requiresHL (asmop * aop)
1072 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
1074 const char *l, *base;
1075 const char *pair = _pairs[pairId].name;
1076 l = aopGetLitWordLong (left, offset, FALSE);
1077 base = aopGetLitWordLong (left, 0, FALSE);
1078 wassert (l && pair && base);
1082 if (pairId == PAIR_HL || pairId == PAIR_IY)
1084 if (_G.pairs[pairId].last_type == left->type)
1086 if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
1088 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
1090 adjustPair (pair, &_G.pairs[pairId].offset, offset);
1093 if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
1100 _G.pairs[pairId].last_type = left->type;
1101 _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
1102 _G.pairs[pairId].offset = offset;
1104 /* Both a lit on the right and a true symbol on the left */
1105 emit2 ("ld %s,!hashedstr", pair, l);
1109 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
1111 /* if this is remateriazable */
1112 if (isLitWord (aop)) {
1113 fetchLitPair (pairId, aop, offset);
1116 /* we need to get it byte by byte */
1117 if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1118 aopGet (aop, offset, FALSE);
1119 switch (aop->size - offset) {
1121 emit2 ("ld l,!*hl");
1122 emit2 ("ld h,!immedbyte", 0);
1125 // PENDING: Requires that you are only fetching two bytes.
1128 emit2 ("ld h,!*hl");
1132 wassertl (0, "Attempted to fetch too much data into HL");
1136 else if (IS_Z80 && aop->type == AOP_IY) {
1137 /* Instead of fetching relative to IY, just grab directly
1138 from the address IY refers to */
1139 char *l = aopGetLitWordLong (aop, offset, FALSE);
1141 emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1143 if (aop->size < 2) {
1144 emit2("ld %s,!zero", _pairs[pairId].h);
1148 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1149 emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1151 /* PENDING: check? */
1152 if (pairId == PAIR_HL)
1153 spillPair (PAIR_HL);
1158 fetchPair (PAIR_ID pairId, asmop * aop)
1160 fetchPairLong (pairId, aop, 0);
1164 fetchHL (asmop * aop)
1166 fetchPair (PAIR_HL, aop);
1170 setupPairFromSP (PAIR_ID id, int offset)
1172 wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
1174 if (offset < INT8MIN || offset > INT8MAX)
1176 emit2 ("ld hl,!immedword", offset);
1177 emit2 ("add hl,sp");
1181 emit2 ("!ldahlsp", offset);
1186 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1191 wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
1192 fetchLitPair (pairId, aop, 0);
1196 wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
1198 fetchLitPair (pairId, aop, offset);
1199 _G.pairs[pairId].offset = offset;
1203 wassertl (IS_Z80, "Only the Z80 has an extended stack");
1204 wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
1207 int offset = aop->aopu.aop_stk + _G.stack.offset;
1209 if (_G.pairs[pairId].last_type == aop->type &&
1210 _G.pairs[pairId].offset == offset)
1216 /* PENDING: Do this better. */
1217 sprintf (buffer, "%d", offset + _G.stack.pushed);
1218 emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
1219 emit2 ("add %s,sp", _pairs[pairId].name);
1220 _G.pairs[pairId].last_type = aop->type;
1221 _G.pairs[pairId].offset = offset;
1228 /* Doesnt include _G.stack.pushed */
1229 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1230 if (aop->aopu.aop_stk > 0)
1232 abso += _G.stack.param_offset;
1234 assert (pairId == PAIR_HL);
1235 /* In some cases we can still inc or dec hl */
1236 if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1238 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1242 setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
1244 _G.pairs[pairId].offset = abso;
1249 adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
1255 _G.pairs[pairId].last_type = aop->type;
1261 emit2 ("!tlabeldef", key);
1265 /*-----------------------------------------------------------------*/
1266 /* aopGet - for fetching value of the aop */
1267 /*-----------------------------------------------------------------*/
1269 aopGet (asmop * aop, int offset, bool bit16)
1273 /* offset is greater than size then zero */
1274 /* PENDING: this seems a bit screwed in some pointer cases. */
1275 if (offset > (aop->size - 1) &&
1276 aop->type != AOP_LIT)
1278 tsprintf (s, "!zero");
1279 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1282 /* depending on type */
1286 /* PENDING: re-target */
1288 tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1293 tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1296 tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1299 tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1302 wassertl (0, "Fetching from beyond the limits of an immediate value.");
1305 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1309 emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
1312 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1316 emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
1319 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1322 return aop->aopu.aop_reg[offset]->name;
1326 setupPair (PAIR_HL, aop, offset);
1327 tsprintf (s, "!*hl");
1329 return traceAlloc(&_G.trace.aops, Safe_strdup (s));
1333 setupPair (PAIR_IY, aop, offset);
1334 tsprintf (s, "!*iyx", offset);
1336 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1340 setupPair (PAIR_IY, aop, offset);
1341 tsprintf (s, "!*iyx", offset, offset);
1343 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1348 setupPair (PAIR_HL, aop, offset);
1349 tsprintf (s, "!*hl");
1353 if (aop->aopu.aop_stk >= 0)
1354 offset += _G.stack.param_offset;
1355 tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
1358 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1361 wassertl (0, "Tried to fetch from a bit variable");
1370 tsprintf(s, "!zero");
1371 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1375 wassert (offset < 2);
1376 return aop->aopu.aop_str[offset];
1379 return aopLiteral (aop->aopu.aop_lit, offset);
1383 unsigned long v = aop->aopu.aop_simplelit;
1386 tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
1388 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1392 return aop->aopu.aop_str[offset];
1395 setupPair (aop->aopu.aop_pairId, aop, offset);
1396 sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
1398 return traceAlloc(&_G.trace.aops, Safe_strdup(s));
1403 wassertl (0, "aopget got unsupported aop->type");
1408 isRegString (const char *s)
1410 if (!strcmp (s, "b") ||
1422 isConstant (const char *s)
1424 /* This is a bit of a hack... */
1425 return (*s == '#' || *s == '$');
1429 canAssignToPtr (const char *s)
1431 if (isRegString (s))
1438 /*-----------------------------------------------------------------*/
1439 /* aopPut - puts a string for a aop */
1440 /*-----------------------------------------------------------------*/
1442 aopPut (asmop * aop, const char *s, int offset)
1446 if (aop->size && offset > (aop->size - 1))
1448 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1449 "aopPut got offset > aop->size");
1454 tsprintf(buffer2, s);
1457 /* will assign value to value */
1458 /* depending on where it is ofcourse */
1464 if (strcmp (s, "a"))
1465 emit2 ("ld a,%s", s);
1466 emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1471 if (strcmp (s, "a"))
1472 emit2 ("ld a,%s", s);
1473 emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1477 if (!strcmp (s, "!*hl"))
1478 emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1481 aop->aopu.aop_reg[offset]->name, s);
1486 if (!canAssignToPtr (s))
1488 emit2 ("ld a,%s", s);
1489 setupPair (PAIR_IY, aop, offset);
1490 emit2 ("ld !*iyx,a", offset);
1494 setupPair (PAIR_IY, aop, offset);
1495 emit2 ("ld !*iyx,%s", offset, s);
1501 /* PENDING: for re-target */
1502 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1504 emit2 ("ld a,!*hl");
1507 setupPair (PAIR_HL, aop, offset);
1509 emit2 ("ld !*hl,%s", s);
1514 if (!canAssignToPtr (s))
1516 emit2 ("ld a,%s", s);
1517 setupPair (PAIR_IY, aop, offset);
1518 emit2 ("ld !*iyx,a", offset);
1522 setupPair (PAIR_IY, aop, offset);
1523 emit2 ("ld !*iyx,%s", offset, s);
1530 /* PENDING: re-target */
1531 if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1533 emit2 ("ld a,!*hl");
1536 setupPair (PAIR_HL, aop, offset);
1537 if (!canAssignToPtr (s))
1539 emit2 ("ld a,%s", s);
1540 emit2 ("ld !*hl,a");
1543 emit2 ("ld !*hl,%s", s);
1547 if (aop->aopu.aop_stk >= 0)
1548 offset += _G.stack.param_offset;
1549 if (!canAssignToPtr (s))
1551 emit2 ("ld a,%s", s);
1552 emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1555 emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1560 /* if bit variable */
1561 if (!aop->aopu.aop_dir)
1568 /* In bit space but not in C - cant happen */
1569 wassertl (0, "Tried to write into a bit variable");
1575 if (strcmp (aop->aopu.aop_str[offset], s))
1577 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1583 if (!offset && (strcmp (s, "acc") == 0))
1587 wassertl (0, "Tried to access past the end of A");
1591 if (strcmp (aop->aopu.aop_str[offset], s))
1592 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1597 wassert (offset < 2);
1598 emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1602 setupPair (aop->aopu.aop_pairId, aop, offset);
1603 emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
1607 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1608 "aopPut got unsupported aop->type");
1613 #define AOP(op) op->aop
1614 #define AOP_TYPE(op) AOP(op)->type
1615 #define AOP_SIZE(op) AOP(op)->size
1616 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1619 commitPair (asmop * aop, PAIR_ID id)
1621 if (id == PAIR_HL && requiresHL (aop))
1625 aopPut (aop, "a", 0);
1626 aopPut (aop, "d", 1);
1630 aopPut (aop, _pairs[id].l, 0);
1631 aopPut (aop, _pairs[id].h, 1);
1635 /*-----------------------------------------------------------------*/
1636 /* getDataSize - get the operand data size */
1637 /*-----------------------------------------------------------------*/
1639 getDataSize (operand * op)
1642 size = AOP_SIZE (op);
1646 wassertl (0, "Somehow got a three byte data pointer");
1651 /*-----------------------------------------------------------------*/
1652 /* movLeft2Result - move byte from left to result */
1653 /*-----------------------------------------------------------------*/
1655 movLeft2Result (operand * left, int offl,
1656 operand * result, int offr, int sign)
1659 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1661 l = aopGet (AOP (left), offl, FALSE);
1665 aopPut (AOP (result), l, offr);
1669 if (getDataSize (left) == offl + 1)
1671 emit2 ("ld a,%s", l);
1672 aopPut (AOP (result), "a", offr);
1679 /** Put Acc into a register set
1682 outAcc (operand * result)
1685 size = getDataSize (result);
1688 aopPut (AOP (result), "a", 0);
1691 /* unsigned or positive */
1694 aopPut (AOP (result), "!zero", offset++);
1699 /** Take the value in carry and put it into a register
1702 outBitCLong (operand * result, bool swap_sense)
1704 /* if the result is bit */
1705 if (AOP_TYPE (result) == AOP_CRY)
1707 wassertl (0, "Tried to write carry to a bit");
1711 emit2 ("ld a,!zero");
1714 emit2 ("xor a,!immedbyte", 1);
1720 outBitC (operand * result)
1722 outBitCLong (result, FALSE);
1725 /*-----------------------------------------------------------------*/
1726 /* toBoolean - emit code for orl a,operator(sizeop) */
1727 /*-----------------------------------------------------------------*/
1729 _toBoolean (operand * oper)
1731 int size = AOP_SIZE (oper);
1735 emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
1738 emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
1742 if (AOP (oper)->type != AOP_ACC)
1745 emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
1750 /*-----------------------------------------------------------------*/
1751 /* genNot - generate code for ! operation */
1752 /*-----------------------------------------------------------------*/
1756 sym_link *optype = operandType (IC_LEFT (ic));
1758 /* assign asmOps to operand & result */
1759 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1760 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1762 /* if in bit space then a special case */
1763 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1765 wassertl (0, "Tried to negate a bit");
1768 /* if type float then do float */
1769 if (IS_FLOAT (optype))
1771 wassertl (0, "Tried to negate a float");
1774 _toBoolean (IC_LEFT (ic));
1779 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1780 emit2 ("sub a,!one");
1781 outBitC (IC_RESULT (ic));
1783 /* release the aops */
1784 freeAsmop (IC_LEFT (ic), NULL, ic);
1785 freeAsmop (IC_RESULT (ic), NULL, ic);
1788 /*-----------------------------------------------------------------*/
1789 /* genCpl - generate code for complement */
1790 /*-----------------------------------------------------------------*/
1798 /* assign asmOps to operand & result */
1799 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1800 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1802 /* if both are in bit space then
1804 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1805 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1807 wassertl (0, "Left and the result are in bit space");
1810 size = AOP_SIZE (IC_RESULT (ic));
1813 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1816 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1819 /* release the aops */
1820 freeAsmop (IC_LEFT (ic), NULL, ic);
1821 freeAsmop (IC_RESULT (ic), NULL, ic);
1825 _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
1832 store de into result
1837 store de into result
1839 const char *first = isAdd ? "add" : "sub";
1840 const char *later = isAdd ? "adc" : "sbc";
1842 wassertl (IS_GB, "Code is only relevent to the gbz80");
1843 wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
1845 fetchPair (PAIR_DE, left);
1848 emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
1851 emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
1854 aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
1855 aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
1857 fetchPairLong (PAIR_DE, left, MSB24);
1858 aopGet (right, MSB24, FALSE);
1862 emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
1865 emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
1867 aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
1868 aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
1872 _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
1874 _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
1877 /*-----------------------------------------------------------------*/
1878 /* genUminus - unary minus code generation */
1879 /*-----------------------------------------------------------------*/
1881 genUminus (iCode * ic)
1884 sym_link *optype, *rtype;
1887 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1888 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1890 /* if both in bit space then special
1892 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1893 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1895 wassertl (0, "Left and right are in bit space");
1899 optype = operandType (IC_LEFT (ic));
1900 rtype = operandType (IC_RESULT (ic));
1902 /* if float then do float stuff */
1903 if (IS_FLOAT (optype))
1905 wassertl (0, "Tried to do a unary minus on a float");
1909 /* otherwise subtract from zero */
1910 size = AOP_SIZE (IC_LEFT (ic));
1912 if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
1914 /* Create a new asmop with value zero */
1915 asmop *azero = newAsmop (AOP_SIMPLELIT);
1916 azero->aopu.aop_simplelit = 0;
1918 _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
1926 const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1927 emit2 ("ld a,!zero");
1928 emit2 ("sbc a,%s", l);
1929 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1932 /* if any remaining bytes in the result */
1933 /* we just need to propagate the sign */
1934 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1939 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1943 /* release the aops */
1944 freeAsmop (IC_LEFT (ic), NULL, ic);
1945 freeAsmop (IC_RESULT (ic), NULL, ic);
1948 /*-----------------------------------------------------------------*/
1949 /* assignResultValue - */
1950 /*-----------------------------------------------------------------*/
1952 assignResultValue (operand * oper)
1954 int size = AOP_SIZE (oper);
1957 wassertl (size <= 4, "Got a result that is bigger than four bytes");
1958 topInA = requiresHL (AOP (oper));
1960 if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1962 /* We do it the hard way here. */
1964 aopPut (AOP (oper), _fReturn[0], 0);
1965 aopPut (AOP (oper), _fReturn[1], 1);
1967 aopPut (AOP (oper), _fReturn[0], 2);
1968 aopPut (AOP (oper), _fReturn[1], 3);
1974 aopPut (AOP (oper), _fReturn[size], size);
1980 _saveRegsForCall(iCode *ic, int sendSetSize)
1983 o Stack parameters are pushed before this function enters
1984 o DE and BC may be used in this function.
1985 o HL and DE may be used to return the result.
1986 o HL and DE may be used to send variables.
1987 o DE and BC may be used to store the result value.
1988 o HL may be used in computing the sent value of DE
1989 o The iPushes for other parameters occur before any addSets
1991 Logic: (to be run inside the first iPush or if none, before sending)
1992 o Compute if DE and/or BC are in use over the call
1993 o Compute if DE is used in the send set
1994 o Compute if DE and/or BC are used to hold the result value
1995 o If (DE is used, or in the send set) and is not used in the result, push.
1996 o If BC is used and is not in the result, push
1998 o If DE is used in the send set, fetch
1999 o If HL is used in the send set, fetch
2003 if (_G.saves.saved == FALSE) {
2004 bool deInUse, bcInUse;
2006 bool bcInRet = FALSE, deInRet = FALSE;
2009 rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2011 deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
2012 bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
2014 deSending = (sendSetSize > 1);
2016 emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
2018 if (bcInUse && bcInRet == FALSE) {
2020 _G.stack.pushedBC = TRUE;
2022 if (deInUse && deInRet == FALSE) {
2024 _G.stack.pushedDE = TRUE;
2027 _G.saves.saved = TRUE;
2030 /* Already saved. */
2034 /*-----------------------------------------------------------------*/
2035 /* genIpush - genrate code for pushing this gets a little complex */
2036 /*-----------------------------------------------------------------*/
2038 genIpush (iCode * ic)
2040 int size, offset = 0;
2043 /* if this is not a parm push : ie. it is spill push
2044 and spill push is always done on the local stack */
2047 wassertl(0, "Encountered an unsupported spill push.");
2051 if (_G.saves.saved == FALSE) {
2052 /* Caller saves, and this is the first iPush. */
2053 /* Scan ahead until we find the function that we are pushing parameters to.
2054 Count the number of addSets on the way to figure out what registers
2055 are used in the send set.
2058 iCode *walk = ic->next;
2061 if (walk->op == SEND) {
2064 else if (walk->op == CALL || walk->op == PCALL) {
2073 _saveRegsForCall(walk, nAddSets);
2076 /* Already saved by another iPush. */
2079 /* then do the push */
2080 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2082 size = AOP_SIZE (IC_LEFT (ic));
2084 if (isPair (AOP (IC_LEFT (ic))))
2086 _G.stack.pushed += 2;
2087 emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
2093 fetchHL (AOP (IC_LEFT (ic)));
2095 spillPair (PAIR_HL);
2096 _G.stack.pushed += 2;
2101 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2103 spillPair (PAIR_HL);
2104 _G.stack.pushed += 2;
2105 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
2107 spillPair (PAIR_HL);
2108 _G.stack.pushed += 2;
2114 if (AOP (IC_LEFT (ic))->type == AOP_IY)
2116 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
2118 emit2 ("ld a,(%s)", l);
2122 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
2123 emit2 ("ld a,%s", l);
2131 freeAsmop (IC_LEFT (ic), NULL, ic);
2134 /*-----------------------------------------------------------------*/
2135 /* genIpop - recover the registers: can happen only for spilling */
2136 /*-----------------------------------------------------------------*/
2138 genIpop (iCode * ic)
2143 /* if the temp was not pushed then */
2144 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2147 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2148 size = AOP_SIZE (IC_LEFT (ic));
2149 offset = (size - 1);
2150 if (isPair (AOP (IC_LEFT (ic))))
2152 emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
2160 spillPair (PAIR_HL);
2161 aopPut (AOP (IC_LEFT (ic)), "l", offset--);
2165 freeAsmop (IC_LEFT (ic), NULL, ic);
2168 /* This is quite unfortunate */
2170 setArea (int inHome)
2173 static int lastArea = 0;
2175 if (_G.in_home != inHome) {
2177 const char *sz = port->mem.code_name;
2178 port->mem.code_name = "HOME";
2179 emit2("!area", CODE_NAME);
2180 port->mem.code_name = sz;
2183 emit2("!area", CODE_NAME); */
2184 _G.in_home = inHome;
2195 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
2199 symbol *sym = OP_SYMBOL (op);
2201 if (sym->isspilt || sym->nRegs == 0)
2204 aopOp (op, ic, FALSE, FALSE);
2207 if (aop->type == AOP_REG)
2210 for (i = 0; i < aop->size; i++)
2212 if (pairId == PAIR_DE)
2214 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2215 if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2217 if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2220 else if (pairId == PAIR_BC)
2222 emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2223 if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2225 if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2235 freeAsmop (IC_LEFT (ic), NULL, ic);
2239 /** Emit the code for a call statement
2242 emitCall (iCode * ic, bool ispcall)
2244 sym_link *dtype = operandType (IC_LEFT (ic));
2246 bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
2248 /* if caller saves & we have not saved then */
2254 _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2256 /* if send set is not empty then assign */
2261 int nSend = elementsInSet(_G.sendSet);
2262 bool swapped = FALSE;
2264 int _z80_sendOrder[] = {
2269 /* Check if the parameters are swapped. If so route through hl instead. */
2270 wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
2272 sic = setFirstItem(_G.sendSet);
2273 sic = setNextItem(_G.sendSet);
2275 if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2276 /* The second send value is loaded from one the one that holds the first
2277 send, i.e. it is overwritten. */
2278 /* Cache the first in HL, and load the second from HL instead. */
2279 emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2280 emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2286 for (sic = setFirstItem (_G.sendSet); sic;
2287 sic = setNextItem (_G.sendSet))
2290 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2292 size = AOP_SIZE (IC_LEFT (sic));
2293 wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2294 wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2296 // PENDING: Mild hack
2297 if (swapped == TRUE && send == 1) {
2299 emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2302 emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2304 emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2307 fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2311 freeAsmop (IC_LEFT (sic), NULL, sic);
2318 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2320 werror (W_INDIR_BANKED);
2322 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2324 if (isLitWord (AOP (IC_LEFT (ic))))
2326 emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2330 symbol *rlbl = newiTempLabel (NULL);
2331 spillPair (PAIR_HL);
2332 emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2334 _G.stack.pushed += 2;
2336 fetchHL (AOP (IC_LEFT (ic)));
2338 emit2 ("!tlabeldef", (rlbl->key + 100));
2339 _G.stack.pushed -= 2;
2341 freeAsmop (IC_LEFT (ic), NULL, ic);
2345 char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2346 OP_SYMBOL (IC_LEFT (ic))->rname :
2347 OP_SYMBOL (IC_LEFT (ic))->name;
2348 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2350 emit2 ("call banked_call");
2351 emit2 ("!dws", name);
2352 emit2 ("!dw !bankimmeds", name);
2357 emit2 ("call %s", name);
2362 /* Mark the regsiters as restored. */
2363 _G.saves.saved = FALSE;
2365 /* if we need assign a result value */
2366 if ((IS_ITEMP (IC_RESULT (ic)) &&
2367 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2368 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2369 IS_TRUE_SYMOP (IC_RESULT (ic)))
2372 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2374 assignResultValue (IC_RESULT (ic));
2376 freeAsmop (IC_RESULT (ic), NULL, ic);
2379 /* adjust the stack for parameters if required */
2382 int i = ic->parmBytes;
2384 _G.stack.pushed -= i;
2387 emit2 ("!ldaspsp", i);
2394 emit2 ("ld hl,#%d", i);
2395 emit2 ("add hl,sp");
2413 if (_G.stack.pushedDE)
2415 bool dInUse = bitVectBitValue(rInUse, D_IDX);
2416 bool eInUse = bitVectBitValue(rInUse, E_IDX);
2418 if (dInUse && eInUse)
2434 wassertl (0, "Neither D or E were in use but it was pushed.");
2436 _G.stack.pushedDE = FALSE;
2439 if (_G.stack.pushedBC)
2441 bool bInUse = bitVectBitValue(rInUse, B_IDX);
2442 bool cInUse = bitVectBitValue(rInUse, C_IDX);
2444 // If both B and C are used in the return value, then we won't get
2446 if (bInUse && cInUse)
2462 wassertl (0, "Neither B or C were in use but it was pushed.");
2464 _G.stack.pushedBC = FALSE;
2468 /*-----------------------------------------------------------------*/
2469 /* genCall - generates a call statement */
2470 /*-----------------------------------------------------------------*/
2472 genCall (iCode * ic)
2474 emitCall (ic, FALSE);
2477 /*-----------------------------------------------------------------*/
2478 /* genPcall - generates a call by pointer statement */
2479 /*-----------------------------------------------------------------*/
2481 genPcall (iCode * ic)
2483 emitCall (ic, TRUE);
2486 /*-----------------------------------------------------------------*/
2487 /* resultRemat - result is rematerializable */
2488 /*-----------------------------------------------------------------*/
2490 resultRemat (iCode * ic)
2492 if (SKIP_IC (ic) || ic->op == IFX)
2495 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2497 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2498 if (sym->remat && !POINTER_SET (ic))
2505 extern set *publics;
2507 /*-----------------------------------------------------------------*/
2508 /* genFunction - generated code for function entry */
2509 /*-----------------------------------------------------------------*/
2511 genFunction (iCode * ic)
2513 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2517 bool bcInUse = FALSE;
2518 bool deInUse = FALSE;
2521 setArea (IFFUNC_NONBANKED (sym->type));
2523 /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2526 _G.receiveOffset = 0;
2528 /* Record the last function name for debugging. */
2529 _G.lastFunctionName = sym->rname;
2531 /* Create the function header */
2532 emit2 ("!functionheader", sym->name);
2533 /* PENDING: portability. */
2534 emit2 ("__%s_start:", sym->rname);
2535 emit2 ("!functionlabeldef", sym->rname);
2537 if (options.profile)
2539 emit2 ("!profileenter");
2542 ftype = operandType (IC_LEFT (ic));
2544 /* if critical function then turn interrupts off */
2545 if (IFFUNC_ISCRITICAL (ftype))
2548 /* if this is an interrupt service routine then save all potentially used registers. */
2549 if (IFFUNC_ISISR (sym->type))
2554 /* PENDING: callee-save etc */
2556 _G.stack.param_offset = 0;
2559 /* Detect which registers are used. */
2563 for (i = 0; i < sym->regsUsed->size; i++)
2565 if (bitVectBitValue (sym->regsUsed, i))
2579 /* Other systems use DE as a temporary. */
2590 _G.stack.param_offset += 2;
2593 _G.stack.pushedBC = bcInUse;
2598 _G.stack.param_offset += 2;
2601 _G.stack.pushedDE = deInUse;
2604 /* adjust the stack for the function */
2605 _G.stack.last = sym->stack;
2607 if (sym->stack && IS_GB && sym->stack > -INT8MIN)
2608 emit2 ("!enterxl", sym->stack);
2609 else if (sym->stack)
2610 emit2 ("!enterx", sym->stack);
2613 _G.stack.offset = sym->stack;
2616 /*-----------------------------------------------------------------*/
2617 /* genEndFunction - generates epilogue for functions */
2618 /*-----------------------------------------------------------------*/
2620 genEndFunction (iCode * ic)
2622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2624 if (IFFUNC_ISISR (sym->type))
2626 wassertl (0, "Tried to close an interrupt support function");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2633 /* PENDING: calleeSave */
2635 if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
2637 emit2 ("!leavexl", _G.stack.offset);
2639 else if (_G.stack.offset)
2641 emit2 ("!leavex", _G.stack.offset);
2649 if (_G.stack.pushedDE)
2652 _G.stack.pushedDE = FALSE;
2655 if (_G.stack.pushedDE)
2658 _G.stack.pushedDE = FALSE;
2662 if (options.profile)
2664 emit2 ("!profileexit");
2668 /* Both baned and non-banked just ret */
2671 /* PENDING: portability. */
2672 emit2 ("__%s_end:", sym->rname);
2674 _G.flushStatics = 1;
2675 _G.stack.pushed = 0;
2676 _G.stack.offset = 0;
2679 /*-----------------------------------------------------------------*/
2680 /* genRet - generate code for return statement */
2681 /*-----------------------------------------------------------------*/
2686 /* Errk. This is a hack until I can figure out how
2687 to cause dehl to spill on a call */
2688 int size, offset = 0;
2690 /* if we have no return value then
2691 just generate the "ret" */
2695 /* we have something to return then
2696 move the return value into place */
2697 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2698 size = AOP_SIZE (IC_LEFT (ic));
2700 if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2704 emit2 ("ld de,%s", l);
2708 emit2 ("ld hl,%s", l);
2713 if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2715 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2716 fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2722 l = aopGet (AOP (IC_LEFT (ic)), offset,
2724 if (strcmp (_fReturn[offset], l))
2725 emit2 ("ld %s,%s", _fReturn[offset++], l);
2729 freeAsmop (IC_LEFT (ic), NULL, ic);
2732 /* generate a jump to the return label
2733 if the next is not the return statement */
2734 if (!(ic->next && ic->next->op == LABEL &&
2735 IC_LABEL (ic->next) == returnLabel))
2737 emit2 ("jp !tlabel", returnLabel->key + 100);
2740 /*-----------------------------------------------------------------*/
2741 /* genLabel - generates a label */
2742 /*-----------------------------------------------------------------*/
2744 genLabel (iCode * ic)
2746 /* special case never generate */
2747 if (IC_LABEL (ic) == entryLabel)
2750 emitLabel (IC_LABEL (ic)->key + 100);
2753 /*-----------------------------------------------------------------*/
2754 /* genGoto - generates a ljmp */
2755 /*-----------------------------------------------------------------*/
2757 genGoto (iCode * ic)
2759 emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2762 /*-----------------------------------------------------------------*/
2763 /* genPlusIncr :- does addition with increment if possible */
2764 /*-----------------------------------------------------------------*/
2766 genPlusIncr (iCode * ic)
2768 unsigned int icount;
2769 unsigned int size = getDataSize (IC_RESULT (ic));
2770 PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2772 /* will try to generate an increment */
2773 /* if the right side is not a literal
2775 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2778 emitDebug ("; genPlusIncr");
2780 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2782 /* If result is a pair */
2783 if (resultId != PAIR_INVALID)
2785 if (isLitWord (AOP (IC_LEFT (ic))))
2787 fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2790 if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2792 fetchPair (resultId, AOP (IC_RIGHT (ic)));
2793 emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
2799 if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2803 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2804 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2808 emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
2813 /* if the literal value of the right hand side
2814 is greater than 4 then it is not worth it */
2818 /* if increment 16 bits in register */
2819 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2825 symbol *tlbl = NULL;
2826 tlbl = newiTempLabel (NULL);
2829 emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2832 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2835 emitLabel (tlbl->key + 100);
2839 /* if the sizes are greater than 1 then we cannot */
2840 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2841 AOP_SIZE (IC_LEFT (ic)) > 1)
2844 /* we can if the aops of the left & result match or
2845 if they are in registers and the registers are the
2847 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2851 emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2859 /*-----------------------------------------------------------------*/
2860 /* outBitAcc - output a bit in acc */
2861 /*-----------------------------------------------------------------*/
2863 outBitAcc (operand * result)
2865 symbol *tlbl = newiTempLabel (NULL);
2866 /* if the result is a bit */
2867 if (AOP_TYPE (result) == AOP_CRY)
2869 wassertl (0, "Tried to write A into a bit");
2873 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2874 emit2 ("ld a,!one");
2875 emitLabel (tlbl->key + 100);
2881 couldDestroyCarry (asmop *aop)
2885 if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
2894 shiftIntoPair (int idx, asmop *aop)
2896 PAIR_ID id = PAIR_INVALID;
2898 wassertl (IS_Z80, "Only implemented for the Z80");
2899 // wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
2911 wassertl (0, "Internal error - hit default case");
2914 emitDebug ("; Shift into pair idx %u", idx);
2918 setupPair (PAIR_HL, aop, 0);
2922 setupPair (PAIR_IY, aop, 0);
2924 emit2 ("pop %s", _pairs[id].name);
2927 aop->type = AOP_PAIRPTR;
2928 aop->aopu.aop_pairId = id;
2929 _G.pairs[id].offset = 0;
2930 _G.pairs[id].last_type = aop->type;
2934 setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
2936 wassert (left && right);
2940 if (couldDestroyCarry (right) && couldDestroyCarry (result))
2942 shiftIntoPair (0, right);
2943 shiftIntoPair (1, result);
2945 else if (couldDestroyCarry (right))
2947 shiftIntoPair (0, right);
2949 else if (couldDestroyCarry (result))
2951 shiftIntoPair (0, result);
2960 /*-----------------------------------------------------------------*/
2961 /* genPlus - generates code for addition */
2962 /*-----------------------------------------------------------------*/
2964 genPlus (iCode * ic)
2966 int size, offset = 0;
2968 /* special cases :- */
2970 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2971 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2972 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2974 /* Swap the left and right operands if:
2976 if literal, literal on the right or
2977 if left requires ACC or right is already
2980 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2981 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2982 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2984 operand *t = IC_RIGHT (ic);
2985 IC_RIGHT (ic) = IC_LEFT (ic);
2989 /* if both left & right are in bit
2991 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2992 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2995 wassertl (0, "Tried to add two bits");
2998 /* if left in bit space & right literal */
2999 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3000 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3002 /* Can happen I guess */
3003 wassertl (0, "Tried to add a bit to a literal");
3006 /* if I can do an increment instead
3007 of add then GOOD for ME */
3008 if (genPlusIncr (ic) == TRUE)
3011 emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
3013 size = getDataSize (IC_RESULT (ic));
3015 /* Special case when left and right are constant */
3016 if (isPair (AOP (IC_RESULT (ic))))
3019 left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
3020 right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
3022 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
3028 sprintf (buffer, "#(%s + %s)", left, right);
3029 emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
3034 if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
3036 /* Fetch into HL then do the add */
3037 spillPair (PAIR_HL);
3038 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3039 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3043 if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
3045 fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3046 emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3048 commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3053 ld hl,sp+n trashes C so we cant afford to do it during an
3054 add with stack based varibles. Worst case is:
3067 So you cant afford to load up hl if either left, right, or result
3068 is on the stack (*sigh*) The alt is:
3076 Combinations in here are:
3077 * If left or right are in bc then the loss is small - trap later
3078 * If the result is in bc then the loss is also small
3082 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3083 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3084 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3086 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3087 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3088 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3089 AOP_SIZE (IC_RIGHT (ic)) <= 2))
3091 if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
3093 /* Swap left and right */
3094 operand *t = IC_RIGHT (ic);
3095 IC_RIGHT (ic) = IC_LEFT (ic);
3098 if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
3100 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3101 emit2 ("add hl,bc");
3105 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3106 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3107 emit2 ("add hl,de");
3109 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3115 /* Be paranoid on the GB with 4 byte variables due to how C
3116 can be trashed by lda hl,n(sp).
3118 _gbz80_emitAddSubLong (ic, TRUE);
3123 setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3127 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3129 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3132 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3135 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3139 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3142 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3145 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3147 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3151 freeAsmop (IC_LEFT (ic), NULL, ic);
3152 freeAsmop (IC_RIGHT (ic), NULL, ic);
3153 freeAsmop (IC_RESULT (ic), NULL, ic);
3157 /*-----------------------------------------------------------------*/
3158 /* genMinusDec :- does subtraction with deccrement if possible */
3159 /*-----------------------------------------------------------------*/
3161 genMinusDec (iCode * ic)
3163 unsigned int icount;
3164 unsigned int size = getDataSize (IC_RESULT (ic));
3166 /* will try to generate an increment */
3167 /* if the right side is not a literal we cannot */
3168 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3171 /* if the literal value of the right hand side
3172 is greater than 4 then it is not worth it */
3173 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
3176 size = getDataSize (IC_RESULT (ic));
3178 /* if decrement 16 bits in register */
3179 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3180 (size > 1) && isPair (AOP (IC_RESULT (ic))))
3183 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3187 /* If result is a pair */
3188 if (isPair (AOP (IC_RESULT (ic))))
3190 movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
3191 movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
3193 emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3197 /* if increment 16 bits in register */
3198 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3202 fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
3205 emit2 ("dec %s", _getTempPairName());
3208 commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
3214 /* if the sizes are greater than 1 then we cannot */
3215 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3216 AOP_SIZE (IC_LEFT (ic)) > 1)
3219 /* we can if the aops of the left & result match or if they are in
3220 registers and the registers are the same */
3221 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3224 emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
3231 /*-----------------------------------------------------------------*/
3232 /* genMinus - generates code for subtraction */
3233 /*-----------------------------------------------------------------*/
3235 genMinus (iCode * ic)
3237 int size, offset = 0;
3238 unsigned long lit = 0L;
3240 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3241 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3242 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3244 /* special cases :- */
3245 /* if both left & right are in bit space */
3246 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3247 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3249 wassertl (0, "Tried to subtract two bits");
3253 /* if I can do an decrement instead of subtract then GOOD for ME */
3254 if (genMinusDec (ic) == TRUE)
3257 size = getDataSize (IC_RESULT (ic));
3259 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3264 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3268 /* Same logic as genPlus */
3271 if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3272 AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3273 AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3275 if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3276 AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3277 (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3278 AOP_SIZE (IC_RIGHT (ic)) <= 2))
3280 PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3281 PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3283 if (left == PAIR_INVALID && right == PAIR_INVALID)
3288 else if (right == PAIR_INVALID)
3290 else if (left == PAIR_INVALID)
3293 fetchPair (left, AOP (IC_LEFT (ic)));
3294 /* Order is important. Right may be HL */
3295 fetchPair (right, AOP (IC_RIGHT (ic)));
3297 emit2 ("ld a,%s", _pairs[left].l);
3298 emit2 ("sub a,%s", _pairs[right].l);
3300 emit2 ("ld a,%s", _pairs[left].h);
3301 emit2 ("sbc a,%s", _pairs[right].h);
3303 aopPut (AOP (IC_RESULT (ic)), "a", 1);
3304 aopPut (AOP (IC_RESULT (ic)), "e", 0);
3310 /* Be paranoid on the GB with 4 byte variables due to how C
3311 can be trashed by lda hl,n(sp).
3313 _gbz80_emitAddSubLong (ic, FALSE);
3318 setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3320 /* if literal, add a,#-lit, else normal subb */
3323 _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3324 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3328 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3331 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3335 /* first add without previous c */
3337 emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
3339 emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3341 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3344 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3345 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3346 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3348 wassertl (0, "Tried to subtract on a long pointer");
3352 freeAsmop (IC_LEFT (ic), NULL, ic);
3353 freeAsmop (IC_RIGHT (ic), NULL, ic);
3354 freeAsmop (IC_RESULT (ic), NULL, ic);
3357 /*-----------------------------------------------------------------*/
3358 /* genMult - generates code for multiplication */
3359 /*-----------------------------------------------------------------*/
3361 genMult (iCode * ic)
3365 /* If true then the final operation should be a subtract */
3366 bool active = FALSE;
3368 /* Shouldn't occur - all done through function calls */
3369 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3370 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3371 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3373 if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
3374 AOP_SIZE (IC_RIGHT (ic)) > 2 ||
3375 AOP_SIZE (IC_RESULT (ic)) > 2)
3377 wassertl (0, "Multiplication is handled through support function calls");
3380 /* Swap left and right such that right is a literal */
3381 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
3383 operand *t = IC_RIGHT (ic);
3384 IC_RIGHT (ic) = IC_LEFT (ic);
3388 wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
3390 val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
3391 // wassertl (val > 0, "Multiply must be positive");
3392 wassertl (val != 1, "Can't multiply by 1");
3398 if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
3400 emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
3408 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3413 /* Fully unroled version of mul.s. Not the most efficient.
3415 for (count = 0; count < 16; count++)
3417 if (count != 0 && active)
3419 emit2 ("add hl,hl");
3423 if (active == FALSE)
3430 emit2 ("add hl,de");
3444 commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3446 freeAsmop (IC_LEFT (ic), NULL, ic);
3447 freeAsmop (IC_RIGHT (ic), NULL, ic);
3448 freeAsmop (IC_RESULT (ic), NULL, ic);
3451 /*-----------------------------------------------------------------*/
3452 /* genDiv - generates code for division */
3453 /*-----------------------------------------------------------------*/
3457 /* Shouldn't occur - all done through function calls */
3458 wassertl (0, "Division is handled through support function calls");
3461 /*-----------------------------------------------------------------*/
3462 /* genMod - generates code for division */
3463 /*-----------------------------------------------------------------*/
3467 /* Shouldn't occur - all done through function calls */
3471 /*-----------------------------------------------------------------*/
3472 /* genIfxJump :- will create a jump depending on the ifx */
3473 /*-----------------------------------------------------------------*/
3475 genIfxJump (iCode * ic, char *jval)
3480 /* if true label then we jump if condition
3484 jlbl = IC_TRUE (ic);
3485 if (!strcmp (jval, "a"))
3489 else if (!strcmp (jval, "c"))
3493 else if (!strcmp (jval, "nc"))
3499 /* The buffer contains the bit on A that we should test */
3505 /* false label is present */
3506 jlbl = IC_FALSE (ic);
3507 if (!strcmp (jval, "a"))
3511 else if (!strcmp (jval, "c"))
3515 else if (!strcmp (jval, "nc"))
3521 /* The buffer contains the bit on A that we should test */
3525 /* Z80 can do a conditional long jump */
3526 if (!strcmp (jval, "a"))
3530 else if (!strcmp (jval, "c"))
3533 else if (!strcmp (jval, "nc"))
3538 emit2 ("bit %s,a", jval);
3540 emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
3542 /* mark the icode as generated */
3548 _getPairIdName (PAIR_ID id)
3550 return _pairs[id].name;
3554 /** Generic compare for > or <
3557 genCmp (operand * left, operand * right,
3558 operand * result, iCode * ifx, int sign)
3560 int size, offset = 0;
3561 unsigned long lit = 0L;
3562 bool swap_sense = FALSE;
3564 /* if left & right are bit variables */
3565 if (AOP_TYPE (left) == AOP_CRY &&
3566 AOP_TYPE (right) == AOP_CRY)
3568 /* Cant happen on the Z80 */
3569 wassertl (0, "Tried to compare two bits");
3573 /* subtract right from left if at the
3574 end the carry flag is set then we know that
3575 left is greater than right */
3576 size = max (AOP_SIZE (left), AOP_SIZE (right));
3578 /* if unsigned char cmp with lit, just compare */
3580 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3582 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3585 emit2 ("xor a,!immedbyte", 0x80);
3586 emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3589 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3591 else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
3593 // On the Gameboy we can't afford to adjust HL as it may trash the carry.
3594 // Pull left into DE and right into HL
3595 aopGet (AOP(left), LSB, FALSE);
3598 aopGet (AOP(right), LSB, FALSE);
3602 if (size == 0 && sign)
3604 // Highest byte when signed needs the bits flipped
3607 emit2 ("ld a,(de)");
3608 emit2 ("xor #0x80");
3610 emit2 ("ld a,(hl)");
3611 emit2 ("xor #0x80");
3615 emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
3619 emit2 ("ld a,(de)");
3620 emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
3630 spillPair (PAIR_HL);
3632 else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
3634 setupPair (PAIR_HL, AOP (left), 0);
3635 aopGet (AOP(right), LSB, FALSE);
3639 if (size == 0 && sign)
3641 // Highest byte when signed needs the bits flipped
3644 emit2 ("ld a,(hl)");
3645 emit2 ("xor #0x80");
3647 emit2 ("ld a,%d(iy)", offset);
3648 emit2 ("xor #0x80");
3652 emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
3656 emit2 ("ld a,(hl)");
3657 emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
3666 spillPair (PAIR_HL);
3667 spillPair (PAIR_IY);
3671 if (AOP_TYPE (right) == AOP_LIT)
3673 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3674 /* optimize if(x < 0) or if(x >= 0) */
3679 /* No sign so it's always false */
3684 /* Just load in the top most bit */
3685 _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3686 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3688 genIfxJump (ifx, "7");
3700 /* First setup h and l contaning the top most bytes XORed */
3701 bool fDidXor = FALSE;
3702 if (AOP_TYPE (left) == AOP_LIT)
3704 unsigned long lit = (unsigned long)
3705 floatFromVal (AOP (left)->aopu.aop_lit);
3706 emit2 ("ld %s,!immedbyte", _fTmp[0],
3707 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3711 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
3712 emit2 ("xor a,!immedbyte", 0x80);
3713 emit2 ("ld %s,a", _fTmp[0]);
3716 if (AOP_TYPE (right) == AOP_LIT)
3718 unsigned long lit = (unsigned long)
3719 floatFromVal (AOP (right)->aopu.aop_lit);
3720 emit2 ("ld %s,!immedbyte", _fTmp[1],
3721 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3725 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
3726 emit2 ("xor a,!immedbyte", 0x80);
3727 emit2 ("ld %s,a", _fTmp[1]);
3733 /* Do a long subtract */
3736 _moveA (aopGet (AOP (left), offset, FALSE));
3738 if (sign && size == 0)
3740 emit2 ("ld a,%s", _fTmp[0]);
3741 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
3745 /* Subtract through, propagating the carry */
3746 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
3754 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3756 outBitCLong (result, swap_sense);
3760 /* if the result is used in the next
3761 ifx conditional branch then generate
3762 code a little differently */
3764 genIfxJump (ifx, swap_sense ? "nc" : "c");
3766 outBitCLong (result, swap_sense);
3767 /* leave the result in acc */
3771 /*-----------------------------------------------------------------*/
3772 /* genCmpGt :- greater than comparison */
3773 /*-----------------------------------------------------------------*/
3775 genCmpGt (iCode * ic, iCode * ifx)
3777 operand *left, *right, *result;
3778 sym_link *letype, *retype;
3781 left = IC_LEFT (ic);
3782 right = IC_RIGHT (ic);
3783 result = IC_RESULT (ic);
3785 letype = getSpec (operandType (left));
3786 retype = getSpec (operandType (right));
3787 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3788 /* assign the amsops */
3789 aopOp (left, ic, FALSE, FALSE);
3790 aopOp (right, ic, FALSE, FALSE);
3791 aopOp (result, ic, TRUE, FALSE);
3793 genCmp (right, left, result, ifx, sign);
3795 freeAsmop (left, NULL, ic);
3796 freeAsmop (right, NULL, ic);
3797 freeAsmop (result, NULL, ic);
3800 /*-----------------------------------------------------------------*/
3801 /* genCmpLt - less than comparisons */
3802 /*-----------------------------------------------------------------*/
3804 genCmpLt (iCode * ic, iCode * ifx)
3806 operand *left, *right, *result;
3807 sym_link *letype, *retype;
3810 left = IC_LEFT (ic);
3811 right = IC_RIGHT (ic);
3812 result = IC_RESULT (ic);
3814 letype = getSpec (operandType (left));
3815 retype = getSpec (operandType (right));
3816 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3818 /* assign the amsops */
3819 aopOp (left, ic, FALSE, FALSE);
3820 aopOp (right, ic, FALSE, FALSE);
3821 aopOp (result, ic, TRUE, FALSE);
3823 genCmp (left, right, result, ifx, sign);
3825 freeAsmop (left, NULL, ic);
3826 freeAsmop (right, NULL, ic);
3827 freeAsmop (result, NULL, ic);
3830 /*-----------------------------------------------------------------*/
3831 /* gencjneshort - compare and jump if not equal */
3832 /*-----------------------------------------------------------------*/
3834 gencjneshort (operand * left, operand * right, symbol * lbl)
3836 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3838 unsigned long lit = 0L;
3840 /* Swap the left and right if it makes the computation easier */
3841 if (AOP_TYPE (left) == AOP_LIT)
3848 if (AOP_TYPE (right) == AOP_LIT)
3849 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3851 /* if the right side is a literal then anything goes */
3852 if (AOP_TYPE (right) == AOP_LIT &&
3853 AOP_TYPE (left) != AOP_DIR)
3857 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3862 emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
3869 emit2 ("jp nz,!tlabel", lbl->key + 100);
3875 emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
3876 if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3879 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
3880 emit2 ("jp nz,!tlabel", lbl->key + 100);
3885 /* if the right side is in a register or in direct space or
3886 if the left is a pointer register & right is not */
3887 else if (AOP_TYPE (right) == AOP_REG ||
3888 AOP_TYPE (right) == AOP_DIR ||
3889 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3893 _moveA (aopGet (AOP (left), offset, FALSE));
3894 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3895 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3897 emit2 ("jp nz,!tlabel", lbl->key + 100);
3900 emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
3901 emit2 ("jp nz,!tlabel", lbl->key + 100);
3908 /* right is a pointer reg need both a & b */
3909 /* PENDING: is this required? */
3912 _moveA (aopGet (AOP (right), offset, FALSE));
3913 emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
3914 emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3920 /*-----------------------------------------------------------------*/
3921 /* gencjne - compare and jump if not equal */
3922 /*-----------------------------------------------------------------*/
3924 gencjne (operand * left, operand * right, symbol * lbl)
3926 symbol *tlbl = newiTempLabel (NULL);
3928 gencjneshort (left, right, lbl);
3931 emit2 ("ld a,!one");
3932 emit2 ("!shortjp !tlabel", tlbl->key + 100);
3933 emitLabel (lbl->key + 100);
3935 emitLabel (tlbl->key + 100);
3938 /*-----------------------------------------------------------------*/
3939 /* genCmpEq - generates code for equal to */
3940 /*-----------------------------------------------------------------*/
3942 genCmpEq (iCode * ic, iCode * ifx)
3944 operand *left, *right, *result;
3946 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3947 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3948 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3950 emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3952 /* Swap operands if it makes the operation easier. ie if:
3953 1. Left is a literal.
3955 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3957 operand *t = IC_RIGHT (ic);
3958 IC_RIGHT (ic) = IC_LEFT (ic);
3962 if (ifx && !AOP_SIZE (result))
3965 /* if they are both bit variables */
3966 if (AOP_TYPE (left) == AOP_CRY &&
3967 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3969 wassertl (0, "Tried to compare two bits");
3973 tlbl = newiTempLabel (NULL);
3974 gencjneshort (left, right, tlbl);
3977 emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3978 emitLabel (tlbl->key + 100);
3982 /* PENDING: do this better */
3983 symbol *lbl = newiTempLabel (NULL);
3984 emit2 ("!shortjp !tlabel", lbl->key + 100);
3985 emitLabel (tlbl->key + 100);
3986 emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3987 emitLabel (lbl->key + 100);
3990 /* mark the icode as generated */
3995 /* if they are both bit variables */
3996 if (AOP_TYPE (left) == AOP_CRY &&
3997 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3999 wassertl (0, "Tried to compare a bit to either a literal or another bit");
4003 gencjne (left, right, newiTempLabel (NULL));
4004 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4010 genIfxJump (ifx, "a");
4013 /* if the result is used in an arithmetic operation
4014 then put the result in place */
4015 if (AOP_TYPE (result) != AOP_CRY)
4019 /* leave the result in acc */
4023 freeAsmop (left, NULL, ic);
4024 freeAsmop (right, NULL, ic);
4025 freeAsmop (result, NULL, ic);
4028 /*-----------------------------------------------------------------*/
4029 /* ifxForOp - returns the icode containing the ifx for operand */
4030 /*-----------------------------------------------------------------*/
4032 ifxForOp (operand * op, iCode * ic)
4034 /* if true symbol then needs to be assigned */
4035 if (IS_TRUE_SYMOP (op))
4038 /* if this has register type condition and
4039 the next instruction is ifx with the same operand
4040 and live to of the operand is upto the ifx only then */
4042 ic->next->op == IFX &&
4043 IC_COND (ic->next)->key == op->key &&
4044 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4050 /*-----------------------------------------------------------------*/
4051 /* genAndOp - for && operation */
4052 /*-----------------------------------------------------------------*/
4054 genAndOp (iCode * ic)
4056 operand *left, *right, *result;
4059 /* note here that && operations that are in an if statement are
4060 taken away by backPatchLabels only those used in arthmetic
4061 operations remain */
4062 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4063 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4064 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4066 /* if both are bit variables */
4067 if (AOP_TYPE (left) == AOP_CRY &&
4068 AOP_TYPE (right) == AOP_CRY)
4070 wassertl (0, "Tried to and two bits");
4074 tlbl = newiTempLabel (NULL);
4076 emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
4078 emitLabel (tlbl->key + 100);
4082 freeAsmop (left, NULL, ic);
4083 freeAsmop (right, NULL, ic);
4084 freeAsmop (result, NULL, ic);
4087 /*-----------------------------------------------------------------*/
4088 /* genOrOp - for || operation */
4089 /*-----------------------------------------------------------------*/
4091 genOrOp (iCode * ic)
4093 operand *left, *right, *result;
4096 /* note here that || operations that are in an
4097 if statement are taken away by backPatchLabels
4098 only those used in arthmetic operations remain */
4099 aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4100 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4101 aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4103 /* if both are bit variables */
4104 if (AOP_TYPE (left) == AOP_CRY &&
4105 AOP_TYPE (right) == AOP_CRY)
4107 wassertl (0, "Tried to OR two bits");
4111 tlbl = newiTempLabel (NULL);
4113 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4115 emitLabel (tlbl->key + 100);
4119 freeAsmop (left, NULL, ic);
4120 freeAsmop (right, NULL, ic);
4121 freeAsmop (result, NULL, ic);
4124 /*-----------------------------------------------------------------*/
4125 /* isLiteralBit - test if lit == 2^n */
4126 /*-----------------------------------------------------------------*/
4128 isLiteralBit (unsigned long lit)
4130 unsigned long pw[32] =
4131 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4132 0x100L, 0x200L, 0x400L, 0x800L,
4133 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4134 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4135 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4136 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4137 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4140 for (idx = 0; idx < 32; idx++)
4146 /*-----------------------------------------------------------------*/
4147 /* jmpTrueOrFalse - */
4148 /*-----------------------------------------------------------------*/
4150 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4152 // ugly but optimized by peephole
4155 symbol *nlbl = newiTempLabel (NULL);
4156 emit2 ("jp !tlabel", nlbl->key + 100);
4157 emitLabel (tlbl->key + 100);
4158 emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
4159 emitLabel (nlbl->key + 100);
4163 emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
4164 emitLabel (tlbl->key + 100);
4169 /*-----------------------------------------------------------------*/
4170 /* genAnd - code for and */
4171 /*-----------------------------------------------------------------*/
4173 genAnd (iCode * ic, iCode * ifx)
4175 operand *left, *right, *result;
4176 int size, offset = 0;
4177 unsigned long lit = 0L;
4180 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4181 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4182 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4184 /* if left is a literal & right is not then exchange them */
4185 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4186 AOP_NEEDSACC (left))
4188 operand *tmp = right;
4193 /* if result = right then exchange them */
4194 if (sameRegs (AOP (result), AOP (right)))
4196 operand *tmp = right;
4201 /* if right is bit then exchange them */
4202 if (AOP_TYPE (right) == AOP_CRY &&
4203 AOP_TYPE (left) != AOP_CRY)
4205 operand *tmp = right;
4209 if (AOP_TYPE (right) == AOP_LIT)
4210 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4212 size = AOP_SIZE (result);
4214 if (AOP_TYPE (left) == AOP_CRY)
4216 wassertl (0, "Tried to perform an AND with a bit as an operand");
4220 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4221 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4222 if ((AOP_TYPE (right) == AOP_LIT) &&
4223 (AOP_TYPE (result) == AOP_CRY) &&
4224 (AOP_TYPE (left) != AOP_CRY))
4226 symbol *tlbl = newiTempLabel (NULL);
4227 int sizel = AOP_SIZE (left);
4230 /* PENDING: Test case for this. */
4235 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4237 _moveA (aopGet (AOP (left), offset, FALSE));
4238 if (bytelit != 0x0FFL)
4240 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
4247 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4251 // bit = left & literal
4255 emit2 ("!tlabeldef", tlbl->key + 100);
4257 // if(left & literal)
4262 jmpTrueOrFalse (ifx, tlbl);
4270 /* if left is same as result */
4271 if (sameRegs (AOP (result), AOP (left)))
4273 for (; size--; offset++)
4275 if (AOP_TYPE (right) == AOP_LIT)
4277 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4282 aopPut (AOP (result), "!zero", offset);
4285 _moveA (aopGet (AOP (left), offset, FALSE));
4287 aopGet (AOP (right), offset, FALSE));
4288 aopPut (AOP (left), "a", offset);
4295 if (AOP_TYPE (left) == AOP_ACC)
4297 wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
4301 _moveA (aopGet (AOP (left), offset, FALSE));
4303 aopGet (AOP (right), offset, FALSE));
4304 aopPut (AOP (left), "a", offset);
4311 // left & result in different registers
4312 if (AOP_TYPE (result) == AOP_CRY)
4314 wassertl (0, "Tried to AND where the result is in carry");
4318 for (; (size--); offset++)
4321 // result = left & right
4322 if (AOP_TYPE (right) == AOP_LIT)
4324 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4326 aopPut (AOP (result),
4327 aopGet (AOP (left), offset, FALSE),
4331 else if (bytelit == 0)
4333 aopPut (AOP (result), "!zero", offset);
4337 // faster than result <- left, anl result,right
4338 // and better if result is SFR
4339 if (AOP_TYPE (left) == AOP_ACC)
4340 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
4343 _moveA (aopGet (AOP (left), offset, FALSE));
4345 aopGet (AOP (right), offset, FALSE));
4347 aopPut (AOP (result), "a", offset);
4354 freeAsmop (left, NULL, ic);
4355 freeAsmop (right, NULL, ic);
4356 freeAsmop (result, NULL, ic);
4359 /*-----------------------------------------------------------------*/
4360 /* genOr - code for or */
4361 /*-----------------------------------------------------------------*/
4363 genOr (iCode * ic, iCode * ifx)
4365 operand *left, *right, *result;
4366 int size, offset = 0;
4367 unsigned long lit = 0L;
4370 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4371 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4372 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4374 /* if left is a literal & right is not then exchange them */
4375 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4376 AOP_NEEDSACC (left))
4378 operand *tmp = right;
4383 /* if result = right then exchange them */
4384 if (sameRegs (AOP (result), AOP (right)))
4386 operand *tmp = right;
4391 /* if right is bit then exchange them */
4392 if (AOP_TYPE (right) == AOP_CRY &&
4393 AOP_TYPE (left) != AOP_CRY)
4395 operand *tmp = right;
4399 if (AOP_TYPE (right) == AOP_LIT)
4400 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4402 size = AOP_SIZE (result);
4404 if (AOP_TYPE (left) == AOP_CRY)
4406 wassertl (0, "Tried to OR where left is a bit");
4410 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4411 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4412 if ((AOP_TYPE (right) == AOP_LIT) &&
4413 (AOP_TYPE (result) == AOP_CRY) &&
4414 (AOP_TYPE (left) != AOP_CRY))
4416 symbol *tlbl = newiTempLabel (NULL);
4417 int sizel = AOP_SIZE (left);
4421 wassertl (0, "Result is assigned to a bit");
4423 /* PENDING: Modeled after the AND code which is inefficent. */
4426 bytelit = (lit >> (offset * 8)) & 0x0FFL;
4428 _moveA (aopGet (AOP (left), offset, FALSE));
4429 /* OR with any literal is the same as OR with itself. */
4431 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4437 jmpTrueOrFalse (ifx, tlbl);
4442 /* if left is same as result */
4443 if (sameRegs (AOP (result), AOP (left)))
4445 for (; size--; offset++)
4447 if (AOP_TYPE (right) == AOP_LIT)
4449 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4453 _moveA (aopGet (AOP (left), offset, FALSE));
4455 aopGet (AOP (right), offset, FALSE));
4456 aopPut (AOP (result), "a", offset);
4461 if (AOP_TYPE (left) == AOP_ACC)
4462 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4465 _moveA (aopGet (AOP (left), offset, FALSE));
4467 aopGet (AOP (right), offset, FALSE));
4468 aopPut (AOP (result), "a", offset);
4475 // left & result in different registers
4476 if (AOP_TYPE (result) == AOP_CRY)
4478 wassertl (0, "Result of OR is in a bit");
4481 for (; (size--); offset++)
4484 // result = left & right
4485 if (AOP_TYPE (right) == AOP_LIT)
4487 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4489 aopPut (AOP (result),
4490 aopGet (AOP (left), offset, FALSE),
4495 // faster than result <- left, anl result,right
4496 // and better if result is SFR
4497 if (AOP_TYPE (left) == AOP_ACC)
4498 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
4501 _moveA (aopGet (AOP (left), offset, FALSE));
4503 aopGet (AOP (right), offset, FALSE));
4505 aopPut (AOP (result), "a", offset);
4506 /* PENDING: something weird is going on here. Add exception. */
4507 if (AOP_TYPE (result) == AOP_ACC)
4513 freeAsmop (left, NULL, ic);
4514 freeAsmop (right, NULL, ic);
4515 freeAsmop (result, NULL, ic);
4518 /*-----------------------------------------------------------------*/
4519 /* genXor - code for xclusive or */
4520 /*-----------------------------------------------------------------*/
4522 genXor (iCode * ic, iCode * ifx)
4524 operand *left, *right, *result;
4525 int size, offset = 0;
4526 unsigned long lit = 0L;
4528 aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4529 aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4530 aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4532 /* if left is a literal & right is not then exchange them */
4533 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4534 AOP_NEEDSACC (left))
4536 operand *tmp = right;
4541 /* if result = right then exchange them */
4542 if (sameRegs (AOP (result), AOP (right)))
4544 operand *tmp = right;
4549 /* if right is bit then exchange them */
4550 if (AOP_TYPE (right) == AOP_CRY &&
4551 AOP_TYPE (left) != AOP_CRY)
4553 operand *tmp = right;
4557 if (AOP_TYPE (right) == AOP_LIT)
4558 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4560 size = AOP_SIZE (result);
4562 if (AOP_TYPE (left) == AOP_CRY)
4564 wassertl (0, "Tried to XOR a bit");
4568 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4569 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4570 if ((AOP_TYPE (right) == AOP_LIT) &&
4571 (AOP_TYPE (result) == AOP_CRY) &&
4572 (AOP_TYPE (left) != AOP_CRY))
4574 symbol *tlbl = newiTempLabel (NULL);
4575 int sizel = AOP_SIZE (left);
4579 /* PENDING: Test case for this. */
4580 wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
4584 _moveA (aopGet (AOP (left), offset, FALSE));
4585 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4586 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4591 jmpTrueOrFalse (ifx, tlbl);
4595 wassertl (0, "Result of XOR was destined for a bit");
4600 /* if left is same as result */
4601 if (sameRegs (AOP (result), AOP (left)))
4603 for (; size--; offset++)
4605 if (AOP_TYPE (right) == AOP_LIT)
4607 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4611 _moveA (aopGet (AOP (right), offset, FALSE));
4613 aopGet (AOP (left), offset, FALSE));
4614 aopPut (AOP (result), "a", offset);
4619 if (AOP_TYPE (left) == AOP_ACC)
4621 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4625 _moveA (aopGet (AOP (right), offset, FALSE));
4627 aopGet (AOP (left), offset, FALSE));
4628 aopPut (AOP (result), "a", 0);
4635 // left & result in different registers
4636 if (AOP_TYPE (result) == AOP_CRY)
4638 wassertl (0, "Result of XOR is in a bit");
4641 for (; (size--); offset++)
4644 // result = left & right
4645 if (AOP_TYPE (right) == AOP_LIT)
4647 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4649 aopPut (AOP (result),
4650 aopGet (AOP (left), offset, FALSE),
4655 // faster than result <- left, anl result,right
4656 // and better if result is SFR
4657 if (AOP_TYPE (left) == AOP_ACC)
4659 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
4663 _moveA (aopGet (AOP (right), offset, FALSE));
4665 aopGet (AOP (left), offset, FALSE));
4667 aopPut (AOP (result), "a", offset);
4672 freeAsmop (left, NULL, ic);
4673 freeAsmop (right, NULL, ic);
4674 freeAsmop (result, NULL, ic);
4677 /*-----------------------------------------------------------------*/
4678 /* genInline - write the inline code out */
4679 /*-----------------------------------------------------------------*/
4681 genInline (iCode * ic)
4683 char *buffer, *bp, *bp1;
4685 _G.lines.isInline += (!options.asmpeep);
4687 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4688 strcpy (buffer, IC_INLINE (ic));
4690 /* emit each line as a code */
4715 _G.lines.isInline -= (!options.asmpeep);
4719 /*-----------------------------------------------------------------*/
4720 /* genRRC - rotate right with carry */
4721 /*-----------------------------------------------------------------*/
4728 /*-----------------------------------------------------------------*/
4729 /* genRLC - generate code for rotate left with carry */
4730 /*-----------------------------------------------------------------*/
4737 /*-----------------------------------------------------------------*/
4738 /* genGetHbit - generates code get highest order bit */
4739 /*-----------------------------------------------------------------*/
4741 genGetHbit (iCode * ic)
4743 operand *left, *result;
4744 left = IC_LEFT (ic);
4745 result = IC_RESULT (ic);
4746 aopOp (left, ic, FALSE, FALSE);
4747 aopOp (result, ic, FALSE, FALSE);
4749 /* get the highest order byte into a */
4750 emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4752 if (AOP_TYPE (result) == AOP_CRY)
4760 /* PENDING: For re-target. */
4766 freeAsmop (left, NULL, ic);
4767 freeAsmop (result, NULL, ic);
4771 emitRsh2 (asmop *aop, int size, int is_signed)
4777 const char *l = aopGet (aop, size, FALSE);
4780 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
4790 /*-----------------------------------------------------------------*/
4791 /* shiftR2Left2Result - shift right two bytes from left to result */
4792 /*-----------------------------------------------------------------*/
4794 shiftR2Left2Result (operand * left, int offl,
4795 operand * result, int offr,
4796 int shCount, int is_signed)
4799 symbol *tlbl, *tlbl1;
4801 movLeft2Result (left, offl, result, offr, 0);
4802 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4804 /* if (AOP(result)->type == AOP_REG) { */
4806 tlbl = newiTempLabel (NULL);
4807 tlbl1 = newiTempLabel (NULL);
4809 /* Left is already in result - so now do the shift */
4814 emitRsh2 (AOP (result), size, is_signed);
4819 emit2 ("ld a,!immedbyte+1", shCount);
4820 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4821 emitLabel (tlbl->key + 100);
4823 emitRsh2 (AOP (result), size, is_signed);
4825 emitLabel (tlbl1->key + 100);
4827 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4831 /*-----------------------------------------------------------------*/
4832 /* shiftL2Left2Result - shift left two bytes from left to result */
4833 /*-----------------------------------------------------------------*/
4835 shiftL2Left2Result (operand * left, int offl,
4836 operand * result, int offr, int shCount)
4838 if (sameRegs (AOP (result), AOP (left)) &&
4839 ((offl + MSB16) == offr))
4845 /* Copy left into result */
4846 movLeft2Result (left, offl, result, offr, 0);
4847 movLeft2Result (left, offl + 1, result, offr + 1, 0);
4849 /* PENDING: for now just see if it'll work. */
4850 /*if (AOP(result)->type == AOP_REG) { */
4854 symbol *tlbl, *tlbl1;
4857 tlbl = newiTempLabel (NULL);
4858 tlbl1 = newiTempLabel (NULL);
4860 /* Left is already in result - so now do the shift */
4863 emit2 ("ld a,!immedbyte+1", shCount);
4864 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4865 emitLabel (tlbl->key + 100);
4870 l = aopGet (AOP (result), offset, FALSE);
4874 emit2 ("sla %s", l);
4885 emitLabel (tlbl1->key + 100);
4887 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4892 /*-----------------------------------------------------------------*/
4893 /* AccRol - rotate left accumulator by known count */
4894 /*-----------------------------------------------------------------*/
4896 AccRol (int shCount)
4898 shCount &= 0x0007; // shCount : 0..7
4937 /*-----------------------------------------------------------------*/
4938 /* AccLsh - left shift accumulator by known count */
4939 /*-----------------------------------------------------------------*/
4941 AccLsh (int shCount)
4943 static const unsigned char SLMask[] =
4945 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
4954 else if (shCount == 2)
4961 /* rotate left accumulator */
4963 /* and kill the lower order bits */
4964 emit2 ("and a,!immedbyte", SLMask[shCount]);
4969 /*-----------------------------------------------------------------*/
4970 /* shiftL1Left2Result - shift left one byte from left to result */
4971 /*-----------------------------------------------------------------*/
4973 shiftL1Left2Result (operand * left, int offl,
4974 operand * result, int offr, int shCount)
4977 l = aopGet (AOP (left), offl, FALSE);
4979 /* shift left accumulator */
4981 aopPut (AOP (result), "a", offr);
4985 /*-----------------------------------------------------------------*/
4986 /* genlshTwo - left shift two bytes by known amount != 0 */
4987 /*-----------------------------------------------------------------*/
4989 genlshTwo (operand * result, operand * left, int shCount)
4991 int size = AOP_SIZE (result);
4993 wassert (size == 2);
4995 /* if shCount >= 8 */
5003 movLeft2Result (left, LSB, result, MSB16, 0);
5004 aopPut (AOP (result), "!zero", 0);
5005 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5009 movLeft2Result (left, LSB, result, MSB16, 0);
5010 aopPut (AOP (result), "!zero", 0);
5015 aopPut (AOP (result), "!zero", LSB);
5018 /* 1 <= shCount <= 7 */
5027 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5032 /*-----------------------------------------------------------------*/
5033 /* genlshOne - left shift a one byte quantity by known count */
5034 /*-----------------------------------------------------------------*/
5036 genlshOne (operand * result, operand * left, int shCount)
5038 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5041 /*-----------------------------------------------------------------*/
5042 /* genLeftShiftLiteral - left shifting by known count */
5043 /*-----------------------------------------------------------------*/
5045 genLeftShiftLiteral (operand * left,
5050 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5053 freeAsmop (right, NULL, ic);
5055 aopOp (left, ic, FALSE, FALSE);
5056 aopOp (result, ic, FALSE, FALSE);
5058 size = getSize (operandType (result));
5060 /* I suppose that the left size >= result size */
5066 else if (shCount >= (size * 8))
5070 aopPut (AOP (result), "!zero", size);
5078 genlshOne (result, left, shCount);
5081 genlshTwo (result, left, shCount);
5084 wassertl (0, "Shifting of longs is currently unsupported");
5090 freeAsmop (left, NULL, ic);
5091 freeAsmop (result, NULL, ic);
5094 /*-----------------------------------------------------------------*/
5095 /* genLeftShift - generates code for left shifting */
5096 /*-----------------------------------------------------------------*/
5098 genLeftShift (iCode * ic)
5102 symbol *tlbl, *tlbl1;
5103 operand *left, *right, *result;
5105 right = IC_RIGHT (ic);
5106 left = IC_LEFT (ic);
5107 result = IC_RESULT (ic);
5109 aopOp (right, ic, FALSE, FALSE);
5111 /* if the shift count is known then do it
5112 as efficiently as possible */
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 genLeftShiftLiteral (left, right, result, ic);
5119 /* shift count is unknown then we have to form a loop get the loop
5120 count in B : Note: we take only the lower order byte since
5121 shifting more that 32 bits make no sense anyway, ( the largest
5122 size of an object can be only 32 bits ) */
5123 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
5125 freeAsmop (right, NULL, ic);
5126 aopOp (left, ic, FALSE, FALSE);
5127 aopOp (result, ic, FALSE, FALSE);
5129 /* now move the left to the result if they are not the
5132 if (!sameRegs (AOP (left), AOP (result)))
5135 size = AOP_SIZE (result);
5139 l = aopGet (AOP (left), offset, FALSE);
5140 aopPut (AOP (result), l, offset);
5145 tlbl = newiTempLabel (NULL);
5146 size = AOP_SIZE (result);
5148 tlbl1 = newiTempLabel (NULL);
5150 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5151 emitLabel (tlbl->key + 100);
5152 l = aopGet (AOP (result), offset, FALSE);
5156 l = aopGet (AOP (result), offset, FALSE);
5160 emit2 ("sla %s", l);
5168 emitLabel (tlbl1->key + 100);
5170 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5172 freeAsmop (left, NULL, ic);
5173 freeAsmop (result, NULL, ic);
5176 /*-----------------------------------------------------------------*/
5177 /* genrshOne - left shift two bytes by known amount != 0 */
5178 /*-----------------------------------------------------------------*/
5180 genrshOne (operand * result, operand * left, int shCount, int is_signed)
5183 int size = AOP_SIZE (result);
5186 wassert (size == 1);
5187 wassert (shCount < 8);
5189 l = aopGet (AOP (left), 0, FALSE);
5191 if (AOP (result)->type == AOP_REG)
5193 aopPut (AOP (result), l, 0);
5194 l = aopGet (AOP (result), 0, FALSE);
5197 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5205 emit2 ("%s a", is_signed ? "sra" : "srl");
5207 aopPut (AOP (result), "a", 0);
5211 /*-----------------------------------------------------------------*/
5212 /* AccRsh - right shift accumulator by known count */
5213 /*-----------------------------------------------------------------*/
5215 AccRsh (int shCount)
5217 static const unsigned char SRMask[] =
5219 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
5224 /* rotate right accumulator */
5225 AccRol (8 - shCount);
5226 /* and kill the higher order bits */
5227 emit2 ("and a,!immedbyte", SRMask[shCount]);
5231 /*-----------------------------------------------------------------*/
5232 /* shiftR1Left2Result - shift right one byte from left to result */
5233 /*-----------------------------------------------------------------*/
5235 shiftR1Left2Result (operand * left, int offl,
5236 operand * result, int offr,
5237 int shCount, int sign)
5239 _moveA (aopGet (AOP (left), offl, FALSE));
5244 emit2 ("%s a", sign ? "sra" : "srl");
5251 aopPut (AOP (result), "a", offr);
5254 /*-----------------------------------------------------------------*/
5255 /* genrshTwo - right shift two bytes by known amount != 0 */
5256 /*-----------------------------------------------------------------*/
5258 genrshTwo (operand * result, operand * left,
5259 int shCount, int sign)
5261 /* if shCount >= 8 */
5267 shiftR1Left2Result (left, MSB16, result, LSB,
5272 movLeft2Result (left, MSB16, result, LSB, sign);
5276 /* Sign extend the result */
5277 _moveA(aopGet (AOP (result), 0, FALSE));
5281 aopPut (AOP (result), ACC_NAME, MSB16);
5285 aopPut (AOP (result), "!zero", 1);
5288 /* 1 <= shCount <= 7 */
5291 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
5295 /*-----------------------------------------------------------------*/
5296 /* genRightShiftLiteral - left shifting by known count */
5297 /*-----------------------------------------------------------------*/
5299 genRightShiftLiteral (operand * left,
5305 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5308 freeAsmop (right, NULL, ic);
5310 aopOp (left, ic, FALSE, FALSE);
5311 aopOp (result, ic, FALSE, FALSE);
5313 size = getSize (operandType (result));
5315 /* I suppose that the left size >= result size */
5321 else if (shCount >= (size * 8))
5323 aopPut (AOP (result), "!zero", size);
5329 genrshOne (result, left, shCount, sign);
5332 genrshTwo (result, left, shCount, sign);
5335 wassertl (0, "Asked to shift right a long which should be a function call");
5338 wassertl (0, "Entered default case in right shift delegate");
5341 freeAsmop (left, NULL, ic);
5342 freeAsmop (result, NULL, ic);
5345 /*-----------------------------------------------------------------*/
5346 /* genRightShift - generate code for right shifting */
5347 /*-----------------------------------------------------------------*/
5349 genRightShift (iCode * ic)
5351 operand *right, *left, *result;
5353 int size, offset, first = 1;
5357 symbol *tlbl, *tlbl1;
5359 /* if signed then we do it the hard way preserve the
5360 sign bit moving it inwards */
5361 retype = getSpec (operandType (IC_RESULT (ic)));
5363 is_signed = !SPEC_USIGN (retype);
5365 /* signed & unsigned types are treated the same : i.e. the
5366 signed is NOT propagated inwards : quoting from the
5367 ANSI - standard : "for E1 >> E2, is equivalent to division
5368 by 2**E2 if unsigned or if it has a non-negative value,
5369 otherwise the result is implementation defined ", MY definition
5370 is that the sign does not get propagated */
5372 right = IC_RIGHT (ic);
5373 left = IC_LEFT (ic);
5374 result = IC_RESULT (ic);
5376 aopOp (right, ic, FALSE, FALSE);
5378 /* if the shift count is known then do it
5379 as efficiently as possible */
5380 if (AOP_TYPE (right) == AOP_LIT)
5382 genRightShiftLiteral (left, right, result, ic, is_signed);
5386 aopOp (left, ic, FALSE, FALSE);
5387 aopOp (result, ic, FALSE, FALSE);
5389 /* now move the left to the result if they are not the
5391 if (!sameRegs (AOP (left), AOP (result)) &&
5392 AOP_SIZE (result) > 1)
5395 size = AOP_SIZE (result);
5399 l = aopGet (AOP (left), offset, FALSE);
5400 aopPut (AOP (result), l, offset);
5405 emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
5407 freeAsmop (right, NULL, ic);
5409 tlbl = newiTempLabel (NULL);
5410 tlbl1 = newiTempLabel (NULL);
5411 size = AOP_SIZE (result);
5414 emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5415 emitLabel (tlbl->key + 100);
5418 l = aopGet (AOP (result), offset--, FALSE);
5421 emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5429 emitLabel (tlbl1->key + 100);
5431 emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5433 freeAsmop (left, NULL, ic);
5434 freeAsmop (result, NULL, ic);
5437 /*-----------------------------------------------------------------*/
5438 /* genGenPointerGet - get value from generic pointer space */
5439 /*-----------------------------------------------------------------*/
5441 genGenPointerGet (operand * left,
5442 operand * result, iCode * ic)
5445 sym_link *retype = getSpec (operandType (result));
5451 aopOp (left, ic, FALSE, FALSE);
5452 aopOp (result, ic, FALSE, FALSE);
5454 if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
5457 if (isPtrPair (AOP (left)))
5459 tsprintf (buffer, "!*pair", getPairName (AOP (left)));
5460 aopPut (AOP (result), buffer, 0);
5464 emit2 ("ld a,!*pair", getPairName (AOP (left)));
5465 aopPut (AOP (result), "a", 0);
5467 freeAsmop (left, NULL, ic);
5471 /* For now we always load into IY */
5472 /* if this is remateriazable */
5473 fetchPair (pair, AOP (left));
5475 /* so iy now contains the address */
5476 freeAsmop (left, NULL, ic);
5478 /* if bit then unpack */
5479 if (IS_BITVAR (retype))
5485 size = AOP_SIZE (result);
5490 /* PENDING: make this better */
5491 if (!IS_GB && AOP (result)->type == AOP_REG)
5493 aopPut (AOP (result), "!*hl", offset++);
5497 emit2 ("ld a,!*pair", _pairs[pair].name);
5498 aopPut (AOP (result), "a", offset++);
5502 emit2 ("inc %s", _pairs[pair].name);
5503 _G.pairs[pair].offset++;
5509 freeAsmop (result, NULL, ic);
5512 /*-----------------------------------------------------------------*/
5513 /* genPointerGet - generate code for pointer get */
5514 /*-----------------------------------------------------------------*/
5516 genPointerGet (iCode * ic)
5518 operand *left, *result;
5519 sym_link *type, *etype;
5521 left = IC_LEFT (ic);
5522 result = IC_RESULT (ic);
5524 /* depending on the type of pointer we need to
5525 move it to the correct pointer register */
5526 type = operandType (left);
5527 etype = getSpec (type);
5529 genGenPointerGet (left, result, ic);
5533 isRegOrLit (asmop * aop)
5535 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
5540 /*-----------------------------------------------------------------*/
5541 /* genGenPointerSet - stores the value into a pointer location */
5542 /*-----------------------------------------------------------------*/
5544 genGenPointerSet (operand * right,
5545 operand * result, iCode * ic)
5548 sym_link *retype = getSpec (operandType (right));
5549 PAIR_ID pairId = PAIR_HL;
5551 aopOp (result, ic, FALSE, FALSE);
5552 aopOp (right, ic, FALSE, FALSE);
5557 /* Handle the exceptions first */
5558 if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
5561 const char *l = aopGet (AOP (right), 0, FALSE);
5562 const char *pair = getPairName (AOP (result));
5563 if (canAssignToPtr (l) && isPtr (pair))
5565 emit2 ("ld !*pair,%s", pair, l);
5570 emit2 ("ld !*pair,a", pair);
5575 /* if the operand is already in dptr
5576 then we do nothing else we move the value to dptr */
5577 if (AOP_TYPE (result) != AOP_STR)
5579 fetchPair (pairId, AOP (result));
5581 /* so hl know contains the address */
5582 freeAsmop (result, NULL, ic);
5584 /* if bit then unpack */
5585 if (IS_BITVAR (retype))
5591 size = AOP_SIZE (right);
5596 const char *l = aopGet (AOP (right), offset, FALSE);
5597 if (isRegOrLit (AOP (right)) && !IS_GB)
5599 emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
5604 emit2 ("ld !*pair,a", _pairs[pairId].name);
5608 emit2 ("inc %s", _pairs[pairId].name);
5609 _G.pairs[pairId].offset++;
5615 freeAsmop (right, NULL, ic);
5618 /*-----------------------------------------------------------------*/
5619 /* genPointerSet - stores the value into a pointer location */
5620 /*-----------------------------------------------------------------*/
5622 genPointerSet (iCode * ic)
5624 operand *right, *result;
5625 sym_link *type, *etype;
5627 right = IC_RIGHT (ic);
5628 result = IC_RESULT (ic);
5630 /* depending on the type of pointer we need to
5631 move it to the correct pointer register */
5632 type = operandType (result);
5633 etype = getSpec (type);
5635 genGenPointerSet (right, result, ic);
5638 /*-----------------------------------------------------------------*/
5639 /* genIfx - generate code for Ifx statement */
5640 /*-----------------------------------------------------------------*/
5642 genIfx (iCode * ic, iCode * popIc)
5644 operand *cond = IC_COND (ic);
5647 aopOp (cond, ic, FALSE, TRUE);
5649 /* get the value into acc */
5650 if (AOP_TYPE (cond) != AOP_CRY)
5654 /* the result is now in the accumulator */
5655 freeAsmop (cond, NULL, ic);
5657 /* if there was something to be popped then do it */
5661 /* if the condition is a bit variable */
5662 if (isbit && IS_ITEMP (cond) &&
5664 genIfxJump (ic, SPIL_LOC (cond)->rname);
5665 else if (isbit && !IS_ITEMP (cond))
5666 genIfxJump (ic, OP_SYMBOL (cond)->rname);
5668 genIfxJump (ic, "a");
5673 /*-----------------------------------------------------------------*/
5674 /* genAddrOf - generates code for address of */
5675 /*-----------------------------------------------------------------*/
5677 genAddrOf (iCode * ic)
5679 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5681 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5683 /* if the operand is on the stack then we
5684 need to get the stack offset of this
5691 if (sym->stack <= 0)
5693 setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
5697 setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5699 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
5703 emit2 ("ld de,!hashedstr", sym->rname);
5704 commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
5712 /* if it has an offset then we need to compute it */
5714 emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5716 emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5717 emit2 ("add hl,sp");
5721 emit2 ("ld hl,#%s", sym->rname);
5723 commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
5725 freeAsmop (IC_RESULT (ic), NULL, ic);
5728 /*-----------------------------------------------------------------*/
5729 /* genAssign - generate code for assignment */
5730 /*-----------------------------------------------------------------*/
5732 genAssign (iCode * ic)
5734 operand *result, *right;
5736 unsigned long lit = 0L;
5738 result = IC_RESULT (ic);
5739 right = IC_RIGHT (ic);
5741 /* Dont bother assigning if they are the same */
5742 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5744 emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5748 aopOp (right, ic, FALSE, FALSE);
5749 aopOp (result, ic, TRUE, FALSE);
5751 /* if they are the same registers */
5752 if (sameRegs (AOP (right), AOP (result)))
5754 emitDebug ("; (registers are the same)");
5758 /* if the result is a bit */
5759 if (AOP_TYPE (result) == AOP_CRY)
5761 wassertl (0, "Tried to assign to a bit");
5765 size = AOP_SIZE (result);
5768 if (AOP_TYPE (right) == AOP_LIT)
5769 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5770 if (isPair (AOP (result)))
5772 fetchPair (getPairId (AOP (result)), AOP (right));
5774 else if ((size > 1) &&
5775 (AOP_TYPE (result) != AOP_REG) &&
5776 (AOP_TYPE (right) == AOP_LIT) &&
5777 !IS_FLOAT (operandType (right)) &&
5780 bool fXored = FALSE;
5782 /* Work from the top down.
5783 Done this way so that we can use the cached copy of 0
5784 in A for a fast clear */
5787 if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5789 if (!fXored && size > 1)
5796 aopPut (AOP (result), "a", offset);
5800 aopPut (AOP (result), "!zero", offset);
5804 aopPut (AOP (result),
5805 aopGet (AOP (right), offset, FALSE),
5810 else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5812 /* Special case. Load into a and d, then load out. */
5813 _moveA (aopGet (AOP (right), 0, FALSE));
5814 emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
5815 aopPut (AOP (result), "a", 0);
5816 aopPut (AOP (result), "e", 1);
5818 else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5820 /* Special case - simple memcpy */
5821 aopGet (AOP (right), LSB, FALSE);
5824 aopGet (AOP (result), LSB, FALSE);
5828 emit2 ("ld a,(de)");
5829 /* Peephole will optimise this. */
5830 emit2 ("ld (hl),a");
5838 spillPair (PAIR_HL);
5844 /* PENDING: do this check better */
5845 if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5847 _moveA (aopGet (AOP (right), offset, FALSE));
5848 aopPut (AOP (result), "a", offset);
5851 aopPut (AOP (result),
5852 aopGet (AOP (right), offset, FALSE),
5859 freeAsmop (right, NULL, ic);
5860 freeAsmop (result, NULL, ic);
5863 /*-----------------------------------------------------------------*/
5864 /* genJumpTab - genrates code for jump table */
5865 /*-----------------------------------------------------------------*/
5867 genJumpTab (iCode * ic)
5872 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5873 /* get the condition into accumulator */
5874 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5877 emit2 ("ld e,%s", l);
5878 emit2 ("ld d,!zero");
5879 jtab = newiTempLabel (NULL);
5881 emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5882 emit2 ("add hl,de");
5883 emit2 ("add hl,de");
5884 emit2 ("add hl,de");
5885 freeAsmop (IC_JTCOND (ic), NULL, ic);
5889 emitLabel (jtab->key + 100);
5890 /* now generate the jump labels */
5891 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5892 jtab = setNextItem (IC_JTLABELS (ic)))
5893 emit2 ("jp !tlabel", jtab->key + 100);
5896 /*-----------------------------------------------------------------*/
5897 /* genCast - gen code for casting */
5898 /*-----------------------------------------------------------------*/
5900 genCast (iCode * ic)
5902 operand *result = IC_RESULT (ic);
5903 sym_link *ctype = operandType (IC_LEFT (ic));
5904 operand *right = IC_RIGHT (ic);
5907 /* if they are equivalent then do nothing */
5908 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5911 aopOp (right, ic, FALSE, FALSE);
5912 aopOp (result, ic, FALSE, FALSE);
5914 /* if the result is a bit */
5915 if (AOP_TYPE (result) == AOP_CRY)
5917 wassertl (0, "Tried to cast to a bit");
5920 /* if they are the same size : or less */
5921 if (AOP_SIZE (result) <= AOP_SIZE (right))
5924 /* if they are in the same place */
5925 if (sameRegs (AOP (right), AOP (result)))
5928 /* if they in different places then copy */
5929 size = AOP_SIZE (result);
5933 aopPut (AOP (result),
5934 aopGet (AOP (right), offset, FALSE),
5941 /* So we now know that the size of destination is greater
5942 than the size of the source */
5943 /* we move to result for the size of source */
5944 size = AOP_SIZE (right);
5948 aopPut (AOP (result),
5949 aopGet (AOP (right), offset, FALSE),
5954 /* now depending on the sign of the destination */
5955 size = AOP_SIZE (result) - AOP_SIZE (right);
5956 /* Unsigned or not an integral type - right fill with zeros */
5957 if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5960 aopPut (AOP (result), "!zero", offset++);
5964 /* we need to extend the sign :{ */
5965 const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5971 aopPut (AOP (result), "a", offset++);
5975 freeAsmop (right, NULL, ic);
5976 freeAsmop (result, NULL, ic);
5979 /*-----------------------------------------------------------------*/
5980 /* genReceive - generate code for a receive iCode */
5981 /*-----------------------------------------------------------------*/
5983 genReceive (iCode * ic)
5985 if (isOperandInFarSpace (IC_RESULT (ic)) &&
5986 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5987 IS_TRUE_SYMOP (IC_RESULT (ic))))
5997 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5998 size = AOP_SIZE(IC_RESULT(ic));
6000 for (i = 0; i < size; i++) {
6001 aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
6005 freeAsmop (IC_RESULT (ic), NULL, ic);
6010 /** Maximum number of bytes to emit per line. */
6014 /** Context for the byte output chunker. */
6017 unsigned char buffer[DBEMIT_MAX_RUN];
6022 /** Flushes a byte chunker by writing out all in the buffer and
6026 _dbFlush(DBEMITCTX *self)
6033 sprintf(line, ".db 0x%02X", self->buffer[0]);
6035 for (i = 1; i < self->pos; i++)
6037 sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
6044 /** Write out another byte, buffering until a decent line is
6048 _dbEmit(DBEMITCTX *self, int c)
6050 if (self->pos == DBEMIT_MAX_RUN)
6054 self->buffer[self->pos++] = c;
6057 /** Context for a simple run length encoder. */
6061 unsigned char buffer[128];
6063 /** runLen may be equivalent to pos. */
6069 RLE_CHANGE_COST = 4,
6073 /** Flush the buffer of a run length encoder by writing out the run or
6074 data that it currently contains.
6077 _rleCommit(RLECTX *self)
6083 memset(&db, 0, sizeof(db));
6085 emit2(".db %u", self->pos);
6087 for (i = 0; i < self->pos; i++)
6089 _dbEmit(&db, self->buffer[i]);
6098 Can get either a run or a block of random stuff.
6099 Only want to change state if a good run comes in or a run ends.
6100 Detecting run end is easy.
6103 Say initial state is in run, len zero, last zero. Then if you get a
6104 few zeros then something else then a short run will be output.
6105 Seems OK. While in run mode, keep counting. While in random mode,
6106 keep a count of the run. If run hits margin, output all up to run,
6107 restart, enter run mode.
6110 /** Add another byte into the run length encoder, flushing as
6111 required. The run length encoder uses the Amiga IFF style, where
6112 a block is prefixed by its run length. A positive length means
6113 the next n bytes pass straight through. A negative length means
6114 that the next byte is repeated -n times. A zero terminates the
6118 _rleAppend(RLECTX *self, int c)
6122 if (c != self->last)
6124 /* The run has stopped. See if it is worthwhile writing it out
6125 as a run. Note that the random data comes in as runs of
6128 if (self->runLen > RLE_CHANGE_COST)
6130 /* Yes, worthwhile. */
6131 /* Commit whatever was in the buffer. */
6133 emit2(".db -%u,0x%02X", self->runLen, self->last);
6137 /* Not worthwhile. Append to the end of the random list. */
6138 for (i = 0; i < self->runLen; i++)
6140 if (self->pos >= RLE_MAX_BLOCK)
6145 self->buffer[self->pos++] = self->last;
6153 if (self->runLen >= RLE_MAX_BLOCK)
6155 /* Commit whatever was in the buffer. */
6158 emit2 (".db -%u,0x%02X", self->runLen, self->last);
6166 _rleFlush(RLECTX *self)
6168 _rleAppend(self, -1);
6175 /** genArrayInit - Special code for initialising an array with constant
6179 genArrayInit (iCode * ic)
6183 int elementSize = 0, eIndex, i;
6184 unsigned val, lastVal;
6188 memset(&rle, 0, sizeof(rle));
6190 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
6192 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
6194 /* Emit the support function call and the destination address. */
6195 emit2("call __initrleblock");
6196 emit2(".dw %s", aopGetWord (AOP(IC_LEFT(ic)), 0));
6200 wassertl (0, "Unexpected operand to genArrayInit.\n");
6203 type = operandType(IC_LEFT(ic));
6205 if (type && type->next)
6207 elementSize = getSize(type->next);
6211 wassertl (0, "Can't determine element size in genArrayInit.");
6214 iLoop = IC_ARRAYILIST(ic);
6215 lastVal = (unsigned)-1;
6217 /* Feed all the bytes into the run length encoder which will handle
6219 This works well for mixed char data, and for random int and long
6228 for (i = 0; i < ix; i++)
6230 for (eIndex = 0; eIndex < elementSize; eIndex++)
6232 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
6233 _rleAppend(&rle, val);
6238 iLoop = iLoop->next;
6242 /* Mark the end of the run. */
6245 freeAsmop (IC_LEFT(ic), NULL, ic);
6248 /*-----------------------------------------------------------------*/
6249 /* genZ80Code - generate code for Z80 based controllers */
6250 /*-----------------------------------------------------------------*/
6252 genZ80Code (iCode * lic)
6260 _fReturn = _gbz80_return;
6261 _fTmp = _gbz80_return;
6265 _fReturn = _z80_return;
6266 _fTmp = _z80_return;
6269 _G.lines.head = _G.lines.current = NULL;
6271 for (ic = lic; ic; ic = ic->next)
6274 if (cln != ic->lineno)
6276 emit2 ("; %s %d", ic->filename, ic->lineno);
6279 /* if the result is marked as
6280 spilt and rematerializable or code for
6281 this has already been generated then
6283 if (resultRemat (ic) || ic->generated)
6286 /* depending on the operation */
6290 emitDebug ("; genNot");
6295 emitDebug ("; genCpl");
6300 emitDebug ("; genUminus");
6305 emitDebug ("; genIpush");
6310 /* IPOP happens only when trying to restore a
6311 spilt live range, if there is an ifx statement
6312 following this pop then the if statement might
6313 be using some of the registers being popped which
6314 would destory the contents of the register so
6315 we need to check for this condition and handle it */
6317 ic->next->op == IFX &&
6318 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
6320 emitDebug ("; genIfx");
6321 genIfx (ic->next, ic);
6325 emitDebug ("; genIpop");
6331 emitDebug ("; genCall");
6336 emitDebug ("; genPcall");
6341 emitDebug ("; genFunction");
6346 emitDebug ("; genEndFunction");
6347 genEndFunction (ic);
6351 emitDebug ("; genRet");
6356 emitDebug ("; genLabel");
6361 emitDebug ("; genGoto");
6366 emitDebug ("; genPlus");
6371 emitDebug ("; genMinus");
6376 emitDebug ("; genMult");
6381 emitDebug ("; genDiv");
6386 emitDebug ("; genMod");
6391 emitDebug ("; genCmpGt");
6392 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
6396 emitDebug ("; genCmpLt");
6397 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
6404 /* note these two are xlated by algebraic equivalence
6405 during parsing SDCC.y */
6406 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6407 "got '>=' or '<=' shouldn't have come here");
6411 emitDebug ("; genCmpEq");
6412 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
6416 emitDebug ("; genAndOp");
6421 emitDebug ("; genOrOp");
6426 emitDebug ("; genXor");
6427 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
6431 emitDebug ("; genOr");
6432 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
6436 emitDebug ("; genAnd");
6437 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
6441 emitDebug ("; genInline");
6446 emitDebug ("; genRRC");
6451 emitDebug ("; genRLC");
6456 emitDebug ("; genGetHBIT");
6461 emitDebug ("; genLeftShift");
6466 emitDebug ("; genRightShift");
6470 case GET_VALUE_AT_ADDRESS:
6471 emitDebug ("; genPointerGet");
6477 if (POINTER_SET (ic))
6479 emitDebug ("; genAssign (pointer)");
6484 emitDebug ("; genAssign");
6490 emitDebug ("; genIfx");
6495 emitDebug ("; genAddrOf");
6500 emitDebug ("; genJumpTab");
6505 emitDebug ("; genCast");
6510 emitDebug ("; genReceive");
6515 emitDebug ("; addSet");
6516 addSet (&_G.sendSet, ic);
6529 /* now we are ready to call the
6530 peep hole optimizer */
6531 if (!options.nopeep)
6532 peepHole (&_G.lines.head);
6534 /* This is unfortunate */
6535 /* now do the actual printing */
6537 FILE *fp = codeOutFile;
6538 if (isInHome () && codeOutFile == code->oFile)
6539 codeOutFile = home->oFile;
6540 printLine (_G.lines.head, codeOutFile);
6541 if (_G.flushStatics)
6544 _G.flushStatics = 0;
6549 freeTrace(&_G.lines.trace);
6550 freeTrace(&_G.trace.aops);
6556 _isPairUsed (iCode * ic, PAIR_ID pairId)
6562 if (bitVectBitValue (ic->rMask, D_IDX))
6564 if (bitVectBitValue (ic->rMask, E_IDX))
6574 fetchLitSpecial (asmop * aop, bool negate, bool xor)
6577 value *val = aop->aopu.aop_lit;
6579 wassert (aop->type == AOP_LIT);
6580 wassert (!IS_FLOAT (val->type));
6582 v = (unsigned long) floatFromVal (val);
6590 tsprintf (buffer, "!immedword", v);
6591 return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));