1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 With reg params for mul and div 16234 202 162D
22 Michael Hope <michaelh@earthling.net> 2000
23 Based on the mcs51 generator -
24 Sandeep Dutta . sandeep.dutta@usa.net (1998)
25 and - Jean-Louis VERN.jlvern@writeme.com (1999)
27 This program is free software; you can redistribute it and/or modify it
28 under the terms of the GNU General Public License as published by the
29 Free Software Foundation; either version 2, or (at your option) any
32 This program is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 In other words, you are welcome to use, share and improve this program.
43 You are forbidden to forbid anyone else to use, share and improve
44 what you give them. Help stamp out software-hoarding!
46 -------------------------------------------------------------------------*/
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
64 /* this is the down and dirty file with all kinds of kludgy & hacky
65 stuff. This is what it is all about CODE GENERATION for a specific MCU.
66 Some of the routines may be reusable, will have to see */
69 static char *_z80_return[] = {"l", "h", "e", "d" };
70 static char *_gbz80_return[] = { "e", "d", "l", "h" };
71 static char **_fReturn;
77 static char *accUse[] = {"a" };
78 static char *hlUse[] = { "l", "h" };
84 extern int ptrRegReq ;
86 extern FILE *codeOutFile;
103 } _pairs[NUM_PAIRS] = {
108 { "iy", "iy.l?", "iy.h?" },
109 { "ix", "ix.l?", "ix.h?" }
112 #define RESULTONSTACK(x) \
113 (IC_RESULT(x) && IC_RESULT(x)->aop && \
114 IC_RESULT(x)->aop->type == AOP_STK )
116 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
117 #define CLRC emitcode("xor","a,a");
119 lineNode *lineHead = NULL;
120 lineNode *lineCurr = NULL;
122 static const unsigned char SLMask[] =
123 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
124 static const unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
158 static char *aopGet(asmop *aop, int offset, bool bit16);
160 static void _tidyUp(char *buf)
162 /* Clean up the line so that it is 'prettier' */
163 if (strchr(buf, ':')) {
164 /* Is a label - cant do anything */
167 /* Change the first (and probably only) ' ' to a tab so
179 static void emit2(const char *szFormat, ...)
184 va_start(ap, szFormat);
186 tvsprintf(buffer, szFormat, ap);
189 lineCurr = (lineCurr ?
190 connectLine(lineCurr,newLineNode(buffer)) :
191 (lineHead = newLineNode(buffer)));
193 lineCurr->isInline = inLine;
194 lineCurr->isDebug = debugLine;
197 /*-----------------------------------------------------------------*/
198 /* emitcode - writes the code into a file : for now it is simple */
199 /*-----------------------------------------------------------------*/
200 void emitcode (const char *inst, const char *fmt, ...)
203 char lb[MAX_INLINEASM];
209 sprintf(lb,"%s\t",inst);
210 vsprintf(lb+(strlen(lb)),fmt,ap);
214 while (isspace(*lbp)) lbp++;
217 lineCurr = (lineCurr ?
218 connectLine(lineCurr,newLineNode(lb)) :
219 (lineHead = newLineNode(lb)));
220 lineCurr->isInline = inLine;
221 lineCurr->isDebug = debugLine;
238 emitcode("ld", "sp,ix");
239 emitcode("pop", "ix");
240 emitcode("pop", "de");
245 const char *getPairName(asmop *aop)
247 if (aop->type == AOP_REG) {
248 switch (aop->aopu.aop_reg[0]->rIdx) {
260 else if (aop->type == AOP_STR) {
261 switch (*aop->aopu.aop_str[0]) {
277 static PAIR_ID getPairId(asmop *aop)
279 if (aop->size == 2) {
280 if (aop->type == AOP_REG) {
281 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
284 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
287 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
291 if (aop->type == AOP_STR) {
292 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
295 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
298 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
306 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
307 bool isPair(asmop *aop)
309 return (getPairId(aop) != PAIR_INVALID);
312 bool isPtrPair(asmop *aop)
314 PAIR_ID pairId = getPairId(aop);
324 /** Push a register pair onto the stack */
325 void genPairPush(asmop *aop)
327 emitcode("push", "%s", getPairName(aop));
331 /*-----------------------------------------------------------------*/
332 /* newAsmop - creates a new asmOp */
333 /*-----------------------------------------------------------------*/
334 static asmop *newAsmop (short type)
338 aop = Safe_calloc(1,sizeof(asmop));
343 /*-----------------------------------------------------------------*/
344 /* aopForSym - for a true symbol */
345 /*-----------------------------------------------------------------*/
346 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
355 space = SPEC_OCLS(sym->etype);
357 /* if already has one */
361 /* Assign depending on the storage class */
362 if (sym->onStack || sym->iaccess) {
363 emitcode("", "; AOP_STK for %s", sym->rname);
364 sym->aop = aop = newAsmop(AOP_STK);
365 aop->size = getSize(sym->type);
366 aop->aopu.aop_stk = sym->stack;
370 /* special case for a function */
371 if (IS_FUNC(sym->type)) {
372 sym->aop = aop = newAsmop(AOP_IMMD);
373 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
374 strcpy(aop->aopu.aop_immd,sym->rname);
380 /* if it is in direct space */
381 if (IN_REGSP(space) && !requires_a) {
382 sym->aop = aop = newAsmop (AOP_SFR);
383 aop->aopu.aop_dir = sym->rname ;
384 aop->size = getSize(sym->type);
385 emitcode("", "; AOP_SFR for %s", sym->rname);
390 /* only remaining is far space */
391 /* in which case DPTR gets the address */
393 emitcode("", "; AOP_HL for %s", sym->rname);
394 sym->aop = aop = newAsmop(AOP_HL);
397 sym->aop = aop = newAsmop(AOP_IY);
399 aop->size = getSize(sym->type);
400 aop->aopu.aop_dir = sym->rname;
402 /* if it is in code space */
403 if (IN_CODESPACE(space))
409 /*-----------------------------------------------------------------*/
410 /* aopForRemat - rematerialzes an object */
411 /*-----------------------------------------------------------------*/
412 static asmop *aopForRemat (symbol *sym)
415 iCode *ic = sym->rematiCode;
416 asmop *aop = newAsmop(AOP_IMMD);
419 /* if plus or minus print the right hand side */
420 if (ic->op == '+' || ic->op == '-') {
421 /* PENDING: for re-target */
422 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
425 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
428 /* we reached the end */
429 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
433 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
434 strcpy(aop->aopu.aop_immd,buffer);
438 /*-----------------------------------------------------------------*/
439 /* regsInCommon - two operands have some registers in common */
440 /*-----------------------------------------------------------------*/
441 bool regsInCommon (operand *op1, operand *op2)
446 /* if they have registers in common */
447 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
450 sym1 = OP_SYMBOL(op1);
451 sym2 = OP_SYMBOL(op2);
453 if (sym1->nRegs == 0 || sym2->nRegs == 0)
456 for (i = 0 ; i < sym1->nRegs ; i++) {
461 for (j = 0 ; j < sym2->nRegs ;j++ ) {
465 if (sym2->regs[j] == sym1->regs[i])
473 /*-----------------------------------------------------------------*/
474 /* operandsEqu - equivalent */
475 /*-----------------------------------------------------------------*/
476 bool operandsEqu ( operand *op1, operand *op2)
480 /* if they not symbols */
481 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
484 sym1 = OP_SYMBOL(op1);
485 sym2 = OP_SYMBOL(op2);
487 /* if both are itemps & one is spilt
488 and the other is not then false */
489 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
490 sym1->isspilt != sym2->isspilt )
493 /* if they are the same */
497 if (strcmp(sym1->rname,sym2->rname) == 0)
501 /* if left is a tmp & right is not */
505 (sym1->usl.spillLoc == sym2))
512 (sym2->usl.spillLoc == sym1))
518 /*-----------------------------------------------------------------*/
519 /* sameRegs - two asmops have the same registers */
520 /*-----------------------------------------------------------------*/
521 bool sameRegs (asmop *aop1, asmop *aop2 )
525 if (aop1->type == AOP_SFR ||
526 aop2->type == AOP_SFR)
532 if (aop1->type != AOP_REG ||
533 aop2->type != AOP_REG )
536 if (aop1->size != aop2->size)
539 for (i = 0 ; i < aop1->size ; i++ )
540 if (aop1->aopu.aop_reg[i] !=
541 aop2->aopu.aop_reg[i] )
547 /*-----------------------------------------------------------------*/
548 /* aopOp - allocates an asmop for an operand : */
549 /*-----------------------------------------------------------------*/
550 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
559 /* if this a literal */
560 if (IS_OP_LITERAL(op)) {
561 op->aop = aop = newAsmop(AOP_LIT);
562 aop->aopu.aop_lit = op->operand.valOperand;
563 aop->size = getSize(operandType(op));
567 /* if already has a asmop then continue */
571 /* if the underlying symbol has a aop */
572 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
573 op->aop = OP_SYMBOL(op)->aop;
577 /* if this is a true symbol */
578 if (IS_TRUE_SYMOP(op)) {
579 op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
583 /* this is a temporary : this has
589 e) can be a return use only */
593 /* if the type is a conditional */
594 if (sym->regType == REG_CND) {
595 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
600 /* if it is spilt then two situations
602 b) has a spill location */
603 if (sym->isspilt || sym->nRegs == 0) {
604 /* rematerialize it NOW */
606 sym->aop = op->aop = aop =
608 aop->size = getSize(sym->type);
614 if (sym->accuse == ACCUSE_A) {
615 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
616 aop->size = getSize(sym->type);
617 for ( i = 0 ; i < 2 ; i++ )
618 aop->aopu.aop_str[i] = accUse[i];
620 else if (sym->accuse == ACCUSE_HL) {
622 aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
623 aop->size = getSize(sym->type);
624 for ( i = 0 ; i < 2 ; i++ )
625 aop->aopu.aop_str[i] = hlUse[i];
634 aop = op->aop = sym->aop = newAsmop(AOP_STR);
635 aop->size = getSize(sym->type);
636 for ( i = 0 ; i < 4 ; i++ )
637 aop->aopu.aop_str[i] = _fReturn[i];
641 /* else spill location */
642 sym->aop = op->aop = aop =
643 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
644 aop->size = getSize(sym->type);
648 /* must be in a register */
649 sym->aop = op->aop = aop = newAsmop(AOP_REG);
650 aop->size = sym->nRegs;
651 for ( i = 0 ; i < sym->nRegs ;i++)
652 aop->aopu.aop_reg[i] = sym->regs[i];
655 /*-----------------------------------------------------------------*/
656 /* freeAsmop - free up the asmop given to an operand */
657 /*----------------------------------------------------------------*/
658 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
676 /* all other cases just dealloc */
680 OP_SYMBOL(op)->aop = NULL;
681 /* if the symbol has a spill */
683 SPIL_LOC(op)->aop = NULL;
688 bool isLitWord(asmop *aop)
690 /* if (aop->size != 2)
701 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
707 if (aop->size != 2 && aop->type != AOP_HL)
710 /* depending on type */
715 /* PENDING: for re-target */
717 tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
719 tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
720 rs = Safe_calloc(1,strlen(s)+1);
724 value * val = aop->aopu.aop_lit;
725 /* if it is a float then it gets tricky */
726 /* otherwise it is fairly simple */
727 if (!IS_FLOAT(val->type)) {
728 unsigned long v = floatFromVal(val);
734 tsprintf(buffer, "!immedword", v);
736 tsprintf(buffer, "!constword", v);
737 rs = Safe_calloc(1,strlen(buffer)+1);
738 return strcpy (rs,buffer);
743 convertFloat(&f, floatFromVal(val));
745 tsprintf(buffer, "!immedword", f.w[offset/2]);
747 tsprintf(buffer, "!constword", f.w[offset/2]);
748 rs = Safe_calloc(1,strlen(buffer)+1);
749 return strcpy (rs,buffer);
757 char *aopGetWord(asmop *aop, int offset)
759 return aopGetLitWordLong(aop, offset, TRUE);
762 bool isPtr(const char *s)
764 if (!strcmp(s, "hl"))
766 if (!strcmp(s, "ix"))
768 if (!strcmp(s, "iy"))
773 static void adjustPair(const char *pair, int *pold, int new)
777 while (*pold < new) {
778 emitcode("inc", "%s", pair);
781 while (*pold > new) {
782 emitcode("dec", "%s", pair);
787 static void spillPair(PAIR_ID pairId)
789 _G.pairs[pairId].last_type = AOP_INVALID;
790 _G.pairs[pairId].lit = NULL;
793 static void spillCached(void)
799 static bool requiresHL(asmop *aop)
810 static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
813 value * val = aop->aopu.aop_lit;
815 wassert(aop->type == AOP_LIT);
816 wassert(!IS_FLOAT(val->type));
818 v = floatFromVal(val);
826 tsprintf(buffer, "!immedword", v);
827 return gc_strdup(buffer);
830 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
833 const char *pair = _pairs[pairId].name;
834 l = aopGetLitWordLong(left, 0, FALSE);
838 if (pairId == PAIR_HL || pairId == PAIR_IY) {
839 if (_G.pairs[pairId].last_type == left->type) {
840 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
841 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
842 adjustPair(pair, &_G.pairs[pairId].offset, offset);
845 if (pairId == PAIR_IY && abs(offset)<127) {
851 _G.pairs[pairId].last_type = left->type;
852 _G.pairs[pairId].lit = gc_strdup(l);
853 _G.pairs[pairId].offset = offset;
855 if (IS_GB && pairId == PAIR_DE && 0) {
856 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
857 if (abs(_G.pairs[pairId].offset - offset) < 3) {
858 adjustPair(pair, &_G.pairs[pairId].offset, offset);
862 _G.pairs[pairId].last_type = left->type;
863 _G.pairs[pairId].lit = gc_strdup(l);
864 _G.pairs[pairId].offset = offset;
866 /* Both a lit on the right and a true symbol on the left */
868 emit2("ld %s,!hashedstr + %u", pair, l, offset);
870 emit2("ld %s,!hashedstr", pair, l);
873 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
875 /* if this is remateriazable */
876 if (isLitWord(aop)) {
877 fetchLitPair(pairId, aop, offset);
879 else { /* we need to get it byte by byte */
880 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
881 aopGet(aop, offset, FALSE);
885 emit2("ld h,!immedbyte", 0);
893 emit2("; WARNING: mlh woosed out. This code is invalid.");
896 else if (IS_Z80 && aop->type == AOP_IY) {
897 /* Instead of fetching relative to IY, just grab directly
898 from the address IY refers to */
899 char *l = aopGetLitWordLong(aop, offset, FALSE);
901 emit2("ld %s,(%s)", _pairs[pairId].name, l);
904 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
905 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
907 /* PENDING: check? */
908 if (pairId == PAIR_HL)
913 static void fetchPair(PAIR_ID pairId, asmop *aop)
915 fetchPairLong(pairId, aop, 0);
918 static void fetchHL(asmop *aop)
920 fetchPair(PAIR_HL, aop);
923 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
925 assert(pairId == PAIR_HL || pairId == PAIR_IY);
929 fetchLitPair(pairId, aop, 0);
932 fetchLitPair(pairId, aop, offset);
933 _G.pairs[pairId].offset = offset;
936 /* Doesnt include _G.stack.pushed */
937 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
938 if (aop->aopu.aop_stk > 0) {
939 abso += _G.stack.param_offset;
941 assert(pairId == PAIR_HL);
942 /* In some cases we can still inc or dec hl */
943 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
944 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
947 emit2("!ldahlsp", abso +_G.stack.pushed);
949 _G.pairs[pairId].offset = abso;
955 _G.pairs[pairId].last_type = aop->type;
958 static void emitLabel(int key)
960 emit2("!tlabeldef", key);
964 /*-----------------------------------------------------------------*/
965 /* aopGet - for fetching value of the aop */
966 /*-----------------------------------------------------------------*/
967 static char *aopGet(asmop *aop, int offset, bool bit16)
972 /* offset is greater than size then zero */
973 /* PENDING: this seems a bit screwed in some pointer cases. */
974 if (offset > (aop->size - 1) &&
975 aop->type != AOP_LIT)
978 /* depending on type */
981 /* PENDING: re-target */
983 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
987 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
990 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
993 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
998 rs = Safe_calloc(1,strlen(s)+1);
1004 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1006 rs = Safe_calloc(1,strlen(s)+1);
1012 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1014 rs = Safe_calloc(1,strlen(s)+1);
1019 return aop->aopu.aop_reg[offset]->name;
1023 setupPair(PAIR_HL, aop, offset);
1024 tsprintf(s, "!*hl");
1025 return gc_strdup(s);
1029 setupPair(PAIR_IY, aop, offset);
1030 tsprintf(s,"!*iyx", offset);
1031 rs = Safe_calloc(1,strlen(s)+1);
1037 setupPair(PAIR_HL, aop, offset);
1038 tsprintf(s, "!*hl");
1041 if (aop->aopu.aop_stk >= 0)
1042 offset += _G.stack.param_offset;
1043 tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
1045 rs = Safe_calloc(1,strlen(s)+1);
1059 wassert(offset < 2);
1060 return aop->aopu.aop_str[offset];
1063 return aopLiteral (aop->aopu.aop_lit,offset);
1067 return aop->aopu.aop_str[offset];
1071 wassertl(0, "aopget got unsupported aop->type");
1075 bool isRegString(const char *s)
1077 if (!strcmp(s, "b") ||
1088 bool isConstant(const char *s)
1090 /* This is a bit of a hack... */
1091 return (*s == '#' || *s == '$');
1094 bool canAssignToPtr(const char *s)
1103 /*-----------------------------------------------------------------*/
1104 /* aopPut - puts a string for a aop */
1105 /*-----------------------------------------------------------------*/
1106 static void aopPut (asmop *aop, const char *s, int offset)
1108 if (aop->size && offset > ( aop->size - 1)) {
1109 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1110 "aopPut got offset > aop->size");
1114 /* will assign value to value */
1115 /* depending on where it is ofcourse */
1116 switch (aop->type) {
1121 emitcode("ld", "a,%s", s);
1122 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1128 emitcode("ld", "a,%s", s);
1129 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1133 if (!strcmp(s, "!*hl"))
1134 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1137 aop->aopu.aop_reg[offset]->name, s);
1142 setupPair(PAIR_IY, aop, offset);
1143 if (!canAssignToPtr(s)) {
1144 emit2("ld a,%s", s);
1145 emit2("ld !*iyx,a", offset);
1148 emit2("ld !*iyx,%s", offset, s);
1153 /* PENDING: for re-target */
1154 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1158 setupPair(PAIR_HL, aop, offset);
1160 emit2("ld !*hl,%s", s);
1165 /* PENDING: re-target */
1166 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1170 setupPair(PAIR_HL, aop, offset);
1171 if (!canAssignToPtr(s)) {
1172 emit2("ld a,%s", s);
1176 emit2("ld !*hl,%s", s);
1179 if (aop->aopu.aop_stk >= 0)
1180 offset += _G.stack.param_offset;
1181 if (!canAssignToPtr(s)) {
1182 emit2("ld a,%s", s);
1183 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1186 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1191 /* if bit variable */
1192 if (!aop->aopu.aop_dir) {
1196 /* In bit space but not in C - cant happen */
1203 if (strcmp(aop->aopu.aop_str[offset],s)) {
1204 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1210 if (!offset && (strcmp(s,"acc") == 0))
1214 emitcode("", "; Error aopPut AOP_ACC");
1217 if (strcmp(aop->aopu.aop_str[offset],s))
1218 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1223 wassert(offset < 2);
1224 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1228 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1229 "aopPut got unsupported aop->type");
1234 #define AOP(op) op->aop
1235 #define AOP_TYPE(op) AOP(op)->type
1236 #define AOP_SIZE(op) AOP(op)->size
1237 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1239 static void commitPair(asmop *aop, PAIR_ID id)
1241 if (id == PAIR_HL && requiresHL(aop)) {
1244 aopPut(aop, "a", 0);
1245 aopPut(aop, "d", 1);
1248 aopPut(aop, _pairs[id].l, 0);
1249 aopPut(aop, _pairs[id].h, 1);
1253 /*-----------------------------------------------------------------*/
1254 /* getDataSize - get the operand data size */
1255 /*-----------------------------------------------------------------*/
1256 int getDataSize(operand *op)
1259 size = AOP_SIZE(op);
1267 /*-----------------------------------------------------------------*/
1268 /* movLeft2Result - move byte from left to result */
1269 /*-----------------------------------------------------------------*/
1270 static void movLeft2Result (operand *left, int offl,
1271 operand *result, int offr, int sign)
1274 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1275 l = aopGet(AOP(left),offl,FALSE);
1278 aopPut(AOP(result),l,offr);
1287 /** Put Acc into a register set
1289 void outAcc(operand *result)
1292 size = getDataSize(result);
1294 aopPut(AOP(result),"a",0);
1297 /* unsigned or positive */
1299 aopPut(AOP(result), zero, offset++);
1304 /** Take the value in carry and put it into a register
1306 void outBitCLong(operand *result, bool swap_sense)
1308 /* if the result is bit */
1309 if (AOP_TYPE(result) == AOP_CRY) {
1310 emitcode("", "; Note: outBitC form 1");
1311 aopPut(AOP(result),"blah",0);
1314 emit2("ld a,!zero");
1317 emit2("xor a,!immedbyte", 1);
1322 void outBitC(operand *result)
1324 outBitCLong(result, FALSE);
1327 /*-----------------------------------------------------------------*/
1328 /* toBoolean - emit code for orl a,operator(sizeop) */
1329 /*-----------------------------------------------------------------*/
1330 void toBoolean(operand *oper)
1332 int size = AOP_SIZE(oper);
1335 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1338 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1341 if (AOP(oper)->type != AOP_ACC) {
1343 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1348 /*-----------------------------------------------------------------*/
1349 /* genNot - generate code for ! operation */
1350 /*-----------------------------------------------------------------*/
1351 static void genNot (iCode *ic)
1353 sym_link *optype = operandType(IC_LEFT(ic));
1355 /* assign asmOps to operand & result */
1356 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1357 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1359 /* if in bit space then a special case */
1360 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1364 /* if type float then do float */
1365 if (IS_FLOAT(optype)) {
1369 toBoolean(IC_LEFT(ic));
1374 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1375 emit2("sub a,!one");
1376 outBitC(IC_RESULT(ic));
1378 /* release the aops */
1379 freeAsmop(IC_LEFT(ic),NULL,ic);
1380 freeAsmop(IC_RESULT(ic),NULL,ic);
1383 /*-----------------------------------------------------------------*/
1384 /* genCpl - generate code for complement */
1385 /*-----------------------------------------------------------------*/
1386 static void genCpl (iCode *ic)
1392 /* assign asmOps to operand & result */
1393 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1394 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1396 /* if both are in bit space then
1398 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1399 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1403 size = AOP_SIZE(IC_RESULT(ic));
1405 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1408 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1411 /* release the aops */
1412 freeAsmop(IC_LEFT(ic),NULL,ic);
1413 freeAsmop(IC_RESULT(ic),NULL,ic);
1416 /*-----------------------------------------------------------------*/
1417 /* genUminus - unary minus code generation */
1418 /*-----------------------------------------------------------------*/
1419 static void genUminus (iCode *ic)
1422 sym_link *optype, *rtype;
1425 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1426 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1428 /* if both in bit space then special
1430 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1431 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1436 optype = operandType(IC_LEFT(ic));
1437 rtype = operandType(IC_RESULT(ic));
1439 /* if float then do float stuff */
1440 if (IS_FLOAT(optype)) {
1445 /* otherwise subtract from zero */
1446 size = AOP_SIZE(IC_LEFT(ic));
1450 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1451 emit2("ld a,!zero");
1452 emit2("sbc a,%s",l);
1453 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1456 /* if any remaining bytes in the result */
1457 /* we just need to propagate the sign */
1458 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1462 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1466 /* release the aops */
1467 freeAsmop(IC_LEFT(ic),NULL,ic);
1468 freeAsmop(IC_RESULT(ic),NULL,ic);
1471 static void _push(PAIR_ID pairId)
1473 emit2("push %s", _pairs[pairId].name);
1474 _G.stack.pushed += 2;
1477 static void _pop(PAIR_ID pairId)
1479 emit2("pop %s", _pairs[pairId].name);
1480 _G.stack.pushed -= 2;
1484 /*-----------------------------------------------------------------*/
1485 /* assignResultValue - */
1486 /*-----------------------------------------------------------------*/
1487 void assignResultValue(operand * oper)
1489 int size = AOP_SIZE(oper);
1493 topInA = requiresHL(AOP(oper));
1499 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1500 /* We do it the hard way here. */
1502 aopPut(AOP(oper), _fReturn[0], 0);
1503 aopPut(AOP(oper), _fReturn[1], 1);
1504 emitcode("pop", "de");
1505 _G.stack.pushed -= 2;
1506 aopPut(AOP(oper), _fReturn[0], 2);
1507 aopPut(AOP(oper), _fReturn[1], 3);
1511 aopPut(AOP(oper), _fReturn[size], size);
1516 /*-----------------------------------------------------------------*/
1517 /* genIpush - genrate code for pushing this gets a little complex */
1518 /*-----------------------------------------------------------------*/
1519 static void genIpush (iCode *ic)
1521 int size, offset = 0 ;
1524 /* if this is not a parm push : ie. it is spill push
1525 and spill push is always done on the local stack */
1526 if (!ic->parmPush) {
1527 /* and the item is spilt then do nothing */
1528 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1531 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1532 size = AOP_SIZE(IC_LEFT(ic));
1533 /* push it on the stack */
1534 if (isPair(AOP(IC_LEFT(ic)))) {
1535 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1536 _G.stack.pushed += 2;
1541 /* Simple for now - load into A and PUSH AF */
1542 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1543 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1545 emit2("ld a,(%s)", l);
1548 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1549 emit2("ld a,%s", l);
1559 /* Hmmm... what about saving the currently used registers
1562 /* then do the push */
1563 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1565 size = AOP_SIZE(IC_LEFT(ic));
1567 if (isPair(AOP(IC_LEFT(ic)))) {
1569 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1573 fetchHL(AOP(IC_LEFT(ic)));
1574 emitcode("push", "hl");
1576 _G.stack.pushed += 2;
1580 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1581 emitcode("push", "hl");
1583 _G.stack.pushed += 2;
1584 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1585 emitcode("push", "hl");
1587 _G.stack.pushed += 2;
1592 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1593 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1595 emit2("ld a,(%s)", l);
1598 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1599 emit2("ld a,%s", l);
1601 emitcode("push", "af");
1602 emitcode("inc", "sp");
1607 freeAsmop(IC_LEFT(ic),NULL,ic);
1610 /*-----------------------------------------------------------------*/
1611 /* genIpop - recover the registers: can happen only for spilling */
1612 /*-----------------------------------------------------------------*/
1613 static void genIpop (iCode *ic)
1618 /* if the temp was not pushed then */
1619 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1622 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1623 size = AOP_SIZE(IC_LEFT(ic));
1625 if (isPair(AOP(IC_LEFT(ic)))) {
1626 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1630 emitcode("dec", "sp");
1631 emitcode("pop", "hl");
1633 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1637 freeAsmop(IC_LEFT(ic),NULL,ic);
1640 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1645 if (bitVectBitValue(ic->rUsed, D_IDX))
1647 if (bitVectBitValue(ic->rUsed, E_IDX))
1656 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1660 symbol *sym = OP_SYMBOL(op);
1662 if (sym->isspilt || sym->nRegs == 0)
1665 aopOp(op, ic, FALSE, FALSE);
1668 if (aop->type == AOP_REG) {
1670 for (i=0; i < aop->size; i++) {
1671 if (pairId == PAIR_DE) {
1672 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1673 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1675 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1684 freeAsmop(IC_LEFT(ic),NULL,ic);
1688 /* This is quite unfortunate */
1689 static void setArea(int inHome)
1691 static int lastArea = 0;
1694 if (_G.in_home != inHome) {
1696 const char *sz = port->mem.code_name;
1697 port->mem.code_name = "HOME";
1698 emit2("!area", CODE_NAME);
1699 port->mem.code_name = sz;
1702 emit2("!area", CODE_NAME);*/
1703 _G.in_home = inHome;
1707 static bool isInHome(void)
1712 /** Emit the code for a call statement
1714 static void emitCall(iCode *ic, bool ispcall)
1717 sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
1719 /* if caller saves & we have not saved then */
1720 if (!ic->regsSaved) {
1724 /* if send set is not empty then assign */
1728 int n = elementsInSet(sendSet);
1729 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1730 /* Only push de if it is used and if it's not used
1731 in the return value */
1732 /* Panic if partly used */
1733 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1734 emit2("; Warning: de crossover");
1736 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1743 if (IS_Z80 && n == 2 ) {
1744 /* Want to load HL first, then DE as HL may = DE */
1745 sic = setFirstItem(sendSet);
1746 sic = setNextItem(sendSet);
1747 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1748 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1750 freeAsmop (IC_LEFT(sic),NULL,sic);
1751 sic = setFirstItem(sendSet);
1752 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1753 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1755 freeAsmop (IC_LEFT(sic),NULL,sic);
1758 for (sic = setFirstItem(sendSet) ; sic ;
1759 sic = setNextItem(sendSet)) {
1761 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1762 size = AOP_SIZE(IC_LEFT(sic));
1764 /* Always send in pairs */
1767 if (IS_Z80 && n == 1)
1768 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1770 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1773 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1776 /* Send set too big */
1780 freeAsmop (IC_LEFT(sic),NULL,sic);
1789 if (IS_BANKEDCALL(detype)) {
1790 werror(W_INDIR_BANKED);
1792 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1794 if (isLitWord(AOP(IC_LEFT(ic)))) {
1795 emitcode("", "; Special case where the pCall is to a constant");
1796 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1799 symbol *rlbl = newiTempLabel(NULL);
1801 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1802 emitcode("push", "hl");
1803 _G.stack.pushed += 2;
1805 fetchHL(AOP(IC_LEFT(ic)));
1807 emit2("!tlabeldef", (rlbl->key+100));
1808 _G.stack.pushed -= 2;
1810 freeAsmop(IC_LEFT(ic),NULL,ic);
1813 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1814 OP_SYMBOL(IC_LEFT(ic))->rname :
1815 OP_SYMBOL(IC_LEFT(ic))->name;
1816 if (IS_BANKEDCALL(detype)) {
1817 emit2("call banked_call");
1818 emit2("!dws", name);
1819 emit2("!dw !bankimmeds", name);
1823 emit2("call %s", name);
1828 /* if we need assign a result value */
1829 if ((IS_ITEMP(IC_RESULT(ic)) &&
1830 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1831 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1832 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1835 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1838 assignResultValue(IC_RESULT(ic));
1840 freeAsmop(IC_RESULT(ic),NULL, ic);
1843 /* adjust the stack for parameters if required */
1844 if (IC_LEFT(ic)->parmBytes) {
1845 int i = IC_LEFT(ic)->parmBytes;
1846 _G.stack.pushed -= i;
1848 emit2("!ldaspsp", i);
1853 emitcode("ld", "hl,#%d", i);
1854 emitcode("add", "hl,sp");
1855 emitcode("ld", "sp,hl");
1859 emitcode("pop", "hl");
1863 emitcode("inc", "sp");
1872 /*-----------------------------------------------------------------*/
1873 /* genCall - generates a call statement */
1874 /*-----------------------------------------------------------------*/
1875 static void genCall (iCode *ic)
1877 sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
1878 emitCall(ic, FALSE);
1881 /*-----------------------------------------------------------------*/
1882 /* genPcall - generates a call by pointer statement */
1883 /*-----------------------------------------------------------------*/
1884 static void genPcall (iCode *ic)
1889 /*-----------------------------------------------------------------*/
1890 /* resultRemat - result is rematerializable */
1891 /*-----------------------------------------------------------------*/
1892 static int resultRemat (iCode *ic)
1894 if (SKIP_IC(ic) || ic->op == IFX)
1897 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1898 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1899 if (sym->remat && !POINTER_SET(ic))
1906 extern set *publics;
1908 /*-----------------------------------------------------------------*/
1909 /* genFunction - generated code for function entry */
1910 /*-----------------------------------------------------------------*/
1911 static void genFunction (iCode *ic)
1913 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1917 setArea(IS_NONBANKED(sym->etype));
1920 if (!IS_STATIC(sym->etype)) {
1921 addSetIfnotP(&publics, sym);
1924 /* create the function header */
1925 emit2("!functionheader", sym->name);
1926 /* PENDING: portability. */
1927 emit2("__%s_start:", sym->rname);
1928 emit2("!functionlabeldef", sym->rname);
1930 fetype = getSpec(operandType(IC_LEFT(ic)));
1932 /* if critical function then turn interrupts off */
1933 if (SPEC_CRTCL(fetype))
1936 /* if this is an interrupt service routine then
1937 save acc, b, dpl, dph */
1938 if (IS_ISR(sym->etype)) {
1941 /* PENDING: callee-save etc */
1943 /* If BC or DE are used, then push */
1944 _G.stack.pushed_bc = 0;
1945 _G.stack.pushed_de = 0;
1946 _G.stack.param_offset = 0;
1947 if (sym->regsUsed) {
1949 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1950 if (bitVectBitValue(sym->regsUsed, i)) {
1954 _G.stack.pushed_bc = 1;
1959 _G.stack.pushed_de = 1;
1964 if (_G.stack.pushed_bc) {
1966 _G.stack.param_offset += 2;
1968 if (_G.stack.pushed_de) {
1970 _G.stack.param_offset += 2;
1974 /* adjust the stack for the function */
1975 _G.stack.last = sym->stack;
1978 emit2("!enterx", sym->stack);
1981 _G.stack.offset = sym->stack;
1984 /*-----------------------------------------------------------------*/
1985 /* genEndFunction - generates epilogue for functions */
1986 /*-----------------------------------------------------------------*/
1987 static void genEndFunction (iCode *ic)
1989 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1991 if (IS_ISR(sym->etype)) {
1995 if (SPEC_CRTCL(sym->etype))
1998 /* PENDING: calleeSave */
2000 /* if debug then send end of function */
2001 if (options.debug && currFunc) {
2003 emitcode("","C$%s$%d$%d$%d ==.",
2004 ic->filename,currFunc->lastLine,
2005 ic->level,ic->block);
2006 if (IS_STATIC(currFunc->etype))
2007 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2009 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2012 if (_G.stack.offset)
2013 emit2("!leavex", _G.stack.offset);
2017 if (_G.stack.pushed_de)
2019 if (_G.stack.pushed_bc)
2021 /* Both baned and non-banked just ret */
2024 /* PENDING: portability. */
2025 emit2("__%s_end:", sym->rname);
2027 _G.flush_statics = 1;
2028 _G.stack.pushed = 0;
2029 _G.stack.offset = 0;
2032 /*-----------------------------------------------------------------*/
2033 /* genRet - generate code for return statement */
2034 /*-----------------------------------------------------------------*/
2035 static void genRet (iCode *ic)
2038 /* Errk. This is a hack until I can figure out how
2039 to cause dehl to spill on a call */
2040 int size,offset = 0;
2042 /* if we have no return value then
2043 just generate the "ret" */
2047 /* we have something to return then
2048 move the return value into place */
2049 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2050 size = AOP_SIZE(IC_LEFT(ic));
2052 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2054 emitcode("ld", "de,%s", l);
2057 emitcode("ld", "hl,%s", l);
2061 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2062 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2063 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2067 l = aopGet(AOP(IC_LEFT(ic)),offset,
2069 if (strcmp(_fReturn[offset],l))
2070 emitcode("ld","%s,%s", _fReturn[offset++],l);
2074 freeAsmop (IC_LEFT(ic),NULL,ic);
2077 /* generate a jump to the return label
2078 if the next is not the return statement */
2079 if (!(ic->next && ic->next->op == LABEL &&
2080 IC_LABEL(ic->next) == returnLabel))
2082 emit2("jp !tlabel", returnLabel->key+100);
2085 /*-----------------------------------------------------------------*/
2086 /* genLabel - generates a label */
2087 /*-----------------------------------------------------------------*/
2088 static void genLabel (iCode *ic)
2090 /* special case never generate */
2091 if (IC_LABEL(ic) == entryLabel)
2094 emitLabel(IC_LABEL(ic)->key+100);
2097 /*-----------------------------------------------------------------*/
2098 /* genGoto - generates a ljmp */
2099 /*-----------------------------------------------------------------*/
2100 static void genGoto (iCode *ic)
2102 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2105 /*-----------------------------------------------------------------*/
2106 /* genPlusIncr :- does addition with increment if possible */
2107 /*-----------------------------------------------------------------*/
2108 static bool genPlusIncr (iCode *ic)
2110 unsigned int icount ;
2111 unsigned int size = getDataSize(IC_RESULT(ic));
2112 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2114 /* will try to generate an increment */
2115 /* if the right side is not a literal
2117 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2120 emitcode("", "; genPlusIncr");
2122 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2124 /* If result is a pair */
2125 if (resultId != PAIR_INVALID) {
2126 if (isLitWord(AOP(IC_LEFT(ic)))) {
2127 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2130 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2131 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2132 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2138 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2141 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2142 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2145 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2150 /* if the literal value of the right hand side
2151 is greater than 4 then it is not worth it */
2155 /* if increment 16 bits in register */
2156 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2161 symbol *tlbl = NULL;
2162 tlbl = newiTempLabel(NULL);
2164 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2166 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2169 emitLabel(tlbl->key+100);
2173 /* if the sizes are greater than 1 then we cannot */
2174 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2175 AOP_SIZE(IC_LEFT(ic)) > 1 )
2178 /* we can if the aops of the left & result match or
2179 if they are in registers and the registers are the
2181 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2183 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2190 /*-----------------------------------------------------------------*/
2191 /* outBitAcc - output a bit in acc */
2192 /*-----------------------------------------------------------------*/
2193 void outBitAcc(operand *result)
2195 symbol *tlbl = newiTempLabel(NULL);
2196 /* if the result is a bit */
2197 if (AOP_TYPE(result) == AOP_CRY){
2201 emit2("!shortjp z,!tlabel", tlbl->key+100);
2203 emitLabel(tlbl->key+100);
2208 /*-----------------------------------------------------------------*/
2209 /* genPlus - generates code for addition */
2210 /*-----------------------------------------------------------------*/
2211 static void genPlus (iCode *ic)
2213 int size, offset = 0;
2215 /* special cases :- */
2217 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2218 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2219 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2221 /* Swap the left and right operands if:
2223 if literal, literal on the right or
2224 if left requires ACC or right is already
2227 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2228 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2229 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2230 operand *t = IC_RIGHT(ic);
2231 IC_RIGHT(ic) = IC_LEFT(ic);
2235 /* if both left & right are in bit
2237 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2238 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2243 /* if left in bit space & right literal */
2244 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2245 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2246 /* Can happen I guess */
2250 /* if I can do an increment instead
2251 of add then GOOD for ME */
2252 if (genPlusIncr (ic) == TRUE)
2255 emit2("; genPlusIncr failed");
2257 size = getDataSize(IC_RESULT(ic));
2259 /* Special case when left and right are constant */
2260 if (isPair(AOP(IC_RESULT(ic)))) {
2263 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2264 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2265 if (left && right) {
2269 sprintf(buffer, "#(%s + %s)", left, right);
2270 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2275 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2276 /* Fetch into HL then do the add */
2278 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2279 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2284 ld hl,sp+n trashes C so we cant afford to do it during an
2285 add with stack based varibles. Worst case is:
2298 So you cant afford to load up hl if either left, right, or result
2299 is on the stack (*sigh*) The alt is:
2307 Combinations in here are:
2308 * If left or right are in bc then the loss is small - trap later
2309 * If the result is in bc then the loss is also small
2312 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2313 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2314 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2315 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2316 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2317 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2318 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2319 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2320 /* Swap left and right */
2321 operand *t = IC_RIGHT(ic);
2322 IC_RIGHT(ic) = IC_LEFT(ic);
2325 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2326 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2330 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2331 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2334 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2337 else if (size == 4) {
2338 emit2("; WARNING: This add is probably broken.\n");
2344 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2345 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2348 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2351 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2353 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2356 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2359 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2361 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2365 freeAsmop(IC_LEFT(ic),NULL,ic);
2366 freeAsmop(IC_RIGHT(ic),NULL,ic);
2367 freeAsmop(IC_RESULT(ic),NULL,ic);
2371 /*-----------------------------------------------------------------*/
2372 /* genMinusDec :- does subtraction with deccrement if possible */
2373 /*-----------------------------------------------------------------*/
2374 static bool genMinusDec (iCode *ic)
2376 unsigned int icount ;
2377 unsigned int size = getDataSize(IC_RESULT(ic));
2379 /* will try to generate an increment */
2380 /* if the right side is not a literal we cannot */
2381 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2384 /* if the literal value of the right hand side
2385 is greater than 4 then it is not worth it */
2386 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2389 size = getDataSize(IC_RESULT(ic));
2392 /* if increment 16 bits in register */
2393 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2396 symbol *tlbl = newiTempLabel(NULL);
2397 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2398 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2400 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2404 emitLabel(tlbl->key+100);
2409 /* if decrement 16 bits in register */
2410 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2411 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2413 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2417 /* If result is a pair */
2418 if (isPair(AOP(IC_RESULT(ic)))) {
2419 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2420 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2422 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2426 /* if the sizes are greater than 1 then we cannot */
2427 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2428 AOP_SIZE(IC_LEFT(ic)) > 1 )
2431 /* we can if the aops of the left & result match or if they are in
2432 registers and the registers are the same */
2433 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2435 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2442 /*-----------------------------------------------------------------*/
2443 /* genMinus - generates code for subtraction */
2444 /*-----------------------------------------------------------------*/
2445 static void genMinus (iCode *ic)
2447 int size, offset = 0;
2448 unsigned long lit = 0L;
2450 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2451 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2452 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2454 /* special cases :- */
2455 /* if both left & right are in bit space */
2456 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2457 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2462 /* if I can do an decrement instead of subtract then GOOD for ME */
2463 if (genMinusDec (ic) == TRUE)
2466 size = getDataSize(IC_RESULT(ic));
2468 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2471 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2475 /* Same logic as genPlus */
2477 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2478 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2479 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2480 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2481 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2482 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2483 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2484 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2485 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2487 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2491 else if (right == PAIR_INVALID)
2493 else if (left == PAIR_INVALID)
2496 fetchPair(left, AOP(IC_LEFT(ic)));
2497 /* Order is important. Right may be HL */
2498 fetchPair(right, AOP(IC_RIGHT(ic)));
2500 emit2("ld a,%s", _pairs[left].l);
2501 emit2("sub a,%s", _pairs[right].l);
2503 emit2("ld a,%s", _pairs[left].h);
2504 emit2("sbc a,%s", _pairs[right].h);
2506 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2507 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2510 else if (size == 4) {
2511 emit2("; WARNING: This sub is probably broken.\n");
2516 /* if literal, add a,#-lit, else normal subb */
2518 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2519 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2521 emitcode("sub","a,%s",
2522 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2524 emitcode("sbc","a,%s",
2525 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2528 /* first add without previous c */
2530 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2532 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2534 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2537 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2538 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2539 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2543 freeAsmop(IC_LEFT(ic),NULL,ic);
2544 freeAsmop(IC_RIGHT(ic),NULL,ic);
2545 freeAsmop(IC_RESULT(ic),NULL,ic);
2548 /*-----------------------------------------------------------------*/
2549 /* genMult - generates code for multiplication */
2550 /*-----------------------------------------------------------------*/
2551 static void genMult (iCode *ic)
2553 /* Shouldn't occur - all done through function calls */
2557 /*-----------------------------------------------------------------*/
2558 /* genDiv - generates code for division */
2559 /*-----------------------------------------------------------------*/
2560 static void genDiv (iCode *ic)
2562 /* Shouldn't occur - all done through function calls */
2566 /*-----------------------------------------------------------------*/
2567 /* genMod - generates code for division */
2568 /*-----------------------------------------------------------------*/
2569 static void genMod (iCode *ic)
2571 /* Shouldn't occur - all done through function calls */
2575 /*-----------------------------------------------------------------*/
2576 /* genIfxJump :- will create a jump depending on the ifx */
2577 /*-----------------------------------------------------------------*/
2578 static void genIfxJump (iCode *ic, char *jval)
2583 /* if true label then we jump if condition
2587 if (!strcmp(jval, "a")) {
2590 else if (!strcmp(jval, "c")) {
2593 else if (!strcmp(jval, "nc")) {
2597 /* The buffer contains the bit on A that we should test */
2602 /* false label is present */
2603 jlbl = IC_FALSE(ic) ;
2604 if (!strcmp(jval, "a")) {
2607 else if (!strcmp(jval, "c")) {
2610 else if (!strcmp(jval, "nc")) {
2614 /* The buffer contains the bit on A that we should test */
2618 /* Z80 can do a conditional long jump */
2619 if (!strcmp(jval, "a")) {
2620 emitcode("or", "a,a");
2622 else if (!strcmp(jval, "c")) {
2624 else if (!strcmp(jval, "nc")) {
2627 emitcode("bit", "%s,a", jval);
2629 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2631 /* mark the icode as generated */
2635 static const char *_getPairIdName(PAIR_ID id)
2637 return _pairs[id].name;
2640 /** Generic compare for > or <
2642 static void genCmp (operand *left,operand *right,
2643 operand *result, iCode *ifx, int sign)
2645 int size, offset = 0 ;
2646 unsigned long lit = 0L;
2647 bool swap_sense = FALSE;
2649 /* if left & right are bit variables */
2650 if (AOP_TYPE(left) == AOP_CRY &&
2651 AOP_TYPE(right) == AOP_CRY ) {
2652 /* Cant happen on the Z80 */
2655 /* subtract right from left if at the
2656 end the carry flag is set then we know that
2657 left is greater than right */
2658 size = max(AOP_SIZE(left),AOP_SIZE(right));
2660 /* if unsigned char cmp with lit, just compare */
2662 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2663 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2665 emit2("xor a,!immedbyte", 0x80);
2666 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2669 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2674 If the left or the right is a lit:
2675 Load -lit into HL, add to right via, check sense.
2677 if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
2678 PAIR_ID id = PAIR_DE;
2679 asmop *lit = AOP(right);
2680 asmop *op = AOP(left);
2683 if (AOP_TYPE(left) == AOP_LIT) {
2689 emit2("ld e,%s", aopGet(op, 0, 0));
2690 emit2("ld a,%s", aopGet(op, 1, 0));
2691 emit2("xor a,!immedbyte", 0x80);
2696 if (id == PAIR_INVALID) {
2697 fetchPair(PAIR_DE, op);
2702 emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
2703 emit2("add hl,%s", _getPairIdName(id));
2706 if(AOP_TYPE(right) == AOP_LIT) {
2707 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2708 /* optimize if(x < 0) or if(x >= 0) */
2711 /* No sign so it's always false */
2715 /* Just load in the top most bit */
2716 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2717 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2718 genIfxJump (ifx,"7");
2722 emitcode("rlc","a");
2728 /* First setup h and l contaning the top most bytes XORed */
2729 bool fDidXor = FALSE;
2730 if (AOP_TYPE(left) == AOP_LIT){
2731 unsigned long lit = (unsigned long)
2732 floatFromVal(AOP(left)->aopu.aop_lit);
2733 emit2("ld %s,!immedbyte", _fTmp[0],
2734 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2737 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2738 emit2("xor a,!immedbyte", 0x80);
2739 emitcode("ld", "%s,a", _fTmp[0]);
2742 if (AOP_TYPE(right) == AOP_LIT) {
2743 unsigned long lit = (unsigned long)
2744 floatFromVal(AOP(right)->aopu.aop_lit);
2745 emit2("ld %s,!immedbyte", _fTmp[1],
2746 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2749 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2750 emit2("xor a,!immedbyte", 0x80);
2751 emitcode("ld", "%s,a", _fTmp[1]);
2761 /* Do a long subtract */
2762 if (!sign || size ) {
2763 MOVA(aopGet(AOP(left),offset,FALSE));
2765 if (sign && size == 0) {
2766 emitcode("ld", "a,%s", _fTmp[0]);
2767 emitcode("sbc", "a,%s", _fTmp[1]);
2770 /* Subtract through, propagating the carry */
2771 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2778 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2779 outBitCLong(result, swap_sense);
2781 /* if the result is used in the next
2782 ifx conditional branch then generate
2783 code a little differently */
2785 genIfxJump(ifx, swap_sense ? "nc" : "c");
2787 outBitCLong(result, swap_sense);
2788 /* leave the result in acc */
2792 /*-----------------------------------------------------------------*/
2793 /* genCmpGt :- greater than comparison */
2794 /*-----------------------------------------------------------------*/
2795 static void genCmpGt (iCode *ic, iCode *ifx)
2797 operand *left, *right, *result;
2798 sym_link *letype , *retype;
2802 right= IC_RIGHT(ic);
2803 result = IC_RESULT(ic);
2805 letype = getSpec(operandType(left));
2806 retype =getSpec(operandType(right));
2807 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2808 /* assign the amsops */
2809 aopOp (left,ic,FALSE, FALSE);
2810 aopOp (right,ic,FALSE, FALSE);
2811 aopOp (result,ic,TRUE, FALSE);
2813 genCmp(right, left, result, ifx, sign);
2815 freeAsmop(left,NULL,ic);
2816 freeAsmop(right,NULL,ic);
2817 freeAsmop(result,NULL,ic);
2820 /*-----------------------------------------------------------------*/
2821 /* genCmpLt - less than comparisons */
2822 /*-----------------------------------------------------------------*/
2823 static void genCmpLt (iCode *ic, iCode *ifx)
2825 operand *left, *right, *result;
2826 sym_link *letype , *retype;
2830 right= IC_RIGHT(ic);
2831 result = IC_RESULT(ic);
2833 letype = getSpec(operandType(left));
2834 retype =getSpec(operandType(right));
2835 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2837 /* assign the amsops */
2838 aopOp (left,ic,FALSE, FALSE);
2839 aopOp (right,ic,FALSE, FALSE);
2840 aopOp (result,ic,TRUE, FALSE);
2842 genCmp(left, right, result, ifx, sign);
2844 freeAsmop(left,NULL,ic);
2845 freeAsmop(right,NULL,ic);
2846 freeAsmop(result,NULL,ic);
2849 /*-----------------------------------------------------------------*/
2850 /* gencjneshort - compare and jump if not equal */
2851 /*-----------------------------------------------------------------*/
2852 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2854 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2856 unsigned long lit = 0L;
2858 /* Swap the left and right if it makes the computation easier */
2859 if (AOP_TYPE(left) == AOP_LIT) {
2865 if(AOP_TYPE(right) == AOP_LIT)
2866 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2868 /* if the right side is a literal then anything goes */
2869 if (AOP_TYPE(right) == AOP_LIT &&
2870 AOP_TYPE(left) != AOP_DIR ) {
2872 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2877 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2881 emitcode("or", "a,a");
2883 emit2("jp nz,!tlabel", lbl->key+100);
2887 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2888 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2889 emitcode("or", "a,a");
2891 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2892 emit2("jp nz,!tlabel", lbl->key+100);
2897 /* if the right side is in a register or in direct space or
2898 if the left is a pointer register & right is not */
2899 else if (AOP_TYPE(right) == AOP_REG ||
2900 AOP_TYPE(right) == AOP_DIR ||
2901 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2903 MOVA(aopGet(AOP(left),offset,FALSE));
2904 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2905 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2907 emit2("jp nz,!tlabel", lbl->key+100);
2909 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2910 emit2("jp nz,!tlabel", lbl->key+100);
2915 /* right is a pointer reg need both a & b */
2916 /* PENDING: is this required? */
2918 MOVA(aopGet(AOP(right),offset,FALSE));
2919 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2920 emit2("!shortjp nz,!tlabel", lbl->key+100);
2926 /*-----------------------------------------------------------------*/
2927 /* gencjne - compare and jump if not equal */
2928 /*-----------------------------------------------------------------*/
2929 static void gencjne(operand *left, operand *right, symbol *lbl)
2931 symbol *tlbl = newiTempLabel(NULL);
2933 gencjneshort(left, right, lbl);
2937 emit2("!shortjp !tlabel", tlbl->key+100);
2938 emitLabel(lbl->key+100);
2939 emitcode("xor","a,a");
2940 emitLabel(tlbl->key+100);
2943 /*-----------------------------------------------------------------*/
2944 /* genCmpEq - generates code for equal to */
2945 /*-----------------------------------------------------------------*/
2946 static void genCmpEq (iCode *ic, iCode *ifx)
2948 operand *left, *right, *result;
2950 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2951 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2952 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2954 /* Swap operands if it makes the operation easier. ie if:
2955 1. Left is a literal.
2957 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2958 operand *t = IC_RIGHT(ic);
2959 IC_RIGHT(ic) = IC_LEFT(ic);
2963 if (ifx && !AOP_SIZE(result)){
2965 /* if they are both bit variables */
2966 if (AOP_TYPE(left) == AOP_CRY &&
2967 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2970 tlbl = newiTempLabel(NULL);
2971 gencjneshort(left, right, tlbl);
2972 if ( IC_TRUE(ifx) ) {
2973 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2974 emitLabel(tlbl->key+100);
2976 /* PENDING: do this better */
2977 symbol *lbl = newiTempLabel(NULL);
2978 emit2("!shortjp !tlabel", lbl->key+100);
2979 emitLabel(tlbl->key+100);
2980 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2981 emitLabel(lbl->key+100);
2984 /* mark the icode as generated */
2989 /* if they are both bit variables */
2990 if (AOP_TYPE(left) == AOP_CRY &&
2991 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2994 gencjne(left,right,newiTempLabel(NULL));
2995 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2999 genIfxJump(ifx,"a");
3002 /* if the result is used in an arithmetic operation
3003 then put the result in place */
3004 if (AOP_TYPE(result) != AOP_CRY) {
3007 /* leave the result in acc */
3011 freeAsmop(left,NULL,ic);
3012 freeAsmop(right,NULL,ic);
3013 freeAsmop(result,NULL,ic);
3016 /*-----------------------------------------------------------------*/
3017 /* ifxForOp - returns the icode containing the ifx for operand */
3018 /*-----------------------------------------------------------------*/
3019 static iCode *ifxForOp ( operand *op, iCode *ic )
3021 /* if true symbol then needs to be assigned */
3022 if (IS_TRUE_SYMOP(op))
3025 /* if this has register type condition and
3026 the next instruction is ifx with the same operand
3027 and live to of the operand is upto the ifx only then */
3029 ic->next->op == IFX &&
3030 IC_COND(ic->next)->key == op->key &&
3031 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3037 /*-----------------------------------------------------------------*/
3038 /* genAndOp - for && operation */
3039 /*-----------------------------------------------------------------*/
3040 static void genAndOp (iCode *ic)
3042 operand *left,*right, *result;
3045 /* note here that && operations that are in an if statement are
3046 taken away by backPatchLabels only those used in arthmetic
3047 operations remain */
3048 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3049 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3050 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3052 /* if both are bit variables */
3053 if (AOP_TYPE(left) == AOP_CRY &&
3054 AOP_TYPE(right) == AOP_CRY ) {
3057 tlbl = newiTempLabel(NULL);
3059 emit2("!shortjp z,!tlabel", tlbl->key+100);
3061 emitLabel(tlbl->key+100);
3065 freeAsmop(left,NULL,ic);
3066 freeAsmop(right,NULL,ic);
3067 freeAsmop(result,NULL,ic);
3070 /*-----------------------------------------------------------------*/
3071 /* genOrOp - for || operation */
3072 /*-----------------------------------------------------------------*/
3073 static void genOrOp (iCode *ic)
3075 operand *left,*right, *result;
3078 /* note here that || operations that are in an
3079 if statement are taken away by backPatchLabels
3080 only those used in arthmetic operations remain */
3081 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3082 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3083 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3085 /* if both are bit variables */
3086 if (AOP_TYPE(left) == AOP_CRY &&
3087 AOP_TYPE(right) == AOP_CRY ) {
3090 tlbl = newiTempLabel(NULL);
3092 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3094 emitLabel(tlbl->key+100);
3098 freeAsmop(left,NULL,ic);
3099 freeAsmop(right,NULL,ic);
3100 freeAsmop(result,NULL,ic);
3103 /*-----------------------------------------------------------------*/
3104 /* isLiteralBit - test if lit == 2^n */
3105 /*-----------------------------------------------------------------*/
3106 int isLiteralBit(unsigned long lit)
3108 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3109 0x100L,0x200L,0x400L,0x800L,
3110 0x1000L,0x2000L,0x4000L,0x8000L,
3111 0x10000L,0x20000L,0x40000L,0x80000L,
3112 0x100000L,0x200000L,0x400000L,0x800000L,
3113 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3114 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3117 for(idx = 0; idx < 32; idx++)
3123 /*-----------------------------------------------------------------*/
3124 /* jmpTrueOrFalse - */
3125 /*-----------------------------------------------------------------*/
3126 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3128 // ugly but optimized by peephole
3130 symbol *nlbl = newiTempLabel(NULL);
3131 emit2("jp !tlabel", nlbl->key+100);
3132 emitLabel(tlbl->key+100);
3133 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3134 emitLabel(nlbl->key+100);
3137 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3138 emitLabel(tlbl->key+100);
3143 /*-----------------------------------------------------------------*/
3144 /* genAnd - code for and */
3145 /*-----------------------------------------------------------------*/
3146 static void genAnd (iCode *ic, iCode *ifx)
3148 operand *left, *right, *result;
3150 unsigned long lit = 0L;
3153 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3154 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3155 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3158 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3160 AOP_TYPE(left), AOP_TYPE(right));
3161 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3163 AOP_SIZE(left), AOP_SIZE(right));
3166 /* if left is a literal & right is not then exchange them */
3167 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3168 AOP_NEEDSACC(left)) {
3169 operand *tmp = right ;
3174 /* if result = right then exchange them */
3175 if(sameRegs(AOP(result),AOP(right))){
3176 operand *tmp = right ;
3181 /* if right is bit then exchange them */
3182 if (AOP_TYPE(right) == AOP_CRY &&
3183 AOP_TYPE(left) != AOP_CRY){
3184 operand *tmp = right ;
3188 if(AOP_TYPE(right) == AOP_LIT)
3189 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3191 size = AOP_SIZE(result);
3193 if (AOP_TYPE(left) == AOP_CRY){
3198 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3199 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3200 if((AOP_TYPE(right) == AOP_LIT) &&
3201 (AOP_TYPE(result) == AOP_CRY) &&
3202 (AOP_TYPE(left) != AOP_CRY)) {
3203 int posbit = isLiteralBit(lit);
3207 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3211 emitcode("mov","c,acc.%d",posbit&0x07);
3216 sprintf(buffer, "%d", posbit&0x07);
3217 genIfxJump(ifx, buffer);
3225 symbol *tlbl = newiTempLabel(NULL);
3226 int sizel = AOP_SIZE(left);
3229 emitcode("setb","c");
3232 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3233 MOVA( aopGet(AOP(left),offset,FALSE));
3235 if((posbit = isLiteralBit(bytelit)) != 0) {
3237 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3240 if(bytelit != 0x0FFL)
3241 emitcode("and","a,%s",
3242 aopGet(AOP(right),offset,FALSE));
3246 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3251 // bit = left & literal
3253 emitcode("clr","c");
3254 emit2("!tlabeldef", tlbl->key+100);
3256 // if(left & literal)
3259 jmpTrueOrFalse(ifx, tlbl);
3267 /* if left is same as result */
3268 if(sameRegs(AOP(result),AOP(left))){
3269 for(;size--; offset++) {
3270 if(AOP_TYPE(right) == AOP_LIT){
3271 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3275 aopPut(AOP(result),zero,offset);
3277 MOVA(aopGet(AOP(left),offset,FALSE));
3278 emitcode("and","a,%s",
3279 aopGet(AOP(right),offset,FALSE));
3280 aopPut(AOP(left), "a", offset);
3285 if (AOP_TYPE(left) == AOP_ACC) {
3289 MOVA(aopGet(AOP(left),offset,FALSE));
3290 emitcode("and","a,%s",
3291 aopGet(AOP(right),offset,FALSE));
3292 aopPut(AOP(left), "a", offset);
3297 // left & result in different registers
3298 if(AOP_TYPE(result) == AOP_CRY){
3301 for(;(size--);offset++) {
3303 // result = left & right
3304 if(AOP_TYPE(right) == AOP_LIT){
3305 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3307 aopGet(AOP(left),offset,FALSE),
3310 } else if(bytelit == 0){
3311 aopPut(AOP(result),zero,offset);
3315 // faster than result <- left, anl result,right
3316 // and better if result is SFR
3317 if (AOP_TYPE(left) == AOP_ACC)
3318 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3320 MOVA(aopGet(AOP(left),offset,FALSE));
3321 emitcode("and","a,%s",
3322 aopGet(AOP(right),offset,FALSE));
3324 aopPut(AOP(result),"a",offset);
3331 freeAsmop(left,NULL,ic);
3332 freeAsmop(right,NULL,ic);
3333 freeAsmop(result,NULL,ic);
3336 /*-----------------------------------------------------------------*/
3337 /* genOr - code for or */
3338 /*-----------------------------------------------------------------*/
3339 static void genOr (iCode *ic, iCode *ifx)
3341 operand *left, *right, *result;
3343 unsigned long lit = 0L;
3345 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3346 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3347 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3350 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3352 AOP_TYPE(left), AOP_TYPE(right));
3353 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3355 AOP_SIZE(left), AOP_SIZE(right));
3358 /* if left is a literal & right is not then exchange them */
3359 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3360 AOP_NEEDSACC(left)) {
3361 operand *tmp = right ;
3366 /* if result = right then exchange them */
3367 if(sameRegs(AOP(result),AOP(right))){
3368 operand *tmp = right ;
3373 /* if right is bit then exchange them */
3374 if (AOP_TYPE(right) == AOP_CRY &&
3375 AOP_TYPE(left) != AOP_CRY){
3376 operand *tmp = right ;
3380 if(AOP_TYPE(right) == AOP_LIT)
3381 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3383 size = AOP_SIZE(result);
3385 if (AOP_TYPE(left) == AOP_CRY){
3390 if((AOP_TYPE(right) == AOP_LIT) &&
3391 (AOP_TYPE(result) == AOP_CRY) &&
3392 (AOP_TYPE(left) != AOP_CRY)){
3397 /* if left is same as result */
3398 if(sameRegs(AOP(result),AOP(left))){
3399 for(;size--; offset++) {
3400 if(AOP_TYPE(right) == AOP_LIT){
3401 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3404 MOVA(aopGet(AOP(left),offset,FALSE));
3405 emitcode("or","a,%s",
3406 aopGet(AOP(right),offset,FALSE));
3407 aopPut(AOP(result),"a", offset);
3410 if (AOP_TYPE(left) == AOP_ACC)
3411 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3413 MOVA(aopGet(AOP(left),offset,FALSE));
3414 emitcode("or","a,%s",
3415 aopGet(AOP(right),offset,FALSE));
3416 aopPut(AOP(result),"a", offset);
3421 // left & result in different registers
3422 if(AOP_TYPE(result) == AOP_CRY){
3424 } else for(;(size--);offset++){
3426 // result = left & right
3427 if(AOP_TYPE(right) == AOP_LIT){
3428 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3430 aopGet(AOP(left),offset,FALSE),
3435 // faster than result <- left, anl result,right
3436 // and better if result is SFR
3437 if (AOP_TYPE(left) == AOP_ACC)
3438 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3440 MOVA(aopGet(AOP(left),offset,FALSE));
3441 emitcode("or","a,%s",
3442 aopGet(AOP(right),offset,FALSE));
3444 aopPut(AOP(result),"a",offset);
3445 /* PENDING: something weird is going on here. Add exception. */
3446 if (AOP_TYPE(result) == AOP_ACC)
3452 freeAsmop(left,NULL,ic);
3453 freeAsmop(right,NULL,ic);
3454 freeAsmop(result,NULL,ic);
3457 /*-----------------------------------------------------------------*/
3458 /* genXor - code for xclusive or */
3459 /*-----------------------------------------------------------------*/
3460 static void genXor (iCode *ic, iCode *ifx)
3462 operand *left, *right, *result;
3464 unsigned long lit = 0L;
3466 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3467 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3468 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3470 /* if left is a literal & right is not then exchange them */
3471 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3472 AOP_NEEDSACC(left)) {
3473 operand *tmp = right ;
3478 /* if result = right then exchange them */
3479 if(sameRegs(AOP(result),AOP(right))){
3480 operand *tmp = right ;
3485 /* if right is bit then exchange them */
3486 if (AOP_TYPE(right) == AOP_CRY &&
3487 AOP_TYPE(left) != AOP_CRY){
3488 operand *tmp = right ;
3492 if(AOP_TYPE(right) == AOP_LIT)
3493 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3495 size = AOP_SIZE(result);
3497 if (AOP_TYPE(left) == AOP_CRY){
3502 if((AOP_TYPE(right) == AOP_LIT) &&
3503 (AOP_TYPE(result) == AOP_CRY) &&
3504 (AOP_TYPE(left) != AOP_CRY)){
3509 /* if left is same as result */
3510 if(sameRegs(AOP(result),AOP(left))){
3511 for(;size--; offset++) {
3512 if(AOP_TYPE(right) == AOP_LIT){
3513 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3516 MOVA(aopGet(AOP(right),offset,FALSE));
3517 emitcode("xor","a,%s",
3518 aopGet(AOP(left),offset,FALSE));
3519 aopPut(AOP(result),"a",0);
3522 if (AOP_TYPE(left) == AOP_ACC)
3523 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3525 MOVA(aopGet(AOP(right),offset,FALSE));
3526 emitcode("xor","a,%s",
3527 aopGet(AOP(left),offset,FALSE));
3528 aopPut(AOP(result),"a",0);
3533 // left & result in different registers
3534 if(AOP_TYPE(result) == AOP_CRY){
3536 } else for(;(size--);offset++){
3538 // result = left & right
3539 if(AOP_TYPE(right) == AOP_LIT){
3540 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3542 aopGet(AOP(left),offset,FALSE),
3547 // faster than result <- left, anl result,right
3548 // and better if result is SFR
3549 if (AOP_TYPE(left) == AOP_ACC)
3550 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3552 MOVA(aopGet(AOP(right),offset,FALSE));
3553 emitcode("xor","a,%s",
3554 aopGet(AOP(left),offset,FALSE));
3555 aopPut(AOP(result),"a",0);
3557 aopPut(AOP(result),"a",offset);
3562 freeAsmop(left,NULL,ic);
3563 freeAsmop(right,NULL,ic);
3564 freeAsmop(result,NULL,ic);
3567 /*-----------------------------------------------------------------*/
3568 /* genInline - write the inline code out */
3569 /*-----------------------------------------------------------------*/
3570 static void genInline (iCode *ic)
3572 char buffer[MAX_INLINEASM];
3576 inLine += (!options.asmpeep);
3577 strcpy(buffer,IC_INLINE(ic));
3579 /* emit each line as a code */
3598 /* emitcode("",buffer); */
3599 inLine -= (!options.asmpeep);
3602 /*-----------------------------------------------------------------*/
3603 /* genRRC - rotate right with carry */
3604 /*-----------------------------------------------------------------*/
3605 static void genRRC (iCode *ic)
3610 /*-----------------------------------------------------------------*/
3611 /* genRLC - generate code for rotate left with carry */
3612 /*-----------------------------------------------------------------*/
3613 static void genRLC (iCode *ic)
3618 /*-----------------------------------------------------------------*/
3619 /* shiftR2Left2Result - shift right two bytes from left to result */
3620 /*-----------------------------------------------------------------*/
3621 static void shiftR2Left2Result (operand *left, int offl,
3622 operand *result, int offr,
3623 int shCount, int sign)
3625 movLeft2Result(left, offl, result, offr, 0);
3626 movLeft2Result(left, offl+1, result, offr+1, 0);
3632 /* if (AOP(result)->type == AOP_REG) {*/
3635 symbol *tlbl , *tlbl1;
3638 tlbl = newiTempLabel(NULL);
3639 tlbl1 = newiTempLabel(NULL);
3641 /* Left is already in result - so now do the shift */
3643 emit2("ld a,!immedbyte+1", shCount);
3644 emit2("!shortjp !tlabel", tlbl1->key+100);
3645 emitLabel(tlbl->key+100);
3648 emitcode("or", "a,a");
3651 l = aopGet(AOP(result), --offset, FALSE);
3652 emitcode("rr","%s", l);
3655 emitLabel(tlbl1->key+100);
3656 emitcode("dec", "a");
3657 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3662 /*-----------------------------------------------------------------*/
3663 /* shiftL2Left2Result - shift left two bytes from left to result */
3664 /*-----------------------------------------------------------------*/
3665 static void shiftL2Left2Result (operand *left, int offl,
3666 operand *result, int offr, int shCount)
3668 if(sameRegs(AOP(result), AOP(left)) &&
3669 ((offl + MSB16) == offr)){
3672 /* Copy left into result */
3673 movLeft2Result(left, offl, result, offr, 0);
3674 movLeft2Result(left, offl+1, result, offr+1, 0);
3676 /* PENDING: for now just see if it'll work. */
3677 /*if (AOP(result)->type == AOP_REG) { */
3681 symbol *tlbl , *tlbl1;
3684 tlbl = newiTempLabel(NULL);
3685 tlbl1 = newiTempLabel(NULL);
3687 /* Left is already in result - so now do the shift */
3689 emit2("ld a,!immedbyte+1", shCount);
3690 emit2("!shortjp !tlabel", tlbl1->key+100);
3691 emitLabel(tlbl->key+100);
3694 emitcode("or", "a,a");
3696 l = aopGet(AOP(result),offset++,FALSE);
3697 emitcode("rl","%s", l);
3700 emitLabel(tlbl1->key+100);
3701 emitcode("dec", "a");
3702 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3707 /*-----------------------------------------------------------------*/
3708 /* AccRol - rotate left accumulator by known count */
3709 /*-----------------------------------------------------------------*/
3710 static void AccRol (int shCount)
3712 shCount &= 0x0007; // shCount : 0..7
3749 /*-----------------------------------------------------------------*/
3750 /* AccLsh - left shift accumulator by known count */
3751 /*-----------------------------------------------------------------*/
3752 static void AccLsh (int shCount)
3756 emitcode("add","a,a");
3758 else if(shCount == 2) {
3759 emitcode("add","a,a");
3760 emitcode("add","a,a");
3762 /* rotate left accumulator */
3764 /* and kill the lower order bits */
3765 emit2("and a,!immedbyte", SLMask[shCount]);
3770 /*-----------------------------------------------------------------*/
3771 /* shiftL1Left2Result - shift left one byte from left to result */
3772 /*-----------------------------------------------------------------*/
3773 static void shiftL1Left2Result (operand *left, int offl,
3774 operand *result, int offr, int shCount)
3777 l = aopGet(AOP(left),offl,FALSE);
3779 /* shift left accumulator */
3781 aopPut(AOP(result),"a",offr);
3785 /*-----------------------------------------------------------------*/
3786 /* genlshTwo - left shift two bytes by known amount != 0 */
3787 /*-----------------------------------------------------------------*/
3788 static void genlshTwo (operand *result,operand *left, int shCount)
3790 int size = AOP_SIZE(result);
3794 /* if shCount >= 8 */
3799 movLeft2Result(left, LSB, result, MSB16, 0);
3800 aopPut(AOP(result),zero, 0);
3801 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3804 movLeft2Result(left, LSB, result, MSB16, 0);
3805 aopPut(AOP(result),zero, 0);
3809 aopPut(AOP(result),zero,LSB);
3812 /* 1 <= shCount <= 7 */
3818 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3823 /*-----------------------------------------------------------------*/
3824 /* genlshOne - left shift a one byte quantity by known count */
3825 /*-----------------------------------------------------------------*/
3826 static void genlshOne (operand *result, operand *left, int shCount)
3828 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3831 /*-----------------------------------------------------------------*/
3832 /* genLeftShiftLiteral - left shifting by known count */
3833 /*-----------------------------------------------------------------*/
3834 static void genLeftShiftLiteral (operand *left,
3839 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3842 freeAsmop(right,NULL,ic);
3844 aopOp(left,ic,FALSE, FALSE);
3845 aopOp(result,ic,FALSE, FALSE);
3847 size = getSize(operandType(result));
3850 emitcode("; shift left ","result %d, left %d",size,
3854 /* I suppose that the left size >= result size */
3859 else if(shCount >= (size * 8))
3861 aopPut(AOP(result),zero,size);
3865 genlshOne (result,left,shCount);
3868 genlshTwo (result,left,shCount);
3877 freeAsmop(left,NULL,ic);
3878 freeAsmop(result,NULL,ic);
3881 /*-----------------------------------------------------------------*/
3882 /* genLeftShift - generates code for left shifting */
3883 /*-----------------------------------------------------------------*/
3884 static void genLeftShift (iCode *ic)
3888 symbol *tlbl , *tlbl1;
3889 operand *left,*right, *result;
3891 right = IC_RIGHT(ic);
3893 result = IC_RESULT(ic);
3895 aopOp(right,ic,FALSE, FALSE);
3897 /* if the shift count is known then do it
3898 as efficiently as possible */
3899 if (AOP_TYPE(right) == AOP_LIT) {
3900 genLeftShiftLiteral (left,right,result,ic);
3904 /* shift count is unknown then we have to form a loop get the loop
3905 count in B : Note: we take only the lower order byte since
3906 shifting more that 32 bits make no sense anyway, ( the largest
3907 size of an object can be only 32 bits ) */
3908 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3909 emitcode("inc","a");
3910 freeAsmop (right,NULL,ic);
3911 aopOp(left,ic,FALSE, FALSE);
3912 aopOp(result,ic,FALSE, FALSE);
3914 /* now move the left to the result if they are not the
3917 if (!sameRegs(AOP(left),AOP(result))) {
3919 size = AOP_SIZE(result);
3922 l = aopGet(AOP(left),offset,FALSE);
3923 aopPut(AOP(result),l,offset);
3928 size = AOP_SIZE(result);
3931 l = aopGet(AOP(left),offset,FALSE);
3932 aopPut(AOP(result),l,offset);
3938 tlbl = newiTempLabel(NULL);
3939 size = AOP_SIZE(result);
3941 tlbl1 = newiTempLabel(NULL);
3943 emit2("!shortjp !tlabel", tlbl1->key+100);
3944 emitLabel(tlbl->key+100);
3945 l = aopGet(AOP(result),offset,FALSE);
3946 emitcode("or", "a,a");
3948 l = aopGet(AOP(result),offset++,FALSE);
3949 emitcode("rl","%s", l);
3951 emitLabel(tlbl1->key+100);
3952 emitcode("dec", "a");
3953 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3955 freeAsmop(left,NULL,ic);
3956 freeAsmop(result,NULL,ic);
3959 /*-----------------------------------------------------------------*/
3960 /* genrshOne - left shift two bytes by known amount != 0 */
3961 /*-----------------------------------------------------------------*/
3962 static void genrshOne (operand *result,operand *left, int shCount)
3965 int size = AOP_SIZE(result);
3971 l = aopGet(AOP(left),0,FALSE);
3972 if (AOP(result)->type == AOP_REG) {
3973 aopPut(AOP(result), l, 0);
3974 l = aopGet(AOP(result), 0, FALSE);
3976 emitcode("srl", "%s", l);
3981 emitcode("srl", "a");
3983 aopPut(AOP(result),"a",0);
3987 /*-----------------------------------------------------------------*/
3988 /* AccRsh - right shift accumulator by known count */
3989 /*-----------------------------------------------------------------*/
3990 static void AccRsh (int shCount)
3993 /* rotate right accumulator */
3994 AccRol(8 - shCount);
3995 /* and kill the higher order bits */
3996 emit2("and a,!immedbyte", SRMask[shCount]);
4000 /*-----------------------------------------------------------------*/
4001 /* shiftR1Left2Result - shift right one byte from left to result */
4002 /*-----------------------------------------------------------------*/
4003 static void shiftR1Left2Result (operand *left, int offl,
4004 operand *result, int offr,
4005 int shCount, int sign)
4007 MOVA(aopGet(AOP(left),offl,FALSE));
4014 aopPut(AOP(result),"a",offr);
4017 /*-----------------------------------------------------------------*/
4018 /* genrshTwo - right shift two bytes by known amount != 0 */
4019 /*-----------------------------------------------------------------*/
4020 static void genrshTwo (operand *result,operand *left,
4021 int shCount, int sign)
4023 /* if shCount >= 8 */
4027 shiftR1Left2Result(left, MSB16, result, LSB,
4031 movLeft2Result(left, MSB16, result, LSB, sign);
4033 aopPut(AOP(result),zero,1);
4035 /* 1 <= shCount <= 7 */
4037 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
4041 /*-----------------------------------------------------------------*/
4042 /* genRightShiftLiteral - left shifting by known count */
4043 /*-----------------------------------------------------------------*/
4044 static void genRightShiftLiteral (operand *left,
4049 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4052 freeAsmop(right,NULL,ic);
4054 aopOp(left,ic,FALSE, FALSE);
4055 aopOp(result,ic,FALSE, FALSE);
4057 size = getSize(operandType(result));
4059 emitcode("; shift right ","result %d, left %d",size,
4062 /* I suppose that the left size >= result size */
4067 else if(shCount >= (size * 8))
4069 aopPut(AOP(result),zero,size);
4073 genrshOne(result, left, shCount);
4076 /* PENDING: sign support */
4077 genrshTwo(result, left, shCount, FALSE);
4086 freeAsmop(left,NULL,ic);
4087 freeAsmop(result,NULL,ic);
4090 /*-----------------------------------------------------------------*/
4091 /* genRightShift - generate code for right shifting */
4092 /*-----------------------------------------------------------------*/
4093 static void genRightShift (iCode *ic)
4095 operand *right, *left, *result;
4097 int size, offset, first = 1;
4101 symbol *tlbl, *tlbl1 ;
4103 /* if signed then we do it the hard way preserve the
4104 sign bit moving it inwards */
4105 retype = getSpec(operandType(IC_RESULT(ic)));
4107 is_signed = !SPEC_USIGN(retype);
4109 /* signed & unsigned types are treated the same : i.e. the
4110 signed is NOT propagated inwards : quoting from the
4111 ANSI - standard : "for E1 >> E2, is equivalent to division
4112 by 2**E2 if unsigned or if it has a non-negative value,
4113 otherwise the result is implementation defined ", MY definition
4114 is that the sign does not get propagated */
4116 right = IC_RIGHT(ic);
4118 result = IC_RESULT(ic);
4120 aopOp(right,ic,FALSE, FALSE);
4122 /* if the shift count is known then do it
4123 as efficiently as possible */
4124 if (AOP_TYPE(right) == AOP_LIT) {
4125 genRightShiftLiteral(left,right,result,ic);
4129 aopOp(left,ic,FALSE, FALSE);
4130 aopOp(result,ic,FALSE, FALSE);
4132 /* now move the left to the result if they are not the
4134 if (!sameRegs(AOP(left),AOP(result)) &&
4135 AOP_SIZE(result) > 1) {
4137 size = AOP_SIZE(result);
4140 l = aopGet(AOP(left),offset,FALSE);
4141 aopPut(AOP(result),l,offset);
4146 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4147 emitcode("inc","a");
4148 freeAsmop (right, NULL, ic);
4150 tlbl = newiTempLabel(NULL);
4151 tlbl1= newiTempLabel(NULL);
4152 size = AOP_SIZE(result);
4155 emit2("!shortjp !tlabel", tlbl1->key+100);
4156 emitLabel(tlbl->key+100);
4158 l = aopGet(AOP(result),offset--,FALSE);
4161 emitcode("sra", "%s", l);
4163 emitcode("srl", "%s", l);
4167 emitcode("rr", "%s", l);
4169 emitLabel(tlbl1->key+100);
4170 emitcode("dec", "a");
4171 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4173 freeAsmop(left,NULL,ic);
4174 freeAsmop(result,NULL,ic);
4177 /*-----------------------------------------------------------------*/
4178 /* genGenPointerGet - get value from generic pointer space */
4179 /*-----------------------------------------------------------------*/
4180 static void genGenPointerGet (operand *left,
4181 operand *result, iCode *ic)
4184 sym_link *retype = getSpec(operandType(result));
4190 aopOp(left,ic,FALSE, FALSE);
4191 aopOp(result,ic,FALSE, FALSE);
4193 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4195 if (isPtrPair(AOP(left)))
4197 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4198 aopPut(AOP(result), buffer, 0);
4201 emit2("ld a,!*pair", getPairName(AOP(left)));
4202 aopPut(AOP(result),"a", 0);
4204 freeAsmop(left,NULL,ic);
4208 /* For now we always load into IY */
4209 /* if this is remateriazable */
4210 fetchPair(pair, AOP(left));
4212 /* so iy now contains the address */
4213 freeAsmop(left,NULL,ic);
4215 /* if bit then unpack */
4216 if (IS_BITVAR(retype)) {
4220 size = AOP_SIZE(result);
4224 /* PENDING: make this better */
4225 if (!IS_GB && AOP(result)->type == AOP_REG) {
4226 aopPut(AOP(result), "!*hl", offset++);
4229 emit2("ld a,!*pair", _pairs[pair].name);
4230 aopPut(AOP(result),"a",offset++);
4233 emit2("inc %s", _pairs[pair].name);
4234 _G.pairs[pair].offset++;
4240 freeAsmop(result,NULL,ic);
4243 /*-----------------------------------------------------------------*/
4244 /* genPointerGet - generate code for pointer get */
4245 /*-----------------------------------------------------------------*/
4246 static void genPointerGet (iCode *ic)
4248 operand *left, *result ;
4249 sym_link *type, *etype;
4252 result = IC_RESULT(ic) ;
4254 /* depending on the type of pointer we need to
4255 move it to the correct pointer register */
4256 type = operandType(left);
4257 etype = getSpec(type);
4259 genGenPointerGet (left,result,ic);
4262 bool isRegOrLit(asmop *aop)
4264 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4269 /*-----------------------------------------------------------------*/
4270 /* genGenPointerSet - stores the value into a pointer location */
4271 /*-----------------------------------------------------------------*/
4272 static void genGenPointerSet (operand *right,
4273 operand *result, iCode *ic)
4276 sym_link *retype = getSpec(operandType(right));
4277 PAIR_ID pairId = PAIR_HL;
4279 aopOp(result,ic,FALSE, FALSE);
4280 aopOp(right,ic,FALSE, FALSE);
4285 /* Handle the exceptions first */
4286 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4288 char *l = aopGet(AOP(right), 0, FALSE);
4289 const char *pair = getPairName(AOP(result));
4290 if (canAssignToPtr(l) && isPtr(pair)) {
4291 emit2("ld !*pair,%s", pair, l);
4295 emit2("ld !*pair,a", pair);
4300 /* if the operand is already in dptr
4301 then we do nothing else we move the value to dptr */
4302 if (AOP_TYPE(result) != AOP_STR) {
4303 fetchPair(pairId, AOP(result));
4305 /* so hl know contains the address */
4306 freeAsmop(result,NULL,ic);
4308 /* if bit then unpack */
4309 if (IS_BITVAR(retype)) {
4313 size = AOP_SIZE(right);
4317 char *l = aopGet(AOP(right),offset,FALSE);
4318 if (isRegOrLit(AOP(right)) && !IS_GB) {
4319 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4323 emit2("ld !*pair,a", _pairs[pairId].name);
4326 emitcode("inc", _pairs[pairId].name);
4327 _G.pairs[pairId].offset++;
4333 freeAsmop(right,NULL,ic);
4336 /*-----------------------------------------------------------------*/
4337 /* genPointerSet - stores the value into a pointer location */
4338 /*-----------------------------------------------------------------*/
4339 static void genPointerSet (iCode *ic)
4341 operand *right, *result ;
4342 sym_link *type, *etype;
4344 right = IC_RIGHT(ic);
4345 result = IC_RESULT(ic) ;
4347 /* depending on the type of pointer we need to
4348 move it to the correct pointer register */
4349 type = operandType(result);
4350 etype = getSpec(type);
4352 genGenPointerSet (right,result,ic);
4355 /*-----------------------------------------------------------------*/
4356 /* genIfx - generate code for Ifx statement */
4357 /*-----------------------------------------------------------------*/
4358 static void genIfx (iCode *ic, iCode *popIc)
4360 operand *cond = IC_COND(ic);
4363 aopOp(cond,ic,FALSE, TRUE);
4365 /* get the value into acc */
4366 if (AOP_TYPE(cond) != AOP_CRY)
4370 /* the result is now in the accumulator */
4371 freeAsmop(cond,NULL,ic);
4373 /* if there was something to be popped then do it */
4377 /* if the condition is a bit variable */
4378 if (isbit && IS_ITEMP(cond) &&
4380 genIfxJump(ic,SPIL_LOC(cond)->rname);
4382 if (isbit && !IS_ITEMP(cond))
4383 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4390 /*-----------------------------------------------------------------*/
4391 /* genAddrOf - generates code for address of */
4392 /*-----------------------------------------------------------------*/
4393 static void genAddrOf (iCode *ic)
4395 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4397 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4399 /* if the operand is on the stack then we
4400 need to get the stack offset of this
4405 if (sym->stack <= 0) {
4406 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4409 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4411 emitcode("ld", "d,h");
4412 emitcode("ld", "e,l");
4415 emit2("ld de,!hashedstr", sym->rname);
4417 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4418 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4423 /* if it has an offset then we need to compute it */
4425 emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
4427 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4428 emitcode("add", "hl,sp");
4431 emitcode("ld", "hl,#%s", sym->rname);
4433 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4434 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4436 freeAsmop(IC_RESULT(ic),NULL,ic);
4439 /*-----------------------------------------------------------------*/
4440 /* genAssign - generate code for assignment */
4441 /*-----------------------------------------------------------------*/
4442 static void genAssign (iCode *ic)
4444 operand *result, *right;
4446 unsigned long lit = 0L;
4448 result = IC_RESULT(ic);
4449 right = IC_RIGHT(ic) ;
4452 /* Dont bother assigning if they are the same */
4453 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4454 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4459 aopOp(right,ic,FALSE, FALSE);
4460 aopOp(result,ic,TRUE, FALSE);
4462 /* if they are the same registers */
4463 if (sameRegs(AOP(right),AOP(result))) {
4464 emitcode("", "; (registers are the same)");
4468 /* if the result is a bit */
4469 if (AOP_TYPE(result) == AOP_CRY) {
4474 size = AOP_SIZE(result);
4477 if(AOP_TYPE(right) == AOP_LIT)
4478 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4479 if (isPair(AOP(result))) {
4480 fetchPair(getPairId(AOP(result)), AOP(right));
4482 else if((size > 1) &&
4483 (AOP_TYPE(result) != AOP_REG) &&
4484 (AOP_TYPE(right) == AOP_LIT) &&
4485 !IS_FLOAT(operandType(right)) &&
4487 bool fXored = FALSE;
4489 /* Work from the top down.
4490 Done this way so that we can use the cached copy of 0
4491 in A for a fast clear */
4493 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4494 if (!fXored && size>1) {
4495 emitcode("xor", "a,a");
4499 aopPut(AOP(result),"a",offset);
4502 aopPut(AOP(result), zero, offset);
4507 aopGet(AOP(right),offset,FALSE),
4512 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4513 /* Special case. Load into a and d, then load out. */
4514 MOVA(aopGet(AOP(right), 0, FALSE));
4515 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4516 aopPut(AOP(result), "a", 0);
4517 aopPut(AOP(result), "e", 1);
4520 /* PENDING: do this check better */
4521 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4522 MOVA(aopGet(AOP(right), offset, FALSE));
4523 aopPut(AOP(result), "a", offset);
4527 aopGet(AOP(right),offset,FALSE),
4534 freeAsmop(right,NULL,ic);
4535 freeAsmop(result,NULL,ic);
4538 /*-----------------------------------------------------------------*/
4539 /* genJumpTab - genrates code for jump table */
4540 /*-----------------------------------------------------------------*/
4541 static void genJumpTab (iCode *ic)
4546 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4547 /* get the condition into accumulator */
4548 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4550 emitcode("push", "de");
4551 emitcode("ld", "e,%s", l);
4552 emit2("ld d,!zero");
4553 jtab = newiTempLabel(NULL);
4555 emit2("ld hl,!immed!tlabel", jtab->key+100);
4556 emitcode("add", "hl,de");
4557 emitcode("add", "hl,de");
4558 emitcode("add", "hl,de");
4559 freeAsmop(IC_JTCOND(ic),NULL,ic);
4561 emitcode("pop", "de");
4563 emitLabel(jtab->key+100);
4564 /* now generate the jump labels */
4565 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4566 jtab = setNextItem(IC_JTLABELS(ic)))
4567 emit2("jp !tlabel", jtab->key+100);
4570 /*-----------------------------------------------------------------*/
4571 /* genCast - gen code for casting */
4572 /*-----------------------------------------------------------------*/
4573 static void genCast (iCode *ic)
4575 operand *result = IC_RESULT(ic);
4576 sym_link *ctype = operandType(IC_LEFT(ic));
4577 operand *right = IC_RIGHT(ic);
4580 /* if they are equivalent then do nothing */
4581 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4584 aopOp(right,ic,FALSE, FALSE);
4585 aopOp(result,ic,FALSE, FALSE);
4587 /* if the result is a bit */
4588 if (AOP_TYPE(result) == AOP_CRY) {
4592 /* if they are the same size : or less */
4593 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4595 /* if they are in the same place */
4596 if (sameRegs(AOP(right),AOP(result)))
4599 /* if they in different places then copy */
4600 size = AOP_SIZE(result);
4604 aopGet(AOP(right),offset,FALSE),
4611 /* PENDING: should be OK. */
4613 /* if the result is of type pointer */
4614 if (IS_PTR(ctype)) {
4619 /* so we now know that the size of destination is greater
4620 than the size of the source */
4621 /* we move to result for the size of source */
4622 size = AOP_SIZE(right);
4626 aopGet(AOP(right),offset,FALSE),
4631 /* now depending on the sign of the destination */
4632 size = AOP_SIZE(result) - AOP_SIZE(right);
4633 /* Unsigned or not an integral type - right fill with zeros */
4634 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4636 aopPut(AOP(result),zero,offset++);
4638 /* we need to extend the sign :{ */
4639 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4642 emitcode("", "; genCast: sign extend untested.");
4643 emitcode("rla", "");
4644 emitcode("sbc", "a,a");
4646 aopPut(AOP(result),"a",offset++);
4650 freeAsmop(right, NULL, ic);
4651 freeAsmop(result, NULL, ic);
4654 /*-----------------------------------------------------------------*/
4655 /* genReceive - generate code for a receive iCode */
4656 /*-----------------------------------------------------------------*/
4657 static void genReceive (iCode *ic)
4659 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4660 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4661 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4665 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4667 assignResultValue(IC_RESULT(ic));
4670 freeAsmop(IC_RESULT(ic),NULL,ic);
4673 /*-----------------------------------------------------------------*/
4674 /* genZ80Code - generate code for Z80 based controllers */
4675 /*-----------------------------------------------------------------*/
4676 void genZ80Code (iCode *lic)
4683 _fReturn = _gbz80_return;
4684 _fTmp = _gbz80_return;
4687 _fReturn = _z80_return;
4688 _fTmp = _z80_return;
4690 tsprintf(zero, "!zero");
4692 lineHead = lineCurr = NULL;
4694 /* if debug information required */
4695 if (options.debug && currFunc) {
4696 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4698 if (IS_STATIC(currFunc->etype))
4699 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4701 emitcode("","G$%s$0$0 ==.",currFunc->name);
4704 /* stack pointer name */
4708 for (ic = lic ; ic ; ic = ic->next ) {
4710 if ( cln != ic->lineno ) {
4711 if ( options.debug ) {
4713 emitcode("","C$%s$%d$%d$%d ==.",
4714 ic->filename,ic->lineno,
4715 ic->level,ic->block);
4718 emitcode(";","%s %d",ic->filename,ic->lineno);
4721 /* if the result is marked as
4722 spilt and rematerializable or code for
4723 this has already been generated then
4725 if (resultRemat(ic) || ic->generated )
4728 /* depending on the operation */
4731 emitcode("", "; genNot");
4736 emitcode("", "; genCpl");
4741 emitcode("", "; genUminus");
4746 emitcode("", "; genIpush");
4751 /* IPOP happens only when trying to restore a
4752 spilt live range, if there is an ifx statement
4753 following this pop then the if statement might
4754 be using some of the registers being popped which
4755 would destory the contents of the register so
4756 we need to check for this condition and handle it */
4758 ic->next->op == IFX &&
4759 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4760 emitcode("", "; genIfx");
4761 genIfx (ic->next,ic);
4764 emitcode("", "; genIpop");
4770 emitcode("", "; genCall");
4775 emitcode("", "; genPcall");
4780 emitcode("", "; genFunction");
4785 emitcode("", "; genEndFunction");
4786 genEndFunction (ic);
4790 emitcode("", "; genRet");
4795 emitcode("", "; genLabel");
4800 emitcode("", "; genGoto");
4805 emitcode("", "; genPlus");
4810 emitcode("", "; genMinus");
4815 emitcode("", "; genMult");
4820 emitcode("", "; genDiv");
4825 emitcode("", "; genMod");
4830 emitcode("", "; genCmpGt");
4831 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4835 emitcode("", "; genCmpLt");
4836 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4843 /* note these two are xlated by algebraic equivalence
4844 during parsing SDCC.y */
4845 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4846 "got '>=' or '<=' shouldn't have come here");
4850 emitcode("", "; genCmpEq");
4851 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4855 emitcode("", "; genAndOp");
4860 emitcode("", "; genOrOp");
4865 emitcode("", "; genXor");
4866 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4870 emitcode("", "; genOr");
4871 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4875 emitcode("", "; genAnd");
4876 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4880 emitcode("", "; genInline");
4885 emitcode("", "; genRRC");
4890 emitcode("", "; genRLC");
4895 emitcode("", "; genHBIT");
4899 emitcode("", "; genLeftShift");
4904 emitcode("", "; genRightShift");
4908 case GET_VALUE_AT_ADDRESS:
4909 emitcode("", "; genPointerGet");
4915 if (POINTER_SET(ic)) {
4916 emitcode("", "; genAssign (pointer)");
4920 emitcode("", "; genAssign");
4926 emitcode("", "; genIfx");
4931 emitcode("", "; genAddrOf");
4936 emitcode("", "; genJumpTab");
4941 emitcode("", "; genCast");
4946 emitcode("", "; genReceive");
4951 emitcode("", "; addSet");
4952 addSet(&sendSet,ic);
4957 /* piCode(ic,stdout); */
4963 /* now we are ready to call the
4964 peep hole optimizer */
4965 if (!options.nopeep)
4966 peepHole (&lineHead);
4968 /* This is unfortunate */
4969 /* now do the actual printing */
4971 FILE *fp = codeOutFile;
4972 if (isInHome() && codeOutFile == code->oFile)
4973 codeOutFile = home->oFile;
4974 printLine (lineHead, codeOutFile);
4975 if (_G.flush_statics) {
4977 _G.flush_statics = 0;