1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 Michael Hope <michaelh@earthling.net> 2000
21 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
22 and - Jean-Louis VERN.jlvern@writeme.com (1999)
24 This program is free software; you can redistribute it and/or modify it
25 under the terms of the GNU General Public License as published by the
26 Free Software Foundation; either version 2, or (at your option) any
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 In other words, you are welcome to use, share and improve this program.
39 You are forbidden to forbid anyone else to use, share and improve
40 what you give them. Help stamp out software-hoarding!
42 -------------------------------------------------------------------------*/
48 #include "SDCCglobl.h"
50 #ifdef HAVE_SYS_ISA_DEFS_H
51 #include <sys/isa_defs.h>
57 #include "SDCChasht.h"
60 #include "SDCCicode.h"
61 #include "SDCClabel.h"
62 #include "SDCCBBlock.h"
65 #include "SDCCcflow.h"
66 #include "SDCCdflow.h"
67 #include "SDCClrange.h"
70 #include "SDCCpeeph.h"
71 #include "SDCCglue.h" /* drdani Jan 30 2000 */
73 /* this is the down and dirty file with all kinds of kludgy & hacky
74 stuff. This is what it is all about CODE GENERATION for a specific MCU.
75 Some of the routines may be reusable, will have to see */
77 static char *zero = "#0x00";
78 static char *one = "#0x01";
80 static char *fReturn[] = {"l", "h", "e", "d" };
81 static char *accUse[] = {"a" };
87 extern int ptrRegReq ;
89 extern FILE *codeOutFile;
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
96 #define CLRC emitcode("xor","a,a");
98 #define LABEL_STR "%05d$"
100 lineNode *lineHead = NULL;
101 lineNode *lineCurr = NULL;
103 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
106 0x07, 0x03, 0x01, 0x00};
108 static int _lastStack = 0;
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
126 void emitcode (const char *inst, const char *fmt, ...)
129 char lb[MAX_INLINEASM];
135 sprintf(lb,"%s\t",inst);
136 vsprintf(lb+(strlen(lb)),fmt,ap);
140 while (isspace(*lbp)) lbp++;
143 lineCurr = (lineCurr ?
144 connectLine(lineCurr,newLineNode(lb)) :
145 (lineHead = newLineNode(lb)));
146 lineCurr->isInline = inLine;
147 lineCurr->isDebug = debugLine;
151 const char *getPairName(asmop *aop)
153 if (aop->type == AOP_REG) {
154 switch (aop->aopu.aop_reg[0]->rIdx) {
166 else if (aop->type == AOP_STR) {
167 switch (*aop->aopu.aop_str[0]) {
183 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
184 bool isPair(asmop *aop)
186 if (aop->size == 2) {
187 if (aop->type == AOP_REG) {
188 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
191 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
194 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
198 if (aop->type == AOP_STR) {
199 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
202 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
205 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
213 /** Push a register pair onto the stack */
214 void genPairPush(asmop *aop)
216 emitcode("push", "%s", getPairName(aop));
219 /*-----------------------------------------------------------------*/
220 /* newAsmop - creates a new asmOp */
221 /*-----------------------------------------------------------------*/
222 static asmop *newAsmop (short type)
226 ALLOC(aop,sizeof(asmop));
231 /*-----------------------------------------------------------------*/
232 /* aopForSym - for a true symbol */
233 /*-----------------------------------------------------------------*/
234 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
237 memmap *space= SPEC_OCLS(sym->etype);
239 /* if already has one */
243 /* Assign depending on the storage class */
244 if (sym->onStack || sym->iaccess) {
245 sym->aop = aop = newAsmop(AOP_STK);
246 aop->size = getSize(sym->type);
248 aop->aopu.aop_stk = sym->stack;
252 /* special case for a function */
253 if (IS_FUNC(sym->type)) {
254 sym->aop = aop = newAsmop(AOP_IMMD);
255 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
256 strcpy(aop->aopu.aop_immd,sym->rname);
261 /* only remaining is far space */
262 /* in which case DPTR gets the address */
263 sym->aop = aop = newAsmop(AOP_IY);
264 emitcode ("ld","iy,#%s", sym->rname);
265 aop->size = getSize(sym->type);
266 aop->aopu.aop_dir = sym->rname;
268 /* if it is in code space */
269 if (IN_CODESPACE(space))
275 /*-----------------------------------------------------------------*/
276 /* aopForRemat - rematerialzes an object */
277 /*-----------------------------------------------------------------*/
278 static asmop *aopForRemat (symbol *sym)
281 iCode *ic = sym->rematiCode;
282 asmop *aop = newAsmop(AOP_IMMD);
285 /* if plus or minus print the right hand side */
286 if (ic->op == '+' || ic->op == '-') {
287 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
290 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
293 /* we reached the end */
294 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
298 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
299 strcpy(aop->aopu.aop_immd,buffer);
303 /*-----------------------------------------------------------------*/
304 /* regsInCommon - two operands have some registers in common */
305 /*-----------------------------------------------------------------*/
306 bool regsInCommon (operand *op1, operand *op2)
311 /* if they have registers in common */
312 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
315 sym1 = OP_SYMBOL(op1);
316 sym2 = OP_SYMBOL(op2);
318 if (sym1->nRegs == 0 || sym2->nRegs == 0)
321 for (i = 0 ; i < sym1->nRegs ; i++) {
326 for (j = 0 ; j < sym2->nRegs ;j++ ) {
330 if (sym2->regs[j] == sym1->regs[i])
338 /*-----------------------------------------------------------------*/
339 /* operandsEqu - equivalent */
340 /*-----------------------------------------------------------------*/
341 bool operandsEqu ( operand *op1, operand *op2)
345 /* if they not symbols */
346 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
349 sym1 = OP_SYMBOL(op1);
350 sym2 = OP_SYMBOL(op2);
352 /* if both are itemps & one is spilt
353 and the other is not then false */
354 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
355 sym1->isspilt != sym2->isspilt )
358 /* if they are the same */
362 if (strcmp(sym1->rname,sym2->rname) == 0)
366 /* if left is a tmp & right is not */
370 (sym1->usl.spillLoc == sym2))
377 (sym2->usl.spillLoc == sym1))
383 /*-----------------------------------------------------------------*/
384 /* sameRegs - two asmops have the same registers */
385 /*-----------------------------------------------------------------*/
386 bool sameRegs (asmop *aop1, asmop *aop2 )
393 if (aop1->type != AOP_REG ||
394 aop2->type != AOP_REG )
397 if (aop1->size != aop2->size)
400 for (i = 0 ; i < aop1->size ; i++ )
401 if (aop1->aopu.aop_reg[i] !=
402 aop2->aopu.aop_reg[i] )
408 /*-----------------------------------------------------------------*/
409 /* aopOp - allocates an asmop for an operand : */
410 /*-----------------------------------------------------------------*/
411 static void aopOp (operand *op, iCode *ic, bool result)
420 /* if this a literal */
421 if (IS_OP_LITERAL(op)) {
422 op->aop = aop = newAsmop(AOP_LIT);
423 aop->aopu.aop_lit = op->operand.valOperand;
424 aop->size = getSize(operandType(op));
428 /* if already has a asmop then continue */
432 /* if the underlying symbol has a aop */
433 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
434 op->aop = OP_SYMBOL(op)->aop;
438 /* if this is a true symbol */
439 if (IS_TRUE_SYMOP(op)) {
440 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
444 /* this is a temporary : this has
450 e) can be a return use only */
454 /* if the type is a conditional */
455 if (sym->regType == REG_CND) {
456 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
461 /* if it is spilt then two situations
463 b) has a spill location */
464 if (sym->isspilt || sym->nRegs == 0) {
465 /* rematerialize it NOW */
467 sym->aop = op->aop = aop =
469 aop->size = getSize(sym->type);
475 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
476 aop->size = getSize(sym->type);
477 for ( i = 0 ; i < 2 ; i++ )
478 aop->aopu.aop_str[i] = accUse[i];
484 aop = op->aop = sym->aop = newAsmop(AOP_STR);
485 aop->size = getSize(sym->type);
486 for ( i = 0 ; i < 4 ; i++ )
487 aop->aopu.aop_str[i] = fReturn[i];
491 /* else spill location */
492 sym->aop = op->aop = aop =
493 aopForSym(ic,sym->usl.spillLoc,result);
494 aop->size = getSize(sym->type);
498 /* must be in a register */
499 sym->aop = op->aop = aop = newAsmop(AOP_REG);
500 aop->size = sym->nRegs;
501 for ( i = 0 ; i < sym->nRegs ;i++)
502 aop->aopu.aop_reg[i] = sym->regs[i];
505 /*-----------------------------------------------------------------*/
506 /* freeAsmop - free up the asmop given to an operand */
507 /*----------------------------------------------------------------*/
508 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
531 /* all other cases just dealloc */
535 OP_SYMBOL(op)->aop = NULL;
536 /* if the symbol has a spill */
538 SPIL_LOC(op)->aop = NULL;
543 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
552 /* depending on type */
555 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
556 ALLOC_ATOMIC(rs,strlen(s)+1);
561 value * val = aop->aopu.aop_lit;
562 /* if it is a float then it gets tricky */
563 /* otherwise it is fairly simple */
564 if (!IS_FLOAT(val->type)) {
565 unsigned long v = floatFromVal(val);
567 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
568 ALLOC_ATOMIC(rs,strlen(buffer)+1);
569 return strcpy (rs,buffer);
578 char *aopGetWord(asmop *aop, int offset)
580 return aopGetWordLong(aop, offset, TRUE);
583 /*-----------------------------------------------------------------*/
584 /* aopGet - for fetching value of the aop */
585 /*-----------------------------------------------------------------*/
586 static char *aopGet (asmop *aop, int offset, bool bit16)
591 /* offset is greater than size then zero */
592 if (offset > (aop->size - 1) &&
593 aop->type != AOP_LIT)
596 /* depending on type */
600 sprintf (s,"#%s",aop->aopu.aop_immd);
610 ALLOC_ATOMIC(rs,strlen(s)+1);
616 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
618 ALLOC_ATOMIC(rs,strlen(s)+1);
623 return aop->aopu.aop_reg[offset]->name;
626 sprintf(s,"%d(iy)", offset);
627 ALLOC_ATOMIC(rs,strlen(s)+1);
632 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
633 ALLOC_ATOMIC(rs,strlen(s)+1);
647 return aopLiteral (aop->aopu.aop_lit,offset);
651 return aop->aopu.aop_str[offset];
654 fprintf(stderr, "Type %u\n", aop->type);
656 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
657 "aopget got unsupported aop->type");
661 bool isRegString(char *s)
663 if (!strcmp(s, "b") ||
674 bool isConstant(char *s)
679 bool canAssignToPtr(char *s)
688 /*-----------------------------------------------------------------*/
689 /* aopPut - puts a string for a aop */
690 /*-----------------------------------------------------------------*/
691 static void aopPut (asmop *aop, char *s, int offset)
695 if (aop->size && offset > ( aop->size - 1)) {
696 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
697 "aopPut got offset > aop->size");
701 /* will assign value to value */
702 /* depending on where it is ofcourse */
707 emitcode("ld", "a,%s", s);
708 emitcode("ld", "(%s+%d),a", d, offset);
712 /* Dont bother if it's a ld x,x */
713 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
714 emitcode("ld","%s,%s",
715 aop->aopu.aop_reg[offset]->name,s);
720 if (!canAssignToPtr(s)) {
721 emitcode("ld", "a,%s", s);
722 emitcode("ld", "%d(iy),a", offset);
725 emitcode("ld", "%d(iy),%s", offset, s);
729 if (!canAssignToPtr(s)) {
730 emitcode("ld", "a,%s", s);
731 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
734 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
738 /* if bit variable */
739 if (!aop->aopu.aop_dir) {
740 emitcode("ld", "a,#0");
743 /* In bit space but not in C - cant happen */
750 if (strcmp(aop->aopu.aop_str[offset],s)) {
751 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
757 if (!offset && (strcmp(s,"acc") == 0))
761 emitcode("", "; Error aopPut AOP_ACC");
764 if (strcmp(aop->aopu.aop_str[offset],s))
765 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
770 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
771 "aopPut got unsupported aop->type");
776 #define AOP(op) op->aop
777 #define AOP_TYPE(op) AOP(op)->type
778 #define AOP_SIZE(op) AOP(op)->size
779 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
781 /*-----------------------------------------------------------------*/
782 /* getDataSize - get the operand data size */
783 /*-----------------------------------------------------------------*/
784 int getDataSize(operand *op)
795 /*-----------------------------------------------------------------*/
796 /* movLeft2Result - move byte from left to result */
797 /*-----------------------------------------------------------------*/
798 static void movLeft2Result (operand *left, int offl,
799 operand *result, int offr, int sign)
802 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
803 l = aopGet(AOP(left),offl,FALSE);
806 aopPut(AOP(result),l,offr);
815 /** Put Acc into a register set
817 void outAcc(operand *result)
820 size = getDataSize(result);
822 aopPut(AOP(result),"a",0);
825 /* unsigned or positive */
827 aopPut(AOP(result),zero,offset++);
832 /** Take the value in carry and put it into a register
834 void outBitC(operand *result)
836 /* if the result is bit */
837 if (AOP_TYPE(result) == AOP_CRY) {
838 emitcode("", "; Note: outBitC form 1");
839 aopPut(AOP(result),"blah",0);
842 emitcode("ld", "a,#0");
848 /*-----------------------------------------------------------------*/
849 /* toBoolean - emit code for orl a,operator(sizeop) */
850 /*-----------------------------------------------------------------*/
851 void toBoolean(operand *oper)
853 int size = AOP_SIZE(oper);
856 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
859 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
863 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
867 /*-----------------------------------------------------------------*/
868 /* genNot - generate code for ! operation */
869 /*-----------------------------------------------------------------*/
870 static void genNot (iCode *ic)
872 link *optype = operandType(IC_LEFT(ic));
874 /* assign asmOps to operand & result */
875 aopOp (IC_LEFT(ic),ic,FALSE);
876 aopOp (IC_RESULT(ic),ic,TRUE);
878 /* if in bit space then a special case */
879 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
883 /* if type float then do float */
884 if (IS_FLOAT(optype)) {
888 toBoolean(IC_LEFT(ic));
893 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
894 emitcode("sub", "a,#0x01");
895 outBitC(IC_RESULT(ic));
897 /* release the aops */
898 freeAsmop(IC_LEFT(ic),NULL,ic);
899 freeAsmop(IC_RESULT(ic),NULL,ic);
902 /*-----------------------------------------------------------------*/
903 /* genCpl - generate code for complement */
904 /*-----------------------------------------------------------------*/
905 static void genCpl (iCode *ic)
911 /* assign asmOps to operand & result */
912 aopOp (IC_LEFT(ic),ic,FALSE);
913 aopOp (IC_RESULT(ic),ic,TRUE);
915 /* if both are in bit space then
917 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
918 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
922 size = AOP_SIZE(IC_RESULT(ic));
924 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
927 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
930 /* release the aops */
931 freeAsmop(IC_LEFT(ic),NULL,ic);
932 freeAsmop(IC_RESULT(ic),NULL,ic);
935 /*-----------------------------------------------------------------*/
936 /* genUminus - unary minus code generation */
937 /*-----------------------------------------------------------------*/
938 static void genUminus (iCode *ic)
941 link *optype, *rtype;
944 aopOp(IC_LEFT(ic),ic,FALSE);
945 aopOp(IC_RESULT(ic),ic,TRUE);
947 /* if both in bit space then special
949 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
950 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
955 optype = operandType(IC_LEFT(ic));
956 rtype = operandType(IC_RESULT(ic));
958 /* if float then do float stuff */
959 if (IS_FLOAT(optype)) {
964 /* otherwise subtract from zero */
965 size = AOP_SIZE(IC_LEFT(ic));
969 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
970 emitcode("ld", "a,#0");
971 emitcode("sbc","a,%s",l);
972 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
975 /* if any remaining bytes in the result */
976 /* we just need to propagate the sign */
977 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
979 emitcode("sbc","a,a");
981 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
985 /* release the aops */
986 freeAsmop(IC_LEFT(ic),NULL,ic);
987 freeAsmop(IC_RESULT(ic),NULL,ic);
991 /*-----------------------------------------------------------------*/
992 /* assignResultValue - */
993 /*-----------------------------------------------------------------*/
994 void assignResultValue(operand * oper)
997 int size = AOP_SIZE(oper);
999 aopPut(AOP(oper),fReturn[offset],offset);
1004 /*-----------------------------------------------------------------*/
1005 /* genIpush - genrate code for pushing this gets a little complex */
1006 /*-----------------------------------------------------------------*/
1007 static void genIpush (iCode *ic)
1009 int size, offset = 0 ;
1013 /* if this is not a parm push : ie. it is spill push
1014 and spill push is always done on the local stack */
1015 if (!ic->parmPush) {
1016 /* and the item is spilt then do nothing */
1017 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1020 aopOp(IC_LEFT(ic),ic,FALSE);
1021 size = AOP_SIZE(IC_LEFT(ic));
1022 /* push it on the stack */
1023 if (isPair(AOP(IC_LEFT(ic)))) {
1024 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1029 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1030 /* Simple for now - load into A and PUSH AF */
1031 emitcode("ld", "a,%s", l);
1032 emitcode("push", "af");
1033 emitcode("inc", "sp");
1039 /* Hmmm... what about saving the currently used registers
1042 /* then do the push */
1043 aopOp(IC_LEFT(ic),ic,FALSE);
1045 size = AOP_SIZE(IC_LEFT(ic));
1047 if (isPair(AOP(IC_LEFT(ic)))) {
1048 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1052 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1054 emitcode("ld", "hl,%s", s);
1055 emitcode("push", "hl");
1058 /* Optimise here - load into HL then push HL */
1059 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
1060 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
1061 emitcode("push", "hl");
1067 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1068 emitcode("ld", "a,%s", l);
1069 emitcode("push", "af");
1070 emitcode("inc", "sp");
1074 freeAsmop(IC_LEFT(ic),NULL,ic);
1077 /*-----------------------------------------------------------------*/
1078 /* genIpop - recover the registers: can happen only for spilling */
1079 /*-----------------------------------------------------------------*/
1080 static void genIpop (iCode *ic)
1085 /* if the temp was not pushed then */
1086 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1089 aopOp(IC_LEFT(ic),ic,FALSE);
1090 size = AOP_SIZE(IC_LEFT(ic));
1092 if (isPair(AOP(IC_LEFT(ic)))) {
1093 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1097 emitcode("dec", "sp");
1098 emitcode("pop", "hl");
1099 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1103 freeAsmop(IC_LEFT(ic),NULL,ic);
1106 /** Emit the code for a call statement
1108 static void emitCall (iCode *ic, bool ispcall)
1110 /* if caller saves & we have not saved then */
1111 if (!ic->regsSaved) {
1115 /* if send set is not empty then assign */
1119 for (sic = setFirstItem(sendSet) ; sic ;
1120 sic = setNextItem(sendSet)) {
1121 int size, offset = 0;
1122 aopOp(IC_LEFT(sic),sic,FALSE);
1123 size = AOP_SIZE(IC_LEFT(sic));
1125 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1127 if (strcmp(l,fReturn[offset]))
1128 emitcode("ld","%s,%s",
1133 freeAsmop (IC_LEFT(sic),NULL,sic);
1139 symbol *rlbl = newiTempLabel(NULL);
1141 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1142 emitcode("push", "hl");
1144 aopOp(IC_LEFT(ic),ic,FALSE);
1145 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1146 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1147 freeAsmop(IC_LEFT(ic),NULL,ic);
1149 emitcode("jp", "(hl)");
1150 emitcode("","%05d$:",(rlbl->key+100));
1154 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1155 OP_SYMBOL(IC_LEFT(ic))->rname :
1156 OP_SYMBOL(IC_LEFT(ic))->name));
1159 /* if we need assign a result value */
1160 if ((IS_ITEMP(IC_RESULT(ic)) &&
1161 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1162 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1163 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1166 aopOp(IC_RESULT(ic),ic,FALSE);
1169 assignResultValue(IC_RESULT(ic));
1171 freeAsmop(IC_RESULT(ic),NULL, ic);
1174 /* adjust the stack for parameters if required */
1175 if (IC_LEFT(ic)->parmBytes) {
1176 int i = IC_LEFT(ic)->parmBytes;
1178 emitcode("ld", "hl,#%d", i);
1179 emitcode("add", "hl,sp");
1180 emitcode("ld", "sp,hl");
1184 emitcode("pop", "hl");
1188 emitcode("inc", "sp");
1194 /*-----------------------------------------------------------------*/
1195 /* genCall - generates a call statement */
1196 /*-----------------------------------------------------------------*/
1197 static void genCall (iCode *ic)
1199 emitCall(ic, FALSE);
1202 /*-----------------------------------------------------------------*/
1203 /* genPcall - generates a call by pointer statement */
1204 /*-----------------------------------------------------------------*/
1205 static void genPcall (iCode *ic)
1210 /*-----------------------------------------------------------------*/
1211 /* resultRemat - result is rematerializable */
1212 /*-----------------------------------------------------------------*/
1213 static int resultRemat (iCode *ic)
1215 if (SKIP_IC(ic) || ic->op == IFX)
1218 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1219 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1220 if (sym->remat && !POINTER_SET(ic))
1227 /*-----------------------------------------------------------------*/
1228 /* genFunction - generated code for function entry */
1229 /*-----------------------------------------------------------------*/
1230 static void genFunction (iCode *ic)
1236 /* create the function header */
1237 emitcode(";","-----------------------------------------");
1238 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1239 emitcode(";","-----------------------------------------");
1241 emitcode("","%s:",sym->rname);
1242 fetype = getSpec(operandType(IC_LEFT(ic)));
1244 /* if critical function then turn interrupts off */
1245 if (SPEC_CRTCL(fetype))
1248 /* if this is an interrupt service routine then
1249 save acc, b, dpl, dph */
1250 if (IS_ISR(sym->etype)) {
1251 emitcode("push", "af");
1252 emitcode("push", "bc");
1253 emitcode("push", "de");
1254 emitcode("push", "hl");
1256 /* PENDING: callee-save etc */
1258 /* adjust the stack for the function */
1259 emitcode("push", "de");
1260 emitcode("push", "bc");
1261 emitcode("push", "ix");
1262 emitcode("ld", "ix,#0");
1263 emitcode("add", "ix,sp");
1265 _lastStack = sym->stack;
1268 emitcode("ld", "hl,#-%d", sym->stack);
1269 emitcode("add", "hl,sp");
1270 emitcode("ld", "sp,hl");
1274 /*-----------------------------------------------------------------*/
1275 /* genEndFunction - generates epilogue for functions */
1276 /*-----------------------------------------------------------------*/
1277 static void genEndFunction (iCode *ic)
1279 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1281 if (IS_ISR(sym->etype)) {
1285 if (SPEC_CRTCL(sym->etype))
1288 /* PENDING: calleeSave */
1290 /* if debug then send end of function */
1291 if (options.debug && currFunc) {
1293 emitcode("","C$%s$%d$%d$%d ==.",
1294 ic->filename,currFunc->lastLine,
1295 ic->level,ic->block);
1296 if (IS_STATIC(currFunc->etype))
1297 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1299 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1302 emitcode("ld", "sp,ix");
1303 emitcode("pop", "ix");
1304 emitcode("pop", "bc");
1305 emitcode("pop", "de");
1306 emitcode("ret", "");
1311 /*-----------------------------------------------------------------*/
1312 /* genRet - generate code for return statement */
1313 /*-----------------------------------------------------------------*/
1314 static void genRet (iCode *ic)
1317 /* Errk. This is a hack until I can figure out how
1318 to cause dehl to spill on a call */
1319 int size,offset = 0;
1321 /* if we have no return value then
1322 just generate the "ret" */
1326 /* we have something to return then
1327 move the return value into place */
1328 aopOp(IC_LEFT(ic),ic,FALSE);
1329 size = AOP_SIZE(IC_LEFT(ic));
1331 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1332 emitcode("ld", "hl,%s", l);
1336 l = aopGet(AOP(IC_LEFT(ic)),offset,
1338 if (strcmp(fReturn[offset],l))
1339 emitcode("ld","%s,%s",fReturn[offset++],l);
1342 freeAsmop (IC_LEFT(ic),NULL,ic);
1345 /* generate a jump to the return label
1346 if the next is not the return statement */
1347 if (!(ic->next && ic->next->op == LABEL &&
1348 IC_LABEL(ic->next) == returnLabel))
1350 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1353 /*-----------------------------------------------------------------*/
1354 /* genLabel - generates a label */
1355 /*-----------------------------------------------------------------*/
1356 static void genLabel (iCode *ic)
1358 /* special case never generate */
1359 if (IC_LABEL(ic) == entryLabel)
1362 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1365 /*-----------------------------------------------------------------*/
1366 /* genGoto - generates a ljmp */
1367 /*-----------------------------------------------------------------*/
1368 static void genGoto (iCode *ic)
1370 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1373 /*-----------------------------------------------------------------*/
1374 /* genPlusIncr :- does addition with increment if possible */
1375 /*-----------------------------------------------------------------*/
1376 static bool genPlusIncr (iCode *ic)
1378 unsigned int icount ;
1379 unsigned int size = getDataSize(IC_RESULT(ic));
1381 /* will try to generate an increment */
1382 /* if the right side is not a literal
1384 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1387 emitcode("", "; genPlusIncr");
1389 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1391 /* If result is a pair */
1392 if (isPair(AOP(IC_RESULT(ic)))) {
1393 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1395 /* Both a lit on the right and a true symbol on the left */
1396 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1401 /* if the literal value of the right hand side
1402 is greater than 4 then it is not worth it */
1407 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1408 isPair(AOP(IC_RESULT(ic)))) {
1410 emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
1414 /* if increment 16 bits in register */
1415 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1418 symbol *tlbl = newiTempLabel(NULL);
1419 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1420 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1422 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1426 emitcode("", LABEL_STR ":",tlbl->key+100);
1430 /* If result is a pair */
1431 if (isPair(AOP(IC_RESULT(ic)))) {
1432 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1433 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1435 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1439 /* if the sizes are greater than 1 then we cannot */
1440 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1441 AOP_SIZE(IC_LEFT(ic)) > 1 )
1444 /* we can if the aops of the left & result match or
1445 if they are in registers and the registers are the
1447 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1449 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1457 /*-----------------------------------------------------------------*/
1458 /* outBitAcc - output a bit in acc */
1459 /*-----------------------------------------------------------------*/
1460 void outBitAcc(operand *result)
1462 symbol *tlbl = newiTempLabel(NULL);
1463 /* if the result is a bit */
1464 if (AOP_TYPE(result) == AOP_CRY){
1468 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1469 emitcode("ld","a,%s",one);
1470 emitcode("", LABEL_STR ":",tlbl->key+100);
1475 /*-----------------------------------------------------------------*/
1476 /* genPlus - generates code for addition */
1477 /*-----------------------------------------------------------------*/
1478 static void genPlus (iCode *ic)
1480 int size, offset = 0;
1482 /* special cases :- */
1484 aopOp (IC_LEFT(ic),ic,FALSE);
1485 aopOp (IC_RIGHT(ic),ic,FALSE);
1486 aopOp (IC_RESULT(ic),ic,TRUE);
1488 /* Swap the left and right operands if:
1490 if literal, literal on the right or
1491 if left requires ACC or right is already
1494 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1495 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1496 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1497 operand *t = IC_RIGHT(ic);
1498 IC_RIGHT(ic) = IC_LEFT(ic);
1502 /* if both left & right are in bit
1504 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1505 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1510 /* if left in bit space & right literal */
1511 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1512 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1513 /* Can happen I guess */
1517 /* if I can do an increment instead
1518 of add then GOOD for ME */
1519 if (genPlusIncr (ic) == TRUE)
1522 size = getDataSize(IC_RESULT(ic));
1524 /* Special case when left and right are constant */
1525 if (isPair(AOP(IC_RESULT(ic)))) {
1528 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1529 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1530 if (left && right) {
1534 sprintf(buffer, "#(%s + %s)", left, right);
1535 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1541 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1542 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1544 emitcode("add","a,%s",
1545 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1547 emitcode("adc","a,%s",
1548 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1550 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1552 emitcode("add","a,%s",
1553 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1555 emitcode("adc","a,%s",
1556 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1558 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1561 /* Some kind of pointer arith. */
1562 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1563 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1564 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1567 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1568 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1569 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1574 freeAsmop(IC_LEFT(ic),NULL,ic);
1575 freeAsmop(IC_RIGHT(ic),NULL,ic);
1576 freeAsmop(IC_RESULT(ic),NULL,ic);
1580 /*-----------------------------------------------------------------*/
1581 /* genMinusDec :- does subtraction with deccrement if possible */
1582 /*-----------------------------------------------------------------*/
1583 static bool genMinusDec (iCode *ic)
1585 unsigned int icount ;
1586 unsigned int size = getDataSize(IC_RESULT(ic));
1588 /* will try to generate an increment */
1589 /* if the right side is not a literal we cannot */
1590 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1593 /* if the literal value of the right hand side
1594 is greater than 4 then it is not worth it */
1595 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1598 size = getDataSize(IC_RESULT(ic));
1599 /* if decrement 16 bits in register */
1600 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1601 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1603 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1607 /* If result is a pair */
1608 if (isPair(AOP(IC_RESULT(ic)))) {
1609 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1610 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1612 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1616 /* if the sizes are greater than 1 then we cannot */
1617 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1618 AOP_SIZE(IC_LEFT(ic)) > 1 )
1621 /* we can if the aops of the left & result match or if they are in
1622 registers and the registers are the same */
1623 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1625 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1632 /*-----------------------------------------------------------------*/
1633 /* genMinus - generates code for subtraction */
1634 /*-----------------------------------------------------------------*/
1635 static void genMinus (iCode *ic)
1637 int size, offset = 0;
1638 unsigned long lit = 0L;
1640 aopOp (IC_LEFT(ic),ic,FALSE);
1641 aopOp (IC_RIGHT(ic),ic,FALSE);
1642 aopOp (IC_RESULT(ic),ic,TRUE);
1644 /* special cases :- */
1645 /* if both left & right are in bit space */
1646 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1647 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1652 /* if I can do an decrement instead of subtract then GOOD for ME */
1653 if (genMinusDec (ic) == TRUE)
1656 size = getDataSize(IC_RESULT(ic));
1658 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1661 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1666 /* if literal, add a,#-lit, else normal subb */
1668 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1669 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1671 emitcode("sub","a,%s",
1672 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1674 emitcode("sbc","a,%s",
1675 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1678 /* first add without previous c */
1680 emitcode("add","a,#0x%02x",
1681 (unsigned int)(lit & 0x0FFL));
1683 emitcode("adc","a,#0x%02x",
1684 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1686 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1689 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1690 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1691 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1695 freeAsmop(IC_LEFT(ic),NULL,ic);
1696 freeAsmop(IC_RIGHT(ic),NULL,ic);
1697 freeAsmop(IC_RESULT(ic),NULL,ic);
1700 /*-----------------------------------------------------------------*/
1701 /* genMult - generates code for multiplication */
1702 /*-----------------------------------------------------------------*/
1703 static void genMult (iCode *ic)
1705 /* Shouldn't occur - all done through function calls */
1709 /*-----------------------------------------------------------------*/
1710 /* genDiv - generates code for division */
1711 /*-----------------------------------------------------------------*/
1712 static void genDiv (iCode *ic)
1714 /* Shouldn't occur - all done through function calls */
1718 /*-----------------------------------------------------------------*/
1719 /* genMod - generates code for division */
1720 /*-----------------------------------------------------------------*/
1721 static void genMod (iCode *ic)
1723 /* Shouldn't occur - all done through function calls */
1727 /*-----------------------------------------------------------------*/
1728 /* genIfxJump :- will create a jump depending on the ifx */
1729 /*-----------------------------------------------------------------*/
1730 static void genIfxJump (iCode *ic, char *jval)
1735 /* if true label then we jump if condition
1737 if ( IC_TRUE(ic) ) {
1739 if (!strcmp(jval, "a")) {
1742 else if (!strcmp(jval, "c")) {
1746 /* The buffer contains the bit on A that we should test */
1751 /* false label is present */
1752 jlbl = IC_FALSE(ic) ;
1753 if (!strcmp(jval, "a")) {
1756 else if (!strcmp(jval, "c")) {
1760 /* The buffer contains the bit on A that we should test */
1764 /* Z80 can do a conditional long jump */
1765 if (!strcmp(jval, "a")) {
1766 emitcode("or", "a,a");
1768 else if (!strcmp(jval, "c")) {
1771 emitcode("bit", "%s,a", jval);
1773 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1775 /* mark the icode as generated */
1779 /** Generic compare for > or <
1781 static void genCmp (operand *left,operand *right,
1782 operand *result, iCode *ifx, int sign)
1784 int size, offset = 0 ;
1785 unsigned long lit = 0L;
1787 /* if left & right are bit variables */
1788 if (AOP_TYPE(left) == AOP_CRY &&
1789 AOP_TYPE(right) == AOP_CRY ) {
1790 /* Cant happen on the Z80 */
1793 /* subtract right from left if at the
1794 end the carry flag is set then we know that
1795 left is greater than right */
1796 size = max(AOP_SIZE(left),AOP_SIZE(right));
1798 /* if unsigned char cmp with lit, just compare */
1800 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1801 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1803 emitcode("xor", "a,#0x80");
1804 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1807 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1810 if(AOP_TYPE(right) == AOP_LIT) {
1811 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1812 /* optimize if(x < 0) or if(x >= 0) */
1815 /* No sign so it's always false */
1819 /* Just load in the top most bit */
1820 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1821 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1822 genIfxJump (ifx,"7");
1826 emitcode("rlc","a");
1832 /* First setup h and l contaning the top most bytes XORed */
1833 bool fDidXor = FALSE;
1834 if (AOP_TYPE(left) == AOP_LIT){
1835 unsigned long lit = (unsigned long)
1836 floatFromVal(AOP(left)->aopu.aop_lit);
1837 emitcode("ld", "l,#0x%02x",
1838 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1841 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1842 emitcode("xor", "a,#0x80");
1843 emitcode("ld", "l,a");
1846 if (AOP_TYPE(right) == AOP_LIT) {
1847 unsigned long lit = (unsigned long)
1848 floatFromVal(AOP(right)->aopu.aop_lit);
1849 emitcode("ld", "h,#0x%02x",
1850 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1853 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1854 emitcode("xor", "a,#0x80");
1855 emitcode("ld", "h,a");
1865 /* Do a long subtract */
1867 MOVA(aopGet(AOP(left),offset,FALSE));
1868 if (sign && size == 0) {
1869 emitcode("ld", "a,l");
1870 emitcode("sbc", "a,h");
1873 /* Subtract through, propagating the carry */
1874 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1881 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1884 /* if the result is used in the next
1885 ifx conditional branch then generate
1886 code a little differently */
1888 genIfxJump (ifx,"c");
1891 /* leave the result in acc */
1895 /*-----------------------------------------------------------------*/
1896 /* genCmpGt :- greater than comparison */
1897 /*-----------------------------------------------------------------*/
1898 static void genCmpGt (iCode *ic, iCode *ifx)
1900 operand *left, *right, *result;
1901 link *letype , *retype;
1905 right= IC_RIGHT(ic);
1906 result = IC_RESULT(ic);
1908 letype = getSpec(operandType(left));
1909 retype =getSpec(operandType(right));
1910 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1911 /* assign the amsops */
1912 aopOp (left,ic,FALSE);
1913 aopOp (right,ic,FALSE);
1914 aopOp (result,ic,TRUE);
1916 genCmp(right, left, result, ifx, sign);
1918 freeAsmop(left,NULL,ic);
1919 freeAsmop(right,NULL,ic);
1920 freeAsmop(result,NULL,ic);
1923 /*-----------------------------------------------------------------*/
1924 /* genCmpLt - less than comparisons */
1925 /*-----------------------------------------------------------------*/
1926 static void genCmpLt (iCode *ic, iCode *ifx)
1928 operand *left, *right, *result;
1929 link *letype , *retype;
1933 right= IC_RIGHT(ic);
1934 result = IC_RESULT(ic);
1936 letype = getSpec(operandType(left));
1937 retype =getSpec(operandType(right));
1938 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1940 /* assign the amsops */
1941 aopOp (left,ic,FALSE);
1942 aopOp (right,ic,FALSE);
1943 aopOp (result,ic,TRUE);
1945 genCmp(left, right, result, ifx, sign);
1947 freeAsmop(left,NULL,ic);
1948 freeAsmop(right,NULL,ic);
1949 freeAsmop(result,NULL,ic);
1952 /*-----------------------------------------------------------------*/
1953 /* gencjneshort - compare and jump if not equal */
1954 /*-----------------------------------------------------------------*/
1955 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1957 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1959 unsigned long lit = 0L;
1961 /* Swap the left and right if it makes the computation easier */
1962 if (AOP_TYPE(left) == AOP_LIT) {
1968 if(AOP_TYPE(right) == AOP_LIT)
1969 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1971 /* if the right side is a literal then anything goes */
1972 if (AOP_TYPE(right) == AOP_LIT &&
1973 AOP_TYPE(left) != AOP_DIR ) {
1975 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1976 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1977 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1981 /* if the right side is in a register or in direct space or
1982 if the left is a pointer register & right is not */
1983 else if (AOP_TYPE(right) == AOP_REG ||
1984 AOP_TYPE(right) == AOP_DIR ||
1985 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1987 MOVA(aopGet(AOP(left),offset,FALSE));
1988 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1989 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1991 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1993 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1994 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1999 /* right is a pointer reg need both a & b */
2000 /* PENDING: is this required? */
2002 char *l = aopGet(AOP(left),offset,FALSE);
2003 MOVA(aopGet(AOP(right),offset,FALSE));
2004 emitcode("cp", "%s", l);
2005 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2011 /*-----------------------------------------------------------------*/
2012 /* gencjne - compare and jump if not equal */
2013 /*-----------------------------------------------------------------*/
2014 static void gencjne(operand *left, operand *right, symbol *lbl)
2016 symbol *tlbl = newiTempLabel(NULL);
2018 gencjneshort(left, right, lbl);
2021 emitcode("ld","a,%s",one);
2022 emitcode("jp", LABEL_STR ,tlbl->key+100);
2023 emitcode("", LABEL_STR ":",lbl->key+100);
2024 emitcode("xor","a,a");
2025 emitcode("", LABEL_STR ":",tlbl->key+100);
2028 /*-----------------------------------------------------------------*/
2029 /* genCmpEq - generates code for equal to */
2030 /*-----------------------------------------------------------------*/
2031 static void genCmpEq (iCode *ic, iCode *ifx)
2033 operand *left, *right, *result;
2035 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2036 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2037 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2039 /* Swap operands if it makes the operation easier. ie if:
2040 1. Left is a literal.
2042 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2043 operand *t = IC_RIGHT(ic);
2044 IC_RIGHT(ic) = IC_LEFT(ic);
2048 if (ifx && !AOP_SIZE(result)){
2050 /* if they are both bit variables */
2051 if (AOP_TYPE(left) == AOP_CRY &&
2052 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2055 tlbl = newiTempLabel(NULL);
2056 gencjneshort(left, right, tlbl);
2057 if ( IC_TRUE(ifx) ) {
2058 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2059 emitcode("", LABEL_STR ":",tlbl->key+100);
2061 /* PENDING: do this better */
2062 symbol *lbl = newiTempLabel(NULL);
2063 emitcode("jp", LABEL_STR ,lbl->key+100);
2064 emitcode("", LABEL_STR ":",tlbl->key+100);
2065 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2066 emitcode("", LABEL_STR ":",lbl->key+100);
2069 /* mark the icode as generated */
2074 /* if they are both bit variables */
2075 if (AOP_TYPE(left) == AOP_CRY &&
2076 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2079 gencjne(left,right,newiTempLabel(NULL));
2080 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2084 genIfxJump(ifx,"a");
2087 /* if the result is used in an arithmetic operation
2088 then put the result in place */
2089 if (AOP_TYPE(result) != AOP_CRY) {
2092 /* leave the result in acc */
2096 freeAsmop(left,NULL,ic);
2097 freeAsmop(right,NULL,ic);
2098 freeAsmop(result,NULL,ic);
2101 /*-----------------------------------------------------------------*/
2102 /* ifxForOp - returns the icode containing the ifx for operand */
2103 /*-----------------------------------------------------------------*/
2104 static iCode *ifxForOp ( operand *op, iCode *ic )
2106 /* if true symbol then needs to be assigned */
2107 if (IS_TRUE_SYMOP(op))
2110 /* if this has register type condition and
2111 the next instruction is ifx with the same operand
2112 and live to of the operand is upto the ifx only then */
2114 ic->next->op == IFX &&
2115 IC_COND(ic->next)->key == op->key &&
2116 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2122 /*-----------------------------------------------------------------*/
2123 /* genAndOp - for && operation */
2124 /*-----------------------------------------------------------------*/
2125 static void genAndOp (iCode *ic)
2127 operand *left,*right, *result;
2130 /* note here that && operations that are in an if statement are
2131 taken away by backPatchLabels only those used in arthmetic
2132 operations remain */
2133 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2134 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2135 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2137 /* if both are bit variables */
2138 if (AOP_TYPE(left) == AOP_CRY &&
2139 AOP_TYPE(right) == AOP_CRY ) {
2142 tlbl = newiTempLabel(NULL);
2144 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2146 emitcode("", LABEL_STR ":",tlbl->key+100);
2150 freeAsmop(left,NULL,ic);
2151 freeAsmop(right,NULL,ic);
2152 freeAsmop(result,NULL,ic);
2155 /*-----------------------------------------------------------------*/
2156 /* genOrOp - for || operation */
2157 /*-----------------------------------------------------------------*/
2158 static void genOrOp (iCode *ic)
2160 operand *left,*right, *result;
2163 /* note here that || operations that are in an
2164 if statement are taken away by backPatchLabels
2165 only those used in arthmetic operations remain */
2166 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2167 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2168 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2170 /* if both are bit variables */
2171 if (AOP_TYPE(left) == AOP_CRY &&
2172 AOP_TYPE(right) == AOP_CRY ) {
2175 tlbl = newiTempLabel(NULL);
2177 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2179 emitcode("", LABEL_STR,tlbl->key+100);
2183 freeAsmop(left,NULL,ic);
2184 freeAsmop(right,NULL,ic);
2185 freeAsmop(result,NULL,ic);
2188 /*-----------------------------------------------------------------*/
2189 /* isLiteralBit - test if lit == 2^n */
2190 /*-----------------------------------------------------------------*/
2191 int isLiteralBit(unsigned long lit)
2193 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2194 0x100L,0x200L,0x400L,0x800L,
2195 0x1000L,0x2000L,0x4000L,0x8000L,
2196 0x10000L,0x20000L,0x40000L,0x80000L,
2197 0x100000L,0x200000L,0x400000L,0x800000L,
2198 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2199 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2202 for(idx = 0; idx < 32; idx++)
2208 /*-----------------------------------------------------------------*/
2209 /* genAnd - code for and */
2210 /*-----------------------------------------------------------------*/
2211 static void genAnd (iCode *ic, iCode *ifx)
2213 operand *left, *right, *result;
2215 unsigned long lit = 0L;
2218 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2219 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2220 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2223 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2225 AOP_TYPE(left), AOP_TYPE(right));
2226 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2228 AOP_SIZE(left), AOP_SIZE(right));
2231 /* if left is a literal & right is not then exchange them */
2232 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2233 AOP_NEEDSACC(left)) {
2234 operand *tmp = right ;
2239 /* if result = right then exchange them */
2240 if(sameRegs(AOP(result),AOP(right))){
2241 operand *tmp = right ;
2246 /* if right is bit then exchange them */
2247 if (AOP_TYPE(right) == AOP_CRY &&
2248 AOP_TYPE(left) != AOP_CRY){
2249 operand *tmp = right ;
2253 if(AOP_TYPE(right) == AOP_LIT)
2254 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2256 size = AOP_SIZE(result);
2258 if (AOP_TYPE(left) == AOP_CRY){
2263 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2264 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2265 if((AOP_TYPE(right) == AOP_LIT) &&
2266 (AOP_TYPE(result) == AOP_CRY) &&
2267 (AOP_TYPE(left) != AOP_CRY)) {
2268 int posbit = isLiteralBit(lit);
2272 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2276 emitcode("mov","c,acc.%d",posbit&0x07);
2281 sprintf(buffer, "%d", posbit&0x07);
2282 genIfxJump(ifx, buffer);
2290 symbol *tlbl = newiTempLabel(NULL);
2291 int sizel = AOP_SIZE(left);
2294 emitcode("setb","c");
2297 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2298 MOVA( aopGet(AOP(left),offset,FALSE));
2300 if((posbit = isLiteralBit(bytelit)) != 0) {
2302 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2305 if(bytelit != 0x0FFL)
2306 emitcode("and","a,%s",
2307 aopGet(AOP(right),offset,FALSE));
2308 emitcode("jr","nz, %05d$",tlbl->key+100);
2313 // bit = left & literal
2315 emitcode("clr","c");
2316 emitcode("","%05d$:",tlbl->key+100);
2318 // if(left & literal)
2322 jmpTrueOrFalse(ifx, tlbl);
2333 /* if left is same as result */
2334 if(sameRegs(AOP(result),AOP(left))){
2335 for(;size--; offset++) {
2336 if(AOP_TYPE(right) == AOP_LIT){
2337 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2341 aopPut(AOP(result),zero,offset);
2343 MOVA(aopGet(AOP(left),offset,FALSE));
2344 emitcode("and","a,%s",
2345 aopGet(AOP(right),offset,FALSE));
2346 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2351 if (AOP_TYPE(left) == AOP_ACC) {
2355 MOVA(aopGet(AOP(right),offset,FALSE));
2356 emitcode("and","%s,a",
2357 aopGet(AOP(left),offset,FALSE));
2362 // left & result in different registers
2363 if(AOP_TYPE(result) == AOP_CRY){
2366 for(;(size--);offset++) {
2368 // result = left & right
2369 if(AOP_TYPE(right) == AOP_LIT){
2370 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2372 aopGet(AOP(left),offset,FALSE),
2375 } else if(bytelit == 0){
2376 aopPut(AOP(result),zero,offset);
2380 // faster than result <- left, anl result,right
2381 // and better if result is SFR
2382 if (AOP_TYPE(left) == AOP_ACC)
2383 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2385 MOVA(aopGet(AOP(right),offset,FALSE));
2386 emitcode("and","a,%s",
2387 aopGet(AOP(left),offset,FALSE));
2389 aopPut(AOP(result),"a",offset);
2396 freeAsmop(left,NULL,ic);
2397 freeAsmop(right,NULL,ic);
2398 freeAsmop(result,NULL,ic);
2401 /*-----------------------------------------------------------------*/
2402 /* genOr - code for or */
2403 /*-----------------------------------------------------------------*/
2404 static void genOr (iCode *ic, iCode *ifx)
2406 operand *left, *right, *result;
2408 unsigned long lit = 0L;
2410 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2411 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2412 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2415 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2417 AOP_TYPE(left), AOP_TYPE(right));
2418 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2420 AOP_SIZE(left), AOP_SIZE(right));
2423 /* if left is a literal & right is not then exchange them */
2424 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2425 AOP_NEEDSACC(left)) {
2426 operand *tmp = right ;
2431 /* if result = right then exchange them */
2432 if(sameRegs(AOP(result),AOP(right))){
2433 operand *tmp = right ;
2438 /* if right is bit then exchange them */
2439 if (AOP_TYPE(right) == AOP_CRY &&
2440 AOP_TYPE(left) != AOP_CRY){
2441 operand *tmp = right ;
2445 if(AOP_TYPE(right) == AOP_LIT)
2446 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2448 size = AOP_SIZE(result);
2450 if (AOP_TYPE(left) == AOP_CRY){
2455 if((AOP_TYPE(right) == AOP_LIT) &&
2456 (AOP_TYPE(result) == AOP_CRY) &&
2457 (AOP_TYPE(left) != AOP_CRY)){
2462 /* if left is same as result */
2463 if(sameRegs(AOP(result),AOP(left))){
2464 for(;size--; offset++) {
2465 if(AOP_TYPE(right) == AOP_LIT){
2466 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2469 emitcode("or","%s,%s; 5",
2470 aopGet(AOP(left),offset,FALSE),
2471 aopGet(AOP(right),offset,FALSE));
2473 if (AOP_TYPE(left) == AOP_ACC)
2474 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2476 MOVA(aopGet(AOP(right),offset,FALSE));
2477 emitcode("or","a,%s ; 7",
2478 aopGet(AOP(left),offset,FALSE));
2479 aopPut(AOP(result),"a ; 8",0);
2484 // left & result in different registers
2485 if(AOP_TYPE(result) == AOP_CRY){
2487 } else for(;(size--);offset++){
2489 // result = left & right
2490 if(AOP_TYPE(right) == AOP_LIT){
2491 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2493 aopGet(AOP(left),offset,FALSE),
2498 // faster than result <- left, anl result,right
2499 // and better if result is SFR
2500 if (AOP_TYPE(left) == AOP_ACC)
2501 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2503 MOVA(aopGet(AOP(right),offset,FALSE));
2504 emitcode("or","a,%s",
2505 aopGet(AOP(left),offset,FALSE));
2507 aopPut(AOP(result),"a",offset);
2508 /* PENDING: something weird is going on here. Add exception. */
2509 if (AOP_TYPE(result) == AOP_ACC)
2515 freeAsmop(left,NULL,ic);
2516 freeAsmop(right,NULL,ic);
2517 freeAsmop(result,NULL,ic);
2520 /*-----------------------------------------------------------------*/
2521 /* genXor - code for xclusive or */
2522 /*-----------------------------------------------------------------*/
2523 static void genXor (iCode *ic, iCode *ifx)
2525 operand *left, *right, *result;
2527 unsigned long lit = 0L;
2529 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2530 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2531 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2533 /* if left is a literal & right is not then exchange them */
2534 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2535 AOP_NEEDSACC(left)) {
2536 operand *tmp = right ;
2541 /* if result = right then exchange them */
2542 if(sameRegs(AOP(result),AOP(right))){
2543 operand *tmp = right ;
2548 /* if right is bit then exchange them */
2549 if (AOP_TYPE(right) == AOP_CRY &&
2550 AOP_TYPE(left) != AOP_CRY){
2551 operand *tmp = right ;
2555 if(AOP_TYPE(right) == AOP_LIT)
2556 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2558 size = AOP_SIZE(result);
2560 if (AOP_TYPE(left) == AOP_CRY){
2565 if((AOP_TYPE(right) == AOP_LIT) &&
2566 (AOP_TYPE(result) == AOP_CRY) &&
2567 (AOP_TYPE(left) != AOP_CRY)){
2572 /* if left is same as result */
2573 if(sameRegs(AOP(result),AOP(left))){
2574 for(;size--; offset++) {
2575 if(AOP_TYPE(right) == AOP_LIT){
2576 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2579 MOVA(aopGet(AOP(right),offset,FALSE));
2580 emitcode("xor","a,%s",
2581 aopGet(AOP(left),offset,FALSE));
2582 aopPut(AOP(result),"a",0);
2585 if (AOP_TYPE(left) == AOP_ACC)
2586 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2588 MOVA(aopGet(AOP(right),offset,FALSE));
2589 emitcode("xor","a,%s",
2590 aopGet(AOP(left),offset,FALSE));
2591 aopPut(AOP(result),"a",0);
2596 // left & result in different registers
2597 if(AOP_TYPE(result) == AOP_CRY){
2599 } else for(;(size--);offset++){
2601 // result = left & right
2602 if(AOP_TYPE(right) == AOP_LIT){
2603 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2605 aopGet(AOP(left),offset,FALSE),
2610 // faster than result <- left, anl result,right
2611 // and better if result is SFR
2612 if (AOP_TYPE(left) == AOP_ACC)
2613 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2615 MOVA(aopGet(AOP(right),offset,FALSE));
2616 emitcode("xor","a,%s",
2617 aopGet(AOP(left),offset,FALSE));
2618 aopPut(AOP(result),"a",0);
2620 aopPut(AOP(result),"a",offset);
2625 freeAsmop(left,NULL,ic);
2626 freeAsmop(right,NULL,ic);
2627 freeAsmop(result,NULL,ic);
2630 /*-----------------------------------------------------------------*/
2631 /* genInline - write the inline code out */
2632 /*-----------------------------------------------------------------*/
2633 static void genInline (iCode *ic)
2635 char buffer[MAX_INLINEASM];
2639 inLine += (!options.asmpeep);
2640 strcpy(buffer,IC_INLINE(ic));
2642 /* emit each line as a code */
2661 /* emitcode("",buffer); */
2662 inLine -= (!options.asmpeep);
2665 /*-----------------------------------------------------------------*/
2666 /* genRRC - rotate right with carry */
2667 /*-----------------------------------------------------------------*/
2668 static void genRRC (iCode *ic)
2673 /*-----------------------------------------------------------------*/
2674 /* genRLC - generate code for rotate left with carry */
2675 /*-----------------------------------------------------------------*/
2676 static void genRLC (iCode *ic)
2681 /*-----------------------------------------------------------------*/
2682 /* shiftR2Left2Result - shift right two bytes from left to result */
2683 /*-----------------------------------------------------------------*/
2684 static void shiftR2Left2Result (operand *left, int offl,
2685 operand *result, int offr,
2686 int shCount, int sign)
2688 if(sameRegs(AOP(result), AOP(left)) &&
2689 ((offl + MSB16) == offr)){
2692 movLeft2Result(left, offl, result, offr, 0);
2693 movLeft2Result(left, offl+1, result, offr+1, 0);
2700 /* if (AOP(result)->type == AOP_REG) {*/
2703 symbol *tlbl , *tlbl1;
2706 /* Left is already in result - so now do the shift */
2708 emitcode("ld","a,#%u+1", shCount);
2709 tlbl = newiTempLabel(NULL);
2710 tlbl1 = newiTempLabel(NULL);
2711 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2712 emitcode("", LABEL_STR ":",tlbl->key+100);
2715 emitcode("or", "a,a");
2718 l = aopGet(AOP(result), --offset, FALSE);
2719 emitcode("rr","%s", l);
2722 emitcode("", LABEL_STR ":",tlbl1->key+100);
2723 emitcode("dec", "a");
2724 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2729 /*-----------------------------------------------------------------*/
2730 /* shiftL2Left2Result - shift left two bytes from left to result */
2731 /*-----------------------------------------------------------------*/
2732 static void shiftL2Left2Result (operand *left, int offl,
2733 operand *result, int offr, int shCount)
2735 if(sameRegs(AOP(result), AOP(left)) &&
2736 ((offl + MSB16) == offr)){
2739 /* Copy left into result */
2740 movLeft2Result(left, offl, result, offr, 0);
2741 movLeft2Result(left, offl+1, result, offr+1, 0);
2743 /* PENDING: for now just see if it'll work. */
2744 /*if (AOP(result)->type == AOP_REG) { */
2748 symbol *tlbl , *tlbl1;
2751 /* Left is already in result - so now do the shift */
2753 emitcode("ld","a,#%u+1", shCount);
2754 tlbl = newiTempLabel(NULL);
2755 tlbl1 = newiTempLabel(NULL);
2756 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2757 emitcode("", LABEL_STR ":",tlbl->key+100);
2760 emitcode("or", "a,a");
2762 l = aopGet(AOP(result),offset++,FALSE);
2763 emitcode("rl","%s", l);
2766 emitcode("", LABEL_STR ":",tlbl1->key+100);
2767 emitcode("dec", "a");
2768 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2773 /*-----------------------------------------------------------------*/
2774 /* AccRol - rotate left accumulator by known count */
2775 /*-----------------------------------------------------------------*/
2776 static void AccRol (int shCount)
2778 shCount &= 0x0007; // shCount : 0..7
2815 /*-----------------------------------------------------------------*/
2816 /* AccLsh - left shift accumulator by known count */
2817 /*-----------------------------------------------------------------*/
2818 static void AccLsh (int shCount)
2822 emitcode("add","a,a");
2825 emitcode("add","a,a");
2826 emitcode("add","a,a");
2828 /* rotate left accumulator */
2830 /* and kill the lower order bits */
2831 emitcode("and","a,#0x%02x", SLMask[shCount]);
2836 /*-----------------------------------------------------------------*/
2837 /* shiftL1Left2Result - shift left one byte from left to result */
2838 /*-----------------------------------------------------------------*/
2839 static void shiftL1Left2Result (operand *left, int offl,
2840 operand *result, int offr, int shCount)
2843 l = aopGet(AOP(left),offl,FALSE);
2845 /* shift left accumulator */
2847 aopPut(AOP(result),"a",offr);
2851 /*-----------------------------------------------------------------*/
2852 /* genlshTwo - left shift two bytes by known amount != 0 */
2853 /*-----------------------------------------------------------------*/
2854 static void genlshTwo (operand *result,operand *left, int shCount)
2856 int size = AOP_SIZE(result);
2860 /* if shCount >= 8 */
2866 movLeft2Result(left, LSB, result, MSB16, 0);
2867 aopPut(AOP(result),zero, 0);
2868 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2871 movLeft2Result(left, LSB, result, MSB16, 0);
2872 aopPut(AOP(result),zero, 0);
2875 aopPut(AOP(result),zero,LSB);
2877 /* 1 <= shCount <= 7 */
2883 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2888 /*-----------------------------------------------------------------*/
2889 /* genlshOne - left shift a one byte quantity by known count */
2890 /*-----------------------------------------------------------------*/
2891 static void genlshOne (operand *result, operand *left, int shCount)
2893 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2896 /*-----------------------------------------------------------------*/
2897 /* genLeftShiftLiteral - left shifting by known count */
2898 /*-----------------------------------------------------------------*/
2899 static void genLeftShiftLiteral (operand *left,
2904 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2907 freeAsmop(right,NULL,ic);
2909 aopOp(left,ic,FALSE);
2910 aopOp(result,ic,FALSE);
2912 size = getSize(operandType(result));
2915 emitcode("; shift left ","result %d, left %d",size,
2919 /* I suppose that the left size >= result size */
2924 else if(shCount >= (size * 8))
2926 aopPut(AOP(result),zero,size);
2930 genlshOne (result,left,shCount);
2933 genlshTwo (result,left,shCount);
2942 freeAsmop(left,NULL,ic);
2943 freeAsmop(result,NULL,ic);
2946 /*-----------------------------------------------------------------*/
2947 /* genLeftShift - generates code for left shifting */
2948 /*-----------------------------------------------------------------*/
2949 static void genLeftShift (iCode *ic)
2953 symbol *tlbl , *tlbl1;
2954 operand *left,*right, *result;
2956 right = IC_RIGHT(ic);
2958 result = IC_RESULT(ic);
2960 aopOp(right,ic,FALSE);
2962 /* if the shift count is known then do it
2963 as efficiently as possible */
2964 if (AOP_TYPE(right) == AOP_LIT) {
2965 genLeftShiftLiteral (left,right,result,ic);
2969 /* shift count is unknown then we have to form a loop get the loop
2970 count in B : Note: we take only the lower order byte since
2971 shifting more that 32 bits make no sense anyway, ( the largest
2972 size of an object can be only 32 bits ) */
2973 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2974 emitcode("inc","a");
2975 freeAsmop (right,NULL,ic);
2976 aopOp(left,ic,FALSE);
2977 aopOp(result,ic,FALSE);
2979 /* now move the left to the result if they are not the
2982 if (!sameRegs(AOP(left),AOP(result))) {
2984 size = AOP_SIZE(result);
2987 l = aopGet(AOP(left),offset,FALSE);
2988 aopPut(AOP(result),l,offset);
2993 size = AOP_SIZE(result);
2996 l = aopGet(AOP(left),offset,FALSE);
2997 aopPut(AOP(result),l,offset);
3003 tlbl = newiTempLabel(NULL);
3004 size = AOP_SIZE(result);
3006 tlbl1 = newiTempLabel(NULL);
3008 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3009 emitcode("", LABEL_STR ":",tlbl->key+100);
3010 l = aopGet(AOP(result),offset,FALSE);
3011 emitcode("or", "a,a");
3013 l = aopGet(AOP(result),offset++,FALSE);
3014 emitcode("rl","%s", l);
3016 emitcode("", LABEL_STR ":",tlbl1->key+100);
3017 emitcode("dec", "a");
3018 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3020 freeAsmop(left,NULL,ic);
3021 freeAsmop(result,NULL,ic);
3024 /* genlshTwo - left shift two bytes by known amount != 0 */
3025 /*-----------------------------------------------------------------*/
3026 static void genrshOne (operand *result,operand *left, int shCount)
3029 int size = AOP_SIZE(result);
3035 l = aopGet(AOP(left),0,FALSE);
3036 if (AOP(result)->type == AOP_REG) {
3037 aopPut(AOP(result), l, 0);
3038 l = aopGet(AOP(result), 0, FALSE);
3040 emitcode("srl", "%s", l);
3045 emitcode("srl", "a");
3047 aopPut(AOP(result),"a",0);
3051 /*-----------------------------------------------------------------*/
3052 /* AccRsh - right shift accumulator by known count */
3053 /*-----------------------------------------------------------------*/
3054 static void AccRsh (int shCount)
3061 /* rotate right accumulator */
3062 AccRol(8 - shCount);
3063 /* and kill the higher order bits */
3064 emitcode("and","a,#0x%02x", SRMask[shCount]);
3069 /*-----------------------------------------------------------------*/
3070 /* shiftR1Left2Result - shift right one byte from left to result */
3071 /*-----------------------------------------------------------------*/
3072 static void shiftR1Left2Result (operand *left, int offl,
3073 operand *result, int offr,
3074 int shCount, int sign)
3076 MOVA(aopGet(AOP(left),offl,FALSE));
3083 aopPut(AOP(result),"a",offr);
3086 /*-----------------------------------------------------------------*/
3087 /* genrshTwo - right shift two bytes by known amount != 0 */
3088 /*-----------------------------------------------------------------*/
3089 static void genrshTwo (operand *result,operand *left,
3090 int shCount, int sign)
3092 /* if shCount >= 8 */
3097 shiftR1Left2Result(left, MSB16, result, LSB,
3101 movLeft2Result(left, MSB16, result, LSB, sign);
3102 aopPut(AOP(result),zero,1);
3105 /* 1 <= shCount <= 7 */
3107 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3111 /*-----------------------------------------------------------------*/
3112 /* genRightShiftLiteral - left shifting by known count */
3113 /*-----------------------------------------------------------------*/
3114 static void genRightShiftLiteral (operand *left,
3119 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3122 freeAsmop(right,NULL,ic);
3124 aopOp(left,ic,FALSE);
3125 aopOp(result,ic,FALSE);
3127 size = getSize(operandType(result));
3129 emitcode("; shift right ","result %d, left %d",size,
3132 /* I suppose that the left size >= result size */
3137 else if(shCount >= (size * 8))
3139 aopPut(AOP(result),zero,size);
3143 genrshOne(result, left, shCount);
3146 /* PENDING: sign support */
3147 genrshTwo(result, left, shCount, FALSE);
3156 freeAsmop(left,NULL,ic);
3157 freeAsmop(result,NULL,ic);
3160 /*-----------------------------------------------------------------*/
3161 /* genRightShift - generate code for right shifting */
3162 /*-----------------------------------------------------------------*/
3163 static void genRightShift (iCode *ic)
3165 operand *left,*right, *result;
3167 right = IC_RIGHT(ic);
3169 result = IC_RESULT(ic);
3171 aopOp(right,ic,FALSE);
3173 /* if the shift count is known then do it
3174 as efficiently as possible */
3175 if (AOP_TYPE(right) == AOP_LIT) {
3176 genRightShiftLiteral (left,right,result,ic);
3184 /*-----------------------------------------------------------------*/
3185 /* genGenPointerGet - gget value from generic pointer space */
3186 /*-----------------------------------------------------------------*/
3187 static void genGenPointerGet (operand *left,
3188 operand *result, iCode *ic)
3191 link *retype = getSpec(operandType(result));
3193 aopOp(left,ic,FALSE);
3194 aopOp(result,ic,FALSE);
3196 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3198 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3199 aopPut(AOP(result),"a", 0);
3200 freeAsmop(left,NULL,ic);
3204 /* For now we always load into IY */
3205 /* if this is remateriazable */
3206 if (AOP_TYPE(left) == AOP_IMMD)
3207 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3208 else { /* we need to get it byte by byte */
3210 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3211 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3213 /* so iy now contains the address */
3214 freeAsmop(left,NULL,ic);
3216 /* if bit then unpack */
3217 if (IS_BITVAR(retype)) {
3221 size = AOP_SIZE(result);
3225 /* PENDING: make this better */
3226 if (AOP(result)->type == AOP_REG) {
3227 aopPut(AOP(result),"(hl)",offset++);
3230 emitcode("ld", "a,(hl)", offset);
3231 aopPut(AOP(result),"a",offset++);
3234 emitcode("inc", "hl");
3240 freeAsmop(result,NULL,ic);
3243 /*-----------------------------------------------------------------*/
3244 /* genPointerGet - generate code for pointer get */
3245 /*-----------------------------------------------------------------*/
3246 static void genPointerGet (iCode *ic)
3248 operand *left, *result ;
3252 result = IC_RESULT(ic) ;
3254 /* depending on the type of pointer we need to
3255 move it to the correct pointer register */
3256 type = operandType(left);
3257 etype = getSpec(type);
3259 genGenPointerGet (left,result,ic);
3262 bool isRegOrLit(asmop *aop)
3264 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3269 /*-----------------------------------------------------------------*/
3270 /* genGenPointerSet - stores the value into a pointer location */
3271 /*-----------------------------------------------------------------*/
3272 static void genGenPointerSet (operand *right,
3273 operand *result, iCode *ic)
3276 link *retype = getSpec(operandType(right));
3278 aopOp(result,ic,FALSE);
3279 aopOp(right,ic,FALSE);
3281 /* Handle the exceptions first */
3282 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3284 char *l = aopGet(AOP(right), 0, FALSE);
3286 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3287 freeAsmop(result,NULL,ic);
3291 /* if the operand is already in dptr
3292 then we do nothing else we move the value to dptr */
3293 if (AOP_TYPE(result) != AOP_STR) {
3294 /* if this is remateriazable */
3295 if (AOP_TYPE(result) == AOP_IMMD) {
3296 emitcode("", "; Error 2");
3297 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3299 else { /* we need to get it byte by byte */
3300 /* PENDING: do this better */
3301 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3302 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3305 /* so hl know contains the address */
3306 freeAsmop(result,NULL,ic);
3308 /* if bit then unpack */
3309 if (IS_BITVAR(retype)) {
3313 size = AOP_SIZE(right);
3317 char *l = aopGet(AOP(right),offset,FALSE);
3319 if (isRegOrLit(AOP(right))) {
3320 emitcode("ld", "(hl),%s", l);
3324 emitcode("ld", "(hl),a", offset);
3327 emitcode("inc", "hl");
3333 freeAsmop(right,NULL,ic);
3336 /*-----------------------------------------------------------------*/
3337 /* genPointerSet - stores the value into a pointer location */
3338 /*-----------------------------------------------------------------*/
3339 static void genPointerSet (iCode *ic)
3341 operand *right, *result ;
3344 right = IC_RIGHT(ic);
3345 result = IC_RESULT(ic) ;
3347 /* depending on the type of pointer we need to
3348 move it to the correct pointer register */
3349 type = operandType(result);
3350 etype = getSpec(type);
3352 genGenPointerSet (right,result,ic);
3355 /*-----------------------------------------------------------------*/
3356 /* genIfx - generate code for Ifx statement */
3357 /*-----------------------------------------------------------------*/
3358 static void genIfx (iCode *ic, iCode *popIc)
3360 operand *cond = IC_COND(ic);
3363 aopOp(cond,ic,FALSE);
3365 /* get the value into acc */
3366 if (AOP_TYPE(cond) != AOP_CRY)
3370 /* the result is now in the accumulator */
3371 freeAsmop(cond,NULL,ic);
3373 /* if there was something to be popped then do it */
3377 /* if the condition is a bit variable */
3378 if (isbit && IS_ITEMP(cond) &&
3380 genIfxJump(ic,SPIL_LOC(cond)->rname);
3382 if (isbit && !IS_ITEMP(cond))
3383 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3390 /*-----------------------------------------------------------------*/
3391 /* genAddrOf - generates code for address of */
3392 /*-----------------------------------------------------------------*/
3393 static void genAddrOf (iCode *ic)
3395 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3397 aopOp(IC_RESULT(ic),ic,FALSE);
3399 /* if the operand is on the stack then we
3400 need to get the stack offset of this
3403 /* if it has an offset then we need to compute it */
3404 emitcode("push", "de");
3405 emitcode("push", "ix");
3406 emitcode("pop", "hl");
3407 emitcode("ld", "de,#%d", sym->stack);
3408 emitcode("add", "hl,de");
3409 emitcode("pop", "de");
3412 emitcode("ld", "hl,#%s", sym->rname);
3414 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3415 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3417 freeAsmop(IC_RESULT(ic),NULL,ic);
3420 /*-----------------------------------------------------------------*/
3421 /* genAssign - generate code for assignment */
3422 /*-----------------------------------------------------------------*/
3423 static void genAssign (iCode *ic)
3425 operand *result, *right;
3427 unsigned long lit = 0L;
3429 result = IC_RESULT(ic);
3430 right = IC_RIGHT(ic) ;
3433 /* Dont bother assigning if they are the same */
3434 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3435 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3440 aopOp(right,ic,FALSE);
3441 aopOp(result,ic,TRUE);
3443 /* if they are the same registers */
3444 if (sameRegs(AOP(right),AOP(result))) {
3445 emitcode("", "; (registers are the same)");
3449 /* if the result is a bit */
3450 if (AOP_TYPE(result) == AOP_CRY) {
3455 size = AOP_SIZE(result);
3458 if(AOP_TYPE(right) == AOP_LIT)
3459 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3461 (AOP_TYPE(result) != AOP_REG) &&
3462 (AOP_TYPE(right) == AOP_LIT) &&
3463 !IS_FLOAT(operandType(right)) &&
3465 bool fXored = FALSE;
3467 /* Work from the top down.
3468 Done this way so that we can use the cached copy of 0
3469 in A for a fast clear */
3471 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3472 if (!fXored && size>1) {
3473 emitcode("xor", "a,a");
3477 aopPut(AOP(result),"a",offset);
3480 aopPut(AOP(result), "#0", offset);
3485 aopGet(AOP(right),offset,FALSE),
3492 aopGet(AOP(right),offset,FALSE),
3499 freeAsmop(right,NULL,ic);
3500 freeAsmop(result,NULL,ic);
3503 /*-----------------------------------------------------------------*/
3504 /* genJumpTab - genrates code for jump table */
3505 /*-----------------------------------------------------------------*/
3506 static void genJumpTab (iCode *ic)
3511 aopOp(IC_JTCOND(ic),ic,FALSE);
3512 /* get the condition into accumulator */
3513 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3515 emitcode("push", "de");
3516 emitcode("ld", "e,%s", l);
3517 emitcode("ld", "d,#0");
3518 jtab = newiTempLabel(NULL);
3519 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3520 emitcode("add", "hl,de");
3521 emitcode("add", "hl,de");
3522 freeAsmop(IC_JTCOND(ic),NULL,ic);
3523 emitcode("pop", "de");
3524 emitcode("jp", "(hl)");
3525 emitcode("","%05d$:",jtab->key+100);
3526 /* now generate the jump labels */
3527 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3528 jtab = setNextItem(IC_JTLABELS(ic)))
3529 emitcode("jp", LABEL_STR, jtab->key+100);
3532 /*-----------------------------------------------------------------*/
3533 /* genCast - gen code for casting */
3534 /*-----------------------------------------------------------------*/
3535 static void genCast (iCode *ic)
3537 operand *result = IC_RESULT(ic);
3538 link *ctype = operandType(IC_LEFT(ic));
3539 operand *right = IC_RIGHT(ic);
3542 /* if they are equivalent then do nothing */
3543 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3546 aopOp(right,ic,FALSE) ;
3547 aopOp(result,ic,FALSE);
3549 /* if the result is a bit */
3550 if (AOP_TYPE(result) == AOP_CRY) {
3554 /* if they are the same size : or less */
3555 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3557 /* if they are in the same place */
3558 if (sameRegs(AOP(right),AOP(result)))
3561 /* if they in different places then copy */
3562 size = AOP_SIZE(result);
3566 aopGet(AOP(right),offset,FALSE),
3573 /* if the result is of type pointer */
3574 if (IS_PTR(ctype)) {
3578 /* so we now know that the size of destination is greater
3579 than the size of the source */
3580 /* we move to result for the size of source */
3581 size = AOP_SIZE(right);
3585 aopGet(AOP(right),offset,FALSE),
3590 /* now depending on the sign of the destination */
3591 size = AOP_SIZE(result) - AOP_SIZE(right);
3592 /* Unsigned or not an integral type - right fill with zeros */
3593 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3595 aopPut(AOP(result),zero,offset++);
3597 /* we need to extend the sign :{ */
3598 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3601 emitcode("", "; genCast: sign extend untested.");
3602 emitcode("rla", "");
3603 emitcode("sbc", "a,a");
3605 aopPut(AOP(result),"a",offset++);
3609 freeAsmop(right, NULL, ic);
3610 freeAsmop(result, NULL, ic);
3613 /*-----------------------------------------------------------------*/
3614 /* genReceive - generate code for a receive iCode */
3615 /*-----------------------------------------------------------------*/
3616 static void genReceive (iCode *ic)
3618 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3619 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3620 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3624 aopOp(IC_RESULT(ic),ic,FALSE);
3626 assignResultValue(IC_RESULT(ic));
3629 freeAsmop(IC_RESULT(ic),NULL,ic);
3632 /*-----------------------------------------------------------------*/
3633 /* genZ80Code - generate code for Z80 based controllers */
3634 /*-----------------------------------------------------------------*/
3635 void genZ80Code (iCode *lic)
3640 lineHead = lineCurr = NULL;
3642 /* if debug information required */
3643 if (options.debug && currFunc) {
3644 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3646 if (IS_STATIC(currFunc->etype))
3647 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3649 emitcode("","G$%s$0$0 ==.",currFunc->name);
3652 /* stack pointer name */
3656 for (ic = lic ; ic ; ic = ic->next ) {
3658 if ( cln != ic->lineno ) {
3659 if ( options.debug ) {
3661 emitcode("","C$%s$%d$%d$%d ==.",
3662 ic->filename,ic->lineno,
3663 ic->level,ic->block);
3666 emitcode(";","%s %d",ic->filename,ic->lineno);
3669 /* if the result is marked as
3670 spilt and rematerializable or code for
3671 this has already been generated then
3673 if (resultRemat(ic) || ic->generated )
3676 /* depending on the operation */
3679 emitcode("", "; genNot");
3684 emitcode("", "; genCpl");
3689 emitcode("", "; genUminus");
3694 emitcode("", "; genIpush");
3699 /* IPOP happens only when trying to restore a
3700 spilt live range, if there is an ifx statement
3701 following this pop then the if statement might
3702 be using some of the registers being popped which
3703 would destory the contents of the register so
3704 we need to check for this condition and handle it */
3706 ic->next->op == IFX &&
3707 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3708 emitcode("", "; genIfx");
3709 genIfx (ic->next,ic);
3712 emitcode("", "; genIpop");
3718 emitcode("", "; genCall");
3723 emitcode("", "; genPcall");
3728 emitcode("", "; genFunction");
3733 emitcode("", "; genEndFunction");
3734 genEndFunction (ic);
3738 emitcode("", "; genRet");
3743 emitcode("", "; genLabel");
3748 emitcode("", "; genGoto");
3753 emitcode("", "; genPlus");
3758 emitcode("", "; genMinus");
3763 emitcode("", "; genMult");
3768 emitcode("", "; genDiv");
3773 emitcode("", "; genMod");
3778 emitcode("", "; genCmpGt");
3779 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3783 emitcode("", "; genCmpLt");
3784 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3791 /* note these two are xlated by algebraic equivalence
3792 during parsing SDCC.y */
3793 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3794 "got '>=' or '<=' shouldn't have come here");
3798 emitcode("", "; genCmpEq");
3799 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3803 emitcode("", "; genAndOp");
3808 emitcode("", "; genOrOp");
3813 emitcode("", "; genXor");
3814 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3818 emitcode("", "; genOr");
3819 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3823 emitcode("", "; genAnd");
3824 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3828 emitcode("", "; genInline");
3833 emitcode("", "; genRRC");
3838 emitcode("", "; genRLC");
3843 emitcode("", "; genHBIT");
3847 emitcode("", "; genLeftShift");
3852 emitcode("", "; genRightShift");
3856 case GET_VALUE_AT_ADDRESS:
3857 emitcode("", "; genPointerGet");
3863 if (POINTER_SET(ic)) {
3864 emitcode("", "; genAssign (pointer)");
3868 emitcode("", "; genAssign");
3874 emitcode("", "; genIfx");
3879 emitcode("", "; genAddrOf");
3884 emitcode("", "; genJumpTab");
3889 emitcode("", "; genCast");
3894 emitcode("", "; genReceive");
3899 emitcode("", "; addSet");
3900 addSet(&sendSet,ic);
3905 /* piCode(ic,stdout); */
3911 /* now we are ready to call the
3912 peep hole optimizer */
3913 if (!options.nopeep)
3914 peepHole (&lineHead);
3916 /* now do the actual printing */
3917 printLine (lineHead,codeOutFile);