1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #include "SDCChasht.h"
43 #include "SDCCicode.h"
44 #include "SDCClabel.h"
45 #include "SDCCBBlock.h"
48 #include "SDCCcflow.h"
49 #include "SDCCdflow.h"
50 #include "SDCClrange.h"
53 #include "SDCCpeeph.h"
55 /* this is the down and dirty file with all kinds of kludgy & hacky
56 stuff. This is what it is all about CODE GENERATION for a specific MCU.
57 Some of the routines may be reusable, will have to see */
59 static char *zero = "#0x00";
60 static char *one = "#0x01";
62 static char *fReturn[] = {"l", "h", "e", "d" };
63 static char *accUse[] = {"a" };
69 extern int ptrRegReq ;
71 extern FILE *codeOutFile;
73 #define RESULTONSTACK(x) \
74 (IC_RESULT(x) && IC_RESULT(x)->aop && \
75 IC_RESULT(x)->aop->type == AOP_STK )
77 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
78 #define CLRC emitcode("xor","a,a");
80 #define LABEL_STR "%05d$"
82 lineNode *lineHead = NULL;
83 lineNode *lineCurr = NULL;
85 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
86 0xE0, 0xC0, 0x80, 0x00};
87 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
88 0x07, 0x03, 0x01, 0x00};
90 static int _lastStack = 0;
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple */
107 /*-----------------------------------------------------------------*/
108 void emitcode (const char *inst, const char *fmt, ...)
111 char lb[MAX_INLINEASM];
117 sprintf(lb,"%s\t",inst);
118 vsprintf(lb+(strlen(lb)),fmt,ap);
122 while (isspace(*lbp)) lbp++;
125 lineCurr = (lineCurr ?
126 connectLine(lineCurr,newLineNode(lb)) :
127 (lineHead = newLineNode(lb)));
128 lineCurr->isInline = inLine;
129 lineCurr->isDebug = debugLine;
133 const char *getPairName(asmop *aop)
135 if (aop->type == AOP_REG) {
136 switch (aop->aopu.aop_reg[0]->rIdx) {
148 else if (aop->type == AOP_STR) {
149 switch (*aop->aopu.aop_str[0]) {
165 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
166 bool isPair(asmop *aop)
168 if (aop->size == 2) {
169 if (aop->type == AOP_REG) {
170 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
173 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
176 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
180 if (aop->type == AOP_STR) {
181 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
184 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
187 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
195 /** Push a register pair onto the stack */
196 void genPairPush(asmop *aop)
198 emitcode("push", "%s", getPairName(aop));
201 /*-----------------------------------------------------------------*/
202 /* newAsmop - creates a new asmOp */
203 /*-----------------------------------------------------------------*/
204 static asmop *newAsmop (short type)
208 ALLOC(aop,sizeof(asmop));
213 /*-----------------------------------------------------------------*/
214 /* aopForSym - for a true symbol */
215 /*-----------------------------------------------------------------*/
216 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
219 memmap *space= SPEC_OCLS(sym->etype);
221 /* if already has one */
225 /* Assign depending on the storage class */
226 if (sym->onStack || sym->iaccess) {
227 sym->aop = aop = newAsmop(AOP_STK);
228 aop->size = getSize(sym->type);
230 aop->aopu.aop_stk = sym->stack;
234 /* special case for a function */
235 if (IS_FUNC(sym->type)) {
236 sym->aop = aop = newAsmop(AOP_IMMD);
237 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
238 strcpy(aop->aopu.aop_immd,sym->rname);
243 /* only remaining is far space */
244 /* in which case DPTR gets the address */
245 sym->aop = aop = newAsmop(AOP_IY);
246 emitcode ("ld","iy,#%s", sym->rname);
247 aop->size = getSize(sym->type);
248 aop->aopu.aop_dir = sym->rname;
250 /* if it is in code space */
251 if (IN_CODESPACE(space))
257 /*-----------------------------------------------------------------*/
258 /* aopForRemat - rematerialzes an object */
259 /*-----------------------------------------------------------------*/
260 static asmop *aopForRemat (symbol *sym)
263 iCode *ic = sym->rematiCode;
264 asmop *aop = newAsmop(AOP_IMMD);
267 /* if plus or minus print the right hand side */
268 if (ic->op == '+' || ic->op == '-') {
269 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
272 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
275 /* we reached the end */
276 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
280 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
281 strcpy(aop->aopu.aop_immd,buffer);
285 /*-----------------------------------------------------------------*/
286 /* regsInCommon - two operands have some registers in common */
287 /*-----------------------------------------------------------------*/
288 bool regsInCommon (operand *op1, operand *op2)
293 /* if they have registers in common */
294 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
297 sym1 = OP_SYMBOL(op1);
298 sym2 = OP_SYMBOL(op2);
300 if (sym1->nRegs == 0 || sym2->nRegs == 0)
303 for (i = 0 ; i < sym1->nRegs ; i++) {
308 for (j = 0 ; j < sym2->nRegs ;j++ ) {
312 if (sym2->regs[j] == sym1->regs[i])
320 /*-----------------------------------------------------------------*/
321 /* operandsEqu - equivalent */
322 /*-----------------------------------------------------------------*/
323 bool operandsEqu ( operand *op1, operand *op2)
327 /* if they not symbols */
328 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
331 sym1 = OP_SYMBOL(op1);
332 sym2 = OP_SYMBOL(op2);
334 /* if both are itemps & one is spilt
335 and the other is not then false */
336 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
337 sym1->isspilt != sym2->isspilt )
340 /* if they are the same */
344 if (strcmp(sym1->rname,sym2->rname) == 0)
348 /* if left is a tmp & right is not */
352 (sym1->usl.spillLoc == sym2))
358 (sym2->usl.spillLoc == sym1))
364 /*-----------------------------------------------------------------*/
365 /* sameRegs - two asmops have the same registers */
366 /*-----------------------------------------------------------------*/
367 bool sameRegs (asmop *aop1, asmop *aop2 )
374 if (aop1->type != AOP_REG ||
375 aop2->type != AOP_REG )
378 if (aop1->size != aop2->size)
381 for (i = 0 ; i < aop1->size ; i++ )
382 if (aop1->aopu.aop_reg[i] !=
383 aop2->aopu.aop_reg[i] )
389 /*-----------------------------------------------------------------*/
390 /* aopOp - allocates an asmop for an operand : */
391 /*-----------------------------------------------------------------*/
392 static void aopOp (operand *op, iCode *ic, bool result)
401 /* if this a literal */
402 if (IS_OP_LITERAL(op)) {
403 op->aop = aop = newAsmop(AOP_LIT);
404 aop->aopu.aop_lit = op->operand.valOperand;
405 aop->size = getSize(operandType(op));
409 /* if already has a asmop then continue */
413 /* if the underlying symbol has a aop */
414 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
415 op->aop = OP_SYMBOL(op)->aop;
419 /* if this is a true symbol */
420 if (IS_TRUE_SYMOP(op)) {
421 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
425 /* this is a temporary : this has
431 e) can be a return use only */
435 /* if the type is a conditional */
436 if (sym->regType == REG_CND) {
437 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
442 /* if it is spilt then two situations
444 b) has a spill location */
445 if (sym->isspilt || sym->nRegs == 0) {
446 /* rematerialize it NOW */
448 sym->aop = op->aop = aop =
450 aop->size = getSize(sym->type);
456 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
457 aop->size = getSize(sym->type);
458 for ( i = 0 ; i < 2 ; i++ )
459 aop->aopu.aop_str[i] = accUse[i];
465 aop = op->aop = sym->aop = newAsmop(AOP_STR);
466 aop->size = getSize(sym->type);
467 for ( i = 0 ; i < 4 ; i++ )
468 aop->aopu.aop_str[i] = fReturn[i];
472 /* else spill location */
473 sym->aop = op->aop = aop =
474 aopForSym(ic,sym->usl.spillLoc,result);
475 aop->size = getSize(sym->type);
479 /* must be in a register */
480 sym->aop = op->aop = aop = newAsmop(AOP_REG);
481 aop->size = sym->nRegs;
482 for ( i = 0 ; i < sym->nRegs ;i++)
483 aop->aopu.aop_reg[i] = sym->regs[i];
486 /*-----------------------------------------------------------------*/
487 /* freeAsmop - free up the asmop given to an operand */
488 /*----------------------------------------------------------------*/
489 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
512 /* all other cases just dealloc */
516 OP_SYMBOL(op)->aop = NULL;
517 /* if the symbol has a spill */
519 SPIL_LOC(op)->aop = NULL;
524 char *aopGetWord(asmop *aop, int offset)
529 assert(aop->size == 2);
532 /* depending on type */
535 sprintf (s,"#%s",aop->aopu.aop_immd);
536 ALLOC_ATOMIC(rs,strlen(s)+1);
541 value * val = aop->aopu.aop_lit;
542 /* if it is a float then it gets tricky */
543 /* otherwise it is fairly simple */
544 if (!IS_FLOAT(val->type)) {
545 unsigned long v = floatFromVal(val);
547 sprintf(buffer,"#0x%04lx", v);
548 ALLOC_ATOMIC(rs,strlen(buffer)+1);
549 return strcpy (rs,buffer);
558 /*-----------------------------------------------------------------*/
559 /* aopGet - for fetching value of the aop */
560 /*-----------------------------------------------------------------*/
561 static char *aopGet (asmop *aop, int offset, bool bit16)
566 /* offset is greater than size then zero */
567 if (offset > (aop->size - 1) &&
568 aop->type != AOP_LIT)
571 /* depending on type */
575 sprintf (s,"#%s",aop->aopu.aop_immd);
585 ALLOC_ATOMIC(rs,strlen(s)+1);
591 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
593 ALLOC_ATOMIC(rs,strlen(s)+1);
598 return aop->aopu.aop_reg[offset]->name;
601 sprintf(s,"%d(iy)", offset);
602 ALLOC_ATOMIC(rs,strlen(s)+1);
607 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
608 ALLOC_ATOMIC(rs,strlen(s)+1);
622 return aopLiteral (aop->aopu.aop_lit,offset);
626 return aop->aopu.aop_str[offset];
629 fprintf(stderr, "Type %u\n", aop->type);
631 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
632 "aopget got unsupported aop->type");
636 bool isRegString(char *s)
638 if (!strcmp(s, "b") ||
649 bool isConstant(char *s)
654 bool canAssignToPtr(char *s)
663 /*-----------------------------------------------------------------*/
664 /* aopPut - puts a string for a aop */
665 /*-----------------------------------------------------------------*/
666 static void aopPut (asmop *aop, char *s, int offset)
670 if (aop->size && offset > ( aop->size - 1)) {
671 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
672 "aopPut got offset > aop->size");
676 /* will assign value to value */
677 /* depending on where it is ofcourse */
682 emitcode("ld", "a,%s", s);
683 emitcode("ld", "(%s+%d),a", d, offset);
687 /* Dont bother if it's a ld x,x */
688 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
689 emitcode("ld","%s,%s",
690 aop->aopu.aop_reg[offset]->name,s);
695 if (!canAssignToPtr(s)) {
696 emitcode("ld", "a,%s", s);
697 emitcode("ld", "%d(iy),a", offset);
700 emitcode("ld", "%d(iy),%s", offset, s);
704 if (!canAssignToPtr(s)) {
705 emitcode("ld", "a,%s", s);
706 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
709 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
713 /* if bit variable */
714 if (!aop->aopu.aop_dir) {
715 emitcode("ld", "a,#0");
718 /* In bit space but not in C - cant happen */
725 if (strcmp(aop->aopu.aop_str[offset],s)) {
726 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
732 if (!offset && (strcmp(s,"acc") == 0))
735 emitcode("", "; Error aopPut AOP_ACC");
738 if (strcmp(aop->aopu.aop_str[offset],s))
739 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
744 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
745 "aopPut got unsupported aop->type");
750 #define AOP(op) op->aop
751 #define AOP_TYPE(op) AOP(op)->type
752 #define AOP_SIZE(op) AOP(op)->size
753 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
755 /*-----------------------------------------------------------------*/
756 /* getDataSize - get the operand data size */
757 /*-----------------------------------------------------------------*/
758 int getDataSize(operand *op)
769 /*-----------------------------------------------------------------*/
770 /* movLeft2Result - move byte from left to result */
771 /*-----------------------------------------------------------------*/
772 static void movLeft2Result (operand *left, int offl,
773 operand *result, int offr, int sign)
776 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
777 l = aopGet(AOP(left),offl,FALSE);
780 aopPut(AOP(result),l,offr);
789 /** Put Acc into a register set
791 void outAcc(operand *result)
794 size = getDataSize(result);
796 aopPut(AOP(result),"a",0);
799 /* unsigned or positive */
801 aopPut(AOP(result),zero,offset++);
806 /** Take the value in carry and put it into a register
808 void outBitC(operand *result)
810 /* if the result is bit */
811 if (AOP_TYPE(result) == AOP_CRY) {
812 emitcode("", "; Note: outBitC form 1");
813 aopPut(AOP(result),"blah",0);
816 emitcode("ld", "a,#0");
822 /*-----------------------------------------------------------------*/
823 /* toBoolean - emit code for orl a,operator(sizeop) */
824 /*-----------------------------------------------------------------*/
825 void toBoolean(operand *oper)
827 int size = AOP_SIZE(oper);
830 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
833 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
837 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
841 /*-----------------------------------------------------------------*/
842 /* genNot - generate code for ! operation */
843 /*-----------------------------------------------------------------*/
844 static void genNot (iCode *ic)
846 link *optype = operandType(IC_LEFT(ic));
848 /* assign asmOps to operand & result */
849 aopOp (IC_LEFT(ic),ic,FALSE);
850 aopOp (IC_RESULT(ic),ic,TRUE);
852 /* if in bit space then a special case */
853 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
857 /* if type float then do float */
858 if (IS_FLOAT(optype)) {
862 toBoolean(IC_LEFT(ic));
867 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
868 emitcode("sub", "a,#0x01");
869 outBitC(IC_RESULT(ic));
871 /* release the aops */
872 freeAsmop(IC_LEFT(ic),NULL,ic);
873 freeAsmop(IC_RESULT(ic),NULL,ic);
876 /*-----------------------------------------------------------------*/
877 /* genCpl - generate code for complement */
878 /*-----------------------------------------------------------------*/
879 static void genCpl (iCode *ic)
885 /* assign asmOps to operand & result */
886 aopOp (IC_LEFT(ic),ic,FALSE);
887 aopOp (IC_RESULT(ic),ic,TRUE);
889 /* if both are in bit space then
891 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
892 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
896 size = AOP_SIZE(IC_RESULT(ic));
898 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
901 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
904 /* release the aops */
905 freeAsmop(IC_LEFT(ic),NULL,ic);
906 freeAsmop(IC_RESULT(ic),NULL,ic);
909 /*-----------------------------------------------------------------*/
910 /* genUminus - unary minus code generation */
911 /*-----------------------------------------------------------------*/
912 static void genUminus (iCode *ic)
918 /*-----------------------------------------------------------------*/
919 /* assignResultValue - */
920 /*-----------------------------------------------------------------*/
921 void assignResultValue(operand * oper)
924 int size = AOP_SIZE(oper);
926 aopPut(AOP(oper),fReturn[offset],offset);
931 /*-----------------------------------------------------------------*/
932 /* genIpush - genrate code for pushing this gets a little complex */
933 /*-----------------------------------------------------------------*/
934 static void genIpush (iCode *ic)
936 int size, offset = 0 ;
940 /* if this is not a parm push : ie. it is spill push
941 and spill push is always done on the local stack */
943 /* and the item is spilt then do nothing */
944 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
947 aopOp(IC_LEFT(ic),ic,FALSE);
948 size = AOP_SIZE(IC_LEFT(ic));
949 /* push it on the stack */
950 if (isPair(AOP(IC_LEFT(ic)))) {
951 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
956 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
957 /* Simple for now - load into A and PUSH AF */
958 emitcode("ld", "a,%s", l);
959 emitcode("push", "af");
960 emitcode("inc", "sp");
966 /* Hmmm... what about saving the currently used registers
969 /* then do the push */
970 aopOp(IC_LEFT(ic),ic,FALSE);
972 size = AOP_SIZE(IC_LEFT(ic));
974 if (isPair(AOP(IC_LEFT(ic)))) {
975 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
979 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
981 emitcode("ld", "hl,%s", s);
982 emitcode("push", "hl");
988 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
989 emitcode("ld", "a,%s", l);
990 emitcode("push", "af");
991 emitcode("inc", "sp");
995 freeAsmop(IC_LEFT(ic),NULL,ic);
998 /*-----------------------------------------------------------------*/
999 /* genIpop - recover the registers: can happen only for spilling */
1000 /*-----------------------------------------------------------------*/
1001 static void genIpop (iCode *ic)
1006 /* if the temp was not pushed then */
1007 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1010 aopOp(IC_LEFT(ic),ic,FALSE);
1011 size = AOP_SIZE(IC_LEFT(ic));
1013 if (isPair(AOP(IC_LEFT(ic)))) {
1014 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1018 emitcode("dec", "sp");
1019 emitcode("pop", "hl");
1020 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1024 freeAsmop(IC_LEFT(ic),NULL,ic);
1027 /** Emit the code for a call statement
1029 static void emitCall (iCode *ic, bool ispcall)
1031 /* if caller saves & we have not saved then */
1032 if (!ic->regsSaved) {
1036 /* if send set is not empty then assign */
1040 for (sic = setFirstItem(sendSet) ; sic ;
1041 sic = setNextItem(sendSet)) {
1042 int size, offset = 0;
1043 aopOp(IC_LEFT(sic),sic,FALSE);
1044 size = AOP_SIZE(IC_LEFT(sic));
1046 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1048 if (strcmp(l,fReturn[offset]))
1049 emitcode("ld","%s,%s",
1054 freeAsmop (IC_LEFT(sic),NULL,sic);
1060 symbol *rlbl = newiTempLabel(NULL);
1062 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1063 emitcode("push", "hl");
1065 aopOp(IC_LEFT(ic),ic,FALSE);
1066 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1067 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1068 freeAsmop(IC_LEFT(ic),NULL,ic);
1070 emitcode("jp", "(hl)");
1071 emitcode("","%05d$:",(rlbl->key+100));
1075 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1076 OP_SYMBOL(IC_LEFT(ic))->rname :
1077 OP_SYMBOL(IC_LEFT(ic))->name));
1080 /* if we need assign a result value */
1081 if ((IS_ITEMP(IC_RESULT(ic)) &&
1082 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1083 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1084 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1087 aopOp(IC_RESULT(ic),ic,FALSE);
1090 assignResultValue(IC_RESULT(ic));
1092 freeAsmop(IC_RESULT(ic),NULL, ic);
1095 /* adjust the stack for parameters if required */
1096 if (IC_LEFT(ic)->parmBytes) {
1097 int i = IC_LEFT(ic)->parmBytes;
1098 /* PENDING: do better */
1100 emitcode("pop", "hl");
1104 emitcode("inc", "sp");
1109 /*-----------------------------------------------------------------*/
1110 /* genCall - generates a call statement */
1111 /*-----------------------------------------------------------------*/
1112 static void genCall (iCode *ic)
1114 emitCall(ic, FALSE);
1117 /*-----------------------------------------------------------------*/
1118 /* genPcall - generates a call by pointer statement */
1119 /*-----------------------------------------------------------------*/
1120 static void genPcall (iCode *ic)
1125 /*-----------------------------------------------------------------*/
1126 /* resultRemat - result is rematerializable */
1127 /*-----------------------------------------------------------------*/
1128 static int resultRemat (iCode *ic)
1130 if (SKIP_IC(ic) || ic->op == IFX)
1133 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1134 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1135 if (sym->remat && !POINTER_SET(ic))
1142 /*-----------------------------------------------------------------*/
1143 /* genFunction - generated code for function entry */
1144 /*-----------------------------------------------------------------*/
1145 static void genFunction (iCode *ic)
1151 /* create the function header */
1152 emitcode(";","-----------------------------------------");
1153 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1154 emitcode(";","-----------------------------------------");
1156 emitcode("","%s:",sym->rname);
1157 fetype = getSpec(operandType(IC_LEFT(ic)));
1159 /* if critical function then turn interrupts off */
1160 if (SPEC_CRTCL(fetype))
1163 /* if this is an interrupt service routine then
1164 save acc, b, dpl, dph */
1165 if (IS_ISR(sym->etype)) {
1166 emitcode("push", "af");
1167 emitcode("push", "bc");
1168 emitcode("push", "de");
1169 emitcode("push", "hl");
1171 /* PENDING: callee-save etc */
1173 /* adjust the stack for the function */
1174 emitcode("push", "de");
1175 emitcode("push", "bc");
1176 emitcode("push", "ix");
1177 emitcode("ld", "ix,#0");
1178 emitcode("add", "ix,sp");
1180 _lastStack = sym->stack;
1183 emitcode("ld", "hl,#-%d", sym->stack);
1184 emitcode("add", "hl,sp");
1185 emitcode("ld", "sp,hl");
1189 /*-----------------------------------------------------------------*/
1190 /* genEndFunction - generates epilogue for functions */
1191 /*-----------------------------------------------------------------*/
1192 static void genEndFunction (iCode *ic)
1194 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1196 if (IS_ISR(sym->etype)) {
1200 if (SPEC_CRTCL(sym->etype))
1203 /* PENDING: calleeSave */
1205 /* if debug then send end of function */
1206 if (options.debug && currFunc) {
1208 emitcode("","C$%s$%d$%d$%d ==.",
1209 ic->filename,currFunc->lastLine,
1210 ic->level,ic->block);
1211 if (IS_STATIC(currFunc->etype))
1212 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1214 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1217 emitcode("ld", "sp,ix");
1218 emitcode("pop", "ix");
1219 emitcode("pop", "bc");
1220 emitcode("pop", "de");
1221 emitcode("ret", "");
1226 /*-----------------------------------------------------------------*/
1227 /* genRet - generate code for return statement */
1228 /*-----------------------------------------------------------------*/
1229 static void genRet (iCode *ic)
1232 /* Errk. This is a hack until I can figure out how
1233 to cause dehl to spill on a call */
1234 int size,offset = 0;
1236 /* if we have no return value then
1237 just generate the "ret" */
1241 /* we have something to return then
1242 move the return value into place */
1243 aopOp(IC_LEFT(ic),ic,FALSE);
1244 size = AOP_SIZE(IC_LEFT(ic));
1246 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1247 emitcode("ld", "hl,%s", l);
1251 l = aopGet(AOP(IC_LEFT(ic)),offset,
1253 if (strcmp(fReturn[offset],l))
1254 emitcode("ld","%s,%s",fReturn[offset++],l);
1257 freeAsmop (IC_LEFT(ic),NULL,ic);
1260 /* generate a jump to the return label
1261 if the next is not the return statement */
1262 if (!(ic->next && ic->next->op == LABEL &&
1263 IC_LABEL(ic->next) == returnLabel))
1265 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1268 /*-----------------------------------------------------------------*/
1269 /* genLabel - generates a label */
1270 /*-----------------------------------------------------------------*/
1271 static void genLabel (iCode *ic)
1273 /* special case never generate */
1274 if (IC_LABEL(ic) == entryLabel)
1277 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1280 /*-----------------------------------------------------------------*/
1281 /* genGoto - generates a ljmp */
1282 /*-----------------------------------------------------------------*/
1283 static void genGoto (iCode *ic)
1285 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1288 /*-----------------------------------------------------------------*/
1289 /* genPlusIncr :- does addition with increment if possible */
1290 /*-----------------------------------------------------------------*/
1291 static bool genPlusIncr (iCode *ic)
1293 unsigned int icount ;
1294 unsigned int size = getDataSize(IC_RESULT(ic));
1296 /* will try to generate an increment */
1297 /* if the right side is not a literal
1299 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1302 /* if the literal value of the right hand side
1303 is greater than 4 then it is not worth it */
1304 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1308 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1309 isPair(AOP(IC_RESULT(ic)))) {
1311 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1315 /* if increment 16 bits in register */
1316 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1319 symbol *tlbl = newiTempLabel(NULL);
1320 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1321 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1323 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1327 emitcode("", LABEL_STR ":",tlbl->key+100);
1331 /* If result is a pair */
1332 if (isPair(AOP(IC_RESULT(ic)))) {
1333 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1334 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1336 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1340 /* if the sizes are greater than 1 then we cannot */
1341 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1342 AOP_SIZE(IC_LEFT(ic)) > 1 )
1345 /* we can if the aops of the left & result match or
1346 if they are in registers and the registers are the
1348 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1350 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1358 /*-----------------------------------------------------------------*/
1359 /* outBitAcc - output a bit in acc */
1360 /*-----------------------------------------------------------------*/
1361 void outBitAcc(operand *result)
1363 symbol *tlbl = newiTempLabel(NULL);
1364 /* if the result is a bit */
1365 if (AOP_TYPE(result) == AOP_CRY){
1369 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1370 emitcode("ld","a,%s",one);
1371 emitcode("", LABEL_STR ":",tlbl->key+100);
1376 /*-----------------------------------------------------------------*/
1377 /* genPlus - generates code for addition */
1378 /*-----------------------------------------------------------------*/
1379 static void genPlus (iCode *ic)
1381 int size, offset = 0;
1383 /* special cases :- */
1385 aopOp (IC_LEFT(ic),ic,FALSE);
1386 aopOp (IC_RIGHT(ic),ic,FALSE);
1387 aopOp (IC_RESULT(ic),ic,TRUE);
1389 /* Swap the left and right operands if:
1391 if literal, literal on the right or
1392 if left requires ACC or right is already
1395 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1396 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1397 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1398 operand *t = IC_RIGHT(ic);
1399 IC_RIGHT(ic) = IC_LEFT(ic);
1403 /* if both left & right are in bit
1405 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1406 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1411 /* if left in bit space & right literal */
1412 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1413 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1414 /* Can happen I guess */
1418 /* if I can do an increment instead
1419 of add then GOOD for ME */
1420 if (genPlusIncr (ic) == TRUE)
1423 size = getDataSize(IC_RESULT(ic));
1426 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1427 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1429 emitcode("add","a,%s",
1430 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1432 emitcode("adc","a,%s",
1433 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1435 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1437 emitcode("add","a,%s",
1438 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1440 emitcode("adc","a,%s",
1441 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1443 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1446 /* Some kind of pointer arith. */
1447 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1448 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1449 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1452 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1453 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1454 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1459 freeAsmop(IC_LEFT(ic),NULL,ic);
1460 freeAsmop(IC_RIGHT(ic),NULL,ic);
1461 freeAsmop(IC_RESULT(ic),NULL,ic);
1465 /*-----------------------------------------------------------------*/
1466 /* genMinusDec :- does subtraction with deccrement if possible */
1467 /*-----------------------------------------------------------------*/
1468 static bool genMinusDec (iCode *ic)
1470 unsigned int icount ;
1471 unsigned int size = getDataSize(IC_RESULT(ic));
1473 /* will try to generate an increment */
1474 /* if the right side is not a literal we cannot */
1475 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1478 /* if the literal value of the right hand side
1479 is greater than 4 then it is not worth it */
1480 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1483 size = getDataSize(IC_RESULT(ic));
1484 /* if decrement 16 bits in register */
1485 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1486 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1488 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1492 /* If result is a pair */
1493 if (isPair(AOP(IC_RESULT(ic)))) {
1494 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1495 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1497 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1501 /* if the sizes are greater than 1 then we cannot */
1502 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1503 AOP_SIZE(IC_LEFT(ic)) > 1 )
1506 /* we can if the aops of the left & result match or if they are in
1507 registers and the registers are the same */
1508 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1510 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1517 /*-----------------------------------------------------------------*/
1518 /* genMinus - generates code for subtraction */
1519 /*-----------------------------------------------------------------*/
1520 static void genMinus (iCode *ic)
1522 int size, offset = 0;
1523 unsigned long lit = 0L;
1525 aopOp (IC_LEFT(ic),ic,FALSE);
1526 aopOp (IC_RIGHT(ic),ic,FALSE);
1527 aopOp (IC_RESULT(ic),ic,TRUE);
1529 /* special cases :- */
1530 /* if both left & right are in bit space */
1531 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1532 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1537 /* if I can do an decrement instead of subtract then GOOD for ME */
1538 if (genMinusDec (ic) == TRUE)
1541 size = getDataSize(IC_RESULT(ic));
1543 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1547 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1552 /* if literal, add a,#-lit, else normal subb */
1554 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1555 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1556 emitcode("sbc","a,%s",
1557 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1559 /* first add without previous c */
1561 emitcode("add","a,#0x%02x",
1562 (unsigned int)(lit & 0x0FFL));
1564 emitcode("adc","a,#0x%02x",
1565 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1567 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1570 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1571 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1572 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1576 freeAsmop(IC_LEFT(ic),NULL,ic);
1577 freeAsmop(IC_RIGHT(ic),NULL,ic);
1578 freeAsmop(IC_RESULT(ic),NULL,ic);
1581 /*-----------------------------------------------------------------*/
1582 /* genMult - generates code for multiplication */
1583 /*-----------------------------------------------------------------*/
1584 static void genMult (iCode *ic)
1586 /* Shouldn't occur - all done through function calls */
1590 /*-----------------------------------------------------------------*/
1591 /* genDiv - generates code for division */
1592 /*-----------------------------------------------------------------*/
1593 static void genDiv (iCode *ic)
1595 /* Shouldn't occur - all done through function calls */
1599 /*-----------------------------------------------------------------*/
1600 /* genMod - generates code for division */
1601 /*-----------------------------------------------------------------*/
1602 static void genMod (iCode *ic)
1604 /* Shouldn't occur - all done through function calls */
1608 /*-----------------------------------------------------------------*/
1609 /* genIfxJump :- will create a jump depending on the ifx */
1610 /*-----------------------------------------------------------------*/
1611 static void genIfxJump (iCode *ic, char *jval)
1616 /* if true label then we jump if condition
1618 if ( IC_TRUE(ic) ) {
1620 if (!strcmp(jval, "a")) {
1623 else if (!strcmp(jval, "c")) {
1627 /* The buffer contains the bit on A that we should test */
1632 /* false label is present */
1633 jlbl = IC_FALSE(ic) ;
1634 if (!strcmp(jval, "a")) {
1637 else if (!strcmp(jval, "c")) {
1641 /* The buffer contains the bit on A that we should test */
1645 /* Z80 can do a conditional long jump */
1646 if (!strcmp(jval, "a")) {
1647 emitcode("or", "a,a");
1649 else if (!strcmp(jval, "c")) {
1652 emitcode("bit", "%s,a", jval);
1654 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1656 /* mark the icode as generated */
1660 /** Generic compare for > or <
1662 static void genCmp (operand *left,operand *right,
1663 operand *result, iCode *ifx, int sign)
1665 int size, offset = 0 ;
1666 unsigned long lit = 0L;
1668 /* if left & right are bit variables */
1669 if (AOP_TYPE(left) == AOP_CRY &&
1670 AOP_TYPE(right) == AOP_CRY ) {
1671 /* Cant happen on the Z80 */
1674 /* subtract right from left if at the
1675 end the carry flag is set then we know that
1676 left is greater than right */
1677 size = max(AOP_SIZE(left),AOP_SIZE(right));
1679 /* if unsigned char cmp with lit, just compare */
1680 if((size == 1) && !sign &&
1681 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1682 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1683 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1686 if(AOP_TYPE(right) == AOP_LIT) {
1687 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1688 /* optimize if(x < 0) or if(x >= 0) */
1691 /* No sign so it's always false */
1695 /* Just load in the top most bit */
1696 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1697 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1699 genIfxJump (ifx,"acc.7");
1703 emitcode("rlc","a");
1709 /* Do a long subtract */
1710 MOVA(aopGet(AOP(left),offset,FALSE));
1711 if (sign && size == 0) {
1712 /* Case where it's signed and we've hit the end */
1715 /* Subtract through, propagating the carry */
1717 emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1720 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1727 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1730 /* if the result is used in the next
1731 ifx conditional branch then generate
1732 code a little differently */
1734 genIfxJump (ifx,"c");
1737 /* leave the result in acc */
1741 /*-----------------------------------------------------------------*/
1742 /* genCmpGt :- greater than comparison */
1743 /*-----------------------------------------------------------------*/
1744 static void genCmpGt (iCode *ic, iCode *ifx)
1746 operand *left, *right, *result;
1747 link *letype , *retype;
1751 right= IC_RIGHT(ic);
1752 result = IC_RESULT(ic);
1754 letype = getSpec(operandType(left));
1755 retype =getSpec(operandType(right));
1756 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1757 /* assign the amsops */
1758 aopOp (left,ic,FALSE);
1759 aopOp (right,ic,FALSE);
1760 aopOp (result,ic,TRUE);
1762 genCmp(right, left, result, ifx, sign);
1764 freeAsmop(left,NULL,ic);
1765 freeAsmop(right,NULL,ic);
1766 freeAsmop(result,NULL,ic);
1769 /*-----------------------------------------------------------------*/
1770 /* genCmpLt - less than comparisons */
1771 /*-----------------------------------------------------------------*/
1772 static void genCmpLt (iCode *ic, iCode *ifx)
1774 operand *left, *right, *result;
1775 link *letype , *retype;
1779 right= IC_RIGHT(ic);
1780 result = IC_RESULT(ic);
1782 letype = getSpec(operandType(left));
1783 retype =getSpec(operandType(right));
1784 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1786 /* assign the amsops */
1787 aopOp (left,ic,FALSE);
1788 aopOp (right,ic,FALSE);
1789 aopOp (result,ic,TRUE);
1791 genCmp(left, right, result, ifx, sign);
1793 freeAsmop(left,NULL,ic);
1794 freeAsmop(right,NULL,ic);
1795 freeAsmop(result,NULL,ic);
1798 /*-----------------------------------------------------------------*/
1799 /* gencjneshort - compare and jump if not equal */
1800 /*-----------------------------------------------------------------*/
1801 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1803 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1805 unsigned long lit = 0L;
1807 /* Swap the left and right if it makes the computation easier */
1808 if (AOP_TYPE(left) == AOP_LIT) {
1814 if(AOP_TYPE(right) == AOP_LIT)
1815 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1817 /* if the right side is a literal then anything goes */
1818 if (AOP_TYPE(right) == AOP_LIT &&
1819 AOP_TYPE(left) != AOP_DIR ) {
1821 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1822 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1823 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1827 /* if the right side is in a register or in direct space or
1828 if the left is a pointer register & right is not */
1829 else if (AOP_TYPE(right) == AOP_REG ||
1830 AOP_TYPE(right) == AOP_DIR ||
1831 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1833 MOVA(aopGet(AOP(left),offset,FALSE));
1834 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1835 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1837 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1839 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1840 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1849 /*-----------------------------------------------------------------*/
1850 /* gencjne - compare and jump if not equal */
1851 /*-----------------------------------------------------------------*/
1852 static void gencjne(operand *left, operand *right, symbol *lbl)
1854 symbol *tlbl = newiTempLabel(NULL);
1856 gencjneshort(left, right, lbl);
1859 emitcode("ld","a,%s",one);
1860 emitcode("jp", LABEL_STR ,tlbl->key+100);
1861 emitcode("", LABEL_STR ":",lbl->key+100);
1862 emitcode("xor","a,a");
1863 emitcode("", LABEL_STR ":",tlbl->key+100);
1866 /*-----------------------------------------------------------------*/
1867 /* genCmpEq - generates code for equal to */
1868 /*-----------------------------------------------------------------*/
1869 static void genCmpEq (iCode *ic, iCode *ifx)
1871 operand *left, *right, *result;
1873 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1874 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1875 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1877 /* Swap operands if it makes the operation easier. ie if:
1878 1. Left is a literal.
1880 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1881 operand *t = IC_RIGHT(ic);
1882 IC_RIGHT(ic) = IC_LEFT(ic);
1886 if (ifx && !AOP_SIZE(result)){
1888 /* if they are both bit variables */
1889 if (AOP_TYPE(left) == AOP_CRY &&
1890 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1893 tlbl = newiTempLabel(NULL);
1894 gencjneshort(left, right, tlbl);
1895 if ( IC_TRUE(ifx) ) {
1896 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1897 emitcode("", LABEL_STR ":",tlbl->key+100);
1899 /* PENDING: do this better */
1900 symbol *lbl = newiTempLabel(NULL);
1901 emitcode("jp", LABEL_STR ,lbl->key+100);
1902 emitcode("", LABEL_STR ":",tlbl->key+100);
1903 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1904 emitcode("", LABEL_STR ":",lbl->key+100);
1907 /* mark the icode as generated */
1912 /* if they are both bit variables */
1913 if (AOP_TYPE(left) == AOP_CRY &&
1914 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1917 gencjne(left,right,newiTempLabel(NULL));
1918 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1922 genIfxJump(ifx,"a");
1925 /* if the result is used in an arithmetic operation
1926 then put the result in place */
1927 if (AOP_TYPE(result) != AOP_CRY) {
1930 /* leave the result in acc */
1934 freeAsmop(left,NULL,ic);
1935 freeAsmop(right,NULL,ic);
1936 freeAsmop(result,NULL,ic);
1939 /*-----------------------------------------------------------------*/
1940 /* ifxForOp - returns the icode containing the ifx for operand */
1941 /*-----------------------------------------------------------------*/
1942 static iCode *ifxForOp ( operand *op, iCode *ic )
1944 /* if true symbol then needs to be assigned */
1945 if (IS_TRUE_SYMOP(op))
1948 /* if this has register type condition and
1949 the next instruction is ifx with the same operand
1950 and live to of the operand is upto the ifx only then */
1952 ic->next->op == IFX &&
1953 IC_COND(ic->next)->key == op->key &&
1954 OP_SYMBOL(op)->liveTo <= ic->next->seq )
1960 /*-----------------------------------------------------------------*/
1961 /* genAndOp - for && operation */
1962 /*-----------------------------------------------------------------*/
1963 static void genAndOp (iCode *ic)
1965 operand *left,*right, *result;
1968 /* note here that && operations that are in an if statement are
1969 taken away by backPatchLabels only those used in arthmetic
1970 operations remain */
1971 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1972 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1973 aopOp((result=IC_RESULT(ic)),ic,FALSE);
1975 /* if both are bit variables */
1976 if (AOP_TYPE(left) == AOP_CRY &&
1977 AOP_TYPE(right) == AOP_CRY ) {
1980 tlbl = newiTempLabel(NULL);
1982 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1984 emitcode("", LABEL_STR ":",tlbl->key+100);
1988 freeAsmop(left,NULL,ic);
1989 freeAsmop(right,NULL,ic);
1990 freeAsmop(result,NULL,ic);
1993 /*-----------------------------------------------------------------*/
1994 /* genOrOp - for || operation */
1995 /*-----------------------------------------------------------------*/
1996 static void genOrOp (iCode *ic)
1998 operand *left,*right, *result;
2001 /* note here that || operations that are in an
2002 if statement are taken away by backPatchLabels
2003 only those used in arthmetic operations remain */
2004 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2005 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2006 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2008 /* if both are bit variables */
2009 if (AOP_TYPE(left) == AOP_CRY &&
2010 AOP_TYPE(right) == AOP_CRY ) {
2013 tlbl = newiTempLabel(NULL);
2015 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2017 emitcode("", LABEL_STR,tlbl->key+100);
2021 freeAsmop(left,NULL,ic);
2022 freeAsmop(right,NULL,ic);
2023 freeAsmop(result,NULL,ic);
2026 /*-----------------------------------------------------------------*/
2027 /* isLiteralBit - test if lit == 2^n */
2028 /*-----------------------------------------------------------------*/
2029 int isLiteralBit(unsigned long lit)
2031 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2032 0x100L,0x200L,0x400L,0x800L,
2033 0x1000L,0x2000L,0x4000L,0x8000L,
2034 0x10000L,0x20000L,0x40000L,0x80000L,
2035 0x100000L,0x200000L,0x400000L,0x800000L,
2036 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2037 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2040 for(idx = 0; idx < 32; idx++)
2046 /*-----------------------------------------------------------------*/
2047 /* genAnd - code for and */
2048 /*-----------------------------------------------------------------*/
2049 static void genAnd (iCode *ic, iCode *ifx)
2051 operand *left, *right, *result;
2053 unsigned long lit = 0L;
2056 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2057 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2058 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2061 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2063 AOP_TYPE(left), AOP_TYPE(right));
2064 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2066 AOP_SIZE(left), AOP_SIZE(right));
2069 /* if left is a literal & right is not then exchange them */
2070 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2071 AOP_NEEDSACC(left)) {
2072 operand *tmp = right ;
2077 /* if result = right then exchange them */
2078 if(sameRegs(AOP(result),AOP(right))){
2079 operand *tmp = right ;
2084 /* if right is bit then exchange them */
2085 if (AOP_TYPE(right) == AOP_CRY &&
2086 AOP_TYPE(left) != AOP_CRY){
2087 operand *tmp = right ;
2091 if(AOP_TYPE(right) == AOP_LIT)
2092 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2094 size = AOP_SIZE(result);
2096 if (AOP_TYPE(left) == AOP_CRY){
2101 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2102 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2103 if((AOP_TYPE(right) == AOP_LIT) &&
2104 (AOP_TYPE(result) == AOP_CRY) &&
2105 (AOP_TYPE(left) != AOP_CRY)) {
2106 int posbit = isLiteralBit(lit);
2110 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2114 emitcode("mov","c,acc.%d",posbit&0x07);
2119 sprintf(buffer, "%d", posbit&0x07);
2120 genIfxJump(ifx, buffer);
2128 symbol *tlbl = newiTempLabel(NULL);
2129 int sizel = AOP_SIZE(left);
2132 emitcode("setb","c");
2135 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2136 MOVA( aopGet(AOP(left),offset,FALSE));
2138 if((posbit = isLiteralBit(bytelit)) != 0) {
2140 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2143 if(bytelit != 0x0FFL)
2144 emitcode("and","a,%s",
2145 aopGet(AOP(right),offset,FALSE));
2146 emitcode("jr","nz, %05d$",tlbl->key+100);
2151 // bit = left & literal
2153 emitcode("clr","c");
2154 emitcode("","%05d$:",tlbl->key+100);
2156 // if(left & literal)
2160 jmpTrueOrFalse(ifx, tlbl);
2171 /* if left is same as result */
2172 if(sameRegs(AOP(result),AOP(left))){
2173 for(;size--; offset++) {
2174 if(AOP_TYPE(right) == AOP_LIT){
2175 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2179 aopPut(AOP(result),zero,offset);
2181 MOVA(aopGet(AOP(left),offset,FALSE));
2182 emitcode("and","a,%s",
2183 aopGet(AOP(right),offset,FALSE));
2184 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2189 if (AOP_TYPE(left) == AOP_ACC) {
2193 MOVA(aopGet(AOP(right),offset,FALSE));
2194 emitcode("and","%s,a",
2195 aopGet(AOP(left),offset,FALSE));
2200 // left & result in different registers
2201 if(AOP_TYPE(result) == AOP_CRY){
2204 for(;(size--);offset++) {
2206 // result = left & right
2207 if(AOP_TYPE(right) == AOP_LIT){
2208 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2210 aopGet(AOP(left),offset,FALSE),
2213 } else if(bytelit == 0){
2214 aopPut(AOP(result),zero,offset);
2218 // faster than result <- left, anl result,right
2219 // and better if result is SFR
2220 if (AOP_TYPE(left) == AOP_ACC)
2221 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2223 MOVA(aopGet(AOP(right),offset,FALSE));
2224 emitcode("and","a,%s",
2225 aopGet(AOP(left),offset,FALSE));
2227 aopPut(AOP(result),"a",offset);
2234 freeAsmop(left,NULL,ic);
2235 freeAsmop(right,NULL,ic);
2236 freeAsmop(result,NULL,ic);
2239 /*-----------------------------------------------------------------*/
2240 /* genOr - code for or */
2241 /*-----------------------------------------------------------------*/
2242 static void genOr (iCode *ic, iCode *ifx)
2244 operand *left, *right, *result;
2246 unsigned long lit = 0L;
2248 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2249 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2250 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2253 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2255 AOP_TYPE(left), AOP_TYPE(right));
2256 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2258 AOP_SIZE(left), AOP_SIZE(right));
2261 /* if left is a literal & right is not then exchange them */
2262 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2263 AOP_NEEDSACC(left)) {
2264 operand *tmp = right ;
2269 /* if result = right then exchange them */
2270 if(sameRegs(AOP(result),AOP(right))){
2271 operand *tmp = right ;
2276 /* if right is bit then exchange them */
2277 if (AOP_TYPE(right) == AOP_CRY &&
2278 AOP_TYPE(left) != AOP_CRY){
2279 operand *tmp = right ;
2283 if(AOP_TYPE(right) == AOP_LIT)
2284 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2286 size = AOP_SIZE(result);
2288 if (AOP_TYPE(left) == AOP_CRY){
2293 if((AOP_TYPE(right) == AOP_LIT) &&
2294 (AOP_TYPE(result) == AOP_CRY) &&
2295 (AOP_TYPE(left) != AOP_CRY)){
2300 /* if left is same as result */
2301 if(sameRegs(AOP(result),AOP(left))){
2302 for(;size--; offset++) {
2303 if(AOP_TYPE(right) == AOP_LIT){
2304 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2307 emitcode("or","%s,%s",
2308 aopGet(AOP(left),offset,FALSE),
2309 aopGet(AOP(right),offset,FALSE));
2311 if (AOP_TYPE(left) == AOP_ACC)
2312 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2314 MOVA(aopGet(AOP(right),offset,FALSE));
2315 emitcode("or","a,%s",
2316 aopGet(AOP(left),offset,FALSE));
2317 aopPut(AOP(result),"a",0);
2322 // left & result in different registers
2323 if(AOP_TYPE(result) == AOP_CRY){
2325 } else for(;(size--);offset++){
2327 // result = left & right
2328 if(AOP_TYPE(right) == AOP_LIT){
2329 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2331 aopGet(AOP(left),offset,FALSE),
2336 // faster than result <- left, anl result,right
2337 // and better if result is SFR
2338 if (AOP_TYPE(left) == AOP_ACC)
2339 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2341 MOVA(aopGet(AOP(right),offset,FALSE));
2342 emitcode("or","a,%s",
2343 aopGet(AOP(left),offset,FALSE));
2344 aopPut(AOP(result),"a",0);
2346 aopPut(AOP(result),"a",offset);
2351 freeAsmop(left,NULL,ic);
2352 freeAsmop(right,NULL,ic);
2353 freeAsmop(result,NULL,ic);
2356 /*-----------------------------------------------------------------*/
2357 /* genXor - code for xclusive or */
2358 /*-----------------------------------------------------------------*/
2359 static void genXor (iCode *ic, iCode *ifx)
2361 operand *left, *right, *result;
2363 unsigned long lit = 0L;
2365 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2366 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2367 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2369 /* if left is a literal & right is not then exchange them */
2370 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2371 AOP_NEEDSACC(left)) {
2372 operand *tmp = right ;
2377 /* if result = right then exchange them */
2378 if(sameRegs(AOP(result),AOP(right))){
2379 operand *tmp = right ;
2384 /* if right is bit then exchange them */
2385 if (AOP_TYPE(right) == AOP_CRY &&
2386 AOP_TYPE(left) != AOP_CRY){
2387 operand *tmp = right ;
2391 if(AOP_TYPE(right) == AOP_LIT)
2392 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2394 size = AOP_SIZE(result);
2396 if (AOP_TYPE(left) == AOP_CRY){
2401 if((AOP_TYPE(right) == AOP_LIT) &&
2402 (AOP_TYPE(result) == AOP_CRY) &&
2403 (AOP_TYPE(left) != AOP_CRY)){
2408 /* if left is same as result */
2409 if(sameRegs(AOP(result),AOP(left))){
2410 for(;size--; offset++) {
2411 if(AOP_TYPE(right) == AOP_LIT){
2412 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2415 MOVA(aopGet(AOP(right),offset,FALSE));
2416 emitcode("xor","a,%s",
2417 aopGet(AOP(left),offset,FALSE));
2418 aopPut(AOP(result),"a",0);
2421 if (AOP_TYPE(left) == AOP_ACC)
2422 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2424 MOVA(aopGet(AOP(right),offset,FALSE));
2425 emitcode("xor","a,%s",
2426 aopGet(AOP(left),offset,FALSE));
2427 aopPut(AOP(result),"a",0);
2432 // left & result in different registers
2433 if(AOP_TYPE(result) == AOP_CRY){
2435 } else for(;(size--);offset++){
2437 // result = left & right
2438 if(AOP_TYPE(right) == AOP_LIT){
2439 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2441 aopGet(AOP(left),offset,FALSE),
2446 // faster than result <- left, anl result,right
2447 // and better if result is SFR
2448 if (AOP_TYPE(left) == AOP_ACC)
2449 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2451 MOVA(aopGet(AOP(right),offset,FALSE));
2452 emitcode("xor","a,%s",
2453 aopGet(AOP(left),offset,FALSE));
2454 aopPut(AOP(result),"a",0);
2456 aopPut(AOP(result),"a",offset);
2461 freeAsmop(left,NULL,ic);
2462 freeAsmop(right,NULL,ic);
2463 freeAsmop(result,NULL,ic);
2466 /*-----------------------------------------------------------------*/
2467 /* genInline - write the inline code out */
2468 /*-----------------------------------------------------------------*/
2469 static void genInline (iCode *ic)
2471 char buffer[MAX_INLINEASM];
2475 inLine += (!options.asmpeep);
2476 strcpy(buffer,IC_INLINE(ic));
2478 /* emit each line as a code */
2497 /* emitcode("",buffer); */
2498 inLine -= (!options.asmpeep);
2501 /*-----------------------------------------------------------------*/
2502 /* genRRC - rotate right with carry */
2503 /*-----------------------------------------------------------------*/
2504 static void genRRC (iCode *ic)
2509 /*-----------------------------------------------------------------*/
2510 /* genRLC - generate code for rotate left with carry */
2511 /*-----------------------------------------------------------------*/
2512 static void genRLC (iCode *ic)
2517 /*-----------------------------------------------------------------*/
2518 /* shiftR2Left2Result - shift right two bytes from left to result */
2519 /*-----------------------------------------------------------------*/
2520 static void shiftR2Left2Result (operand *left, int offl,
2521 operand *result, int offr,
2522 int shCount, int sign)
2524 if(sameRegs(AOP(result), AOP(left)) &&
2525 ((offl + MSB16) == offr)){
2528 movLeft2Result(left, offl, result, offr, 0);
2529 movLeft2Result(left, offl+1, result, offr+1, 0);
2536 /* if (AOP(result)->type == AOP_REG) {*/
2539 symbol *tlbl , *tlbl1;
2542 /* Left is already in result - so now do the shift */
2544 emitcode("ld","a,#%u+1", shCount);
2545 tlbl = newiTempLabel(NULL);
2546 tlbl1 = newiTempLabel(NULL);
2547 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2548 emitcode("", LABEL_STR ":",tlbl->key+100);
2551 emitcode("or", "a,a");
2554 l = aopGet(AOP(result), --offset, FALSE);
2555 emitcode("rr","%s", l);
2558 emitcode("", LABEL_STR ":",tlbl1->key+100);
2559 emitcode("dec", "a");
2560 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2565 /*-----------------------------------------------------------------*/
2566 /* shiftL2Left2Result - shift left two bytes from left to result */
2567 /*-----------------------------------------------------------------*/
2568 static void shiftL2Left2Result (operand *left, int offl,
2569 operand *result, int offr, int shCount)
2571 if(sameRegs(AOP(result), AOP(left)) &&
2572 ((offl + MSB16) == offr)){
2575 /* Copy left into result */
2576 movLeft2Result(left,offl, result, offr, 0);
2578 if (AOP(result)->type == AOP_REG) {
2581 symbol *tlbl , *tlbl1;
2584 /* Left is already in result - so now do the shift */
2586 emitcode("ld","a,#%u+1", shCount);
2587 tlbl = newiTempLabel(NULL);
2588 tlbl1 = newiTempLabel(NULL);
2589 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2590 emitcode("", LABEL_STR ":",tlbl->key+100);
2593 emitcode("or", "a,a");
2595 l = aopGet(AOP(result),offset++,FALSE);
2596 emitcode("rl","%s", l);
2599 emitcode("", LABEL_STR ":",tlbl1->key+100);
2600 emitcode("dec", "a");
2601 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2605 /* PENDING: do something */
2610 /*-----------------------------------------------------------------*/
2611 /* AccRol - rotate left accumulator by known count */
2612 /*-----------------------------------------------------------------*/
2613 static void AccRol (int shCount)
2615 shCount &= 0x0007; // shCount : 0..7
2652 /*-----------------------------------------------------------------*/
2653 /* AccLsh - left shift accumulator by known count */
2654 /*-----------------------------------------------------------------*/
2655 static void AccLsh (int shCount)
2659 emitcode("add","a,a");
2662 emitcode("add","a,a");
2663 emitcode("add","a,a");
2665 /* rotate left accumulator */
2667 /* and kill the lower order bits */
2668 emitcode("and","a,#0x%02x", SLMask[shCount]);
2673 /*-----------------------------------------------------------------*/
2674 /* shiftL1Left2Result - shift left one byte from left to result */
2675 /*-----------------------------------------------------------------*/
2676 static void shiftL1Left2Result (operand *left, int offl,
2677 operand *result, int offr, int shCount)
2680 l = aopGet(AOP(left),offl,FALSE);
2682 /* shift left accumulator */
2684 aopPut(AOP(result),"a",offr);
2688 /*-----------------------------------------------------------------*/
2689 /* genlshTwo - left shift two bytes by known amount != 0 */
2690 /*-----------------------------------------------------------------*/
2691 static void genlshTwo (operand *result,operand *left, int shCount)
2693 int size = AOP_SIZE(result);
2697 /* if shCount >= 8 */
2703 movLeft2Result(left, LSB, result, MSB16, 0);
2704 aopPut(AOP(result),zero, 0);
2705 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2708 movLeft2Result(left, LSB, result, MSB16, 0);
2709 aopPut(AOP(result),zero, 0);
2712 aopPut(AOP(result),zero,LSB);
2714 /* 1 <= shCount <= 7 */
2720 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2725 /*-----------------------------------------------------------------*/
2726 /* genlshOne - left shift a one byte quantity by known count */
2727 /*-----------------------------------------------------------------*/
2728 static void genlshOne (operand *result, operand *left, int shCount)
2730 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2733 /*-----------------------------------------------------------------*/
2734 /* genLeftShiftLiteral - left shifting by known count */
2735 /*-----------------------------------------------------------------*/
2736 static void genLeftShiftLiteral (operand *left,
2741 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2744 freeAsmop(right,NULL,ic);
2746 aopOp(left,ic,FALSE);
2747 aopOp(result,ic,FALSE);
2749 size = getSize(operandType(result));
2752 emitcode("; shift left ","result %d, left %d",size,
2756 /* I suppose that the left size >= result size */
2761 else if(shCount >= (size * 8))
2763 aopPut(AOP(result),zero,size);
2767 genlshOne (result,left,shCount);
2770 genlshTwo (result,left,shCount);
2779 freeAsmop(left,NULL,ic);
2780 freeAsmop(result,NULL,ic);
2783 /*-----------------------------------------------------------------*/
2784 /* genLeftShift - generates code for left shifting */
2785 /*-----------------------------------------------------------------*/
2786 static void genLeftShift (iCode *ic)
2790 symbol *tlbl , *tlbl1;
2791 operand *left,*right, *result;
2793 right = IC_RIGHT(ic);
2795 result = IC_RESULT(ic);
2797 aopOp(right,ic,FALSE);
2799 /* if the shift count is known then do it
2800 as efficiently as possible */
2801 if (AOP_TYPE(right) == AOP_LIT) {
2802 genLeftShiftLiteral (left,right,result,ic);
2806 /* shift count is unknown then we have to form a loop get the loop
2807 count in B : Note: we take only the lower order byte since
2808 shifting more that 32 bits make no sense anyway, ( the largest
2809 size of an object can be only 32 bits ) */
2810 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2811 emitcode("inc","a");
2812 freeAsmop (right,NULL,ic);
2813 aopOp(left,ic,FALSE);
2814 aopOp(result,ic,FALSE);
2816 /* now move the left to the result if they are not the
2819 if (!sameRegs(AOP(left),AOP(result))) {
2821 size = AOP_SIZE(result);
2824 l = aopGet(AOP(left),offset,FALSE);
2825 aopPut(AOP(result),l,offset);
2830 size = AOP_SIZE(result);
2833 l = aopGet(AOP(left),offset,FALSE);
2834 aopPut(AOP(result),l,offset);
2840 tlbl = newiTempLabel(NULL);
2841 size = AOP_SIZE(result);
2843 tlbl1 = newiTempLabel(NULL);
2845 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2846 emitcode("", LABEL_STR ":",tlbl->key+100);
2847 l = aopGet(AOP(result),offset,FALSE);
2848 emitcode("or", "a,a");
2850 l = aopGet(AOP(result),offset++,FALSE);
2851 emitcode("rl","%s", l);
2853 emitcode("", LABEL_STR ":",tlbl1->key+100);
2854 emitcode("dec", "a");
2855 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2857 freeAsmop(left,NULL,ic);
2858 freeAsmop(result,NULL,ic);
2861 /* genlshTwo - left shift two bytes by known amount != 0 */
2862 /*-----------------------------------------------------------------*/
2863 static void genrshOne (operand *result,operand *left, int shCount)
2866 int size = AOP_SIZE(result);
2872 l = aopGet(AOP(left),0,FALSE);
2873 if (AOP(result)->type == AOP_REG) {
2874 aopPut(AOP(result), l, 0);
2875 l = aopGet(AOP(result), 0, FALSE);
2877 emitcode("srl", "%s", l);
2882 emitcode("srl", "a");
2884 aopPut(AOP(result),"a",0);
2888 /*-----------------------------------------------------------------*/
2889 /* AccRsh - right shift accumulator by known count */
2890 /*-----------------------------------------------------------------*/
2891 static void AccRsh (int shCount)
2898 /* rotate right accumulator */
2899 AccRol(8 - shCount);
2900 /* and kill the higher order bits */
2901 emitcode("and","a,#0x%02x", SRMask[shCount]);
2906 /*-----------------------------------------------------------------*/
2907 /* shiftR1Left2Result - shift right one byte from left to result */
2908 /*-----------------------------------------------------------------*/
2909 static void shiftR1Left2Result (operand *left, int offl,
2910 operand *result, int offr,
2911 int shCount, int sign)
2913 MOVA(aopGet(AOP(left),offl,FALSE));
2920 aopPut(AOP(result),"a",offr);
2923 /*-----------------------------------------------------------------*/
2924 /* genrshTwo - right shift two bytes by known amount != 0 */
2925 /*-----------------------------------------------------------------*/
2926 static void genrshTwo (operand *result,operand *left,
2927 int shCount, int sign)
2929 /* if shCount >= 8 */
2934 shiftR1Left2Result(left, MSB16, result, LSB,
2938 movLeft2Result(left, MSB16, result, LSB, sign);
2939 aopPut(AOP(result),zero,1);
2942 /* 1 <= shCount <= 7 */
2944 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
2948 /*-----------------------------------------------------------------*/
2949 /* genRightShiftLiteral - left shifting by known count */
2950 /*-----------------------------------------------------------------*/
2951 static void genRightShiftLiteral (operand *left,
2956 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2959 freeAsmop(right,NULL,ic);
2961 aopOp(left,ic,FALSE);
2962 aopOp(result,ic,FALSE);
2964 size = getSize(operandType(result));
2966 emitcode("; shift right ","result %d, left %d",size,
2969 /* I suppose that the left size >= result size */
2974 else if(shCount >= (size * 8))
2976 aopPut(AOP(result),zero,size);
2980 genrshOne(result, left, shCount);
2983 /* PENDING: sign support */
2984 genrshTwo(result, left, shCount, FALSE);
2993 freeAsmop(left,NULL,ic);
2994 freeAsmop(result,NULL,ic);
2997 /*-----------------------------------------------------------------*/
2998 /* genRightShift - generate code for right shifting */
2999 /*-----------------------------------------------------------------*/
3000 static void genRightShift (iCode *ic)
3002 operand *left,*right, *result;
3004 right = IC_RIGHT(ic);
3006 result = IC_RESULT(ic);
3008 aopOp(right,ic,FALSE);
3010 /* if the shift count is known then do it
3011 as efficiently as possible */
3012 if (AOP_TYPE(right) == AOP_LIT) {
3013 genRightShiftLiteral (left,right,result,ic);
3021 /*-----------------------------------------------------------------*/
3022 /* genGenPointerGet - gget value from generic pointer space */
3023 /*-----------------------------------------------------------------*/
3024 static void genGenPointerGet (operand *left,
3025 operand *result, iCode *ic)
3028 link *retype = getSpec(operandType(result));
3030 aopOp(left,ic,FALSE);
3031 aopOp(result,ic,FALSE);
3033 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3035 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3036 aopPut(AOP(result),"a", 0);
3037 freeAsmop(left,NULL,ic);
3041 /* For now we always load into IY */
3042 /* if this is remateriazable */
3043 if (AOP_TYPE(left) == AOP_IMMD)
3044 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3045 else { /* we need to get it byte by byte */
3046 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3047 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3049 /* so iy now contains the address */
3050 freeAsmop(left,NULL,ic);
3052 /* if bit then unpack */
3053 if (IS_BITVAR(retype)) {
3057 size = AOP_SIZE(result);
3061 /* PENDING: make this better */
3062 if (AOP(result)->type == AOP_REG) {
3063 aopPut(AOP(result),"(hl)",offset++);
3066 emitcode("ld", "a,(hl)", offset);
3067 aopPut(AOP(result),"a",offset++);
3070 emitcode("inc", "hl");
3076 freeAsmop(result,NULL,ic);
3079 /*-----------------------------------------------------------------*/
3080 /* genPointerGet - generate code for pointer get */
3081 /*-----------------------------------------------------------------*/
3082 static void genPointerGet (iCode *ic)
3084 operand *left, *result ;
3088 result = IC_RESULT(ic) ;
3090 /* depending on the type of pointer we need to
3091 move it to the correct pointer register */
3092 type = operandType(left);
3093 etype = getSpec(type);
3095 genGenPointerGet (left,result,ic);
3098 bool isRegOrLit(asmop *aop)
3100 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3105 /*-----------------------------------------------------------------*/
3106 /* genGenPointerSet - stores the value into a pointer location */
3107 /*-----------------------------------------------------------------*/
3108 static void genGenPointerSet (operand *right,
3109 operand *result, iCode *ic)
3112 link *retype = getSpec(operandType(right));
3114 aopOp(result,ic,FALSE);
3115 aopOp(right,ic,FALSE);
3117 /* Handle the exceptions first */
3118 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3120 char *l = aopGet(AOP(right), 0, FALSE);
3122 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3123 freeAsmop(result,NULL,ic);
3127 /* if the operand is already in dptr
3128 then we do nothing else we move the value to dptr */
3129 if (AOP_TYPE(result) != AOP_STR) {
3130 /* if this is remateriazable */
3131 if (AOP_TYPE(result) == AOP_IMMD) {
3132 emitcode("", "; Error 2");
3133 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3135 else { /* we need to get it byte by byte */
3136 /* PENDING: do this better */
3137 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3138 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3141 /* so hl know contains the address */
3142 freeAsmop(result,NULL,ic);
3144 /* if bit then unpack */
3145 if (IS_BITVAR(retype)) {
3149 size = AOP_SIZE(right);
3153 char *l = aopGet(AOP(right),offset,FALSE);
3155 if (isRegOrLit(AOP(right))) {
3156 emitcode("ld", "(hl),%s", l);
3160 emitcode("ld", "(hl),a", offset);
3163 emitcode("inc", "hl");
3169 freeAsmop(right,NULL,ic);
3172 /*-----------------------------------------------------------------*/
3173 /* genPointerSet - stores the value into a pointer location */
3174 /*-----------------------------------------------------------------*/
3175 static void genPointerSet (iCode *ic)
3177 operand *right, *result ;
3180 right = IC_RIGHT(ic);
3181 result = IC_RESULT(ic) ;
3183 /* depending on the type of pointer we need to
3184 move it to the correct pointer register */
3185 type = operandType(result);
3186 etype = getSpec(type);
3188 genGenPointerSet (right,result,ic);
3191 /*-----------------------------------------------------------------*/
3192 /* genIfx - generate code for Ifx statement */
3193 /*-----------------------------------------------------------------*/
3194 static void genIfx (iCode *ic, iCode *popIc)
3196 operand *cond = IC_COND(ic);
3199 aopOp(cond,ic,FALSE);
3201 /* get the value into acc */
3202 if (AOP_TYPE(cond) != AOP_CRY)
3206 /* the result is now in the accumulator */
3207 freeAsmop(cond,NULL,ic);
3209 /* if there was something to be popped then do it */
3213 /* if the condition is a bit variable */
3214 if (isbit && IS_ITEMP(cond) &&
3216 genIfxJump(ic,SPIL_LOC(cond)->rname);
3218 if (isbit && !IS_ITEMP(cond))
3219 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3226 /*-----------------------------------------------------------------*/
3227 /* genAddrOf - generates code for address of */
3228 /*-----------------------------------------------------------------*/
3229 static void genAddrOf (iCode *ic)
3231 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3233 aopOp(IC_RESULT(ic),ic,FALSE);
3235 /* if the operand is on the stack then we
3236 need to get the stack offset of this
3239 /* if it has an offset then we need to compute it */
3240 emitcode("push", "de");
3241 emitcode("push", "ix");
3242 emitcode("pop", "hl");
3243 emitcode("ld", "de,#%d", sym->stack);
3244 emitcode("add", "hl,de");
3245 emitcode("pop", "de");
3248 emitcode("ld", "hl,#%s", sym->rname);
3250 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3251 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3253 freeAsmop(IC_RESULT(ic),NULL,ic);
3256 /*-----------------------------------------------------------------*/
3257 /* genAssign - generate code for assignment */
3258 /*-----------------------------------------------------------------*/
3259 static void genAssign (iCode *ic)
3261 operand *result, *right;
3263 unsigned long lit = 0L;
3265 result = IC_RESULT(ic);
3266 right = IC_RIGHT(ic) ;
3268 /* Dont bother assigning if they are the same */
3269 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3270 emitcode("", "; (operands are equal)");
3274 aopOp(right,ic,FALSE);
3275 aopOp(result,ic,TRUE);
3277 /* if they are the same registers */
3278 if (sameRegs(AOP(right),AOP(result))) {
3279 emitcode("", "; (registers are the same)");
3283 /* if the result is a bit */
3284 if (AOP_TYPE(result) == AOP_CRY) {
3289 size = AOP_SIZE(result);
3292 if(AOP_TYPE(right) == AOP_LIT)
3293 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3295 (AOP_TYPE(result) != AOP_REG) &&
3296 (AOP_TYPE(right) == AOP_LIT) &&
3297 !IS_FLOAT(operandType(right)) &&
3299 emitcode("xor","a,a");
3300 /* Work from the top down.
3301 Done this way so that we can use the cached copy of 0
3302 in A for a fast clear */
3304 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3305 aopPut(AOP(result),"a",size);
3308 aopGet(AOP(right),size,FALSE),
3314 aopGet(AOP(right),offset,FALSE),
3321 freeAsmop(right,NULL,ic);
3322 freeAsmop(result,NULL,ic);
3325 /*-----------------------------------------------------------------*/
3326 /* genJumpTab - genrates code for jump table */
3327 /*-----------------------------------------------------------------*/
3328 static void genJumpTab (iCode *ic)
3333 /*-----------------------------------------------------------------*/
3334 /* genCast - gen code for casting */
3335 /*-----------------------------------------------------------------*/
3336 static void genCast (iCode *ic)
3338 operand *result = IC_RESULT(ic);
3339 link *ctype = operandType(IC_LEFT(ic));
3340 operand *right = IC_RIGHT(ic);
3343 /* if they are equivalent then do nothing */
3344 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3347 aopOp(right,ic,FALSE) ;
3348 aopOp(result,ic,FALSE);
3350 /* if the result is a bit */
3351 if (AOP_TYPE(result) == AOP_CRY) {
3355 /* if they are the same size : or less */
3356 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3358 /* if they are in the same place */
3359 if (sameRegs(AOP(right),AOP(result)))
3362 /* if they in different places then copy */
3363 size = AOP_SIZE(result);
3367 aopGet(AOP(right),offset,FALSE),
3374 /* if the result is of type pointer */
3375 if (IS_PTR(ctype)) {
3379 /* so we now know that the size of destination is greater
3380 than the size of the source */
3381 /* we move to result for the size of source */
3382 size = AOP_SIZE(right);
3386 aopGet(AOP(right),offset,FALSE),
3391 /* now depending on the sign of the destination */
3392 size = AOP_SIZE(result) - AOP_SIZE(right);
3393 /* Unsigned or not an integral type - right fill with zeros */
3394 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3396 aopPut(AOP(result),zero,offset++);
3398 /* we need to extend the sign :{ */
3399 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3402 emitcode("", "; genCast: sign extend untested.");
3403 emitcode("rla", "");
3404 emitcode("sbc", "a,a");
3406 aopPut(AOP(result),"a",offset++);
3410 freeAsmop(right, NULL, ic);
3411 freeAsmop(result, NULL, ic);
3414 /*-----------------------------------------------------------------*/
3415 /* genReceive - generate code for a receive iCode */
3416 /*-----------------------------------------------------------------*/
3417 static void genReceive (iCode *ic)
3419 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3420 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3421 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3425 aopOp(IC_RESULT(ic),ic,FALSE);
3427 assignResultValue(IC_RESULT(ic));
3430 freeAsmop(IC_RESULT(ic),NULL,ic);
3433 /*-----------------------------------------------------------------*/
3434 /* genZ80Code - generate code for Z80 based controllers */
3435 /*-----------------------------------------------------------------*/
3436 void genZ80Code (iCode *lic)
3441 lineHead = lineCurr = NULL;
3443 /* if debug information required */
3444 if (options.debug && currFunc) {
3445 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3447 if (IS_STATIC(currFunc->etype))
3448 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3450 emitcode("","G$%s$0$0 ==.",currFunc->name);
3453 /* stack pointer name */
3457 for (ic = lic ; ic ; ic = ic->next ) {
3459 if ( cln != ic->lineno ) {
3460 if ( options.debug ) {
3462 emitcode("","C$%s$%d$%d$%d ==.",
3463 ic->filename,ic->lineno,
3464 ic->level,ic->block);
3467 emitcode(";","%s %d",ic->filename,ic->lineno);
3470 /* if the result is marked as
3471 spilt and rematerializable or code for
3472 this has already been generated then
3474 if (resultRemat(ic) || ic->generated )
3477 /* depending on the operation */
3480 emitcode("", "; genNot");
3485 emitcode("", "; genCpl");
3490 emitcode("", "; genUminus");
3495 emitcode("", "; genIpush");
3500 /* IPOP happens only when trying to restore a
3501 spilt live range, if there is an ifx statement
3502 following this pop then the if statement might
3503 be using some of the registers being popped which
3504 would destory the contents of the register so
3505 we need to check for this condition and handle it */
3507 ic->next->op == IFX &&
3508 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3509 emitcode("", "; genIfx");
3510 genIfx (ic->next,ic);
3513 emitcode("", "; genIpop");
3519 emitcode("", "; genCall");
3524 emitcode("", "; genPcall");
3529 emitcode("", "; genFunction");
3534 emitcode("", "; genEndFunction");
3535 genEndFunction (ic);
3539 emitcode("", "; genRet");
3544 emitcode("", "; genLabel");
3549 emitcode("", "; genGoto");
3554 emitcode("", "; genPlus");
3559 emitcode("", "; genMinus");
3564 emitcode("", "; genMult");
3569 emitcode("", "; genDiv");
3574 emitcode("", "; genMod");
3579 emitcode("", "; genCmpGt");
3580 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3584 emitcode("", "; genCmpLt");
3585 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3592 /* note these two are xlated by algebraic equivalence
3593 during parsing SDCC.y */
3594 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3595 "got '>=' or '<=' shouldn't have come here");
3599 emitcode("", "; genCmpEq");
3600 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3604 emitcode("", "; genAndOp");
3609 emitcode("", "; genOrOp");
3614 emitcode("", "; genXor");
3615 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3619 emitcode("", "; genOr");
3620 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3624 emitcode("", "; genAnd");
3625 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3629 emitcode("", "; genInline");
3634 emitcode("", "; genRRC");
3639 emitcode("", "; genRLC");
3644 emitcode("", "; genHBIT");
3648 emitcode("", "; genLeftShift");
3653 emitcode("", "; genRightShift");
3657 case GET_VALUE_AT_ADDRESS:
3658 emitcode("", "; genPointerGet");
3664 if (POINTER_SET(ic)) {
3665 emitcode("", "; genAssign (pointer)");
3669 emitcode("", "; genAssign");
3675 emitcode("", "; genIfx");
3680 emitcode("", "; genAddrOf");
3685 emitcode("", "; genJumpTab");
3690 emitcode("", "; genCast");
3695 emitcode("", "; genReceive");
3700 emitcode("", "; addSet");
3701 addSet(&sendSet,ic);
3706 /* piCode(ic,stdout); */
3712 /* now we are ready to call the
3713 peep hole optimizer */
3714 /* if (!options.nopeep)
3715 peepHole (&lineHead); */
3717 /* now do the actual printing */
3718 printLine (lineHead,codeOutFile);