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 Michael Hope <michaelh@earthling.net> 2000
21 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
22 and - Jean-Louis VERN.jlvern@writeme.com (1999)
24 This program is free software; you can redistribute it and/or modify it
25 under the terms of the GNU General Public License as published by the
26 Free Software Foundation; either version 2, or (at your option) any
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 In other words, you are welcome to use, share and improve this program.
39 You are forbidden to forbid anyone else to use, share and improve
40 what you give them. Help stamp out software-hoarding!
42 -------------------------------------------------------------------------*/
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
54 #include "SDCCpeeph.h"
58 /* this is the down and dirty file with all kinds of kludgy & hacky
59 stuff. This is what it is all about CODE GENERATION for a specific MCU.
60 Some of the routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
66 static char *_z80_return[] = {"l", "h", "e", "d" };
67 static char *_gbz80_return[] = { "e", "d", "l", "h" };
68 static char **_fReturn;
71 static char *accUse[] = {"a" };
77 extern int ptrRegReq ;
79 extern FILE *codeOutFile;
81 const char *_shortJP = "jp";
97 } _pairs[NUM_PAIRS] = {
102 { "iy", "iy.l?", "iy.h?" },
103 { "ix", "ix.l?", "ix.h?" }
106 #define RESULTONSTACK(x) \
107 (IC_RESULT(x) && IC_RESULT(x)->aop && \
108 IC_RESULT(x)->aop->type == AOP_STK )
110 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
111 #define CLRC emitcode("xor","a,a");
113 #define LABEL_STR "%05d$"
115 lineNode *lineHead = NULL;
116 lineNode *lineCurr = NULL;
118 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
119 0xE0, 0xC0, 0x80, 0x00};
120 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
121 0x07, 0x03, 0x01, 0x00};
149 static char *aopGet(asmop *aop, int offset, bool bit16);
151 /*-----------------------------------------------------------------*/
152 /* emitcode - writes the code into a file : for now it is simple */
153 /*-----------------------------------------------------------------*/
154 void emitcode (const char *inst, const char *fmt, ...)
157 char lb[MAX_INLINEASM];
163 sprintf(lb,"%s\t",inst);
164 vsprintf(lb+(strlen(lb)),fmt,ap);
168 while (isspace(*lbp)) lbp++;
171 lineCurr = (lineCurr ?
172 connectLine(lineCurr,newLineNode(lb)) :
173 (lineHead = newLineNode(lb)));
174 lineCurr->isInline = inLine;
175 lineCurr->isDebug = debugLine;
179 const char *getPairName(asmop *aop)
181 if (aop->type == AOP_REG) {
182 switch (aop->aopu.aop_reg[0]->rIdx) {
194 else if (aop->type == AOP_STR) {
195 switch (*aop->aopu.aop_str[0]) {
211 static PAIR_ID getPairId(asmop *aop)
213 if (aop->size == 2) {
214 if (aop->type == AOP_REG) {
215 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
218 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
221 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
225 if (aop->type == AOP_STR) {
226 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
229 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
232 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
240 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
241 bool isPair(asmop *aop)
243 return (getPairId(aop) != PAIR_INVALID);
246 bool isPtrPair(asmop *aop)
248 PAIR_ID pairId = getPairId(aop);
258 /** Push a register pair onto the stack */
259 void genPairPush(asmop *aop)
261 emitcode("push", "%s", getPairName(aop));
264 static char *_strdup(const char *s)
267 ALLOC_ATOMIC(ret, strlen(s)+1);
273 /*-----------------------------------------------------------------*/
274 /* newAsmop - creates a new asmOp */
275 /*-----------------------------------------------------------------*/
276 static asmop *newAsmop (short type)
280 ALLOC(aop,sizeof(asmop));
285 /*-----------------------------------------------------------------*/
286 /* aopForSym - for a true symbol */
287 /*-----------------------------------------------------------------*/
288 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
291 memmap *space= SPEC_OCLS(sym->etype);
293 /* if already has one */
297 /* Assign depending on the storage class */
298 if (sym->onStack || sym->iaccess) {
299 sym->aop = aop = newAsmop(AOP_STK);
300 aop->size = getSize(sym->type);
301 aop->aopu.aop_stk = sym->stack;
305 /* special case for a function */
306 if (IS_FUNC(sym->type)) {
307 sym->aop = aop = newAsmop(AOP_IMMD);
308 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
309 strcpy(aop->aopu.aop_immd,sym->rname);
316 /* if it is in direct space */
317 if (IN_DIRSPACE(space)) {
318 sym->aop = aop = newAsmop (AOP_DIR);
319 aop->aopu.aop_dir = sym->rname ;
320 aop->size = getSize(sym->type);
321 emitcode("", "; AOP_DIR for %s", sym->rname);
327 /* only remaining is far space */
328 /* in which case DPTR gets the address */
330 sym->aop = aop = newAsmop(AOP_HL);
333 sym->aop = aop = newAsmop(AOP_IY);
335 aop->size = getSize(sym->type);
336 aop->aopu.aop_dir = sym->rname;
338 /* if it is in code space */
339 if (IN_CODESPACE(space))
345 /*-----------------------------------------------------------------*/
346 /* aopForRemat - rematerialzes an object */
347 /*-----------------------------------------------------------------*/
348 static asmop *aopForRemat (symbol *sym)
351 iCode *ic = sym->rematiCode;
352 asmop *aop = newAsmop(AOP_IMMD);
355 /* if plus or minus print the right hand side */
356 if (ic->op == '+' || ic->op == '-') {
357 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
360 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
363 /* we reached the end */
364 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
368 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
369 strcpy(aop->aopu.aop_immd,buffer);
373 /*-----------------------------------------------------------------*/
374 /* regsInCommon - two operands have some registers in common */
375 /*-----------------------------------------------------------------*/
376 bool regsInCommon (operand *op1, operand *op2)
381 /* if they have registers in common */
382 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
385 sym1 = OP_SYMBOL(op1);
386 sym2 = OP_SYMBOL(op2);
388 if (sym1->nRegs == 0 || sym2->nRegs == 0)
391 for (i = 0 ; i < sym1->nRegs ; i++) {
396 for (j = 0 ; j < sym2->nRegs ;j++ ) {
400 if (sym2->regs[j] == sym1->regs[i])
408 /*-----------------------------------------------------------------*/
409 /* operandsEqu - equivalent */
410 /*-----------------------------------------------------------------*/
411 bool operandsEqu ( operand *op1, operand *op2)
415 /* if they not symbols */
416 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
419 sym1 = OP_SYMBOL(op1);
420 sym2 = OP_SYMBOL(op2);
422 /* if both are itemps & one is spilt
423 and the other is not then false */
424 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
425 sym1->isspilt != sym2->isspilt )
428 /* if they are the same */
432 if (strcmp(sym1->rname,sym2->rname) == 0)
436 /* if left is a tmp & right is not */
440 (sym1->usl.spillLoc == sym2))
447 (sym2->usl.spillLoc == sym1))
453 /*-----------------------------------------------------------------*/
454 /* sameRegs - two asmops have the same registers */
455 /*-----------------------------------------------------------------*/
456 bool sameRegs (asmop *aop1, asmop *aop2 )
463 if (aop1->type != AOP_REG ||
464 aop2->type != AOP_REG )
467 if (aop1->size != aop2->size)
470 for (i = 0 ; i < aop1->size ; i++ )
471 if (aop1->aopu.aop_reg[i] !=
472 aop2->aopu.aop_reg[i] )
478 /*-----------------------------------------------------------------*/
479 /* aopOp - allocates an asmop for an operand : */
480 /*-----------------------------------------------------------------*/
481 static void aopOp (operand *op, iCode *ic, bool result)
490 /* if this a literal */
491 if (IS_OP_LITERAL(op)) {
492 op->aop = aop = newAsmop(AOP_LIT);
493 aop->aopu.aop_lit = op->operand.valOperand;
494 aop->size = getSize(operandType(op));
498 /* if already has a asmop then continue */
502 /* if the underlying symbol has a aop */
503 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
504 op->aop = OP_SYMBOL(op)->aop;
508 /* if this is a true symbol */
509 if (IS_TRUE_SYMOP(op)) {
510 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
514 /* this is a temporary : this has
520 e) can be a return use only */
524 /* if the type is a conditional */
525 if (sym->regType == REG_CND) {
526 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
531 /* if it is spilt then two situations
533 b) has a spill location */
534 if (sym->isspilt || sym->nRegs == 0) {
535 /* rematerialize it NOW */
537 sym->aop = op->aop = aop =
539 aop->size = getSize(sym->type);
545 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
546 aop->size = getSize(sym->type);
547 for ( i = 0 ; i < 2 ; i++ )
548 aop->aopu.aop_str[i] = accUse[i];
554 aop = op->aop = sym->aop = newAsmop(AOP_STR);
555 aop->size = getSize(sym->type);
556 for ( i = 0 ; i < 4 ; i++ )
557 aop->aopu.aop_str[i] = _fReturn[i];
561 /* else spill location */
562 sym->aop = op->aop = aop =
563 aopForSym(ic,sym->usl.spillLoc,result);
564 aop->size = getSize(sym->type);
568 /* must be in a register */
569 sym->aop = op->aop = aop = newAsmop(AOP_REG);
570 aop->size = sym->nRegs;
571 for ( i = 0 ; i < sym->nRegs ;i++)
572 aop->aopu.aop_reg[i] = sym->regs[i];
575 /*-----------------------------------------------------------------*/
576 /* freeAsmop - free up the asmop given to an operand */
577 /*----------------------------------------------------------------*/
578 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
596 /* all other cases just dealloc */
600 OP_SYMBOL(op)->aop = NULL;
601 /* if the symbol has a spill */
603 SPIL_LOC(op)->aop = NULL;
608 bool isLitWord(asmop *aop)
610 /* if (aop->size != 2)
621 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
627 if (aop->size != 2 && aop->type != AOP_HL)
630 wassert(offset == 0);
632 /* depending on type */
637 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
638 ALLOC_ATOMIC(rs,strlen(s)+1);
642 value * val = aop->aopu.aop_lit;
643 /* if it is a float then it gets tricky */
644 /* otherwise it is fairly simple */
645 if (!IS_FLOAT(val->type)) {
646 unsigned long v = floatFromVal(val);
648 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
649 ALLOC_ATOMIC(rs,strlen(buffer)+1);
650 return strcpy (rs,buffer);
660 char *aopGetWord(asmop *aop, int offset)
662 return aopGetLitWordLong(aop, offset, TRUE);
665 bool isPtr(const char *s)
667 if (!strcmp(s, "hl"))
669 if (!strcmp(s, "ix"))
671 if (!strcmp(s, "iy"))
676 static void adjustPair(const char *pair, int *pold, int new)
680 while (*pold < new) {
681 emitcode("inc", "%s", pair);
684 while (*pold > new) {
685 emitcode("dec", "%s", pair);
690 static void spillPair(PAIR_ID pairId)
692 _G.pairs[pairId].last_type = AOP_INVALID;
693 _G.pairs[pairId].lit = NULL;
696 static void spillCached(void)
702 static bool requiresHL(asmop *aop)
713 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
716 const char *pair = _pairs[pairId].name;
717 l = aopGetLitWordLong(left, 0, FALSE);
721 if (pairId == PAIR_HL || pairId == PAIR_IY) {
722 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
723 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
724 adjustPair(pair, &_G.pairs[pairId].offset, offset);
727 if (pairId == PAIR_IY && abs(offset)<127) {
732 _G.pairs[pairId].last_type = left->type;
733 _G.pairs[pairId].lit = _strdup(l);
734 _G.pairs[pairId].offset = offset;
736 /* Both a lit on the right and a true symbol on the left */
738 emitcode("ld", "%s,#%s + %d", pair, l, offset);
740 emitcode("ld", "%s,#%s", pair, l);
743 static void fetchPair(PAIR_ID pairId, asmop *aop)
745 /* if this is remateriazable */
746 if (isLitWord(aop)) {
747 fetchLitPair(pairId, aop, 0);
749 else { /* we need to get it byte by byte */
750 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
751 aopGet(aop, 0, FALSE);
752 emitcode("ld", "a,(hl+)");
753 emitcode("ld", "h,(hl)");
754 emitcode("ld", "l,a");
757 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, 0, FALSE));
758 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, 1, FALSE));
760 /* PENDING: check? */
761 if (pairId == PAIR_HL)
766 static void fetchHL(asmop *aop)
768 fetchPair(PAIR_HL, aop);
771 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
773 assert(pairId == PAIR_HL || pairId == PAIR_IY);
778 fetchLitPair(pairId, aop, offset);
779 _G.pairs[pairId].offset = offset;
782 /* Doesnt include _G.stack.pushed */
783 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
784 assert(pairId == PAIR_HL);
785 /* In some cases we can still inc or dec hl */
786 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
787 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
790 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _G.stack.pushed, _G.stack.offset);
792 _G.pairs[pairId].offset = abso;
798 _G.pairs[pairId].last_type = aop->type;
801 static void emitLabel(int key)
803 emitcode("", LABEL_STR ":", key);
807 /*-----------------------------------------------------------------*/
808 /* aopGet - for fetching value of the aop */
809 /*-----------------------------------------------------------------*/
810 static char *aopGet(asmop *aop, int offset, bool bit16)
815 /* offset is greater than size then zero */
816 /* PENDING: this seems a bit screwed in some pointer cases. */
817 if (offset > (aop->size - 1) &&
818 aop->type != AOP_LIT)
821 /* depending on type */
825 sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
828 wassert(offset == 1);
835 ALLOC_ATOMIC(rs,strlen(s)+1);
841 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
843 ALLOC_ATOMIC(rs,strlen(s)+1);
848 return aop->aopu.aop_reg[offset]->name;
853 setupPair(PAIR_HL, aop, offset);
855 return _strdup("(hl)");
859 setupPair(PAIR_IY, aop, offset);
860 sprintf(s,"%d(iy)", offset);
861 ALLOC_ATOMIC(rs,strlen(s)+1);
867 setupPair(PAIR_HL, aop, offset);
871 sprintf(s,"%d(ix)", aop->aopu.aop_stk+offset);
873 ALLOC_ATOMIC(rs,strlen(s)+1);
887 return aopLiteral (aop->aopu.aop_lit,offset);
891 return aop->aopu.aop_str[offset];
895 wassertl(0, "aopget got unsupported aop->type");
899 bool isRegString(char *s)
901 if (!strcmp(s, "b") ||
912 bool isConstant(const char *s)
917 bool canAssignToPtr(char *s)
926 /*-----------------------------------------------------------------*/
927 /* aopPut - puts a string for a aop */
928 /*-----------------------------------------------------------------*/
929 static void aopPut (asmop *aop, char *s, int offset)
931 if (aop->size && offset > ( aop->size - 1)) {
932 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
933 "aopPut got offset > aop->size");
937 /* will assign value to value */
938 /* depending on where it is ofcourse */
943 emitcode("ld", "a,%s", s);
944 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
948 /* Dont bother if it's a ld x,x */
949 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
950 emitcode("ld","%s,%s",
951 aop->aopu.aop_reg[offset]->name,s);
957 setupPair(PAIR_IY, aop, offset);
958 if (!canAssignToPtr(s)) {
959 emitcode("ld", "a,%s", s);
960 emitcode("ld", "%d(iy),a", offset);
963 emitcode("ld", "%d(iy),%s", offset, s);
968 if (!strcmp(s, "(hl)")) {
969 emitcode("ld", "a,(hl)");
973 setupPair(PAIR_HL, aop, offset);
974 emitcode("ld", "(hl),%s", s);
979 if (!strcmp("(hl)", s)) {
980 emitcode("ld", "a,(hl)");
983 setupPair(PAIR_HL, aop, offset);
984 if (!canAssignToPtr(s)) {
985 emitcode("ld", "a,%s", s);
986 emitcode("ld", "(hl),a");
989 emitcode("ld", "(hl),%s", s);
992 if (!canAssignToPtr(s)) {
993 emitcode("ld", "a,%s", s);
994 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
997 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
1002 /* if bit variable */
1003 if (!aop->aopu.aop_dir) {
1004 emitcode("ld", "a,#0");
1005 emitcode("rla", "");
1007 /* In bit space but not in C - cant happen */
1014 if (strcmp(aop->aopu.aop_str[offset],s)) {
1015 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1021 if (!offset && (strcmp(s,"acc") == 0))
1025 emitcode("", "; Error aopPut AOP_ACC");
1028 if (strcmp(aop->aopu.aop_str[offset],s))
1029 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1034 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1035 "aopPut got unsupported aop->type");
1040 #define AOP(op) op->aop
1041 #define AOP_TYPE(op) AOP(op)->type
1042 #define AOP_SIZE(op) AOP(op)->size
1043 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1045 /*-----------------------------------------------------------------*/
1046 /* getDataSize - get the operand data size */
1047 /*-----------------------------------------------------------------*/
1048 int getDataSize(operand *op)
1051 size = AOP_SIZE(op);
1059 /*-----------------------------------------------------------------*/
1060 /* movLeft2Result - move byte from left to result */
1061 /*-----------------------------------------------------------------*/
1062 static void movLeft2Result (operand *left, int offl,
1063 operand *result, int offr, int sign)
1066 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1067 l = aopGet(AOP(left),offl,FALSE);
1070 aopPut(AOP(result),l,offr);
1079 /** Put Acc into a register set
1081 void outAcc(operand *result)
1084 size = getDataSize(result);
1086 aopPut(AOP(result),"a",0);
1089 /* unsigned or positive */
1091 aopPut(AOP(result),zero,offset++);
1096 /** Take the value in carry and put it into a register
1098 void outBitC(operand *result)
1100 /* if the result is bit */
1101 if (AOP_TYPE(result) == AOP_CRY) {
1102 emitcode("", "; Note: outBitC form 1");
1103 aopPut(AOP(result),"blah",0);
1106 emitcode("ld", "a,#0");
1107 emitcode("rla", "");
1112 /*-----------------------------------------------------------------*/
1113 /* toBoolean - emit code for orl a,operator(sizeop) */
1114 /*-----------------------------------------------------------------*/
1115 void toBoolean(operand *oper)
1117 int size = AOP_SIZE(oper);
1120 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1123 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1126 if (AOP(oper)->type != AOP_ACC) {
1128 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1133 /*-----------------------------------------------------------------*/
1134 /* genNot - generate code for ! operation */
1135 /*-----------------------------------------------------------------*/
1136 static void genNot (iCode *ic)
1138 link *optype = operandType(IC_LEFT(ic));
1140 /* assign asmOps to operand & result */
1141 aopOp (IC_LEFT(ic),ic,FALSE);
1142 aopOp (IC_RESULT(ic),ic,TRUE);
1144 /* if in bit space then a special case */
1145 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1149 /* if type float then do float */
1150 if (IS_FLOAT(optype)) {
1154 toBoolean(IC_LEFT(ic));
1159 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1160 emitcode("sub", "a,#0x01");
1161 outBitC(IC_RESULT(ic));
1163 /* release the aops */
1164 freeAsmop(IC_LEFT(ic),NULL,ic);
1165 freeAsmop(IC_RESULT(ic),NULL,ic);
1168 /*-----------------------------------------------------------------*/
1169 /* genCpl - generate code for complement */
1170 /*-----------------------------------------------------------------*/
1171 static void genCpl (iCode *ic)
1177 /* assign asmOps to operand & result */
1178 aopOp (IC_LEFT(ic),ic,FALSE);
1179 aopOp (IC_RESULT(ic),ic,TRUE);
1181 /* if both are in bit space then
1183 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1184 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1188 size = AOP_SIZE(IC_RESULT(ic));
1190 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1193 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1196 /* release the aops */
1197 freeAsmop(IC_LEFT(ic),NULL,ic);
1198 freeAsmop(IC_RESULT(ic),NULL,ic);
1201 /*-----------------------------------------------------------------*/
1202 /* genUminus - unary minus code generation */
1203 /*-----------------------------------------------------------------*/
1204 static void genUminus (iCode *ic)
1207 link *optype, *rtype;
1210 aopOp(IC_LEFT(ic),ic,FALSE);
1211 aopOp(IC_RESULT(ic),ic,TRUE);
1213 /* if both in bit space then special
1215 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1216 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1221 optype = operandType(IC_LEFT(ic));
1222 rtype = operandType(IC_RESULT(ic));
1224 /* if float then do float stuff */
1225 if (IS_FLOAT(optype)) {
1230 /* otherwise subtract from zero */
1231 size = AOP_SIZE(IC_LEFT(ic));
1235 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1236 emitcode("ld", "a,#0");
1237 emitcode("sbc","a,%s",l);
1238 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1241 /* if any remaining bytes in the result */
1242 /* we just need to propagate the sign */
1243 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1244 emitcode("rlc","a");
1245 emitcode("sbc","a,a");
1247 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1251 /* release the aops */
1252 freeAsmop(IC_LEFT(ic),NULL,ic);
1253 freeAsmop(IC_RESULT(ic),NULL,ic);
1256 /*-----------------------------------------------------------------*/
1257 /* assignResultValue - */
1258 /*-----------------------------------------------------------------*/
1259 void assignResultValue(operand * oper)
1262 int size = AOP_SIZE(oper);
1267 aopPut(AOP(oper),_fReturn[offset],offset);
1272 /*-----------------------------------------------------------------*/
1273 /* genIpush - genrate code for pushing this gets a little complex */
1274 /*-----------------------------------------------------------------*/
1275 static void genIpush (iCode *ic)
1277 int size, offset = 0 ;
1281 /* if this is not a parm push : ie. it is spill push
1282 and spill push is always done on the local stack */
1283 if (!ic->parmPush) {
1284 /* and the item is spilt then do nothing */
1285 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1288 aopOp(IC_LEFT(ic),ic,FALSE);
1289 size = AOP_SIZE(IC_LEFT(ic));
1290 /* push it on the stack */
1291 if (isPair(AOP(IC_LEFT(ic)))) {
1292 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1293 _G.stack.pushed += 2;
1298 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1299 /* Simple for now - load into A and PUSH AF */
1300 emitcode("ld", "a,%s", l);
1301 emitcode("push", "af");
1302 emitcode("inc", "sp");
1309 /* Hmmm... what about saving the currently used registers
1312 /* then do the push */
1313 aopOp(IC_LEFT(ic),ic,FALSE);
1315 size = AOP_SIZE(IC_LEFT(ic));
1317 if (isPair(AOP(IC_LEFT(ic)))) {
1319 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1323 fetchHL(AOP(IC_LEFT(ic)));
1324 emitcode("push", "hl ; 2");
1326 _G.stack.pushed += 2;
1331 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1332 emitcode("ld", "a,%s", l);
1333 emitcode("push", "af");
1334 emitcode("inc", "sp");
1339 freeAsmop(IC_LEFT(ic),NULL,ic);
1342 /*-----------------------------------------------------------------*/
1343 /* genIpop - recover the registers: can happen only for spilling */
1344 /*-----------------------------------------------------------------*/
1345 static void genIpop (iCode *ic)
1350 /* if the temp was not pushed then */
1351 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1354 aopOp(IC_LEFT(ic),ic,FALSE);
1355 size = AOP_SIZE(IC_LEFT(ic));
1357 if (isPair(AOP(IC_LEFT(ic)))) {
1358 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1362 emitcode("dec", "sp");
1363 emitcode("pop", "hl");
1365 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1369 freeAsmop(IC_LEFT(ic),NULL,ic);
1372 /** Emit the code for a call statement
1374 static void emitCall (iCode *ic, bool ispcall)
1376 /* if caller saves & we have not saved then */
1377 if (!ic->regsSaved) {
1381 /* if send set is not empty then assign */
1384 for (sic = setFirstItem(sendSet) ; sic ;
1385 sic = setNextItem(sendSet)) {
1386 int size, offset = 0;
1387 aopOp(IC_LEFT(sic),sic,FALSE);
1388 size = AOP_SIZE(IC_LEFT(sic));
1390 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1392 if (strcmp(l, _fReturn[offset]))
1393 emitcode("ld","%s,%s",
1398 freeAsmop (IC_LEFT(sic),NULL,sic);
1404 aopOp(IC_LEFT(ic),ic,FALSE);
1406 if (isLitWord(AOP(IC_LEFT(ic)))) {
1407 emitcode("", "; Special case where the pCall is to a constant");
1408 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1411 symbol *rlbl = newiTempLabel(NULL);
1413 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1414 emitcode("push", "hl");
1415 _G.stack.pushed += 2;
1417 fetchHL(AOP(IC_LEFT(ic)));
1418 emitcode("jp", "(hl)");
1419 emitcode("","%05d$:",(rlbl->key+100));
1420 _G.stack.pushed -= 2;
1422 freeAsmop(IC_LEFT(ic),NULL,ic);
1426 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1427 OP_SYMBOL(IC_LEFT(ic))->rname :
1428 OP_SYMBOL(IC_LEFT(ic))->name;
1429 emitcode("call", "%s", name);
1433 /* if we need assign a result value */
1434 if ((IS_ITEMP(IC_RESULT(ic)) &&
1435 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1436 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1437 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1440 aopOp(IC_RESULT(ic),ic,FALSE);
1443 assignResultValue(IC_RESULT(ic));
1445 freeAsmop(IC_RESULT(ic),NULL, ic);
1448 /* adjust the stack for parameters if required */
1449 if (IC_LEFT(ic)->parmBytes) {
1450 int i = IC_LEFT(ic)->parmBytes;
1451 _G.stack.pushed -= i;
1453 emitcode("lda", "sp,%d(sp)", i);
1458 emitcode("ld", "hl,#%d", i);
1459 emitcode("add", "hl,sp");
1460 emitcode("ld", "sp,hl");
1464 emitcode("pop", "hl");
1468 emitcode("inc", "sp");
1476 /*-----------------------------------------------------------------*/
1477 /* genCall - generates a call statement */
1478 /*-----------------------------------------------------------------*/
1479 static void genCall (iCode *ic)
1481 emitCall(ic, FALSE);
1484 /*-----------------------------------------------------------------*/
1485 /* genPcall - generates a call by pointer statement */
1486 /*-----------------------------------------------------------------*/
1487 static void genPcall (iCode *ic)
1492 /*-----------------------------------------------------------------*/
1493 /* resultRemat - result is rematerializable */
1494 /*-----------------------------------------------------------------*/
1495 static int resultRemat (iCode *ic)
1497 if (SKIP_IC(ic) || ic->op == IFX)
1500 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1501 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1502 if (sym->remat && !POINTER_SET(ic))
1509 /*-----------------------------------------------------------------*/
1510 /* genFunction - generated code for function entry */
1511 /*-----------------------------------------------------------------*/
1512 static void genFunction (iCode *ic)
1514 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1518 /* create the function header */
1519 emitcode(";","-----------------------------------------");
1520 emitcode(";"," function %s", sym->name);
1521 emitcode(";","-----------------------------------------");
1523 emitcode("", "__%s_start:", sym->rname);
1524 emitcode("","%s:",sym->rname);
1526 fetype = getSpec(operandType(IC_LEFT(ic)));
1528 /* if critical function then turn interrupts off */
1529 if (SPEC_CRTCL(fetype))
1532 /* if this is an interrupt service routine then
1533 save acc, b, dpl, dph */
1534 if (IS_ISR(sym->etype)) {
1535 emitcode("push", "af");
1536 emitcode("push", "bc");
1537 emitcode("push", "de");
1538 emitcode("push", "hl");
1540 /* PENDING: callee-save etc */
1542 /* adjust the stack for the function */
1543 emitcode("push", "bc");
1545 emitcode("push", "de");
1546 emitcode("push", "ix");
1547 emitcode("ld", "ix,#0");
1548 emitcode("add", "ix,sp");
1551 _G.stack.last = sym->stack;
1555 emitcode("lda", "sp,-%d(sp)", sym->stack);
1558 emitcode("ld", "hl,#-%d", sym->stack);
1559 emitcode("add", "hl,sp");
1560 emitcode("ld", "sp,hl");
1563 _G.stack.offset = sym->stack;
1566 /*-----------------------------------------------------------------*/
1567 /* genEndFunction - generates epilogue for functions */
1568 /*-----------------------------------------------------------------*/
1569 static void genEndFunction (iCode *ic)
1571 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1573 if (IS_ISR(sym->etype)) {
1577 if (SPEC_CRTCL(sym->etype))
1580 /* PENDING: calleeSave */
1582 /* if debug then send end of function */
1583 if (options.debug && currFunc) {
1585 emitcode("","C$%s$%d$%d$%d ==.",
1586 ic->filename,currFunc->lastLine,
1587 ic->level,ic->block);
1588 if (IS_STATIC(currFunc->etype))
1589 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1591 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1595 emitcode("ld", "sp,ix");
1596 emitcode("pop", "ix");
1597 emitcode("pop", "de");
1600 if (_G.stack.offset) {
1601 emitcode("ld", "hl,#%d", _G.stack.offset);
1602 emitcode("add", "hl,sp");
1603 emitcode("ld", "sp,hl");
1606 emitcode("pop", "bc");
1607 emitcode("ret", "");
1608 emitcode("; Useful for profiling and debugging", "");
1609 emitcode(".dw", "%s", sym->rname);
1610 emitcode("", "__%s_end:", sym->rname);
1612 _G.stack.pushed = 0;
1613 _G.stack.offset = 0;
1616 /*-----------------------------------------------------------------*/
1617 /* genRet - generate code for return statement */
1618 /*-----------------------------------------------------------------*/
1619 static void genRet (iCode *ic)
1622 /* Errk. This is a hack until I can figure out how
1623 to cause dehl to spill on a call */
1624 int size,offset = 0;
1626 /* if we have no return value then
1627 just generate the "ret" */
1631 /* we have something to return then
1632 move the return value into place */
1633 aopOp(IC_LEFT(ic),ic,FALSE);
1634 size = AOP_SIZE(IC_LEFT(ic));
1636 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1638 emitcode("ld", "de,%s", l);
1641 emitcode("ld", "hl,%s", l);
1646 l = aopGet(AOP(IC_LEFT(ic)),offset,
1648 if (strcmp(_fReturn[offset],l))
1649 emitcode("ld","%s,%s", _fReturn[offset++],l);
1652 freeAsmop (IC_LEFT(ic),NULL,ic);
1655 /* generate a jump to the return label
1656 if the next is not the return statement */
1657 if (!(ic->next && ic->next->op == LABEL &&
1658 IC_LABEL(ic->next) == returnLabel))
1660 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1663 /*-----------------------------------------------------------------*/
1664 /* genLabel - generates a label */
1665 /*-----------------------------------------------------------------*/
1666 static void genLabel (iCode *ic)
1668 /* special case never generate */
1669 if (IC_LABEL(ic) == entryLabel)
1672 emitLabel(IC_LABEL(ic)->key+100);
1675 /*-----------------------------------------------------------------*/
1676 /* genGoto - generates a ljmp */
1677 /*-----------------------------------------------------------------*/
1678 static void genGoto (iCode *ic)
1680 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1683 /*-----------------------------------------------------------------*/
1684 /* genPlusIncr :- does addition with increment if possible */
1685 /*-----------------------------------------------------------------*/
1686 static bool genPlusIncr (iCode *ic)
1688 unsigned int icount ;
1689 unsigned int size = getDataSize(IC_RESULT(ic));
1690 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
1692 /* will try to generate an increment */
1693 /* if the right side is not a literal
1695 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1698 emitcode("", "; genPlusIncr");
1700 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1702 /* If result is a pair */
1703 if (resultId != PAIR_INVALID) {
1704 if (isLitWord(AOP(IC_LEFT(ic)))) {
1705 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1708 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
1709 fetchPair(resultId, AOP(IC_RIGHT(ic)));
1710 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
1716 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1719 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1720 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1723 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1728 /* if the literal value of the right hand side
1729 is greater than 4 then it is not worth it */
1733 /* if increment 16 bits in register */
1734 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1737 symbol *tlbl = newiTempLabel(NULL);
1738 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1739 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1741 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1745 emitLabel(tlbl->key+100);
1749 /* if the sizes are greater than 1 then we cannot */
1750 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1751 AOP_SIZE(IC_LEFT(ic)) > 1 )
1754 /* we can if the aops of the left & result match or
1755 if they are in registers and the registers are the
1757 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1759 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1767 /*-----------------------------------------------------------------*/
1768 /* outBitAcc - output a bit in acc */
1769 /*-----------------------------------------------------------------*/
1770 void outBitAcc(operand *result)
1772 symbol *tlbl = newiTempLabel(NULL);
1773 /* if the result is a bit */
1774 if (AOP_TYPE(result) == AOP_CRY){
1778 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1779 emitcode("ld","a,%s",one);
1780 emitLabel(tlbl->key+100);
1785 /*-----------------------------------------------------------------*/
1786 /* genPlus - generates code for addition */
1787 /*-----------------------------------------------------------------*/
1788 static void genPlus (iCode *ic)
1790 int size, offset = 0;
1792 /* special cases :- */
1794 aopOp (IC_LEFT(ic),ic,FALSE);
1795 aopOp (IC_RIGHT(ic),ic,FALSE);
1796 aopOp (IC_RESULT(ic),ic,TRUE);
1798 /* Swap the left and right operands if:
1800 if literal, literal on the right or
1801 if left requires ACC or right is already
1804 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1805 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1806 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1807 operand *t = IC_RIGHT(ic);
1808 IC_RIGHT(ic) = IC_LEFT(ic);
1812 /* if both left & right are in bit
1814 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1815 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1820 /* if left in bit space & right literal */
1821 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1822 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1823 /* Can happen I guess */
1827 /* if I can do an increment instead
1828 of add then GOOD for ME */
1829 if (genPlusIncr (ic) == TRUE)
1832 size = getDataSize(IC_RESULT(ic));
1834 /* Special case when left and right are constant */
1835 if (isPair(AOP(IC_RESULT(ic)))) {
1838 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1839 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1840 if (left && right) {
1844 sprintf(buffer, "#(%s + %s)", left, right);
1845 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1850 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1851 /* Fetch into HL then do the add */
1853 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1854 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1859 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1860 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1862 emitcode("add","a,%s",
1863 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1865 emitcode("adc","a,%s",
1866 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1868 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1870 emitcode("add","a,%s",
1871 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1873 emitcode("adc","a,%s",
1874 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1876 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1879 /* Some kind of pointer arith. */
1880 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1881 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1882 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1885 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1886 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1887 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1892 freeAsmop(IC_LEFT(ic),NULL,ic);
1893 freeAsmop(IC_RIGHT(ic),NULL,ic);
1894 freeAsmop(IC_RESULT(ic),NULL,ic);
1898 /*-----------------------------------------------------------------*/
1899 /* genMinusDec :- does subtraction with deccrement if possible */
1900 /*-----------------------------------------------------------------*/
1901 static bool genMinusDec (iCode *ic)
1903 unsigned int icount ;
1904 unsigned int size = getDataSize(IC_RESULT(ic));
1906 /* will try to generate an increment */
1907 /* if the right side is not a literal we cannot */
1908 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1911 /* if the literal value of the right hand side
1912 is greater than 4 then it is not worth it */
1913 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1916 size = getDataSize(IC_RESULT(ic));
1919 /* if increment 16 bits in register */
1920 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1923 symbol *tlbl = newiTempLabel(NULL);
1924 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1925 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1927 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1931 emitLabel(tlbl->key+100);
1936 /* if decrement 16 bits in register */
1937 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1938 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1940 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1944 /* If result is a pair */
1945 if (isPair(AOP(IC_RESULT(ic)))) {
1946 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1947 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1949 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1953 /* if the sizes are greater than 1 then we cannot */
1954 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1955 AOP_SIZE(IC_LEFT(ic)) > 1 )
1958 /* we can if the aops of the left & result match or if they are in
1959 registers and the registers are the same */
1960 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1962 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1969 /*-----------------------------------------------------------------*/
1970 /* genMinus - generates code for subtraction */
1971 /*-----------------------------------------------------------------*/
1972 static void genMinus (iCode *ic)
1974 int size, offset = 0;
1975 unsigned long lit = 0L;
1977 aopOp (IC_LEFT(ic),ic,FALSE);
1978 aopOp (IC_RIGHT(ic),ic,FALSE);
1979 aopOp (IC_RESULT(ic),ic,TRUE);
1981 /* special cases :- */
1982 /* if both left & right are in bit space */
1983 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1984 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1989 /* if I can do an decrement instead of subtract then GOOD for ME */
1990 if (genMinusDec (ic) == TRUE)
1993 size = getDataSize(IC_RESULT(ic));
1995 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1998 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2003 /* if literal, add a,#-lit, else normal subb */
2005 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2006 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2008 emitcode("sub","a,%s",
2009 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2011 emitcode("sbc","a,%s",
2012 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2015 /* first add without previous c */
2017 emitcode("add","a,#0x%02x",
2018 (unsigned int)(lit & 0x0FFL));
2020 emitcode("adc","a,#0x%02x",
2021 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2023 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2026 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2027 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2028 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2032 freeAsmop(IC_LEFT(ic),NULL,ic);
2033 freeAsmop(IC_RIGHT(ic),NULL,ic);
2034 freeAsmop(IC_RESULT(ic),NULL,ic);
2037 /*-----------------------------------------------------------------*/
2038 /* genMult - generates code for multiplication */
2039 /*-----------------------------------------------------------------*/
2040 static void genMult (iCode *ic)
2042 /* Shouldn't occur - all done through function calls */
2046 /*-----------------------------------------------------------------*/
2047 /* genDiv - generates code for division */
2048 /*-----------------------------------------------------------------*/
2049 static void genDiv (iCode *ic)
2051 /* Shouldn't occur - all done through function calls */
2055 /*-----------------------------------------------------------------*/
2056 /* genMod - generates code for division */
2057 /*-----------------------------------------------------------------*/
2058 static void genMod (iCode *ic)
2060 /* Shouldn't occur - all done through function calls */
2064 /*-----------------------------------------------------------------*/
2065 /* genIfxJump :- will create a jump depending on the ifx */
2066 /*-----------------------------------------------------------------*/
2067 static void genIfxJump (iCode *ic, char *jval)
2072 /* if true label then we jump if condition
2074 if ( IC_TRUE(ic) ) {
2076 if (!strcmp(jval, "a")) {
2079 else if (!strcmp(jval, "c")) {
2083 /* The buffer contains the bit on A that we should test */
2088 /* false label is present */
2089 jlbl = IC_FALSE(ic) ;
2090 if (!strcmp(jval, "a")) {
2093 else if (!strcmp(jval, "c")) {
2097 /* The buffer contains the bit on A that we should test */
2101 /* Z80 can do a conditional long jump */
2102 if (!strcmp(jval, "a")) {
2103 emitcode("or", "a,a");
2105 else if (!strcmp(jval, "c")) {
2108 emitcode("bit", "%s,a", jval);
2110 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
2112 /* mark the icode as generated */
2116 /** Generic compare for > or <
2118 static void genCmp (operand *left,operand *right,
2119 operand *result, iCode *ifx, int sign)
2121 int size, offset = 0 ;
2122 unsigned long lit = 0L;
2124 /* if left & right are bit variables */
2125 if (AOP_TYPE(left) == AOP_CRY &&
2126 AOP_TYPE(right) == AOP_CRY ) {
2127 /* Cant happen on the Z80 */
2130 /* subtract right from left if at the
2131 end the carry flag is set then we know that
2132 left is greater than right */
2133 size = max(AOP_SIZE(left),AOP_SIZE(right));
2135 /* if unsigned char cmp with lit, just compare */
2137 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2138 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2140 emitcode("xor", "a,#0x80");
2141 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
2144 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
2147 if(AOP_TYPE(right) == AOP_LIT) {
2148 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2149 /* optimize if(x < 0) or if(x >= 0) */
2152 /* No sign so it's always false */
2156 /* Just load in the top most bit */
2157 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2158 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2159 genIfxJump (ifx,"7");
2163 emitcode("rlc","a");
2169 /* First setup h and l contaning the top most bytes XORed */
2170 bool fDidXor = FALSE;
2171 if (AOP_TYPE(left) == AOP_LIT){
2172 unsigned long lit = (unsigned long)
2173 floatFromVal(AOP(left)->aopu.aop_lit);
2174 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2175 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2178 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2179 emitcode("xor", "a,#0x80");
2180 emitcode("ld", "%s,a", _fTmp[0]);
2183 if (AOP_TYPE(right) == AOP_LIT) {
2184 unsigned long lit = (unsigned long)
2185 floatFromVal(AOP(right)->aopu.aop_lit);
2186 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2187 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2190 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2191 emitcode("xor", "a,#0x80");
2192 emitcode("ld", "%s,a", _fTmp[1]);
2202 /* Do a long subtract */
2203 if (!sign || size ) {
2204 MOVA(aopGet(AOP(left),offset,FALSE));
2206 if (sign && size == 0) {
2207 emitcode("ld", "a,%s", _fTmp[0]);
2208 emitcode("sbc", "a,%s", _fTmp[1]);
2211 /* Subtract through, propagating the carry */
2212 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2219 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2222 /* if the result is used in the next
2223 ifx conditional branch then generate
2224 code a little differently */
2226 genIfxJump (ifx,"c");
2229 /* leave the result in acc */
2233 /*-----------------------------------------------------------------*/
2234 /* genCmpGt :- greater than comparison */
2235 /*-----------------------------------------------------------------*/
2236 static void genCmpGt (iCode *ic, iCode *ifx)
2238 operand *left, *right, *result;
2239 link *letype , *retype;
2243 right= IC_RIGHT(ic);
2244 result = IC_RESULT(ic);
2246 letype = getSpec(operandType(left));
2247 retype =getSpec(operandType(right));
2248 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2249 /* assign the amsops */
2250 aopOp (left,ic,FALSE);
2251 aopOp (right,ic,FALSE);
2252 aopOp (result,ic,TRUE);
2254 genCmp(right, left, result, ifx, sign);
2256 freeAsmop(left,NULL,ic);
2257 freeAsmop(right,NULL,ic);
2258 freeAsmop(result,NULL,ic);
2261 /*-----------------------------------------------------------------*/
2262 /* genCmpLt - less than comparisons */
2263 /*-----------------------------------------------------------------*/
2264 static void genCmpLt (iCode *ic, iCode *ifx)
2266 operand *left, *right, *result;
2267 link *letype , *retype;
2271 right= IC_RIGHT(ic);
2272 result = IC_RESULT(ic);
2274 letype = getSpec(operandType(left));
2275 retype =getSpec(operandType(right));
2276 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2278 /* assign the amsops */
2279 aopOp (left,ic,FALSE);
2280 aopOp (right,ic,FALSE);
2281 aopOp (result,ic,TRUE);
2283 genCmp(left, right, result, ifx, sign);
2285 freeAsmop(left,NULL,ic);
2286 freeAsmop(right,NULL,ic);
2287 freeAsmop(result,NULL,ic);
2290 /*-----------------------------------------------------------------*/
2291 /* gencjneshort - compare and jump if not equal */
2292 /*-----------------------------------------------------------------*/
2293 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2295 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2297 unsigned long lit = 0L;
2299 /* Swap the left and right if it makes the computation easier */
2300 if (AOP_TYPE(left) == AOP_LIT) {
2306 if(AOP_TYPE(right) == AOP_LIT)
2307 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2309 /* if the right side is a literal then anything goes */
2310 if (AOP_TYPE(right) == AOP_LIT &&
2311 AOP_TYPE(left) != AOP_DIR ) {
2313 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2318 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2322 emitcode("or", "a,a");
2324 emitcode("jp", "nz," LABEL_STR, lbl->key+100);
2328 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2329 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2330 emitcode("or", "a,a");
2332 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2333 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2338 /* if the right side is in a register or in direct space or
2339 if the left is a pointer register & right is not */
2340 else if (AOP_TYPE(right) == AOP_REG ||
2341 AOP_TYPE(right) == AOP_DIR ||
2342 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2344 MOVA(aopGet(AOP(left),offset,FALSE));
2345 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2346 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2348 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2350 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2351 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2356 /* right is a pointer reg need both a & b */
2357 /* PENDING: is this required? */
2359 MOVA(aopGet(AOP(right),offset,FALSE));
2360 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2361 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2367 /*-----------------------------------------------------------------*/
2368 /* gencjne - compare and jump if not equal */
2369 /*-----------------------------------------------------------------*/
2370 static void gencjne(operand *left, operand *right, symbol *lbl)
2372 symbol *tlbl = newiTempLabel(NULL);
2374 gencjneshort(left, right, lbl);
2377 emitcode("ld","a,%s",one);
2378 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2379 emitLabel(lbl->key+100);
2380 emitcode("xor","a,a");
2381 emitLabel(tlbl->key+100);
2384 /*-----------------------------------------------------------------*/
2385 /* genCmpEq - generates code for equal to */
2386 /*-----------------------------------------------------------------*/
2387 static void genCmpEq (iCode *ic, iCode *ifx)
2389 operand *left, *right, *result;
2391 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2392 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2393 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2395 /* Swap operands if it makes the operation easier. ie if:
2396 1. Left is a literal.
2398 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2399 operand *t = IC_RIGHT(ic);
2400 IC_RIGHT(ic) = IC_LEFT(ic);
2404 if (ifx && !AOP_SIZE(result)){
2406 /* if they are both bit variables */
2407 if (AOP_TYPE(left) == AOP_CRY &&
2408 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2411 tlbl = newiTempLabel(NULL);
2412 gencjneshort(left, right, tlbl);
2413 if ( IC_TRUE(ifx) ) {
2414 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2415 emitLabel(tlbl->key+100);
2417 /* PENDING: do this better */
2418 symbol *lbl = newiTempLabel(NULL);
2419 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2420 emitLabel(tlbl->key+100);
2421 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2422 emitLabel(lbl->key+100);
2425 /* mark the icode as generated */
2430 /* if they are both bit variables */
2431 if (AOP_TYPE(left) == AOP_CRY &&
2432 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2435 gencjne(left,right,newiTempLabel(NULL));
2436 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2440 genIfxJump(ifx,"a");
2443 /* if the result is used in an arithmetic operation
2444 then put the result in place */
2445 if (AOP_TYPE(result) != AOP_CRY) {
2448 /* leave the result in acc */
2452 freeAsmop(left,NULL,ic);
2453 freeAsmop(right,NULL,ic);
2454 freeAsmop(result,NULL,ic);
2457 /*-----------------------------------------------------------------*/
2458 /* ifxForOp - returns the icode containing the ifx for operand */
2459 /*-----------------------------------------------------------------*/
2460 static iCode *ifxForOp ( operand *op, iCode *ic )
2462 /* if true symbol then needs to be assigned */
2463 if (IS_TRUE_SYMOP(op))
2466 /* if this has register type condition and
2467 the next instruction is ifx with the same operand
2468 and live to of the operand is upto the ifx only then */
2470 ic->next->op == IFX &&
2471 IC_COND(ic->next)->key == op->key &&
2472 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2478 /*-----------------------------------------------------------------*/
2479 /* genAndOp - for && operation */
2480 /*-----------------------------------------------------------------*/
2481 static void genAndOp (iCode *ic)
2483 operand *left,*right, *result;
2486 /* note here that && operations that are in an if statement are
2487 taken away by backPatchLabels only those used in arthmetic
2488 operations remain */
2489 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2490 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2491 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2493 /* if both are bit variables */
2494 if (AOP_TYPE(left) == AOP_CRY &&
2495 AOP_TYPE(right) == AOP_CRY ) {
2498 tlbl = newiTempLabel(NULL);
2500 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2502 emitLabel(tlbl->key+100);
2506 freeAsmop(left,NULL,ic);
2507 freeAsmop(right,NULL,ic);
2508 freeAsmop(result,NULL,ic);
2511 /*-----------------------------------------------------------------*/
2512 /* genOrOp - for || operation */
2513 /*-----------------------------------------------------------------*/
2514 static void genOrOp (iCode *ic)
2516 operand *left,*right, *result;
2519 /* note here that || operations that are in an
2520 if statement are taken away by backPatchLabels
2521 only those used in arthmetic operations remain */
2522 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2523 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2524 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2526 /* if both are bit variables */
2527 if (AOP_TYPE(left) == AOP_CRY &&
2528 AOP_TYPE(right) == AOP_CRY ) {
2531 tlbl = newiTempLabel(NULL);
2533 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2535 emitLabel(tlbl->key+100);
2539 freeAsmop(left,NULL,ic);
2540 freeAsmop(right,NULL,ic);
2541 freeAsmop(result,NULL,ic);
2544 /*-----------------------------------------------------------------*/
2545 /* isLiteralBit - test if lit == 2^n */
2546 /*-----------------------------------------------------------------*/
2547 int isLiteralBit(unsigned long lit)
2549 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2550 0x100L,0x200L,0x400L,0x800L,
2551 0x1000L,0x2000L,0x4000L,0x8000L,
2552 0x10000L,0x20000L,0x40000L,0x80000L,
2553 0x100000L,0x200000L,0x400000L,0x800000L,
2554 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2555 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2558 for(idx = 0; idx < 32; idx++)
2564 /*-----------------------------------------------------------------*/
2565 /* jmpTrueOrFalse - */
2566 /*-----------------------------------------------------------------*/
2567 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2569 // ugly but optimized by peephole
2571 symbol *nlbl = newiTempLabel(NULL);
2572 emitcode("jp", LABEL_STR, nlbl->key+100);
2573 emitLabel(tlbl->key+100);
2574 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2575 emitLabel(nlbl->key+100);
2578 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2579 emitLabel(tlbl->key+100);
2584 /*-----------------------------------------------------------------*/
2585 /* genAnd - code for and */
2586 /*-----------------------------------------------------------------*/
2587 static void genAnd (iCode *ic, iCode *ifx)
2589 operand *left, *right, *result;
2591 unsigned long lit = 0L;
2594 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2595 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2596 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2599 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2601 AOP_TYPE(left), AOP_TYPE(right));
2602 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2604 AOP_SIZE(left), AOP_SIZE(right));
2607 /* if left is a literal & right is not then exchange them */
2608 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2609 AOP_NEEDSACC(left)) {
2610 operand *tmp = right ;
2615 /* if result = right then exchange them */
2616 if(sameRegs(AOP(result),AOP(right))){
2617 operand *tmp = right ;
2622 /* if right is bit then exchange them */
2623 if (AOP_TYPE(right) == AOP_CRY &&
2624 AOP_TYPE(left) != AOP_CRY){
2625 operand *tmp = right ;
2629 if(AOP_TYPE(right) == AOP_LIT)
2630 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2632 size = AOP_SIZE(result);
2634 if (AOP_TYPE(left) == AOP_CRY){
2639 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2640 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2641 if((AOP_TYPE(right) == AOP_LIT) &&
2642 (AOP_TYPE(result) == AOP_CRY) &&
2643 (AOP_TYPE(left) != AOP_CRY)) {
2644 int posbit = isLiteralBit(lit);
2648 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2652 emitcode("mov","c,acc.%d",posbit&0x07);
2657 sprintf(buffer, "%d", posbit&0x07);
2658 genIfxJump(ifx, buffer);
2666 symbol *tlbl = newiTempLabel(NULL);
2667 int sizel = AOP_SIZE(left);
2670 emitcode("setb","c");
2673 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2674 MOVA( aopGet(AOP(left),offset,FALSE));
2676 if((posbit = isLiteralBit(bytelit)) != 0) {
2678 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2681 if(bytelit != 0x0FFL)
2682 emitcode("and","a,%s",
2683 aopGet(AOP(right),offset,FALSE));
2684 emitcode("jr","nz, %05d$",tlbl->key+100);
2689 // bit = left & literal
2691 emitcode("clr","c");
2692 emitcode("","%05d$:",tlbl->key+100);
2694 // if(left & literal)
2697 jmpTrueOrFalse(ifx, tlbl);
2705 /* if left is same as result */
2706 if(sameRegs(AOP(result),AOP(left))){
2707 for(;size--; offset++) {
2708 if(AOP_TYPE(right) == AOP_LIT){
2709 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2713 aopPut(AOP(result),zero,offset);
2715 MOVA(aopGet(AOP(left),offset,FALSE));
2716 emitcode("and","a,%s",
2717 aopGet(AOP(right),offset,FALSE));
2718 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2723 if (AOP_TYPE(left) == AOP_ACC) {
2727 MOVA(aopGet(AOP(right),offset,FALSE));
2728 emitcode("and","%s,a",
2729 aopGet(AOP(left),offset,FALSE));
2734 // left & result in different registers
2735 if(AOP_TYPE(result) == AOP_CRY){
2738 for(;(size--);offset++) {
2740 // result = left & right
2741 if(AOP_TYPE(right) == AOP_LIT){
2742 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2744 aopGet(AOP(left),offset,FALSE),
2747 } else if(bytelit == 0){
2748 aopPut(AOP(result),zero,offset);
2752 // faster than result <- left, anl result,right
2753 // and better if result is SFR
2754 if (AOP_TYPE(left) == AOP_ACC)
2755 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2757 MOVA(aopGet(AOP(right),offset,FALSE));
2758 emitcode("and","a,%s",
2759 aopGet(AOP(left),offset,FALSE));
2761 aopPut(AOP(result),"a",offset);
2768 freeAsmop(left,NULL,ic);
2769 freeAsmop(right,NULL,ic);
2770 freeAsmop(result,NULL,ic);
2773 /*-----------------------------------------------------------------*/
2774 /* genOr - code for or */
2775 /*-----------------------------------------------------------------*/
2776 static void genOr (iCode *ic, iCode *ifx)
2778 operand *left, *right, *result;
2780 unsigned long lit = 0L;
2782 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2783 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2784 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2787 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2789 AOP_TYPE(left), AOP_TYPE(right));
2790 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2792 AOP_SIZE(left), AOP_SIZE(right));
2795 /* if left is a literal & right is not then exchange them */
2796 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2797 AOP_NEEDSACC(left)) {
2798 operand *tmp = right ;
2803 /* if result = right then exchange them */
2804 if(sameRegs(AOP(result),AOP(right))){
2805 operand *tmp = right ;
2810 /* if right is bit then exchange them */
2811 if (AOP_TYPE(right) == AOP_CRY &&
2812 AOP_TYPE(left) != AOP_CRY){
2813 operand *tmp = right ;
2817 if(AOP_TYPE(right) == AOP_LIT)
2818 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2820 size = AOP_SIZE(result);
2822 if (AOP_TYPE(left) == AOP_CRY){
2827 if((AOP_TYPE(right) == AOP_LIT) &&
2828 (AOP_TYPE(result) == AOP_CRY) &&
2829 (AOP_TYPE(left) != AOP_CRY)){
2834 /* if left is same as result */
2835 if(sameRegs(AOP(result),AOP(left))){
2836 for(;size--; offset++) {
2837 if(AOP_TYPE(right) == AOP_LIT){
2838 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2841 MOVA(aopGet(AOP(right),offset,FALSE));
2842 emitcode("or","a,%s; 5",
2843 aopGet(AOP(left),offset,FALSE));
2844 aopPut(AOP(result),"a ; 8", offset);
2847 if (AOP_TYPE(left) == AOP_ACC)
2848 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2850 MOVA(aopGet(AOP(right),offset,FALSE));
2851 emitcode("or","a,%s ; 7",
2852 aopGet(AOP(left),offset,FALSE));
2853 aopPut(AOP(result),"a ; 8", offset);
2858 // left & result in different registers
2859 if(AOP_TYPE(result) == AOP_CRY){
2861 } else for(;(size--);offset++){
2863 // result = left & right
2864 if(AOP_TYPE(right) == AOP_LIT){
2865 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2867 aopGet(AOP(left),offset,FALSE),
2872 // faster than result <- left, anl result,right
2873 // and better if result is SFR
2874 if (AOP_TYPE(left) == AOP_ACC)
2875 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2877 MOVA(aopGet(AOP(right),offset,FALSE));
2878 emitcode("or","a,%s",
2879 aopGet(AOP(left),offset,FALSE));
2881 aopPut(AOP(result),"a",offset);
2882 /* PENDING: something weird is going on here. Add exception. */
2883 if (AOP_TYPE(result) == AOP_ACC)
2889 freeAsmop(left,NULL,ic);
2890 freeAsmop(right,NULL,ic);
2891 freeAsmop(result,NULL,ic);
2894 /*-----------------------------------------------------------------*/
2895 /* genXor - code for xclusive or */
2896 /*-----------------------------------------------------------------*/
2897 static void genXor (iCode *ic, iCode *ifx)
2899 operand *left, *right, *result;
2901 unsigned long lit = 0L;
2903 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2904 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2905 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2907 /* if left is a literal & right is not then exchange them */
2908 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2909 AOP_NEEDSACC(left)) {
2910 operand *tmp = right ;
2915 /* if result = right then exchange them */
2916 if(sameRegs(AOP(result),AOP(right))){
2917 operand *tmp = right ;
2922 /* if right is bit then exchange them */
2923 if (AOP_TYPE(right) == AOP_CRY &&
2924 AOP_TYPE(left) != AOP_CRY){
2925 operand *tmp = right ;
2929 if(AOP_TYPE(right) == AOP_LIT)
2930 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2932 size = AOP_SIZE(result);
2934 if (AOP_TYPE(left) == AOP_CRY){
2939 if((AOP_TYPE(right) == AOP_LIT) &&
2940 (AOP_TYPE(result) == AOP_CRY) &&
2941 (AOP_TYPE(left) != AOP_CRY)){
2946 /* if left is same as result */
2947 if(sameRegs(AOP(result),AOP(left))){
2948 for(;size--; offset++) {
2949 if(AOP_TYPE(right) == AOP_LIT){
2950 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2953 MOVA(aopGet(AOP(right),offset,FALSE));
2954 emitcode("xor","a,%s",
2955 aopGet(AOP(left),offset,FALSE));
2956 aopPut(AOP(result),"a",0);
2959 if (AOP_TYPE(left) == AOP_ACC)
2960 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2962 MOVA(aopGet(AOP(right),offset,FALSE));
2963 emitcode("xor","a,%s",
2964 aopGet(AOP(left),offset,FALSE));
2965 aopPut(AOP(result),"a",0);
2970 // left & result in different registers
2971 if(AOP_TYPE(result) == AOP_CRY){
2973 } else for(;(size--);offset++){
2975 // result = left & right
2976 if(AOP_TYPE(right) == AOP_LIT){
2977 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2979 aopGet(AOP(left),offset,FALSE),
2984 // faster than result <- left, anl result,right
2985 // and better if result is SFR
2986 if (AOP_TYPE(left) == AOP_ACC)
2987 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2989 MOVA(aopGet(AOP(right),offset,FALSE));
2990 emitcode("xor","a,%s",
2991 aopGet(AOP(left),offset,FALSE));
2992 aopPut(AOP(result),"a",0);
2994 aopPut(AOP(result),"a",offset);
2999 freeAsmop(left,NULL,ic);
3000 freeAsmop(right,NULL,ic);
3001 freeAsmop(result,NULL,ic);
3004 /*-----------------------------------------------------------------*/
3005 /* genInline - write the inline code out */
3006 /*-----------------------------------------------------------------*/
3007 static void genInline (iCode *ic)
3009 char buffer[MAX_INLINEASM];
3013 inLine += (!options.asmpeep);
3014 strcpy(buffer,IC_INLINE(ic));
3016 /* emit each line as a code */
3035 /* emitcode("",buffer); */
3036 inLine -= (!options.asmpeep);
3039 /*-----------------------------------------------------------------*/
3040 /* genRRC - rotate right with carry */
3041 /*-----------------------------------------------------------------*/
3042 static void genRRC (iCode *ic)
3047 /*-----------------------------------------------------------------*/
3048 /* genRLC - generate code for rotate left with carry */
3049 /*-----------------------------------------------------------------*/
3050 static void genRLC (iCode *ic)
3055 /*-----------------------------------------------------------------*/
3056 /* shiftR2Left2Result - shift right two bytes from left to result */
3057 /*-----------------------------------------------------------------*/
3058 static void shiftR2Left2Result (operand *left, int offl,
3059 operand *result, int offr,
3060 int shCount, int sign)
3062 if(sameRegs(AOP(result), AOP(left)) &&
3063 ((offl + MSB16) == offr)){
3066 movLeft2Result(left, offl, result, offr, 0);
3067 movLeft2Result(left, offl+1, result, offr+1, 0);
3074 /* if (AOP(result)->type == AOP_REG) {*/
3077 symbol *tlbl , *tlbl1;
3080 /* Left is already in result - so now do the shift */
3082 emitcode("ld","a,#%u+1", shCount);
3083 tlbl = newiTempLabel(NULL);
3084 tlbl1 = newiTempLabel(NULL);
3085 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3086 emitLabel(tlbl->key+100);
3089 emitcode("or", "a,a");
3092 l = aopGet(AOP(result), --offset, FALSE);
3093 emitcode("rr","%s", l);
3096 emitLabel(tlbl1->key+100);
3097 emitcode("dec", "a");
3098 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3103 /*-----------------------------------------------------------------*/
3104 /* shiftL2Left2Result - shift left two bytes from left to result */
3105 /*-----------------------------------------------------------------*/
3106 static void shiftL2Left2Result (operand *left, int offl,
3107 operand *result, int offr, int shCount)
3109 if(sameRegs(AOP(result), AOP(left)) &&
3110 ((offl + MSB16) == offr)){
3113 /* Copy left into result */
3114 movLeft2Result(left, offl, result, offr, 0);
3115 movLeft2Result(left, offl+1, result, offr+1, 0);
3117 /* PENDING: for now just see if it'll work. */
3118 /*if (AOP(result)->type == AOP_REG) { */
3122 symbol *tlbl , *tlbl1;
3125 /* Left is already in result - so now do the shift */
3127 emitcode("ld","a,#%u+1", shCount);
3128 tlbl = newiTempLabel(NULL);
3129 tlbl1 = newiTempLabel(NULL);
3130 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3131 emitLabel(tlbl->key+100);
3134 emitcode("or", "a,a");
3136 l = aopGet(AOP(result),offset++,FALSE);
3137 emitcode("rl","%s", l);
3140 emitLabel(tlbl1->key+100);
3141 emitcode("dec", "a");
3142 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3147 /*-----------------------------------------------------------------*/
3148 /* AccRol - rotate left accumulator by known count */
3149 /*-----------------------------------------------------------------*/
3150 static void AccRol (int shCount)
3152 shCount &= 0x0007; // shCount : 0..7
3189 /*-----------------------------------------------------------------*/
3190 /* AccLsh - left shift accumulator by known count */
3191 /*-----------------------------------------------------------------*/
3192 static void AccLsh (int shCount)
3196 emitcode("add","a,a");
3199 emitcode("add","a,a");
3200 emitcode("add","a,a");
3202 /* rotate left accumulator */
3204 /* and kill the lower order bits */
3205 emitcode("and","a,#0x%02x", SLMask[shCount]);
3210 /*-----------------------------------------------------------------*/
3211 /* shiftL1Left2Result - shift left one byte from left to result */
3212 /*-----------------------------------------------------------------*/
3213 static void shiftL1Left2Result (operand *left, int offl,
3214 operand *result, int offr, int shCount)
3217 l = aopGet(AOP(left),offl,FALSE);
3219 /* shift left accumulator */
3221 aopPut(AOP(result),"a",offr);
3225 /*-----------------------------------------------------------------*/
3226 /* genlshTwo - left shift two bytes by known amount != 0 */
3227 /*-----------------------------------------------------------------*/
3228 static void genlshTwo (operand *result,operand *left, int shCount)
3230 int size = AOP_SIZE(result);
3234 /* if shCount >= 8 */
3240 movLeft2Result(left, LSB, result, MSB16, 0);
3241 aopPut(AOP(result),zero, 0);
3242 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3245 movLeft2Result(left, LSB, result, MSB16, 0);
3246 aopPut(AOP(result),zero, 0);
3249 aopPut(AOP(result),zero,LSB);
3251 /* 1 <= shCount <= 7 */
3257 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3262 /*-----------------------------------------------------------------*/
3263 /* genlshOne - left shift a one byte quantity by known count */
3264 /*-----------------------------------------------------------------*/
3265 static void genlshOne (operand *result, operand *left, int shCount)
3267 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3270 /*-----------------------------------------------------------------*/
3271 /* genLeftShiftLiteral - left shifting by known count */
3272 /*-----------------------------------------------------------------*/
3273 static void genLeftShiftLiteral (operand *left,
3278 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3281 freeAsmop(right,NULL,ic);
3283 aopOp(left,ic,FALSE);
3284 aopOp(result,ic,FALSE);
3286 size = getSize(operandType(result));
3289 emitcode("; shift left ","result %d, left %d",size,
3293 /* I suppose that the left size >= result size */
3298 else if(shCount >= (size * 8))
3300 aopPut(AOP(result),zero,size);
3304 genlshOne (result,left,shCount);
3307 genlshTwo (result,left,shCount);
3316 freeAsmop(left,NULL,ic);
3317 freeAsmop(result,NULL,ic);
3320 /*-----------------------------------------------------------------*/
3321 /* genLeftShift - generates code for left shifting */
3322 /*-----------------------------------------------------------------*/
3323 static void genLeftShift (iCode *ic)
3327 symbol *tlbl , *tlbl1;
3328 operand *left,*right, *result;
3330 right = IC_RIGHT(ic);
3332 result = IC_RESULT(ic);
3334 aopOp(right,ic,FALSE);
3336 /* if the shift count is known then do it
3337 as efficiently as possible */
3338 if (AOP_TYPE(right) == AOP_LIT) {
3339 genLeftShiftLiteral (left,right,result,ic);
3343 /* shift count is unknown then we have to form a loop get the loop
3344 count in B : Note: we take only the lower order byte since
3345 shifting more that 32 bits make no sense anyway, ( the largest
3346 size of an object can be only 32 bits ) */
3347 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3348 emitcode("inc","a");
3349 freeAsmop (right,NULL,ic);
3350 aopOp(left,ic,FALSE);
3351 aopOp(result,ic,FALSE);
3353 /* now move the left to the result if they are not the
3356 if (!sameRegs(AOP(left),AOP(result))) {
3358 size = AOP_SIZE(result);
3361 l = aopGet(AOP(left),offset,FALSE);
3362 aopPut(AOP(result),l,offset);
3367 size = AOP_SIZE(result);
3370 l = aopGet(AOP(left),offset,FALSE);
3371 aopPut(AOP(result),l,offset);
3377 tlbl = newiTempLabel(NULL);
3378 size = AOP_SIZE(result);
3380 tlbl1 = newiTempLabel(NULL);
3382 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3383 emitLabel(tlbl->key+100);
3384 l = aopGet(AOP(result),offset,FALSE);
3385 emitcode("or", "a,a");
3387 l = aopGet(AOP(result),offset++,FALSE);
3388 emitcode("rl","%s", l);
3390 emitLabel(tlbl1->key+100);
3391 emitcode("dec", "a");
3392 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3394 freeAsmop(left,NULL,ic);
3395 freeAsmop(result,NULL,ic);
3398 /* genlshTwo - left shift two bytes by known amount != 0 */
3399 /*-----------------------------------------------------------------*/
3400 static void genrshOne (operand *result,operand *left, int shCount)
3403 int size = AOP_SIZE(result);
3409 l = aopGet(AOP(left),0,FALSE);
3410 if (AOP(result)->type == AOP_REG) {
3411 aopPut(AOP(result), l, 0);
3412 l = aopGet(AOP(result), 0, FALSE);
3414 emitcode("srl", "%s", l);
3419 emitcode("srl", "a");
3421 aopPut(AOP(result),"a",0);
3425 /*-----------------------------------------------------------------*/
3426 /* AccRsh - right shift accumulator by known count */
3427 /*-----------------------------------------------------------------*/
3428 static void AccRsh (int shCount)
3435 /* rotate right accumulator */
3436 AccRol(8 - shCount);
3437 /* and kill the higher order bits */
3438 emitcode("and","a,#0x%02x", SRMask[shCount]);
3443 /*-----------------------------------------------------------------*/
3444 /* shiftR1Left2Result - shift right one byte from left to result */
3445 /*-----------------------------------------------------------------*/
3446 static void shiftR1Left2Result (operand *left, int offl,
3447 operand *result, int offr,
3448 int shCount, int sign)
3450 MOVA(aopGet(AOP(left),offl,FALSE));
3457 aopPut(AOP(result),"a",offr);
3460 /*-----------------------------------------------------------------*/
3461 /* genrshTwo - right shift two bytes by known amount != 0 */
3462 /*-----------------------------------------------------------------*/
3463 static void genrshTwo (operand *result,operand *left,
3464 int shCount, int sign)
3466 /* if shCount >= 8 */
3471 shiftR1Left2Result(left, MSB16, result, LSB,
3475 movLeft2Result(left, MSB16, result, LSB, sign);
3476 aopPut(AOP(result),zero,1);
3479 /* 1 <= shCount <= 7 */
3481 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3485 /*-----------------------------------------------------------------*/
3486 /* genRightShiftLiteral - left shifting by known count */
3487 /*-----------------------------------------------------------------*/
3488 static void genRightShiftLiteral (operand *left,
3493 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3496 freeAsmop(right,NULL,ic);
3498 aopOp(left,ic,FALSE);
3499 aopOp(result,ic,FALSE);
3501 size = getSize(operandType(result));
3503 emitcode("; shift right ","result %d, left %d",size,
3506 /* I suppose that the left size >= result size */
3511 else if(shCount >= (size * 8))
3513 aopPut(AOP(result),zero,size);
3517 genrshOne(result, left, shCount);
3520 /* PENDING: sign support */
3521 genrshTwo(result, left, shCount, FALSE);
3530 freeAsmop(left,NULL,ic);
3531 freeAsmop(result,NULL,ic);
3534 /*-----------------------------------------------------------------*/
3535 /* genRightShift - generate code for right shifting */
3536 /*-----------------------------------------------------------------*/
3537 static void genRightShift (iCode *ic)
3539 operand *left,*right, *result;
3541 right = IC_RIGHT(ic);
3543 result = IC_RESULT(ic);
3545 aopOp(right,ic,FALSE);
3547 /* if the shift count is known then do it
3548 as efficiently as possible */
3549 if (AOP_TYPE(right) == AOP_LIT) {
3550 genRightShiftLiteral (left,right,result,ic);
3558 /*-----------------------------------------------------------------*/
3559 /* genGenPointerGet - gget value from generic pointer space */
3560 /*-----------------------------------------------------------------*/
3561 static void genGenPointerGet (operand *left,
3562 operand *result, iCode *ic)
3565 link *retype = getSpec(operandType(result));
3571 aopOp(left,ic,FALSE);
3572 aopOp(result,ic,FALSE);
3574 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3576 if (isPtrPair(AOP(left)))
3578 sprintf(buffer, "(%s)", getPairName(AOP(left)));
3579 aopPut(AOP(result), buffer, 0);
3582 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3583 aopPut(AOP(result),"a", 0);
3585 freeAsmop(left,NULL,ic);
3589 /* For now we always load into IY */
3590 /* if this is remateriazable */
3591 fetchPair(pair, AOP(left));
3593 /* so iy now contains the address */
3594 freeAsmop(left,NULL,ic);
3596 /* if bit then unpack */
3597 if (IS_BITVAR(retype)) {
3601 size = AOP_SIZE(result);
3605 /* PENDING: make this better */
3606 if (!IS_GB && AOP(result)->type == AOP_REG) {
3607 aopPut(AOP(result),"(hl)",offset++);
3610 emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
3611 aopPut(AOP(result),"a",offset++);
3614 emitcode("inc", "%s", _pairs[pair].name);
3620 freeAsmop(result,NULL,ic);
3623 /*-----------------------------------------------------------------*/
3624 /* genPointerGet - generate code for pointer get */
3625 /*-----------------------------------------------------------------*/
3626 static void genPointerGet (iCode *ic)
3628 operand *left, *result ;
3632 result = IC_RESULT(ic) ;
3634 /* depending on the type of pointer we need to
3635 move it to the correct pointer register */
3636 type = operandType(left);
3637 etype = getSpec(type);
3639 genGenPointerGet (left,result,ic);
3642 bool isRegOrLit(asmop *aop)
3644 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3649 /*-----------------------------------------------------------------*/
3650 /* genGenPointerSet - stores the value into a pointer location */
3651 /*-----------------------------------------------------------------*/
3652 static void genGenPointerSet (operand *right,
3653 operand *result, iCode *ic)
3656 link *retype = getSpec(operandType(right));
3657 PAIR_ID pairId = PAIR_HL;
3659 aopOp(result,ic,FALSE);
3660 aopOp(right,ic,FALSE);
3665 /* Handle the exceptions first */
3666 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3668 char *l = aopGet(AOP(right), 0, FALSE);
3669 const char *pair = getPairName(AOP(result));
3670 if (canAssignToPtr(l) && isPtr(pair)) {
3671 emitcode("ld", "(%s),%s", pair, l);
3675 emitcode("ld", "(%s),a ; 1", pair);
3680 /* if the operand is already in dptr
3681 then we do nothing else we move the value to dptr */
3682 if (AOP_TYPE(result) != AOP_STR) {
3683 fetchPair(pairId, AOP(result));
3685 /* so hl know contains the address */
3686 freeAsmop(result,NULL,ic);
3688 /* if bit then unpack */
3689 if (IS_BITVAR(retype)) {
3693 size = AOP_SIZE(right);
3697 char *l = aopGet(AOP(right),offset,FALSE);
3698 if (isRegOrLit(AOP(right)) && !IS_GB) {
3699 emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
3703 emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
3706 emitcode("inc", _pairs[pairId].name);
3712 freeAsmop(right,NULL,ic);
3715 /*-----------------------------------------------------------------*/
3716 /* genPointerSet - stores the value into a pointer location */
3717 /*-----------------------------------------------------------------*/
3718 static void genPointerSet (iCode *ic)
3720 operand *right, *result ;
3723 right = IC_RIGHT(ic);
3724 result = IC_RESULT(ic) ;
3726 /* depending on the type of pointer we need to
3727 move it to the correct pointer register */
3728 type = operandType(result);
3729 etype = getSpec(type);
3731 genGenPointerSet (right,result,ic);
3734 /*-----------------------------------------------------------------*/
3735 /* genIfx - generate code for Ifx statement */
3736 /*-----------------------------------------------------------------*/
3737 static void genIfx (iCode *ic, iCode *popIc)
3739 operand *cond = IC_COND(ic);
3742 aopOp(cond,ic,FALSE);
3744 /* get the value into acc */
3745 if (AOP_TYPE(cond) != AOP_CRY)
3749 /* the result is now in the accumulator */
3750 freeAsmop(cond,NULL,ic);
3752 /* if there was something to be popped then do it */
3756 /* if the condition is a bit variable */
3757 if (isbit && IS_ITEMP(cond) &&
3759 genIfxJump(ic,SPIL_LOC(cond)->rname);
3761 if (isbit && !IS_ITEMP(cond))
3762 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3769 /*-----------------------------------------------------------------*/
3770 /* genAddrOf - generates code for address of */
3771 /*-----------------------------------------------------------------*/
3772 static void genAddrOf (iCode *ic)
3774 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3776 aopOp(IC_RESULT(ic),ic,FALSE);
3778 /* if the operand is on the stack then we
3779 need to get the stack offset of this
3784 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _G.stack.pushed, _G.stack.offset);
3785 emitcode("ld", "d,h");
3786 emitcode("ld", "e,l");
3789 emitcode("ld", "de,#%s", sym->rname);
3791 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3792 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3797 /* if it has an offset then we need to compute it */
3798 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3799 emitcode("add", "hl,sp");
3802 emitcode("ld", "hl,#%s", sym->rname);
3804 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3805 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3807 freeAsmop(IC_RESULT(ic),NULL,ic);
3810 /*-----------------------------------------------------------------*/
3811 /* genAssign - generate code for assignment */
3812 /*-----------------------------------------------------------------*/
3813 static void genAssign (iCode *ic)
3815 operand *result, *right;
3817 unsigned long lit = 0L;
3819 result = IC_RESULT(ic);
3820 right = IC_RIGHT(ic) ;
3823 /* Dont bother assigning if they are the same */
3824 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3825 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3830 aopOp(right,ic,FALSE);
3831 aopOp(result,ic,TRUE);
3833 /* if they are the same registers */
3834 if (sameRegs(AOP(right),AOP(result))) {
3835 emitcode("", "; (registers are the same)");
3839 /* if the result is a bit */
3840 if (AOP_TYPE(result) == AOP_CRY) {
3845 size = AOP_SIZE(result);
3848 if(AOP_TYPE(right) == AOP_LIT)
3849 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3850 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3851 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3853 else if((size > 1) &&
3854 (AOP_TYPE(result) != AOP_REG) &&
3855 (AOP_TYPE(right) == AOP_LIT) &&
3856 !IS_FLOAT(operandType(right)) &&
3858 bool fXored = FALSE;
3860 /* Work from the top down.
3861 Done this way so that we can use the cached copy of 0
3862 in A for a fast clear */
3864 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3865 if (!fXored && size>1) {
3866 emitcode("xor", "a,a");
3870 aopPut(AOP(result),"a",offset);
3873 aopPut(AOP(result), "#0", offset);
3878 aopGet(AOP(right),offset,FALSE),
3883 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3884 /* Special case. Load into a and d, then load out. */
3885 MOVA(aopGet(AOP(right), 0, FALSE));
3886 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3887 aopPut(AOP(result), "a", 0);
3888 aopPut(AOP(result), "e", 1);
3892 aopGet(AOP(right),offset,FALSE),
3899 freeAsmop(right,NULL,ic);
3900 freeAsmop(result,NULL,ic);
3903 /*-----------------------------------------------------------------*/
3904 /* genJumpTab - genrates code for jump table */
3905 /*-----------------------------------------------------------------*/
3906 static void genJumpTab (iCode *ic)
3911 aopOp(IC_JTCOND(ic),ic,FALSE);
3912 /* get the condition into accumulator */
3913 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3916 emitcode("push", "de");
3917 emitcode("ld", "e,%s", l);
3918 emitcode("ld", "d,#0");
3919 jtab = newiTempLabel(NULL);
3921 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3922 emitcode("add", "hl,de");
3923 emitcode("add", "hl,de");
3924 emitcode("add", "hl,de");
3925 freeAsmop(IC_JTCOND(ic),NULL,ic);
3927 emitcode("pop", "de");
3928 emitcode("jp", "(hl)");
3929 emitLabel(jtab->key+100);
3930 /* now generate the jump labels */
3931 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3932 jtab = setNextItem(IC_JTLABELS(ic)))
3933 emitcode("jp", LABEL_STR, jtab->key+100);
3936 /*-----------------------------------------------------------------*/
3937 /* genCast - gen code for casting */
3938 /*-----------------------------------------------------------------*/
3939 static void genCast (iCode *ic)
3941 operand *result = IC_RESULT(ic);
3942 link *ctype = operandType(IC_LEFT(ic));
3943 operand *right = IC_RIGHT(ic);
3946 /* if they are equivalent then do nothing */
3947 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3950 aopOp(right,ic,FALSE) ;
3951 aopOp(result,ic,FALSE);
3953 /* if the result is a bit */
3954 if (AOP_TYPE(result) == AOP_CRY) {
3958 /* if they are the same size : or less */
3959 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3961 /* if they are in the same place */
3962 if (sameRegs(AOP(right),AOP(result)))
3965 /* if they in different places then copy */
3966 size = AOP_SIZE(result);
3970 aopGet(AOP(right),offset,FALSE),
3977 /* PENDING: should be OK. */
3979 /* if the result is of type pointer */
3980 if (IS_PTR(ctype)) {
3985 /* so we now know that the size of destination is greater
3986 than the size of the source */
3987 /* we move to result for the size of source */
3988 size = AOP_SIZE(right);
3992 aopGet(AOP(right),offset,FALSE),
3997 /* now depending on the sign of the destination */
3998 size = AOP_SIZE(result) - AOP_SIZE(right);
3999 /* Unsigned or not an integral type - right fill with zeros */
4000 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4002 aopPut(AOP(result),zero,offset++);
4004 /* we need to extend the sign :{ */
4005 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4008 emitcode("", "; genCast: sign extend untested.");
4009 emitcode("rla", "");
4010 emitcode("sbc", "a,a");
4012 aopPut(AOP(result),"a",offset++);
4016 freeAsmop(right, NULL, ic);
4017 freeAsmop(result, NULL, ic);
4020 /*-----------------------------------------------------------------*/
4021 /* genReceive - generate code for a receive iCode */
4022 /*-----------------------------------------------------------------*/
4023 static void genReceive (iCode *ic)
4025 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4026 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4027 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4031 aopOp(IC_RESULT(ic),ic,FALSE);
4033 assignResultValue(IC_RESULT(ic));
4036 freeAsmop(IC_RESULT(ic),NULL,ic);
4039 /*-----------------------------------------------------------------*/
4040 /* genZ80Code - generate code for Z80 based controllers */
4041 /*-----------------------------------------------------------------*/
4042 void genZ80Code (iCode *lic)
4049 _fReturn = _gbz80_return;
4050 _fTmp = _gbz80_return;
4054 _fReturn = _z80_return;
4055 _fTmp = _z80_return;
4059 lineHead = lineCurr = NULL;
4061 /* if debug information required */
4062 if (options.debug && currFunc) {
4063 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4065 if (IS_STATIC(currFunc->etype))
4066 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4068 emitcode("","G$%s$0$0 ==.",currFunc->name);
4071 /* stack pointer name */
4075 for (ic = lic ; ic ; ic = ic->next ) {
4077 if ( cln != ic->lineno ) {
4078 if ( options.debug ) {
4080 emitcode("","C$%s$%d$%d$%d ==.",
4081 ic->filename,ic->lineno,
4082 ic->level,ic->block);
4085 emitcode(";","%s %d",ic->filename,ic->lineno);
4088 /* if the result is marked as
4089 spilt and rematerializable or code for
4090 this has already been generated then
4092 if (resultRemat(ic) || ic->generated )
4095 /* depending on the operation */
4098 emitcode("", "; genNot");
4103 emitcode("", "; genCpl");
4108 emitcode("", "; genUminus");
4113 emitcode("", "; genIpush");
4118 /* IPOP happens only when trying to restore a
4119 spilt live range, if there is an ifx statement
4120 following this pop then the if statement might
4121 be using some of the registers being popped which
4122 would destory the contents of the register so
4123 we need to check for this condition and handle it */
4125 ic->next->op == IFX &&
4126 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4127 emitcode("", "; genIfx");
4128 genIfx (ic->next,ic);
4131 emitcode("", "; genIpop");
4137 emitcode("", "; genCall");
4142 emitcode("", "; genPcall");
4147 emitcode("", "; genFunction");
4152 emitcode("", "; genEndFunction");
4153 genEndFunction (ic);
4157 emitcode("", "; genRet");
4162 emitcode("", "; genLabel");
4167 emitcode("", "; genGoto");
4172 emitcode("", "; genPlus");
4177 emitcode("", "; genMinus");
4182 emitcode("", "; genMult");
4187 emitcode("", "; genDiv");
4192 emitcode("", "; genMod");
4197 emitcode("", "; genCmpGt");
4198 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4202 emitcode("", "; genCmpLt");
4203 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4210 /* note these two are xlated by algebraic equivalence
4211 during parsing SDCC.y */
4212 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4213 "got '>=' or '<=' shouldn't have come here");
4217 emitcode("", "; genCmpEq");
4218 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4222 emitcode("", "; genAndOp");
4227 emitcode("", "; genOrOp");
4232 emitcode("", "; genXor");
4233 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4237 emitcode("", "; genOr");
4238 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4242 emitcode("", "; genAnd");
4243 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4247 emitcode("", "; genInline");
4252 emitcode("", "; genRRC");
4257 emitcode("", "; genRLC");
4262 emitcode("", "; genHBIT");
4266 emitcode("", "; genLeftShift");
4271 emitcode("", "; genRightShift");
4275 case GET_VALUE_AT_ADDRESS:
4276 emitcode("", "; genPointerGet");
4282 if (POINTER_SET(ic)) {
4283 emitcode("", "; genAssign (pointer)");
4287 emitcode("", "; genAssign");
4293 emitcode("", "; genIfx");
4298 emitcode("", "; genAddrOf");
4303 emitcode("", "; genJumpTab");
4308 emitcode("", "; genCast");
4313 emitcode("", "; genReceive");
4318 emitcode("", "; addSet");
4319 addSet(&sendSet,ic);
4324 /* piCode(ic,stdout); */
4330 /* now we are ready to call the
4331 peep hole optimizer */
4332 if (!options.nopeep)
4333 peepHole (&lineHead);
4335 /* now do the actual printing */
4336 printLine (lineHead,codeOutFile);