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"
54 #include "SDCCglue.h" /* drdani Jan 30 2000 */
56 /* this is the down and dirty file with all kinds of kludgy & hacky
57 stuff. This is what it is all about CODE GENERATION for a specific MCU.
58 Some of the routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
63 static char *fReturn[] = {"l", "h", "e", "d" };
64 static char *accUse[] = {"a" };
70 extern int ptrRegReq ;
72 extern FILE *codeOutFile;
74 #define RESULTONSTACK(x) \
75 (IC_RESULT(x) && IC_RESULT(x)->aop && \
76 IC_RESULT(x)->aop->type == AOP_STK )
78 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
79 #define CLRC emitcode("xor","a,a");
81 #define LABEL_STR "%05d$"
83 lineNode *lineHead = NULL;
84 lineNode *lineCurr = NULL;
86 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
87 0xE0, 0xC0, 0x80, 0x00};
88 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
89 0x07, 0x03, 0x01, 0x00};
91 static int _lastStack = 0;
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple */
108 /*-----------------------------------------------------------------*/
109 void emitcode (const char *inst, const char *fmt, ...)
112 char lb[MAX_INLINEASM];
118 sprintf(lb,"%s\t",inst);
119 vsprintf(lb+(strlen(lb)),fmt,ap);
123 while (isspace(*lbp)) lbp++;
126 lineCurr = (lineCurr ?
127 connectLine(lineCurr,newLineNode(lb)) :
128 (lineHead = newLineNode(lb)));
129 lineCurr->isInline = inLine;
130 lineCurr->isDebug = debugLine;
134 const char *getPairName(asmop *aop)
136 if (aop->type == AOP_REG) {
137 switch (aop->aopu.aop_reg[0]->rIdx) {
149 else if (aop->type == AOP_STR) {
150 switch (*aop->aopu.aop_str[0]) {
166 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
167 bool isPair(asmop *aop)
169 if (aop->size == 2) {
170 if (aop->type == AOP_REG) {
171 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
174 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
177 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
181 if (aop->type == AOP_STR) {
182 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
185 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
188 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
196 /** Push a register pair onto the stack */
197 void genPairPush(asmop *aop)
199 emitcode("push", "%s", getPairName(aop));
202 /*-----------------------------------------------------------------*/
203 /* newAsmop - creates a new asmOp */
204 /*-----------------------------------------------------------------*/
205 static asmop *newAsmop (short type)
209 ALLOC(aop,sizeof(asmop));
214 /*-----------------------------------------------------------------*/
215 /* aopForSym - for a true symbol */
216 /*-----------------------------------------------------------------*/
217 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
220 memmap *space= SPEC_OCLS(sym->etype);
222 /* if already has one */
226 /* Assign depending on the storage class */
227 if (sym->onStack || sym->iaccess) {
228 sym->aop = aop = newAsmop(AOP_STK);
229 aop->size = getSize(sym->type);
231 aop->aopu.aop_stk = sym->stack;
235 /* special case for a function */
236 if (IS_FUNC(sym->type)) {
237 sym->aop = aop = newAsmop(AOP_IMMD);
238 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
239 strcpy(aop->aopu.aop_immd,sym->rname);
244 /* only remaining is far space */
245 /* in which case DPTR gets the address */
246 sym->aop = aop = newAsmop(AOP_IY);
247 emitcode ("ld","iy,#%s", sym->rname);
248 aop->size = getSize(sym->type);
249 aop->aopu.aop_dir = sym->rname;
251 /* if it is in code space */
252 if (IN_CODESPACE(space))
258 /*-----------------------------------------------------------------*/
259 /* aopForRemat - rematerialzes an object */
260 /*-----------------------------------------------------------------*/
261 static asmop *aopForRemat (symbol *sym)
264 iCode *ic = sym->rematiCode;
265 asmop *aop = newAsmop(AOP_IMMD);
268 /* if plus or minus print the right hand side */
269 if (ic->op == '+' || ic->op == '-') {
270 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
273 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
276 /* we reached the end */
277 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
281 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
282 strcpy(aop->aopu.aop_immd,buffer);
286 /*-----------------------------------------------------------------*/
287 /* regsInCommon - two operands have some registers in common */
288 /*-----------------------------------------------------------------*/
289 bool regsInCommon (operand *op1, operand *op2)
294 /* if they have registers in common */
295 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
298 sym1 = OP_SYMBOL(op1);
299 sym2 = OP_SYMBOL(op2);
301 if (sym1->nRegs == 0 || sym2->nRegs == 0)
304 for (i = 0 ; i < sym1->nRegs ; i++) {
309 for (j = 0 ; j < sym2->nRegs ;j++ ) {
313 if (sym2->regs[j] == sym1->regs[i])
321 /*-----------------------------------------------------------------*/
322 /* operandsEqu - equivalent */
323 /*-----------------------------------------------------------------*/
324 bool operandsEqu ( operand *op1, operand *op2)
328 /* if they not symbols */
329 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
332 sym1 = OP_SYMBOL(op1);
333 sym2 = OP_SYMBOL(op2);
335 /* if both are itemps & one is spilt
336 and the other is not then false */
337 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
338 sym1->isspilt != sym2->isspilt )
341 /* if they are the same */
345 if (strcmp(sym1->rname,sym2->rname) == 0)
349 /* if left is a tmp & right is not */
353 (sym1->usl.spillLoc == sym2))
360 (sym2->usl.spillLoc == sym1))
366 /*-----------------------------------------------------------------*/
367 /* sameRegs - two asmops have the same registers */
368 /*-----------------------------------------------------------------*/
369 bool sameRegs (asmop *aop1, asmop *aop2 )
376 if (aop1->type != AOP_REG ||
377 aop2->type != AOP_REG )
380 if (aop1->size != aop2->size)
383 for (i = 0 ; i < aop1->size ; i++ )
384 if (aop1->aopu.aop_reg[i] !=
385 aop2->aopu.aop_reg[i] )
391 /*-----------------------------------------------------------------*/
392 /* aopOp - allocates an asmop for an operand : */
393 /*-----------------------------------------------------------------*/
394 static void aopOp (operand *op, iCode *ic, bool result)
403 /* if this a literal */
404 if (IS_OP_LITERAL(op)) {
405 op->aop = aop = newAsmop(AOP_LIT);
406 aop->aopu.aop_lit = op->operand.valOperand;
407 aop->size = getSize(operandType(op));
411 /* if already has a asmop then continue */
415 /* if the underlying symbol has a aop */
416 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
417 op->aop = OP_SYMBOL(op)->aop;
421 /* if this is a true symbol */
422 if (IS_TRUE_SYMOP(op)) {
423 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
427 /* this is a temporary : this has
433 e) can be a return use only */
437 /* if the type is a conditional */
438 if (sym->regType == REG_CND) {
439 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
444 /* if it is spilt then two situations
446 b) has a spill location */
447 if (sym->isspilt || sym->nRegs == 0) {
448 /* rematerialize it NOW */
450 sym->aop = op->aop = aop =
452 aop->size = getSize(sym->type);
458 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
459 aop->size = getSize(sym->type);
460 for ( i = 0 ; i < 2 ; i++ )
461 aop->aopu.aop_str[i] = accUse[i];
467 aop = op->aop = sym->aop = newAsmop(AOP_STR);
468 aop->size = getSize(sym->type);
469 for ( i = 0 ; i < 4 ; i++ )
470 aop->aopu.aop_str[i] = fReturn[i];
474 /* else spill location */
475 sym->aop = op->aop = aop =
476 aopForSym(ic,sym->usl.spillLoc,result);
477 aop->size = getSize(sym->type);
481 /* must be in a register */
482 sym->aop = op->aop = aop = newAsmop(AOP_REG);
483 aop->size = sym->nRegs;
484 for ( i = 0 ; i < sym->nRegs ;i++)
485 aop->aopu.aop_reg[i] = sym->regs[i];
488 /*-----------------------------------------------------------------*/
489 /* freeAsmop - free up the asmop given to an operand */
490 /*----------------------------------------------------------------*/
491 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
514 /* all other cases just dealloc */
518 OP_SYMBOL(op)->aop = NULL;
519 /* if the symbol has a spill */
521 SPIL_LOC(op)->aop = NULL;
526 char *aopGetWord(asmop *aop, int offset)
531 assert(aop->size == 2);
534 /* depending on type */
537 sprintf (s,"#%s",aop->aopu.aop_immd);
538 ALLOC_ATOMIC(rs,strlen(s)+1);
543 value * val = aop->aopu.aop_lit;
544 /* if it is a float then it gets tricky */
545 /* otherwise it is fairly simple */
546 if (!IS_FLOAT(val->type)) {
547 unsigned long v = floatFromVal(val);
549 sprintf(buffer,"#0x%04lx", v);
550 ALLOC_ATOMIC(rs,strlen(buffer)+1);
551 return strcpy (rs,buffer);
560 /*-----------------------------------------------------------------*/
561 /* aopGet - for fetching value of the aop */
562 /*-----------------------------------------------------------------*/
563 static char *aopGet (asmop *aop, int offset, bool bit16)
568 /* offset is greater than size then zero */
569 if (offset > (aop->size - 1) &&
570 aop->type != AOP_LIT)
573 /* depending on type */
577 sprintf (s,"#%s",aop->aopu.aop_immd);
587 ALLOC_ATOMIC(rs,strlen(s)+1);
593 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
595 ALLOC_ATOMIC(rs,strlen(s)+1);
600 return aop->aopu.aop_reg[offset]->name;
603 sprintf(s,"%d(iy)", offset);
604 ALLOC_ATOMIC(rs,strlen(s)+1);
609 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
610 ALLOC_ATOMIC(rs,strlen(s)+1);
624 return aopLiteral (aop->aopu.aop_lit,offset);
628 return aop->aopu.aop_str[offset];
631 fprintf(stderr, "Type %u\n", aop->type);
633 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
634 "aopget got unsupported aop->type");
638 bool isRegString(char *s)
640 if (!strcmp(s, "b") ||
651 bool isConstant(char *s)
656 bool canAssignToPtr(char *s)
665 /*-----------------------------------------------------------------*/
666 /* aopPut - puts a string for a aop */
667 /*-----------------------------------------------------------------*/
668 static void aopPut (asmop *aop, char *s, int offset)
672 if (aop->size && offset > ( aop->size - 1)) {
673 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
674 "aopPut got offset > aop->size");
678 /* will assign value to value */
679 /* depending on where it is ofcourse */
684 emitcode("ld", "a,%s", s);
685 emitcode("ld", "(%s+%d),a", d, offset);
689 /* Dont bother if it's a ld x,x */
690 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
691 emitcode("ld","%s,%s",
692 aop->aopu.aop_reg[offset]->name,s);
697 if (!canAssignToPtr(s)) {
698 emitcode("ld", "a,%s", s);
699 emitcode("ld", "%d(iy),a", offset);
702 emitcode("ld", "%d(iy),%s", offset, s);
706 if (!canAssignToPtr(s)) {
707 emitcode("ld", "a,%s", s);
708 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
711 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
715 /* if bit variable */
716 if (!aop->aopu.aop_dir) {
717 emitcode("ld", "a,#0");
720 /* In bit space but not in C - cant happen */
727 if (strcmp(aop->aopu.aop_str[offset],s)) {
728 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
734 if (!offset && (strcmp(s,"acc") == 0))
737 emitcode("", "; Error aopPut AOP_ACC");
740 if (strcmp(aop->aopu.aop_str[offset],s))
741 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
746 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
747 "aopPut got unsupported aop->type");
752 #define AOP(op) op->aop
753 #define AOP_TYPE(op) AOP(op)->type
754 #define AOP_SIZE(op) AOP(op)->size
755 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
757 /*-----------------------------------------------------------------*/
758 /* getDataSize - get the operand data size */
759 /*-----------------------------------------------------------------*/
760 int getDataSize(operand *op)
771 /*-----------------------------------------------------------------*/
772 /* movLeft2Result - move byte from left to result */
773 /*-----------------------------------------------------------------*/
774 static void movLeft2Result (operand *left, int offl,
775 operand *result, int offr, int sign)
778 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
779 l = aopGet(AOP(left),offl,FALSE);
782 aopPut(AOP(result),l,offr);
791 /** Put Acc into a register set
793 void outAcc(operand *result)
796 size = getDataSize(result);
798 aopPut(AOP(result),"a",0);
801 /* unsigned or positive */
803 aopPut(AOP(result),zero,offset++);
808 /** Take the value in carry and put it into a register
810 void outBitC(operand *result)
812 /* if the result is bit */
813 if (AOP_TYPE(result) == AOP_CRY) {
814 emitcode("", "; Note: outBitC form 1");
815 aopPut(AOP(result),"blah",0);
818 emitcode("ld", "a,#0");
824 /*-----------------------------------------------------------------*/
825 /* toBoolean - emit code for orl a,operator(sizeop) */
826 /*-----------------------------------------------------------------*/
827 void toBoolean(operand *oper)
829 int size = AOP_SIZE(oper);
832 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
835 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
839 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
843 /*-----------------------------------------------------------------*/
844 /* genNot - generate code for ! operation */
845 /*-----------------------------------------------------------------*/
846 static void genNot (iCode *ic)
848 link *optype = operandType(IC_LEFT(ic));
850 /* assign asmOps to operand & result */
851 aopOp (IC_LEFT(ic),ic,FALSE);
852 aopOp (IC_RESULT(ic),ic,TRUE);
854 /* if in bit space then a special case */
855 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
859 /* if type float then do float */
860 if (IS_FLOAT(optype)) {
864 toBoolean(IC_LEFT(ic));
869 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
870 emitcode("sub", "a,#0x01");
871 outBitC(IC_RESULT(ic));
873 /* release the aops */
874 freeAsmop(IC_LEFT(ic),NULL,ic);
875 freeAsmop(IC_RESULT(ic),NULL,ic);
878 /*-----------------------------------------------------------------*/
879 /* genCpl - generate code for complement */
880 /*-----------------------------------------------------------------*/
881 static void genCpl (iCode *ic)
887 /* assign asmOps to operand & result */
888 aopOp (IC_LEFT(ic),ic,FALSE);
889 aopOp (IC_RESULT(ic),ic,TRUE);
891 /* if both are in bit space then
893 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
894 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
898 size = AOP_SIZE(IC_RESULT(ic));
900 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
903 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
906 /* release the aops */
907 freeAsmop(IC_LEFT(ic),NULL,ic);
908 freeAsmop(IC_RESULT(ic),NULL,ic);
911 /*-----------------------------------------------------------------*/
912 /* genUminus - unary minus code generation */
913 /*-----------------------------------------------------------------*/
914 static void genUminus (iCode *ic)
920 /*-----------------------------------------------------------------*/
921 /* assignResultValue - */
922 /*-----------------------------------------------------------------*/
923 void assignResultValue(operand * oper)
926 int size = AOP_SIZE(oper);
928 aopPut(AOP(oper),fReturn[offset],offset);
933 /*-----------------------------------------------------------------*/
934 /* genIpush - genrate code for pushing this gets a little complex */
935 /*-----------------------------------------------------------------*/
936 static void genIpush (iCode *ic)
938 int size, offset = 0 ;
942 /* if this is not a parm push : ie. it is spill push
943 and spill push is always done on the local stack */
945 /* and the item is spilt then do nothing */
946 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
949 aopOp(IC_LEFT(ic),ic,FALSE);
950 size = AOP_SIZE(IC_LEFT(ic));
951 /* push it on the stack */
952 if (isPair(AOP(IC_LEFT(ic)))) {
953 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
958 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
959 /* Simple for now - load into A and PUSH AF */
960 emitcode("ld", "a,%s", l);
961 emitcode("push", "af");
962 emitcode("inc", "sp");
968 /* Hmmm... what about saving the currently used registers
971 /* then do the push */
972 aopOp(IC_LEFT(ic),ic,FALSE);
974 size = AOP_SIZE(IC_LEFT(ic));
976 if (isPair(AOP(IC_LEFT(ic)))) {
977 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
981 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
983 emitcode("ld", "hl,%s", s);
984 emitcode("push", "hl");
990 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
991 emitcode("ld", "a,%s", l);
992 emitcode("push", "af");
993 emitcode("inc", "sp");
997 freeAsmop(IC_LEFT(ic),NULL,ic);
1000 /*-----------------------------------------------------------------*/
1001 /* genIpop - recover the registers: can happen only for spilling */
1002 /*-----------------------------------------------------------------*/
1003 static void genIpop (iCode *ic)
1008 /* if the temp was not pushed then */
1009 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1012 aopOp(IC_LEFT(ic),ic,FALSE);
1013 size = AOP_SIZE(IC_LEFT(ic));
1015 if (isPair(AOP(IC_LEFT(ic)))) {
1016 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1020 emitcode("dec", "sp");
1021 emitcode("pop", "hl");
1022 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1026 freeAsmop(IC_LEFT(ic),NULL,ic);
1029 /** Emit the code for a call statement
1031 static void emitCall (iCode *ic, bool ispcall)
1033 /* if caller saves & we have not saved then */
1034 if (!ic->regsSaved) {
1038 /* if send set is not empty then assign */
1042 for (sic = setFirstItem(sendSet) ; sic ;
1043 sic = setNextItem(sendSet)) {
1044 int size, offset = 0;
1045 aopOp(IC_LEFT(sic),sic,FALSE);
1046 size = AOP_SIZE(IC_LEFT(sic));
1048 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1050 if (strcmp(l,fReturn[offset]))
1051 emitcode("ld","%s,%s",
1056 freeAsmop (IC_LEFT(sic),NULL,sic);
1062 symbol *rlbl = newiTempLabel(NULL);
1064 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1065 emitcode("push", "hl");
1067 aopOp(IC_LEFT(ic),ic,FALSE);
1068 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1069 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1070 freeAsmop(IC_LEFT(ic),NULL,ic);
1072 emitcode("jp", "(hl)");
1073 emitcode("","%05d$:",(rlbl->key+100));
1077 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1078 OP_SYMBOL(IC_LEFT(ic))->rname :
1079 OP_SYMBOL(IC_LEFT(ic))->name));
1082 /* if we need assign a result value */
1083 if ((IS_ITEMP(IC_RESULT(ic)) &&
1084 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1085 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1086 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1089 aopOp(IC_RESULT(ic),ic,FALSE);
1092 assignResultValue(IC_RESULT(ic));
1094 freeAsmop(IC_RESULT(ic),NULL, ic);
1097 /* adjust the stack for parameters if required */
1098 if (IC_LEFT(ic)->parmBytes) {
1099 int i = IC_LEFT(ic)->parmBytes;
1101 emitcode("ld", "hl,#%d", i);
1102 emitcode("add", "hl,sp");
1103 emitcode("ld", "sp,hl");
1107 emitcode("pop", "hl");
1111 emitcode("inc", "sp");
1117 /*-----------------------------------------------------------------*/
1118 /* genCall - generates a call statement */
1119 /*-----------------------------------------------------------------*/
1120 static void genCall (iCode *ic)
1122 emitCall(ic, FALSE);
1125 /*-----------------------------------------------------------------*/
1126 /* genPcall - generates a call by pointer statement */
1127 /*-----------------------------------------------------------------*/
1128 static void genPcall (iCode *ic)
1133 /*-----------------------------------------------------------------*/
1134 /* resultRemat - result is rematerializable */
1135 /*-----------------------------------------------------------------*/
1136 static int resultRemat (iCode *ic)
1138 if (SKIP_IC(ic) || ic->op == IFX)
1141 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1142 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1143 if (sym->remat && !POINTER_SET(ic))
1150 /*-----------------------------------------------------------------*/
1151 /* genFunction - generated code for function entry */
1152 /*-----------------------------------------------------------------*/
1153 static void genFunction (iCode *ic)
1159 /* create the function header */
1160 emitcode(";","-----------------------------------------");
1161 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1162 emitcode(";","-----------------------------------------");
1164 emitcode("","%s:",sym->rname);
1165 fetype = getSpec(operandType(IC_LEFT(ic)));
1167 /* if critical function then turn interrupts off */
1168 if (SPEC_CRTCL(fetype))
1171 /* if this is an interrupt service routine then
1172 save acc, b, dpl, dph */
1173 if (IS_ISR(sym->etype)) {
1174 emitcode("push", "af");
1175 emitcode("push", "bc");
1176 emitcode("push", "de");
1177 emitcode("push", "hl");
1179 /* PENDING: callee-save etc */
1181 /* adjust the stack for the function */
1182 emitcode("push", "de");
1183 emitcode("push", "bc");
1184 emitcode("push", "ix");
1185 emitcode("ld", "ix,#0");
1186 emitcode("add", "ix,sp");
1188 _lastStack = sym->stack;
1191 emitcode("ld", "hl,#-%d", sym->stack);
1192 emitcode("add", "hl,sp");
1193 emitcode("ld", "sp,hl");
1197 /*-----------------------------------------------------------------*/
1198 /* genEndFunction - generates epilogue for functions */
1199 /*-----------------------------------------------------------------*/
1200 static void genEndFunction (iCode *ic)
1202 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1204 if (IS_ISR(sym->etype)) {
1208 if (SPEC_CRTCL(sym->etype))
1211 /* PENDING: calleeSave */
1213 /* if debug then send end of function */
1214 if (options.debug && currFunc) {
1216 emitcode("","C$%s$%d$%d$%d ==.",
1217 ic->filename,currFunc->lastLine,
1218 ic->level,ic->block);
1219 if (IS_STATIC(currFunc->etype))
1220 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1222 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1225 emitcode("ld", "sp,ix");
1226 emitcode("pop", "ix");
1227 emitcode("pop", "bc");
1228 emitcode("pop", "de");
1229 emitcode("ret", "");
1234 /*-----------------------------------------------------------------*/
1235 /* genRet - generate code for return statement */
1236 /*-----------------------------------------------------------------*/
1237 static void genRet (iCode *ic)
1240 /* Errk. This is a hack until I can figure out how
1241 to cause dehl to spill on a call */
1242 int size,offset = 0;
1244 /* if we have no return value then
1245 just generate the "ret" */
1249 /* we have something to return then
1250 move the return value into place */
1251 aopOp(IC_LEFT(ic),ic,FALSE);
1252 size = AOP_SIZE(IC_LEFT(ic));
1254 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1255 emitcode("ld", "hl,%s", l);
1259 l = aopGet(AOP(IC_LEFT(ic)),offset,
1261 if (strcmp(fReturn[offset],l))
1262 emitcode("ld","%s,%s",fReturn[offset++],l);
1265 freeAsmop (IC_LEFT(ic),NULL,ic);
1268 /* generate a jump to the return label
1269 if the next is not the return statement */
1270 if (!(ic->next && ic->next->op == LABEL &&
1271 IC_LABEL(ic->next) == returnLabel))
1273 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1276 /*-----------------------------------------------------------------*/
1277 /* genLabel - generates a label */
1278 /*-----------------------------------------------------------------*/
1279 static void genLabel (iCode *ic)
1281 /* special case never generate */
1282 if (IC_LABEL(ic) == entryLabel)
1285 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1288 /*-----------------------------------------------------------------*/
1289 /* genGoto - generates a ljmp */
1290 /*-----------------------------------------------------------------*/
1291 static void genGoto (iCode *ic)
1293 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1296 /*-----------------------------------------------------------------*/
1297 /* genPlusIncr :- does addition with increment if possible */
1298 /*-----------------------------------------------------------------*/
1299 static bool genPlusIncr (iCode *ic)
1301 unsigned int icount ;
1302 unsigned int size = getDataSize(IC_RESULT(ic));
1304 /* will try to generate an increment */
1305 /* if the right side is not a literal
1307 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1310 /* if the literal value of the right hand side
1311 is greater than 4 then it is not worth it */
1312 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1316 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1317 isPair(AOP(IC_RESULT(ic)))) {
1319 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1323 /* if increment 16 bits in register */
1324 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1327 symbol *tlbl = newiTempLabel(NULL);
1328 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1329 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1331 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1335 emitcode("", LABEL_STR ":",tlbl->key+100);
1339 /* If result is a pair */
1340 if (isPair(AOP(IC_RESULT(ic)))) {
1341 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1342 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1344 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1348 /* if the sizes are greater than 1 then we cannot */
1349 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1350 AOP_SIZE(IC_LEFT(ic)) > 1 )
1353 /* we can if the aops of the left & result match or
1354 if they are in registers and the registers are the
1356 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1358 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1366 /*-----------------------------------------------------------------*/
1367 /* outBitAcc - output a bit in acc */
1368 /*-----------------------------------------------------------------*/
1369 void outBitAcc(operand *result)
1371 symbol *tlbl = newiTempLabel(NULL);
1372 /* if the result is a bit */
1373 if (AOP_TYPE(result) == AOP_CRY){
1377 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1378 emitcode("ld","a,%s",one);
1379 emitcode("", LABEL_STR ":",tlbl->key+100);
1384 /*-----------------------------------------------------------------*/
1385 /* genPlus - generates code for addition */
1386 /*-----------------------------------------------------------------*/
1387 static void genPlus (iCode *ic)
1389 int size, offset = 0;
1391 /* special cases :- */
1393 aopOp (IC_LEFT(ic),ic,FALSE);
1394 aopOp (IC_RIGHT(ic),ic,FALSE);
1395 aopOp (IC_RESULT(ic),ic,TRUE);
1397 /* Swap the left and right operands if:
1399 if literal, literal on the right or
1400 if left requires ACC or right is already
1403 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1404 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1405 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1406 operand *t = IC_RIGHT(ic);
1407 IC_RIGHT(ic) = IC_LEFT(ic);
1411 /* if both left & right are in bit
1413 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1414 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1419 /* if left in bit space & right literal */
1420 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1421 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1422 /* Can happen I guess */
1426 /* if I can do an increment instead
1427 of add then GOOD for ME */
1428 if (genPlusIncr (ic) == TRUE)
1431 size = getDataSize(IC_RESULT(ic));
1434 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1435 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1437 emitcode("add","a,%s",
1438 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1440 emitcode("adc","a,%s",
1441 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1443 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1445 emitcode("add","a,%s",
1446 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1448 emitcode("adc","a,%s",
1449 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1451 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1454 /* Some kind of pointer arith. */
1455 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1456 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1457 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1460 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1461 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1462 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1467 freeAsmop(IC_LEFT(ic),NULL,ic);
1468 freeAsmop(IC_RIGHT(ic),NULL,ic);
1469 freeAsmop(IC_RESULT(ic),NULL,ic);
1473 /*-----------------------------------------------------------------*/
1474 /* genMinusDec :- does subtraction with deccrement if possible */
1475 /*-----------------------------------------------------------------*/
1476 static bool genMinusDec (iCode *ic)
1478 unsigned int icount ;
1479 unsigned int size = getDataSize(IC_RESULT(ic));
1481 /* will try to generate an increment */
1482 /* if the right side is not a literal we cannot */
1483 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1486 /* if the literal value of the right hand side
1487 is greater than 4 then it is not worth it */
1488 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1491 size = getDataSize(IC_RESULT(ic));
1492 /* if decrement 16 bits in register */
1493 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1494 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1496 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1500 /* If result is a pair */
1501 if (isPair(AOP(IC_RESULT(ic)))) {
1502 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1503 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1505 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1509 /* if the sizes are greater than 1 then we cannot */
1510 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1511 AOP_SIZE(IC_LEFT(ic)) > 1 )
1514 /* we can if the aops of the left & result match or if they are in
1515 registers and the registers are the same */
1516 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1518 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1525 /*-----------------------------------------------------------------*/
1526 /* genMinus - generates code for subtraction */
1527 /*-----------------------------------------------------------------*/
1528 static void genMinus (iCode *ic)
1530 int size, offset = 0;
1531 unsigned long lit = 0L;
1533 aopOp (IC_LEFT(ic),ic,FALSE);
1534 aopOp (IC_RIGHT(ic),ic,FALSE);
1535 aopOp (IC_RESULT(ic),ic,TRUE);
1537 /* special cases :- */
1538 /* if both left & right are in bit space */
1539 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1540 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1545 /* if I can do an decrement instead of subtract then GOOD for ME */
1546 if (genMinusDec (ic) == TRUE)
1549 size = getDataSize(IC_RESULT(ic));
1551 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1555 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1560 /* if literal, add a,#-lit, else normal subb */
1562 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1563 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1564 emitcode("sbc","a,%s",
1565 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1567 /* first add without previous c */
1569 emitcode("add","a,#0x%02x",
1570 (unsigned int)(lit & 0x0FFL));
1572 emitcode("adc","a,#0x%02x",
1573 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1575 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1578 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1579 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1580 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1584 freeAsmop(IC_LEFT(ic),NULL,ic);
1585 freeAsmop(IC_RIGHT(ic),NULL,ic);
1586 freeAsmop(IC_RESULT(ic),NULL,ic);
1589 /*-----------------------------------------------------------------*/
1590 /* genMult - generates code for multiplication */
1591 /*-----------------------------------------------------------------*/
1592 static void genMult (iCode *ic)
1594 /* Shouldn't occur - all done through function calls */
1598 /*-----------------------------------------------------------------*/
1599 /* genDiv - generates code for division */
1600 /*-----------------------------------------------------------------*/
1601 static void genDiv (iCode *ic)
1603 /* Shouldn't occur - all done through function calls */
1607 /*-----------------------------------------------------------------*/
1608 /* genMod - generates code for division */
1609 /*-----------------------------------------------------------------*/
1610 static void genMod (iCode *ic)
1612 /* Shouldn't occur - all done through function calls */
1616 /*-----------------------------------------------------------------*/
1617 /* genIfxJump :- will create a jump depending on the ifx */
1618 /*-----------------------------------------------------------------*/
1619 static void genIfxJump (iCode *ic, char *jval)
1624 /* if true label then we jump if condition
1626 if ( IC_TRUE(ic) ) {
1628 if (!strcmp(jval, "a")) {
1631 else if (!strcmp(jval, "c")) {
1635 /* The buffer contains the bit on A that we should test */
1640 /* false label is present */
1641 jlbl = IC_FALSE(ic) ;
1642 if (!strcmp(jval, "a")) {
1645 else if (!strcmp(jval, "c")) {
1649 /* The buffer contains the bit on A that we should test */
1653 /* Z80 can do a conditional long jump */
1654 if (!strcmp(jval, "a")) {
1655 emitcode("or", "a,a");
1657 else if (!strcmp(jval, "c")) {
1660 emitcode("bit", "%s,a", jval);
1662 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1664 /* mark the icode as generated */
1668 /** Generic compare for > or <
1670 static void genCmp (operand *left,operand *right,
1671 operand *result, iCode *ifx, int sign)
1673 int size, offset = 0 ;
1674 unsigned long lit = 0L;
1676 /* if left & right are bit variables */
1677 if (AOP_TYPE(left) == AOP_CRY &&
1678 AOP_TYPE(right) == AOP_CRY ) {
1679 /* Cant happen on the Z80 */
1682 /* subtract right from left if at the
1683 end the carry flag is set then we know that
1684 left is greater than right */
1685 size = max(AOP_SIZE(left),AOP_SIZE(right));
1687 /* if unsigned char cmp with lit, just compare */
1688 if((size == 1) && !sign &&
1689 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1690 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1691 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1694 if(AOP_TYPE(right) == AOP_LIT) {
1695 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1696 /* optimize if(x < 0) or if(x >= 0) */
1699 /* No sign so it's always false */
1703 /* Just load in the top most bit */
1704 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1705 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1706 genIfxJump (ifx,"7");
1710 emitcode("rlc","a");
1716 /* Do a long subtract */
1717 MOVA(aopGet(AOP(left),offset,FALSE));
1718 if (sign && size == 0) {
1719 /* Case where it's signed and we've hit the end */
1720 /* PENDING: This is almost certanitly wrong.
1721 On the 8051 xrl doesnt change C, but xor does.
1723 emitcode("xor","a,#0x80");
1724 if (AOP_TYPE(right) == AOP_LIT){
1725 unsigned long lit = (unsigned long)
1726 floatFromVal(AOP(right)->aopu.aop_lit);
1727 emitcode("sbc","a,#0x%02x",
1728 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1730 /* The bad way... */
1731 emitcode("push", "af");
1732 emitcode("ld","a,%s",aopGet(AOP(right),offset++,FALSE));
1733 emitcode("xor", "a,#0x80");
1734 emitcode("ld", "l,a");
1735 emitcode("pop", "af");
1736 emitcode("sbc","a,l");
1739 /* Subtract through, propagating the carry */
1741 emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1744 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1751 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1754 /* if the result is used in the next
1755 ifx conditional branch then generate
1756 code a little differently */
1758 genIfxJump (ifx,"c");
1761 /* leave the result in acc */
1765 /*-----------------------------------------------------------------*/
1766 /* genCmpGt :- greater than comparison */
1767 /*-----------------------------------------------------------------*/
1768 static void genCmpGt (iCode *ic, iCode *ifx)
1770 operand *left, *right, *result;
1771 link *letype , *retype;
1775 right= IC_RIGHT(ic);
1776 result = IC_RESULT(ic);
1778 letype = getSpec(operandType(left));
1779 retype =getSpec(operandType(right));
1780 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1781 /* assign the amsops */
1782 aopOp (left,ic,FALSE);
1783 aopOp (right,ic,FALSE);
1784 aopOp (result,ic,TRUE);
1786 genCmp(right, left, result, ifx, sign);
1788 freeAsmop(left,NULL,ic);
1789 freeAsmop(right,NULL,ic);
1790 freeAsmop(result,NULL,ic);
1793 /*-----------------------------------------------------------------*/
1794 /* genCmpLt - less than comparisons */
1795 /*-----------------------------------------------------------------*/
1796 static void genCmpLt (iCode *ic, iCode *ifx)
1798 operand *left, *right, *result;
1799 link *letype , *retype;
1803 right= IC_RIGHT(ic);
1804 result = IC_RESULT(ic);
1806 letype = getSpec(operandType(left));
1807 retype =getSpec(operandType(right));
1808 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1810 /* assign the amsops */
1811 aopOp (left,ic,FALSE);
1812 aopOp (right,ic,FALSE);
1813 aopOp (result,ic,TRUE);
1815 genCmp(left, right, result, ifx, sign);
1817 freeAsmop(left,NULL,ic);
1818 freeAsmop(right,NULL,ic);
1819 freeAsmop(result,NULL,ic);
1822 /*-----------------------------------------------------------------*/
1823 /* gencjneshort - compare and jump if not equal */
1824 /*-----------------------------------------------------------------*/
1825 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1827 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1829 unsigned long lit = 0L;
1831 /* Swap the left and right if it makes the computation easier */
1832 if (AOP_TYPE(left) == AOP_LIT) {
1838 if(AOP_TYPE(right) == AOP_LIT)
1839 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1841 /* if the right side is a literal then anything goes */
1842 if (AOP_TYPE(right) == AOP_LIT &&
1843 AOP_TYPE(left) != AOP_DIR ) {
1845 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1846 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1847 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1851 /* if the right side is in a register or in direct space or
1852 if the left is a pointer register & right is not */
1853 else if (AOP_TYPE(right) == AOP_REG ||
1854 AOP_TYPE(right) == AOP_DIR ||
1855 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1857 MOVA(aopGet(AOP(left),offset,FALSE));
1858 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1859 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1861 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1863 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1864 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1869 /* right is a pointer reg need both a & b */
1870 /* PENDING: is this required? */
1872 char *l = aopGet(AOP(left),offset,FALSE);
1873 MOVA(aopGet(AOP(right),offset,FALSE));
1874 emitcode("cp", "%s", l);
1875 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
1881 /*-----------------------------------------------------------------*/
1882 /* gencjne - compare and jump if not equal */
1883 /*-----------------------------------------------------------------*/
1884 static void gencjne(operand *left, operand *right, symbol *lbl)
1886 symbol *tlbl = newiTempLabel(NULL);
1888 gencjneshort(left, right, lbl);
1891 emitcode("ld","a,%s",one);
1892 emitcode("jp", LABEL_STR ,tlbl->key+100);
1893 emitcode("", LABEL_STR ":",lbl->key+100);
1894 emitcode("xor","a,a");
1895 emitcode("", LABEL_STR ":",tlbl->key+100);
1898 /*-----------------------------------------------------------------*/
1899 /* genCmpEq - generates code for equal to */
1900 /*-----------------------------------------------------------------*/
1901 static void genCmpEq (iCode *ic, iCode *ifx)
1903 operand *left, *right, *result;
1905 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1906 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1907 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1909 /* Swap operands if it makes the operation easier. ie if:
1910 1. Left is a literal.
1912 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1913 operand *t = IC_RIGHT(ic);
1914 IC_RIGHT(ic) = IC_LEFT(ic);
1918 if (ifx && !AOP_SIZE(result)){
1920 /* if they are both bit variables */
1921 if (AOP_TYPE(left) == AOP_CRY &&
1922 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1925 tlbl = newiTempLabel(NULL);
1926 gencjneshort(left, right, tlbl);
1927 if ( IC_TRUE(ifx) ) {
1928 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1929 emitcode("", LABEL_STR ":",tlbl->key+100);
1931 /* PENDING: do this better */
1932 symbol *lbl = newiTempLabel(NULL);
1933 emitcode("jp", LABEL_STR ,lbl->key+100);
1934 emitcode("", LABEL_STR ":",tlbl->key+100);
1935 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1936 emitcode("", LABEL_STR ":",lbl->key+100);
1939 /* mark the icode as generated */
1944 /* if they are both bit variables */
1945 if (AOP_TYPE(left) == AOP_CRY &&
1946 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1949 gencjne(left,right,newiTempLabel(NULL));
1950 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1954 genIfxJump(ifx,"a");
1957 /* if the result is used in an arithmetic operation
1958 then put the result in place */
1959 if (AOP_TYPE(result) != AOP_CRY) {
1962 /* leave the result in acc */
1966 freeAsmop(left,NULL,ic);
1967 freeAsmop(right,NULL,ic);
1968 freeAsmop(result,NULL,ic);
1971 /*-----------------------------------------------------------------*/
1972 /* ifxForOp - returns the icode containing the ifx for operand */
1973 /*-----------------------------------------------------------------*/
1974 static iCode *ifxForOp ( operand *op, iCode *ic )
1976 /* if true symbol then needs to be assigned */
1977 if (IS_TRUE_SYMOP(op))
1980 /* if this has register type condition and
1981 the next instruction is ifx with the same operand
1982 and live to of the operand is upto the ifx only then */
1984 ic->next->op == IFX &&
1985 IC_COND(ic->next)->key == op->key &&
1986 OP_SYMBOL(op)->liveTo <= ic->next->seq )
1992 /*-----------------------------------------------------------------*/
1993 /* genAndOp - for && operation */
1994 /*-----------------------------------------------------------------*/
1995 static void genAndOp (iCode *ic)
1997 operand *left,*right, *result;
2000 /* note here that && operations that are in an if statement are
2001 taken away by backPatchLabels only those used in arthmetic
2002 operations remain */
2003 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2004 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2005 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2007 /* if both are bit variables */
2008 if (AOP_TYPE(left) == AOP_CRY &&
2009 AOP_TYPE(right) == AOP_CRY ) {
2012 tlbl = newiTempLabel(NULL);
2014 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2016 emitcode("", LABEL_STR ":",tlbl->key+100);
2020 freeAsmop(left,NULL,ic);
2021 freeAsmop(right,NULL,ic);
2022 freeAsmop(result,NULL,ic);
2025 /*-----------------------------------------------------------------*/
2026 /* genOrOp - for || operation */
2027 /*-----------------------------------------------------------------*/
2028 static void genOrOp (iCode *ic)
2030 operand *left,*right, *result;
2033 /* note here that || operations that are in an
2034 if statement are taken away by backPatchLabels
2035 only those used in arthmetic operations remain */
2036 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2037 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2038 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2040 /* if both are bit variables */
2041 if (AOP_TYPE(left) == AOP_CRY &&
2042 AOP_TYPE(right) == AOP_CRY ) {
2045 tlbl = newiTempLabel(NULL);
2047 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2049 emitcode("", LABEL_STR,tlbl->key+100);
2053 freeAsmop(left,NULL,ic);
2054 freeAsmop(right,NULL,ic);
2055 freeAsmop(result,NULL,ic);
2058 /*-----------------------------------------------------------------*/
2059 /* isLiteralBit - test if lit == 2^n */
2060 /*-----------------------------------------------------------------*/
2061 int isLiteralBit(unsigned long lit)
2063 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2064 0x100L,0x200L,0x400L,0x800L,
2065 0x1000L,0x2000L,0x4000L,0x8000L,
2066 0x10000L,0x20000L,0x40000L,0x80000L,
2067 0x100000L,0x200000L,0x400000L,0x800000L,
2068 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2069 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2072 for(idx = 0; idx < 32; idx++)
2078 /*-----------------------------------------------------------------*/
2079 /* genAnd - code for and */
2080 /*-----------------------------------------------------------------*/
2081 static void genAnd (iCode *ic, iCode *ifx)
2083 operand *left, *right, *result;
2085 unsigned long lit = 0L;
2088 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2089 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2090 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2093 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2095 AOP_TYPE(left), AOP_TYPE(right));
2096 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2098 AOP_SIZE(left), AOP_SIZE(right));
2101 /* if left is a literal & right is not then exchange them */
2102 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2103 AOP_NEEDSACC(left)) {
2104 operand *tmp = right ;
2109 /* if result = right then exchange them */
2110 if(sameRegs(AOP(result),AOP(right))){
2111 operand *tmp = right ;
2116 /* if right is bit then exchange them */
2117 if (AOP_TYPE(right) == AOP_CRY &&
2118 AOP_TYPE(left) != AOP_CRY){
2119 operand *tmp = right ;
2123 if(AOP_TYPE(right) == AOP_LIT)
2124 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2126 size = AOP_SIZE(result);
2128 if (AOP_TYPE(left) == AOP_CRY){
2133 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2134 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2135 if((AOP_TYPE(right) == AOP_LIT) &&
2136 (AOP_TYPE(result) == AOP_CRY) &&
2137 (AOP_TYPE(left) != AOP_CRY)) {
2138 int posbit = isLiteralBit(lit);
2142 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2146 emitcode("mov","c,acc.%d",posbit&0x07);
2151 sprintf(buffer, "%d", posbit&0x07);
2152 genIfxJump(ifx, buffer);
2160 symbol *tlbl = newiTempLabel(NULL);
2161 int sizel = AOP_SIZE(left);
2164 emitcode("setb","c");
2167 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2168 MOVA( aopGet(AOP(left),offset,FALSE));
2170 if((posbit = isLiteralBit(bytelit)) != 0) {
2172 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2175 if(bytelit != 0x0FFL)
2176 emitcode("and","a,%s",
2177 aopGet(AOP(right),offset,FALSE));
2178 emitcode("jr","nz, %05d$",tlbl->key+100);
2183 // bit = left & literal
2185 emitcode("clr","c");
2186 emitcode("","%05d$:",tlbl->key+100);
2188 // if(left & literal)
2192 jmpTrueOrFalse(ifx, tlbl);
2203 /* if left is same as result */
2204 if(sameRegs(AOP(result),AOP(left))){
2205 for(;size--; offset++) {
2206 if(AOP_TYPE(right) == AOP_LIT){
2207 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2211 aopPut(AOP(result),zero,offset);
2213 MOVA(aopGet(AOP(left),offset,FALSE));
2214 emitcode("and","a,%s",
2215 aopGet(AOP(right),offset,FALSE));
2216 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2221 if (AOP_TYPE(left) == AOP_ACC) {
2225 MOVA(aopGet(AOP(right),offset,FALSE));
2226 emitcode("and","%s,a",
2227 aopGet(AOP(left),offset,FALSE));
2232 // left & result in different registers
2233 if(AOP_TYPE(result) == AOP_CRY){
2236 for(;(size--);offset++) {
2238 // result = left & right
2239 if(AOP_TYPE(right) == AOP_LIT){
2240 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2242 aopGet(AOP(left),offset,FALSE),
2245 } else if(bytelit == 0){
2246 aopPut(AOP(result),zero,offset);
2250 // faster than result <- left, anl result,right
2251 // and better if result is SFR
2252 if (AOP_TYPE(left) == AOP_ACC)
2253 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2255 MOVA(aopGet(AOP(right),offset,FALSE));
2256 emitcode("and","a,%s",
2257 aopGet(AOP(left),offset,FALSE));
2259 aopPut(AOP(result),"a",offset);
2266 freeAsmop(left,NULL,ic);
2267 freeAsmop(right,NULL,ic);
2268 freeAsmop(result,NULL,ic);
2271 /*-----------------------------------------------------------------*/
2272 /* genOr - code for or */
2273 /*-----------------------------------------------------------------*/
2274 static void genOr (iCode *ic, iCode *ifx)
2276 operand *left, *right, *result;
2278 unsigned long lit = 0L;
2280 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2281 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2282 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2285 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2287 AOP_TYPE(left), AOP_TYPE(right));
2288 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2290 AOP_SIZE(left), AOP_SIZE(right));
2293 /* if left is a literal & right is not then exchange them */
2294 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2295 AOP_NEEDSACC(left)) {
2296 operand *tmp = right ;
2301 /* if result = right then exchange them */
2302 if(sameRegs(AOP(result),AOP(right))){
2303 operand *tmp = right ;
2308 /* if right is bit then exchange them */
2309 if (AOP_TYPE(right) == AOP_CRY &&
2310 AOP_TYPE(left) != AOP_CRY){
2311 operand *tmp = right ;
2315 if(AOP_TYPE(right) == AOP_LIT)
2316 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2318 size = AOP_SIZE(result);
2320 if (AOP_TYPE(left) == AOP_CRY){
2325 if((AOP_TYPE(right) == AOP_LIT) &&
2326 (AOP_TYPE(result) == AOP_CRY) &&
2327 (AOP_TYPE(left) != AOP_CRY)){
2332 /* if left is same as result */
2333 if(sameRegs(AOP(result),AOP(left))){
2334 for(;size--; offset++) {
2335 if(AOP_TYPE(right) == AOP_LIT){
2336 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2339 emitcode("or","%s,%s",
2340 aopGet(AOP(left),offset,FALSE),
2341 aopGet(AOP(right),offset,FALSE));
2343 if (AOP_TYPE(left) == AOP_ACC)
2344 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2346 MOVA(aopGet(AOP(right),offset,FALSE));
2347 emitcode("or","a,%s",
2348 aopGet(AOP(left),offset,FALSE));
2349 aopPut(AOP(result),"a",0);
2354 // left & result in different registers
2355 if(AOP_TYPE(result) == AOP_CRY){
2357 } else for(;(size--);offset++){
2359 // result = left & right
2360 if(AOP_TYPE(right) == AOP_LIT){
2361 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2363 aopGet(AOP(left),offset,FALSE),
2368 // faster than result <- left, anl result,right
2369 // and better if result is SFR
2370 if (AOP_TYPE(left) == AOP_ACC)
2371 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2373 MOVA(aopGet(AOP(right),offset,FALSE));
2374 emitcode("or","a,%s",
2375 aopGet(AOP(left),offset,FALSE));
2376 aopPut(AOP(result),"a",0);
2378 aopPut(AOP(result),"a",offset);
2383 freeAsmop(left,NULL,ic);
2384 freeAsmop(right,NULL,ic);
2385 freeAsmop(result,NULL,ic);
2388 /*-----------------------------------------------------------------*/
2389 /* genXor - code for xclusive or */
2390 /*-----------------------------------------------------------------*/
2391 static void genXor (iCode *ic, iCode *ifx)
2393 operand *left, *right, *result;
2395 unsigned long lit = 0L;
2397 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2398 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2399 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2401 /* if left is a literal & right is not then exchange them */
2402 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2403 AOP_NEEDSACC(left)) {
2404 operand *tmp = right ;
2409 /* if result = right then exchange them */
2410 if(sameRegs(AOP(result),AOP(right))){
2411 operand *tmp = right ;
2416 /* if right is bit then exchange them */
2417 if (AOP_TYPE(right) == AOP_CRY &&
2418 AOP_TYPE(left) != AOP_CRY){
2419 operand *tmp = right ;
2423 if(AOP_TYPE(right) == AOP_LIT)
2424 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2426 size = AOP_SIZE(result);
2428 if (AOP_TYPE(left) == AOP_CRY){
2433 if((AOP_TYPE(right) == AOP_LIT) &&
2434 (AOP_TYPE(result) == AOP_CRY) &&
2435 (AOP_TYPE(left) != AOP_CRY)){
2440 /* if left is same as result */
2441 if(sameRegs(AOP(result),AOP(left))){
2442 for(;size--; offset++) {
2443 if(AOP_TYPE(right) == AOP_LIT){
2444 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2447 MOVA(aopGet(AOP(right),offset,FALSE));
2448 emitcode("xor","a,%s",
2449 aopGet(AOP(left),offset,FALSE));
2450 aopPut(AOP(result),"a",0);
2453 if (AOP_TYPE(left) == AOP_ACC)
2454 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2456 MOVA(aopGet(AOP(right),offset,FALSE));
2457 emitcode("xor","a,%s",
2458 aopGet(AOP(left),offset,FALSE));
2459 aopPut(AOP(result),"a",0);
2464 // left & result in different registers
2465 if(AOP_TYPE(result) == AOP_CRY){
2467 } else for(;(size--);offset++){
2469 // result = left & right
2470 if(AOP_TYPE(right) == AOP_LIT){
2471 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2473 aopGet(AOP(left),offset,FALSE),
2478 // faster than result <- left, anl result,right
2479 // and better if result is SFR
2480 if (AOP_TYPE(left) == AOP_ACC)
2481 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2483 MOVA(aopGet(AOP(right),offset,FALSE));
2484 emitcode("xor","a,%s",
2485 aopGet(AOP(left),offset,FALSE));
2486 aopPut(AOP(result),"a",0);
2488 aopPut(AOP(result),"a",offset);
2493 freeAsmop(left,NULL,ic);
2494 freeAsmop(right,NULL,ic);
2495 freeAsmop(result,NULL,ic);
2498 /*-----------------------------------------------------------------*/
2499 /* genInline - write the inline code out */
2500 /*-----------------------------------------------------------------*/
2501 static void genInline (iCode *ic)
2503 char buffer[MAX_INLINEASM];
2507 inLine += (!options.asmpeep);
2508 strcpy(buffer,IC_INLINE(ic));
2510 /* emit each line as a code */
2529 /* emitcode("",buffer); */
2530 inLine -= (!options.asmpeep);
2533 /*-----------------------------------------------------------------*/
2534 /* genRRC - rotate right with carry */
2535 /*-----------------------------------------------------------------*/
2536 static void genRRC (iCode *ic)
2541 /*-----------------------------------------------------------------*/
2542 /* genRLC - generate code for rotate left with carry */
2543 /*-----------------------------------------------------------------*/
2544 static void genRLC (iCode *ic)
2549 /*-----------------------------------------------------------------*/
2550 /* shiftR2Left2Result - shift right two bytes from left to result */
2551 /*-----------------------------------------------------------------*/
2552 static void shiftR2Left2Result (operand *left, int offl,
2553 operand *result, int offr,
2554 int shCount, int sign)
2556 if(sameRegs(AOP(result), AOP(left)) &&
2557 ((offl + MSB16) == offr)){
2560 movLeft2Result(left, offl, result, offr, 0);
2561 movLeft2Result(left, offl+1, result, offr+1, 0);
2568 /* if (AOP(result)->type == AOP_REG) {*/
2571 symbol *tlbl , *tlbl1;
2574 /* Left is already in result - so now do the shift */
2576 emitcode("ld","a,#%u+1", shCount);
2577 tlbl = newiTempLabel(NULL);
2578 tlbl1 = newiTempLabel(NULL);
2579 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2580 emitcode("", LABEL_STR ":",tlbl->key+100);
2583 emitcode("or", "a,a");
2586 l = aopGet(AOP(result), --offset, FALSE);
2587 emitcode("rr","%s", l);
2590 emitcode("", LABEL_STR ":",tlbl1->key+100);
2591 emitcode("dec", "a");
2592 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2597 /*-----------------------------------------------------------------*/
2598 /* shiftL2Left2Result - shift left two bytes from left to result */
2599 /*-----------------------------------------------------------------*/
2600 static void shiftL2Left2Result (operand *left, int offl,
2601 operand *result, int offr, int shCount)
2603 if(sameRegs(AOP(result), AOP(left)) &&
2604 ((offl + MSB16) == offr)){
2607 /* Copy left into result */
2608 movLeft2Result(left,offl, result, offr, 0);
2610 /* PENDING: for now just see if it'll work. */
2611 /*if (AOP(result)->type == AOP_REG) { */
2615 symbol *tlbl , *tlbl1;
2618 /* Left is already in result - so now do the shift */
2620 emitcode("ld","a,#%u+1", shCount);
2621 tlbl = newiTempLabel(NULL);
2622 tlbl1 = newiTempLabel(NULL);
2623 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2624 emitcode("", LABEL_STR ":",tlbl->key+100);
2627 emitcode("or", "a,a");
2629 l = aopGet(AOP(result),offset++,FALSE);
2630 emitcode("rl","%s", l);
2633 emitcode("", LABEL_STR ":",tlbl1->key+100);
2634 emitcode("dec", "a");
2635 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2640 /*-----------------------------------------------------------------*/
2641 /* AccRol - rotate left accumulator by known count */
2642 /*-----------------------------------------------------------------*/
2643 static void AccRol (int shCount)
2645 shCount &= 0x0007; // shCount : 0..7
2682 /*-----------------------------------------------------------------*/
2683 /* AccLsh - left shift accumulator by known count */
2684 /*-----------------------------------------------------------------*/
2685 static void AccLsh (int shCount)
2689 emitcode("add","a,a");
2692 emitcode("add","a,a");
2693 emitcode("add","a,a");
2695 /* rotate left accumulator */
2697 /* and kill the lower order bits */
2698 emitcode("and","a,#0x%02x", SLMask[shCount]);
2703 /*-----------------------------------------------------------------*/
2704 /* shiftL1Left2Result - shift left one byte from left to result */
2705 /*-----------------------------------------------------------------*/
2706 static void shiftL1Left2Result (operand *left, int offl,
2707 operand *result, int offr, int shCount)
2710 l = aopGet(AOP(left),offl,FALSE);
2712 /* shift left accumulator */
2714 aopPut(AOP(result),"a",offr);
2718 /*-----------------------------------------------------------------*/
2719 /* genlshTwo - left shift two bytes by known amount != 0 */
2720 /*-----------------------------------------------------------------*/
2721 static void genlshTwo (operand *result,operand *left, int shCount)
2723 int size = AOP_SIZE(result);
2727 /* if shCount >= 8 */
2733 movLeft2Result(left, LSB, result, MSB16, 0);
2734 aopPut(AOP(result),zero, 0);
2735 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2738 movLeft2Result(left, LSB, result, MSB16, 0);
2739 aopPut(AOP(result),zero, 0);
2742 aopPut(AOP(result),zero,LSB);
2744 /* 1 <= shCount <= 7 */
2750 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2755 /*-----------------------------------------------------------------*/
2756 /* genlshOne - left shift a one byte quantity by known count */
2757 /*-----------------------------------------------------------------*/
2758 static void genlshOne (operand *result, operand *left, int shCount)
2760 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2763 /*-----------------------------------------------------------------*/
2764 /* genLeftShiftLiteral - left shifting by known count */
2765 /*-----------------------------------------------------------------*/
2766 static void genLeftShiftLiteral (operand *left,
2771 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2774 freeAsmop(right,NULL,ic);
2776 aopOp(left,ic,FALSE);
2777 aopOp(result,ic,FALSE);
2779 size = getSize(operandType(result));
2782 emitcode("; shift left ","result %d, left %d",size,
2786 /* I suppose that the left size >= result size */
2791 else if(shCount >= (size * 8))
2793 aopPut(AOP(result),zero,size);
2797 genlshOne (result,left,shCount);
2800 genlshTwo (result,left,shCount);
2809 freeAsmop(left,NULL,ic);
2810 freeAsmop(result,NULL,ic);
2813 /*-----------------------------------------------------------------*/
2814 /* genLeftShift - generates code for left shifting */
2815 /*-----------------------------------------------------------------*/
2816 static void genLeftShift (iCode *ic)
2820 symbol *tlbl , *tlbl1;
2821 operand *left,*right, *result;
2823 right = IC_RIGHT(ic);
2825 result = IC_RESULT(ic);
2827 aopOp(right,ic,FALSE);
2829 /* if the shift count is known then do it
2830 as efficiently as possible */
2831 if (AOP_TYPE(right) == AOP_LIT) {
2832 genLeftShiftLiteral (left,right,result,ic);
2836 /* shift count is unknown then we have to form a loop get the loop
2837 count in B : Note: we take only the lower order byte since
2838 shifting more that 32 bits make no sense anyway, ( the largest
2839 size of an object can be only 32 bits ) */
2840 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2841 emitcode("inc","a");
2842 freeAsmop (right,NULL,ic);
2843 aopOp(left,ic,FALSE);
2844 aopOp(result,ic,FALSE);
2846 /* now move the left to the result if they are not the
2849 if (!sameRegs(AOP(left),AOP(result))) {
2851 size = AOP_SIZE(result);
2854 l = aopGet(AOP(left),offset,FALSE);
2855 aopPut(AOP(result),l,offset);
2860 size = AOP_SIZE(result);
2863 l = aopGet(AOP(left),offset,FALSE);
2864 aopPut(AOP(result),l,offset);
2870 tlbl = newiTempLabel(NULL);
2871 size = AOP_SIZE(result);
2873 tlbl1 = newiTempLabel(NULL);
2875 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2876 emitcode("", LABEL_STR ":",tlbl->key+100);
2877 l = aopGet(AOP(result),offset,FALSE);
2878 emitcode("or", "a,a");
2880 l = aopGet(AOP(result),offset++,FALSE);
2881 emitcode("rl","%s", l);
2883 emitcode("", LABEL_STR ":",tlbl1->key+100);
2884 emitcode("dec", "a");
2885 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2887 freeAsmop(left,NULL,ic);
2888 freeAsmop(result,NULL,ic);
2891 /* genlshTwo - left shift two bytes by known amount != 0 */
2892 /*-----------------------------------------------------------------*/
2893 static void genrshOne (operand *result,operand *left, int shCount)
2896 int size = AOP_SIZE(result);
2902 l = aopGet(AOP(left),0,FALSE);
2903 if (AOP(result)->type == AOP_REG) {
2904 aopPut(AOP(result), l, 0);
2905 l = aopGet(AOP(result), 0, FALSE);
2907 emitcode("srl", "%s", l);
2912 emitcode("srl", "a");
2914 aopPut(AOP(result),"a",0);
2918 /*-----------------------------------------------------------------*/
2919 /* AccRsh - right shift accumulator by known count */
2920 /*-----------------------------------------------------------------*/
2921 static void AccRsh (int shCount)
2928 /* rotate right accumulator */
2929 AccRol(8 - shCount);
2930 /* and kill the higher order bits */
2931 emitcode("and","a,#0x%02x", SRMask[shCount]);
2936 /*-----------------------------------------------------------------*/
2937 /* shiftR1Left2Result - shift right one byte from left to result */
2938 /*-----------------------------------------------------------------*/
2939 static void shiftR1Left2Result (operand *left, int offl,
2940 operand *result, int offr,
2941 int shCount, int sign)
2943 MOVA(aopGet(AOP(left),offl,FALSE));
2950 aopPut(AOP(result),"a",offr);
2953 /*-----------------------------------------------------------------*/
2954 /* genrshTwo - right shift two bytes by known amount != 0 */
2955 /*-----------------------------------------------------------------*/
2956 static void genrshTwo (operand *result,operand *left,
2957 int shCount, int sign)
2959 /* if shCount >= 8 */
2964 shiftR1Left2Result(left, MSB16, result, LSB,
2968 movLeft2Result(left, MSB16, result, LSB, sign);
2969 aopPut(AOP(result),zero,1);
2972 /* 1 <= shCount <= 7 */
2974 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
2978 /*-----------------------------------------------------------------*/
2979 /* genRightShiftLiteral - left shifting by known count */
2980 /*-----------------------------------------------------------------*/
2981 static void genRightShiftLiteral (operand *left,
2986 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2989 freeAsmop(right,NULL,ic);
2991 aopOp(left,ic,FALSE);
2992 aopOp(result,ic,FALSE);
2994 size = getSize(operandType(result));
2996 emitcode("; shift right ","result %d, left %d",size,
2999 /* I suppose that the left size >= result size */
3004 else if(shCount >= (size * 8))
3006 aopPut(AOP(result),zero,size);
3010 genrshOne(result, left, shCount);
3013 /* PENDING: sign support */
3014 genrshTwo(result, left, shCount, FALSE);
3023 freeAsmop(left,NULL,ic);
3024 freeAsmop(result,NULL,ic);
3027 /*-----------------------------------------------------------------*/
3028 /* genRightShift - generate code for right shifting */
3029 /*-----------------------------------------------------------------*/
3030 static void genRightShift (iCode *ic)
3032 operand *left,*right, *result;
3034 right = IC_RIGHT(ic);
3036 result = IC_RESULT(ic);
3038 aopOp(right,ic,FALSE);
3040 /* if the shift count is known then do it
3041 as efficiently as possible */
3042 if (AOP_TYPE(right) == AOP_LIT) {
3043 genRightShiftLiteral (left,right,result,ic);
3051 /*-----------------------------------------------------------------*/
3052 /* genGenPointerGet - gget value from generic pointer space */
3053 /*-----------------------------------------------------------------*/
3054 static void genGenPointerGet (operand *left,
3055 operand *result, iCode *ic)
3058 link *retype = getSpec(operandType(result));
3060 aopOp(left,ic,FALSE);
3061 aopOp(result,ic,FALSE);
3063 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3065 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3066 aopPut(AOP(result),"a", 0);
3067 freeAsmop(left,NULL,ic);
3071 /* For now we always load into IY */
3072 /* if this is remateriazable */
3073 if (AOP_TYPE(left) == AOP_IMMD)
3074 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3075 else { /* we need to get it byte by byte */
3076 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3077 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3079 /* so iy now contains the address */
3080 freeAsmop(left,NULL,ic);
3082 /* if bit then unpack */
3083 if (IS_BITVAR(retype)) {
3087 size = AOP_SIZE(result);
3091 /* PENDING: make this better */
3092 if (AOP(result)->type == AOP_REG) {
3093 aopPut(AOP(result),"(hl)",offset++);
3096 emitcode("ld", "a,(hl)", offset);
3097 aopPut(AOP(result),"a",offset++);
3100 emitcode("inc", "hl");
3106 freeAsmop(result,NULL,ic);
3109 /*-----------------------------------------------------------------*/
3110 /* genPointerGet - generate code for pointer get */
3111 /*-----------------------------------------------------------------*/
3112 static void genPointerGet (iCode *ic)
3114 operand *left, *result ;
3118 result = IC_RESULT(ic) ;
3120 /* depending on the type of pointer we need to
3121 move it to the correct pointer register */
3122 type = operandType(left);
3123 etype = getSpec(type);
3125 genGenPointerGet (left,result,ic);
3128 bool isRegOrLit(asmop *aop)
3130 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3135 /*-----------------------------------------------------------------*/
3136 /* genGenPointerSet - stores the value into a pointer location */
3137 /*-----------------------------------------------------------------*/
3138 static void genGenPointerSet (operand *right,
3139 operand *result, iCode *ic)
3142 link *retype = getSpec(operandType(right));
3144 aopOp(result,ic,FALSE);
3145 aopOp(right,ic,FALSE);
3147 /* Handle the exceptions first */
3148 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3150 char *l = aopGet(AOP(right), 0, FALSE);
3152 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3153 freeAsmop(result,NULL,ic);
3157 /* if the operand is already in dptr
3158 then we do nothing else we move the value to dptr */
3159 if (AOP_TYPE(result) != AOP_STR) {
3160 /* if this is remateriazable */
3161 if (AOP_TYPE(result) == AOP_IMMD) {
3162 emitcode("", "; Error 2");
3163 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3165 else { /* we need to get it byte by byte */
3166 /* PENDING: do this better */
3167 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3168 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3171 /* so hl know contains the address */
3172 freeAsmop(result,NULL,ic);
3174 /* if bit then unpack */
3175 if (IS_BITVAR(retype)) {
3179 size = AOP_SIZE(right);
3183 char *l = aopGet(AOP(right),offset,FALSE);
3185 if (isRegOrLit(AOP(right))) {
3186 emitcode("ld", "(hl),%s", l);
3190 emitcode("ld", "(hl),a", offset);
3193 emitcode("inc", "hl");
3199 freeAsmop(right,NULL,ic);
3202 /*-----------------------------------------------------------------*/
3203 /* genPointerSet - stores the value into a pointer location */
3204 /*-----------------------------------------------------------------*/
3205 static void genPointerSet (iCode *ic)
3207 operand *right, *result ;
3210 right = IC_RIGHT(ic);
3211 result = IC_RESULT(ic) ;
3213 /* depending on the type of pointer we need to
3214 move it to the correct pointer register */
3215 type = operandType(result);
3216 etype = getSpec(type);
3218 genGenPointerSet (right,result,ic);
3221 /*-----------------------------------------------------------------*/
3222 /* genIfx - generate code for Ifx statement */
3223 /*-----------------------------------------------------------------*/
3224 static void genIfx (iCode *ic, iCode *popIc)
3226 operand *cond = IC_COND(ic);
3229 aopOp(cond,ic,FALSE);
3231 /* get the value into acc */
3232 if (AOP_TYPE(cond) != AOP_CRY)
3236 /* the result is now in the accumulator */
3237 freeAsmop(cond,NULL,ic);
3239 /* if there was something to be popped then do it */
3243 /* if the condition is a bit variable */
3244 if (isbit && IS_ITEMP(cond) &&
3246 genIfxJump(ic,SPIL_LOC(cond)->rname);
3248 if (isbit && !IS_ITEMP(cond))
3249 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3256 /*-----------------------------------------------------------------*/
3257 /* genAddrOf - generates code for address of */
3258 /*-----------------------------------------------------------------*/
3259 static void genAddrOf (iCode *ic)
3261 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3263 aopOp(IC_RESULT(ic),ic,FALSE);
3265 /* if the operand is on the stack then we
3266 need to get the stack offset of this
3269 /* if it has an offset then we need to compute it */
3270 emitcode("push", "de");
3271 emitcode("push", "ix");
3272 emitcode("pop", "hl");
3273 emitcode("ld", "de,#%d", sym->stack);
3274 emitcode("add", "hl,de");
3275 emitcode("pop", "de");
3278 emitcode("ld", "hl,#%s", sym->rname);
3280 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3281 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3283 freeAsmop(IC_RESULT(ic),NULL,ic);
3286 /*-----------------------------------------------------------------*/
3287 /* genAssign - generate code for assignment */
3288 /*-----------------------------------------------------------------*/
3289 static void genAssign (iCode *ic)
3291 operand *result, *right;
3293 unsigned long lit = 0L;
3295 result = IC_RESULT(ic);
3296 right = IC_RIGHT(ic) ;
3299 /* Dont bother assigning if they are the same */
3300 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3301 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3306 aopOp(right,ic,FALSE);
3307 aopOp(result,ic,TRUE);
3309 /* if they are the same registers */
3310 if (sameRegs(AOP(right),AOP(result))) {
3311 emitcode("", "; (registers are the same)");
3315 /* if the result is a bit */
3316 if (AOP_TYPE(result) == AOP_CRY) {
3321 size = AOP_SIZE(result);
3324 if(AOP_TYPE(right) == AOP_LIT)
3325 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3327 (AOP_TYPE(result) != AOP_REG) &&
3328 (AOP_TYPE(right) == AOP_LIT) &&
3329 !IS_FLOAT(operandType(right)) &&
3331 emitcode("xor","a,a");
3332 /* Work from the top down.
3333 Done this way so that we can use the cached copy of 0
3334 in A for a fast clear */
3336 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3337 aopPut(AOP(result),"a",size);
3340 aopGet(AOP(right),size,FALSE),
3346 aopGet(AOP(right),offset,FALSE),
3353 freeAsmop(right,NULL,ic);
3354 freeAsmop(result,NULL,ic);
3357 /*-----------------------------------------------------------------*/
3358 /* genJumpTab - genrates code for jump table */
3359 /*-----------------------------------------------------------------*/
3360 static void genJumpTab (iCode *ic)
3365 aopOp(IC_JTCOND(ic),ic,FALSE);
3366 /* get the condition into accumulator */
3367 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3369 emitcode("push", "de");
3370 emitcode("ld", "e,%s", l);
3371 emitcode("ld", "d,#0");
3372 jtab = newiTempLabel(NULL);
3373 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3374 emitcode("add", "hl,de");
3375 emitcode("add", "hl,de");
3376 freeAsmop(IC_JTCOND(ic),NULL,ic);
3377 emitcode("pop", "de");
3378 emitcode("jp", "(hl)");
3379 emitcode("","%05d$:",jtab->key+100);
3380 /* now generate the jump labels */
3381 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3382 jtab = setNextItem(IC_JTLABELS(ic)))
3383 emitcode("jp", LABEL_STR, jtab->key+100);
3386 /*-----------------------------------------------------------------*/
3387 /* genCast - gen code for casting */
3388 /*-----------------------------------------------------------------*/
3389 static void genCast (iCode *ic)
3391 operand *result = IC_RESULT(ic);
3392 link *ctype = operandType(IC_LEFT(ic));
3393 operand *right = IC_RIGHT(ic);
3396 /* if they are equivalent then do nothing */
3397 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3400 aopOp(right,ic,FALSE) ;
3401 aopOp(result,ic,FALSE);
3403 /* if the result is a bit */
3404 if (AOP_TYPE(result) == AOP_CRY) {
3408 /* if they are the same size : or less */
3409 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3411 /* if they are in the same place */
3412 if (sameRegs(AOP(right),AOP(result)))
3415 /* if they in different places then copy */
3416 size = AOP_SIZE(result);
3420 aopGet(AOP(right),offset,FALSE),
3427 /* if the result is of type pointer */
3428 if (IS_PTR(ctype)) {
3432 /* so we now know that the size of destination is greater
3433 than the size of the source */
3434 /* we move to result for the size of source */
3435 size = AOP_SIZE(right);
3439 aopGet(AOP(right),offset,FALSE),
3444 /* now depending on the sign of the destination */
3445 size = AOP_SIZE(result) - AOP_SIZE(right);
3446 /* Unsigned or not an integral type - right fill with zeros */
3447 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3449 aopPut(AOP(result),zero,offset++);
3451 /* we need to extend the sign :{ */
3452 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3455 emitcode("", "; genCast: sign extend untested.");
3456 emitcode("rla", "");
3457 emitcode("sbc", "a,a");
3459 aopPut(AOP(result),"a",offset++);
3463 freeAsmop(right, NULL, ic);
3464 freeAsmop(result, NULL, ic);
3467 /*-----------------------------------------------------------------*/
3468 /* genReceive - generate code for a receive iCode */
3469 /*-----------------------------------------------------------------*/
3470 static void genReceive (iCode *ic)
3472 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3473 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3474 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3478 aopOp(IC_RESULT(ic),ic,FALSE);
3480 assignResultValue(IC_RESULT(ic));
3483 freeAsmop(IC_RESULT(ic),NULL,ic);
3486 /*-----------------------------------------------------------------*/
3487 /* genZ80Code - generate code for Z80 based controllers */
3488 /*-----------------------------------------------------------------*/
3489 void genZ80Code (iCode *lic)
3494 lineHead = lineCurr = NULL;
3496 /* if debug information required */
3497 if (options.debug && currFunc) {
3498 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3500 if (IS_STATIC(currFunc->etype))
3501 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3503 emitcode("","G$%s$0$0 ==.",currFunc->name);
3506 /* stack pointer name */
3510 for (ic = lic ; ic ; ic = ic->next ) {
3512 if ( cln != ic->lineno ) {
3513 if ( options.debug ) {
3515 emitcode("","C$%s$%d$%d$%d ==.",
3516 ic->filename,ic->lineno,
3517 ic->level,ic->block);
3520 emitcode(";","%s %d",ic->filename,ic->lineno);
3523 /* if the result is marked as
3524 spilt and rematerializable or code for
3525 this has already been generated then
3527 if (resultRemat(ic) || ic->generated )
3530 /* depending on the operation */
3533 emitcode("", "; genNot");
3538 emitcode("", "; genCpl");
3543 emitcode("", "; genUminus");
3548 emitcode("", "; genIpush");
3553 /* IPOP happens only when trying to restore a
3554 spilt live range, if there is an ifx statement
3555 following this pop then the if statement might
3556 be using some of the registers being popped which
3557 would destory the contents of the register so
3558 we need to check for this condition and handle it */
3560 ic->next->op == IFX &&
3561 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3562 emitcode("", "; genIfx");
3563 genIfx (ic->next,ic);
3566 emitcode("", "; genIpop");
3572 emitcode("", "; genCall");
3577 emitcode("", "; genPcall");
3582 emitcode("", "; genFunction");
3587 emitcode("", "; genEndFunction");
3588 genEndFunction (ic);
3592 emitcode("", "; genRet");
3597 emitcode("", "; genLabel");
3602 emitcode("", "; genGoto");
3607 emitcode("", "; genPlus");
3612 emitcode("", "; genMinus");
3617 emitcode("", "; genMult");
3622 emitcode("", "; genDiv");
3627 emitcode("", "; genMod");
3632 emitcode("", "; genCmpGt");
3633 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3637 emitcode("", "; genCmpLt");
3638 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3645 /* note these two are xlated by algebraic equivalence
3646 during parsing SDCC.y */
3647 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3648 "got '>=' or '<=' shouldn't have come here");
3652 emitcode("", "; genCmpEq");
3653 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3657 emitcode("", "; genAndOp");
3662 emitcode("", "; genOrOp");
3667 emitcode("", "; genXor");
3668 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3672 emitcode("", "; genOr");
3673 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3677 emitcode("", "; genAnd");
3678 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3682 emitcode("", "; genInline");
3687 emitcode("", "; genRRC");
3692 emitcode("", "; genRLC");
3697 emitcode("", "; genHBIT");
3701 emitcode("", "; genLeftShift");
3706 emitcode("", "; genRightShift");
3710 case GET_VALUE_AT_ADDRESS:
3711 emitcode("", "; genPointerGet");
3717 if (POINTER_SET(ic)) {
3718 emitcode("", "; genAssign (pointer)");
3722 emitcode("", "; genAssign");
3728 emitcode("", "; genIfx");
3733 emitcode("", "; genAddrOf");
3738 emitcode("", "; genJumpTab");
3743 emitcode("", "; genCast");
3748 emitcode("", "; genReceive");
3753 emitcode("", "; addSet");
3754 addSet(&sendSet,ic);
3759 /* piCode(ic,stdout); */
3765 /* now we are ready to call the
3766 peep hole optimizer */
3767 /* if (!options.nopeep)
3768 peepHole (&lineHead); */
3770 /* now do the actual printing */
3771 printLine (lineHead,codeOutFile);