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
19 Michael Hope <michaelh@earthling.net> 2000
20 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
21 and - Jean-Louis VERN.jlvern@writeme.com (1999)
23 This program is free software; you can redistribute it and/or modify it
24 under the terms of the GNU General Public License as published by the
25 Free Software Foundation; either version 2, or (at your option) any
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program; if not, write to the Free Software
35 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 In other words, you are welcome to use, share and improve this program.
38 You are forbidden to forbid anyone else to use, share and improve
39 what you give them. Help stamp out software-hoarding!
41 -------------------------------------------------------------------------*/
47 #include "SDCCglobl.h"
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
56 #include "SDCChasht.h"
59 #include "SDCCicode.h"
60 #include "SDCClabel.h"
61 #include "SDCCBBlock.h"
64 #include "SDCCcflow.h"
65 #include "SDCCdflow.h"
66 #include "SDCClrange.h"
69 #include "SDCCpeeph.h"
70 #include "SDCCglue.h" /* drdani Jan 30 2000 */
72 /* this is the down and dirty file with all kinds of kludgy & hacky
73 stuff. This is what it is all about CODE GENERATION for a specific MCU.
74 Some of the routines may be reusable, will have to see */
76 static char *zero = "#0x00";
77 static char *one = "#0x01";
79 static char *fReturn[] = {"l", "h", "e", "d" };
80 static char *accUse[] = {"a" };
86 extern int ptrRegReq ;
88 extern FILE *codeOutFile;
90 #define RESULTONSTACK(x) \
91 (IC_RESULT(x) && IC_RESULT(x)->aop && \
92 IC_RESULT(x)->aop->type == AOP_STK )
94 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
95 #define CLRC emitcode("xor","a,a");
97 #define LABEL_STR "%05d$"
99 lineNode *lineHead = NULL;
100 lineNode *lineCurr = NULL;
102 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
103 0xE0, 0xC0, 0x80, 0x00};
104 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105 0x07, 0x03, 0x01, 0x00};
107 static int _lastStack = 0;
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
125 void emitcode (const char *inst, const char *fmt, ...)
128 char lb[MAX_INLINEASM];
134 sprintf(lb,"%s\t",inst);
135 vsprintf(lb+(strlen(lb)),fmt,ap);
139 while (isspace(*lbp)) lbp++;
142 lineCurr = (lineCurr ?
143 connectLine(lineCurr,newLineNode(lb)) :
144 (lineHead = newLineNode(lb)));
145 lineCurr->isInline = inLine;
146 lineCurr->isDebug = debugLine;
150 const char *getPairName(asmop *aop)
152 if (aop->type == AOP_REG) {
153 switch (aop->aopu.aop_reg[0]->rIdx) {
165 else if (aop->type == AOP_STR) {
166 switch (*aop->aopu.aop_str[0]) {
182 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
183 bool isPair(asmop *aop)
185 if (aop->size == 2) {
186 if (aop->type == AOP_REG) {
187 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
190 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
193 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
197 if (aop->type == AOP_STR) {
198 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
201 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
204 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
212 /** Push a register pair onto the stack */
213 void genPairPush(asmop *aop)
215 emitcode("push", "%s", getPairName(aop));
218 /*-----------------------------------------------------------------*/
219 /* newAsmop - creates a new asmOp */
220 /*-----------------------------------------------------------------*/
221 static asmop *newAsmop (short type)
225 ALLOC(aop,sizeof(asmop));
230 /*-----------------------------------------------------------------*/
231 /* aopForSym - for a true symbol */
232 /*-----------------------------------------------------------------*/
233 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
236 memmap *space= SPEC_OCLS(sym->etype);
238 /* if already has one */
242 /* Assign depending on the storage class */
243 if (sym->onStack || sym->iaccess) {
244 sym->aop = aop = newAsmop(AOP_STK);
245 aop->size = getSize(sym->type);
247 aop->aopu.aop_stk = sym->stack;
251 /* special case for a function */
252 if (IS_FUNC(sym->type)) {
253 sym->aop = aop = newAsmop(AOP_IMMD);
254 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
255 strcpy(aop->aopu.aop_immd,sym->rname);
260 /* only remaining is far space */
261 /* in which case DPTR gets the address */
262 sym->aop = aop = newAsmop(AOP_IY);
263 emitcode ("ld","iy,#%s", sym->rname);
264 aop->size = getSize(sym->type);
265 aop->aopu.aop_dir = sym->rname;
267 /* if it is in code space */
268 if (IN_CODESPACE(space))
274 /*-----------------------------------------------------------------*/
275 /* aopForRemat - rematerialzes an object */
276 /*-----------------------------------------------------------------*/
277 static asmop *aopForRemat (symbol *sym)
280 iCode *ic = sym->rematiCode;
281 asmop *aop = newAsmop(AOP_IMMD);
284 /* if plus or minus print the right hand side */
285 if (ic->op == '+' || ic->op == '-') {
286 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
289 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
292 /* we reached the end */
293 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
297 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
298 strcpy(aop->aopu.aop_immd,buffer);
302 /*-----------------------------------------------------------------*/
303 /* regsInCommon - two operands have some registers in common */
304 /*-----------------------------------------------------------------*/
305 bool regsInCommon (operand *op1, operand *op2)
310 /* if they have registers in common */
311 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
314 sym1 = OP_SYMBOL(op1);
315 sym2 = OP_SYMBOL(op2);
317 if (sym1->nRegs == 0 || sym2->nRegs == 0)
320 for (i = 0 ; i < sym1->nRegs ; i++) {
325 for (j = 0 ; j < sym2->nRegs ;j++ ) {
329 if (sym2->regs[j] == sym1->regs[i])
337 /*-----------------------------------------------------------------*/
338 /* operandsEqu - equivalent */
339 /*-----------------------------------------------------------------*/
340 bool operandsEqu ( operand *op1, operand *op2)
344 /* if they not symbols */
345 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
348 sym1 = OP_SYMBOL(op1);
349 sym2 = OP_SYMBOL(op2);
351 /* if both are itemps & one is spilt
352 and the other is not then false */
353 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
354 sym1->isspilt != sym2->isspilt )
357 /* if they are the same */
361 if (strcmp(sym1->rname,sym2->rname) == 0)
365 /* if left is a tmp & right is not */
369 (sym1->usl.spillLoc == sym2))
376 (sym2->usl.spillLoc == sym1))
382 /*-----------------------------------------------------------------*/
383 /* sameRegs - two asmops have the same registers */
384 /*-----------------------------------------------------------------*/
385 bool sameRegs (asmop *aop1, asmop *aop2 )
392 if (aop1->type != AOP_REG ||
393 aop2->type != AOP_REG )
396 if (aop1->size != aop2->size)
399 for (i = 0 ; i < aop1->size ; i++ )
400 if (aop1->aopu.aop_reg[i] !=
401 aop2->aopu.aop_reg[i] )
407 /*-----------------------------------------------------------------*/
408 /* aopOp - allocates an asmop for an operand : */
409 /*-----------------------------------------------------------------*/
410 static void aopOp (operand *op, iCode *ic, bool result)
419 /* if this a literal */
420 if (IS_OP_LITERAL(op)) {
421 op->aop = aop = newAsmop(AOP_LIT);
422 aop->aopu.aop_lit = op->operand.valOperand;
423 aop->size = getSize(operandType(op));
427 /* if already has a asmop then continue */
431 /* if the underlying symbol has a aop */
432 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
433 op->aop = OP_SYMBOL(op)->aop;
437 /* if this is a true symbol */
438 if (IS_TRUE_SYMOP(op)) {
439 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
443 /* this is a temporary : this has
449 e) can be a return use only */
453 /* if the type is a conditional */
454 if (sym->regType == REG_CND) {
455 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
460 /* if it is spilt then two situations
462 b) has a spill location */
463 if (sym->isspilt || sym->nRegs == 0) {
464 /* rematerialize it NOW */
466 sym->aop = op->aop = aop =
468 aop->size = getSize(sym->type);
474 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
475 aop->size = getSize(sym->type);
476 for ( i = 0 ; i < 2 ; i++ )
477 aop->aopu.aop_str[i] = accUse[i];
483 aop = op->aop = sym->aop = newAsmop(AOP_STR);
484 aop->size = getSize(sym->type);
485 for ( i = 0 ; i < 4 ; i++ )
486 aop->aopu.aop_str[i] = fReturn[i];
490 /* else spill location */
491 sym->aop = op->aop = aop =
492 aopForSym(ic,sym->usl.spillLoc,result);
493 aop->size = getSize(sym->type);
497 /* must be in a register */
498 sym->aop = op->aop = aop = newAsmop(AOP_REG);
499 aop->size = sym->nRegs;
500 for ( i = 0 ; i < sym->nRegs ;i++)
501 aop->aopu.aop_reg[i] = sym->regs[i];
504 /*-----------------------------------------------------------------*/
505 /* freeAsmop - free up the asmop given to an operand */
506 /*----------------------------------------------------------------*/
507 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
530 /* all other cases just dealloc */
534 OP_SYMBOL(op)->aop = NULL;
535 /* if the symbol has a spill */
537 SPIL_LOC(op)->aop = NULL;
542 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
551 /* depending on type */
554 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
555 ALLOC_ATOMIC(rs,strlen(s)+1);
560 value * val = aop->aopu.aop_lit;
561 /* if it is a float then it gets tricky */
562 /* otherwise it is fairly simple */
563 if (!IS_FLOAT(val->type)) {
564 unsigned long v = floatFromVal(val);
566 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
567 ALLOC_ATOMIC(rs,strlen(buffer)+1);
568 return strcpy (rs,buffer);
577 char *aopGetWord(asmop *aop, int offset)
579 return aopGetWordLong(aop, offset, TRUE);
582 /*-----------------------------------------------------------------*/
583 /* aopGet - for fetching value of the aop */
584 /*-----------------------------------------------------------------*/
585 static char *aopGet (asmop *aop, int offset, bool bit16)
590 /* offset is greater than size then zero */
591 if (offset > (aop->size - 1) &&
592 aop->type != AOP_LIT)
595 /* depending on type */
599 sprintf (s,"#%s",aop->aopu.aop_immd);
609 ALLOC_ATOMIC(rs,strlen(s)+1);
615 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
617 ALLOC_ATOMIC(rs,strlen(s)+1);
622 return aop->aopu.aop_reg[offset]->name;
625 sprintf(s,"%d(iy)", offset);
626 ALLOC_ATOMIC(rs,strlen(s)+1);
631 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
632 ALLOC_ATOMIC(rs,strlen(s)+1);
646 return aopLiteral (aop->aopu.aop_lit,offset);
650 return aop->aopu.aop_str[offset];
653 fprintf(stderr, "Type %u\n", aop->type);
655 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
656 "aopget got unsupported aop->type");
660 bool isRegString(char *s)
662 if (!strcmp(s, "b") ||
673 bool isConstant(char *s)
678 bool canAssignToPtr(char *s)
687 /*-----------------------------------------------------------------*/
688 /* aopPut - puts a string for a aop */
689 /*-----------------------------------------------------------------*/
690 static void aopPut (asmop *aop, char *s, int offset)
694 if (aop->size && offset > ( aop->size - 1)) {
695 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
696 "aopPut got offset > aop->size");
700 /* will assign value to value */
701 /* depending on where it is ofcourse */
706 emitcode("ld", "a,%s", s);
707 emitcode("ld", "(%s+%d),a", d, offset);
711 /* Dont bother if it's a ld x,x */
712 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
713 emitcode("ld","%s,%s",
714 aop->aopu.aop_reg[offset]->name,s);
719 if (!canAssignToPtr(s)) {
720 emitcode("ld", "a,%s", s);
721 emitcode("ld", "%d(iy),a", offset);
724 emitcode("ld", "%d(iy),%s", offset, s);
728 if (!canAssignToPtr(s)) {
729 emitcode("ld", "a,%s", s);
730 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
733 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
737 /* if bit variable */
738 if (!aop->aopu.aop_dir) {
739 emitcode("ld", "a,#0");
742 /* In bit space but not in C - cant happen */
749 if (strcmp(aop->aopu.aop_str[offset],s)) {
750 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
756 if (!offset && (strcmp(s,"acc") == 0))
760 emitcode("", "; Error aopPut AOP_ACC");
763 if (strcmp(aop->aopu.aop_str[offset],s))
764 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
769 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
770 "aopPut got unsupported aop->type");
775 #define AOP(op) op->aop
776 #define AOP_TYPE(op) AOP(op)->type
777 #define AOP_SIZE(op) AOP(op)->size
778 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
780 /*-----------------------------------------------------------------*/
781 /* getDataSize - get the operand data size */
782 /*-----------------------------------------------------------------*/
783 int getDataSize(operand *op)
794 /*-----------------------------------------------------------------*/
795 /* movLeft2Result - move byte from left to result */
796 /*-----------------------------------------------------------------*/
797 static void movLeft2Result (operand *left, int offl,
798 operand *result, int offr, int sign)
801 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
802 l = aopGet(AOP(left),offl,FALSE);
805 aopPut(AOP(result),l,offr);
814 /** Put Acc into a register set
816 void outAcc(operand *result)
819 size = getDataSize(result);
821 aopPut(AOP(result),"a",0);
824 /* unsigned or positive */
826 aopPut(AOP(result),zero,offset++);
831 /** Take the value in carry and put it into a register
833 void outBitC(operand *result)
835 /* if the result is bit */
836 if (AOP_TYPE(result) == AOP_CRY) {
837 emitcode("", "; Note: outBitC form 1");
838 aopPut(AOP(result),"blah",0);
841 emitcode("ld", "a,#0");
847 /*-----------------------------------------------------------------*/
848 /* toBoolean - emit code for orl a,operator(sizeop) */
849 /*-----------------------------------------------------------------*/
850 void toBoolean(operand *oper)
852 int size = AOP_SIZE(oper);
855 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
858 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
862 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
866 /*-----------------------------------------------------------------*/
867 /* genNot - generate code for ! operation */
868 /*-----------------------------------------------------------------*/
869 static void genNot (iCode *ic)
871 link *optype = operandType(IC_LEFT(ic));
873 /* assign asmOps to operand & result */
874 aopOp (IC_LEFT(ic),ic,FALSE);
875 aopOp (IC_RESULT(ic),ic,TRUE);
877 /* if in bit space then a special case */
878 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
882 /* if type float then do float */
883 if (IS_FLOAT(optype)) {
887 toBoolean(IC_LEFT(ic));
892 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
893 emitcode("sub", "a,#0x01");
894 outBitC(IC_RESULT(ic));
896 /* release the aops */
897 freeAsmop(IC_LEFT(ic),NULL,ic);
898 freeAsmop(IC_RESULT(ic),NULL,ic);
901 /*-----------------------------------------------------------------*/
902 /* genCpl - generate code for complement */
903 /*-----------------------------------------------------------------*/
904 static void genCpl (iCode *ic)
910 /* assign asmOps to operand & result */
911 aopOp (IC_LEFT(ic),ic,FALSE);
912 aopOp (IC_RESULT(ic),ic,TRUE);
914 /* if both are in bit space then
916 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
917 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
921 size = AOP_SIZE(IC_RESULT(ic));
923 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
926 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
929 /* release the aops */
930 freeAsmop(IC_LEFT(ic),NULL,ic);
931 freeAsmop(IC_RESULT(ic),NULL,ic);
934 /*-----------------------------------------------------------------*/
935 /* genUminus - unary minus code generation */
936 /*-----------------------------------------------------------------*/
937 static void genUminus (iCode *ic)
940 link *optype, *rtype;
943 aopOp(IC_LEFT(ic),ic,FALSE);
944 aopOp(IC_RESULT(ic),ic,TRUE);
946 /* if both in bit space then special
948 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
949 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
954 optype = operandType(IC_LEFT(ic));
955 rtype = operandType(IC_RESULT(ic));
957 /* if float then do float stuff */
958 if (IS_FLOAT(optype)) {
963 /* otherwise subtract from zero */
964 size = AOP_SIZE(IC_LEFT(ic));
968 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
969 emitcode("ld", "a,#0");
970 emitcode("sbc","a,%s",l);
971 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
974 /* if any remaining bytes in the result */
975 /* we just need to propagate the sign */
976 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
978 emitcode("sbc","a,a");
980 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
984 /* release the aops */
985 freeAsmop(IC_LEFT(ic),NULL,ic);
986 freeAsmop(IC_RESULT(ic),NULL,ic);
990 /*-----------------------------------------------------------------*/
991 /* assignResultValue - */
992 /*-----------------------------------------------------------------*/
993 void assignResultValue(operand * oper)
996 int size = AOP_SIZE(oper);
998 aopPut(AOP(oper),fReturn[offset],offset);
1003 /*-----------------------------------------------------------------*/
1004 /* genIpush - genrate code for pushing this gets a little complex */
1005 /*-----------------------------------------------------------------*/
1006 static void genIpush (iCode *ic)
1008 int size, offset = 0 ;
1012 /* if this is not a parm push : ie. it is spill push
1013 and spill push is always done on the local stack */
1014 if (!ic->parmPush) {
1015 /* and the item is spilt then do nothing */
1016 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1019 aopOp(IC_LEFT(ic),ic,FALSE);
1020 size = AOP_SIZE(IC_LEFT(ic));
1021 /* push it on the stack */
1022 if (isPair(AOP(IC_LEFT(ic)))) {
1023 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1028 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1029 /* Simple for now - load into A and PUSH AF */
1030 emitcode("ld", "a,%s", l);
1031 emitcode("push", "af");
1032 emitcode("inc", "sp");
1038 /* Hmmm... what about saving the currently used registers
1041 /* then do the push */
1042 aopOp(IC_LEFT(ic),ic,FALSE);
1044 size = AOP_SIZE(IC_LEFT(ic));
1046 if (isPair(AOP(IC_LEFT(ic)))) {
1047 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1051 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1053 emitcode("ld", "hl,%s", s);
1054 emitcode("push", "hl");
1057 /* Optimise here - load into HL then push HL */
1058 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
1059 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
1060 emitcode("push", "hl");
1066 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1067 emitcode("ld", "a,%s", l);
1068 emitcode("push", "af");
1069 emitcode("inc", "sp");
1073 freeAsmop(IC_LEFT(ic),NULL,ic);
1076 /*-----------------------------------------------------------------*/
1077 /* genIpop - recover the registers: can happen only for spilling */
1078 /*-----------------------------------------------------------------*/
1079 static void genIpop (iCode *ic)
1084 /* if the temp was not pushed then */
1085 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1088 aopOp(IC_LEFT(ic),ic,FALSE);
1089 size = AOP_SIZE(IC_LEFT(ic));
1091 if (isPair(AOP(IC_LEFT(ic)))) {
1092 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1096 emitcode("dec", "sp");
1097 emitcode("pop", "hl");
1098 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1102 freeAsmop(IC_LEFT(ic),NULL,ic);
1105 /** Emit the code for a call statement
1107 static void emitCall (iCode *ic, bool ispcall)
1109 /* if caller saves & we have not saved then */
1110 if (!ic->regsSaved) {
1114 /* if send set is not empty then assign */
1118 for (sic = setFirstItem(sendSet) ; sic ;
1119 sic = setNextItem(sendSet)) {
1120 int size, offset = 0;
1121 aopOp(IC_LEFT(sic),sic,FALSE);
1122 size = AOP_SIZE(IC_LEFT(sic));
1124 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1126 if (strcmp(l,fReturn[offset]))
1127 emitcode("ld","%s,%s",
1132 freeAsmop (IC_LEFT(sic),NULL,sic);
1138 symbol *rlbl = newiTempLabel(NULL);
1140 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1141 emitcode("push", "hl");
1143 aopOp(IC_LEFT(ic),ic,FALSE);
1144 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1145 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1146 freeAsmop(IC_LEFT(ic),NULL,ic);
1148 emitcode("jp", "(hl)");
1149 emitcode("","%05d$:",(rlbl->key+100));
1153 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1154 OP_SYMBOL(IC_LEFT(ic))->rname :
1155 OP_SYMBOL(IC_LEFT(ic))->name));
1158 /* if we need assign a result value */
1159 if ((IS_ITEMP(IC_RESULT(ic)) &&
1160 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1161 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1162 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1165 aopOp(IC_RESULT(ic),ic,FALSE);
1168 assignResultValue(IC_RESULT(ic));
1170 freeAsmop(IC_RESULT(ic),NULL, ic);
1173 /* adjust the stack for parameters if required */
1174 if (IC_LEFT(ic)->parmBytes) {
1175 int i = IC_LEFT(ic)->parmBytes;
1177 emitcode("ld", "hl,#%d", i);
1178 emitcode("add", "hl,sp");
1179 emitcode("ld", "sp,hl");
1183 emitcode("pop", "hl");
1187 emitcode("inc", "sp");
1193 /*-----------------------------------------------------------------*/
1194 /* genCall - generates a call statement */
1195 /*-----------------------------------------------------------------*/
1196 static void genCall (iCode *ic)
1198 emitCall(ic, FALSE);
1201 /*-----------------------------------------------------------------*/
1202 /* genPcall - generates a call by pointer statement */
1203 /*-----------------------------------------------------------------*/
1204 static void genPcall (iCode *ic)
1209 /*-----------------------------------------------------------------*/
1210 /* resultRemat - result is rematerializable */
1211 /*-----------------------------------------------------------------*/
1212 static int resultRemat (iCode *ic)
1214 if (SKIP_IC(ic) || ic->op == IFX)
1217 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1218 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1219 if (sym->remat && !POINTER_SET(ic))
1226 /*-----------------------------------------------------------------*/
1227 /* genFunction - generated code for function entry */
1228 /*-----------------------------------------------------------------*/
1229 static void genFunction (iCode *ic)
1235 /* create the function header */
1236 emitcode(";","-----------------------------------------");
1237 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1238 emitcode(";","-----------------------------------------");
1240 emitcode("","%s:",sym->rname);
1241 fetype = getSpec(operandType(IC_LEFT(ic)));
1243 /* if critical function then turn interrupts off */
1244 if (SPEC_CRTCL(fetype))
1247 /* if this is an interrupt service routine then
1248 save acc, b, dpl, dph */
1249 if (IS_ISR(sym->etype)) {
1250 emitcode("push", "af");
1251 emitcode("push", "bc");
1252 emitcode("push", "de");
1253 emitcode("push", "hl");
1255 /* PENDING: callee-save etc */
1257 /* adjust the stack for the function */
1258 emitcode("push", "de");
1259 emitcode("push", "bc");
1260 emitcode("push", "ix");
1261 emitcode("ld", "ix,#0");
1262 emitcode("add", "ix,sp");
1264 _lastStack = sym->stack;
1267 emitcode("ld", "hl,#-%d", sym->stack);
1268 emitcode("add", "hl,sp");
1269 emitcode("ld", "sp,hl");
1273 /*-----------------------------------------------------------------*/
1274 /* genEndFunction - generates epilogue for functions */
1275 /*-----------------------------------------------------------------*/
1276 static void genEndFunction (iCode *ic)
1278 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1280 if (IS_ISR(sym->etype)) {
1284 if (SPEC_CRTCL(sym->etype))
1287 /* PENDING: calleeSave */
1289 /* if debug then send end of function */
1290 if (options.debug && currFunc) {
1292 emitcode("","C$%s$%d$%d$%d ==.",
1293 ic->filename,currFunc->lastLine,
1294 ic->level,ic->block);
1295 if (IS_STATIC(currFunc->etype))
1296 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1298 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1301 emitcode("ld", "sp,ix");
1302 emitcode("pop", "ix");
1303 emitcode("pop", "bc");
1304 emitcode("pop", "de");
1305 emitcode("ret", "");
1310 /*-----------------------------------------------------------------*/
1311 /* genRet - generate code for return statement */
1312 /*-----------------------------------------------------------------*/
1313 static void genRet (iCode *ic)
1316 /* Errk. This is a hack until I can figure out how
1317 to cause dehl to spill on a call */
1318 int size,offset = 0;
1320 /* if we have no return value then
1321 just generate the "ret" */
1325 /* we have something to return then
1326 move the return value into place */
1327 aopOp(IC_LEFT(ic),ic,FALSE);
1328 size = AOP_SIZE(IC_LEFT(ic));
1330 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1331 emitcode("ld", "hl,%s", l);
1335 l = aopGet(AOP(IC_LEFT(ic)),offset,
1337 if (strcmp(fReturn[offset],l))
1338 emitcode("ld","%s,%s",fReturn[offset++],l);
1341 freeAsmop (IC_LEFT(ic),NULL,ic);
1344 /* generate a jump to the return label
1345 if the next is not the return statement */
1346 if (!(ic->next && ic->next->op == LABEL &&
1347 IC_LABEL(ic->next) == returnLabel))
1349 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1352 /*-----------------------------------------------------------------*/
1353 /* genLabel - generates a label */
1354 /*-----------------------------------------------------------------*/
1355 static void genLabel (iCode *ic)
1357 /* special case never generate */
1358 if (IC_LABEL(ic) == entryLabel)
1361 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1364 /*-----------------------------------------------------------------*/
1365 /* genGoto - generates a ljmp */
1366 /*-----------------------------------------------------------------*/
1367 static void genGoto (iCode *ic)
1369 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1372 /*-----------------------------------------------------------------*/
1373 /* genPlusIncr :- does addition with increment if possible */
1374 /*-----------------------------------------------------------------*/
1375 static bool genPlusIncr (iCode *ic)
1377 unsigned int icount ;
1378 unsigned int size = getDataSize(IC_RESULT(ic));
1380 /* will try to generate an increment */
1381 /* if the right side is not a literal
1383 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1386 emitcode("", "; genPlusIncr");
1388 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1390 /* If result is a pair */
1391 if (isPair(AOP(IC_RESULT(ic)))) {
1392 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1394 /* Both a lit on the right and a true symbol on the left */
1395 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1400 /* if the literal value of the right hand side
1401 is greater than 4 then it is not worth it */
1406 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1407 isPair(AOP(IC_RESULT(ic)))) {
1409 emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
1413 /* if increment 16 bits in register */
1414 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1417 symbol *tlbl = newiTempLabel(NULL);
1418 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1419 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1421 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1425 emitcode("", LABEL_STR ":",tlbl->key+100);
1429 /* If result is a pair */
1430 if (isPair(AOP(IC_RESULT(ic)))) {
1431 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1432 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1434 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1438 /* if the sizes are greater than 1 then we cannot */
1439 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1440 AOP_SIZE(IC_LEFT(ic)) > 1 )
1443 /* we can if the aops of the left & result match or
1444 if they are in registers and the registers are the
1446 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1448 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1456 /*-----------------------------------------------------------------*/
1457 /* outBitAcc - output a bit in acc */
1458 /*-----------------------------------------------------------------*/
1459 void outBitAcc(operand *result)
1461 symbol *tlbl = newiTempLabel(NULL);
1462 /* if the result is a bit */
1463 if (AOP_TYPE(result) == AOP_CRY){
1467 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1468 emitcode("ld","a,%s",one);
1469 emitcode("", LABEL_STR ":",tlbl->key+100);
1474 /*-----------------------------------------------------------------*/
1475 /* genPlus - generates code for addition */
1476 /*-----------------------------------------------------------------*/
1477 static void genPlus (iCode *ic)
1479 int size, offset = 0;
1481 /* special cases :- */
1483 aopOp (IC_LEFT(ic),ic,FALSE);
1484 aopOp (IC_RIGHT(ic),ic,FALSE);
1485 aopOp (IC_RESULT(ic),ic,TRUE);
1487 /* Swap the left and right operands if:
1489 if literal, literal on the right or
1490 if left requires ACC or right is already
1493 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1494 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1495 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1496 operand *t = IC_RIGHT(ic);
1497 IC_RIGHT(ic) = IC_LEFT(ic);
1501 /* if both left & right are in bit
1503 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1504 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1509 /* if left in bit space & right literal */
1510 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1511 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1512 /* Can happen I guess */
1516 /* if I can do an increment instead
1517 of add then GOOD for ME */
1518 if (genPlusIncr (ic) == TRUE)
1521 size = getDataSize(IC_RESULT(ic));
1523 /* Special case when left and right are constant */
1524 if (isPair(AOP(IC_RESULT(ic)))) {
1527 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1528 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1529 if (left && right) {
1533 sprintf(buffer, "#(%s + %s)", left, right);
1534 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1540 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1541 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1543 emitcode("add","a,%s",
1544 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1546 emitcode("adc","a,%s",
1547 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1549 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1551 emitcode("add","a,%s",
1552 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1554 emitcode("adc","a,%s",
1555 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1557 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1560 /* Some kind of pointer arith. */
1561 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1562 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1563 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1566 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1567 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1568 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1573 freeAsmop(IC_LEFT(ic),NULL,ic);
1574 freeAsmop(IC_RIGHT(ic),NULL,ic);
1575 freeAsmop(IC_RESULT(ic),NULL,ic);
1579 /*-----------------------------------------------------------------*/
1580 /* genMinusDec :- does subtraction with deccrement if possible */
1581 /*-----------------------------------------------------------------*/
1582 static bool genMinusDec (iCode *ic)
1584 unsigned int icount ;
1585 unsigned int size = getDataSize(IC_RESULT(ic));
1587 /* will try to generate an increment */
1588 /* if the right side is not a literal we cannot */
1589 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1592 /* if the literal value of the right hand side
1593 is greater than 4 then it is not worth it */
1594 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1597 size = getDataSize(IC_RESULT(ic));
1598 /* if decrement 16 bits in register */
1599 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1600 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1602 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1606 /* If result is a pair */
1607 if (isPair(AOP(IC_RESULT(ic)))) {
1608 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1609 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1611 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1615 /* if the sizes are greater than 1 then we cannot */
1616 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1617 AOP_SIZE(IC_LEFT(ic)) > 1 )
1620 /* we can if the aops of the left & result match or if they are in
1621 registers and the registers are the same */
1622 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1624 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1631 /*-----------------------------------------------------------------*/
1632 /* genMinus - generates code for subtraction */
1633 /*-----------------------------------------------------------------*/
1634 static void genMinus (iCode *ic)
1636 int size, offset = 0;
1637 unsigned long lit = 0L;
1639 aopOp (IC_LEFT(ic),ic,FALSE);
1640 aopOp (IC_RIGHT(ic),ic,FALSE);
1641 aopOp (IC_RESULT(ic),ic,TRUE);
1643 /* special cases :- */
1644 /* if both left & right are in bit space */
1645 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1646 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1651 /* if I can do an decrement instead of subtract then GOOD for ME */
1652 if (genMinusDec (ic) == TRUE)
1655 size = getDataSize(IC_RESULT(ic));
1657 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1660 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1665 /* if literal, add a,#-lit, else normal subb */
1667 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1668 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1670 emitcode("sub","a,%s",
1671 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1673 emitcode("sbc","a,%s",
1674 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1677 /* first add without previous c */
1679 emitcode("add","a,#0x%02x",
1680 (unsigned int)(lit & 0x0FFL));
1682 emitcode("adc","a,#0x%02x",
1683 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1685 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1688 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1689 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1690 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1694 freeAsmop(IC_LEFT(ic),NULL,ic);
1695 freeAsmop(IC_RIGHT(ic),NULL,ic);
1696 freeAsmop(IC_RESULT(ic),NULL,ic);
1699 /*-----------------------------------------------------------------*/
1700 /* genMult - generates code for multiplication */
1701 /*-----------------------------------------------------------------*/
1702 static void genMult (iCode *ic)
1704 /* Shouldn't occur - all done through function calls */
1708 /*-----------------------------------------------------------------*/
1709 /* genDiv - generates code for division */
1710 /*-----------------------------------------------------------------*/
1711 static void genDiv (iCode *ic)
1713 /* Shouldn't occur - all done through function calls */
1717 /*-----------------------------------------------------------------*/
1718 /* genMod - generates code for division */
1719 /*-----------------------------------------------------------------*/
1720 static void genMod (iCode *ic)
1722 /* Shouldn't occur - all done through function calls */
1726 /*-----------------------------------------------------------------*/
1727 /* genIfxJump :- will create a jump depending on the ifx */
1728 /*-----------------------------------------------------------------*/
1729 static void genIfxJump (iCode *ic, char *jval)
1734 /* if true label then we jump if condition
1736 if ( IC_TRUE(ic) ) {
1738 if (!strcmp(jval, "a")) {
1741 else if (!strcmp(jval, "c")) {
1745 /* The buffer contains the bit on A that we should test */
1750 /* false label is present */
1751 jlbl = IC_FALSE(ic) ;
1752 if (!strcmp(jval, "a")) {
1755 else if (!strcmp(jval, "c")) {
1759 /* The buffer contains the bit on A that we should test */
1763 /* Z80 can do a conditional long jump */
1764 if (!strcmp(jval, "a")) {
1765 emitcode("or", "a,a");
1767 else if (!strcmp(jval, "c")) {
1770 emitcode("bit", "%s,a", jval);
1772 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1774 /* mark the icode as generated */
1778 /** Generic compare for > or <
1780 static void genCmp (operand *left,operand *right,
1781 operand *result, iCode *ifx, int sign)
1783 int size, offset = 0 ;
1784 unsigned long lit = 0L;
1786 /* if left & right are bit variables */
1787 if (AOP_TYPE(left) == AOP_CRY &&
1788 AOP_TYPE(right) == AOP_CRY ) {
1789 /* Cant happen on the Z80 */
1792 /* subtract right from left if at the
1793 end the carry flag is set then we know that
1794 left is greater than right */
1795 size = max(AOP_SIZE(left),AOP_SIZE(right));
1797 /* if unsigned char cmp with lit, just compare */
1799 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1800 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1802 emitcode("xor", "a,#0x80");
1803 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1806 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1809 if(AOP_TYPE(right) == AOP_LIT) {
1810 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1811 /* optimize if(x < 0) or if(x >= 0) */
1814 /* No sign so it's always false */
1818 /* Just load in the top most bit */
1819 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1820 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1821 genIfxJump (ifx,"7");
1825 emitcode("rlc","a");
1831 /* First setup h and l contaning the top most bytes XORed */
1832 bool fDidXor = FALSE;
1833 if (AOP_TYPE(left) == AOP_LIT){
1834 unsigned long lit = (unsigned long)
1835 floatFromVal(AOP(left)->aopu.aop_lit);
1836 emitcode("ld", "l,#0x%02x",
1837 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1840 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1841 emitcode("xor", "a,#0x80");
1842 emitcode("ld", "l,a");
1845 if (AOP_TYPE(right) == AOP_LIT) {
1846 unsigned long lit = (unsigned long)
1847 floatFromVal(AOP(right)->aopu.aop_lit);
1848 emitcode("ld", "h,#0x%02x",
1849 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1852 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1853 emitcode("xor", "a,#0x80");
1854 emitcode("ld", "h,a");
1864 /* Do a long subtract */
1866 MOVA(aopGet(AOP(left),offset,FALSE));
1867 if (sign && size == 0) {
1868 emitcode("ld", "a,l");
1869 emitcode("sbc", "a,h");
1872 /* Subtract through, propagating the carry */
1873 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1880 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1883 /* if the result is used in the next
1884 ifx conditional branch then generate
1885 code a little differently */
1887 genIfxJump (ifx,"c");
1890 /* leave the result in acc */
1894 /*-----------------------------------------------------------------*/
1895 /* genCmpGt :- greater than comparison */
1896 /*-----------------------------------------------------------------*/
1897 static void genCmpGt (iCode *ic, iCode *ifx)
1899 operand *left, *right, *result;
1900 link *letype , *retype;
1904 right= IC_RIGHT(ic);
1905 result = IC_RESULT(ic);
1907 letype = getSpec(operandType(left));
1908 retype =getSpec(operandType(right));
1909 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1910 /* assign the amsops */
1911 aopOp (left,ic,FALSE);
1912 aopOp (right,ic,FALSE);
1913 aopOp (result,ic,TRUE);
1915 genCmp(right, left, result, ifx, sign);
1917 freeAsmop(left,NULL,ic);
1918 freeAsmop(right,NULL,ic);
1919 freeAsmop(result,NULL,ic);
1922 /*-----------------------------------------------------------------*/
1923 /* genCmpLt - less than comparisons */
1924 /*-----------------------------------------------------------------*/
1925 static void genCmpLt (iCode *ic, iCode *ifx)
1927 operand *left, *right, *result;
1928 link *letype , *retype;
1932 right= IC_RIGHT(ic);
1933 result = IC_RESULT(ic);
1935 letype = getSpec(operandType(left));
1936 retype =getSpec(operandType(right));
1937 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1939 /* assign the amsops */
1940 aopOp (left,ic,FALSE);
1941 aopOp (right,ic,FALSE);
1942 aopOp (result,ic,TRUE);
1944 genCmp(left, right, result, ifx, sign);
1946 freeAsmop(left,NULL,ic);
1947 freeAsmop(right,NULL,ic);
1948 freeAsmop(result,NULL,ic);
1951 /*-----------------------------------------------------------------*/
1952 /* gencjneshort - compare and jump if not equal */
1953 /*-----------------------------------------------------------------*/
1954 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1956 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1958 unsigned long lit = 0L;
1960 /* Swap the left and right if it makes the computation easier */
1961 if (AOP_TYPE(left) == AOP_LIT) {
1967 if(AOP_TYPE(right) == AOP_LIT)
1968 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1970 /* if the right side is a literal then anything goes */
1971 if (AOP_TYPE(right) == AOP_LIT &&
1972 AOP_TYPE(left) != AOP_DIR ) {
1974 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1975 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1976 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1980 /* if the right side is in a register or in direct space or
1981 if the left is a pointer register & right is not */
1982 else if (AOP_TYPE(right) == AOP_REG ||
1983 AOP_TYPE(right) == AOP_DIR ||
1984 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1986 MOVA(aopGet(AOP(left),offset,FALSE));
1987 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1988 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1990 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1992 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1993 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1998 /* right is a pointer reg need both a & b */
1999 /* PENDING: is this required? */
2001 char *l = aopGet(AOP(left),offset,FALSE);
2002 MOVA(aopGet(AOP(right),offset,FALSE));
2003 emitcode("cp", "%s", l);
2004 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2010 /*-----------------------------------------------------------------*/
2011 /* gencjne - compare and jump if not equal */
2012 /*-----------------------------------------------------------------*/
2013 static void gencjne(operand *left, operand *right, symbol *lbl)
2015 symbol *tlbl = newiTempLabel(NULL);
2017 gencjneshort(left, right, lbl);
2020 emitcode("ld","a,%s",one);
2021 emitcode("jp", LABEL_STR ,tlbl->key+100);
2022 emitcode("", LABEL_STR ":",lbl->key+100);
2023 emitcode("xor","a,a");
2024 emitcode("", LABEL_STR ":",tlbl->key+100);
2027 /*-----------------------------------------------------------------*/
2028 /* genCmpEq - generates code for equal to */
2029 /*-----------------------------------------------------------------*/
2030 static void genCmpEq (iCode *ic, iCode *ifx)
2032 operand *left, *right, *result;
2034 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2035 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2036 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2038 /* Swap operands if it makes the operation easier. ie if:
2039 1. Left is a literal.
2041 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2042 operand *t = IC_RIGHT(ic);
2043 IC_RIGHT(ic) = IC_LEFT(ic);
2047 if (ifx && !AOP_SIZE(result)){
2049 /* if they are both bit variables */
2050 if (AOP_TYPE(left) == AOP_CRY &&
2051 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2054 tlbl = newiTempLabel(NULL);
2055 gencjneshort(left, right, tlbl);
2056 if ( IC_TRUE(ifx) ) {
2057 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2058 emitcode("", LABEL_STR ":",tlbl->key+100);
2060 /* PENDING: do this better */
2061 symbol *lbl = newiTempLabel(NULL);
2062 emitcode("jp", LABEL_STR ,lbl->key+100);
2063 emitcode("", LABEL_STR ":",tlbl->key+100);
2064 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2065 emitcode("", LABEL_STR ":",lbl->key+100);
2068 /* mark the icode as generated */
2073 /* if they are both bit variables */
2074 if (AOP_TYPE(left) == AOP_CRY &&
2075 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2078 gencjne(left,right,newiTempLabel(NULL));
2079 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2083 genIfxJump(ifx,"a");
2086 /* if the result is used in an arithmetic operation
2087 then put the result in place */
2088 if (AOP_TYPE(result) != AOP_CRY) {
2091 /* leave the result in acc */
2095 freeAsmop(left,NULL,ic);
2096 freeAsmop(right,NULL,ic);
2097 freeAsmop(result,NULL,ic);
2100 /*-----------------------------------------------------------------*/
2101 /* ifxForOp - returns the icode containing the ifx for operand */
2102 /*-----------------------------------------------------------------*/
2103 static iCode *ifxForOp ( operand *op, iCode *ic )
2105 /* if true symbol then needs to be assigned */
2106 if (IS_TRUE_SYMOP(op))
2109 /* if this has register type condition and
2110 the next instruction is ifx with the same operand
2111 and live to of the operand is upto the ifx only then */
2113 ic->next->op == IFX &&
2114 IC_COND(ic->next)->key == op->key &&
2115 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2121 /*-----------------------------------------------------------------*/
2122 /* genAndOp - for && operation */
2123 /*-----------------------------------------------------------------*/
2124 static void genAndOp (iCode *ic)
2126 operand *left,*right, *result;
2129 /* note here that && operations that are in an if statement are
2130 taken away by backPatchLabels only those used in arthmetic
2131 operations remain */
2132 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2133 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2134 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2136 /* if both are bit variables */
2137 if (AOP_TYPE(left) == AOP_CRY &&
2138 AOP_TYPE(right) == AOP_CRY ) {
2141 tlbl = newiTempLabel(NULL);
2143 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2145 emitcode("", LABEL_STR ":",tlbl->key+100);
2149 freeAsmop(left,NULL,ic);
2150 freeAsmop(right,NULL,ic);
2151 freeAsmop(result,NULL,ic);
2154 /*-----------------------------------------------------------------*/
2155 /* genOrOp - for || operation */
2156 /*-----------------------------------------------------------------*/
2157 static void genOrOp (iCode *ic)
2159 operand *left,*right, *result;
2162 /* note here that || operations that are in an
2163 if statement are taken away by backPatchLabels
2164 only those used in arthmetic operations remain */
2165 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2166 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2167 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2169 /* if both are bit variables */
2170 if (AOP_TYPE(left) == AOP_CRY &&
2171 AOP_TYPE(right) == AOP_CRY ) {
2174 tlbl = newiTempLabel(NULL);
2176 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2178 emitcode("", LABEL_STR,tlbl->key+100);
2182 freeAsmop(left,NULL,ic);
2183 freeAsmop(right,NULL,ic);
2184 freeAsmop(result,NULL,ic);
2187 /*-----------------------------------------------------------------*/
2188 /* isLiteralBit - test if lit == 2^n */
2189 /*-----------------------------------------------------------------*/
2190 int isLiteralBit(unsigned long lit)
2192 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2193 0x100L,0x200L,0x400L,0x800L,
2194 0x1000L,0x2000L,0x4000L,0x8000L,
2195 0x10000L,0x20000L,0x40000L,0x80000L,
2196 0x100000L,0x200000L,0x400000L,0x800000L,
2197 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2198 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2201 for(idx = 0; idx < 32; idx++)
2207 /*-----------------------------------------------------------------*/
2208 /* genAnd - code for and */
2209 /*-----------------------------------------------------------------*/
2210 static void genAnd (iCode *ic, iCode *ifx)
2212 operand *left, *right, *result;
2214 unsigned long lit = 0L;
2217 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2218 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2219 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2222 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2224 AOP_TYPE(left), AOP_TYPE(right));
2225 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2227 AOP_SIZE(left), AOP_SIZE(right));
2230 /* if left is a literal & right is not then exchange them */
2231 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2232 AOP_NEEDSACC(left)) {
2233 operand *tmp = right ;
2238 /* if result = right then exchange them */
2239 if(sameRegs(AOP(result),AOP(right))){
2240 operand *tmp = right ;
2245 /* if right is bit then exchange them */
2246 if (AOP_TYPE(right) == AOP_CRY &&
2247 AOP_TYPE(left) != AOP_CRY){
2248 operand *tmp = right ;
2252 if(AOP_TYPE(right) == AOP_LIT)
2253 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2255 size = AOP_SIZE(result);
2257 if (AOP_TYPE(left) == AOP_CRY){
2262 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2263 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2264 if((AOP_TYPE(right) == AOP_LIT) &&
2265 (AOP_TYPE(result) == AOP_CRY) &&
2266 (AOP_TYPE(left) != AOP_CRY)) {
2267 int posbit = isLiteralBit(lit);
2271 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2275 emitcode("mov","c,acc.%d",posbit&0x07);
2280 sprintf(buffer, "%d", posbit&0x07);
2281 genIfxJump(ifx, buffer);
2289 symbol *tlbl = newiTempLabel(NULL);
2290 int sizel = AOP_SIZE(left);
2293 emitcode("setb","c");
2296 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2297 MOVA( aopGet(AOP(left),offset,FALSE));
2299 if((posbit = isLiteralBit(bytelit)) != 0) {
2301 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2304 if(bytelit != 0x0FFL)
2305 emitcode("and","a,%s",
2306 aopGet(AOP(right),offset,FALSE));
2307 emitcode("jr","nz, %05d$",tlbl->key+100);
2312 // bit = left & literal
2314 emitcode("clr","c");
2315 emitcode("","%05d$:",tlbl->key+100);
2317 // if(left & literal)
2321 jmpTrueOrFalse(ifx, tlbl);
2332 /* if left is same as result */
2333 if(sameRegs(AOP(result),AOP(left))){
2334 for(;size--; offset++) {
2335 if(AOP_TYPE(right) == AOP_LIT){
2336 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2340 aopPut(AOP(result),zero,offset);
2342 MOVA(aopGet(AOP(left),offset,FALSE));
2343 emitcode("and","a,%s",
2344 aopGet(AOP(right),offset,FALSE));
2345 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2350 if (AOP_TYPE(left) == AOP_ACC) {
2354 MOVA(aopGet(AOP(right),offset,FALSE));
2355 emitcode("and","%s,a",
2356 aopGet(AOP(left),offset,FALSE));
2361 // left & result in different registers
2362 if(AOP_TYPE(result) == AOP_CRY){
2365 for(;(size--);offset++) {
2367 // result = left & right
2368 if(AOP_TYPE(right) == AOP_LIT){
2369 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2371 aopGet(AOP(left),offset,FALSE),
2374 } else if(bytelit == 0){
2375 aopPut(AOP(result),zero,offset);
2379 // faster than result <- left, anl result,right
2380 // and better if result is SFR
2381 if (AOP_TYPE(left) == AOP_ACC)
2382 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2384 MOVA(aopGet(AOP(right),offset,FALSE));
2385 emitcode("and","a,%s",
2386 aopGet(AOP(left),offset,FALSE));
2388 aopPut(AOP(result),"a",offset);
2395 freeAsmop(left,NULL,ic);
2396 freeAsmop(right,NULL,ic);
2397 freeAsmop(result,NULL,ic);
2400 /*-----------------------------------------------------------------*/
2401 /* genOr - code for or */
2402 /*-----------------------------------------------------------------*/
2403 static void genOr (iCode *ic, iCode *ifx)
2405 operand *left, *right, *result;
2407 unsigned long lit = 0L;
2409 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2410 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2411 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2414 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2416 AOP_TYPE(left), AOP_TYPE(right));
2417 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2419 AOP_SIZE(left), AOP_SIZE(right));
2422 /* if left is a literal & right is not then exchange them */
2423 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2424 AOP_NEEDSACC(left)) {
2425 operand *tmp = right ;
2430 /* if result = right then exchange them */
2431 if(sameRegs(AOP(result),AOP(right))){
2432 operand *tmp = right ;
2437 /* if right is bit then exchange them */
2438 if (AOP_TYPE(right) == AOP_CRY &&
2439 AOP_TYPE(left) != AOP_CRY){
2440 operand *tmp = right ;
2444 if(AOP_TYPE(right) == AOP_LIT)
2445 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2447 size = AOP_SIZE(result);
2449 if (AOP_TYPE(left) == AOP_CRY){
2454 if((AOP_TYPE(right) == AOP_LIT) &&
2455 (AOP_TYPE(result) == AOP_CRY) &&
2456 (AOP_TYPE(left) != AOP_CRY)){
2461 /* if left is same as result */
2462 if(sameRegs(AOP(result),AOP(left))){
2463 for(;size--; offset++) {
2464 if(AOP_TYPE(right) == AOP_LIT){
2465 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2468 emitcode("or","%s,%s; 5",
2469 aopGet(AOP(left),offset,FALSE),
2470 aopGet(AOP(right),offset,FALSE));
2472 if (AOP_TYPE(left) == AOP_ACC)
2473 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2475 MOVA(aopGet(AOP(right),offset,FALSE));
2476 emitcode("or","a,%s ; 7",
2477 aopGet(AOP(left),offset,FALSE));
2478 aopPut(AOP(result),"a ; 8",0);
2483 // left & result in different registers
2484 if(AOP_TYPE(result) == AOP_CRY){
2486 } else for(;(size--);offset++){
2488 // result = left & right
2489 if(AOP_TYPE(right) == AOP_LIT){
2490 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2492 aopGet(AOP(left),offset,FALSE),
2497 // faster than result <- left, anl result,right
2498 // and better if result is SFR
2499 if (AOP_TYPE(left) == AOP_ACC)
2500 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2502 MOVA(aopGet(AOP(right),offset,FALSE));
2503 emitcode("or","a,%s",
2504 aopGet(AOP(left),offset,FALSE));
2506 aopPut(AOP(result),"a",offset);
2507 /* PENDING: something weird is going on here. Add exception. */
2508 if (AOP_TYPE(result) == AOP_ACC)
2514 freeAsmop(left,NULL,ic);
2515 freeAsmop(right,NULL,ic);
2516 freeAsmop(result,NULL,ic);
2519 /*-----------------------------------------------------------------*/
2520 /* genXor - code for xclusive or */
2521 /*-----------------------------------------------------------------*/
2522 static void genXor (iCode *ic, iCode *ifx)
2524 operand *left, *right, *result;
2526 unsigned long lit = 0L;
2528 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2529 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2530 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2532 /* if left is a literal & right is not then exchange them */
2533 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2534 AOP_NEEDSACC(left)) {
2535 operand *tmp = right ;
2540 /* if result = right then exchange them */
2541 if(sameRegs(AOP(result),AOP(right))){
2542 operand *tmp = right ;
2547 /* if right is bit then exchange them */
2548 if (AOP_TYPE(right) == AOP_CRY &&
2549 AOP_TYPE(left) != AOP_CRY){
2550 operand *tmp = right ;
2554 if(AOP_TYPE(right) == AOP_LIT)
2555 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2557 size = AOP_SIZE(result);
2559 if (AOP_TYPE(left) == AOP_CRY){
2564 if((AOP_TYPE(right) == AOP_LIT) &&
2565 (AOP_TYPE(result) == AOP_CRY) &&
2566 (AOP_TYPE(left) != AOP_CRY)){
2571 /* if left is same as result */
2572 if(sameRegs(AOP(result),AOP(left))){
2573 for(;size--; offset++) {
2574 if(AOP_TYPE(right) == AOP_LIT){
2575 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2578 MOVA(aopGet(AOP(right),offset,FALSE));
2579 emitcode("xor","a,%s",
2580 aopGet(AOP(left),offset,FALSE));
2581 aopPut(AOP(result),"a",0);
2584 if (AOP_TYPE(left) == AOP_ACC)
2585 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2587 MOVA(aopGet(AOP(right),offset,FALSE));
2588 emitcode("xor","a,%s",
2589 aopGet(AOP(left),offset,FALSE));
2590 aopPut(AOP(result),"a",0);
2595 // left & result in different registers
2596 if(AOP_TYPE(result) == AOP_CRY){
2598 } else for(;(size--);offset++){
2600 // result = left & right
2601 if(AOP_TYPE(right) == AOP_LIT){
2602 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2604 aopGet(AOP(left),offset,FALSE),
2609 // faster than result <- left, anl result,right
2610 // and better if result is SFR
2611 if (AOP_TYPE(left) == AOP_ACC)
2612 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2614 MOVA(aopGet(AOP(right),offset,FALSE));
2615 emitcode("xor","a,%s",
2616 aopGet(AOP(left),offset,FALSE));
2617 aopPut(AOP(result),"a",0);
2619 aopPut(AOP(result),"a",offset);
2624 freeAsmop(left,NULL,ic);
2625 freeAsmop(right,NULL,ic);
2626 freeAsmop(result,NULL,ic);
2629 /*-----------------------------------------------------------------*/
2630 /* genInline - write the inline code out */
2631 /*-----------------------------------------------------------------*/
2632 static void genInline (iCode *ic)
2634 char buffer[MAX_INLINEASM];
2638 inLine += (!options.asmpeep);
2639 strcpy(buffer,IC_INLINE(ic));
2641 /* emit each line as a code */
2660 /* emitcode("",buffer); */
2661 inLine -= (!options.asmpeep);
2664 /*-----------------------------------------------------------------*/
2665 /* genRRC - rotate right with carry */
2666 /*-----------------------------------------------------------------*/
2667 static void genRRC (iCode *ic)
2672 /*-----------------------------------------------------------------*/
2673 /* genRLC - generate code for rotate left with carry */
2674 /*-----------------------------------------------------------------*/
2675 static void genRLC (iCode *ic)
2680 /*-----------------------------------------------------------------*/
2681 /* shiftR2Left2Result - shift right two bytes from left to result */
2682 /*-----------------------------------------------------------------*/
2683 static void shiftR2Left2Result (operand *left, int offl,
2684 operand *result, int offr,
2685 int shCount, int sign)
2687 if(sameRegs(AOP(result), AOP(left)) &&
2688 ((offl + MSB16) == offr)){
2691 movLeft2Result(left, offl, result, offr, 0);
2692 movLeft2Result(left, offl+1, result, offr+1, 0);
2699 /* if (AOP(result)->type == AOP_REG) {*/
2702 symbol *tlbl , *tlbl1;
2705 /* Left is already in result - so now do the shift */
2707 emitcode("ld","a,#%u+1", shCount);
2708 tlbl = newiTempLabel(NULL);
2709 tlbl1 = newiTempLabel(NULL);
2710 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2711 emitcode("", LABEL_STR ":",tlbl->key+100);
2714 emitcode("or", "a,a");
2717 l = aopGet(AOP(result), --offset, FALSE);
2718 emitcode("rr","%s", l);
2721 emitcode("", LABEL_STR ":",tlbl1->key+100);
2722 emitcode("dec", "a");
2723 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2728 /*-----------------------------------------------------------------*/
2729 /* shiftL2Left2Result - shift left two bytes from left to result */
2730 /*-----------------------------------------------------------------*/
2731 static void shiftL2Left2Result (operand *left, int offl,
2732 operand *result, int offr, int shCount)
2734 if(sameRegs(AOP(result), AOP(left)) &&
2735 ((offl + MSB16) == offr)){
2738 /* Copy left into result */
2739 movLeft2Result(left, offl, result, offr, 0);
2740 movLeft2Result(left, offl+1, result, offr+1, 0);
2742 /* PENDING: for now just see if it'll work. */
2743 /*if (AOP(result)->type == AOP_REG) { */
2747 symbol *tlbl , *tlbl1;
2750 /* Left is already in result - so now do the shift */
2752 emitcode("ld","a,#%u+1", shCount);
2753 tlbl = newiTempLabel(NULL);
2754 tlbl1 = newiTempLabel(NULL);
2755 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2756 emitcode("", LABEL_STR ":",tlbl->key+100);
2759 emitcode("or", "a,a");
2761 l = aopGet(AOP(result),offset++,FALSE);
2762 emitcode("rl","%s", l);
2765 emitcode("", LABEL_STR ":",tlbl1->key+100);
2766 emitcode("dec", "a");
2767 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2772 /*-----------------------------------------------------------------*/
2773 /* AccRol - rotate left accumulator by known count */
2774 /*-----------------------------------------------------------------*/
2775 static void AccRol (int shCount)
2777 shCount &= 0x0007; // shCount : 0..7
2814 /*-----------------------------------------------------------------*/
2815 /* AccLsh - left shift accumulator by known count */
2816 /*-----------------------------------------------------------------*/
2817 static void AccLsh (int shCount)
2821 emitcode("add","a,a");
2824 emitcode("add","a,a");
2825 emitcode("add","a,a");
2827 /* rotate left accumulator */
2829 /* and kill the lower order bits */
2830 emitcode("and","a,#0x%02x", SLMask[shCount]);
2835 /*-----------------------------------------------------------------*/
2836 /* shiftL1Left2Result - shift left one byte from left to result */
2837 /*-----------------------------------------------------------------*/
2838 static void shiftL1Left2Result (operand *left, int offl,
2839 operand *result, int offr, int shCount)
2842 l = aopGet(AOP(left),offl,FALSE);
2844 /* shift left accumulator */
2846 aopPut(AOP(result),"a",offr);
2850 /*-----------------------------------------------------------------*/
2851 /* genlshTwo - left shift two bytes by known amount != 0 */
2852 /*-----------------------------------------------------------------*/
2853 static void genlshTwo (operand *result,operand *left, int shCount)
2855 int size = AOP_SIZE(result);
2859 /* if shCount >= 8 */
2865 movLeft2Result(left, LSB, result, MSB16, 0);
2866 aopPut(AOP(result),zero, 0);
2867 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2870 movLeft2Result(left, LSB, result, MSB16, 0);
2871 aopPut(AOP(result),zero, 0);
2874 aopPut(AOP(result),zero,LSB);
2876 /* 1 <= shCount <= 7 */
2882 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2887 /*-----------------------------------------------------------------*/
2888 /* genlshOne - left shift a one byte quantity by known count */
2889 /*-----------------------------------------------------------------*/
2890 static void genlshOne (operand *result, operand *left, int shCount)
2892 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2895 /*-----------------------------------------------------------------*/
2896 /* genLeftShiftLiteral - left shifting by known count */
2897 /*-----------------------------------------------------------------*/
2898 static void genLeftShiftLiteral (operand *left,
2903 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2906 freeAsmop(right,NULL,ic);
2908 aopOp(left,ic,FALSE);
2909 aopOp(result,ic,FALSE);
2911 size = getSize(operandType(result));
2914 emitcode("; shift left ","result %d, left %d",size,
2918 /* I suppose that the left size >= result size */
2923 else if(shCount >= (size * 8))
2925 aopPut(AOP(result),zero,size);
2929 genlshOne (result,left,shCount);
2932 genlshTwo (result,left,shCount);
2941 freeAsmop(left,NULL,ic);
2942 freeAsmop(result,NULL,ic);
2945 /*-----------------------------------------------------------------*/
2946 /* genLeftShift - generates code for left shifting */
2947 /*-----------------------------------------------------------------*/
2948 static void genLeftShift (iCode *ic)
2952 symbol *tlbl , *tlbl1;
2953 operand *left,*right, *result;
2955 right = IC_RIGHT(ic);
2957 result = IC_RESULT(ic);
2959 aopOp(right,ic,FALSE);
2961 /* if the shift count is known then do it
2962 as efficiently as possible */
2963 if (AOP_TYPE(right) == AOP_LIT) {
2964 genLeftShiftLiteral (left,right,result,ic);
2968 /* shift count is unknown then we have to form a loop get the loop
2969 count in B : Note: we take only the lower order byte since
2970 shifting more that 32 bits make no sense anyway, ( the largest
2971 size of an object can be only 32 bits ) */
2972 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2973 emitcode("inc","a");
2974 freeAsmop (right,NULL,ic);
2975 aopOp(left,ic,FALSE);
2976 aopOp(result,ic,FALSE);
2978 /* now move the left to the result if they are not the
2981 if (!sameRegs(AOP(left),AOP(result))) {
2983 size = AOP_SIZE(result);
2986 l = aopGet(AOP(left),offset,FALSE);
2987 aopPut(AOP(result),l,offset);
2992 size = AOP_SIZE(result);
2995 l = aopGet(AOP(left),offset,FALSE);
2996 aopPut(AOP(result),l,offset);
3002 tlbl = newiTempLabel(NULL);
3003 size = AOP_SIZE(result);
3005 tlbl1 = newiTempLabel(NULL);
3007 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3008 emitcode("", LABEL_STR ":",tlbl->key+100);
3009 l = aopGet(AOP(result),offset,FALSE);
3010 emitcode("or", "a,a");
3012 l = aopGet(AOP(result),offset++,FALSE);
3013 emitcode("rl","%s", l);
3015 emitcode("", LABEL_STR ":",tlbl1->key+100);
3016 emitcode("dec", "a");
3017 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3019 freeAsmop(left,NULL,ic);
3020 freeAsmop(result,NULL,ic);
3023 /* genlshTwo - left shift two bytes by known amount != 0 */
3024 /*-----------------------------------------------------------------*/
3025 static void genrshOne (operand *result,operand *left, int shCount)
3028 int size = AOP_SIZE(result);
3034 l = aopGet(AOP(left),0,FALSE);
3035 if (AOP(result)->type == AOP_REG) {
3036 aopPut(AOP(result), l, 0);
3037 l = aopGet(AOP(result), 0, FALSE);
3039 emitcode("srl", "%s", l);
3044 emitcode("srl", "a");
3046 aopPut(AOP(result),"a",0);
3050 /*-----------------------------------------------------------------*/
3051 /* AccRsh - right shift accumulator by known count */
3052 /*-----------------------------------------------------------------*/
3053 static void AccRsh (int shCount)
3060 /* rotate right accumulator */
3061 AccRol(8 - shCount);
3062 /* and kill the higher order bits */
3063 emitcode("and","a,#0x%02x", SRMask[shCount]);
3068 /*-----------------------------------------------------------------*/
3069 /* shiftR1Left2Result - shift right one byte from left to result */
3070 /*-----------------------------------------------------------------*/
3071 static void shiftR1Left2Result (operand *left, int offl,
3072 operand *result, int offr,
3073 int shCount, int sign)
3075 MOVA(aopGet(AOP(left),offl,FALSE));
3082 aopPut(AOP(result),"a",offr);
3085 /*-----------------------------------------------------------------*/
3086 /* genrshTwo - right shift two bytes by known amount != 0 */
3087 /*-----------------------------------------------------------------*/
3088 static void genrshTwo (operand *result,operand *left,
3089 int shCount, int sign)
3091 /* if shCount >= 8 */
3096 shiftR1Left2Result(left, MSB16, result, LSB,
3100 movLeft2Result(left, MSB16, result, LSB, sign);
3101 aopPut(AOP(result),zero,1);
3104 /* 1 <= shCount <= 7 */
3106 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3110 /*-----------------------------------------------------------------*/
3111 /* genRightShiftLiteral - left shifting by known count */
3112 /*-----------------------------------------------------------------*/
3113 static void genRightShiftLiteral (operand *left,
3118 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3121 freeAsmop(right,NULL,ic);
3123 aopOp(left,ic,FALSE);
3124 aopOp(result,ic,FALSE);
3126 size = getSize(operandType(result));
3128 emitcode("; shift right ","result %d, left %d",size,
3131 /* I suppose that the left size >= result size */
3136 else if(shCount >= (size * 8))
3138 aopPut(AOP(result),zero,size);
3142 genrshOne(result, left, shCount);
3145 /* PENDING: sign support */
3146 genrshTwo(result, left, shCount, FALSE);
3155 freeAsmop(left,NULL,ic);
3156 freeAsmop(result,NULL,ic);
3159 /*-----------------------------------------------------------------*/
3160 /* genRightShift - generate code for right shifting */
3161 /*-----------------------------------------------------------------*/
3162 static void genRightShift (iCode *ic)
3164 operand *left,*right, *result;
3166 right = IC_RIGHT(ic);
3168 result = IC_RESULT(ic);
3170 aopOp(right,ic,FALSE);
3172 /* if the shift count is known then do it
3173 as efficiently as possible */
3174 if (AOP_TYPE(right) == AOP_LIT) {
3175 genRightShiftLiteral (left,right,result,ic);
3183 /*-----------------------------------------------------------------*/
3184 /* genGenPointerGet - gget value from generic pointer space */
3185 /*-----------------------------------------------------------------*/
3186 static void genGenPointerGet (operand *left,
3187 operand *result, iCode *ic)
3190 link *retype = getSpec(operandType(result));
3192 aopOp(left,ic,FALSE);
3193 aopOp(result,ic,FALSE);
3195 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3197 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3198 aopPut(AOP(result),"a", 0);
3199 freeAsmop(left,NULL,ic);
3203 /* For now we always load into IY */
3204 /* if this is remateriazable */
3205 if (AOP_TYPE(left) == AOP_IMMD)
3206 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3207 else { /* we need to get it byte by byte */
3209 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3210 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3212 /* so iy now contains the address */
3213 freeAsmop(left,NULL,ic);
3215 /* if bit then unpack */
3216 if (IS_BITVAR(retype)) {
3220 size = AOP_SIZE(result);
3224 /* PENDING: make this better */
3225 if (AOP(result)->type == AOP_REG) {
3226 aopPut(AOP(result),"(hl)",offset++);
3229 emitcode("ld", "a,(hl)", offset);
3230 aopPut(AOP(result),"a",offset++);
3233 emitcode("inc", "hl");
3239 freeAsmop(result,NULL,ic);
3242 /*-----------------------------------------------------------------*/
3243 /* genPointerGet - generate code for pointer get */
3244 /*-----------------------------------------------------------------*/
3245 static void genPointerGet (iCode *ic)
3247 operand *left, *result ;
3251 result = IC_RESULT(ic) ;
3253 /* depending on the type of pointer we need to
3254 move it to the correct pointer register */
3255 type = operandType(left);
3256 etype = getSpec(type);
3258 genGenPointerGet (left,result,ic);
3261 bool isRegOrLit(asmop *aop)
3263 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3268 /*-----------------------------------------------------------------*/
3269 /* genGenPointerSet - stores the value into a pointer location */
3270 /*-----------------------------------------------------------------*/
3271 static void genGenPointerSet (operand *right,
3272 operand *result, iCode *ic)
3275 link *retype = getSpec(operandType(right));
3277 aopOp(result,ic,FALSE);
3278 aopOp(right,ic,FALSE);
3280 /* Handle the exceptions first */
3281 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3283 char *l = aopGet(AOP(right), 0, FALSE);
3285 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3286 freeAsmop(result,NULL,ic);
3290 /* if the operand is already in dptr
3291 then we do nothing else we move the value to dptr */
3292 if (AOP_TYPE(result) != AOP_STR) {
3293 /* if this is remateriazable */
3294 if (AOP_TYPE(result) == AOP_IMMD) {
3295 emitcode("", "; Error 2");
3296 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3298 else { /* we need to get it byte by byte */
3299 /* PENDING: do this better */
3300 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3301 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3304 /* so hl know contains the address */
3305 freeAsmop(result,NULL,ic);
3307 /* if bit then unpack */
3308 if (IS_BITVAR(retype)) {
3312 size = AOP_SIZE(right);
3316 char *l = aopGet(AOP(right),offset,FALSE);
3318 if (isRegOrLit(AOP(right))) {
3319 emitcode("ld", "(hl),%s", l);
3323 emitcode("ld", "(hl),a", offset);
3326 emitcode("inc", "hl");
3332 freeAsmop(right,NULL,ic);
3335 /*-----------------------------------------------------------------*/
3336 /* genPointerSet - stores the value into a pointer location */
3337 /*-----------------------------------------------------------------*/
3338 static void genPointerSet (iCode *ic)
3340 operand *right, *result ;
3343 right = IC_RIGHT(ic);
3344 result = IC_RESULT(ic) ;
3346 /* depending on the type of pointer we need to
3347 move it to the correct pointer register */
3348 type = operandType(result);
3349 etype = getSpec(type);
3351 genGenPointerSet (right,result,ic);
3354 /*-----------------------------------------------------------------*/
3355 /* genIfx - generate code for Ifx statement */
3356 /*-----------------------------------------------------------------*/
3357 static void genIfx (iCode *ic, iCode *popIc)
3359 operand *cond = IC_COND(ic);
3362 aopOp(cond,ic,FALSE);
3364 /* get the value into acc */
3365 if (AOP_TYPE(cond) != AOP_CRY)
3369 /* the result is now in the accumulator */
3370 freeAsmop(cond,NULL,ic);
3372 /* if there was something to be popped then do it */
3376 /* if the condition is a bit variable */
3377 if (isbit && IS_ITEMP(cond) &&
3379 genIfxJump(ic,SPIL_LOC(cond)->rname);
3381 if (isbit && !IS_ITEMP(cond))
3382 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3389 /*-----------------------------------------------------------------*/
3390 /* genAddrOf - generates code for address of */
3391 /*-----------------------------------------------------------------*/
3392 static void genAddrOf (iCode *ic)
3394 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3396 aopOp(IC_RESULT(ic),ic,FALSE);
3398 /* if the operand is on the stack then we
3399 need to get the stack offset of this
3402 /* if it has an offset then we need to compute it */
3403 emitcode("push", "de");
3404 emitcode("push", "ix");
3405 emitcode("pop", "hl");
3406 emitcode("ld", "de,#%d", sym->stack);
3407 emitcode("add", "hl,de");
3408 emitcode("pop", "de");
3411 emitcode("ld", "hl,#%s", sym->rname);
3413 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3414 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3416 freeAsmop(IC_RESULT(ic),NULL,ic);
3419 /*-----------------------------------------------------------------*/
3420 /* genAssign - generate code for assignment */
3421 /*-----------------------------------------------------------------*/
3422 static void genAssign (iCode *ic)
3424 operand *result, *right;
3426 unsigned long lit = 0L;
3428 result = IC_RESULT(ic);
3429 right = IC_RIGHT(ic) ;
3432 /* Dont bother assigning if they are the same */
3433 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3434 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3439 aopOp(right,ic,FALSE);
3440 aopOp(result,ic,TRUE);
3442 /* if they are the same registers */
3443 if (sameRegs(AOP(right),AOP(result))) {
3444 emitcode("", "; (registers are the same)");
3448 /* if the result is a bit */
3449 if (AOP_TYPE(result) == AOP_CRY) {
3454 size = AOP_SIZE(result);
3457 if(AOP_TYPE(right) == AOP_LIT)
3458 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3460 (AOP_TYPE(result) != AOP_REG) &&
3461 (AOP_TYPE(right) == AOP_LIT) &&
3462 !IS_FLOAT(operandType(right)) &&
3464 bool fXored = FALSE;
3466 /* Work from the top down.
3467 Done this way so that we can use the cached copy of 0
3468 in A for a fast clear */
3470 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3471 if (!fXored && size>1) {
3472 emitcode("xor", "a,a");
3476 aopPut(AOP(result),"a",offset);
3479 aopPut(AOP(result), "#0", offset);
3484 aopGet(AOP(right),offset,FALSE),
3491 aopGet(AOP(right),offset,FALSE),
3498 freeAsmop(right,NULL,ic);
3499 freeAsmop(result,NULL,ic);
3502 /*-----------------------------------------------------------------*/
3503 /* genJumpTab - genrates code for jump table */
3504 /*-----------------------------------------------------------------*/
3505 static void genJumpTab (iCode *ic)
3510 aopOp(IC_JTCOND(ic),ic,FALSE);
3511 /* get the condition into accumulator */
3512 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3514 emitcode("push", "de");
3515 emitcode("ld", "e,%s", l);
3516 emitcode("ld", "d,#0");
3517 jtab = newiTempLabel(NULL);
3518 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3519 emitcode("add", "hl,de");
3520 emitcode("add", "hl,de");
3521 freeAsmop(IC_JTCOND(ic),NULL,ic);
3522 emitcode("pop", "de");
3523 emitcode("jp", "(hl)");
3524 emitcode("","%05d$:",jtab->key+100);
3525 /* now generate the jump labels */
3526 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3527 jtab = setNextItem(IC_JTLABELS(ic)))
3528 emitcode("jp", LABEL_STR, jtab->key+100);
3531 /*-----------------------------------------------------------------*/
3532 /* genCast - gen code for casting */
3533 /*-----------------------------------------------------------------*/
3534 static void genCast (iCode *ic)
3536 operand *result = IC_RESULT(ic);
3537 link *ctype = operandType(IC_LEFT(ic));
3538 operand *right = IC_RIGHT(ic);
3541 /* if they are equivalent then do nothing */
3542 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3545 aopOp(right,ic,FALSE) ;
3546 aopOp(result,ic,FALSE);
3548 /* if the result is a bit */
3549 if (AOP_TYPE(result) == AOP_CRY) {
3553 /* if they are the same size : or less */
3554 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3556 /* if they are in the same place */
3557 if (sameRegs(AOP(right),AOP(result)))
3560 /* if they in different places then copy */
3561 size = AOP_SIZE(result);
3565 aopGet(AOP(right),offset,FALSE),
3572 /* if the result is of type pointer */
3573 if (IS_PTR(ctype)) {
3577 /* so we now know that the size of destination is greater
3578 than the size of the source */
3579 /* we move to result for the size of source */
3580 size = AOP_SIZE(right);
3584 aopGet(AOP(right),offset,FALSE),
3589 /* now depending on the sign of the destination */
3590 size = AOP_SIZE(result) - AOP_SIZE(right);
3591 /* Unsigned or not an integral type - right fill with zeros */
3592 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3594 aopPut(AOP(result),zero,offset++);
3596 /* we need to extend the sign :{ */
3597 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3600 emitcode("", "; genCast: sign extend untested.");
3601 emitcode("rla", "");
3602 emitcode("sbc", "a,a");
3604 aopPut(AOP(result),"a",offset++);
3608 freeAsmop(right, NULL, ic);
3609 freeAsmop(result, NULL, ic);
3612 /*-----------------------------------------------------------------*/
3613 /* genReceive - generate code for a receive iCode */
3614 /*-----------------------------------------------------------------*/
3615 static void genReceive (iCode *ic)
3617 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3618 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3619 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3623 aopOp(IC_RESULT(ic),ic,FALSE);
3625 assignResultValue(IC_RESULT(ic));
3628 freeAsmop(IC_RESULT(ic),NULL,ic);
3631 /*-----------------------------------------------------------------*/
3632 /* genZ80Code - generate code for Z80 based controllers */
3633 /*-----------------------------------------------------------------*/
3634 void genZ80Code (iCode *lic)
3639 lineHead = lineCurr = NULL;
3641 /* if debug information required */
3642 if (options.debug && currFunc) {
3643 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3645 if (IS_STATIC(currFunc->etype))
3646 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3648 emitcode("","G$%s$0$0 ==.",currFunc->name);
3651 /* stack pointer name */
3655 for (ic = lic ; ic ; ic = ic->next ) {
3657 if ( cln != ic->lineno ) {
3658 if ( options.debug ) {
3660 emitcode("","C$%s$%d$%d$%d ==.",
3661 ic->filename,ic->lineno,
3662 ic->level,ic->block);
3665 emitcode(";","%s %d",ic->filename,ic->lineno);
3668 /* if the result is marked as
3669 spilt and rematerializable or code for
3670 this has already been generated then
3672 if (resultRemat(ic) || ic->generated )
3675 /* depending on the operation */
3678 emitcode("", "; genNot");
3683 emitcode("", "; genCpl");
3688 emitcode("", "; genUminus");
3693 emitcode("", "; genIpush");
3698 /* IPOP happens only when trying to restore a
3699 spilt live range, if there is an ifx statement
3700 following this pop then the if statement might
3701 be using some of the registers being popped which
3702 would destory the contents of the register so
3703 we need to check for this condition and handle it */
3705 ic->next->op == IFX &&
3706 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3707 emitcode("", "; genIfx");
3708 genIfx (ic->next,ic);
3711 emitcode("", "; genIpop");
3717 emitcode("", "; genCall");
3722 emitcode("", "; genPcall");
3727 emitcode("", "; genFunction");
3732 emitcode("", "; genEndFunction");
3733 genEndFunction (ic);
3737 emitcode("", "; genRet");
3742 emitcode("", "; genLabel");
3747 emitcode("", "; genGoto");
3752 emitcode("", "; genPlus");
3757 emitcode("", "; genMinus");
3762 emitcode("", "; genMult");
3767 emitcode("", "; genDiv");
3772 emitcode("", "; genMod");
3777 emitcode("", "; genCmpGt");
3778 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3782 emitcode("", "; genCmpLt");
3783 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3790 /* note these two are xlated by algebraic equivalence
3791 during parsing SDCC.y */
3792 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3793 "got '>=' or '<=' shouldn't have come here");
3797 emitcode("", "; genCmpEq");
3798 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3802 emitcode("", "; genAndOp");
3807 emitcode("", "; genOrOp");
3812 emitcode("", "; genXor");
3813 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3817 emitcode("", "; genOr");
3818 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3822 emitcode("", "; genAnd");
3823 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3827 emitcode("", "; genInline");
3832 emitcode("", "; genRRC");
3837 emitcode("", "; genRLC");
3842 emitcode("", "; genHBIT");
3846 emitcode("", "; genLeftShift");
3851 emitcode("", "; genRightShift");
3855 case GET_VALUE_AT_ADDRESS:
3856 emitcode("", "; genPointerGet");
3862 if (POINTER_SET(ic)) {
3863 emitcode("", "; genAssign (pointer)");
3867 emitcode("", "; genAssign");
3873 emitcode("", "; genIfx");
3878 emitcode("", "; genAddrOf");
3883 emitcode("", "; genJumpTab");
3888 emitcode("", "; genCast");
3893 emitcode("", "; genReceive");
3898 emitcode("", "; addSet");
3899 addSet(&sendSet,ic);
3904 /* piCode(ic,stdout); */
3910 /* now we are ready to call the
3911 peep hole optimizer */
3912 if (!options.nopeep)
3913 peepHole (&lineHead);
3915 /* now do the actual printing */
3916 printLine (lineHead,codeOutFile);