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
21 Michael Hope <michaelh@earthling.net> 2000
22 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
23 and - Jean-Louis VERN.jlvern@writeme.com (1999)
25 This program is free software; you can redistribute it and/or modify it
26 under the terms of the GNU General Public License as published by the
27 Free Software Foundation; either version 2, or (at your option) any
30 This program is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
35 You should have received a copy of the GNU General Public License
36 along with this program; if not, write to the Free Software
37 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 In other words, you are welcome to use, share and improve this program.
40 You are forbidden to forbid anyone else to use, share and improve
41 what you give them. Help stamp out software-hoarding!
43 -------------------------------------------------------------------------*/
50 #ifdef HAVE_SYS_ISA_DEFS_H
51 #include <sys/isa_defs.h>
55 #include "SDCCpeeph.h"
59 /* this is the down and dirty file with all kinds of kludgy & hacky
60 stuff. This is what it is all about CODE GENERATION for a specific MCU.
61 Some of the routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
67 static char *_z80_return[] = {"l", "h", "e", "d" };
68 static char *_gbz80_return[] = { "e", "d", "l", "h" };
69 static char **_fReturn;
72 static char *accUse[] = {"a" };
78 extern int ptrRegReq ;
80 extern FILE *codeOutFile;
82 const char *_shortJP = "jp";
98 } _pairs[NUM_PAIRS] = {
103 { "iy", "iy.l?", "iy.h?" },
104 { "ix", "ix.l?", "ix.h?" }
107 #define RESULTONSTACK(x) \
108 (IC_RESULT(x) && IC_RESULT(x)->aop && \
109 IC_RESULT(x)->aop->type == AOP_STK )
111 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
112 #define CLRC emitcode("xor","a,a");
114 #define LABEL_STR "%05d$"
116 lineNode *lineHead = NULL;
117 lineNode *lineCurr = NULL;
119 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
120 0xE0, 0xC0, 0x80, 0x00};
121 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
122 0x07, 0x03, 0x01, 0x00};
150 static char *aopGet(asmop *aop, int offset, bool bit16);
152 /*-----------------------------------------------------------------*/
153 /* emitcode - writes the code into a file : for now it is simple */
154 /*-----------------------------------------------------------------*/
155 void emitcode (const char *inst, const char *fmt, ...)
158 char lb[MAX_INLINEASM];
164 sprintf(lb,"%s\t",inst);
165 vsprintf(lb+(strlen(lb)),fmt,ap);
169 while (isspace(*lbp)) lbp++;
172 lineCurr = (lineCurr ?
173 connectLine(lineCurr,newLineNode(lb)) :
174 (lineHead = newLineNode(lb)));
175 lineCurr->isInline = inLine;
176 lineCurr->isDebug = debugLine;
180 const char *getPairName(asmop *aop)
182 if (aop->type == AOP_REG) {
183 switch (aop->aopu.aop_reg[0]->rIdx) {
195 else if (aop->type == AOP_STR) {
196 switch (*aop->aopu.aop_str[0]) {
212 static PAIR_ID getPairId(asmop *aop)
214 if (aop->size == 2) {
215 if (aop->type == AOP_REG) {
216 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
219 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
222 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
226 if (aop->type == AOP_STR) {
227 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
230 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
233 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
241 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
242 bool isPair(asmop *aop)
244 return (getPairId(aop) != PAIR_INVALID);
247 bool isPtrPair(asmop *aop)
249 PAIR_ID pairId = getPairId(aop);
259 /** Push a register pair onto the stack */
260 void genPairPush(asmop *aop)
262 emitcode("push", "%s", getPairName(aop));
265 static char *_strdup(const char *s)
268 ALLOC_ATOMIC(ret, strlen(s)+1);
274 /*-----------------------------------------------------------------*/
275 /* newAsmop - creates a new asmOp */
276 /*-----------------------------------------------------------------*/
277 static asmop *newAsmop (short type)
281 ALLOC(aop,sizeof(asmop));
286 /*-----------------------------------------------------------------*/
287 /* aopForSym - for a true symbol */
288 /*-----------------------------------------------------------------*/
289 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
292 memmap *space= SPEC_OCLS(sym->etype);
294 /* if already has one */
298 /* Assign depending on the storage class */
299 if (sym->onStack || sym->iaccess) {
300 sym->aop = aop = newAsmop(AOP_STK);
301 aop->size = getSize(sym->type);
302 aop->aopu.aop_stk = sym->stack;
306 /* special case for a function */
307 if (IS_FUNC(sym->type)) {
308 sym->aop = aop = newAsmop(AOP_IMMD);
309 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
310 strcpy(aop->aopu.aop_immd,sym->rname);
317 /* if it is in direct space */
318 if (IN_DIRSPACE(space)) {
319 sym->aop = aop = newAsmop (AOP_DIR);
320 aop->aopu.aop_dir = sym->rname ;
321 aop->size = getSize(sym->type);
322 emitcode("", "; AOP_DIR for %s", sym->rname);
328 /* only remaining is far space */
329 /* in which case DPTR gets the address */
331 sym->aop = aop = newAsmop(AOP_HL);
334 sym->aop = aop = newAsmop(AOP_IY);
336 aop->size = getSize(sym->type);
337 aop->aopu.aop_dir = sym->rname;
339 /* if it is in code space */
340 if (IN_CODESPACE(space))
346 /*-----------------------------------------------------------------*/
347 /* aopForRemat - rematerialzes an object */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForRemat (symbol *sym)
352 iCode *ic = sym->rematiCode;
353 asmop *aop = newAsmop(AOP_IMMD);
356 /* if plus or minus print the right hand side */
357 if (ic->op == '+' || ic->op == '-') {
358 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
361 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
364 /* we reached the end */
365 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
369 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
370 strcpy(aop->aopu.aop_immd,buffer);
374 /*-----------------------------------------------------------------*/
375 /* regsInCommon - two operands have some registers in common */
376 /*-----------------------------------------------------------------*/
377 bool regsInCommon (operand *op1, operand *op2)
382 /* if they have registers in common */
383 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
386 sym1 = OP_SYMBOL(op1);
387 sym2 = OP_SYMBOL(op2);
389 if (sym1->nRegs == 0 || sym2->nRegs == 0)
392 for (i = 0 ; i < sym1->nRegs ; i++) {
397 for (j = 0 ; j < sym2->nRegs ;j++ ) {
401 if (sym2->regs[j] == sym1->regs[i])
409 /*-----------------------------------------------------------------*/
410 /* operandsEqu - equivalent */
411 /*-----------------------------------------------------------------*/
412 bool operandsEqu ( operand *op1, operand *op2)
416 /* if they not symbols */
417 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
420 sym1 = OP_SYMBOL(op1);
421 sym2 = OP_SYMBOL(op2);
423 /* if both are itemps & one is spilt
424 and the other is not then false */
425 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
426 sym1->isspilt != sym2->isspilt )
429 /* if they are the same */
433 if (strcmp(sym1->rname,sym2->rname) == 0)
437 /* if left is a tmp & right is not */
441 (sym1->usl.spillLoc == sym2))
448 (sym2->usl.spillLoc == sym1))
454 /*-----------------------------------------------------------------*/
455 /* sameRegs - two asmops have the same registers */
456 /*-----------------------------------------------------------------*/
457 bool sameRegs (asmop *aop1, asmop *aop2 )
464 if (aop1->type != AOP_REG ||
465 aop2->type != AOP_REG )
468 if (aop1->size != aop2->size)
471 for (i = 0 ; i < aop1->size ; i++ )
472 if (aop1->aopu.aop_reg[i] !=
473 aop2->aopu.aop_reg[i] )
479 /*-----------------------------------------------------------------*/
480 /* aopOp - allocates an asmop for an operand : */
481 /*-----------------------------------------------------------------*/
482 static void aopOp (operand *op, iCode *ic, bool result)
491 /* if this a literal */
492 if (IS_OP_LITERAL(op)) {
493 op->aop = aop = newAsmop(AOP_LIT);
494 aop->aopu.aop_lit = op->operand.valOperand;
495 aop->size = getSize(operandType(op));
499 /* if already has a asmop then continue */
503 /* if the underlying symbol has a aop */
504 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
505 op->aop = OP_SYMBOL(op)->aop;
509 /* if this is a true symbol */
510 if (IS_TRUE_SYMOP(op)) {
511 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
515 /* this is a temporary : this has
521 e) can be a return use only */
525 /* if the type is a conditional */
526 if (sym->regType == REG_CND) {
527 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
532 /* if it is spilt then two situations
534 b) has a spill location */
535 if (sym->isspilt || sym->nRegs == 0) {
536 /* rematerialize it NOW */
538 sym->aop = op->aop = aop =
540 aop->size = getSize(sym->type);
546 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
547 aop->size = getSize(sym->type);
548 for ( i = 0 ; i < 2 ; i++ )
549 aop->aopu.aop_str[i] = accUse[i];
555 aop = op->aop = sym->aop = newAsmop(AOP_STR);
556 aop->size = getSize(sym->type);
557 for ( i = 0 ; i < 4 ; i++ )
558 aop->aopu.aop_str[i] = _fReturn[i];
562 /* else spill location */
563 sym->aop = op->aop = aop =
564 aopForSym(ic,sym->usl.spillLoc,result);
565 aop->size = getSize(sym->type);
569 /* must be in a register */
570 sym->aop = op->aop = aop = newAsmop(AOP_REG);
571 aop->size = sym->nRegs;
572 for ( i = 0 ; i < sym->nRegs ;i++)
573 aop->aopu.aop_reg[i] = sym->regs[i];
576 /*-----------------------------------------------------------------*/
577 /* freeAsmop - free up the asmop given to an operand */
578 /*----------------------------------------------------------------*/
579 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
597 /* all other cases just dealloc */
601 OP_SYMBOL(op)->aop = NULL;
602 /* if the symbol has a spill */
604 SPIL_LOC(op)->aop = NULL;
609 bool isLitWord(asmop *aop)
611 /* if (aop->size != 2)
622 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
628 if (aop->size != 2 && aop->type != AOP_HL)
631 wassert(offset == 0);
633 /* depending on type */
638 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
639 ALLOC_ATOMIC(rs,strlen(s)+1);
643 value * val = aop->aopu.aop_lit;
644 /* if it is a float then it gets tricky */
645 /* otherwise it is fairly simple */
646 if (!IS_FLOAT(val->type)) {
647 unsigned long v = floatFromVal(val);
649 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
650 ALLOC_ATOMIC(rs,strlen(buffer)+1);
651 return strcpy (rs,buffer);
661 char *aopGetWord(asmop *aop, int offset)
663 return aopGetLitWordLong(aop, offset, TRUE);
666 bool isPtr(const char *s)
668 if (!strcmp(s, "hl"))
670 if (!strcmp(s, "ix"))
672 if (!strcmp(s, "iy"))
677 static void adjustPair(const char *pair, int *pold, int new)
681 while (*pold < new) {
682 emitcode("inc", "%s", pair);
685 while (*pold > new) {
686 emitcode("dec", "%s", pair);
691 static void spillPair(PAIR_ID pairId)
693 _G.pairs[pairId].last_type = AOP_INVALID;
694 _G.pairs[pairId].lit = NULL;
697 static void spillCached(void)
703 static bool requiresHL(asmop *aop)
714 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
717 const char *pair = _pairs[pairId].name;
718 l = aopGetLitWordLong(left, 0, FALSE);
722 if (pairId == PAIR_HL || pairId == PAIR_IY) {
723 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
724 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
725 adjustPair(pair, &_G.pairs[pairId].offset, offset);
728 if (pairId == PAIR_IY && abs(offset)<127) {
733 _G.pairs[pairId].last_type = left->type;
734 _G.pairs[pairId].lit = _strdup(l);
735 _G.pairs[pairId].offset = offset;
737 /* Both a lit on the right and a true symbol on the left */
739 emitcode("ld", "%s,#%s + %d", pair, l, offset);
741 emitcode("ld", "%s,#%s", pair, l);
744 static void fetchPair(PAIR_ID pairId, asmop *aop)
746 /* if this is remateriazable */
747 if (isLitWord(aop)) {
748 fetchLitPair(pairId, aop, 0);
750 else { /* we need to get it byte by byte */
751 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
752 aopGet(aop, 0, FALSE);
753 emitcode("ld", "a,(hl+)");
754 emitcode("ld", "h,(hl)");
755 emitcode("ld", "l,a");
758 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, 0, FALSE));
759 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, 1, FALSE));
761 /* PENDING: check? */
762 if (pairId == PAIR_HL)
767 static void fetchHL(asmop *aop)
769 fetchPair(PAIR_HL, aop);
772 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
774 assert(pairId == PAIR_HL || pairId == PAIR_IY);
779 fetchLitPair(pairId, aop, offset);
780 _G.pairs[pairId].offset = offset;
783 /* Doesnt include _G.stack.pushed */
784 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
785 assert(pairId == PAIR_HL);
786 /* In some cases we can still inc or dec hl */
787 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
788 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
791 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _G.stack.pushed, _G.stack.offset);
793 _G.pairs[pairId].offset = abso;
799 _G.pairs[pairId].last_type = aop->type;
802 static void emitLabel(int key)
804 emitcode("", LABEL_STR ":", key);
808 /*-----------------------------------------------------------------*/
809 /* aopGet - for fetching value of the aop */
810 /*-----------------------------------------------------------------*/
811 static char *aopGet(asmop *aop, int offset, bool bit16)
816 /* offset is greater than size then zero */
817 /* PENDING: this seems a bit screwed in some pointer cases. */
818 if (offset > (aop->size - 1) &&
819 aop->type != AOP_LIT)
822 /* depending on type */
826 sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
829 wassert(offset == 1);
836 ALLOC_ATOMIC(rs,strlen(s)+1);
842 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
844 ALLOC_ATOMIC(rs,strlen(s)+1);
849 return aop->aopu.aop_reg[offset]->name;
854 setupPair(PAIR_HL, aop, offset);
856 return _strdup("(hl)");
860 setupPair(PAIR_IY, aop, offset);
861 sprintf(s,"%d(iy)", offset);
862 ALLOC_ATOMIC(rs,strlen(s)+1);
868 setupPair(PAIR_HL, aop, offset);
872 sprintf(s,"%d(ix)", aop->aopu.aop_stk+offset);
874 ALLOC_ATOMIC(rs,strlen(s)+1);
888 return aopLiteral (aop->aopu.aop_lit,offset);
892 return aop->aopu.aop_str[offset];
896 wassertl(0, "aopget got unsupported aop->type");
900 bool isRegString(char *s)
902 if (!strcmp(s, "b") ||
913 bool isConstant(const char *s)
918 bool canAssignToPtr(char *s)
927 /*-----------------------------------------------------------------*/
928 /* aopPut - puts a string for a aop */
929 /*-----------------------------------------------------------------*/
930 static void aopPut (asmop *aop, char *s, int offset)
932 if (aop->size && offset > ( aop->size - 1)) {
933 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
934 "aopPut got offset > aop->size");
938 /* will assign value to value */
939 /* depending on where it is ofcourse */
944 emitcode("ld", "a,%s", s);
945 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
949 /* Dont bother if it's a ld x,x */
950 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
951 emitcode("ld","%s,%s",
952 aop->aopu.aop_reg[offset]->name,s);
958 setupPair(PAIR_IY, aop, offset);
959 if (!canAssignToPtr(s)) {
960 emitcode("ld", "a,%s", s);
961 emitcode("ld", "%d(iy),a", offset);
964 emitcode("ld", "%d(iy),%s", offset, s);
969 if (!strcmp(s, "(hl)")) {
970 emitcode("ld", "a,(hl)");
974 setupPair(PAIR_HL, aop, offset);
975 emitcode("ld", "(hl),%s", s);
980 if (!strcmp("(hl)", s)) {
981 emitcode("ld", "a,(hl)");
984 setupPair(PAIR_HL, aop, offset);
985 if (!canAssignToPtr(s)) {
986 emitcode("ld", "a,%s", s);
987 emitcode("ld", "(hl),a");
990 emitcode("ld", "(hl),%s", s);
993 if (!canAssignToPtr(s)) {
994 emitcode("ld", "a,%s", s);
995 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
998 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
1003 /* if bit variable */
1004 if (!aop->aopu.aop_dir) {
1005 emitcode("ld", "a,#0");
1006 emitcode("rla", "");
1008 /* In bit space but not in C - cant happen */
1015 if (strcmp(aop->aopu.aop_str[offset],s)) {
1016 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1022 if (!offset && (strcmp(s,"acc") == 0))
1026 emitcode("", "; Error aopPut AOP_ACC");
1029 if (strcmp(aop->aopu.aop_str[offset],s))
1030 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1035 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1036 "aopPut got unsupported aop->type");
1041 #define AOP(op) op->aop
1042 #define AOP_TYPE(op) AOP(op)->type
1043 #define AOP_SIZE(op) AOP(op)->size
1044 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1046 /*-----------------------------------------------------------------*/
1047 /* getDataSize - get the operand data size */
1048 /*-----------------------------------------------------------------*/
1049 int getDataSize(operand *op)
1052 size = AOP_SIZE(op);
1060 /*-----------------------------------------------------------------*/
1061 /* movLeft2Result - move byte from left to result */
1062 /*-----------------------------------------------------------------*/
1063 static void movLeft2Result (operand *left, int offl,
1064 operand *result, int offr, int sign)
1067 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1068 l = aopGet(AOP(left),offl,FALSE);
1071 aopPut(AOP(result),l,offr);
1080 /** Put Acc into a register set
1082 void outAcc(operand *result)
1085 size = getDataSize(result);
1087 aopPut(AOP(result),"a",0);
1090 /* unsigned or positive */
1092 aopPut(AOP(result),zero,offset++);
1097 /** Take the value in carry and put it into a register
1099 void outBitC(operand *result)
1101 /* if the result is bit */
1102 if (AOP_TYPE(result) == AOP_CRY) {
1103 emitcode("", "; Note: outBitC form 1");
1104 aopPut(AOP(result),"blah",0);
1107 emitcode("ld", "a,#0");
1108 emitcode("rla", "");
1113 /*-----------------------------------------------------------------*/
1114 /* toBoolean - emit code for orl a,operator(sizeop) */
1115 /*-----------------------------------------------------------------*/
1116 void toBoolean(operand *oper)
1118 int size = AOP_SIZE(oper);
1121 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1124 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1127 if (AOP(oper)->type != AOP_ACC) {
1129 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1134 /*-----------------------------------------------------------------*/
1135 /* genNot - generate code for ! operation */
1136 /*-----------------------------------------------------------------*/
1137 static void genNot (iCode *ic)
1139 link *optype = operandType(IC_LEFT(ic));
1141 /* assign asmOps to operand & result */
1142 aopOp (IC_LEFT(ic),ic,FALSE);
1143 aopOp (IC_RESULT(ic),ic,TRUE);
1145 /* if in bit space then a special case */
1146 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1150 /* if type float then do float */
1151 if (IS_FLOAT(optype)) {
1155 toBoolean(IC_LEFT(ic));
1160 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1161 emitcode("sub", "a,#0x01");
1162 outBitC(IC_RESULT(ic));
1164 /* release the aops */
1165 freeAsmop(IC_LEFT(ic),NULL,ic);
1166 freeAsmop(IC_RESULT(ic),NULL,ic);
1169 /*-----------------------------------------------------------------*/
1170 /* genCpl - generate code for complement */
1171 /*-----------------------------------------------------------------*/
1172 static void genCpl (iCode *ic)
1178 /* assign asmOps to operand & result */
1179 aopOp (IC_LEFT(ic),ic,FALSE);
1180 aopOp (IC_RESULT(ic),ic,TRUE);
1182 /* if both are in bit space then
1184 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1185 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1189 size = AOP_SIZE(IC_RESULT(ic));
1191 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1194 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1197 /* release the aops */
1198 freeAsmop(IC_LEFT(ic),NULL,ic);
1199 freeAsmop(IC_RESULT(ic),NULL,ic);
1202 /*-----------------------------------------------------------------*/
1203 /* genUminus - unary minus code generation */
1204 /*-----------------------------------------------------------------*/
1205 static void genUminus (iCode *ic)
1208 link *optype, *rtype;
1211 aopOp(IC_LEFT(ic),ic,FALSE);
1212 aopOp(IC_RESULT(ic),ic,TRUE);
1214 /* if both in bit space then special
1216 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1217 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1222 optype = operandType(IC_LEFT(ic));
1223 rtype = operandType(IC_RESULT(ic));
1225 /* if float then do float stuff */
1226 if (IS_FLOAT(optype)) {
1231 /* otherwise subtract from zero */
1232 size = AOP_SIZE(IC_LEFT(ic));
1236 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1237 emitcode("ld", "a,#0");
1238 emitcode("sbc","a,%s",l);
1239 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1242 /* if any remaining bytes in the result */
1243 /* we just need to propagate the sign */
1244 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1245 emitcode("rlc","a");
1246 emitcode("sbc","a,a");
1248 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1252 /* release the aops */
1253 freeAsmop(IC_LEFT(ic),NULL,ic);
1254 freeAsmop(IC_RESULT(ic),NULL,ic);
1257 /*-----------------------------------------------------------------*/
1258 /* assignResultValue - */
1259 /*-----------------------------------------------------------------*/
1260 void assignResultValue(operand * oper)
1263 int size = AOP_SIZE(oper);
1268 aopPut(AOP(oper),_fReturn[offset],offset);
1273 /*-----------------------------------------------------------------*/
1274 /* genIpush - genrate code for pushing this gets a little complex */
1275 /*-----------------------------------------------------------------*/
1276 static void genIpush (iCode *ic)
1278 int size, offset = 0 ;
1282 /* if this is not a parm push : ie. it is spill push
1283 and spill push is always done on the local stack */
1284 if (!ic->parmPush) {
1285 /* and the item is spilt then do nothing */
1286 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1289 aopOp(IC_LEFT(ic),ic,FALSE);
1290 size = AOP_SIZE(IC_LEFT(ic));
1291 /* push it on the stack */
1292 if (isPair(AOP(IC_LEFT(ic)))) {
1293 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1294 _G.stack.pushed += 2;
1299 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1300 /* Simple for now - load into A and PUSH AF */
1301 emitcode("ld", "a,%s", l);
1302 emitcode("push", "af");
1303 emitcode("inc", "sp");
1310 /* Hmmm... what about saving the currently used registers
1313 /* then do the push */
1314 aopOp(IC_LEFT(ic),ic,FALSE);
1316 size = AOP_SIZE(IC_LEFT(ic));
1318 if (isPair(AOP(IC_LEFT(ic)))) {
1320 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1324 fetchHL(AOP(IC_LEFT(ic)));
1325 emitcode("push", "hl ; 2");
1327 _G.stack.pushed += 2;
1332 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1333 emitcode("ld", "a,%s", l);
1334 emitcode("push", "af");
1335 emitcode("inc", "sp");
1340 freeAsmop(IC_LEFT(ic),NULL,ic);
1343 /*-----------------------------------------------------------------*/
1344 /* genIpop - recover the registers: can happen only for spilling */
1345 /*-----------------------------------------------------------------*/
1346 static void genIpop (iCode *ic)
1351 /* if the temp was not pushed then */
1352 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1355 aopOp(IC_LEFT(ic),ic,FALSE);
1356 size = AOP_SIZE(IC_LEFT(ic));
1358 if (isPair(AOP(IC_LEFT(ic)))) {
1359 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1363 emitcode("dec", "sp");
1364 emitcode("pop", "hl");
1366 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1370 freeAsmop(IC_LEFT(ic),NULL,ic);
1373 /** Emit the code for a call statement
1375 static void emitCall (iCode *ic, bool ispcall)
1377 /* if caller saves & we have not saved then */
1378 if (!ic->regsSaved) {
1382 /* if send set is not empty then assign */
1385 for (sic = setFirstItem(sendSet) ; sic ;
1386 sic = setNextItem(sendSet)) {
1387 int size, offset = 0;
1388 aopOp(IC_LEFT(sic),sic,FALSE);
1389 size = AOP_SIZE(IC_LEFT(sic));
1391 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1393 if (strcmp(l, _fReturn[offset]))
1394 emitcode("ld","%s,%s",
1399 freeAsmop (IC_LEFT(sic),NULL,sic);
1405 aopOp(IC_LEFT(ic),ic,FALSE);
1407 if (isLitWord(AOP(IC_LEFT(ic)))) {
1408 emitcode("", "; Special case where the pCall is to a constant");
1409 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1412 symbol *rlbl = newiTempLabel(NULL);
1414 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1415 emitcode("push", "hl");
1416 _G.stack.pushed += 2;
1418 fetchHL(AOP(IC_LEFT(ic)));
1419 emitcode("jp", "(hl)");
1420 emitcode("","%05d$:",(rlbl->key+100));
1421 _G.stack.pushed -= 2;
1423 freeAsmop(IC_LEFT(ic),NULL,ic);
1427 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1428 OP_SYMBOL(IC_LEFT(ic))->rname :
1429 OP_SYMBOL(IC_LEFT(ic))->name;
1430 emitcode("call", "%s", name);
1434 /* if we need assign a result value */
1435 if ((IS_ITEMP(IC_RESULT(ic)) &&
1436 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1437 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1438 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1441 aopOp(IC_RESULT(ic),ic,FALSE);
1444 assignResultValue(IC_RESULT(ic));
1446 freeAsmop(IC_RESULT(ic),NULL, ic);
1449 /* adjust the stack for parameters if required */
1450 if (IC_LEFT(ic)->parmBytes) {
1451 int i = IC_LEFT(ic)->parmBytes;
1452 _G.stack.pushed -= i;
1454 emitcode("lda", "sp,%d(sp)", i);
1459 emitcode("ld", "hl,#%d", i);
1460 emitcode("add", "hl,sp");
1461 emitcode("ld", "sp,hl");
1465 emitcode("pop", "hl");
1469 emitcode("inc", "sp");
1477 /*-----------------------------------------------------------------*/
1478 /* genCall - generates a call statement */
1479 /*-----------------------------------------------------------------*/
1480 static void genCall (iCode *ic)
1482 emitCall(ic, FALSE);
1485 /*-----------------------------------------------------------------*/
1486 /* genPcall - generates a call by pointer statement */
1487 /*-----------------------------------------------------------------*/
1488 static void genPcall (iCode *ic)
1493 /*-----------------------------------------------------------------*/
1494 /* resultRemat - result is rematerializable */
1495 /*-----------------------------------------------------------------*/
1496 static int resultRemat (iCode *ic)
1498 if (SKIP_IC(ic) || ic->op == IFX)
1501 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1502 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1503 if (sym->remat && !POINTER_SET(ic))
1510 /*-----------------------------------------------------------------*/
1511 /* genFunction - generated code for function entry */
1512 /*-----------------------------------------------------------------*/
1513 static void genFunction (iCode *ic)
1515 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1519 /* create the function header */
1520 emitcode(";","-----------------------------------------");
1521 emitcode(";"," function %s", sym->name);
1522 emitcode(";","-----------------------------------------");
1524 emitcode("", "__%s_start:", sym->rname);
1525 emitcode("","%s:",sym->rname);
1527 fetype = getSpec(operandType(IC_LEFT(ic)));
1529 /* if critical function then turn interrupts off */
1530 if (SPEC_CRTCL(fetype))
1533 /* if this is an interrupt service routine then
1534 save acc, b, dpl, dph */
1535 if (IS_ISR(sym->etype)) {
1536 emitcode("push", "af");
1537 emitcode("push", "bc");
1538 emitcode("push", "de");
1539 emitcode("push", "hl");
1541 /* PENDING: callee-save etc */
1543 /* adjust the stack for the function */
1544 emitcode("push", "bc");
1546 emitcode("push", "de");
1547 emitcode("push", "ix");
1548 emitcode("ld", "ix,#0");
1549 emitcode("add", "ix,sp");
1552 _G.stack.last = sym->stack;
1556 emitcode("lda", "sp,-%d(sp)", sym->stack);
1559 emitcode("ld", "hl,#-%d", sym->stack);
1560 emitcode("add", "hl,sp");
1561 emitcode("ld", "sp,hl");
1564 _G.stack.offset = sym->stack;
1567 /*-----------------------------------------------------------------*/
1568 /* genEndFunction - generates epilogue for functions */
1569 /*-----------------------------------------------------------------*/
1570 static void genEndFunction (iCode *ic)
1572 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1574 if (IS_ISR(sym->etype)) {
1578 if (SPEC_CRTCL(sym->etype))
1581 /* PENDING: calleeSave */
1583 /* if debug then send end of function */
1584 if (options.debug && currFunc) {
1586 emitcode("","C$%s$%d$%d$%d ==.",
1587 ic->filename,currFunc->lastLine,
1588 ic->level,ic->block);
1589 if (IS_STATIC(currFunc->etype))
1590 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1592 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1596 emitcode("ld", "sp,ix");
1597 emitcode("pop", "ix");
1598 emitcode("pop", "de");
1601 if (_G.stack.offset) {
1602 emitcode("ld", "hl,#%d", _G.stack.offset);
1603 emitcode("add", "hl,sp");
1604 emitcode("ld", "sp,hl");
1607 emitcode("pop", "bc");
1608 emitcode("ret", "");
1609 emitcode("; Useful for profiling and debugging", "");
1610 emitcode(".dw", "%s", sym->rname);
1611 emitcode("", "__%s_end:", sym->rname);
1613 _G.stack.pushed = 0;
1614 _G.stack.offset = 0;
1617 /*-----------------------------------------------------------------*/
1618 /* genRet - generate code for return statement */
1619 /*-----------------------------------------------------------------*/
1620 static void genRet (iCode *ic)
1623 /* Errk. This is a hack until I can figure out how
1624 to cause dehl to spill on a call */
1625 int size,offset = 0;
1627 /* if we have no return value then
1628 just generate the "ret" */
1632 /* we have something to return then
1633 move the return value into place */
1634 aopOp(IC_LEFT(ic),ic,FALSE);
1635 size = AOP_SIZE(IC_LEFT(ic));
1637 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1639 emitcode("ld", "de,%s", l);
1642 emitcode("ld", "hl,%s", l);
1647 l = aopGet(AOP(IC_LEFT(ic)),offset,
1649 if (strcmp(_fReturn[offset],l))
1650 emitcode("ld","%s,%s", _fReturn[offset++],l);
1653 freeAsmop (IC_LEFT(ic),NULL,ic);
1656 /* generate a jump to the return label
1657 if the next is not the return statement */
1658 if (!(ic->next && ic->next->op == LABEL &&
1659 IC_LABEL(ic->next) == returnLabel))
1661 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1664 /*-----------------------------------------------------------------*/
1665 /* genLabel - generates a label */
1666 /*-----------------------------------------------------------------*/
1667 static void genLabel (iCode *ic)
1669 /* special case never generate */
1670 if (IC_LABEL(ic) == entryLabel)
1673 emitLabel(IC_LABEL(ic)->key+100);
1676 /*-----------------------------------------------------------------*/
1677 /* genGoto - generates a ljmp */
1678 /*-----------------------------------------------------------------*/
1679 static void genGoto (iCode *ic)
1681 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1684 /*-----------------------------------------------------------------*/
1685 /* genPlusIncr :- does addition with increment if possible */
1686 /*-----------------------------------------------------------------*/
1687 static bool genPlusIncr (iCode *ic)
1689 unsigned int icount ;
1690 unsigned int size = getDataSize(IC_RESULT(ic));
1691 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
1693 /* will try to generate an increment */
1694 /* if the right side is not a literal
1696 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1699 emitcode("", "; genPlusIncr");
1701 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1703 /* If result is a pair */
1704 if (resultId != PAIR_INVALID) {
1705 if (isLitWord(AOP(IC_LEFT(ic)))) {
1706 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1709 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
1710 fetchPair(resultId, AOP(IC_RIGHT(ic)));
1711 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
1717 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1720 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1721 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1724 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1729 /* if the literal value of the right hand side
1730 is greater than 4 then it is not worth it */
1734 /* if increment 16 bits in register */
1735 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1738 symbol *tlbl = newiTempLabel(NULL);
1739 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1740 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1742 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1746 emitLabel(tlbl->key+100);
1750 /* if the sizes are greater than 1 then we cannot */
1751 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1752 AOP_SIZE(IC_LEFT(ic)) > 1 )
1755 /* we can if the aops of the left & result match or
1756 if they are in registers and the registers are the
1758 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1760 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1768 /*-----------------------------------------------------------------*/
1769 /* outBitAcc - output a bit in acc */
1770 /*-----------------------------------------------------------------*/
1771 void outBitAcc(operand *result)
1773 symbol *tlbl = newiTempLabel(NULL);
1774 /* if the result is a bit */
1775 if (AOP_TYPE(result) == AOP_CRY){
1779 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1780 emitcode("ld","a,%s",one);
1781 emitLabel(tlbl->key+100);
1786 /*-----------------------------------------------------------------*/
1787 /* genPlus - generates code for addition */
1788 /*-----------------------------------------------------------------*/
1789 static void genPlus (iCode *ic)
1791 int size, offset = 0;
1793 /* special cases :- */
1795 aopOp (IC_LEFT(ic),ic,FALSE);
1796 aopOp (IC_RIGHT(ic),ic,FALSE);
1797 aopOp (IC_RESULT(ic),ic,TRUE);
1799 /* Swap the left and right operands if:
1801 if literal, literal on the right or
1802 if left requires ACC or right is already
1805 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1806 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1807 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1808 operand *t = IC_RIGHT(ic);
1809 IC_RIGHT(ic) = IC_LEFT(ic);
1813 /* if both left & right are in bit
1815 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1816 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1821 /* if left in bit space & right literal */
1822 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1823 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1824 /* Can happen I guess */
1828 /* if I can do an increment instead
1829 of add then GOOD for ME */
1830 if (genPlusIncr (ic) == TRUE)
1833 size = getDataSize(IC_RESULT(ic));
1835 /* Special case when left and right are constant */
1836 if (isPair(AOP(IC_RESULT(ic)))) {
1839 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1840 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1841 if (left && right) {
1845 sprintf(buffer, "#(%s + %s)", left, right);
1846 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1851 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1852 /* Fetch into HL then do the add */
1854 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1855 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1860 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1861 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1863 emitcode("add","a,%s",
1864 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1866 emitcode("adc","a,%s",
1867 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1869 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1871 emitcode("add","a,%s",
1872 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1874 emitcode("adc","a,%s",
1875 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1877 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1880 /* Some kind of pointer arith. */
1881 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1882 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1883 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1886 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1887 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1888 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1893 freeAsmop(IC_LEFT(ic),NULL,ic);
1894 freeAsmop(IC_RIGHT(ic),NULL,ic);
1895 freeAsmop(IC_RESULT(ic),NULL,ic);
1899 /*-----------------------------------------------------------------*/
1900 /* genMinusDec :- does subtraction with deccrement if possible */
1901 /*-----------------------------------------------------------------*/
1902 static bool genMinusDec (iCode *ic)
1904 unsigned int icount ;
1905 unsigned int size = getDataSize(IC_RESULT(ic));
1907 /* will try to generate an increment */
1908 /* if the right side is not a literal we cannot */
1909 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1912 /* if the literal value of the right hand side
1913 is greater than 4 then it is not worth it */
1914 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1917 size = getDataSize(IC_RESULT(ic));
1920 /* if increment 16 bits in register */
1921 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1924 symbol *tlbl = newiTempLabel(NULL);
1925 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1926 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1928 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1932 emitLabel(tlbl->key+100);
1937 /* if decrement 16 bits in register */
1938 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1939 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1941 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1945 /* If result is a pair */
1946 if (isPair(AOP(IC_RESULT(ic)))) {
1947 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1948 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1950 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1954 /* if the sizes are greater than 1 then we cannot */
1955 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1956 AOP_SIZE(IC_LEFT(ic)) > 1 )
1959 /* we can if the aops of the left & result match or if they are in
1960 registers and the registers are the same */
1961 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1963 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1970 /*-----------------------------------------------------------------*/
1971 /* genMinus - generates code for subtraction */
1972 /*-----------------------------------------------------------------*/
1973 static void genMinus (iCode *ic)
1975 int size, offset = 0;
1976 unsigned long lit = 0L;
1978 aopOp (IC_LEFT(ic),ic,FALSE);
1979 aopOp (IC_RIGHT(ic),ic,FALSE);
1980 aopOp (IC_RESULT(ic),ic,TRUE);
1982 /* special cases :- */
1983 /* if both left & right are in bit space */
1984 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1985 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1990 /* if I can do an decrement instead of subtract then GOOD for ME */
1991 if (genMinusDec (ic) == TRUE)
1994 size = getDataSize(IC_RESULT(ic));
1996 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1999 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2004 /* if literal, add a,#-lit, else normal subb */
2006 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2007 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2009 emitcode("sub","a,%s",
2010 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2012 emitcode("sbc","a,%s",
2013 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2016 /* first add without previous c */
2018 emitcode("add","a,#0x%02x",
2019 (unsigned int)(lit & 0x0FFL));
2021 emitcode("adc","a,#0x%02x",
2022 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2024 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2027 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2028 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2029 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2033 freeAsmop(IC_LEFT(ic),NULL,ic);
2034 freeAsmop(IC_RIGHT(ic),NULL,ic);
2035 freeAsmop(IC_RESULT(ic),NULL,ic);
2038 /*-----------------------------------------------------------------*/
2039 /* genMult - generates code for multiplication */
2040 /*-----------------------------------------------------------------*/
2041 static void genMult (iCode *ic)
2043 /* Shouldn't occur - all done through function calls */
2047 /*-----------------------------------------------------------------*/
2048 /* genDiv - generates code for division */
2049 /*-----------------------------------------------------------------*/
2050 static void genDiv (iCode *ic)
2052 /* Shouldn't occur - all done through function calls */
2056 /*-----------------------------------------------------------------*/
2057 /* genMod - generates code for division */
2058 /*-----------------------------------------------------------------*/
2059 static void genMod (iCode *ic)
2061 /* Shouldn't occur - all done through function calls */
2065 /*-----------------------------------------------------------------*/
2066 /* genIfxJump :- will create a jump depending on the ifx */
2067 /*-----------------------------------------------------------------*/
2068 static void genIfxJump (iCode *ic, char *jval)
2073 /* if true label then we jump if condition
2075 if ( IC_TRUE(ic) ) {
2077 if (!strcmp(jval, "a")) {
2080 else if (!strcmp(jval, "c")) {
2084 /* The buffer contains the bit on A that we should test */
2089 /* false label is present */
2090 jlbl = IC_FALSE(ic) ;
2091 if (!strcmp(jval, "a")) {
2094 else if (!strcmp(jval, "c")) {
2098 /* The buffer contains the bit on A that we should test */
2102 /* Z80 can do a conditional long jump */
2103 if (!strcmp(jval, "a")) {
2104 emitcode("or", "a,a");
2106 else if (!strcmp(jval, "c")) {
2109 emitcode("bit", "%s,a", jval);
2111 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
2113 /* mark the icode as generated */
2117 /** Generic compare for > or <
2119 static void genCmp (operand *left,operand *right,
2120 operand *result, iCode *ifx, int sign)
2122 int size, offset = 0 ;
2123 unsigned long lit = 0L;
2125 /* if left & right are bit variables */
2126 if (AOP_TYPE(left) == AOP_CRY &&
2127 AOP_TYPE(right) == AOP_CRY ) {
2128 /* Cant happen on the Z80 */
2131 /* subtract right from left if at the
2132 end the carry flag is set then we know that
2133 left is greater than right */
2134 size = max(AOP_SIZE(left),AOP_SIZE(right));
2136 /* if unsigned char cmp with lit, just compare */
2138 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2139 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2141 emitcode("xor", "a,#0x80");
2142 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
2145 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
2148 if(AOP_TYPE(right) == AOP_LIT) {
2149 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2150 /* optimize if(x < 0) or if(x >= 0) */
2153 /* No sign so it's always false */
2157 /* Just load in the top most bit */
2158 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2159 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2160 genIfxJump (ifx,"7");
2164 emitcode("rlc","a");
2170 /* First setup h and l contaning the top most bytes XORed */
2171 bool fDidXor = FALSE;
2172 if (AOP_TYPE(left) == AOP_LIT){
2173 unsigned long lit = (unsigned long)
2174 floatFromVal(AOP(left)->aopu.aop_lit);
2175 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2176 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2179 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2180 emitcode("xor", "a,#0x80");
2181 emitcode("ld", "%s,a", _fTmp[0]);
2184 if (AOP_TYPE(right) == AOP_LIT) {
2185 unsigned long lit = (unsigned long)
2186 floatFromVal(AOP(right)->aopu.aop_lit);
2187 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2188 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2191 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2192 emitcode("xor", "a,#0x80");
2193 emitcode("ld", "%s,a", _fTmp[1]);
2203 /* Do a long subtract */
2204 if (!sign || size ) {
2205 MOVA(aopGet(AOP(left),offset,FALSE));
2207 if (sign && size == 0) {
2208 emitcode("ld", "a,%s", _fTmp[0]);
2209 emitcode("sbc", "a,%s", _fTmp[1]);
2212 /* Subtract through, propagating the carry */
2213 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2220 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2223 /* if the result is used in the next
2224 ifx conditional branch then generate
2225 code a little differently */
2227 genIfxJump (ifx,"c");
2230 /* leave the result in acc */
2234 /*-----------------------------------------------------------------*/
2235 /* genCmpGt :- greater than comparison */
2236 /*-----------------------------------------------------------------*/
2237 static void genCmpGt (iCode *ic, iCode *ifx)
2239 operand *left, *right, *result;
2240 link *letype , *retype;
2244 right= IC_RIGHT(ic);
2245 result = IC_RESULT(ic);
2247 letype = getSpec(operandType(left));
2248 retype =getSpec(operandType(right));
2249 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2250 /* assign the amsops */
2251 aopOp (left,ic,FALSE);
2252 aopOp (right,ic,FALSE);
2253 aopOp (result,ic,TRUE);
2255 genCmp(right, left, result, ifx, sign);
2257 freeAsmop(left,NULL,ic);
2258 freeAsmop(right,NULL,ic);
2259 freeAsmop(result,NULL,ic);
2262 /*-----------------------------------------------------------------*/
2263 /* genCmpLt - less than comparisons */
2264 /*-----------------------------------------------------------------*/
2265 static void genCmpLt (iCode *ic, iCode *ifx)
2267 operand *left, *right, *result;
2268 link *letype , *retype;
2272 right= IC_RIGHT(ic);
2273 result = IC_RESULT(ic);
2275 letype = getSpec(operandType(left));
2276 retype =getSpec(operandType(right));
2277 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2279 /* assign the amsops */
2280 aopOp (left,ic,FALSE);
2281 aopOp (right,ic,FALSE);
2282 aopOp (result,ic,TRUE);
2284 genCmp(left, right, result, ifx, sign);
2286 freeAsmop(left,NULL,ic);
2287 freeAsmop(right,NULL,ic);
2288 freeAsmop(result,NULL,ic);
2291 /*-----------------------------------------------------------------*/
2292 /* gencjneshort - compare and jump if not equal */
2293 /*-----------------------------------------------------------------*/
2294 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2296 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2298 unsigned long lit = 0L;
2300 /* Swap the left and right if it makes the computation easier */
2301 if (AOP_TYPE(left) == AOP_LIT) {
2307 if(AOP_TYPE(right) == AOP_LIT)
2308 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2310 /* if the right side is a literal then anything goes */
2311 if (AOP_TYPE(right) == AOP_LIT &&
2312 AOP_TYPE(left) != AOP_DIR ) {
2314 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2319 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2323 emitcode("or", "a,a");
2325 emitcode("jp", "nz," LABEL_STR, lbl->key+100);
2329 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2330 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2331 emitcode("or", "a,a");
2333 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2334 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2339 /* if the right side is in a register or in direct space or
2340 if the left is a pointer register & right is not */
2341 else if (AOP_TYPE(right) == AOP_REG ||
2342 AOP_TYPE(right) == AOP_DIR ||
2343 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2345 MOVA(aopGet(AOP(left),offset,FALSE));
2346 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2347 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2349 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2351 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2352 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2357 /* right is a pointer reg need both a & b */
2358 /* PENDING: is this required? */
2360 MOVA(aopGet(AOP(right),offset,FALSE));
2361 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2362 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2368 /*-----------------------------------------------------------------*/
2369 /* gencjne - compare and jump if not equal */
2370 /*-----------------------------------------------------------------*/
2371 static void gencjne(operand *left, operand *right, symbol *lbl)
2373 symbol *tlbl = newiTempLabel(NULL);
2375 gencjneshort(left, right, lbl);
2378 emitcode("ld","a,%s",one);
2379 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2380 emitLabel(lbl->key+100);
2381 emitcode("xor","a,a");
2382 emitLabel(tlbl->key+100);
2385 /*-----------------------------------------------------------------*/
2386 /* genCmpEq - generates code for equal to */
2387 /*-----------------------------------------------------------------*/
2388 static void genCmpEq (iCode *ic, iCode *ifx)
2390 operand *left, *right, *result;
2392 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2393 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2394 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2396 /* Swap operands if it makes the operation easier. ie if:
2397 1. Left is a literal.
2399 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2400 operand *t = IC_RIGHT(ic);
2401 IC_RIGHT(ic) = IC_LEFT(ic);
2405 if (ifx && !AOP_SIZE(result)){
2407 /* if they are both bit variables */
2408 if (AOP_TYPE(left) == AOP_CRY &&
2409 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2412 tlbl = newiTempLabel(NULL);
2413 gencjneshort(left, right, tlbl);
2414 if ( IC_TRUE(ifx) ) {
2415 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2416 emitLabel(tlbl->key+100);
2418 /* PENDING: do this better */
2419 symbol *lbl = newiTempLabel(NULL);
2420 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2421 emitLabel(tlbl->key+100);
2422 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2423 emitLabel(lbl->key+100);
2426 /* mark the icode as generated */
2431 /* if they are both bit variables */
2432 if (AOP_TYPE(left) == AOP_CRY &&
2433 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2436 gencjne(left,right,newiTempLabel(NULL));
2437 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2441 genIfxJump(ifx,"a");
2444 /* if the result is used in an arithmetic operation
2445 then put the result in place */
2446 if (AOP_TYPE(result) != AOP_CRY) {
2449 /* leave the result in acc */
2453 freeAsmop(left,NULL,ic);
2454 freeAsmop(right,NULL,ic);
2455 freeAsmop(result,NULL,ic);
2458 /*-----------------------------------------------------------------*/
2459 /* ifxForOp - returns the icode containing the ifx for operand */
2460 /*-----------------------------------------------------------------*/
2461 static iCode *ifxForOp ( operand *op, iCode *ic )
2463 /* if true symbol then needs to be assigned */
2464 if (IS_TRUE_SYMOP(op))
2467 /* if this has register type condition and
2468 the next instruction is ifx with the same operand
2469 and live to of the operand is upto the ifx only then */
2471 ic->next->op == IFX &&
2472 IC_COND(ic->next)->key == op->key &&
2473 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2479 /*-----------------------------------------------------------------*/
2480 /* genAndOp - for && operation */
2481 /*-----------------------------------------------------------------*/
2482 static void genAndOp (iCode *ic)
2484 operand *left,*right, *result;
2487 /* note here that && operations that are in an if statement are
2488 taken away by backPatchLabels only those used in arthmetic
2489 operations remain */
2490 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2491 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2492 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2494 /* if both are bit variables */
2495 if (AOP_TYPE(left) == AOP_CRY &&
2496 AOP_TYPE(right) == AOP_CRY ) {
2499 tlbl = newiTempLabel(NULL);
2501 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2503 emitLabel(tlbl->key+100);
2507 freeAsmop(left,NULL,ic);
2508 freeAsmop(right,NULL,ic);
2509 freeAsmop(result,NULL,ic);
2512 /*-----------------------------------------------------------------*/
2513 /* genOrOp - for || operation */
2514 /*-----------------------------------------------------------------*/
2515 static void genOrOp (iCode *ic)
2517 operand *left,*right, *result;
2520 /* note here that || operations that are in an
2521 if statement are taken away by backPatchLabels
2522 only those used in arthmetic operations remain */
2523 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2524 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2525 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2527 /* if both are bit variables */
2528 if (AOP_TYPE(left) == AOP_CRY &&
2529 AOP_TYPE(right) == AOP_CRY ) {
2532 tlbl = newiTempLabel(NULL);
2534 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2536 emitLabel(tlbl->key+100);
2540 freeAsmop(left,NULL,ic);
2541 freeAsmop(right,NULL,ic);
2542 freeAsmop(result,NULL,ic);
2545 /*-----------------------------------------------------------------*/
2546 /* isLiteralBit - test if lit == 2^n */
2547 /*-----------------------------------------------------------------*/
2548 int isLiteralBit(unsigned long lit)
2550 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2551 0x100L,0x200L,0x400L,0x800L,
2552 0x1000L,0x2000L,0x4000L,0x8000L,
2553 0x10000L,0x20000L,0x40000L,0x80000L,
2554 0x100000L,0x200000L,0x400000L,0x800000L,
2555 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2556 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2559 for(idx = 0; idx < 32; idx++)
2565 /*-----------------------------------------------------------------*/
2566 /* jmpTrueOrFalse - */
2567 /*-----------------------------------------------------------------*/
2568 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2570 // ugly but optimized by peephole
2572 symbol *nlbl = newiTempLabel(NULL);
2573 emitcode("jp", LABEL_STR, nlbl->key+100);
2574 emitLabel(tlbl->key+100);
2575 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2576 emitLabel(nlbl->key+100);
2579 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2580 emitLabel(tlbl->key+100);
2585 /*-----------------------------------------------------------------*/
2586 /* genAnd - code for and */
2587 /*-----------------------------------------------------------------*/
2588 static void genAnd (iCode *ic, iCode *ifx)
2590 operand *left, *right, *result;
2592 unsigned long lit = 0L;
2595 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2596 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2597 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2600 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2602 AOP_TYPE(left), AOP_TYPE(right));
2603 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2605 AOP_SIZE(left), AOP_SIZE(right));
2608 /* if left is a literal & right is not then exchange them */
2609 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2610 AOP_NEEDSACC(left)) {
2611 operand *tmp = right ;
2616 /* if result = right then exchange them */
2617 if(sameRegs(AOP(result),AOP(right))){
2618 operand *tmp = right ;
2623 /* if right is bit then exchange them */
2624 if (AOP_TYPE(right) == AOP_CRY &&
2625 AOP_TYPE(left) != AOP_CRY){
2626 operand *tmp = right ;
2630 if(AOP_TYPE(right) == AOP_LIT)
2631 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2633 size = AOP_SIZE(result);
2635 if (AOP_TYPE(left) == AOP_CRY){
2640 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2641 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2642 if((AOP_TYPE(right) == AOP_LIT) &&
2643 (AOP_TYPE(result) == AOP_CRY) &&
2644 (AOP_TYPE(left) != AOP_CRY)) {
2645 int posbit = isLiteralBit(lit);
2649 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2653 emitcode("mov","c,acc.%d",posbit&0x07);
2658 sprintf(buffer, "%d", posbit&0x07);
2659 genIfxJump(ifx, buffer);
2667 symbol *tlbl = newiTempLabel(NULL);
2668 int sizel = AOP_SIZE(left);
2671 emitcode("setb","c");
2674 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2675 MOVA( aopGet(AOP(left),offset,FALSE));
2677 if((posbit = isLiteralBit(bytelit)) != 0) {
2679 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2682 if(bytelit != 0x0FFL)
2683 emitcode("and","a,%s",
2684 aopGet(AOP(right),offset,FALSE));
2685 emitcode("jr","nz, %05d$",tlbl->key+100);
2690 // bit = left & literal
2692 emitcode("clr","c");
2693 emitcode("","%05d$:",tlbl->key+100);
2695 // if(left & literal)
2698 jmpTrueOrFalse(ifx, tlbl);
2706 /* if left is same as result */
2707 if(sameRegs(AOP(result),AOP(left))){
2708 for(;size--; offset++) {
2709 if(AOP_TYPE(right) == AOP_LIT){
2710 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2714 aopPut(AOP(result),zero,offset);
2716 MOVA(aopGet(AOP(left),offset,FALSE));
2717 emitcode("and","a,%s",
2718 aopGet(AOP(right),offset,FALSE));
2719 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2724 if (AOP_TYPE(left) == AOP_ACC) {
2728 MOVA(aopGet(AOP(right),offset,FALSE));
2729 emitcode("and","%s,a",
2730 aopGet(AOP(left),offset,FALSE));
2735 // left & result in different registers
2736 if(AOP_TYPE(result) == AOP_CRY){
2739 for(;(size--);offset++) {
2741 // result = left & right
2742 if(AOP_TYPE(right) == AOP_LIT){
2743 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2745 aopGet(AOP(left),offset,FALSE),
2748 } else if(bytelit == 0){
2749 aopPut(AOP(result),zero,offset);
2753 // faster than result <- left, anl result,right
2754 // and better if result is SFR
2755 if (AOP_TYPE(left) == AOP_ACC)
2756 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2758 MOVA(aopGet(AOP(right),offset,FALSE));
2759 emitcode("and","a,%s",
2760 aopGet(AOP(left),offset,FALSE));
2762 aopPut(AOP(result),"a",offset);
2769 freeAsmop(left,NULL,ic);
2770 freeAsmop(right,NULL,ic);
2771 freeAsmop(result,NULL,ic);
2774 /*-----------------------------------------------------------------*/
2775 /* genOr - code for or */
2776 /*-----------------------------------------------------------------*/
2777 static void genOr (iCode *ic, iCode *ifx)
2779 operand *left, *right, *result;
2781 unsigned long lit = 0L;
2783 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2784 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2785 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2788 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2790 AOP_TYPE(left), AOP_TYPE(right));
2791 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2793 AOP_SIZE(left), AOP_SIZE(right));
2796 /* if left is a literal & right is not then exchange them */
2797 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2798 AOP_NEEDSACC(left)) {
2799 operand *tmp = right ;
2804 /* if result = right then exchange them */
2805 if(sameRegs(AOP(result),AOP(right))){
2806 operand *tmp = right ;
2811 /* if right is bit then exchange them */
2812 if (AOP_TYPE(right) == AOP_CRY &&
2813 AOP_TYPE(left) != AOP_CRY){
2814 operand *tmp = right ;
2818 if(AOP_TYPE(right) == AOP_LIT)
2819 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2821 size = AOP_SIZE(result);
2823 if (AOP_TYPE(left) == AOP_CRY){
2828 if((AOP_TYPE(right) == AOP_LIT) &&
2829 (AOP_TYPE(result) == AOP_CRY) &&
2830 (AOP_TYPE(left) != AOP_CRY)){
2835 /* if left is same as result */
2836 if(sameRegs(AOP(result),AOP(left))){
2837 for(;size--; offset++) {
2838 if(AOP_TYPE(right) == AOP_LIT){
2839 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2842 MOVA(aopGet(AOP(right),offset,FALSE));
2843 emitcode("or","a,%s; 5",
2844 aopGet(AOP(left),offset,FALSE));
2845 aopPut(AOP(result),"a ; 8", offset);
2848 if (AOP_TYPE(left) == AOP_ACC)
2849 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2851 MOVA(aopGet(AOP(right),offset,FALSE));
2852 emitcode("or","a,%s ; 7",
2853 aopGet(AOP(left),offset,FALSE));
2854 aopPut(AOP(result),"a ; 8", offset);
2859 // left & result in different registers
2860 if(AOP_TYPE(result) == AOP_CRY){
2862 } else for(;(size--);offset++){
2864 // result = left & right
2865 if(AOP_TYPE(right) == AOP_LIT){
2866 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2868 aopGet(AOP(left),offset,FALSE),
2873 // faster than result <- left, anl result,right
2874 // and better if result is SFR
2875 if (AOP_TYPE(left) == AOP_ACC)
2876 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2878 MOVA(aopGet(AOP(right),offset,FALSE));
2879 emitcode("or","a,%s",
2880 aopGet(AOP(left),offset,FALSE));
2882 aopPut(AOP(result),"a",offset);
2883 /* PENDING: something weird is going on here. Add exception. */
2884 if (AOP_TYPE(result) == AOP_ACC)
2890 freeAsmop(left,NULL,ic);
2891 freeAsmop(right,NULL,ic);
2892 freeAsmop(result,NULL,ic);
2895 /*-----------------------------------------------------------------*/
2896 /* genXor - code for xclusive or */
2897 /*-----------------------------------------------------------------*/
2898 static void genXor (iCode *ic, iCode *ifx)
2900 operand *left, *right, *result;
2902 unsigned long lit = 0L;
2904 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2905 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2906 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2908 /* if left is a literal & right is not then exchange them */
2909 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2910 AOP_NEEDSACC(left)) {
2911 operand *tmp = right ;
2916 /* if result = right then exchange them */
2917 if(sameRegs(AOP(result),AOP(right))){
2918 operand *tmp = right ;
2923 /* if right is bit then exchange them */
2924 if (AOP_TYPE(right) == AOP_CRY &&
2925 AOP_TYPE(left) != AOP_CRY){
2926 operand *tmp = right ;
2930 if(AOP_TYPE(right) == AOP_LIT)
2931 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2933 size = AOP_SIZE(result);
2935 if (AOP_TYPE(left) == AOP_CRY){
2940 if((AOP_TYPE(right) == AOP_LIT) &&
2941 (AOP_TYPE(result) == AOP_CRY) &&
2942 (AOP_TYPE(left) != AOP_CRY)){
2947 /* if left is same as result */
2948 if(sameRegs(AOP(result),AOP(left))){
2949 for(;size--; offset++) {
2950 if(AOP_TYPE(right) == AOP_LIT){
2951 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2954 MOVA(aopGet(AOP(right),offset,FALSE));
2955 emitcode("xor","a,%s",
2956 aopGet(AOP(left),offset,FALSE));
2957 aopPut(AOP(result),"a",0);
2960 if (AOP_TYPE(left) == AOP_ACC)
2961 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2963 MOVA(aopGet(AOP(right),offset,FALSE));
2964 emitcode("xor","a,%s",
2965 aopGet(AOP(left),offset,FALSE));
2966 aopPut(AOP(result),"a",0);
2971 // left & result in different registers
2972 if(AOP_TYPE(result) == AOP_CRY){
2974 } else for(;(size--);offset++){
2976 // result = left & right
2977 if(AOP_TYPE(right) == AOP_LIT){
2978 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2980 aopGet(AOP(left),offset,FALSE),
2985 // faster than result <- left, anl result,right
2986 // and better if result is SFR
2987 if (AOP_TYPE(left) == AOP_ACC)
2988 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2990 MOVA(aopGet(AOP(right),offset,FALSE));
2991 emitcode("xor","a,%s",
2992 aopGet(AOP(left),offset,FALSE));
2993 aopPut(AOP(result),"a",0);
2995 aopPut(AOP(result),"a",offset);
3000 freeAsmop(left,NULL,ic);
3001 freeAsmop(right,NULL,ic);
3002 freeAsmop(result,NULL,ic);
3005 /*-----------------------------------------------------------------*/
3006 /* genInline - write the inline code out */
3007 /*-----------------------------------------------------------------*/
3008 static void genInline (iCode *ic)
3010 char buffer[MAX_INLINEASM];
3014 inLine += (!options.asmpeep);
3015 strcpy(buffer,IC_INLINE(ic));
3017 /* emit each line as a code */
3036 /* emitcode("",buffer); */
3037 inLine -= (!options.asmpeep);
3040 /*-----------------------------------------------------------------*/
3041 /* genRRC - rotate right with carry */
3042 /*-----------------------------------------------------------------*/
3043 static void genRRC (iCode *ic)
3048 /*-----------------------------------------------------------------*/
3049 /* genRLC - generate code for rotate left with carry */
3050 /*-----------------------------------------------------------------*/
3051 static void genRLC (iCode *ic)
3056 /*-----------------------------------------------------------------*/
3057 /* shiftR2Left2Result - shift right two bytes from left to result */
3058 /*-----------------------------------------------------------------*/
3059 static void shiftR2Left2Result (operand *left, int offl,
3060 operand *result, int offr,
3061 int shCount, int sign)
3063 if(sameRegs(AOP(result), AOP(left)) &&
3064 ((offl + MSB16) == offr)){
3067 movLeft2Result(left, offl, result, offr, 0);
3068 movLeft2Result(left, offl+1, result, offr+1, 0);
3075 /* if (AOP(result)->type == AOP_REG) {*/
3078 symbol *tlbl , *tlbl1;
3081 /* Left is already in result - so now do the shift */
3083 emitcode("ld","a,#%u+1", shCount);
3084 tlbl = newiTempLabel(NULL);
3085 tlbl1 = newiTempLabel(NULL);
3086 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3087 emitLabel(tlbl->key+100);
3090 emitcode("or", "a,a");
3093 l = aopGet(AOP(result), --offset, FALSE);
3094 emitcode("rr","%s", l);
3097 emitLabel(tlbl1->key+100);
3098 emitcode("dec", "a");
3099 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3104 /*-----------------------------------------------------------------*/
3105 /* shiftL2Left2Result - shift left two bytes from left to result */
3106 /*-----------------------------------------------------------------*/
3107 static void shiftL2Left2Result (operand *left, int offl,
3108 operand *result, int offr, int shCount)
3110 if(sameRegs(AOP(result), AOP(left)) &&
3111 ((offl + MSB16) == offr)){
3114 /* Copy left into result */
3115 movLeft2Result(left, offl, result, offr, 0);
3116 movLeft2Result(left, offl+1, result, offr+1, 0);
3118 /* PENDING: for now just see if it'll work. */
3119 /*if (AOP(result)->type == AOP_REG) { */
3123 symbol *tlbl , *tlbl1;
3126 /* Left is already in result - so now do the shift */
3128 emitcode("ld","a,#%u+1", shCount);
3129 tlbl = newiTempLabel(NULL);
3130 tlbl1 = newiTempLabel(NULL);
3131 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3132 emitLabel(tlbl->key+100);
3135 emitcode("or", "a,a");
3137 l = aopGet(AOP(result),offset++,FALSE);
3138 emitcode("rl","%s", l);
3141 emitLabel(tlbl1->key+100);
3142 emitcode("dec", "a");
3143 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3148 /*-----------------------------------------------------------------*/
3149 /* AccRol - rotate left accumulator by known count */
3150 /*-----------------------------------------------------------------*/
3151 static void AccRol (int shCount)
3153 shCount &= 0x0007; // shCount : 0..7
3190 /*-----------------------------------------------------------------*/
3191 /* AccLsh - left shift accumulator by known count */
3192 /*-----------------------------------------------------------------*/
3193 static void AccLsh (int shCount)
3197 emitcode("add","a,a");
3200 emitcode("add","a,a");
3201 emitcode("add","a,a");
3203 /* rotate left accumulator */
3205 /* and kill the lower order bits */
3206 emitcode("and","a,#0x%02x", SLMask[shCount]);
3211 /*-----------------------------------------------------------------*/
3212 /* shiftL1Left2Result - shift left one byte from left to result */
3213 /*-----------------------------------------------------------------*/
3214 static void shiftL1Left2Result (operand *left, int offl,
3215 operand *result, int offr, int shCount)
3218 l = aopGet(AOP(left),offl,FALSE);
3220 /* shift left accumulator */
3222 aopPut(AOP(result),"a",offr);
3226 /*-----------------------------------------------------------------*/
3227 /* genlshTwo - left shift two bytes by known amount != 0 */
3228 /*-----------------------------------------------------------------*/
3229 static void genlshTwo (operand *result,operand *left, int shCount)
3231 int size = AOP_SIZE(result);
3235 /* if shCount >= 8 */
3241 movLeft2Result(left, LSB, result, MSB16, 0);
3242 aopPut(AOP(result),zero, 0);
3243 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3246 movLeft2Result(left, LSB, result, MSB16, 0);
3247 aopPut(AOP(result),zero, 0);
3250 aopPut(AOP(result),zero,LSB);
3252 /* 1 <= shCount <= 7 */
3258 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3263 /*-----------------------------------------------------------------*/
3264 /* genlshOne - left shift a one byte quantity by known count */
3265 /*-----------------------------------------------------------------*/
3266 static void genlshOne (operand *result, operand *left, int shCount)
3268 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3271 /*-----------------------------------------------------------------*/
3272 /* genLeftShiftLiteral - left shifting by known count */
3273 /*-----------------------------------------------------------------*/
3274 static void genLeftShiftLiteral (operand *left,
3279 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3282 freeAsmop(right,NULL,ic);
3284 aopOp(left,ic,FALSE);
3285 aopOp(result,ic,FALSE);
3287 size = getSize(operandType(result));
3290 emitcode("; shift left ","result %d, left %d",size,
3294 /* I suppose that the left size >= result size */
3299 else if(shCount >= (size * 8))
3301 aopPut(AOP(result),zero,size);
3305 genlshOne (result,left,shCount);
3308 genlshTwo (result,left,shCount);
3317 freeAsmop(left,NULL,ic);
3318 freeAsmop(result,NULL,ic);
3321 /*-----------------------------------------------------------------*/
3322 /* genLeftShift - generates code for left shifting */
3323 /*-----------------------------------------------------------------*/
3324 static void genLeftShift (iCode *ic)
3328 symbol *tlbl , *tlbl1;
3329 operand *left,*right, *result;
3331 right = IC_RIGHT(ic);
3333 result = IC_RESULT(ic);
3335 aopOp(right,ic,FALSE);
3337 /* if the shift count is known then do it
3338 as efficiently as possible */
3339 if (AOP_TYPE(right) == AOP_LIT) {
3340 genLeftShiftLiteral (left,right,result,ic);
3344 /* shift count is unknown then we have to form a loop get the loop
3345 count in B : Note: we take only the lower order byte since
3346 shifting more that 32 bits make no sense anyway, ( the largest
3347 size of an object can be only 32 bits ) */
3348 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3349 emitcode("inc","a");
3350 freeAsmop (right,NULL,ic);
3351 aopOp(left,ic,FALSE);
3352 aopOp(result,ic,FALSE);
3354 /* now move the left to the result if they are not the
3357 if (!sameRegs(AOP(left),AOP(result))) {
3359 size = AOP_SIZE(result);
3362 l = aopGet(AOP(left),offset,FALSE);
3363 aopPut(AOP(result),l,offset);
3368 size = AOP_SIZE(result);
3371 l = aopGet(AOP(left),offset,FALSE);
3372 aopPut(AOP(result),l,offset);
3378 tlbl = newiTempLabel(NULL);
3379 size = AOP_SIZE(result);
3381 tlbl1 = newiTempLabel(NULL);
3383 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3384 emitLabel(tlbl->key+100);
3385 l = aopGet(AOP(result),offset,FALSE);
3386 emitcode("or", "a,a");
3388 l = aopGet(AOP(result),offset++,FALSE);
3389 emitcode("rl","%s", l);
3391 emitLabel(tlbl1->key+100);
3392 emitcode("dec", "a");
3393 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3395 freeAsmop(left,NULL,ic);
3396 freeAsmop(result,NULL,ic);
3399 /* genlshTwo - left shift two bytes by known amount != 0 */
3400 /*-----------------------------------------------------------------*/
3401 static void genrshOne (operand *result,operand *left, int shCount)
3404 int size = AOP_SIZE(result);
3410 l = aopGet(AOP(left),0,FALSE);
3411 if (AOP(result)->type == AOP_REG) {
3412 aopPut(AOP(result), l, 0);
3413 l = aopGet(AOP(result), 0, FALSE);
3415 emitcode("srl", "%s", l);
3420 emitcode("srl", "a");
3422 aopPut(AOP(result),"a",0);
3426 /*-----------------------------------------------------------------*/
3427 /* AccRsh - right shift accumulator by known count */
3428 /*-----------------------------------------------------------------*/
3429 static void AccRsh (int shCount)
3436 /* rotate right accumulator */
3437 AccRol(8 - shCount);
3438 /* and kill the higher order bits */
3439 emitcode("and","a,#0x%02x", SRMask[shCount]);
3444 /*-----------------------------------------------------------------*/
3445 /* shiftR1Left2Result - shift right one byte from left to result */
3446 /*-----------------------------------------------------------------*/
3447 static void shiftR1Left2Result (operand *left, int offl,
3448 operand *result, int offr,
3449 int shCount, int sign)
3451 MOVA(aopGet(AOP(left),offl,FALSE));
3458 aopPut(AOP(result),"a",offr);
3461 /*-----------------------------------------------------------------*/
3462 /* genrshTwo - right shift two bytes by known amount != 0 */
3463 /*-----------------------------------------------------------------*/
3464 static void genrshTwo (operand *result,operand *left,
3465 int shCount, int sign)
3467 /* if shCount >= 8 */
3472 shiftR1Left2Result(left, MSB16, result, LSB,
3476 movLeft2Result(left, MSB16, result, LSB, sign);
3477 aopPut(AOP(result),zero,1);
3480 /* 1 <= shCount <= 7 */
3482 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3486 /*-----------------------------------------------------------------*/
3487 /* genRightShiftLiteral - left shifting by known count */
3488 /*-----------------------------------------------------------------*/
3489 static void genRightShiftLiteral (operand *left,
3494 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3497 freeAsmop(right,NULL,ic);
3499 aopOp(left,ic,FALSE);
3500 aopOp(result,ic,FALSE);
3502 size = getSize(operandType(result));
3504 emitcode("; shift right ","result %d, left %d",size,
3507 /* I suppose that the left size >= result size */
3512 else if(shCount >= (size * 8))
3514 aopPut(AOP(result),zero,size);
3518 genrshOne(result, left, shCount);
3521 /* PENDING: sign support */
3522 genrshTwo(result, left, shCount, FALSE);
3531 freeAsmop(left,NULL,ic);
3532 freeAsmop(result,NULL,ic);
3535 /*-----------------------------------------------------------------*/
3536 /* genRightShift - generate code for right shifting */
3537 /*-----------------------------------------------------------------*/
3538 static void genRightShift (iCode *ic)
3540 operand *left,*right, *result;
3542 right = IC_RIGHT(ic);
3544 result = IC_RESULT(ic);
3546 aopOp(right,ic,FALSE);
3548 /* if the shift count is known then do it
3549 as efficiently as possible */
3550 if (AOP_TYPE(right) == AOP_LIT) {
3551 genRightShiftLiteral (left,right,result,ic);
3559 /*-----------------------------------------------------------------*/
3560 /* genGenPointerGet - gget value from generic pointer space */
3561 /*-----------------------------------------------------------------*/
3562 static void genGenPointerGet (operand *left,
3563 operand *result, iCode *ic)
3566 link *retype = getSpec(operandType(result));
3572 aopOp(left,ic,FALSE);
3573 aopOp(result,ic,FALSE);
3575 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3577 if (isPtrPair(AOP(left)))
3579 sprintf(buffer, "(%s)", getPairName(AOP(left)));
3580 aopPut(AOP(result), buffer, 0);
3583 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3584 aopPut(AOP(result),"a", 0);
3586 freeAsmop(left,NULL,ic);
3590 /* For now we always load into IY */
3591 /* if this is remateriazable */
3592 fetchPair(pair, AOP(left));
3594 /* so iy now contains the address */
3595 freeAsmop(left,NULL,ic);
3597 /* if bit then unpack */
3598 if (IS_BITVAR(retype)) {
3602 size = AOP_SIZE(result);
3606 /* PENDING: make this better */
3607 if (!IS_GB && AOP(result)->type == AOP_REG) {
3608 aopPut(AOP(result),"(hl)",offset++);
3611 emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
3612 aopPut(AOP(result),"a",offset++);
3615 emitcode("inc", "%s", _pairs[pair].name);
3621 freeAsmop(result,NULL,ic);
3624 /*-----------------------------------------------------------------*/
3625 /* genPointerGet - generate code for pointer get */
3626 /*-----------------------------------------------------------------*/
3627 static void genPointerGet (iCode *ic)
3629 operand *left, *result ;
3633 result = IC_RESULT(ic) ;
3635 /* depending on the type of pointer we need to
3636 move it to the correct pointer register */
3637 type = operandType(left);
3638 etype = getSpec(type);
3640 genGenPointerGet (left,result,ic);
3643 bool isRegOrLit(asmop *aop)
3645 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3650 /*-----------------------------------------------------------------*/
3651 /* genGenPointerSet - stores the value into a pointer location */
3652 /*-----------------------------------------------------------------*/
3653 static void genGenPointerSet (operand *right,
3654 operand *result, iCode *ic)
3657 link *retype = getSpec(operandType(right));
3658 PAIR_ID pairId = PAIR_HL;
3660 aopOp(result,ic,FALSE);
3661 aopOp(right,ic,FALSE);
3666 /* Handle the exceptions first */
3667 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3669 char *l = aopGet(AOP(right), 0, FALSE);
3670 const char *pair = getPairName(AOP(result));
3671 if (canAssignToPtr(l) && isPtr(pair)) {
3672 emitcode("ld", "(%s),%s", pair, l);
3676 emitcode("ld", "(%s),a ; 1", pair);
3681 /* if the operand is already in dptr
3682 then we do nothing else we move the value to dptr */
3683 if (AOP_TYPE(result) != AOP_STR) {
3684 fetchPair(pairId, AOP(result));
3686 /* so hl know contains the address */
3687 freeAsmop(result,NULL,ic);
3689 /* if bit then unpack */
3690 if (IS_BITVAR(retype)) {
3694 size = AOP_SIZE(right);
3698 char *l = aopGet(AOP(right),offset,FALSE);
3699 if (isRegOrLit(AOP(right)) && !IS_GB) {
3700 emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
3704 emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
3707 emitcode("inc", _pairs[pairId].name);
3713 freeAsmop(right,NULL,ic);
3716 /*-----------------------------------------------------------------*/
3717 /* genPointerSet - stores the value into a pointer location */
3718 /*-----------------------------------------------------------------*/
3719 static void genPointerSet (iCode *ic)
3721 operand *right, *result ;
3724 right = IC_RIGHT(ic);
3725 result = IC_RESULT(ic) ;
3727 /* depending on the type of pointer we need to
3728 move it to the correct pointer register */
3729 type = operandType(result);
3730 etype = getSpec(type);
3732 genGenPointerSet (right,result,ic);
3735 /*-----------------------------------------------------------------*/
3736 /* genIfx - generate code for Ifx statement */
3737 /*-----------------------------------------------------------------*/
3738 static void genIfx (iCode *ic, iCode *popIc)
3740 operand *cond = IC_COND(ic);
3743 aopOp(cond,ic,FALSE);
3745 /* get the value into acc */
3746 if (AOP_TYPE(cond) != AOP_CRY)
3750 /* the result is now in the accumulator */
3751 freeAsmop(cond,NULL,ic);
3753 /* if there was something to be popped then do it */
3757 /* if the condition is a bit variable */
3758 if (isbit && IS_ITEMP(cond) &&
3760 genIfxJump(ic,SPIL_LOC(cond)->rname);
3762 if (isbit && !IS_ITEMP(cond))
3763 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3770 /*-----------------------------------------------------------------*/
3771 /* genAddrOf - generates code for address of */
3772 /*-----------------------------------------------------------------*/
3773 static void genAddrOf (iCode *ic)
3775 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3777 aopOp(IC_RESULT(ic),ic,FALSE);
3779 /* if the operand is on the stack then we
3780 need to get the stack offset of this
3785 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _G.stack.pushed, _G.stack.offset);
3786 emitcode("ld", "d,h");
3787 emitcode("ld", "e,l");
3790 emitcode("ld", "de,#%s", sym->rname);
3792 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3793 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3798 /* if it has an offset then we need to compute it */
3799 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3800 emitcode("add", "hl,sp");
3803 emitcode("ld", "hl,#%s", sym->rname);
3805 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3806 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3808 freeAsmop(IC_RESULT(ic),NULL,ic);
3811 /*-----------------------------------------------------------------*/
3812 /* genAssign - generate code for assignment */
3813 /*-----------------------------------------------------------------*/
3814 static void genAssign (iCode *ic)
3816 operand *result, *right;
3818 unsigned long lit = 0L;
3820 result = IC_RESULT(ic);
3821 right = IC_RIGHT(ic) ;
3824 /* Dont bother assigning if they are the same */
3825 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3826 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3831 aopOp(right,ic,FALSE);
3832 aopOp(result,ic,TRUE);
3834 /* if they are the same registers */
3835 if (sameRegs(AOP(right),AOP(result))) {
3836 emitcode("", "; (registers are the same)");
3840 /* if the result is a bit */
3841 if (AOP_TYPE(result) == AOP_CRY) {
3846 size = AOP_SIZE(result);
3849 if(AOP_TYPE(right) == AOP_LIT)
3850 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3851 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3852 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3854 else if((size > 1) &&
3855 (AOP_TYPE(result) != AOP_REG) &&
3856 (AOP_TYPE(right) == AOP_LIT) &&
3857 !IS_FLOAT(operandType(right)) &&
3859 bool fXored = FALSE;
3861 /* Work from the top down.
3862 Done this way so that we can use the cached copy of 0
3863 in A for a fast clear */
3865 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3866 if (!fXored && size>1) {
3867 emitcode("xor", "a,a");
3871 aopPut(AOP(result),"a",offset);
3874 aopPut(AOP(result), "#0", offset);
3879 aopGet(AOP(right),offset,FALSE),
3884 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3885 /* Special case. Load into a and d, then load out. */
3886 MOVA(aopGet(AOP(right), 0, FALSE));
3887 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3888 aopPut(AOP(result), "a", 0);
3889 aopPut(AOP(result), "e", 1);
3893 aopGet(AOP(right),offset,FALSE),
3900 freeAsmop(right,NULL,ic);
3901 freeAsmop(result,NULL,ic);
3904 /*-----------------------------------------------------------------*/
3905 /* genJumpTab - genrates code for jump table */
3906 /*-----------------------------------------------------------------*/
3907 static void genJumpTab (iCode *ic)
3912 aopOp(IC_JTCOND(ic),ic,FALSE);
3913 /* get the condition into accumulator */
3914 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3917 emitcode("push", "de");
3918 emitcode("ld", "e,%s", l);
3919 emitcode("ld", "d,#0");
3920 jtab = newiTempLabel(NULL);
3922 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3923 emitcode("add", "hl,de");
3924 emitcode("add", "hl,de");
3925 emitcode("add", "hl,de");
3926 freeAsmop(IC_JTCOND(ic),NULL,ic);
3928 emitcode("pop", "de");
3929 emitcode("jp", "(hl)");
3930 emitLabel(jtab->key+100);
3931 /* now generate the jump labels */
3932 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3933 jtab = setNextItem(IC_JTLABELS(ic)))
3934 emitcode("jp", LABEL_STR, jtab->key+100);
3937 /*-----------------------------------------------------------------*/
3938 /* genCast - gen code for casting */
3939 /*-----------------------------------------------------------------*/
3940 static void genCast (iCode *ic)
3942 operand *result = IC_RESULT(ic);
3943 link *ctype = operandType(IC_LEFT(ic));
3944 operand *right = IC_RIGHT(ic);
3947 /* if they are equivalent then do nothing */
3948 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3951 aopOp(right,ic,FALSE) ;
3952 aopOp(result,ic,FALSE);
3954 /* if the result is a bit */
3955 if (AOP_TYPE(result) == AOP_CRY) {
3959 /* if they are the same size : or less */
3960 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3962 /* if they are in the same place */
3963 if (sameRegs(AOP(right),AOP(result)))
3966 /* if they in different places then copy */
3967 size = AOP_SIZE(result);
3971 aopGet(AOP(right),offset,FALSE),
3978 /* PENDING: should be OK. */
3980 /* if the result is of type pointer */
3981 if (IS_PTR(ctype)) {
3986 /* so we now know that the size of destination is greater
3987 than the size of the source */
3988 /* we move to result for the size of source */
3989 size = AOP_SIZE(right);
3993 aopGet(AOP(right),offset,FALSE),
3998 /* now depending on the sign of the destination */
3999 size = AOP_SIZE(result) - AOP_SIZE(right);
4000 /* Unsigned or not an integral type - right fill with zeros */
4001 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4003 aopPut(AOP(result),zero,offset++);
4005 /* we need to extend the sign :{ */
4006 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4009 emitcode("", "; genCast: sign extend untested.");
4010 emitcode("rla", "");
4011 emitcode("sbc", "a,a");
4013 aopPut(AOP(result),"a",offset++);
4017 freeAsmop(right, NULL, ic);
4018 freeAsmop(result, NULL, ic);
4021 /*-----------------------------------------------------------------*/
4022 /* genReceive - generate code for a receive iCode */
4023 /*-----------------------------------------------------------------*/
4024 static void genReceive (iCode *ic)
4026 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4027 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4028 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4032 aopOp(IC_RESULT(ic),ic,FALSE);
4034 assignResultValue(IC_RESULT(ic));
4037 freeAsmop(IC_RESULT(ic),NULL,ic);
4040 /*-----------------------------------------------------------------*/
4041 /* genZ80Code - generate code for Z80 based controllers */
4042 /*-----------------------------------------------------------------*/
4043 void genZ80Code (iCode *lic)
4050 _fReturn = _gbz80_return;
4051 _fTmp = _gbz80_return;
4055 _fReturn = _z80_return;
4056 _fTmp = _z80_return;
4060 lineHead = lineCurr = NULL;
4062 /* if debug information required */
4063 if (options.debug && currFunc) {
4064 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4066 if (IS_STATIC(currFunc->etype))
4067 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4069 emitcode("","G$%s$0$0 ==.",currFunc->name);
4072 /* stack pointer name */
4076 for (ic = lic ; ic ; ic = ic->next ) {
4078 if ( cln != ic->lineno ) {
4079 if ( options.debug ) {
4081 emitcode("","C$%s$%d$%d$%d ==.",
4082 ic->filename,ic->lineno,
4083 ic->level,ic->block);
4086 emitcode(";","%s %d",ic->filename,ic->lineno);
4089 /* if the result is marked as
4090 spilt and rematerializable or code for
4091 this has already been generated then
4093 if (resultRemat(ic) || ic->generated )
4096 /* depending on the operation */
4099 emitcode("", "; genNot");
4104 emitcode("", "; genCpl");
4109 emitcode("", "; genUminus");
4114 emitcode("", "; genIpush");
4119 /* IPOP happens only when trying to restore a
4120 spilt live range, if there is an ifx statement
4121 following this pop then the if statement might
4122 be using some of the registers being popped which
4123 would destory the contents of the register so
4124 we need to check for this condition and handle it */
4126 ic->next->op == IFX &&
4127 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4128 emitcode("", "; genIfx");
4129 genIfx (ic->next,ic);
4132 emitcode("", "; genIpop");
4138 emitcode("", "; genCall");
4143 emitcode("", "; genPcall");
4148 emitcode("", "; genFunction");
4153 emitcode("", "; genEndFunction");
4154 genEndFunction (ic);
4158 emitcode("", "; genRet");
4163 emitcode("", "; genLabel");
4168 emitcode("", "; genGoto");
4173 emitcode("", "; genPlus");
4178 emitcode("", "; genMinus");
4183 emitcode("", "; genMult");
4188 emitcode("", "; genDiv");
4193 emitcode("", "; genMod");
4198 emitcode("", "; genCmpGt");
4199 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4203 emitcode("", "; genCmpLt");
4204 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4211 /* note these two are xlated by algebraic equivalence
4212 during parsing SDCC.y */
4213 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4214 "got '>=' or '<=' shouldn't have come here");
4218 emitcode("", "; genCmpEq");
4219 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4223 emitcode("", "; genAndOp");
4228 emitcode("", "; genOrOp");
4233 emitcode("", "; genXor");
4234 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4238 emitcode("", "; genOr");
4239 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4243 emitcode("", "; genAnd");
4244 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4248 emitcode("", "; genInline");
4253 emitcode("", "; genRRC");
4258 emitcode("", "; genRLC");
4263 emitcode("", "; genHBIT");
4267 emitcode("", "; genLeftShift");
4272 emitcode("", "; genRightShift");
4276 case GET_VALUE_AT_ADDRESS:
4277 emitcode("", "; genPointerGet");
4283 if (POINTER_SET(ic)) {
4284 emitcode("", "; genAssign (pointer)");
4288 emitcode("", "; genAssign");
4294 emitcode("", "; genIfx");
4299 emitcode("", "; genAddrOf");
4304 emitcode("", "; genJumpTab");
4309 emitcode("", "; genCast");
4314 emitcode("", "; genReceive");
4319 emitcode("", "; addSet");
4320 addSet(&sendSet,ic);
4325 /* piCode(ic,stdout); */
4331 /* now we are ready to call the
4332 peep hole optimizer */
4333 if (!options.nopeep)
4334 peepHole (&lineHead);
4336 /* now do the actual printing */
4337 printLine (lineHead,codeOutFile);