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 fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
746 /* if this is remateriazable */
747 if (isLitWord(aop)) {
748 fetchLitPair(pairId, aop, offset);
750 else { /* we need to get it byte by byte */
751 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
752 aopGet(aop, offset, 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, offset, FALSE));
759 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
761 /* PENDING: check? */
762 if (pairId == PAIR_HL)
767 static void fetchPair(PAIR_ID pairId, asmop *aop)
769 fetchPairLong(pairId, aop, 0);
772 static void fetchHL(asmop *aop)
774 fetchPair(PAIR_HL, aop);
777 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
779 assert(pairId == PAIR_HL || pairId == PAIR_IY);
784 fetchLitPair(pairId, aop, offset);
785 _G.pairs[pairId].offset = offset;
788 /* Doesnt include _G.stack.pushed */
789 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
790 assert(pairId == PAIR_HL);
791 /* In some cases we can still inc or dec hl */
792 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
793 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
796 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _G.stack.pushed, _G.stack.offset);
798 _G.pairs[pairId].offset = abso;
804 _G.pairs[pairId].last_type = aop->type;
807 static void emitLabel(int key)
809 emitcode("", LABEL_STR ":", key);
813 /*-----------------------------------------------------------------*/
814 /* aopGet - for fetching value of the aop */
815 /*-----------------------------------------------------------------*/
816 static char *aopGet(asmop *aop, int offset, bool bit16)
821 /* offset is greater than size then zero */
822 /* PENDING: this seems a bit screwed in some pointer cases. */
823 if (offset > (aop->size - 1) &&
824 aop->type != AOP_LIT)
827 /* depending on type */
831 sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
834 wassert(offset == 1);
841 ALLOC_ATOMIC(rs,strlen(s)+1);
847 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
849 ALLOC_ATOMIC(rs,strlen(s)+1);
854 return aop->aopu.aop_reg[offset]->name;
859 setupPair(PAIR_HL, aop, offset);
861 return _strdup("(hl)");
865 setupPair(PAIR_IY, aop, offset);
866 sprintf(s,"%d(iy)", offset);
867 ALLOC_ATOMIC(rs,strlen(s)+1);
873 setupPair(PAIR_HL, aop, offset);
877 sprintf(s,"%d(ix)", aop->aopu.aop_stk+offset);
879 ALLOC_ATOMIC(rs,strlen(s)+1);
893 return aopLiteral (aop->aopu.aop_lit,offset);
897 return aop->aopu.aop_str[offset];
901 wassertl(0, "aopget got unsupported aop->type");
905 bool isRegString(char *s)
907 if (!strcmp(s, "b") ||
918 bool isConstant(const char *s)
923 bool canAssignToPtr(char *s)
932 /*-----------------------------------------------------------------*/
933 /* aopPut - puts a string for a aop */
934 /*-----------------------------------------------------------------*/
935 static void aopPut (asmop *aop, char *s, int offset)
937 if (aop->size && offset > ( aop->size - 1)) {
938 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
939 "aopPut got offset > aop->size");
943 /* will assign value to value */
944 /* depending on where it is ofcourse */
949 emitcode("ld", "a,%s", s);
950 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
954 /* Dont bother if it's a ld x,x */
955 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
956 emitcode("ld","%s,%s",
957 aop->aopu.aop_reg[offset]->name,s);
963 setupPair(PAIR_IY, aop, offset);
964 if (!canAssignToPtr(s)) {
965 emitcode("ld", "a,%s", s);
966 emitcode("ld", "%d(iy),a", offset);
969 emitcode("ld", "%d(iy),%s", offset, s);
974 if (!strcmp(s, "(hl)")) {
975 emitcode("ld", "a,(hl)");
979 setupPair(PAIR_HL, aop, offset);
980 emitcode("ld", "(hl),%s", s);
985 if (!strcmp("(hl)", s)) {
986 emitcode("ld", "a,(hl)");
989 setupPair(PAIR_HL, aop, offset);
990 if (!canAssignToPtr(s)) {
991 emitcode("ld", "a,%s", s);
992 emitcode("ld", "(hl),a");
995 emitcode("ld", "(hl),%s", s);
998 if (!canAssignToPtr(s)) {
999 emitcode("ld", "a,%s", s);
1000 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
1003 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
1008 /* if bit variable */
1009 if (!aop->aopu.aop_dir) {
1010 emitcode("ld", "a,#0");
1011 emitcode("rla", "");
1013 /* In bit space but not in C - cant happen */
1020 if (strcmp(aop->aopu.aop_str[offset],s)) {
1021 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1027 if (!offset && (strcmp(s,"acc") == 0))
1031 emitcode("", "; Error aopPut AOP_ACC");
1034 if (strcmp(aop->aopu.aop_str[offset],s))
1035 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1040 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1041 "aopPut got unsupported aop->type");
1046 #define AOP(op) op->aop
1047 #define AOP_TYPE(op) AOP(op)->type
1048 #define AOP_SIZE(op) AOP(op)->size
1049 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1051 /*-----------------------------------------------------------------*/
1052 /* getDataSize - get the operand data size */
1053 /*-----------------------------------------------------------------*/
1054 int getDataSize(operand *op)
1057 size = AOP_SIZE(op);
1065 /*-----------------------------------------------------------------*/
1066 /* movLeft2Result - move byte from left to result */
1067 /*-----------------------------------------------------------------*/
1068 static void movLeft2Result (operand *left, int offl,
1069 operand *result, int offr, int sign)
1072 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1073 l = aopGet(AOP(left),offl,FALSE);
1076 aopPut(AOP(result),l,offr);
1085 /** Put Acc into a register set
1087 void outAcc(operand *result)
1090 size = getDataSize(result);
1092 aopPut(AOP(result),"a",0);
1095 /* unsigned or positive */
1097 aopPut(AOP(result),zero,offset++);
1102 /** Take the value in carry and put it into a register
1104 void outBitC(operand *result)
1106 /* if the result is bit */
1107 if (AOP_TYPE(result) == AOP_CRY) {
1108 emitcode("", "; Note: outBitC form 1");
1109 aopPut(AOP(result),"blah",0);
1112 emitcode("ld", "a,#0");
1113 emitcode("rla", "");
1118 /*-----------------------------------------------------------------*/
1119 /* toBoolean - emit code for orl a,operator(sizeop) */
1120 /*-----------------------------------------------------------------*/
1121 void toBoolean(operand *oper)
1123 int size = AOP_SIZE(oper);
1126 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1129 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1132 if (AOP(oper)->type != AOP_ACC) {
1134 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1139 /*-----------------------------------------------------------------*/
1140 /* genNot - generate code for ! operation */
1141 /*-----------------------------------------------------------------*/
1142 static void genNot (iCode *ic)
1144 link *optype = operandType(IC_LEFT(ic));
1146 /* assign asmOps to operand & result */
1147 aopOp (IC_LEFT(ic),ic,FALSE);
1148 aopOp (IC_RESULT(ic),ic,TRUE);
1150 /* if in bit space then a special case */
1151 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1155 /* if type float then do float */
1156 if (IS_FLOAT(optype)) {
1160 toBoolean(IC_LEFT(ic));
1165 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1166 emitcode("sub", "a,#0x01");
1167 outBitC(IC_RESULT(ic));
1169 /* release the aops */
1170 freeAsmop(IC_LEFT(ic),NULL,ic);
1171 freeAsmop(IC_RESULT(ic),NULL,ic);
1174 /*-----------------------------------------------------------------*/
1175 /* genCpl - generate code for complement */
1176 /*-----------------------------------------------------------------*/
1177 static void genCpl (iCode *ic)
1183 /* assign asmOps to operand & result */
1184 aopOp (IC_LEFT(ic),ic,FALSE);
1185 aopOp (IC_RESULT(ic),ic,TRUE);
1187 /* if both are in bit space then
1189 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1190 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1194 size = AOP_SIZE(IC_RESULT(ic));
1196 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1199 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1202 /* release the aops */
1203 freeAsmop(IC_LEFT(ic),NULL,ic);
1204 freeAsmop(IC_RESULT(ic),NULL,ic);
1207 /*-----------------------------------------------------------------*/
1208 /* genUminus - unary minus code generation */
1209 /*-----------------------------------------------------------------*/
1210 static void genUminus (iCode *ic)
1213 link *optype, *rtype;
1216 aopOp(IC_LEFT(ic),ic,FALSE);
1217 aopOp(IC_RESULT(ic),ic,TRUE);
1219 /* if both in bit space then special
1221 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1222 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1227 optype = operandType(IC_LEFT(ic));
1228 rtype = operandType(IC_RESULT(ic));
1230 /* if float then do float stuff */
1231 if (IS_FLOAT(optype)) {
1236 /* otherwise subtract from zero */
1237 size = AOP_SIZE(IC_LEFT(ic));
1241 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1242 emitcode("ld", "a,#0");
1243 emitcode("sbc","a,%s",l);
1244 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1247 /* if any remaining bytes in the result */
1248 /* we just need to propagate the sign */
1249 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1250 emitcode("rlc","a");
1251 emitcode("sbc","a,a");
1253 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1257 /* release the aops */
1258 freeAsmop(IC_LEFT(ic),NULL,ic);
1259 freeAsmop(IC_RESULT(ic),NULL,ic);
1262 /*-----------------------------------------------------------------*/
1263 /* assignResultValue - */
1264 /*-----------------------------------------------------------------*/
1265 void assignResultValue(operand * oper)
1267 int size = AOP_SIZE(oper);
1271 topInA = requiresHL(AOP(oper));
1275 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1276 /* We do it the hard way here. */
1277 emitcode("push", "hl");
1278 _G.stack.pushed += 2;
1279 aopPut(AOP(oper), _fReturn[0], 0);
1280 aopPut(AOP(oper), _fReturn[1], 1);
1281 emitcode("pop", "de");
1282 _G.stack.pushed -= 2;
1283 aopPut(AOP(oper), _fReturn[0], 2);
1284 aopPut(AOP(oper), _fReturn[1], 3);
1288 aopPut(AOP(oper), _fReturn[size], size);
1293 /*-----------------------------------------------------------------*/
1294 /* genIpush - genrate code for pushing this gets a little complex */
1295 /*-----------------------------------------------------------------*/
1296 static void genIpush (iCode *ic)
1298 int size, offset = 0 ;
1302 /* if this is not a parm push : ie. it is spill push
1303 and spill push is always done on the local stack */
1304 if (!ic->parmPush) {
1305 /* and the item is spilt then do nothing */
1306 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1309 aopOp(IC_LEFT(ic),ic,FALSE);
1310 size = AOP_SIZE(IC_LEFT(ic));
1311 /* push it on the stack */
1312 if (isPair(AOP(IC_LEFT(ic)))) {
1313 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1314 _G.stack.pushed += 2;
1319 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1320 /* Simple for now - load into A and PUSH AF */
1321 emitcode("ld", "a,%s", l);
1322 emitcode("push", "af");
1323 emitcode("inc", "sp");
1330 /* Hmmm... what about saving the currently used registers
1333 /* then do the push */
1334 aopOp(IC_LEFT(ic),ic,FALSE);
1336 size = AOP_SIZE(IC_LEFT(ic));
1338 if (isPair(AOP(IC_LEFT(ic)))) {
1340 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1344 fetchHL(AOP(IC_LEFT(ic)));
1345 emitcode("push", "hl ; 2");
1347 _G.stack.pushed += 2;
1352 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1353 emitcode("ld", "a,%s", l);
1354 emitcode("push", "af");
1355 emitcode("inc", "sp");
1360 freeAsmop(IC_LEFT(ic),NULL,ic);
1363 /*-----------------------------------------------------------------*/
1364 /* genIpop - recover the registers: can happen only for spilling */
1365 /*-----------------------------------------------------------------*/
1366 static void genIpop (iCode *ic)
1371 /* if the temp was not pushed then */
1372 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1375 aopOp(IC_LEFT(ic),ic,FALSE);
1376 size = AOP_SIZE(IC_LEFT(ic));
1378 if (isPair(AOP(IC_LEFT(ic)))) {
1379 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1383 emitcode("dec", "sp");
1384 emitcode("pop", "hl");
1386 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1390 freeAsmop(IC_LEFT(ic),NULL,ic);
1393 /** Emit the code for a call statement
1395 static void emitCall (iCode *ic, bool ispcall)
1397 /* if caller saves & we have not saved then */
1398 if (!ic->regsSaved) {
1402 /* if send set is not empty then assign */
1405 for (sic = setFirstItem(sendSet) ; sic ;
1406 sic = setNextItem(sendSet)) {
1407 int size, offset = 0;
1408 aopOp(IC_LEFT(sic),sic,FALSE);
1409 size = AOP_SIZE(IC_LEFT(sic));
1411 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1413 if (strcmp(l, _fReturn[offset]))
1414 emitcode("ld","%s,%s",
1419 freeAsmop (IC_LEFT(sic),NULL,sic);
1425 aopOp(IC_LEFT(ic),ic,FALSE);
1427 if (isLitWord(AOP(IC_LEFT(ic)))) {
1428 emitcode("", "; Special case where the pCall is to a constant");
1429 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1432 symbol *rlbl = newiTempLabel(NULL);
1434 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1435 emitcode("push", "hl");
1436 _G.stack.pushed += 2;
1438 fetchHL(AOP(IC_LEFT(ic)));
1439 emitcode("jp", "(hl)");
1440 emitcode("","%05d$:",(rlbl->key+100));
1441 _G.stack.pushed -= 2;
1443 freeAsmop(IC_LEFT(ic),NULL,ic);
1447 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1448 OP_SYMBOL(IC_LEFT(ic))->rname :
1449 OP_SYMBOL(IC_LEFT(ic))->name;
1450 emitcode("call", "%s", name);
1454 /* if we need assign a result value */
1455 if ((IS_ITEMP(IC_RESULT(ic)) &&
1456 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1457 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1458 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1461 aopOp(IC_RESULT(ic),ic,FALSE);
1464 assignResultValue(IC_RESULT(ic));
1466 freeAsmop(IC_RESULT(ic),NULL, ic);
1469 /* adjust the stack for parameters if required */
1470 if (IC_LEFT(ic)->parmBytes) {
1471 int i = IC_LEFT(ic)->parmBytes;
1472 _G.stack.pushed -= i;
1474 emitcode("lda", "sp,%d(sp)", i);
1479 emitcode("ld", "hl,#%d", i);
1480 emitcode("add", "hl,sp");
1481 emitcode("ld", "sp,hl");
1485 emitcode("pop", "hl");
1489 emitcode("inc", "sp");
1497 /*-----------------------------------------------------------------*/
1498 /* genCall - generates a call statement */
1499 /*-----------------------------------------------------------------*/
1500 static void genCall (iCode *ic)
1502 emitCall(ic, FALSE);
1505 /*-----------------------------------------------------------------*/
1506 /* genPcall - generates a call by pointer statement */
1507 /*-----------------------------------------------------------------*/
1508 static void genPcall (iCode *ic)
1513 /*-----------------------------------------------------------------*/
1514 /* resultRemat - result is rematerializable */
1515 /*-----------------------------------------------------------------*/
1516 static int resultRemat (iCode *ic)
1518 if (SKIP_IC(ic) || ic->op == IFX)
1521 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1522 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1523 if (sym->remat && !POINTER_SET(ic))
1530 /*-----------------------------------------------------------------*/
1531 /* genFunction - generated code for function entry */
1532 /*-----------------------------------------------------------------*/
1533 static void genFunction (iCode *ic)
1535 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1539 /* create the function header */
1540 emitcode(";","-----------------------------------------");
1541 emitcode(";"," function %s", sym->name);
1542 emitcode(";","-----------------------------------------");
1544 emitcode("", "__%s_start:", sym->rname);
1545 emitcode("","%s:",sym->rname);
1547 fetype = getSpec(operandType(IC_LEFT(ic)));
1549 /* if critical function then turn interrupts off */
1550 if (SPEC_CRTCL(fetype))
1553 /* if this is an interrupt service routine then
1554 save acc, b, dpl, dph */
1555 if (IS_ISR(sym->etype)) {
1556 emitcode("push", "af");
1557 emitcode("push", "bc");
1558 emitcode("push", "de");
1559 emitcode("push", "hl");
1561 /* PENDING: callee-save etc */
1563 /* adjust the stack for the function */
1564 emitcode("push", "bc");
1566 emitcode("push", "de");
1567 emitcode("push", "ix");
1568 emitcode("ld", "ix,#0");
1569 emitcode("add", "ix,sp");
1572 _G.stack.last = sym->stack;
1576 emitcode("lda", "sp,-%d(sp)", sym->stack);
1579 emitcode("ld", "hl,#-%d", sym->stack);
1580 emitcode("add", "hl,sp");
1581 emitcode("ld", "sp,hl");
1584 _G.stack.offset = sym->stack;
1587 /*-----------------------------------------------------------------*/
1588 /* genEndFunction - generates epilogue for functions */
1589 /*-----------------------------------------------------------------*/
1590 static void genEndFunction (iCode *ic)
1592 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1594 if (IS_ISR(sym->etype)) {
1598 if (SPEC_CRTCL(sym->etype))
1601 /* PENDING: calleeSave */
1603 /* if debug then send end of function */
1604 if (options.debug && currFunc) {
1606 emitcode("","C$%s$%d$%d$%d ==.",
1607 ic->filename,currFunc->lastLine,
1608 ic->level,ic->block);
1609 if (IS_STATIC(currFunc->etype))
1610 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1612 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1616 emitcode("ld", "sp,ix");
1617 emitcode("pop", "ix");
1618 emitcode("pop", "de");
1621 if (_G.stack.offset) {
1622 emitcode("lda", "sp,%d(sp)", _G.stack.offset);
1625 emitcode("pop", "bc");
1626 emitcode("ret", "");
1628 _G.stack.pushed = 0;
1629 _G.stack.offset = 0;
1632 /*-----------------------------------------------------------------*/
1633 /* genRet - generate code for return statement */
1634 /*-----------------------------------------------------------------*/
1635 static void genRet (iCode *ic)
1638 /* Errk. This is a hack until I can figure out how
1639 to cause dehl to spill on a call */
1640 int size,offset = 0;
1642 /* if we have no return value then
1643 just generate the "ret" */
1647 /* we have something to return then
1648 move the return value into place */
1649 aopOp(IC_LEFT(ic),ic,FALSE);
1650 size = AOP_SIZE(IC_LEFT(ic));
1652 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1654 emitcode("ld", "de,%s", l);
1657 emitcode("ld", "hl,%s", l);
1661 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
1662 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
1663 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1667 l = aopGet(AOP(IC_LEFT(ic)),offset,
1669 if (strcmp(_fReturn[offset],l))
1670 emitcode("ld","%s,%s", _fReturn[offset++],l);
1674 freeAsmop (IC_LEFT(ic),NULL,ic);
1677 /* generate a jump to the return label
1678 if the next is not the return statement */
1679 if (!(ic->next && ic->next->op == LABEL &&
1680 IC_LABEL(ic->next) == returnLabel))
1682 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1685 /*-----------------------------------------------------------------*/
1686 /* genLabel - generates a label */
1687 /*-----------------------------------------------------------------*/
1688 static void genLabel (iCode *ic)
1690 /* special case never generate */
1691 if (IC_LABEL(ic) == entryLabel)
1694 emitLabel(IC_LABEL(ic)->key+100);
1697 /*-----------------------------------------------------------------*/
1698 /* genGoto - generates a ljmp */
1699 /*-----------------------------------------------------------------*/
1700 static void genGoto (iCode *ic)
1702 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1705 /*-----------------------------------------------------------------*/
1706 /* genPlusIncr :- does addition with increment if possible */
1707 /*-----------------------------------------------------------------*/
1708 static bool genPlusIncr (iCode *ic)
1710 unsigned int icount ;
1711 unsigned int size = getDataSize(IC_RESULT(ic));
1712 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
1714 /* will try to generate an increment */
1715 /* if the right side is not a literal
1717 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1720 emitcode("", "; genPlusIncr");
1722 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1724 /* If result is a pair */
1725 if (resultId != PAIR_INVALID) {
1726 if (isLitWord(AOP(IC_LEFT(ic)))) {
1727 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1730 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
1731 fetchPair(resultId, AOP(IC_RIGHT(ic)));
1732 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
1738 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1741 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1742 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1745 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1750 /* if the literal value of the right hand side
1751 is greater than 4 then it is not worth it */
1755 /* if increment 16 bits in register */
1756 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1759 symbol *tlbl = newiTempLabel(NULL);
1760 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1761 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1763 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1767 emitLabel(tlbl->key+100);
1771 /* if the sizes are greater than 1 then we cannot */
1772 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1773 AOP_SIZE(IC_LEFT(ic)) > 1 )
1776 /* we can if the aops of the left & result match or
1777 if they are in registers and the registers are the
1779 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1781 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1789 /*-----------------------------------------------------------------*/
1790 /* outBitAcc - output a bit in acc */
1791 /*-----------------------------------------------------------------*/
1792 void outBitAcc(operand *result)
1794 symbol *tlbl = newiTempLabel(NULL);
1795 /* if the result is a bit */
1796 if (AOP_TYPE(result) == AOP_CRY){
1800 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1801 emitcode("ld","a,%s",one);
1802 emitLabel(tlbl->key+100);
1807 /*-----------------------------------------------------------------*/
1808 /* genPlus - generates code for addition */
1809 /*-----------------------------------------------------------------*/
1810 static void genPlus (iCode *ic)
1812 int size, offset = 0;
1814 /* special cases :- */
1816 aopOp (IC_LEFT(ic),ic,FALSE);
1817 aopOp (IC_RIGHT(ic),ic,FALSE);
1818 aopOp (IC_RESULT(ic),ic,TRUE);
1820 /* Swap the left and right operands if:
1822 if literal, literal on the right or
1823 if left requires ACC or right is already
1826 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1827 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1828 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1829 operand *t = IC_RIGHT(ic);
1830 IC_RIGHT(ic) = IC_LEFT(ic);
1834 /* if both left & right are in bit
1836 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1837 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1842 /* if left in bit space & right literal */
1843 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1844 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1845 /* Can happen I guess */
1849 /* if I can do an increment instead
1850 of add then GOOD for ME */
1851 if (genPlusIncr (ic) == TRUE)
1854 size = getDataSize(IC_RESULT(ic));
1856 /* Special case when left and right are constant */
1857 if (isPair(AOP(IC_RESULT(ic)))) {
1860 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1861 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1862 if (left && right) {
1866 sprintf(buffer, "#(%s + %s)", left, right);
1867 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1872 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1873 /* Fetch into HL then do the add */
1875 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1876 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1881 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1882 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1884 emitcode("add","a,%s",
1885 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1887 emitcode("adc","a,%s",
1888 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1890 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1892 emitcode("add","a,%s",
1893 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1895 emitcode("adc","a,%s",
1896 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1898 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1901 /* Some kind of pointer arith. */
1902 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1903 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1904 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1907 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1908 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1909 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1914 freeAsmop(IC_LEFT(ic),NULL,ic);
1915 freeAsmop(IC_RIGHT(ic),NULL,ic);
1916 freeAsmop(IC_RESULT(ic),NULL,ic);
1920 /*-----------------------------------------------------------------*/
1921 /* genMinusDec :- does subtraction with deccrement if possible */
1922 /*-----------------------------------------------------------------*/
1923 static bool genMinusDec (iCode *ic)
1925 unsigned int icount ;
1926 unsigned int size = getDataSize(IC_RESULT(ic));
1928 /* will try to generate an increment */
1929 /* if the right side is not a literal we cannot */
1930 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1933 /* if the literal value of the right hand side
1934 is greater than 4 then it is not worth it */
1935 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1938 size = getDataSize(IC_RESULT(ic));
1941 /* if increment 16 bits in register */
1942 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1945 symbol *tlbl = newiTempLabel(NULL);
1946 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1947 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1949 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1953 emitLabel(tlbl->key+100);
1958 /* if decrement 16 bits in register */
1959 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1960 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1962 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1966 /* If result is a pair */
1967 if (isPair(AOP(IC_RESULT(ic)))) {
1968 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1969 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1971 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1975 /* if the sizes are greater than 1 then we cannot */
1976 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1977 AOP_SIZE(IC_LEFT(ic)) > 1 )
1980 /* we can if the aops of the left & result match or if they are in
1981 registers and the registers are the same */
1982 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1984 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1991 /*-----------------------------------------------------------------*/
1992 /* genMinus - generates code for subtraction */
1993 /*-----------------------------------------------------------------*/
1994 static void genMinus (iCode *ic)
1996 int size, offset = 0;
1997 unsigned long lit = 0L;
1999 aopOp (IC_LEFT(ic),ic,FALSE);
2000 aopOp (IC_RIGHT(ic),ic,FALSE);
2001 aopOp (IC_RESULT(ic),ic,TRUE);
2003 /* special cases :- */
2004 /* if both left & right are in bit space */
2005 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2006 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2011 /* if I can do an decrement instead of subtract then GOOD for ME */
2012 if (genMinusDec (ic) == TRUE)
2015 size = getDataSize(IC_RESULT(ic));
2017 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2020 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2025 /* if literal, add a,#-lit, else normal subb */
2027 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2028 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2030 emitcode("sub","a,%s",
2031 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2033 emitcode("sbc","a,%s",
2034 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2037 /* first add without previous c */
2039 emitcode("add","a,#0x%02x",
2040 (unsigned int)(lit & 0x0FFL));
2042 emitcode("adc","a,#0x%02x",
2043 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2045 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2048 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2049 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2050 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2054 freeAsmop(IC_LEFT(ic),NULL,ic);
2055 freeAsmop(IC_RIGHT(ic),NULL,ic);
2056 freeAsmop(IC_RESULT(ic),NULL,ic);
2059 /*-----------------------------------------------------------------*/
2060 /* genMult - generates code for multiplication */
2061 /*-----------------------------------------------------------------*/
2062 static void genMult (iCode *ic)
2064 /* Shouldn't occur - all done through function calls */
2068 /*-----------------------------------------------------------------*/
2069 /* genDiv - generates code for division */
2070 /*-----------------------------------------------------------------*/
2071 static void genDiv (iCode *ic)
2073 /* Shouldn't occur - all done through function calls */
2077 /*-----------------------------------------------------------------*/
2078 /* genMod - generates code for division */
2079 /*-----------------------------------------------------------------*/
2080 static void genMod (iCode *ic)
2082 /* Shouldn't occur - all done through function calls */
2086 /*-----------------------------------------------------------------*/
2087 /* genIfxJump :- will create a jump depending on the ifx */
2088 /*-----------------------------------------------------------------*/
2089 static void genIfxJump (iCode *ic, char *jval)
2094 /* if true label then we jump if condition
2096 if ( IC_TRUE(ic) ) {
2098 if (!strcmp(jval, "a")) {
2101 else if (!strcmp(jval, "c")) {
2105 /* The buffer contains the bit on A that we should test */
2110 /* false label is present */
2111 jlbl = IC_FALSE(ic) ;
2112 if (!strcmp(jval, "a")) {
2115 else if (!strcmp(jval, "c")) {
2119 /* The buffer contains the bit on A that we should test */
2123 /* Z80 can do a conditional long jump */
2124 if (!strcmp(jval, "a")) {
2125 emitcode("or", "a,a");
2127 else if (!strcmp(jval, "c")) {
2130 emitcode("bit", "%s,a", jval);
2132 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
2134 /* mark the icode as generated */
2138 /** Generic compare for > or <
2140 static void genCmp (operand *left,operand *right,
2141 operand *result, iCode *ifx, int sign)
2143 int size, offset = 0 ;
2144 unsigned long lit = 0L;
2146 /* if left & right are bit variables */
2147 if (AOP_TYPE(left) == AOP_CRY &&
2148 AOP_TYPE(right) == AOP_CRY ) {
2149 /* Cant happen on the Z80 */
2152 /* subtract right from left if at the
2153 end the carry flag is set then we know that
2154 left is greater than right */
2155 size = max(AOP_SIZE(left),AOP_SIZE(right));
2157 /* if unsigned char cmp with lit, just compare */
2159 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2160 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2162 emitcode("xor", "a,#0x80");
2163 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
2166 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
2169 if(AOP_TYPE(right) == AOP_LIT) {
2170 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2171 /* optimize if(x < 0) or if(x >= 0) */
2174 /* No sign so it's always false */
2178 /* Just load in the top most bit */
2179 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2180 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2181 genIfxJump (ifx,"7");
2185 emitcode("rlc","a");
2191 /* First setup h and l contaning the top most bytes XORed */
2192 bool fDidXor = FALSE;
2193 if (AOP_TYPE(left) == AOP_LIT){
2194 unsigned long lit = (unsigned long)
2195 floatFromVal(AOP(left)->aopu.aop_lit);
2196 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2197 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2200 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2201 emitcode("xor", "a,#0x80");
2202 emitcode("ld", "%s,a", _fTmp[0]);
2205 if (AOP_TYPE(right) == AOP_LIT) {
2206 unsigned long lit = (unsigned long)
2207 floatFromVal(AOP(right)->aopu.aop_lit);
2208 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2209 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2212 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2213 emitcode("xor", "a,#0x80");
2214 emitcode("ld", "%s,a", _fTmp[1]);
2224 /* Do a long subtract */
2225 if (!sign || size ) {
2226 MOVA(aopGet(AOP(left),offset,FALSE));
2228 if (sign && size == 0) {
2229 emitcode("ld", "a,%s", _fTmp[0]);
2230 emitcode("sbc", "a,%s", _fTmp[1]);
2233 /* Subtract through, propagating the carry */
2234 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2241 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2244 /* if the result is used in the next
2245 ifx conditional branch then generate
2246 code a little differently */
2248 genIfxJump (ifx,"c");
2251 /* leave the result in acc */
2255 /*-----------------------------------------------------------------*/
2256 /* genCmpGt :- greater than comparison */
2257 /*-----------------------------------------------------------------*/
2258 static void genCmpGt (iCode *ic, iCode *ifx)
2260 operand *left, *right, *result;
2261 link *letype , *retype;
2265 right= IC_RIGHT(ic);
2266 result = IC_RESULT(ic);
2268 letype = getSpec(operandType(left));
2269 retype =getSpec(operandType(right));
2270 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2271 /* assign the amsops */
2272 aopOp (left,ic,FALSE);
2273 aopOp (right,ic,FALSE);
2274 aopOp (result,ic,TRUE);
2276 genCmp(right, left, result, ifx, sign);
2278 freeAsmop(left,NULL,ic);
2279 freeAsmop(right,NULL,ic);
2280 freeAsmop(result,NULL,ic);
2283 /*-----------------------------------------------------------------*/
2284 /* genCmpLt - less than comparisons */
2285 /*-----------------------------------------------------------------*/
2286 static void genCmpLt (iCode *ic, iCode *ifx)
2288 operand *left, *right, *result;
2289 link *letype , *retype;
2293 right= IC_RIGHT(ic);
2294 result = IC_RESULT(ic);
2296 letype = getSpec(operandType(left));
2297 retype =getSpec(operandType(right));
2298 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2300 /* assign the amsops */
2301 aopOp (left,ic,FALSE);
2302 aopOp (right,ic,FALSE);
2303 aopOp (result,ic,TRUE);
2305 genCmp(left, right, result, ifx, sign);
2307 freeAsmop(left,NULL,ic);
2308 freeAsmop(right,NULL,ic);
2309 freeAsmop(result,NULL,ic);
2312 /*-----------------------------------------------------------------*/
2313 /* gencjneshort - compare and jump if not equal */
2314 /*-----------------------------------------------------------------*/
2315 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2317 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2319 unsigned long lit = 0L;
2321 /* Swap the left and right if it makes the computation easier */
2322 if (AOP_TYPE(left) == AOP_LIT) {
2328 if(AOP_TYPE(right) == AOP_LIT)
2329 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2331 /* if the right side is a literal then anything goes */
2332 if (AOP_TYPE(right) == AOP_LIT &&
2333 AOP_TYPE(left) != AOP_DIR ) {
2335 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2340 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2344 emitcode("or", "a,a");
2346 emitcode("jp", "nz," LABEL_STR, lbl->key+100);
2350 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2351 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2352 emitcode("or", "a,a");
2354 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2355 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2360 /* if the right side is in a register or in direct space or
2361 if the left is a pointer register & right is not */
2362 else if (AOP_TYPE(right) == AOP_REG ||
2363 AOP_TYPE(right) == AOP_DIR ||
2364 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2366 MOVA(aopGet(AOP(left),offset,FALSE));
2367 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2368 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2370 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2372 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2373 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2378 /* right is a pointer reg need both a & b */
2379 /* PENDING: is this required? */
2381 MOVA(aopGet(AOP(right),offset,FALSE));
2382 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2383 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2389 /*-----------------------------------------------------------------*/
2390 /* gencjne - compare and jump if not equal */
2391 /*-----------------------------------------------------------------*/
2392 static void gencjne(operand *left, operand *right, symbol *lbl)
2394 symbol *tlbl = newiTempLabel(NULL);
2396 gencjneshort(left, right, lbl);
2399 emitcode("ld","a,%s",one);
2400 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2401 emitLabel(lbl->key+100);
2402 emitcode("xor","a,a");
2403 emitLabel(tlbl->key+100);
2406 /*-----------------------------------------------------------------*/
2407 /* genCmpEq - generates code for equal to */
2408 /*-----------------------------------------------------------------*/
2409 static void genCmpEq (iCode *ic, iCode *ifx)
2411 operand *left, *right, *result;
2413 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2414 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2415 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2417 /* Swap operands if it makes the operation easier. ie if:
2418 1. Left is a literal.
2420 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2421 operand *t = IC_RIGHT(ic);
2422 IC_RIGHT(ic) = IC_LEFT(ic);
2426 if (ifx && !AOP_SIZE(result)){
2428 /* if they are both bit variables */
2429 if (AOP_TYPE(left) == AOP_CRY &&
2430 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2433 tlbl = newiTempLabel(NULL);
2434 gencjneshort(left, right, tlbl);
2435 if ( IC_TRUE(ifx) ) {
2436 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2437 emitLabel(tlbl->key+100);
2439 /* PENDING: do this better */
2440 symbol *lbl = newiTempLabel(NULL);
2441 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2442 emitLabel(tlbl->key+100);
2443 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2444 emitLabel(lbl->key+100);
2447 /* mark the icode as generated */
2452 /* if they are both bit variables */
2453 if (AOP_TYPE(left) == AOP_CRY &&
2454 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2457 gencjne(left,right,newiTempLabel(NULL));
2458 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2462 genIfxJump(ifx,"a");
2465 /* if the result is used in an arithmetic operation
2466 then put the result in place */
2467 if (AOP_TYPE(result) != AOP_CRY) {
2470 /* leave the result in acc */
2474 freeAsmop(left,NULL,ic);
2475 freeAsmop(right,NULL,ic);
2476 freeAsmop(result,NULL,ic);
2479 /*-----------------------------------------------------------------*/
2480 /* ifxForOp - returns the icode containing the ifx for operand */
2481 /*-----------------------------------------------------------------*/
2482 static iCode *ifxForOp ( operand *op, iCode *ic )
2484 /* if true symbol then needs to be assigned */
2485 if (IS_TRUE_SYMOP(op))
2488 /* if this has register type condition and
2489 the next instruction is ifx with the same operand
2490 and live to of the operand is upto the ifx only then */
2492 ic->next->op == IFX &&
2493 IC_COND(ic->next)->key == op->key &&
2494 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2500 /*-----------------------------------------------------------------*/
2501 /* genAndOp - for && operation */
2502 /*-----------------------------------------------------------------*/
2503 static void genAndOp (iCode *ic)
2505 operand *left,*right, *result;
2508 /* note here that && operations that are in an if statement are
2509 taken away by backPatchLabels only those used in arthmetic
2510 operations remain */
2511 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2512 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2513 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2515 /* if both are bit variables */
2516 if (AOP_TYPE(left) == AOP_CRY &&
2517 AOP_TYPE(right) == AOP_CRY ) {
2520 tlbl = newiTempLabel(NULL);
2522 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2524 emitLabel(tlbl->key+100);
2528 freeAsmop(left,NULL,ic);
2529 freeAsmop(right,NULL,ic);
2530 freeAsmop(result,NULL,ic);
2533 /*-----------------------------------------------------------------*/
2534 /* genOrOp - for || operation */
2535 /*-----------------------------------------------------------------*/
2536 static void genOrOp (iCode *ic)
2538 operand *left,*right, *result;
2541 /* note here that || operations that are in an
2542 if statement are taken away by backPatchLabels
2543 only those used in arthmetic operations remain */
2544 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2545 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2546 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2548 /* if both are bit variables */
2549 if (AOP_TYPE(left) == AOP_CRY &&
2550 AOP_TYPE(right) == AOP_CRY ) {
2553 tlbl = newiTempLabel(NULL);
2555 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2557 emitLabel(tlbl->key+100);
2561 freeAsmop(left,NULL,ic);
2562 freeAsmop(right,NULL,ic);
2563 freeAsmop(result,NULL,ic);
2566 /*-----------------------------------------------------------------*/
2567 /* isLiteralBit - test if lit == 2^n */
2568 /*-----------------------------------------------------------------*/
2569 int isLiteralBit(unsigned long lit)
2571 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2572 0x100L,0x200L,0x400L,0x800L,
2573 0x1000L,0x2000L,0x4000L,0x8000L,
2574 0x10000L,0x20000L,0x40000L,0x80000L,
2575 0x100000L,0x200000L,0x400000L,0x800000L,
2576 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2577 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2580 for(idx = 0; idx < 32; idx++)
2586 /*-----------------------------------------------------------------*/
2587 /* jmpTrueOrFalse - */
2588 /*-----------------------------------------------------------------*/
2589 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2591 // ugly but optimized by peephole
2593 symbol *nlbl = newiTempLabel(NULL);
2594 emitcode("jp", LABEL_STR, nlbl->key+100);
2595 emitLabel(tlbl->key+100);
2596 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2597 emitLabel(nlbl->key+100);
2600 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2601 emitLabel(tlbl->key+100);
2606 /*-----------------------------------------------------------------*/
2607 /* genAnd - code for and */
2608 /*-----------------------------------------------------------------*/
2609 static void genAnd (iCode *ic, iCode *ifx)
2611 operand *left, *right, *result;
2613 unsigned long lit = 0L;
2616 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2617 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2618 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2621 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2623 AOP_TYPE(left), AOP_TYPE(right));
2624 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2626 AOP_SIZE(left), AOP_SIZE(right));
2629 /* if left is a literal & right is not then exchange them */
2630 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2631 AOP_NEEDSACC(left)) {
2632 operand *tmp = right ;
2637 /* if result = right then exchange them */
2638 if(sameRegs(AOP(result),AOP(right))){
2639 operand *tmp = right ;
2644 /* if right is bit then exchange them */
2645 if (AOP_TYPE(right) == AOP_CRY &&
2646 AOP_TYPE(left) != AOP_CRY){
2647 operand *tmp = right ;
2651 if(AOP_TYPE(right) == AOP_LIT)
2652 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2654 size = AOP_SIZE(result);
2656 if (AOP_TYPE(left) == AOP_CRY){
2661 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2662 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2663 if((AOP_TYPE(right) == AOP_LIT) &&
2664 (AOP_TYPE(result) == AOP_CRY) &&
2665 (AOP_TYPE(left) != AOP_CRY)) {
2666 int posbit = isLiteralBit(lit);
2670 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2674 emitcode("mov","c,acc.%d",posbit&0x07);
2679 sprintf(buffer, "%d", posbit&0x07);
2680 genIfxJump(ifx, buffer);
2688 symbol *tlbl = newiTempLabel(NULL);
2689 int sizel = AOP_SIZE(left);
2692 emitcode("setb","c");
2695 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2696 MOVA( aopGet(AOP(left),offset,FALSE));
2698 if((posbit = isLiteralBit(bytelit)) != 0) {
2700 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2703 if(bytelit != 0x0FFL)
2704 emitcode("and","a,%s",
2705 aopGet(AOP(right),offset,FALSE));
2706 emitcode("jr","nz, %05d$",tlbl->key+100);
2711 // bit = left & literal
2713 emitcode("clr","c");
2714 emitcode("","%05d$:",tlbl->key+100);
2716 // if(left & literal)
2719 jmpTrueOrFalse(ifx, tlbl);
2727 /* if left is same as result */
2728 if(sameRegs(AOP(result),AOP(left))){
2729 for(;size--; offset++) {
2730 if(AOP_TYPE(right) == AOP_LIT){
2731 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2735 aopPut(AOP(result),zero,offset);
2737 MOVA(aopGet(AOP(left),offset,FALSE));
2738 emitcode("and","a,%s",
2739 aopGet(AOP(right),offset,FALSE));
2740 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2745 if (AOP_TYPE(left) == AOP_ACC) {
2749 MOVA(aopGet(AOP(right),offset,FALSE));
2750 emitcode("and","%s,a",
2751 aopGet(AOP(left),offset,FALSE));
2756 // left & result in different registers
2757 if(AOP_TYPE(result) == AOP_CRY){
2760 for(;(size--);offset++) {
2762 // result = left & right
2763 if(AOP_TYPE(right) == AOP_LIT){
2764 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2766 aopGet(AOP(left),offset,FALSE),
2769 } else if(bytelit == 0){
2770 aopPut(AOP(result),zero,offset);
2774 // faster than result <- left, anl result,right
2775 // and better if result is SFR
2776 if (AOP_TYPE(left) == AOP_ACC)
2777 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2779 MOVA(aopGet(AOP(right),offset,FALSE));
2780 emitcode("and","a,%s",
2781 aopGet(AOP(left),offset,FALSE));
2783 aopPut(AOP(result),"a",offset);
2790 freeAsmop(left,NULL,ic);
2791 freeAsmop(right,NULL,ic);
2792 freeAsmop(result,NULL,ic);
2795 /*-----------------------------------------------------------------*/
2796 /* genOr - code for or */
2797 /*-----------------------------------------------------------------*/
2798 static void genOr (iCode *ic, iCode *ifx)
2800 operand *left, *right, *result;
2802 unsigned long lit = 0L;
2804 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2805 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2806 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2809 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2811 AOP_TYPE(left), AOP_TYPE(right));
2812 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2814 AOP_SIZE(left), AOP_SIZE(right));
2817 /* if left is a literal & right is not then exchange them */
2818 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2819 AOP_NEEDSACC(left)) {
2820 operand *tmp = right ;
2825 /* if result = right then exchange them */
2826 if(sameRegs(AOP(result),AOP(right))){
2827 operand *tmp = right ;
2832 /* if right is bit then exchange them */
2833 if (AOP_TYPE(right) == AOP_CRY &&
2834 AOP_TYPE(left) != AOP_CRY){
2835 operand *tmp = right ;
2839 if(AOP_TYPE(right) == AOP_LIT)
2840 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2842 size = AOP_SIZE(result);
2844 if (AOP_TYPE(left) == AOP_CRY){
2849 if((AOP_TYPE(right) == AOP_LIT) &&
2850 (AOP_TYPE(result) == AOP_CRY) &&
2851 (AOP_TYPE(left) != AOP_CRY)){
2856 /* if left is same as result */
2857 if(sameRegs(AOP(result),AOP(left))){
2858 for(;size--; offset++) {
2859 if(AOP_TYPE(right) == AOP_LIT){
2860 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2863 MOVA(aopGet(AOP(right),offset,FALSE));
2864 emitcode("or","a,%s; 5",
2865 aopGet(AOP(left),offset,FALSE));
2866 aopPut(AOP(result),"a ; 8", offset);
2869 if (AOP_TYPE(left) == AOP_ACC)
2870 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2872 MOVA(aopGet(AOP(right),offset,FALSE));
2873 emitcode("or","a,%s ; 7",
2874 aopGet(AOP(left),offset,FALSE));
2875 aopPut(AOP(result),"a ; 8", offset);
2880 // left & result in different registers
2881 if(AOP_TYPE(result) == AOP_CRY){
2883 } else for(;(size--);offset++){
2885 // result = left & right
2886 if(AOP_TYPE(right) == AOP_LIT){
2887 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2889 aopGet(AOP(left),offset,FALSE),
2894 // faster than result <- left, anl result,right
2895 // and better if result is SFR
2896 if (AOP_TYPE(left) == AOP_ACC)
2897 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2899 MOVA(aopGet(AOP(right),offset,FALSE));
2900 emitcode("or","a,%s",
2901 aopGet(AOP(left),offset,FALSE));
2903 aopPut(AOP(result),"a",offset);
2904 /* PENDING: something weird is going on here. Add exception. */
2905 if (AOP_TYPE(result) == AOP_ACC)
2911 freeAsmop(left,NULL,ic);
2912 freeAsmop(right,NULL,ic);
2913 freeAsmop(result,NULL,ic);
2916 /*-----------------------------------------------------------------*/
2917 /* genXor - code for xclusive or */
2918 /*-----------------------------------------------------------------*/
2919 static void genXor (iCode *ic, iCode *ifx)
2921 operand *left, *right, *result;
2923 unsigned long lit = 0L;
2925 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2926 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2927 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2929 /* if left is a literal & right is not then exchange them */
2930 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2931 AOP_NEEDSACC(left)) {
2932 operand *tmp = right ;
2937 /* if result = right then exchange them */
2938 if(sameRegs(AOP(result),AOP(right))){
2939 operand *tmp = right ;
2944 /* if right is bit then exchange them */
2945 if (AOP_TYPE(right) == AOP_CRY &&
2946 AOP_TYPE(left) != AOP_CRY){
2947 operand *tmp = right ;
2951 if(AOP_TYPE(right) == AOP_LIT)
2952 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2954 size = AOP_SIZE(result);
2956 if (AOP_TYPE(left) == AOP_CRY){
2961 if((AOP_TYPE(right) == AOP_LIT) &&
2962 (AOP_TYPE(result) == AOP_CRY) &&
2963 (AOP_TYPE(left) != AOP_CRY)){
2968 /* if left is same as result */
2969 if(sameRegs(AOP(result),AOP(left))){
2970 for(;size--; offset++) {
2971 if(AOP_TYPE(right) == AOP_LIT){
2972 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2975 MOVA(aopGet(AOP(right),offset,FALSE));
2976 emitcode("xor","a,%s",
2977 aopGet(AOP(left),offset,FALSE));
2978 aopPut(AOP(result),"a",0);
2981 if (AOP_TYPE(left) == AOP_ACC)
2982 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2984 MOVA(aopGet(AOP(right),offset,FALSE));
2985 emitcode("xor","a,%s",
2986 aopGet(AOP(left),offset,FALSE));
2987 aopPut(AOP(result),"a",0);
2992 // left & result in different registers
2993 if(AOP_TYPE(result) == AOP_CRY){
2995 } else for(;(size--);offset++){
2997 // result = left & right
2998 if(AOP_TYPE(right) == AOP_LIT){
2999 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3001 aopGet(AOP(left),offset,FALSE),
3006 // faster than result <- left, anl result,right
3007 // and better if result is SFR
3008 if (AOP_TYPE(left) == AOP_ACC)
3009 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3011 MOVA(aopGet(AOP(right),offset,FALSE));
3012 emitcode("xor","a,%s",
3013 aopGet(AOP(left),offset,FALSE));
3014 aopPut(AOP(result),"a",0);
3016 aopPut(AOP(result),"a",offset);
3021 freeAsmop(left,NULL,ic);
3022 freeAsmop(right,NULL,ic);
3023 freeAsmop(result,NULL,ic);
3026 /*-----------------------------------------------------------------*/
3027 /* genInline - write the inline code out */
3028 /*-----------------------------------------------------------------*/
3029 static void genInline (iCode *ic)
3031 char buffer[MAX_INLINEASM];
3035 inLine += (!options.asmpeep);
3036 strcpy(buffer,IC_INLINE(ic));
3038 /* emit each line as a code */
3057 /* emitcode("",buffer); */
3058 inLine -= (!options.asmpeep);
3061 /*-----------------------------------------------------------------*/
3062 /* genRRC - rotate right with carry */
3063 /*-----------------------------------------------------------------*/
3064 static void genRRC (iCode *ic)
3069 /*-----------------------------------------------------------------*/
3070 /* genRLC - generate code for rotate left with carry */
3071 /*-----------------------------------------------------------------*/
3072 static void genRLC (iCode *ic)
3077 /*-----------------------------------------------------------------*/
3078 /* shiftR2Left2Result - shift right two bytes from left to result */
3079 /*-----------------------------------------------------------------*/
3080 static void shiftR2Left2Result (operand *left, int offl,
3081 operand *result, int offr,
3082 int shCount, int sign)
3084 if(sameRegs(AOP(result), AOP(left)) &&
3085 ((offl + MSB16) == offr)){
3088 movLeft2Result(left, offl, result, offr, 0);
3089 movLeft2Result(left, offl+1, result, offr+1, 0);
3096 /* if (AOP(result)->type == AOP_REG) {*/
3099 symbol *tlbl , *tlbl1;
3102 /* Left is already in result - so now do the shift */
3104 emitcode("ld","a,#%u+1", shCount);
3105 tlbl = newiTempLabel(NULL);
3106 tlbl1 = newiTempLabel(NULL);
3107 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3108 emitLabel(tlbl->key+100);
3111 emitcode("or", "a,a");
3114 l = aopGet(AOP(result), --offset, FALSE);
3115 emitcode("rr","%s", l);
3118 emitLabel(tlbl1->key+100);
3119 emitcode("dec", "a");
3120 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3125 /*-----------------------------------------------------------------*/
3126 /* shiftL2Left2Result - shift left two bytes from left to result */
3127 /*-----------------------------------------------------------------*/
3128 static void shiftL2Left2Result (operand *left, int offl,
3129 operand *result, int offr, int shCount)
3131 if(sameRegs(AOP(result), AOP(left)) &&
3132 ((offl + MSB16) == offr)){
3135 /* Copy left into result */
3136 movLeft2Result(left, offl, result, offr, 0);
3137 movLeft2Result(left, offl+1, result, offr+1, 0);
3139 /* PENDING: for now just see if it'll work. */
3140 /*if (AOP(result)->type == AOP_REG) { */
3144 symbol *tlbl , *tlbl1;
3147 /* Left is already in result - so now do the shift */
3149 emitcode("ld","a,#%u+1", shCount);
3150 tlbl = newiTempLabel(NULL);
3151 tlbl1 = newiTempLabel(NULL);
3152 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3153 emitLabel(tlbl->key+100);
3156 emitcode("or", "a,a");
3158 l = aopGet(AOP(result),offset++,FALSE);
3159 emitcode("rl","%s", l);
3162 emitLabel(tlbl1->key+100);
3163 emitcode("dec", "a");
3164 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3169 /*-----------------------------------------------------------------*/
3170 /* AccRol - rotate left accumulator by known count */
3171 /*-----------------------------------------------------------------*/
3172 static void AccRol (int shCount)
3174 shCount &= 0x0007; // shCount : 0..7
3211 /*-----------------------------------------------------------------*/
3212 /* AccLsh - left shift accumulator by known count */
3213 /*-----------------------------------------------------------------*/
3214 static void AccLsh (int shCount)
3218 emitcode("add","a,a");
3221 emitcode("add","a,a");
3222 emitcode("add","a,a");
3224 /* rotate left accumulator */
3226 /* and kill the lower order bits */
3227 emitcode("and","a,#0x%02x", SLMask[shCount]);
3232 /*-----------------------------------------------------------------*/
3233 /* shiftL1Left2Result - shift left one byte from left to result */
3234 /*-----------------------------------------------------------------*/
3235 static void shiftL1Left2Result (operand *left, int offl,
3236 operand *result, int offr, int shCount)
3239 l = aopGet(AOP(left),offl,FALSE);
3241 /* shift left accumulator */
3243 aopPut(AOP(result),"a",offr);
3247 /*-----------------------------------------------------------------*/
3248 /* genlshTwo - left shift two bytes by known amount != 0 */
3249 /*-----------------------------------------------------------------*/
3250 static void genlshTwo (operand *result,operand *left, int shCount)
3252 int size = AOP_SIZE(result);
3256 /* if shCount >= 8 */
3262 movLeft2Result(left, LSB, result, MSB16, 0);
3263 aopPut(AOP(result),zero, 0);
3264 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3267 movLeft2Result(left, LSB, result, MSB16, 0);
3268 aopPut(AOP(result),zero, 0);
3271 aopPut(AOP(result),zero,LSB);
3273 /* 1 <= shCount <= 7 */
3279 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3284 /*-----------------------------------------------------------------*/
3285 /* genlshOne - left shift a one byte quantity by known count */
3286 /*-----------------------------------------------------------------*/
3287 static void genlshOne (operand *result, operand *left, int shCount)
3289 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3292 /*-----------------------------------------------------------------*/
3293 /* genLeftShiftLiteral - left shifting by known count */
3294 /*-----------------------------------------------------------------*/
3295 static void genLeftShiftLiteral (operand *left,
3300 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3303 freeAsmop(right,NULL,ic);
3305 aopOp(left,ic,FALSE);
3306 aopOp(result,ic,FALSE);
3308 size = getSize(operandType(result));
3311 emitcode("; shift left ","result %d, left %d",size,
3315 /* I suppose that the left size >= result size */
3320 else if(shCount >= (size * 8))
3322 aopPut(AOP(result),zero,size);
3326 genlshOne (result,left,shCount);
3329 genlshTwo (result,left,shCount);
3338 freeAsmop(left,NULL,ic);
3339 freeAsmop(result,NULL,ic);
3342 /*-----------------------------------------------------------------*/
3343 /* genLeftShift - generates code for left shifting */
3344 /*-----------------------------------------------------------------*/
3345 static void genLeftShift (iCode *ic)
3349 symbol *tlbl , *tlbl1;
3350 operand *left,*right, *result;
3352 right = IC_RIGHT(ic);
3354 result = IC_RESULT(ic);
3356 aopOp(right,ic,FALSE);
3358 /* if the shift count is known then do it
3359 as efficiently as possible */
3360 if (AOP_TYPE(right) == AOP_LIT) {
3361 genLeftShiftLiteral (left,right,result,ic);
3365 /* shift count is unknown then we have to form a loop get the loop
3366 count in B : Note: we take only the lower order byte since
3367 shifting more that 32 bits make no sense anyway, ( the largest
3368 size of an object can be only 32 bits ) */
3369 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3370 emitcode("inc","a");
3371 freeAsmop (right,NULL,ic);
3372 aopOp(left,ic,FALSE);
3373 aopOp(result,ic,FALSE);
3375 /* now move the left to the result if they are not the
3378 if (!sameRegs(AOP(left),AOP(result))) {
3380 size = AOP_SIZE(result);
3383 l = aopGet(AOP(left),offset,FALSE);
3384 aopPut(AOP(result),l,offset);
3389 size = AOP_SIZE(result);
3392 l = aopGet(AOP(left),offset,FALSE);
3393 aopPut(AOP(result),l,offset);
3399 tlbl = newiTempLabel(NULL);
3400 size = AOP_SIZE(result);
3402 tlbl1 = newiTempLabel(NULL);
3404 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3405 emitLabel(tlbl->key+100);
3406 l = aopGet(AOP(result),offset,FALSE);
3407 emitcode("or", "a,a");
3409 l = aopGet(AOP(result),offset++,FALSE);
3410 emitcode("rl","%s", l);
3412 emitLabel(tlbl1->key+100);
3413 emitcode("dec", "a");
3414 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3416 freeAsmop(left,NULL,ic);
3417 freeAsmop(result,NULL,ic);
3420 /*-----------------------------------------------------------------*/
3421 /* genlshTwo - left shift two bytes by known amount != 0 */
3422 /*-----------------------------------------------------------------*/
3423 static void genrshOne (operand *result,operand *left, int shCount)
3426 int size = AOP_SIZE(result);
3432 l = aopGet(AOP(left),0,FALSE);
3433 if (AOP(result)->type == AOP_REG) {
3434 aopPut(AOP(result), l, 0);
3435 l = aopGet(AOP(result), 0, FALSE);
3437 emitcode("srl", "%s", l);
3442 emitcode("srl", "a");
3444 aopPut(AOP(result),"a",0);
3448 /*-----------------------------------------------------------------*/
3449 /* AccRsh - right shift accumulator by known count */
3450 /*-----------------------------------------------------------------*/
3451 static void AccRsh (int shCount)
3458 /* rotate right accumulator */
3459 AccRol(8 - shCount);
3460 /* and kill the higher order bits */
3461 emitcode("and","a,#0x%02x", SRMask[shCount]);
3466 /*-----------------------------------------------------------------*/
3467 /* shiftR1Left2Result - shift right one byte from left to result */
3468 /*-----------------------------------------------------------------*/
3469 static void shiftR1Left2Result (operand *left, int offl,
3470 operand *result, int offr,
3471 int shCount, int sign)
3473 MOVA(aopGet(AOP(left),offl,FALSE));
3480 aopPut(AOP(result),"a",offr);
3483 /*-----------------------------------------------------------------*/
3484 /* genrshTwo - right shift two bytes by known amount != 0 */
3485 /*-----------------------------------------------------------------*/
3486 static void genrshTwo (operand *result,operand *left,
3487 int shCount, int sign)
3489 /* if shCount >= 8 */
3494 shiftR1Left2Result(left, MSB16, result, LSB,
3498 movLeft2Result(left, MSB16, result, LSB, sign);
3499 aopPut(AOP(result),zero,1);
3502 /* 1 <= shCount <= 7 */
3504 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3508 /*-----------------------------------------------------------------*/
3509 /* genRightShiftLiteral - left shifting by known count */
3510 /*-----------------------------------------------------------------*/
3511 static void genRightShiftLiteral (operand *left,
3516 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3519 freeAsmop(right,NULL,ic);
3521 aopOp(left,ic,FALSE);
3522 aopOp(result,ic,FALSE);
3524 size = getSize(operandType(result));
3526 emitcode("; shift right ","result %d, left %d",size,
3529 /* I suppose that the left size >= result size */
3534 else if(shCount >= (size * 8))
3536 aopPut(AOP(result),zero,size);
3540 genrshOne(result, left, shCount);
3543 /* PENDING: sign support */
3544 genrshTwo(result, left, shCount, FALSE);
3553 freeAsmop(left,NULL,ic);
3554 freeAsmop(result,NULL,ic);
3557 /*-----------------------------------------------------------------*/
3558 /* genRightShift - generate code for right shifting */
3559 /*-----------------------------------------------------------------*/
3560 static void genRightShift (iCode *ic)
3562 operand *right, *left, *result;
3564 int size, offset, first = 1;
3568 symbol *tlbl, *tlbl1 ;
3570 /* if signed then we do it the hard way preserve the
3571 sign bit moving it inwards */
3572 retype = getSpec(operandType(IC_RESULT(ic)));
3574 is_signed = !SPEC_USIGN(retype);
3576 /* signed & unsigned types are treated the same : i.e. the
3577 signed is NOT propagated inwards : quoting from the
3578 ANSI - standard : "for E1 >> E2, is equivalent to division
3579 by 2**E2 if unsigned or if it has a non-negative value,
3580 otherwise the result is implementation defined ", MY definition
3581 is that the sign does not get propagated */
3583 right = IC_RIGHT(ic);
3585 result = IC_RESULT(ic);
3587 aopOp(right,ic,FALSE);
3589 /* if the shift count is known then do it
3590 as efficiently as possible */
3591 if (AOP_TYPE(right) == AOP_LIT) {
3592 genRightShiftLiteral(left,right,result,ic);
3596 aopOp(left,ic,FALSE);
3597 aopOp(result,ic,FALSE);
3599 /* now move the left to the result if they are not the
3601 if (!sameRegs(AOP(left),AOP(result)) &&
3602 AOP_SIZE(result) > 1) {
3604 size = AOP_SIZE(result);
3607 l = aopGet(AOP(left),offset,FALSE);
3608 aopPut(AOP(result),l,offset);
3613 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
3614 emitcode("inc","a");
3615 freeAsmop (right, NULL, ic);
3617 tlbl = newiTempLabel(NULL);
3618 tlbl1= newiTempLabel(NULL);
3619 size = AOP_SIZE(result);
3622 emitcode(_shortJP, LABEL_STR, tlbl1->key+100);
3623 emitcode("", LABEL_STR ":", tlbl->key+100);
3625 l = aopGet(AOP(result),offset--,FALSE);
3628 emitcode("sra", "%s", l);
3630 emitcode("srl", "%s", l);
3634 emitcode("rr", "%s", l);
3636 emitcode("", LABEL_STR ":", tlbl1->key+100);
3637 emitcode("dec", "a");
3638 emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100);
3640 freeAsmop(left,NULL,ic);
3641 freeAsmop(result,NULL,ic);
3644 /*-----------------------------------------------------------------*/
3645 /* genGenPointerGet - gget value from generic pointer space */
3646 /*-----------------------------------------------------------------*/
3647 static void genGenPointerGet (operand *left,
3648 operand *result, iCode *ic)
3651 link *retype = getSpec(operandType(result));
3657 aopOp(left,ic,FALSE);
3658 aopOp(result,ic,FALSE);
3660 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3662 if (isPtrPair(AOP(left)))
3664 sprintf(buffer, "(%s)", getPairName(AOP(left)));
3665 aopPut(AOP(result), buffer, 0);
3668 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3669 aopPut(AOP(result),"a", 0);
3671 freeAsmop(left,NULL,ic);
3675 /* For now we always load into IY */
3676 /* if this is remateriazable */
3677 fetchPair(pair, AOP(left));
3679 /* so iy now contains the address */
3680 freeAsmop(left,NULL,ic);
3682 /* if bit then unpack */
3683 if (IS_BITVAR(retype)) {
3687 size = AOP_SIZE(result);
3691 /* PENDING: make this better */
3692 if (!IS_GB && AOP(result)->type == AOP_REG) {
3693 aopPut(AOP(result),"(hl)",offset++);
3696 emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
3697 aopPut(AOP(result),"a",offset++);
3700 emitcode("inc", "%s", _pairs[pair].name);
3706 freeAsmop(result,NULL,ic);
3709 /*-----------------------------------------------------------------*/
3710 /* genPointerGet - generate code for pointer get */
3711 /*-----------------------------------------------------------------*/
3712 static void genPointerGet (iCode *ic)
3714 operand *left, *result ;
3718 result = IC_RESULT(ic) ;
3720 /* depending on the type of pointer we need to
3721 move it to the correct pointer register */
3722 type = operandType(left);
3723 etype = getSpec(type);
3725 genGenPointerGet (left,result,ic);
3728 bool isRegOrLit(asmop *aop)
3730 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3735 /*-----------------------------------------------------------------*/
3736 /* genGenPointerSet - stores the value into a pointer location */
3737 /*-----------------------------------------------------------------*/
3738 static void genGenPointerSet (operand *right,
3739 operand *result, iCode *ic)
3742 link *retype = getSpec(operandType(right));
3743 PAIR_ID pairId = PAIR_HL;
3745 aopOp(result,ic,FALSE);
3746 aopOp(right,ic,FALSE);
3751 /* Handle the exceptions first */
3752 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3754 char *l = aopGet(AOP(right), 0, FALSE);
3755 const char *pair = getPairName(AOP(result));
3756 if (canAssignToPtr(l) && isPtr(pair)) {
3757 emitcode("ld", "(%s),%s", pair, l);
3761 emitcode("ld", "(%s),a ; 1", pair);
3766 /* if the operand is already in dptr
3767 then we do nothing else we move the value to dptr */
3768 if (AOP_TYPE(result) != AOP_STR) {
3769 fetchPair(pairId, AOP(result));
3771 /* so hl know contains the address */
3772 freeAsmop(result,NULL,ic);
3774 /* if bit then unpack */
3775 if (IS_BITVAR(retype)) {
3779 size = AOP_SIZE(right);
3783 char *l = aopGet(AOP(right),offset,FALSE);
3784 if (isRegOrLit(AOP(right)) && !IS_GB) {
3785 emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
3789 emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
3792 emitcode("inc", _pairs[pairId].name);
3798 freeAsmop(right,NULL,ic);
3801 /*-----------------------------------------------------------------*/
3802 /* genPointerSet - stores the value into a pointer location */
3803 /*-----------------------------------------------------------------*/
3804 static void genPointerSet (iCode *ic)
3806 operand *right, *result ;
3809 right = IC_RIGHT(ic);
3810 result = IC_RESULT(ic) ;
3812 /* depending on the type of pointer we need to
3813 move it to the correct pointer register */
3814 type = operandType(result);
3815 etype = getSpec(type);
3817 genGenPointerSet (right,result,ic);
3820 /*-----------------------------------------------------------------*/
3821 /* genIfx - generate code for Ifx statement */
3822 /*-----------------------------------------------------------------*/
3823 static void genIfx (iCode *ic, iCode *popIc)
3825 operand *cond = IC_COND(ic);
3828 aopOp(cond,ic,FALSE);
3830 /* get the value into acc */
3831 if (AOP_TYPE(cond) != AOP_CRY)
3835 /* the result is now in the accumulator */
3836 freeAsmop(cond,NULL,ic);
3838 /* if there was something to be popped then do it */
3842 /* if the condition is a bit variable */
3843 if (isbit && IS_ITEMP(cond) &&
3845 genIfxJump(ic,SPIL_LOC(cond)->rname);
3847 if (isbit && !IS_ITEMP(cond))
3848 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3855 /*-----------------------------------------------------------------*/
3856 /* genAddrOf - generates code for address of */
3857 /*-----------------------------------------------------------------*/
3858 static void genAddrOf (iCode *ic)
3860 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3862 aopOp(IC_RESULT(ic),ic,FALSE);
3864 /* if the operand is on the stack then we
3865 need to get the stack offset of this
3870 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _G.stack.pushed, _G.stack.offset);
3871 emitcode("ld", "d,h");
3872 emitcode("ld", "e,l");
3875 emitcode("ld", "de,#%s", sym->rname);
3877 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3878 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3883 /* if it has an offset then we need to compute it */
3884 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3885 emitcode("add", "hl,sp");
3888 emitcode("ld", "hl,#%s", sym->rname);
3890 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3891 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3893 freeAsmop(IC_RESULT(ic),NULL,ic);
3896 /*-----------------------------------------------------------------*/
3897 /* genAssign - generate code for assignment */
3898 /*-----------------------------------------------------------------*/
3899 static void genAssign (iCode *ic)
3901 operand *result, *right;
3903 unsigned long lit = 0L;
3905 result = IC_RESULT(ic);
3906 right = IC_RIGHT(ic) ;
3909 /* Dont bother assigning if they are the same */
3910 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3911 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3916 aopOp(right,ic,FALSE);
3917 aopOp(result,ic,TRUE);
3919 /* if they are the same registers */
3920 if (sameRegs(AOP(right),AOP(result))) {
3921 emitcode("", "; (registers are the same)");
3925 /* if the result is a bit */
3926 if (AOP_TYPE(result) == AOP_CRY) {
3931 size = AOP_SIZE(result);
3934 if(AOP_TYPE(right) == AOP_LIT)
3935 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3936 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3937 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3939 else if((size > 1) &&
3940 (AOP_TYPE(result) != AOP_REG) &&
3941 (AOP_TYPE(right) == AOP_LIT) &&
3942 !IS_FLOAT(operandType(right)) &&
3944 bool fXored = FALSE;
3946 /* Work from the top down.
3947 Done this way so that we can use the cached copy of 0
3948 in A for a fast clear */
3950 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3951 if (!fXored && size>1) {
3952 emitcode("xor", "a,a");
3956 aopPut(AOP(result),"a",offset);
3959 aopPut(AOP(result), "#0", offset);
3964 aopGet(AOP(right),offset,FALSE),
3969 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3970 /* Special case. Load into a and d, then load out. */
3971 MOVA(aopGet(AOP(right), 0, FALSE));
3972 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3973 aopPut(AOP(result), "a", 0);
3974 aopPut(AOP(result), "e", 1);
3978 aopGet(AOP(right),offset,FALSE),
3985 freeAsmop(right,NULL,ic);
3986 freeAsmop(result,NULL,ic);
3989 /*-----------------------------------------------------------------*/
3990 /* genJumpTab - genrates code for jump table */
3991 /*-----------------------------------------------------------------*/
3992 static void genJumpTab (iCode *ic)
3997 aopOp(IC_JTCOND(ic),ic,FALSE);
3998 /* get the condition into accumulator */
3999 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4002 emitcode("push", "de");
4003 emitcode("ld", "e,%s", l);
4004 emitcode("ld", "d,#0");
4005 jtab = newiTempLabel(NULL);
4007 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
4008 emitcode("add", "hl,de");
4009 emitcode("add", "hl,de");
4010 emitcode("add", "hl,de");
4011 freeAsmop(IC_JTCOND(ic),NULL,ic);
4013 emitcode("pop", "de");
4014 emitcode("jp", "(hl)");
4015 emitLabel(jtab->key+100);
4016 /* now generate the jump labels */
4017 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4018 jtab = setNextItem(IC_JTLABELS(ic)))
4019 emitcode("jp", LABEL_STR, jtab->key+100);
4022 /*-----------------------------------------------------------------*/
4023 /* genCast - gen code for casting */
4024 /*-----------------------------------------------------------------*/
4025 static void genCast (iCode *ic)
4027 operand *result = IC_RESULT(ic);
4028 link *ctype = operandType(IC_LEFT(ic));
4029 operand *right = IC_RIGHT(ic);
4032 /* if they are equivalent then do nothing */
4033 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4036 aopOp(right,ic,FALSE) ;
4037 aopOp(result,ic,FALSE);
4039 /* if the result is a bit */
4040 if (AOP_TYPE(result) == AOP_CRY) {
4044 /* if they are the same size : or less */
4045 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4047 /* if they are in the same place */
4048 if (sameRegs(AOP(right),AOP(result)))
4051 /* if they in different places then copy */
4052 size = AOP_SIZE(result);
4056 aopGet(AOP(right),offset,FALSE),
4063 /* PENDING: should be OK. */
4065 /* if the result is of type pointer */
4066 if (IS_PTR(ctype)) {
4071 /* so we now know that the size of destination is greater
4072 than the size of the source */
4073 /* we move to result for the size of source */
4074 size = AOP_SIZE(right);
4078 aopGet(AOP(right),offset,FALSE),
4083 /* now depending on the sign of the destination */
4084 size = AOP_SIZE(result) - AOP_SIZE(right);
4085 /* Unsigned or not an integral type - right fill with zeros */
4086 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4088 aopPut(AOP(result),zero,offset++);
4090 /* we need to extend the sign :{ */
4091 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4094 emitcode("", "; genCast: sign extend untested.");
4095 emitcode("rla", "");
4096 emitcode("sbc", "a,a");
4098 aopPut(AOP(result),"a",offset++);
4102 freeAsmop(right, NULL, ic);
4103 freeAsmop(result, NULL, ic);
4106 /*-----------------------------------------------------------------*/
4107 /* genReceive - generate code for a receive iCode */
4108 /*-----------------------------------------------------------------*/
4109 static void genReceive (iCode *ic)
4111 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4112 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4113 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4117 aopOp(IC_RESULT(ic),ic,FALSE);
4119 assignResultValue(IC_RESULT(ic));
4122 freeAsmop(IC_RESULT(ic),NULL,ic);
4125 /*-----------------------------------------------------------------*/
4126 /* genZ80Code - generate code for Z80 based controllers */
4127 /*-----------------------------------------------------------------*/
4128 void genZ80Code (iCode *lic)
4135 _fReturn = _gbz80_return;
4136 _fTmp = _gbz80_return;
4140 _fReturn = _z80_return;
4141 _fTmp = _z80_return;
4145 lineHead = lineCurr = NULL;
4147 /* if debug information required */
4148 if (options.debug && currFunc) {
4149 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4151 if (IS_STATIC(currFunc->etype))
4152 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4154 emitcode("","G$%s$0$0 ==.",currFunc->name);
4157 /* stack pointer name */
4161 for (ic = lic ; ic ; ic = ic->next ) {
4163 if ( cln != ic->lineno ) {
4164 if ( options.debug ) {
4166 emitcode("","C$%s$%d$%d$%d ==.",
4167 ic->filename,ic->lineno,
4168 ic->level,ic->block);
4171 emitcode(";","%s %d",ic->filename,ic->lineno);
4174 /* if the result is marked as
4175 spilt and rematerializable or code for
4176 this has already been generated then
4178 if (resultRemat(ic) || ic->generated )
4181 /* depending on the operation */
4184 emitcode("", "; genNot");
4189 emitcode("", "; genCpl");
4194 emitcode("", "; genUminus");
4199 emitcode("", "; genIpush");
4204 /* IPOP happens only when trying to restore a
4205 spilt live range, if there is an ifx statement
4206 following this pop then the if statement might
4207 be using some of the registers being popped which
4208 would destory the contents of the register so
4209 we need to check for this condition and handle it */
4211 ic->next->op == IFX &&
4212 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4213 emitcode("", "; genIfx");
4214 genIfx (ic->next,ic);
4217 emitcode("", "; genIpop");
4223 emitcode("", "; genCall");
4228 emitcode("", "; genPcall");
4233 emitcode("", "; genFunction");
4238 emitcode("", "; genEndFunction");
4239 genEndFunction (ic);
4243 emitcode("", "; genRet");
4248 emitcode("", "; genLabel");
4253 emitcode("", "; genGoto");
4258 emitcode("", "; genPlus");
4263 emitcode("", "; genMinus");
4268 emitcode("", "; genMult");
4273 emitcode("", "; genDiv");
4278 emitcode("", "; genMod");
4283 emitcode("", "; genCmpGt");
4284 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4288 emitcode("", "; genCmpLt");
4289 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4296 /* note these two are xlated by algebraic equivalence
4297 during parsing SDCC.y */
4298 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4299 "got '>=' or '<=' shouldn't have come here");
4303 emitcode("", "; genCmpEq");
4304 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4308 emitcode("", "; genAndOp");
4313 emitcode("", "; genOrOp");
4318 emitcode("", "; genXor");
4319 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4323 emitcode("", "; genOr");
4324 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4328 emitcode("", "; genAnd");
4329 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4333 emitcode("", "; genInline");
4338 emitcode("", "; genRRC");
4343 emitcode("", "; genRLC");
4348 emitcode("", "; genHBIT");
4352 emitcode("", "; genLeftShift");
4357 emitcode("", "; genRightShift");
4361 case GET_VALUE_AT_ADDRESS:
4362 emitcode("", "; genPointerGet");
4368 if (POINTER_SET(ic)) {
4369 emitcode("", "; genAssign (pointer)");
4373 emitcode("", "; genAssign");
4379 emitcode("", "; genIfx");
4384 emitcode("", "; genAddrOf");
4389 emitcode("", "; genJumpTab");
4394 emitcode("", "; genCast");
4399 emitcode("", "; genReceive");
4404 emitcode("", "; addSet");
4405 addSet(&sendSet,ic);
4410 /* piCode(ic,stdout); */
4416 /* now we are ready to call the
4417 peep hole optimizer */
4418 if (!options.nopeep)
4419 peepHole (&lineHead);
4421 /* now do the actual printing */
4422 printLine (lineHead,codeOutFile);