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 "SDCCpeeph.h"
62 /* this is the down and dirty file with all kinds of kludgy & hacky
63 stuff. This is what it is all about CODE GENERATION for a specific MCU.
64 Some of the routines may be reusable, will have to see */
67 static char *_z80_return[] = {"l", "h", "e", "d" };
68 static char *_gbz80_return[] = { "e", "d", "l", "h" };
69 static char **_fReturn;
75 static char *accUse[] = {"a" };
76 static char *hlUse[] = { "l", "h" };
82 extern int ptrRegReq ;
84 extern FILE *codeOutFile;
101 } _pairs[NUM_PAIRS] = {
106 { "iy", "iy.l?", "iy.h?" },
107 { "ix", "ix.l?", "ix.h?" }
110 #define RESULTONSTACK(x) \
111 (IC_RESULT(x) && IC_RESULT(x)->aop && \
112 IC_RESULT(x)->aop->type == AOP_STK )
114 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
115 #define CLRC emitcode("xor","a,a");
117 lineNode *lineHead = NULL;
118 lineNode *lineCurr = NULL;
120 static const unsigned char SLMask[] =
121 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
122 static const unsigned char SRMask[] =
123 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
156 static char *aopGet(asmop *aop, int offset, bool bit16);
158 static void _tidyUp(char *buf)
160 /* Clean up the line so that it is 'prettier' */
161 if (strchr(buf, ':')) {
162 /* Is a label - cant do anything */
165 /* Change the first (and probably only) ' ' to a tab so
177 static void emit2(const char *szFormat, ...)
182 va_start(ap, szFormat);
184 tvsprintf(buffer, szFormat, ap);
187 lineCurr = (lineCurr ?
188 connectLine(lineCurr,newLineNode(buffer)) :
189 (lineHead = newLineNode(buffer)));
191 lineCurr->isInline = inLine;
192 lineCurr->isDebug = debugLine;
195 /*-----------------------------------------------------------------*/
196 /* emitcode - writes the code into a file : for now it is simple */
197 /*-----------------------------------------------------------------*/
198 void emitcode (const char *inst, const char *fmt, ...)
201 char lb[MAX_INLINEASM];
207 sprintf(lb,"%s\t",inst);
208 vsprintf(lb+(strlen(lb)),fmt,ap);
212 while (isspace(*lbp)) lbp++;
215 lineCurr = (lineCurr ?
216 connectLine(lineCurr,newLineNode(lb)) :
217 (lineHead = newLineNode(lb)));
218 lineCurr->isInline = inLine;
219 lineCurr->isDebug = debugLine;
236 emitcode("ld", "sp,ix");
237 emitcode("pop", "ix");
238 emitcode("pop", "de");
243 const char *getPairName(asmop *aop)
245 if (aop->type == AOP_REG) {
246 switch (aop->aopu.aop_reg[0]->rIdx) {
258 else if (aop->type == AOP_STR) {
259 switch (*aop->aopu.aop_str[0]) {
275 static PAIR_ID getPairId(asmop *aop)
277 if (aop->size == 2) {
278 if (aop->type == AOP_REG) {
279 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
282 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
285 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
289 if (aop->type == AOP_STR) {
290 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
293 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
296 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
304 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
305 bool isPair(asmop *aop)
307 return (getPairId(aop) != PAIR_INVALID);
310 bool isPtrPair(asmop *aop)
312 PAIR_ID pairId = getPairId(aop);
322 /** Push a register pair onto the stack */
323 void genPairPush(asmop *aop)
325 emitcode("push", "%s", getPairName(aop));
329 /*-----------------------------------------------------------------*/
330 /* newAsmop - creates a new asmOp */
331 /*-----------------------------------------------------------------*/
332 static asmop *newAsmop (short type)
336 ALLOC(aop,sizeof(asmop));
341 /*-----------------------------------------------------------------*/
342 /* aopForSym - for a true symbol */
343 /*-----------------------------------------------------------------*/
344 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
353 space = SPEC_OCLS(sym->etype);
355 /* if already has one */
359 /* Assign depending on the storage class */
360 if (sym->onStack || sym->iaccess) {
361 emitcode("", "; AOP_STK for %s", sym->rname);
362 sym->aop = aop = newAsmop(AOP_STK);
363 aop->size = getSize(sym->type);
364 aop->aopu.aop_stk = sym->stack;
368 /* special case for a function */
369 if (IS_FUNC(sym->type)) {
370 sym->aop = aop = newAsmop(AOP_IMMD);
371 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
372 strcpy(aop->aopu.aop_immd,sym->rname);
378 /* if it is in direct space */
379 if (IN_REGSP(space) && !requires_a) {
380 sym->aop = aop = newAsmop (AOP_SFR);
381 aop->aopu.aop_dir = sym->rname ;
382 aop->size = getSize(sym->type);
383 emitcode("", "; AOP_SFR for %s", sym->rname);
388 /* only remaining is far space */
389 /* in which case DPTR gets the address */
391 emitcode("", "; AOP_HL for %s", sym->rname);
392 sym->aop = aop = newAsmop(AOP_HL);
395 sym->aop = aop = newAsmop(AOP_IY);
397 aop->size = getSize(sym->type);
398 aop->aopu.aop_dir = sym->rname;
400 /* if it is in code space */
401 if (IN_CODESPACE(space))
407 /*-----------------------------------------------------------------*/
408 /* aopForRemat - rematerialzes an object */
409 /*-----------------------------------------------------------------*/
410 static asmop *aopForRemat (symbol *sym)
413 iCode *ic = sym->rematiCode;
414 asmop *aop = newAsmop(AOP_IMMD);
417 /* if plus or minus print the right hand side */
418 if (ic->op == '+' || ic->op == '-') {
419 /* PENDING: for re-target */
420 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
423 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
426 /* we reached the end */
427 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
431 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
432 strcpy(aop->aopu.aop_immd,buffer);
436 /*-----------------------------------------------------------------*/
437 /* regsInCommon - two operands have some registers in common */
438 /*-----------------------------------------------------------------*/
439 bool regsInCommon (operand *op1, operand *op2)
444 /* if they have registers in common */
445 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
448 sym1 = OP_SYMBOL(op1);
449 sym2 = OP_SYMBOL(op2);
451 if (sym1->nRegs == 0 || sym2->nRegs == 0)
454 for (i = 0 ; i < sym1->nRegs ; i++) {
459 for (j = 0 ; j < sym2->nRegs ;j++ ) {
463 if (sym2->regs[j] == sym1->regs[i])
471 /*-----------------------------------------------------------------*/
472 /* operandsEqu - equivalent */
473 /*-----------------------------------------------------------------*/
474 bool operandsEqu ( operand *op1, operand *op2)
478 /* if they not symbols */
479 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
482 sym1 = OP_SYMBOL(op1);
483 sym2 = OP_SYMBOL(op2);
485 /* if both are itemps & one is spilt
486 and the other is not then false */
487 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
488 sym1->isspilt != sym2->isspilt )
491 /* if they are the same */
495 if (strcmp(sym1->rname,sym2->rname) == 0)
499 /* if left is a tmp & right is not */
503 (sym1->usl.spillLoc == sym2))
510 (sym2->usl.spillLoc == sym1))
516 /*-----------------------------------------------------------------*/
517 /* sameRegs - two asmops have the same registers */
518 /*-----------------------------------------------------------------*/
519 bool sameRegs (asmop *aop1, asmop *aop2 )
523 if (aop1->type == AOP_SFR ||
524 aop2->type == AOP_SFR)
530 if (aop1->type != AOP_REG ||
531 aop2->type != AOP_REG )
534 if (aop1->size != aop2->size)
537 for (i = 0 ; i < aop1->size ; i++ )
538 if (aop1->aopu.aop_reg[i] !=
539 aop2->aopu.aop_reg[i] )
545 /*-----------------------------------------------------------------*/
546 /* aopOp - allocates an asmop for an operand : */
547 /*-----------------------------------------------------------------*/
548 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
557 /* if this a literal */
558 if (IS_OP_LITERAL(op)) {
559 op->aop = aop = newAsmop(AOP_LIT);
560 aop->aopu.aop_lit = op->operand.valOperand;
561 aop->size = getSize(operandType(op));
565 /* if already has a asmop then continue */
569 /* if the underlying symbol has a aop */
570 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
571 op->aop = OP_SYMBOL(op)->aop;
575 /* if this is a true symbol */
576 if (IS_TRUE_SYMOP(op)) {
577 op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
581 /* this is a temporary : this has
587 e) can be a return use only */
591 /* if the type is a conditional */
592 if (sym->regType == REG_CND) {
593 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
598 /* if it is spilt then two situations
600 b) has a spill location */
601 if (sym->isspilt || sym->nRegs == 0) {
602 /* rematerialize it NOW */
604 sym->aop = op->aop = aop =
606 aop->size = getSize(sym->type);
612 if (sym->accuse == ACCUSE_A) {
613 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
614 aop->size = getSize(sym->type);
615 for ( i = 0 ; i < 2 ; i++ )
616 aop->aopu.aop_str[i] = accUse[i];
618 else if (sym->accuse == ACCUSE_HL) {
620 aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
621 aop->size = getSize(sym->type);
622 for ( i = 0 ; i < 2 ; i++ )
623 aop->aopu.aop_str[i] = hlUse[i];
632 aop = op->aop = sym->aop = newAsmop(AOP_STR);
633 aop->size = getSize(sym->type);
634 for ( i = 0 ; i < 4 ; i++ )
635 aop->aopu.aop_str[i] = _fReturn[i];
639 /* else spill location */
640 sym->aop = op->aop = aop =
641 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
642 aop->size = getSize(sym->type);
646 /* must be in a register */
647 sym->aop = op->aop = aop = newAsmop(AOP_REG);
648 aop->size = sym->nRegs;
649 for ( i = 0 ; i < sym->nRegs ;i++)
650 aop->aopu.aop_reg[i] = sym->regs[i];
653 /*-----------------------------------------------------------------*/
654 /* freeAsmop - free up the asmop given to an operand */
655 /*----------------------------------------------------------------*/
656 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
674 /* all other cases just dealloc */
678 OP_SYMBOL(op)->aop = NULL;
679 /* if the symbol has a spill */
681 SPIL_LOC(op)->aop = NULL;
686 bool isLitWord(asmop *aop)
688 /* if (aop->size != 2)
699 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
705 if (aop->size != 2 && aop->type != AOP_HL)
708 /* depending on type */
713 /* PENDING: for re-target */
715 tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
717 tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
718 ALLOC_ATOMIC(rs,strlen(s)+1);
722 value * val = aop->aopu.aop_lit;
723 /* if it is a float then it gets tricky */
724 /* otherwise it is fairly simple */
725 if (!IS_FLOAT(val->type)) {
726 unsigned long v = floatFromVal(val);
732 tsprintf(buffer, "!immedword", v);
734 tsprintf(buffer, "!constword", v);
735 ALLOC_ATOMIC(rs,strlen(buffer)+1);
736 return strcpy (rs,buffer);
741 convertFloat(&f, floatFromVal(val));
743 tsprintf(buffer, "!immedword", f.w[offset/2]);
745 tsprintf(buffer, "!constword", f.w[offset/2]);
746 ALLOC_ATOMIC(rs,strlen(buffer)+1);
747 return strcpy (rs,buffer);
755 char *aopGetWord(asmop *aop, int offset)
757 return aopGetLitWordLong(aop, offset, TRUE);
760 bool isPtr(const char *s)
762 if (!strcmp(s, "hl"))
764 if (!strcmp(s, "ix"))
766 if (!strcmp(s, "iy"))
771 static void adjustPair(const char *pair, int *pold, int new)
775 while (*pold < new) {
776 emitcode("inc", "%s", pair);
779 while (*pold > new) {
780 emitcode("dec", "%s", pair);
785 static void spillPair(PAIR_ID pairId)
787 _G.pairs[pairId].last_type = AOP_INVALID;
788 _G.pairs[pairId].lit = NULL;
791 static void spillCached(void)
797 static bool requiresHL(asmop *aop)
808 static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
811 value * val = aop->aopu.aop_lit;
813 wassert(aop->type == AOP_LIT);
814 wassert(!IS_FLOAT(val->type));
816 v = floatFromVal(val);
824 tsprintf(buffer, "!immedword", v);
825 return gc_strdup(buffer);
828 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
831 const char *pair = _pairs[pairId].name;
832 l = aopGetLitWordLong(left, 0, FALSE);
836 if (pairId == PAIR_HL || pairId == PAIR_IY) {
837 if (_G.pairs[pairId].last_type == left->type) {
838 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
839 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
840 adjustPair(pair, &_G.pairs[pairId].offset, offset);
843 if (pairId == PAIR_IY && abs(offset)<127) {
849 _G.pairs[pairId].last_type = left->type;
850 _G.pairs[pairId].lit = gc_strdup(l);
851 _G.pairs[pairId].offset = offset;
853 if (IS_GB && pairId == PAIR_DE && 0) {
854 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
855 if (abs(_G.pairs[pairId].offset - offset) < 3) {
856 adjustPair(pair, &_G.pairs[pairId].offset, offset);
860 _G.pairs[pairId].last_type = left->type;
861 _G.pairs[pairId].lit = gc_strdup(l);
862 _G.pairs[pairId].offset = offset;
864 /* Both a lit on the right and a true symbol on the left */
866 emit2("ld %s,!hashedstr + %u", pair, l, offset);
868 emit2("ld %s,!hashedstr", pair, l);
871 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
873 /* if this is remateriazable */
874 if (isLitWord(aop)) {
875 fetchLitPair(pairId, aop, offset);
877 else { /* we need to get it byte by byte */
878 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
879 aopGet(aop, offset, FALSE);
883 emit2("ld h,!immedbyte", 0);
891 emit2("; WARNING: mlh woosed out. This code is invalid.");
894 else if (IS_Z80 && aop->type == AOP_IY) {
895 /* Instead of fetching relative to IY, just grab directly
896 from the address IY refers to */
897 char *l = aopGetLitWordLong(aop, offset, FALSE);
899 emit2("ld %s,(%s)", _pairs[pairId].name, l);
902 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
903 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
905 /* PENDING: check? */
906 if (pairId == PAIR_HL)
911 static void fetchPair(PAIR_ID pairId, asmop *aop)
913 fetchPairLong(pairId, aop, 0);
916 static void fetchHL(asmop *aop)
918 fetchPair(PAIR_HL, aop);
921 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
923 assert(pairId == PAIR_HL || pairId == PAIR_IY);
927 fetchLitPair(pairId, aop, 0);
930 fetchLitPair(pairId, aop, offset);
931 _G.pairs[pairId].offset = offset;
934 /* Doesnt include _G.stack.pushed */
935 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
936 if (aop->aopu.aop_stk > 0) {
937 abso += _G.stack.param_offset;
939 assert(pairId == PAIR_HL);
940 /* In some cases we can still inc or dec hl */
941 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
942 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
945 emit2("!ldahlsp", abso +_G.stack.pushed);
947 _G.pairs[pairId].offset = abso;
953 _G.pairs[pairId].last_type = aop->type;
956 static void emitLabel(int key)
958 emit2("!tlabeldef", key);
962 /*-----------------------------------------------------------------*/
963 /* aopGet - for fetching value of the aop */
964 /*-----------------------------------------------------------------*/
965 static char *aopGet(asmop *aop, int offset, bool bit16)
970 /* offset is greater than size then zero */
971 /* PENDING: this seems a bit screwed in some pointer cases. */
972 if (offset > (aop->size - 1) &&
973 aop->type != AOP_LIT)
976 /* depending on type */
979 /* PENDING: re-target */
981 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
985 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
988 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
991 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
996 ALLOC_ATOMIC(rs,strlen(s)+1);
1002 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1004 ALLOC_ATOMIC(rs,strlen(s)+1);
1010 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1012 ALLOC_ATOMIC(rs,strlen(s)+1);
1017 return aop->aopu.aop_reg[offset]->name;
1021 setupPair(PAIR_HL, aop, offset);
1022 tsprintf(s, "!*hl");
1023 return gc_strdup(s);
1027 setupPair(PAIR_IY, aop, offset);
1028 tsprintf(s,"!*iyx", offset);
1029 ALLOC_ATOMIC(rs,strlen(s)+1);
1035 setupPair(PAIR_HL, aop, offset);
1036 tsprintf(s, "!*hl");
1039 if (aop->aopu.aop_stk >= 0)
1040 offset += _G.stack.param_offset;
1041 tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
1043 ALLOC_ATOMIC(rs,strlen(s)+1);
1057 wassert(offset < 2);
1058 return aop->aopu.aop_str[offset];
1061 return aopLiteral (aop->aopu.aop_lit,offset);
1065 return aop->aopu.aop_str[offset];
1069 wassertl(0, "aopget got unsupported aop->type");
1073 bool isRegString(const char *s)
1075 if (!strcmp(s, "b") ||
1086 bool isConstant(const char *s)
1088 /* This is a bit of a hack... */
1089 return (*s == '#' || *s == '$');
1092 bool canAssignToPtr(const char *s)
1101 /*-----------------------------------------------------------------*/
1102 /* aopPut - puts a string for a aop */
1103 /*-----------------------------------------------------------------*/
1104 static void aopPut (asmop *aop, const char *s, int offset)
1106 if (aop->size && offset > ( aop->size - 1)) {
1107 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1108 "aopPut got offset > aop->size");
1112 /* will assign value to value */
1113 /* depending on where it is ofcourse */
1114 switch (aop->type) {
1119 emitcode("ld", "a,%s", s);
1120 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1126 emitcode("ld", "a,%s", s);
1127 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1131 if (!strcmp(s, "!*hl"))
1132 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1135 aop->aopu.aop_reg[offset]->name, s);
1140 setupPair(PAIR_IY, aop, offset);
1141 if (!canAssignToPtr(s)) {
1142 emit2("ld a,%s", s);
1143 emit2("ld !*iyx,a", offset);
1146 emit2("ld !*iyx,%s", offset, s);
1151 /* PENDING: for re-target */
1152 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1156 setupPair(PAIR_HL, aop, offset);
1158 emit2("ld !*hl,%s", s);
1163 /* PENDING: re-target */
1164 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1168 setupPair(PAIR_HL, aop, offset);
1169 if (!canAssignToPtr(s)) {
1170 emit2("ld a,%s", s);
1174 emit2("ld !*hl,%s", s);
1177 if (aop->aopu.aop_stk >= 0)
1178 offset += _G.stack.param_offset;
1179 if (!canAssignToPtr(s)) {
1180 emit2("ld a,%s", s);
1181 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1184 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1189 /* if bit variable */
1190 if (!aop->aopu.aop_dir) {
1194 /* In bit space but not in C - cant happen */
1201 if (strcmp(aop->aopu.aop_str[offset],s)) {
1202 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1208 if (!offset && (strcmp(s,"acc") == 0))
1212 emitcode("", "; Error aopPut AOP_ACC");
1215 if (strcmp(aop->aopu.aop_str[offset],s))
1216 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1221 wassert(offset < 2);
1222 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1227 "aopPut got unsupported aop->type");
1232 #define AOP(op) op->aop
1233 #define AOP_TYPE(op) AOP(op)->type
1234 #define AOP_SIZE(op) AOP(op)->size
1235 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1237 static void commitPair(asmop *aop, PAIR_ID id)
1239 if (id == PAIR_HL && requiresHL(aop)) {
1242 aopPut(aop, "a", 0);
1243 aopPut(aop, "d", 1);
1246 aopPut(aop, _pairs[id].l, 0);
1247 aopPut(aop, _pairs[id].h, 1);
1251 /*-----------------------------------------------------------------*/
1252 /* getDataSize - get the operand data size */
1253 /*-----------------------------------------------------------------*/
1254 int getDataSize(operand *op)
1257 size = AOP_SIZE(op);
1265 /*-----------------------------------------------------------------*/
1266 /* movLeft2Result - move byte from left to result */
1267 /*-----------------------------------------------------------------*/
1268 static void movLeft2Result (operand *left, int offl,
1269 operand *result, int offr, int sign)
1272 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1273 l = aopGet(AOP(left),offl,FALSE);
1276 aopPut(AOP(result),l,offr);
1285 /** Put Acc into a register set
1287 void outAcc(operand *result)
1290 size = getDataSize(result);
1292 aopPut(AOP(result),"a",0);
1295 /* unsigned or positive */
1297 aopPut(AOP(result), zero, offset++);
1302 /** Take the value in carry and put it into a register
1304 void outBitCLong(operand *result, bool swap_sense)
1306 /* if the result is bit */
1307 if (AOP_TYPE(result) == AOP_CRY) {
1308 emitcode("", "; Note: outBitC form 1");
1309 aopPut(AOP(result),"blah",0);
1312 emit2("ld a,!zero");
1315 emit2("xor a,!immedbyte", 1);
1320 void outBitC(operand *result)
1322 outBitCLong(result, FALSE);
1325 /*-----------------------------------------------------------------*/
1326 /* toBoolean - emit code for orl a,operator(sizeop) */
1327 /*-----------------------------------------------------------------*/
1328 void toBoolean(operand *oper)
1330 int size = AOP_SIZE(oper);
1333 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1336 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1339 if (AOP(oper)->type != AOP_ACC) {
1341 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1346 /*-----------------------------------------------------------------*/
1347 /* genNot - generate code for ! operation */
1348 /*-----------------------------------------------------------------*/
1349 static void genNot (iCode *ic)
1351 link *optype = operandType(IC_LEFT(ic));
1353 /* assign asmOps to operand & result */
1354 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1355 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1357 /* if in bit space then a special case */
1358 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1362 /* if type float then do float */
1363 if (IS_FLOAT(optype)) {
1367 toBoolean(IC_LEFT(ic));
1372 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1373 emit2("sub a,!one");
1374 outBitC(IC_RESULT(ic));
1376 /* release the aops */
1377 freeAsmop(IC_LEFT(ic),NULL,ic);
1378 freeAsmop(IC_RESULT(ic),NULL,ic);
1381 /*-----------------------------------------------------------------*/
1382 /* genCpl - generate code for complement */
1383 /*-----------------------------------------------------------------*/
1384 static void genCpl (iCode *ic)
1390 /* assign asmOps to operand & result */
1391 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1392 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1394 /* if both are in bit space then
1396 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1397 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1401 size = AOP_SIZE(IC_RESULT(ic));
1403 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1406 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1409 /* release the aops */
1410 freeAsmop(IC_LEFT(ic),NULL,ic);
1411 freeAsmop(IC_RESULT(ic),NULL,ic);
1414 /*-----------------------------------------------------------------*/
1415 /* genUminus - unary minus code generation */
1416 /*-----------------------------------------------------------------*/
1417 static void genUminus (iCode *ic)
1420 link *optype, *rtype;
1423 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1424 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1426 /* if both in bit space then special
1428 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1429 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1434 optype = operandType(IC_LEFT(ic));
1435 rtype = operandType(IC_RESULT(ic));
1437 /* if float then do float stuff */
1438 if (IS_FLOAT(optype)) {
1443 /* otherwise subtract from zero */
1444 size = AOP_SIZE(IC_LEFT(ic));
1448 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1449 emit2("ld a,!zero");
1450 emit2("sbc a,%s",l);
1451 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1454 /* if any remaining bytes in the result */
1455 /* we just need to propagate the sign */
1456 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1460 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1464 /* release the aops */
1465 freeAsmop(IC_LEFT(ic),NULL,ic);
1466 freeAsmop(IC_RESULT(ic),NULL,ic);
1469 static void _push(PAIR_ID pairId)
1471 emit2("push %s", _pairs[pairId].name);
1472 _G.stack.pushed += 2;
1475 static void _pop(PAIR_ID pairId)
1477 emit2("pop %s", _pairs[pairId].name);
1478 _G.stack.pushed -= 2;
1482 /*-----------------------------------------------------------------*/
1483 /* assignResultValue - */
1484 /*-----------------------------------------------------------------*/
1485 void assignResultValue(operand * oper)
1487 int size = AOP_SIZE(oper);
1491 topInA = requiresHL(AOP(oper));
1497 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1498 /* We do it the hard way here. */
1500 aopPut(AOP(oper), _fReturn[0], 0);
1501 aopPut(AOP(oper), _fReturn[1], 1);
1502 emitcode("pop", "de");
1503 _G.stack.pushed -= 2;
1504 aopPut(AOP(oper), _fReturn[0], 2);
1505 aopPut(AOP(oper), _fReturn[1], 3);
1509 aopPut(AOP(oper), _fReturn[size], size);
1514 /*-----------------------------------------------------------------*/
1515 /* genIpush - genrate code for pushing this gets a little complex */
1516 /*-----------------------------------------------------------------*/
1517 static void genIpush (iCode *ic)
1519 int size, offset = 0 ;
1522 /* if this is not a parm push : ie. it is spill push
1523 and spill push is always done on the local stack */
1524 if (!ic->parmPush) {
1525 /* and the item is spilt then do nothing */
1526 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1529 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1530 size = AOP_SIZE(IC_LEFT(ic));
1531 /* push it on the stack */
1532 if (isPair(AOP(IC_LEFT(ic)))) {
1533 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1534 _G.stack.pushed += 2;
1539 /* Simple for now - load into A and PUSH AF */
1540 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1541 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1543 emit2("ld a,(%s)", l);
1546 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1547 emit2("ld a,%s", l);
1557 /* Hmmm... what about saving the currently used registers
1560 /* then do the push */
1561 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1563 size = AOP_SIZE(IC_LEFT(ic));
1565 if (isPair(AOP(IC_LEFT(ic)))) {
1567 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1571 fetchHL(AOP(IC_LEFT(ic)));
1572 emitcode("push", "hl");
1574 _G.stack.pushed += 2;
1578 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1579 emitcode("push", "hl");
1581 _G.stack.pushed += 2;
1582 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1583 emitcode("push", "hl");
1585 _G.stack.pushed += 2;
1590 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1591 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1593 emit2("ld a,(%s)", l);
1596 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1597 emit2("ld a,%s", l);
1599 emitcode("push", "af");
1600 emitcode("inc", "sp");
1605 freeAsmop(IC_LEFT(ic),NULL,ic);
1608 /*-----------------------------------------------------------------*/
1609 /* genIpop - recover the registers: can happen only for spilling */
1610 /*-----------------------------------------------------------------*/
1611 static void genIpop (iCode *ic)
1616 /* if the temp was not pushed then */
1617 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1620 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1621 size = AOP_SIZE(IC_LEFT(ic));
1623 if (isPair(AOP(IC_LEFT(ic)))) {
1624 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1628 emitcode("dec", "sp");
1629 emitcode("pop", "hl");
1631 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1635 freeAsmop(IC_LEFT(ic),NULL,ic);
1638 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1643 if (bitVectBitValue(ic->rUsed, D_IDX))
1645 if (bitVectBitValue(ic->rUsed, E_IDX))
1654 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1658 symbol *sym = OP_SYMBOL(op);
1660 if (sym->isspilt || sym->nRegs == 0)
1663 aopOp(op, ic, FALSE, FALSE);
1666 if (aop->type == AOP_REG) {
1668 for (i=0; i < aop->size; i++) {
1669 if (pairId == PAIR_DE) {
1670 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1671 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1673 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1682 freeAsmop(IC_LEFT(ic),NULL,ic);
1686 /* This is quite unfortunate */
1687 static void setArea(int inHome)
1689 static int lastArea = 0;
1692 if (_G.in_home != inHome) {
1694 const char *sz = port->mem.code_name;
1695 port->mem.code_name = "HOME";
1696 emit2("!area", CODE_NAME);
1697 port->mem.code_name = sz;
1700 emit2("!area", CODE_NAME);*/
1701 _G.in_home = inHome;
1705 static bool isInHome(void)
1710 /** Emit the code for a call statement
1712 static void emitCall(iCode *ic, bool ispcall)
1715 link *detype = getSpec(operandType(IC_LEFT(ic)));
1717 /* if caller saves & we have not saved then */
1718 if (!ic->regsSaved) {
1722 /* if send set is not empty then assign */
1726 int n = elementsInSet(sendSet);
1727 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1728 /* Only push de if it is used and if it's not used
1729 in the return value */
1730 /* Panic if partly used */
1731 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1732 emit2("; Warning: de crossover");
1734 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1741 if (IS_Z80 && n == 2 ) {
1742 /* Want to load HL first, then DE as HL may = DE */
1743 sic = setFirstItem(sendSet);
1744 sic = setNextItem(sendSet);
1745 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1746 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1748 freeAsmop (IC_LEFT(sic),NULL,sic);
1749 sic = setFirstItem(sendSet);
1750 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1751 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1753 freeAsmop (IC_LEFT(sic),NULL,sic);
1756 for (sic = setFirstItem(sendSet) ; sic ;
1757 sic = setNextItem(sendSet)) {
1759 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1760 size = AOP_SIZE(IC_LEFT(sic));
1762 /* Always send in pairs */
1765 if (IS_Z80 && n == 1)
1766 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1768 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1771 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1774 /* Send set too big */
1778 freeAsmop (IC_LEFT(sic),NULL,sic);
1787 if (IS_BANKEDCALL(detype)) {
1788 werror(W_INDIR_BANKED);
1790 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1792 if (isLitWord(AOP(IC_LEFT(ic)))) {
1793 emitcode("", "; Special case where the pCall is to a constant");
1794 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1797 symbol *rlbl = newiTempLabel(NULL);
1799 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1800 emitcode("push", "hl");
1801 _G.stack.pushed += 2;
1803 fetchHL(AOP(IC_LEFT(ic)));
1805 emit2("!tlabeldef", (rlbl->key+100));
1806 _G.stack.pushed -= 2;
1808 freeAsmop(IC_LEFT(ic),NULL,ic);
1811 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1812 OP_SYMBOL(IC_LEFT(ic))->rname :
1813 OP_SYMBOL(IC_LEFT(ic))->name;
1814 if (IS_BANKEDCALL(detype)) {
1815 emit2("call banked_call");
1816 emit2("!dws", name);
1817 emit2("!dw !bankimmeds", name);
1821 emit2("call %s", name);
1826 /* if we need assign a result value */
1827 if ((IS_ITEMP(IC_RESULT(ic)) &&
1828 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1829 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1830 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1833 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1836 assignResultValue(IC_RESULT(ic));
1838 freeAsmop(IC_RESULT(ic),NULL, ic);
1841 /* adjust the stack for parameters if required */
1842 if (IC_LEFT(ic)->parmBytes) {
1843 int i = IC_LEFT(ic)->parmBytes;
1844 _G.stack.pushed -= i;
1846 emit2("!ldaspsp", i);
1851 emitcode("ld", "hl,#%d", i);
1852 emitcode("add", "hl,sp");
1853 emitcode("ld", "sp,hl");
1857 emitcode("pop", "hl");
1861 emitcode("inc", "sp");
1870 /*-----------------------------------------------------------------*/
1871 /* genCall - generates a call statement */
1872 /*-----------------------------------------------------------------*/
1873 static void genCall (iCode *ic)
1875 link *detype = getSpec(operandType(IC_LEFT(ic)));
1876 emitCall(ic, FALSE);
1879 /*-----------------------------------------------------------------*/
1880 /* genPcall - generates a call by pointer statement */
1881 /*-----------------------------------------------------------------*/
1882 static void genPcall (iCode *ic)
1887 /*-----------------------------------------------------------------*/
1888 /* resultRemat - result is rematerializable */
1889 /*-----------------------------------------------------------------*/
1890 static int resultRemat (iCode *ic)
1892 if (SKIP_IC(ic) || ic->op == IFX)
1895 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1896 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1897 if (sym->remat && !POINTER_SET(ic))
1904 extern set *publics;
1906 /*-----------------------------------------------------------------*/
1907 /* genFunction - generated code for function entry */
1908 /*-----------------------------------------------------------------*/
1909 static void genFunction (iCode *ic)
1911 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1915 setArea(IS_NONBANKED(sym->etype));
1918 if (!IS_STATIC(sym->etype)) {
1919 addSetIfnotP(&publics, sym);
1922 /* create the function header */
1923 emit2("!functionheader", sym->name);
1924 /* PENDING: portability. */
1925 emit2("__%s_start:", sym->rname);
1926 emit2("!functionlabeldef", sym->rname);
1928 fetype = getSpec(operandType(IC_LEFT(ic)));
1930 /* if critical function then turn interrupts off */
1931 if (SPEC_CRTCL(fetype))
1934 /* if this is an interrupt service routine then
1935 save acc, b, dpl, dph */
1936 if (IS_ISR(sym->etype)) {
1939 /* PENDING: callee-save etc */
1941 /* If BC or DE are used, then push */
1942 _G.stack.pushed_bc = 0;
1943 _G.stack.pushed_de = 0;
1944 _G.stack.param_offset = 0;
1945 if (sym->regsUsed) {
1947 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1948 if (bitVectBitValue(sym->regsUsed, i)) {
1952 _G.stack.pushed_bc = 1;
1957 _G.stack.pushed_de = 1;
1962 if (_G.stack.pushed_bc) {
1964 _G.stack.param_offset += 2;
1966 if (_G.stack.pushed_de) {
1968 _G.stack.param_offset += 2;
1972 /* adjust the stack for the function */
1973 _G.stack.last = sym->stack;
1976 emit2("!enterx", sym->stack);
1979 _G.stack.offset = sym->stack;
1982 /*-----------------------------------------------------------------*/
1983 /* genEndFunction - generates epilogue for functions */
1984 /*-----------------------------------------------------------------*/
1985 static void genEndFunction (iCode *ic)
1987 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1989 if (IS_ISR(sym->etype)) {
1993 if (SPEC_CRTCL(sym->etype))
1996 /* PENDING: calleeSave */
1998 /* if debug then send end of function */
1999 if (options.debug && currFunc) {
2001 emitcode("","C$%s$%d$%d$%d ==.",
2002 ic->filename,currFunc->lastLine,
2003 ic->level,ic->block);
2004 if (IS_STATIC(currFunc->etype))
2005 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2007 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2010 if (_G.stack.offset)
2011 emit2("!leavex", _G.stack.offset);
2015 if (_G.stack.pushed_de)
2017 if (_G.stack.pushed_bc)
2019 /* Both baned and non-banked just ret */
2022 /* PENDING: portability. */
2023 emit2("__%s_end:", sym->rname);
2025 _G.flush_statics = 1;
2026 _G.stack.pushed = 0;
2027 _G.stack.offset = 0;
2030 /*-----------------------------------------------------------------*/
2031 /* genRet - generate code for return statement */
2032 /*-----------------------------------------------------------------*/
2033 static void genRet (iCode *ic)
2036 /* Errk. This is a hack until I can figure out how
2037 to cause dehl to spill on a call */
2038 int size,offset = 0;
2040 /* if we have no return value then
2041 just generate the "ret" */
2045 /* we have something to return then
2046 move the return value into place */
2047 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2048 size = AOP_SIZE(IC_LEFT(ic));
2050 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2052 emitcode("ld", "de,%s", l);
2055 emitcode("ld", "hl,%s", l);
2059 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2060 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2061 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2065 l = aopGet(AOP(IC_LEFT(ic)),offset,
2067 if (strcmp(_fReturn[offset],l))
2068 emitcode("ld","%s,%s", _fReturn[offset++],l);
2072 freeAsmop (IC_LEFT(ic),NULL,ic);
2075 /* generate a jump to the return label
2076 if the next is not the return statement */
2077 if (!(ic->next && ic->next->op == LABEL &&
2078 IC_LABEL(ic->next) == returnLabel))
2080 emit2("jp !tlabel", returnLabel->key+100);
2083 /*-----------------------------------------------------------------*/
2084 /* genLabel - generates a label */
2085 /*-----------------------------------------------------------------*/
2086 static void genLabel (iCode *ic)
2088 /* special case never generate */
2089 if (IC_LABEL(ic) == entryLabel)
2092 emitLabel(IC_LABEL(ic)->key+100);
2095 /*-----------------------------------------------------------------*/
2096 /* genGoto - generates a ljmp */
2097 /*-----------------------------------------------------------------*/
2098 static void genGoto (iCode *ic)
2100 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2103 /*-----------------------------------------------------------------*/
2104 /* genPlusIncr :- does addition with increment if possible */
2105 /*-----------------------------------------------------------------*/
2106 static bool genPlusIncr (iCode *ic)
2108 unsigned int icount ;
2109 unsigned int size = getDataSize(IC_RESULT(ic));
2110 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2112 /* will try to generate an increment */
2113 /* if the right side is not a literal
2115 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2118 emitcode("", "; genPlusIncr");
2120 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2122 /* If result is a pair */
2123 if (resultId != PAIR_INVALID) {
2124 if (isLitWord(AOP(IC_LEFT(ic)))) {
2125 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2128 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2129 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2130 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2136 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2139 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2140 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2143 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2148 /* if the literal value of the right hand side
2149 is greater than 4 then it is not worth it */
2153 /* if increment 16 bits in register */
2154 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2159 symbol *tlbl = NULL;
2160 tlbl = newiTempLabel(NULL);
2162 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2164 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2167 emitLabel(tlbl->key+100);
2171 /* if the sizes are greater than 1 then we cannot */
2172 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2173 AOP_SIZE(IC_LEFT(ic)) > 1 )
2176 /* we can if the aops of the left & result match or
2177 if they are in registers and the registers are the
2179 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2181 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2188 /*-----------------------------------------------------------------*/
2189 /* outBitAcc - output a bit in acc */
2190 /*-----------------------------------------------------------------*/
2191 void outBitAcc(operand *result)
2193 symbol *tlbl = newiTempLabel(NULL);
2194 /* if the result is a bit */
2195 if (AOP_TYPE(result) == AOP_CRY){
2199 emit2("!shortjp z,!tlabel", tlbl->key+100);
2201 emitLabel(tlbl->key+100);
2206 /*-----------------------------------------------------------------*/
2207 /* genPlus - generates code for addition */
2208 /*-----------------------------------------------------------------*/
2209 static void genPlus (iCode *ic)
2211 int size, offset = 0;
2213 /* special cases :- */
2215 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2216 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2217 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2219 /* Swap the left and right operands if:
2221 if literal, literal on the right or
2222 if left requires ACC or right is already
2225 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2226 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2227 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2228 operand *t = IC_RIGHT(ic);
2229 IC_RIGHT(ic) = IC_LEFT(ic);
2233 /* if both left & right are in bit
2235 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2236 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2241 /* if left in bit space & right literal */
2242 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2243 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2244 /* Can happen I guess */
2248 /* if I can do an increment instead
2249 of add then GOOD for ME */
2250 if (genPlusIncr (ic) == TRUE)
2253 emit2("; genPlusIncr failed");
2255 size = getDataSize(IC_RESULT(ic));
2257 /* Special case when left and right are constant */
2258 if (isPair(AOP(IC_RESULT(ic)))) {
2261 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2262 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2263 if (left && right) {
2267 sprintf(buffer, "#(%s + %s)", left, right);
2268 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2273 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2274 /* Fetch into HL then do the add */
2276 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2277 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2282 ld hl,sp+n trashes C so we cant afford to do it during an
2283 add with stack based varibles. Worst case is:
2296 So you cant afford to load up hl if either left, right, or result
2297 is on the stack (*sigh*) The alt is:
2305 Combinations in here are:
2306 * If left or right are in bc then the loss is small - trap later
2307 * If the result is in bc then the loss is also small
2310 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2311 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2312 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2313 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2314 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2315 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2316 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2317 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2318 /* Swap left and right */
2319 operand *t = IC_RIGHT(ic);
2320 IC_RIGHT(ic) = IC_LEFT(ic);
2323 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2324 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2328 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2329 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2332 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2335 else if (size == 4) {
2336 emit2("; WARNING: This add is probably broken.\n");
2342 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2343 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2346 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2349 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2351 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2354 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2357 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2359 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2363 freeAsmop(IC_LEFT(ic),NULL,ic);
2364 freeAsmop(IC_RIGHT(ic),NULL,ic);
2365 freeAsmop(IC_RESULT(ic),NULL,ic);
2369 /*-----------------------------------------------------------------*/
2370 /* genMinusDec :- does subtraction with deccrement if possible */
2371 /*-----------------------------------------------------------------*/
2372 static bool genMinusDec (iCode *ic)
2374 unsigned int icount ;
2375 unsigned int size = getDataSize(IC_RESULT(ic));
2377 /* will try to generate an increment */
2378 /* if the right side is not a literal we cannot */
2379 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2382 /* if the literal value of the right hand side
2383 is greater than 4 then it is not worth it */
2384 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2387 size = getDataSize(IC_RESULT(ic));
2390 /* if increment 16 bits in register */
2391 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2394 symbol *tlbl = newiTempLabel(NULL);
2395 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2396 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2398 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2402 emitLabel(tlbl->key+100);
2407 /* if decrement 16 bits in register */
2408 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2409 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2411 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2415 /* If result is a pair */
2416 if (isPair(AOP(IC_RESULT(ic)))) {
2417 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2418 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2420 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2424 /* if the sizes are greater than 1 then we cannot */
2425 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2426 AOP_SIZE(IC_LEFT(ic)) > 1 )
2429 /* we can if the aops of the left & result match or if they are in
2430 registers and the registers are the same */
2431 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2433 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2440 /*-----------------------------------------------------------------*/
2441 /* genMinus - generates code for subtraction */
2442 /*-----------------------------------------------------------------*/
2443 static void genMinus (iCode *ic)
2445 int size, offset = 0;
2446 unsigned long lit = 0L;
2448 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2449 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2450 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2452 /* special cases :- */
2453 /* if both left & right are in bit space */
2454 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2455 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2460 /* if I can do an decrement instead of subtract then GOOD for ME */
2461 if (genMinusDec (ic) == TRUE)
2464 size = getDataSize(IC_RESULT(ic));
2466 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2469 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2473 /* Same logic as genPlus */
2475 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2476 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2477 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2478 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2479 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2480 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2481 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2482 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2483 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2485 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2489 else if (right == PAIR_INVALID)
2491 else if (left == PAIR_INVALID)
2494 fetchPair(left, AOP(IC_LEFT(ic)));
2495 /* Order is important. Right may be HL */
2496 fetchPair(right, AOP(IC_RIGHT(ic)));
2498 emit2("ld a,%s", _pairs[left].l);
2499 emit2("sub a,%s", _pairs[right].l);
2501 emit2("ld a,%s", _pairs[left].h);
2502 emit2("sbc a,%s", _pairs[right].h);
2504 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2505 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2508 else if (size == 4) {
2509 emit2("; WARNING: This sub is probably broken.\n");
2514 /* if literal, add a,#-lit, else normal subb */
2516 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2517 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2519 emitcode("sub","a,%s",
2520 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2522 emitcode("sbc","a,%s",
2523 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2526 /* first add without previous c */
2528 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2530 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2532 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2535 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2536 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2537 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2541 freeAsmop(IC_LEFT(ic),NULL,ic);
2542 freeAsmop(IC_RIGHT(ic),NULL,ic);
2543 freeAsmop(IC_RESULT(ic),NULL,ic);
2546 /*-----------------------------------------------------------------*/
2547 /* genMult - generates code for multiplication */
2548 /*-----------------------------------------------------------------*/
2549 static void genMult (iCode *ic)
2551 /* Shouldn't occur - all done through function calls */
2555 /*-----------------------------------------------------------------*/
2556 /* genDiv - generates code for division */
2557 /*-----------------------------------------------------------------*/
2558 static void genDiv (iCode *ic)
2560 /* Shouldn't occur - all done through function calls */
2564 /*-----------------------------------------------------------------*/
2565 /* genMod - generates code for division */
2566 /*-----------------------------------------------------------------*/
2567 static void genMod (iCode *ic)
2569 /* Shouldn't occur - all done through function calls */
2573 /*-----------------------------------------------------------------*/
2574 /* genIfxJump :- will create a jump depending on the ifx */
2575 /*-----------------------------------------------------------------*/
2576 static void genIfxJump (iCode *ic, char *jval)
2581 /* if true label then we jump if condition
2585 if (!strcmp(jval, "a")) {
2588 else if (!strcmp(jval, "c")) {
2591 else if (!strcmp(jval, "nc")) {
2595 /* The buffer contains the bit on A that we should test */
2600 /* false label is present */
2601 jlbl = IC_FALSE(ic) ;
2602 if (!strcmp(jval, "a")) {
2605 else if (!strcmp(jval, "c")) {
2608 else if (!strcmp(jval, "nc")) {
2612 /* The buffer contains the bit on A that we should test */
2616 /* Z80 can do a conditional long jump */
2617 if (!strcmp(jval, "a")) {
2618 emitcode("or", "a,a");
2620 else if (!strcmp(jval, "c")) {
2622 else if (!strcmp(jval, "nc")) {
2625 emitcode("bit", "%s,a", jval);
2627 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2629 /* mark the icode as generated */
2633 static const char *_getPairIdName(PAIR_ID id)
2635 return _pairs[id].name;
2638 /** Generic compare for > or <
2640 static void genCmp (operand *left,operand *right,
2641 operand *result, iCode *ifx, int sign)
2643 int size, offset = 0 ;
2644 unsigned long lit = 0L;
2645 bool swap_sense = FALSE;
2647 /* if left & right are bit variables */
2648 if (AOP_TYPE(left) == AOP_CRY &&
2649 AOP_TYPE(right) == AOP_CRY ) {
2650 /* Cant happen on the Z80 */
2653 /* subtract right from left if at the
2654 end the carry flag is set then we know that
2655 left is greater than right */
2656 size = max(AOP_SIZE(left),AOP_SIZE(right));
2658 /* if unsigned char cmp with lit, just compare */
2660 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2661 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2663 emit2("xor a,!immedbyte", 0x80);
2664 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2667 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2672 If the left or the right is a lit:
2673 Load -lit into HL, add to right via, check sense.
2675 if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
2676 PAIR_ID id = PAIR_DE;
2677 asmop *lit = AOP(right);
2678 asmop *op = AOP(left);
2681 if (AOP_TYPE(left) == AOP_LIT) {
2687 emit2("ld e,%s", aopGet(op, 0, 0));
2688 emit2("ld a,%s", aopGet(op, 1, 0));
2689 emit2("xor a,!immedbyte", 0x80);
2694 if (id == PAIR_INVALID) {
2695 fetchPair(PAIR_DE, op);
2700 emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
2701 emit2("add hl,%s", _getPairIdName(id));
2704 if(AOP_TYPE(right) == AOP_LIT) {
2705 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2706 /* optimize if(x < 0) or if(x >= 0) */
2709 /* No sign so it's always false */
2713 /* Just load in the top most bit */
2714 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2715 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2716 genIfxJump (ifx,"7");
2720 emitcode("rlc","a");
2726 /* First setup h and l contaning the top most bytes XORed */
2727 bool fDidXor = FALSE;
2728 if (AOP_TYPE(left) == AOP_LIT){
2729 unsigned long lit = (unsigned long)
2730 floatFromVal(AOP(left)->aopu.aop_lit);
2731 emit2("ld %s,!immedbyte", _fTmp[0],
2732 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2735 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2736 emit2("xor a,!immedbyte", 0x80);
2737 emitcode("ld", "%s,a", _fTmp[0]);
2740 if (AOP_TYPE(right) == AOP_LIT) {
2741 unsigned long lit = (unsigned long)
2742 floatFromVal(AOP(right)->aopu.aop_lit);
2743 emit2("ld %s,!immedbyte", _fTmp[1],
2744 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2747 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2748 emit2("xor a,!immedbyte", 0x80);
2749 emitcode("ld", "%s,a", _fTmp[1]);
2759 /* Do a long subtract */
2760 if (!sign || size ) {
2761 MOVA(aopGet(AOP(left),offset,FALSE));
2763 if (sign && size == 0) {
2764 emitcode("ld", "a,%s", _fTmp[0]);
2765 emitcode("sbc", "a,%s", _fTmp[1]);
2768 /* Subtract through, propagating the carry */
2769 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2776 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2777 outBitCLong(result, swap_sense);
2779 /* if the result is used in the next
2780 ifx conditional branch then generate
2781 code a little differently */
2783 genIfxJump(ifx, swap_sense ? "nc" : "c");
2785 outBitCLong(result, swap_sense);
2786 /* leave the result in acc */
2790 /*-----------------------------------------------------------------*/
2791 /* genCmpGt :- greater than comparison */
2792 /*-----------------------------------------------------------------*/
2793 static void genCmpGt (iCode *ic, iCode *ifx)
2795 operand *left, *right, *result;
2796 link *letype , *retype;
2800 right= IC_RIGHT(ic);
2801 result = IC_RESULT(ic);
2803 letype = getSpec(operandType(left));
2804 retype =getSpec(operandType(right));
2805 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2806 /* assign the amsops */
2807 aopOp (left,ic,FALSE, FALSE);
2808 aopOp (right,ic,FALSE, FALSE);
2809 aopOp (result,ic,TRUE, FALSE);
2811 genCmp(right, left, result, ifx, sign);
2813 freeAsmop(left,NULL,ic);
2814 freeAsmop(right,NULL,ic);
2815 freeAsmop(result,NULL,ic);
2818 /*-----------------------------------------------------------------*/
2819 /* genCmpLt - less than comparisons */
2820 /*-----------------------------------------------------------------*/
2821 static void genCmpLt (iCode *ic, iCode *ifx)
2823 operand *left, *right, *result;
2824 link *letype , *retype;
2828 right= IC_RIGHT(ic);
2829 result = IC_RESULT(ic);
2831 letype = getSpec(operandType(left));
2832 retype =getSpec(operandType(right));
2833 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2835 /* assign the amsops */
2836 aopOp (left,ic,FALSE, FALSE);
2837 aopOp (right,ic,FALSE, FALSE);
2838 aopOp (result,ic,TRUE, FALSE);
2840 genCmp(left, right, result, ifx, sign);
2842 freeAsmop(left,NULL,ic);
2843 freeAsmop(right,NULL,ic);
2844 freeAsmop(result,NULL,ic);
2847 /*-----------------------------------------------------------------*/
2848 /* gencjneshort - compare and jump if not equal */
2849 /*-----------------------------------------------------------------*/
2850 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2852 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2854 unsigned long lit = 0L;
2856 /* Swap the left and right if it makes the computation easier */
2857 if (AOP_TYPE(left) == AOP_LIT) {
2863 if(AOP_TYPE(right) == AOP_LIT)
2864 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2866 /* if the right side is a literal then anything goes */
2867 if (AOP_TYPE(right) == AOP_LIT &&
2868 AOP_TYPE(left) != AOP_DIR ) {
2870 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2875 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2879 emitcode("or", "a,a");
2881 emit2("jp nz,!tlabel", lbl->key+100);
2885 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2886 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2887 emitcode("or", "a,a");
2889 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2890 emit2("jp nz,!tlabel", lbl->key+100);
2895 /* if the right side is in a register or in direct space or
2896 if the left is a pointer register & right is not */
2897 else if (AOP_TYPE(right) == AOP_REG ||
2898 AOP_TYPE(right) == AOP_DIR ||
2899 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2901 MOVA(aopGet(AOP(left),offset,FALSE));
2902 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2903 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2905 emit2("jp nz,!tlabel", lbl->key+100);
2907 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2908 emit2("jp nz,!tlabel", lbl->key+100);
2913 /* right is a pointer reg need both a & b */
2914 /* PENDING: is this required? */
2916 MOVA(aopGet(AOP(right),offset,FALSE));
2917 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2918 emit2("!shortjp nz,!tlabel", lbl->key+100);
2924 /*-----------------------------------------------------------------*/
2925 /* gencjne - compare and jump if not equal */
2926 /*-----------------------------------------------------------------*/
2927 static void gencjne(operand *left, operand *right, symbol *lbl)
2929 symbol *tlbl = newiTempLabel(NULL);
2931 gencjneshort(left, right, lbl);
2935 emit2("!shortjp !tlabel", tlbl->key+100);
2936 emitLabel(lbl->key+100);
2937 emitcode("xor","a,a");
2938 emitLabel(tlbl->key+100);
2941 /*-----------------------------------------------------------------*/
2942 /* genCmpEq - generates code for equal to */
2943 /*-----------------------------------------------------------------*/
2944 static void genCmpEq (iCode *ic, iCode *ifx)
2946 operand *left, *right, *result;
2948 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2949 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2950 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2952 /* Swap operands if it makes the operation easier. ie if:
2953 1. Left is a literal.
2955 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2956 operand *t = IC_RIGHT(ic);
2957 IC_RIGHT(ic) = IC_LEFT(ic);
2961 if (ifx && !AOP_SIZE(result)){
2963 /* if they are both bit variables */
2964 if (AOP_TYPE(left) == AOP_CRY &&
2965 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2968 tlbl = newiTempLabel(NULL);
2969 gencjneshort(left, right, tlbl);
2970 if ( IC_TRUE(ifx) ) {
2971 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2972 emitLabel(tlbl->key+100);
2974 /* PENDING: do this better */
2975 symbol *lbl = newiTempLabel(NULL);
2976 emit2("!shortjp !tlabel", lbl->key+100);
2977 emitLabel(tlbl->key+100);
2978 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2979 emitLabel(lbl->key+100);
2982 /* mark the icode as generated */
2987 /* if they are both bit variables */
2988 if (AOP_TYPE(left) == AOP_CRY &&
2989 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2992 gencjne(left,right,newiTempLabel(NULL));
2993 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2997 genIfxJump(ifx,"a");
3000 /* if the result is used in an arithmetic operation
3001 then put the result in place */
3002 if (AOP_TYPE(result) != AOP_CRY) {
3005 /* leave the result in acc */
3009 freeAsmop(left,NULL,ic);
3010 freeAsmop(right,NULL,ic);
3011 freeAsmop(result,NULL,ic);
3014 /*-----------------------------------------------------------------*/
3015 /* ifxForOp - returns the icode containing the ifx for operand */
3016 /*-----------------------------------------------------------------*/
3017 static iCode *ifxForOp ( operand *op, iCode *ic )
3019 /* if true symbol then needs to be assigned */
3020 if (IS_TRUE_SYMOP(op))
3023 /* if this has register type condition and
3024 the next instruction is ifx with the same operand
3025 and live to of the operand is upto the ifx only then */
3027 ic->next->op == IFX &&
3028 IC_COND(ic->next)->key == op->key &&
3029 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3035 /*-----------------------------------------------------------------*/
3036 /* genAndOp - for && operation */
3037 /*-----------------------------------------------------------------*/
3038 static void genAndOp (iCode *ic)
3040 operand *left,*right, *result;
3043 /* note here that && operations that are in an if statement are
3044 taken away by backPatchLabels only those used in arthmetic
3045 operations remain */
3046 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3047 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3048 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3050 /* if both are bit variables */
3051 if (AOP_TYPE(left) == AOP_CRY &&
3052 AOP_TYPE(right) == AOP_CRY ) {
3055 tlbl = newiTempLabel(NULL);
3057 emit2("!shortjp z,!tlabel", tlbl->key+100);
3059 emitLabel(tlbl->key+100);
3063 freeAsmop(left,NULL,ic);
3064 freeAsmop(right,NULL,ic);
3065 freeAsmop(result,NULL,ic);
3068 /*-----------------------------------------------------------------*/
3069 /* genOrOp - for || operation */
3070 /*-----------------------------------------------------------------*/
3071 static void genOrOp (iCode *ic)
3073 operand *left,*right, *result;
3076 /* note here that || operations that are in an
3077 if statement are taken away by backPatchLabels
3078 only those used in arthmetic operations remain */
3079 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3080 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3081 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3083 /* if both are bit variables */
3084 if (AOP_TYPE(left) == AOP_CRY &&
3085 AOP_TYPE(right) == AOP_CRY ) {
3088 tlbl = newiTempLabel(NULL);
3090 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3092 emitLabel(tlbl->key+100);
3096 freeAsmop(left,NULL,ic);
3097 freeAsmop(right,NULL,ic);
3098 freeAsmop(result,NULL,ic);
3101 /*-----------------------------------------------------------------*/
3102 /* isLiteralBit - test if lit == 2^n */
3103 /*-----------------------------------------------------------------*/
3104 int isLiteralBit(unsigned long lit)
3106 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3107 0x100L,0x200L,0x400L,0x800L,
3108 0x1000L,0x2000L,0x4000L,0x8000L,
3109 0x10000L,0x20000L,0x40000L,0x80000L,
3110 0x100000L,0x200000L,0x400000L,0x800000L,
3111 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3112 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3115 for(idx = 0; idx < 32; idx++)
3121 /*-----------------------------------------------------------------*/
3122 /* jmpTrueOrFalse - */
3123 /*-----------------------------------------------------------------*/
3124 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3126 // ugly but optimized by peephole
3128 symbol *nlbl = newiTempLabel(NULL);
3129 emit2("jp !tlabel", nlbl->key+100);
3130 emitLabel(tlbl->key+100);
3131 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3132 emitLabel(nlbl->key+100);
3135 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3136 emitLabel(tlbl->key+100);
3141 /*-----------------------------------------------------------------*/
3142 /* genAnd - code for and */
3143 /*-----------------------------------------------------------------*/
3144 static void genAnd (iCode *ic, iCode *ifx)
3146 operand *left, *right, *result;
3148 unsigned long lit = 0L;
3151 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3152 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3153 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3156 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3158 AOP_TYPE(left), AOP_TYPE(right));
3159 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3161 AOP_SIZE(left), AOP_SIZE(right));
3164 /* if left is a literal & right is not then exchange them */
3165 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3166 AOP_NEEDSACC(left)) {
3167 operand *tmp = right ;
3172 /* if result = right then exchange them */
3173 if(sameRegs(AOP(result),AOP(right))){
3174 operand *tmp = right ;
3179 /* if right is bit then exchange them */
3180 if (AOP_TYPE(right) == AOP_CRY &&
3181 AOP_TYPE(left) != AOP_CRY){
3182 operand *tmp = right ;
3186 if(AOP_TYPE(right) == AOP_LIT)
3187 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3189 size = AOP_SIZE(result);
3191 if (AOP_TYPE(left) == AOP_CRY){
3196 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3197 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3198 if((AOP_TYPE(right) == AOP_LIT) &&
3199 (AOP_TYPE(result) == AOP_CRY) &&
3200 (AOP_TYPE(left) != AOP_CRY)) {
3201 int posbit = isLiteralBit(lit);
3205 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3209 emitcode("mov","c,acc.%d",posbit&0x07);
3214 sprintf(buffer, "%d", posbit&0x07);
3215 genIfxJump(ifx, buffer);
3223 symbol *tlbl = newiTempLabel(NULL);
3224 int sizel = AOP_SIZE(left);
3227 emitcode("setb","c");
3230 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3231 MOVA( aopGet(AOP(left),offset,FALSE));
3233 if((posbit = isLiteralBit(bytelit)) != 0) {
3235 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3238 if(bytelit != 0x0FFL)
3239 emitcode("and","a,%s",
3240 aopGet(AOP(right),offset,FALSE));
3244 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3249 // bit = left & literal
3251 emitcode("clr","c");
3252 emit2("!tlabeldef", tlbl->key+100);
3254 // if(left & literal)
3257 jmpTrueOrFalse(ifx, tlbl);
3265 /* if left is same as result */
3266 if(sameRegs(AOP(result),AOP(left))){
3267 for(;size--; offset++) {
3268 if(AOP_TYPE(right) == AOP_LIT){
3269 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3273 aopPut(AOP(result),zero,offset);
3275 MOVA(aopGet(AOP(left),offset,FALSE));
3276 emitcode("and","a,%s",
3277 aopGet(AOP(right),offset,FALSE));
3278 aopPut(AOP(left), "a", offset);
3283 if (AOP_TYPE(left) == AOP_ACC) {
3287 MOVA(aopGet(AOP(left),offset,FALSE));
3288 emitcode("and","a,%s",
3289 aopGet(AOP(right),offset,FALSE));
3290 aopPut(AOP(left), "a", offset);
3295 // left & result in different registers
3296 if(AOP_TYPE(result) == AOP_CRY){
3299 for(;(size--);offset++) {
3301 // result = left & right
3302 if(AOP_TYPE(right) == AOP_LIT){
3303 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3305 aopGet(AOP(left),offset,FALSE),
3308 } else if(bytelit == 0){
3309 aopPut(AOP(result),zero,offset);
3313 // faster than result <- left, anl result,right
3314 // and better if result is SFR
3315 if (AOP_TYPE(left) == AOP_ACC)
3316 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3318 MOVA(aopGet(AOP(left),offset,FALSE));
3319 emitcode("and","a,%s",
3320 aopGet(AOP(right),offset,FALSE));
3322 aopPut(AOP(result),"a",offset);
3329 freeAsmop(left,NULL,ic);
3330 freeAsmop(right,NULL,ic);
3331 freeAsmop(result,NULL,ic);
3334 /*-----------------------------------------------------------------*/
3335 /* genOr - code for or */
3336 /*-----------------------------------------------------------------*/
3337 static void genOr (iCode *ic, iCode *ifx)
3339 operand *left, *right, *result;
3341 unsigned long lit = 0L;
3343 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3344 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3345 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3348 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3350 AOP_TYPE(left), AOP_TYPE(right));
3351 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3353 AOP_SIZE(left), AOP_SIZE(right));
3356 /* if left is a literal & right is not then exchange them */
3357 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3358 AOP_NEEDSACC(left)) {
3359 operand *tmp = right ;
3364 /* if result = right then exchange them */
3365 if(sameRegs(AOP(result),AOP(right))){
3366 operand *tmp = right ;
3371 /* if right is bit then exchange them */
3372 if (AOP_TYPE(right) == AOP_CRY &&
3373 AOP_TYPE(left) != AOP_CRY){
3374 operand *tmp = right ;
3378 if(AOP_TYPE(right) == AOP_LIT)
3379 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3381 size = AOP_SIZE(result);
3383 if (AOP_TYPE(left) == AOP_CRY){
3388 if((AOP_TYPE(right) == AOP_LIT) &&
3389 (AOP_TYPE(result) == AOP_CRY) &&
3390 (AOP_TYPE(left) != AOP_CRY)){
3395 /* if left is same as result */
3396 if(sameRegs(AOP(result),AOP(left))){
3397 for(;size--; offset++) {
3398 if(AOP_TYPE(right) == AOP_LIT){
3399 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3402 MOVA(aopGet(AOP(left),offset,FALSE));
3403 emitcode("or","a,%s",
3404 aopGet(AOP(right),offset,FALSE));
3405 aopPut(AOP(result),"a", offset);
3408 if (AOP_TYPE(left) == AOP_ACC)
3409 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3411 MOVA(aopGet(AOP(left),offset,FALSE));
3412 emitcode("or","a,%s",
3413 aopGet(AOP(right),offset,FALSE));
3414 aopPut(AOP(result),"a", offset);
3419 // left & result in different registers
3420 if(AOP_TYPE(result) == AOP_CRY){
3422 } else for(;(size--);offset++){
3424 // result = left & right
3425 if(AOP_TYPE(right) == AOP_LIT){
3426 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3428 aopGet(AOP(left),offset,FALSE),
3433 // faster than result <- left, anl result,right
3434 // and better if result is SFR
3435 if (AOP_TYPE(left) == AOP_ACC)
3436 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3438 MOVA(aopGet(AOP(left),offset,FALSE));
3439 emitcode("or","a,%s",
3440 aopGet(AOP(right),offset,FALSE));
3442 aopPut(AOP(result),"a",offset);
3443 /* PENDING: something weird is going on here. Add exception. */
3444 if (AOP_TYPE(result) == AOP_ACC)
3450 freeAsmop(left,NULL,ic);
3451 freeAsmop(right,NULL,ic);
3452 freeAsmop(result,NULL,ic);
3455 /*-----------------------------------------------------------------*/
3456 /* genXor - code for xclusive or */
3457 /*-----------------------------------------------------------------*/
3458 static void genXor (iCode *ic, iCode *ifx)
3460 operand *left, *right, *result;
3462 unsigned long lit = 0L;
3464 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3465 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3466 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3468 /* if left is a literal & right is not then exchange them */
3469 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3470 AOP_NEEDSACC(left)) {
3471 operand *tmp = right ;
3476 /* if result = right then exchange them */
3477 if(sameRegs(AOP(result),AOP(right))){
3478 operand *tmp = right ;
3483 /* if right is bit then exchange them */
3484 if (AOP_TYPE(right) == AOP_CRY &&
3485 AOP_TYPE(left) != AOP_CRY){
3486 operand *tmp = right ;
3490 if(AOP_TYPE(right) == AOP_LIT)
3491 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3493 size = AOP_SIZE(result);
3495 if (AOP_TYPE(left) == AOP_CRY){
3500 if((AOP_TYPE(right) == AOP_LIT) &&
3501 (AOP_TYPE(result) == AOP_CRY) &&
3502 (AOP_TYPE(left) != AOP_CRY)){
3507 /* if left is same as result */
3508 if(sameRegs(AOP(result),AOP(left))){
3509 for(;size--; offset++) {
3510 if(AOP_TYPE(right) == AOP_LIT){
3511 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3514 MOVA(aopGet(AOP(right),offset,FALSE));
3515 emitcode("xor","a,%s",
3516 aopGet(AOP(left),offset,FALSE));
3517 aopPut(AOP(result),"a",0);
3520 if (AOP_TYPE(left) == AOP_ACC)
3521 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3523 MOVA(aopGet(AOP(right),offset,FALSE));
3524 emitcode("xor","a,%s",
3525 aopGet(AOP(left),offset,FALSE));
3526 aopPut(AOP(result),"a",0);
3531 // left & result in different registers
3532 if(AOP_TYPE(result) == AOP_CRY){
3534 } else for(;(size--);offset++){
3536 // result = left & right
3537 if(AOP_TYPE(right) == AOP_LIT){
3538 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3540 aopGet(AOP(left),offset,FALSE),
3545 // faster than result <- left, anl result,right
3546 // and better if result is SFR
3547 if (AOP_TYPE(left) == AOP_ACC)
3548 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3550 MOVA(aopGet(AOP(right),offset,FALSE));
3551 emitcode("xor","a,%s",
3552 aopGet(AOP(left),offset,FALSE));
3553 aopPut(AOP(result),"a",0);
3555 aopPut(AOP(result),"a",offset);
3560 freeAsmop(left,NULL,ic);
3561 freeAsmop(right,NULL,ic);
3562 freeAsmop(result,NULL,ic);
3565 /*-----------------------------------------------------------------*/
3566 /* genInline - write the inline code out */
3567 /*-----------------------------------------------------------------*/
3568 static void genInline (iCode *ic)
3570 char buffer[MAX_INLINEASM];
3574 inLine += (!options.asmpeep);
3575 strcpy(buffer,IC_INLINE(ic));
3577 /* emit each line as a code */
3596 /* emitcode("",buffer); */
3597 inLine -= (!options.asmpeep);
3600 /*-----------------------------------------------------------------*/
3601 /* genRRC - rotate right with carry */
3602 /*-----------------------------------------------------------------*/
3603 static void genRRC (iCode *ic)
3608 /*-----------------------------------------------------------------*/
3609 /* genRLC - generate code for rotate left with carry */
3610 /*-----------------------------------------------------------------*/
3611 static void genRLC (iCode *ic)
3616 /*-----------------------------------------------------------------*/
3617 /* shiftR2Left2Result - shift right two bytes from left to result */
3618 /*-----------------------------------------------------------------*/
3619 static void shiftR2Left2Result (operand *left, int offl,
3620 operand *result, int offr,
3621 int shCount, int sign)
3623 movLeft2Result(left, offl, result, offr, 0);
3624 movLeft2Result(left, offl+1, result, offr+1, 0);
3630 /* if (AOP(result)->type == AOP_REG) {*/
3633 symbol *tlbl , *tlbl1;
3636 tlbl = newiTempLabel(NULL);
3637 tlbl1 = newiTempLabel(NULL);
3639 /* Left is already in result - so now do the shift */
3641 emit2("ld a,!immedbyte+1", shCount);
3642 emit2("!shortjp !tlabel", tlbl1->key+100);
3643 emitLabel(tlbl->key+100);
3646 emitcode("or", "a,a");
3649 l = aopGet(AOP(result), --offset, FALSE);
3650 emitcode("rr","%s", l);
3653 emitLabel(tlbl1->key+100);
3654 emitcode("dec", "a");
3655 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3660 /*-----------------------------------------------------------------*/
3661 /* shiftL2Left2Result - shift left two bytes from left to result */
3662 /*-----------------------------------------------------------------*/
3663 static void shiftL2Left2Result (operand *left, int offl,
3664 operand *result, int offr, int shCount)
3666 if(sameRegs(AOP(result), AOP(left)) &&
3667 ((offl + MSB16) == offr)){
3670 /* Copy left into result */
3671 movLeft2Result(left, offl, result, offr, 0);
3672 movLeft2Result(left, offl+1, result, offr+1, 0);
3674 /* PENDING: for now just see if it'll work. */
3675 /*if (AOP(result)->type == AOP_REG) { */
3679 symbol *tlbl , *tlbl1;
3682 tlbl = newiTempLabel(NULL);
3683 tlbl1 = newiTempLabel(NULL);
3685 /* Left is already in result - so now do the shift */
3687 emit2("ld a,!immedbyte+1", shCount);
3688 emit2("!shortjp !tlabel", tlbl1->key+100);
3689 emitLabel(tlbl->key+100);
3692 emitcode("or", "a,a");
3694 l = aopGet(AOP(result),offset++,FALSE);
3695 emitcode("rl","%s", l);
3698 emitLabel(tlbl1->key+100);
3699 emitcode("dec", "a");
3700 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3705 /*-----------------------------------------------------------------*/
3706 /* AccRol - rotate left accumulator by known count */
3707 /*-----------------------------------------------------------------*/
3708 static void AccRol (int shCount)
3710 shCount &= 0x0007; // shCount : 0..7
3747 /*-----------------------------------------------------------------*/
3748 /* AccLsh - left shift accumulator by known count */
3749 /*-----------------------------------------------------------------*/
3750 static void AccLsh (int shCount)
3754 emitcode("add","a,a");
3756 else if(shCount == 2) {
3757 emitcode("add","a,a");
3758 emitcode("add","a,a");
3760 /* rotate left accumulator */
3762 /* and kill the lower order bits */
3763 emit2("and a,!immedbyte", SLMask[shCount]);
3768 /*-----------------------------------------------------------------*/
3769 /* shiftL1Left2Result - shift left one byte from left to result */
3770 /*-----------------------------------------------------------------*/
3771 static void shiftL1Left2Result (operand *left, int offl,
3772 operand *result, int offr, int shCount)
3775 l = aopGet(AOP(left),offl,FALSE);
3777 /* shift left accumulator */
3779 aopPut(AOP(result),"a",offr);
3783 /*-----------------------------------------------------------------*/
3784 /* genlshTwo - left shift two bytes by known amount != 0 */
3785 /*-----------------------------------------------------------------*/
3786 static void genlshTwo (operand *result,operand *left, int shCount)
3788 int size = AOP_SIZE(result);
3792 /* if shCount >= 8 */
3797 movLeft2Result(left, LSB, result, MSB16, 0);
3798 aopPut(AOP(result),zero, 0);
3799 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3802 movLeft2Result(left, LSB, result, MSB16, 0);
3803 aopPut(AOP(result),zero, 0);
3807 aopPut(AOP(result),zero,LSB);
3810 /* 1 <= shCount <= 7 */
3816 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3821 /*-----------------------------------------------------------------*/
3822 /* genlshOne - left shift a one byte quantity by known count */
3823 /*-----------------------------------------------------------------*/
3824 static void genlshOne (operand *result, operand *left, int shCount)
3826 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3829 /*-----------------------------------------------------------------*/
3830 /* genLeftShiftLiteral - left shifting by known count */
3831 /*-----------------------------------------------------------------*/
3832 static void genLeftShiftLiteral (operand *left,
3837 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3840 freeAsmop(right,NULL,ic);
3842 aopOp(left,ic,FALSE, FALSE);
3843 aopOp(result,ic,FALSE, FALSE);
3845 size = getSize(operandType(result));
3848 emitcode("; shift left ","result %d, left %d",size,
3852 /* I suppose that the left size >= result size */
3857 else if(shCount >= (size * 8))
3859 aopPut(AOP(result),zero,size);
3863 genlshOne (result,left,shCount);
3866 genlshTwo (result,left,shCount);
3875 freeAsmop(left,NULL,ic);
3876 freeAsmop(result,NULL,ic);
3879 /*-----------------------------------------------------------------*/
3880 /* genLeftShift - generates code for left shifting */
3881 /*-----------------------------------------------------------------*/
3882 static void genLeftShift (iCode *ic)
3886 symbol *tlbl , *tlbl1;
3887 operand *left,*right, *result;
3889 right = IC_RIGHT(ic);
3891 result = IC_RESULT(ic);
3893 aopOp(right,ic,FALSE, FALSE);
3895 /* if the shift count is known then do it
3896 as efficiently as possible */
3897 if (AOP_TYPE(right) == AOP_LIT) {
3898 genLeftShiftLiteral (left,right,result,ic);
3902 /* shift count is unknown then we have to form a loop get the loop
3903 count in B : Note: we take only the lower order byte since
3904 shifting more that 32 bits make no sense anyway, ( the largest
3905 size of an object can be only 32 bits ) */
3906 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3907 emitcode("inc","a");
3908 freeAsmop (right,NULL,ic);
3909 aopOp(left,ic,FALSE, FALSE);
3910 aopOp(result,ic,FALSE, FALSE);
3912 /* now move the left to the result if they are not the
3915 if (!sameRegs(AOP(left),AOP(result))) {
3917 size = AOP_SIZE(result);
3920 l = aopGet(AOP(left),offset,FALSE);
3921 aopPut(AOP(result),l,offset);
3926 size = AOP_SIZE(result);
3929 l = aopGet(AOP(left),offset,FALSE);
3930 aopPut(AOP(result),l,offset);
3936 tlbl = newiTempLabel(NULL);
3937 size = AOP_SIZE(result);
3939 tlbl1 = newiTempLabel(NULL);
3941 emit2("!shortjp !tlabel", tlbl1->key+100);
3942 emitLabel(tlbl->key+100);
3943 l = aopGet(AOP(result),offset,FALSE);
3944 emitcode("or", "a,a");
3946 l = aopGet(AOP(result),offset++,FALSE);
3947 emitcode("rl","%s", l);
3949 emitLabel(tlbl1->key+100);
3950 emitcode("dec", "a");
3951 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3953 freeAsmop(left,NULL,ic);
3954 freeAsmop(result,NULL,ic);
3957 /*-----------------------------------------------------------------*/
3958 /* genrshOne - left shift two bytes by known amount != 0 */
3959 /*-----------------------------------------------------------------*/
3960 static void genrshOne (operand *result,operand *left, int shCount)
3963 int size = AOP_SIZE(result);
3969 l = aopGet(AOP(left),0,FALSE);
3970 if (AOP(result)->type == AOP_REG) {
3971 aopPut(AOP(result), l, 0);
3972 l = aopGet(AOP(result), 0, FALSE);
3974 emitcode("srl", "%s", l);
3979 emitcode("srl", "a");
3981 aopPut(AOP(result),"a",0);
3985 /*-----------------------------------------------------------------*/
3986 /* AccRsh - right shift accumulator by known count */
3987 /*-----------------------------------------------------------------*/
3988 static void AccRsh (int shCount)
3991 /* rotate right accumulator */
3992 AccRol(8 - shCount);
3993 /* and kill the higher order bits */
3994 emit2("and a,!immedbyte", SRMask[shCount]);
3998 /*-----------------------------------------------------------------*/
3999 /* shiftR1Left2Result - shift right one byte from left to result */
4000 /*-----------------------------------------------------------------*/
4001 static void shiftR1Left2Result (operand *left, int offl,
4002 operand *result, int offr,
4003 int shCount, int sign)
4005 MOVA(aopGet(AOP(left),offl,FALSE));
4012 aopPut(AOP(result),"a",offr);
4015 /*-----------------------------------------------------------------*/
4016 /* genrshTwo - right shift two bytes by known amount != 0 */
4017 /*-----------------------------------------------------------------*/
4018 static void genrshTwo (operand *result,operand *left,
4019 int shCount, int sign)
4021 /* if shCount >= 8 */
4025 shiftR1Left2Result(left, MSB16, result, LSB,
4029 movLeft2Result(left, MSB16, result, LSB, sign);
4031 aopPut(AOP(result),zero,1);
4033 /* 1 <= shCount <= 7 */
4035 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
4039 /*-----------------------------------------------------------------*/
4040 /* genRightShiftLiteral - left shifting by known count */
4041 /*-----------------------------------------------------------------*/
4042 static void genRightShiftLiteral (operand *left,
4047 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4050 freeAsmop(right,NULL,ic);
4052 aopOp(left,ic,FALSE, FALSE);
4053 aopOp(result,ic,FALSE, FALSE);
4055 size = getSize(operandType(result));
4057 emitcode("; shift right ","result %d, left %d",size,
4060 /* I suppose that the left size >= result size */
4065 else if(shCount >= (size * 8))
4067 aopPut(AOP(result),zero,size);
4071 genrshOne(result, left, shCount);
4074 /* PENDING: sign support */
4075 genrshTwo(result, left, shCount, FALSE);
4084 freeAsmop(left,NULL,ic);
4085 freeAsmop(result,NULL,ic);
4088 /*-----------------------------------------------------------------*/
4089 /* genRightShift - generate code for right shifting */
4090 /*-----------------------------------------------------------------*/
4091 static void genRightShift (iCode *ic)
4093 operand *right, *left, *result;
4095 int size, offset, first = 1;
4099 symbol *tlbl, *tlbl1 ;
4101 /* if signed then we do it the hard way preserve the
4102 sign bit moving it inwards */
4103 retype = getSpec(operandType(IC_RESULT(ic)));
4105 is_signed = !SPEC_USIGN(retype);
4107 /* signed & unsigned types are treated the same : i.e. the
4108 signed is NOT propagated inwards : quoting from the
4109 ANSI - standard : "for E1 >> E2, is equivalent to division
4110 by 2**E2 if unsigned or if it has a non-negative value,
4111 otherwise the result is implementation defined ", MY definition
4112 is that the sign does not get propagated */
4114 right = IC_RIGHT(ic);
4116 result = IC_RESULT(ic);
4118 aopOp(right,ic,FALSE, FALSE);
4120 /* if the shift count is known then do it
4121 as efficiently as possible */
4122 if (AOP_TYPE(right) == AOP_LIT) {
4123 genRightShiftLiteral(left,right,result,ic);
4127 aopOp(left,ic,FALSE, FALSE);
4128 aopOp(result,ic,FALSE, FALSE);
4130 /* now move the left to the result if they are not the
4132 if (!sameRegs(AOP(left),AOP(result)) &&
4133 AOP_SIZE(result) > 1) {
4135 size = AOP_SIZE(result);
4138 l = aopGet(AOP(left),offset,FALSE);
4139 aopPut(AOP(result),l,offset);
4144 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4145 emitcode("inc","a");
4146 freeAsmop (right, NULL, ic);
4148 tlbl = newiTempLabel(NULL);
4149 tlbl1= newiTempLabel(NULL);
4150 size = AOP_SIZE(result);
4153 emit2("!shortjp !tlabel", tlbl1->key+100);
4154 emitLabel(tlbl->key+100);
4156 l = aopGet(AOP(result),offset--,FALSE);
4159 emitcode("sra", "%s", l);
4161 emitcode("srl", "%s", l);
4165 emitcode("rr", "%s", l);
4167 emitLabel(tlbl1->key+100);
4168 emitcode("dec", "a");
4169 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4171 freeAsmop(left,NULL,ic);
4172 freeAsmop(result,NULL,ic);
4175 /*-----------------------------------------------------------------*/
4176 /* genGenPointerGet - get value from generic pointer space */
4177 /*-----------------------------------------------------------------*/
4178 static void genGenPointerGet (operand *left,
4179 operand *result, iCode *ic)
4182 link *retype = getSpec(operandType(result));
4188 aopOp(left,ic,FALSE, FALSE);
4189 aopOp(result,ic,FALSE, FALSE);
4191 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4193 if (isPtrPair(AOP(left)))
4195 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4196 aopPut(AOP(result), buffer, 0);
4199 emit2("ld a,!*pair", getPairName(AOP(left)));
4200 aopPut(AOP(result),"a", 0);
4202 freeAsmop(left,NULL,ic);
4206 /* For now we always load into IY */
4207 /* if this is remateriazable */
4208 fetchPair(pair, AOP(left));
4210 /* so iy now contains the address */
4211 freeAsmop(left,NULL,ic);
4213 /* if bit then unpack */
4214 if (IS_BITVAR(retype)) {
4218 size = AOP_SIZE(result);
4222 /* PENDING: make this better */
4223 if (!IS_GB && AOP(result)->type == AOP_REG) {
4224 aopPut(AOP(result), "!*hl", offset++);
4227 emit2("ld a,!*pair", _pairs[pair].name);
4228 aopPut(AOP(result),"a",offset++);
4231 emit2("inc %s", _pairs[pair].name);
4232 _G.pairs[pair].offset++;
4238 freeAsmop(result,NULL,ic);
4241 /*-----------------------------------------------------------------*/
4242 /* genPointerGet - generate code for pointer get */
4243 /*-----------------------------------------------------------------*/
4244 static void genPointerGet (iCode *ic)
4246 operand *left, *result ;
4250 result = IC_RESULT(ic) ;
4252 /* depending on the type of pointer we need to
4253 move it to the correct pointer register */
4254 type = operandType(left);
4255 etype = getSpec(type);
4257 genGenPointerGet (left,result,ic);
4260 bool isRegOrLit(asmop *aop)
4262 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4267 /*-----------------------------------------------------------------*/
4268 /* genGenPointerSet - stores the value into a pointer location */
4269 /*-----------------------------------------------------------------*/
4270 static void genGenPointerSet (operand *right,
4271 operand *result, iCode *ic)
4274 link *retype = getSpec(operandType(right));
4275 PAIR_ID pairId = PAIR_HL;
4277 aopOp(result,ic,FALSE, FALSE);
4278 aopOp(right,ic,FALSE, FALSE);
4283 /* Handle the exceptions first */
4284 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4286 char *l = aopGet(AOP(right), 0, FALSE);
4287 const char *pair = getPairName(AOP(result));
4288 if (canAssignToPtr(l) && isPtr(pair)) {
4289 emit2("ld !*pair,%s", pair, l);
4293 emit2("ld !*pair,a", pair);
4298 /* if the operand is already in dptr
4299 then we do nothing else we move the value to dptr */
4300 if (AOP_TYPE(result) != AOP_STR) {
4301 fetchPair(pairId, AOP(result));
4303 /* so hl know contains the address */
4304 freeAsmop(result,NULL,ic);
4306 /* if bit then unpack */
4307 if (IS_BITVAR(retype)) {
4311 size = AOP_SIZE(right);
4315 char *l = aopGet(AOP(right),offset,FALSE);
4316 if (isRegOrLit(AOP(right)) && !IS_GB) {
4317 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4321 emit2("ld !*pair,a", _pairs[pairId].name);
4324 emitcode("inc", _pairs[pairId].name);
4325 _G.pairs[pairId].offset++;
4331 freeAsmop(right,NULL,ic);
4334 /*-----------------------------------------------------------------*/
4335 /* genPointerSet - stores the value into a pointer location */
4336 /*-----------------------------------------------------------------*/
4337 static void genPointerSet (iCode *ic)
4339 operand *right, *result ;
4342 right = IC_RIGHT(ic);
4343 result = IC_RESULT(ic) ;
4345 /* depending on the type of pointer we need to
4346 move it to the correct pointer register */
4347 type = operandType(result);
4348 etype = getSpec(type);
4350 genGenPointerSet (right,result,ic);
4353 /*-----------------------------------------------------------------*/
4354 /* genIfx - generate code for Ifx statement */
4355 /*-----------------------------------------------------------------*/
4356 static void genIfx (iCode *ic, iCode *popIc)
4358 operand *cond = IC_COND(ic);
4361 aopOp(cond,ic,FALSE, TRUE);
4363 /* get the value into acc */
4364 if (AOP_TYPE(cond) != AOP_CRY)
4368 /* the result is now in the accumulator */
4369 freeAsmop(cond,NULL,ic);
4371 /* if there was something to be popped then do it */
4375 /* if the condition is a bit variable */
4376 if (isbit && IS_ITEMP(cond) &&
4378 genIfxJump(ic,SPIL_LOC(cond)->rname);
4380 if (isbit && !IS_ITEMP(cond))
4381 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4388 /*-----------------------------------------------------------------*/
4389 /* genAddrOf - generates code for address of */
4390 /*-----------------------------------------------------------------*/
4391 static void genAddrOf (iCode *ic)
4393 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4395 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4397 /* if the operand is on the stack then we
4398 need to get the stack offset of this
4403 if (sym->stack <= 0) {
4404 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4407 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4409 emitcode("ld", "d,h");
4410 emitcode("ld", "e,l");
4413 emit2("ld de,!hashedstr", sym->rname);
4415 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4416 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4421 /* if it has an offset then we need to compute it */
4423 emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
4425 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4426 emitcode("add", "hl,sp");
4429 emitcode("ld", "hl,#%s", sym->rname);
4431 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4432 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4434 freeAsmop(IC_RESULT(ic),NULL,ic);
4437 /*-----------------------------------------------------------------*/
4438 /* genAssign - generate code for assignment */
4439 /*-----------------------------------------------------------------*/
4440 static void genAssign (iCode *ic)
4442 operand *result, *right;
4444 unsigned long lit = 0L;
4446 result = IC_RESULT(ic);
4447 right = IC_RIGHT(ic) ;
4450 /* Dont bother assigning if they are the same */
4451 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4452 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4457 aopOp(right,ic,FALSE, FALSE);
4458 aopOp(result,ic,TRUE, FALSE);
4460 /* if they are the same registers */
4461 if (sameRegs(AOP(right),AOP(result))) {
4462 emitcode("", "; (registers are the same)");
4466 /* if the result is a bit */
4467 if (AOP_TYPE(result) == AOP_CRY) {
4472 size = AOP_SIZE(result);
4475 if(AOP_TYPE(right) == AOP_LIT)
4476 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4477 if (isPair(AOP(result))) {
4478 fetchPair(getPairId(AOP(result)), AOP(right));
4480 else if((size > 1) &&
4481 (AOP_TYPE(result) != AOP_REG) &&
4482 (AOP_TYPE(right) == AOP_LIT) &&
4483 !IS_FLOAT(operandType(right)) &&
4485 bool fXored = FALSE;
4487 /* Work from the top down.
4488 Done this way so that we can use the cached copy of 0
4489 in A for a fast clear */
4491 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4492 if (!fXored && size>1) {
4493 emitcode("xor", "a,a");
4497 aopPut(AOP(result),"a",offset);
4500 aopPut(AOP(result), zero, offset);
4505 aopGet(AOP(right),offset,FALSE),
4510 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4511 /* Special case. Load into a and d, then load out. */
4512 MOVA(aopGet(AOP(right), 0, FALSE));
4513 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4514 aopPut(AOP(result), "a", 0);
4515 aopPut(AOP(result), "e", 1);
4518 /* PENDING: do this check better */
4519 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4520 MOVA(aopGet(AOP(right), offset, FALSE));
4521 aopPut(AOP(result), "a", offset);
4525 aopGet(AOP(right),offset,FALSE),
4532 freeAsmop(right,NULL,ic);
4533 freeAsmop(result,NULL,ic);
4536 /*-----------------------------------------------------------------*/
4537 /* genJumpTab - genrates code for jump table */
4538 /*-----------------------------------------------------------------*/
4539 static void genJumpTab (iCode *ic)
4544 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4545 /* get the condition into accumulator */
4546 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4548 emitcode("push", "de");
4549 emitcode("ld", "e,%s", l);
4550 emit2("ld d,!zero");
4551 jtab = newiTempLabel(NULL);
4553 emit2("ld hl,!immed!tlabel", jtab->key+100);
4554 emitcode("add", "hl,de");
4555 emitcode("add", "hl,de");
4556 emitcode("add", "hl,de");
4557 freeAsmop(IC_JTCOND(ic),NULL,ic);
4559 emitcode("pop", "de");
4561 emitLabel(jtab->key+100);
4562 /* now generate the jump labels */
4563 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4564 jtab = setNextItem(IC_JTLABELS(ic)))
4565 emit2("jp !tlabel", jtab->key+100);
4568 /*-----------------------------------------------------------------*/
4569 /* genCast - gen code for casting */
4570 /*-----------------------------------------------------------------*/
4571 static void genCast (iCode *ic)
4573 operand *result = IC_RESULT(ic);
4574 link *ctype = operandType(IC_LEFT(ic));
4575 operand *right = IC_RIGHT(ic);
4578 /* if they are equivalent then do nothing */
4579 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4582 aopOp(right,ic,FALSE, FALSE);
4583 aopOp(result,ic,FALSE, FALSE);
4585 /* if the result is a bit */
4586 if (AOP_TYPE(result) == AOP_CRY) {
4590 /* if they are the same size : or less */
4591 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4593 /* if they are in the same place */
4594 if (sameRegs(AOP(right),AOP(result)))
4597 /* if they in different places then copy */
4598 size = AOP_SIZE(result);
4602 aopGet(AOP(right),offset,FALSE),
4609 /* PENDING: should be OK. */
4611 /* if the result is of type pointer */
4612 if (IS_PTR(ctype)) {
4617 /* so we now know that the size of destination is greater
4618 than the size of the source */
4619 /* we move to result for the size of source */
4620 size = AOP_SIZE(right);
4624 aopGet(AOP(right),offset,FALSE),
4629 /* now depending on the sign of the destination */
4630 size = AOP_SIZE(result) - AOP_SIZE(right);
4631 /* Unsigned or not an integral type - right fill with zeros */
4632 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4634 aopPut(AOP(result),zero,offset++);
4636 /* we need to extend the sign :{ */
4637 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4640 emitcode("", "; genCast: sign extend untested.");
4641 emitcode("rla", "");
4642 emitcode("sbc", "a,a");
4644 aopPut(AOP(result),"a",offset++);
4648 freeAsmop(right, NULL, ic);
4649 freeAsmop(result, NULL, ic);
4652 /*-----------------------------------------------------------------*/
4653 /* genReceive - generate code for a receive iCode */
4654 /*-----------------------------------------------------------------*/
4655 static void genReceive (iCode *ic)
4657 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4658 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4659 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4663 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4665 assignResultValue(IC_RESULT(ic));
4668 freeAsmop(IC_RESULT(ic),NULL,ic);
4671 /*-----------------------------------------------------------------*/
4672 /* genZ80Code - generate code for Z80 based controllers */
4673 /*-----------------------------------------------------------------*/
4674 void genZ80Code (iCode *lic)
4681 _fReturn = _gbz80_return;
4682 _fTmp = _gbz80_return;
4685 _fReturn = _z80_return;
4686 _fTmp = _z80_return;
4688 tsprintf(zero, "!zero");
4690 lineHead = lineCurr = NULL;
4692 /* if debug information required */
4693 if (options.debug && currFunc) {
4694 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4696 if (IS_STATIC(currFunc->etype))
4697 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4699 emitcode("","G$%s$0$0 ==.",currFunc->name);
4702 /* stack pointer name */
4706 for (ic = lic ; ic ; ic = ic->next ) {
4708 if ( cln != ic->lineno ) {
4709 if ( options.debug ) {
4711 emitcode("","C$%s$%d$%d$%d ==.",
4712 ic->filename,ic->lineno,
4713 ic->level,ic->block);
4716 emitcode(";","%s %d",ic->filename,ic->lineno);
4719 /* if the result is marked as
4720 spilt and rematerializable or code for
4721 this has already been generated then
4723 if (resultRemat(ic) || ic->generated )
4726 /* depending on the operation */
4729 emitcode("", "; genNot");
4734 emitcode("", "; genCpl");
4739 emitcode("", "; genUminus");
4744 emitcode("", "; genIpush");
4749 /* IPOP happens only when trying to restore a
4750 spilt live range, if there is an ifx statement
4751 following this pop then the if statement might
4752 be using some of the registers being popped which
4753 would destory the contents of the register so
4754 we need to check for this condition and handle it */
4756 ic->next->op == IFX &&
4757 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4758 emitcode("", "; genIfx");
4759 genIfx (ic->next,ic);
4762 emitcode("", "; genIpop");
4768 emitcode("", "; genCall");
4773 emitcode("", "; genPcall");
4778 emitcode("", "; genFunction");
4783 emitcode("", "; genEndFunction");
4784 genEndFunction (ic);
4788 emitcode("", "; genRet");
4793 emitcode("", "; genLabel");
4798 emitcode("", "; genGoto");
4803 emitcode("", "; genPlus");
4808 emitcode("", "; genMinus");
4813 emitcode("", "; genMult");
4818 emitcode("", "; genDiv");
4823 emitcode("", "; genMod");
4828 emitcode("", "; genCmpGt");
4829 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4833 emitcode("", "; genCmpLt");
4834 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4841 /* note these two are xlated by algebraic equivalence
4842 during parsing SDCC.y */
4843 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4844 "got '>=' or '<=' shouldn't have come here");
4848 emitcode("", "; genCmpEq");
4849 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4853 emitcode("", "; genAndOp");
4858 emitcode("", "; genOrOp");
4863 emitcode("", "; genXor");
4864 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4868 emitcode("", "; genOr");
4869 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4873 emitcode("", "; genAnd");
4874 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4878 emitcode("", "; genInline");
4883 emitcode("", "; genRRC");
4888 emitcode("", "; genRLC");
4893 emitcode("", "; genHBIT");
4897 emitcode("", "; genLeftShift");
4902 emitcode("", "; genRightShift");
4906 case GET_VALUE_AT_ADDRESS:
4907 emitcode("", "; genPointerGet");
4913 if (POINTER_SET(ic)) {
4914 emitcode("", "; genAssign (pointer)");
4918 emitcode("", "; genAssign");
4924 emitcode("", "; genIfx");
4929 emitcode("", "; genAddrOf");
4934 emitcode("", "; genJumpTab");
4939 emitcode("", "; genCast");
4944 emitcode("", "; genReceive");
4949 emitcode("", "; addSet");
4950 addSet(&sendSet,ic);
4955 /* piCode(ic,stdout); */
4961 /* now we are ready to call the
4962 peep hole optimizer */
4963 if (!options.nopeep)
4964 peepHole (&lineHead);
4966 /* This is unfortunate */
4967 /* now do the actual printing */
4969 FILE *fp = codeOutFile;
4970 if (isInHome() && codeOutFile == code->oFile)
4971 codeOutFile = home->oFile;
4972 printLine (lineHead, codeOutFile);
4973 if (_G.flush_statics) {
4975 _G.flush_statics = 0;