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;
1100 /* PENDING: do better */
1102 emitcode("pop", "hl");
1106 emitcode("inc", "sp");
1111 /*-----------------------------------------------------------------*/
1112 /* genCall - generates a call statement */
1113 /*-----------------------------------------------------------------*/
1114 static void genCall (iCode *ic)
1116 emitCall(ic, FALSE);
1119 /*-----------------------------------------------------------------*/
1120 /* genPcall - generates a call by pointer statement */
1121 /*-----------------------------------------------------------------*/
1122 static void genPcall (iCode *ic)
1127 /*-----------------------------------------------------------------*/
1128 /* resultRemat - result is rematerializable */
1129 /*-----------------------------------------------------------------*/
1130 static int resultRemat (iCode *ic)
1132 if (SKIP_IC(ic) || ic->op == IFX)
1135 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1136 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1137 if (sym->remat && !POINTER_SET(ic))
1144 /*-----------------------------------------------------------------*/
1145 /* genFunction - generated code for function entry */
1146 /*-----------------------------------------------------------------*/
1147 static void genFunction (iCode *ic)
1153 /* create the function header */
1154 emitcode(";","-----------------------------------------");
1155 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1156 emitcode(";","-----------------------------------------");
1158 emitcode("","%s:",sym->rname);
1159 fetype = getSpec(operandType(IC_LEFT(ic)));
1161 /* if critical function then turn interrupts off */
1162 if (SPEC_CRTCL(fetype))
1165 /* if this is an interrupt service routine then
1166 save acc, b, dpl, dph */
1167 if (IS_ISR(sym->etype)) {
1168 emitcode("push", "af");
1169 emitcode("push", "bc");
1170 emitcode("push", "de");
1171 emitcode("push", "hl");
1173 /* PENDING: callee-save etc */
1175 /* adjust the stack for the function */
1176 emitcode("push", "de");
1177 emitcode("push", "bc");
1178 emitcode("push", "ix");
1179 emitcode("ld", "ix,#0");
1180 emitcode("add", "ix,sp");
1182 _lastStack = sym->stack;
1185 emitcode("ld", "hl,#-%d", sym->stack);
1186 emitcode("add", "hl,sp");
1187 emitcode("ld", "sp,hl");
1191 /*-----------------------------------------------------------------*/
1192 /* genEndFunction - generates epilogue for functions */
1193 /*-----------------------------------------------------------------*/
1194 static void genEndFunction (iCode *ic)
1196 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1198 if (IS_ISR(sym->etype)) {
1202 if (SPEC_CRTCL(sym->etype))
1205 /* PENDING: calleeSave */
1207 /* if debug then send end of function */
1208 if (options.debug && currFunc) {
1210 emitcode("","C$%s$%d$%d$%d ==.",
1211 ic->filename,currFunc->lastLine,
1212 ic->level,ic->block);
1213 if (IS_STATIC(currFunc->etype))
1214 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1216 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1219 emitcode("ld", "sp,ix");
1220 emitcode("pop", "ix");
1221 emitcode("pop", "bc");
1222 emitcode("pop", "de");
1223 emitcode("ret", "");
1228 /*-----------------------------------------------------------------*/
1229 /* genRet - generate code for return statement */
1230 /*-----------------------------------------------------------------*/
1231 static void genRet (iCode *ic)
1234 /* Errk. This is a hack until I can figure out how
1235 to cause dehl to spill on a call */
1236 int size,offset = 0;
1238 /* if we have no return value then
1239 just generate the "ret" */
1243 /* we have something to return then
1244 move the return value into place */
1245 aopOp(IC_LEFT(ic),ic,FALSE);
1246 size = AOP_SIZE(IC_LEFT(ic));
1248 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1249 emitcode("ld", "hl,%s", l);
1253 l = aopGet(AOP(IC_LEFT(ic)),offset,
1255 if (strcmp(fReturn[offset],l))
1256 emitcode("ld","%s,%s",fReturn[offset++],l);
1259 freeAsmop (IC_LEFT(ic),NULL,ic);
1262 /* generate a jump to the return label
1263 if the next is not the return statement */
1264 if (!(ic->next && ic->next->op == LABEL &&
1265 IC_LABEL(ic->next) == returnLabel))
1267 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1270 /*-----------------------------------------------------------------*/
1271 /* genLabel - generates a label */
1272 /*-----------------------------------------------------------------*/
1273 static void genLabel (iCode *ic)
1275 /* special case never generate */
1276 if (IC_LABEL(ic) == entryLabel)
1279 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1282 /*-----------------------------------------------------------------*/
1283 /* genGoto - generates a ljmp */
1284 /*-----------------------------------------------------------------*/
1285 static void genGoto (iCode *ic)
1287 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1290 /*-----------------------------------------------------------------*/
1291 /* genPlusIncr :- does addition with increment if possible */
1292 /*-----------------------------------------------------------------*/
1293 static bool genPlusIncr (iCode *ic)
1295 unsigned int icount ;
1296 unsigned int size = getDataSize(IC_RESULT(ic));
1298 /* will try to generate an increment */
1299 /* if the right side is not a literal
1301 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1304 /* if the literal value of the right hand side
1305 is greater than 4 then it is not worth it */
1306 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1310 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1311 isPair(AOP(IC_RESULT(ic)))) {
1313 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1317 /* if increment 16 bits in register */
1318 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1321 symbol *tlbl = newiTempLabel(NULL);
1322 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1323 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1325 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1329 emitcode("", LABEL_STR ":",tlbl->key+100);
1333 /* If result is a pair */
1334 if (isPair(AOP(IC_RESULT(ic)))) {
1335 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1336 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1338 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1342 /* if the sizes are greater than 1 then we cannot */
1343 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1344 AOP_SIZE(IC_LEFT(ic)) > 1 )
1347 /* we can if the aops of the left & result match or
1348 if they are in registers and the registers are the
1350 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1352 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1360 /*-----------------------------------------------------------------*/
1361 /* outBitAcc - output a bit in acc */
1362 /*-----------------------------------------------------------------*/
1363 void outBitAcc(operand *result)
1365 symbol *tlbl = newiTempLabel(NULL);
1366 /* if the result is a bit */
1367 if (AOP_TYPE(result) == AOP_CRY){
1371 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1372 emitcode("ld","a,%s",one);
1373 emitcode("", LABEL_STR ":",tlbl->key+100);
1378 /*-----------------------------------------------------------------*/
1379 /* genPlus - generates code for addition */
1380 /*-----------------------------------------------------------------*/
1381 static void genPlus (iCode *ic)
1383 int size, offset = 0;
1385 /* special cases :- */
1387 aopOp (IC_LEFT(ic),ic,FALSE);
1388 aopOp (IC_RIGHT(ic),ic,FALSE);
1389 aopOp (IC_RESULT(ic),ic,TRUE);
1391 /* Swap the left and right operands if:
1393 if literal, literal on the right or
1394 if left requires ACC or right is already
1397 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1398 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1399 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1400 operand *t = IC_RIGHT(ic);
1401 IC_RIGHT(ic) = IC_LEFT(ic);
1405 /* if both left & right are in bit
1407 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1408 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1413 /* if left in bit space & right literal */
1414 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1415 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1416 /* Can happen I guess */
1420 /* if I can do an increment instead
1421 of add then GOOD for ME */
1422 if (genPlusIncr (ic) == TRUE)
1425 size = getDataSize(IC_RESULT(ic));
1428 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1429 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1431 emitcode("add","a,%s",
1432 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1434 emitcode("adc","a,%s",
1435 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1437 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1439 emitcode("add","a,%s",
1440 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1442 emitcode("adc","a,%s",
1443 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1445 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1448 /* Some kind of pointer arith. */
1449 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1450 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1451 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1454 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1455 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1456 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1461 freeAsmop(IC_LEFT(ic),NULL,ic);
1462 freeAsmop(IC_RIGHT(ic),NULL,ic);
1463 freeAsmop(IC_RESULT(ic),NULL,ic);
1467 /*-----------------------------------------------------------------*/
1468 /* genMinusDec :- does subtraction with deccrement if possible */
1469 /*-----------------------------------------------------------------*/
1470 static bool genMinusDec (iCode *ic)
1472 unsigned int icount ;
1473 unsigned int size = getDataSize(IC_RESULT(ic));
1475 /* will try to generate an increment */
1476 /* if the right side is not a literal we cannot */
1477 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1480 /* if the literal value of the right hand side
1481 is greater than 4 then it is not worth it */
1482 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1485 size = getDataSize(IC_RESULT(ic));
1486 /* if decrement 16 bits in register */
1487 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1488 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1490 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1494 /* If result is a pair */
1495 if (isPair(AOP(IC_RESULT(ic)))) {
1496 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1497 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1499 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1503 /* if the sizes are greater than 1 then we cannot */
1504 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1505 AOP_SIZE(IC_LEFT(ic)) > 1 )
1508 /* we can if the aops of the left & result match or if they are in
1509 registers and the registers are the same */
1510 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1512 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1519 /*-----------------------------------------------------------------*/
1520 /* genMinus - generates code for subtraction */
1521 /*-----------------------------------------------------------------*/
1522 static void genMinus (iCode *ic)
1524 int size, offset = 0;
1525 unsigned long lit = 0L;
1527 aopOp (IC_LEFT(ic),ic,FALSE);
1528 aopOp (IC_RIGHT(ic),ic,FALSE);
1529 aopOp (IC_RESULT(ic),ic,TRUE);
1531 /* special cases :- */
1532 /* if both left & right are in bit space */
1533 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1534 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1539 /* if I can do an decrement instead of subtract then GOOD for ME */
1540 if (genMinusDec (ic) == TRUE)
1543 size = getDataSize(IC_RESULT(ic));
1545 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1549 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1554 /* if literal, add a,#-lit, else normal subb */
1556 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1557 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1558 emitcode("sbc","a,%s",
1559 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1561 /* first add without previous c */
1563 emitcode("add","a,#0x%02x",
1564 (unsigned int)(lit & 0x0FFL));
1566 emitcode("adc","a,#0x%02x",
1567 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1569 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1572 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1573 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1574 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1578 freeAsmop(IC_LEFT(ic),NULL,ic);
1579 freeAsmop(IC_RIGHT(ic),NULL,ic);
1580 freeAsmop(IC_RESULT(ic),NULL,ic);
1583 /*-----------------------------------------------------------------*/
1584 /* genMult - generates code for multiplication */
1585 /*-----------------------------------------------------------------*/
1586 static void genMult (iCode *ic)
1588 /* Shouldn't occur - all done through function calls */
1592 /*-----------------------------------------------------------------*/
1593 /* genDiv - generates code for division */
1594 /*-----------------------------------------------------------------*/
1595 static void genDiv (iCode *ic)
1597 /* Shouldn't occur - all done through function calls */
1601 /*-----------------------------------------------------------------*/
1602 /* genMod - generates code for division */
1603 /*-----------------------------------------------------------------*/
1604 static void genMod (iCode *ic)
1606 /* Shouldn't occur - all done through function calls */
1610 /*-----------------------------------------------------------------*/
1611 /* genIfxJump :- will create a jump depending on the ifx */
1612 /*-----------------------------------------------------------------*/
1613 static void genIfxJump (iCode *ic, char *jval)
1618 /* if true label then we jump if condition
1620 if ( IC_TRUE(ic) ) {
1622 if (!strcmp(jval, "a")) {
1625 else if (!strcmp(jval, "c")) {
1629 /* The buffer contains the bit on A that we should test */
1634 /* false label is present */
1635 jlbl = IC_FALSE(ic) ;
1636 if (!strcmp(jval, "a")) {
1639 else if (!strcmp(jval, "c")) {
1643 /* The buffer contains the bit on A that we should test */
1647 /* Z80 can do a conditional long jump */
1648 if (!strcmp(jval, "a")) {
1649 emitcode("or", "a,a");
1651 else if (!strcmp(jval, "c")) {
1654 emitcode("bit", "%s,a", jval);
1656 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1658 /* mark the icode as generated */
1662 /** Generic compare for > or <
1664 static void genCmp (operand *left,operand *right,
1665 operand *result, iCode *ifx, int sign)
1667 int size, offset = 0 ;
1668 unsigned long lit = 0L;
1670 /* if left & right are bit variables */
1671 if (AOP_TYPE(left) == AOP_CRY &&
1672 AOP_TYPE(right) == AOP_CRY ) {
1673 /* Cant happen on the Z80 */
1676 /* subtract right from left if at the
1677 end the carry flag is set then we know that
1678 left is greater than right */
1679 size = max(AOP_SIZE(left),AOP_SIZE(right));
1681 /* if unsigned char cmp with lit, just compare */
1682 if((size == 1) && !sign &&
1683 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1684 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1685 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1688 if(AOP_TYPE(right) == AOP_LIT) {
1689 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1690 /* optimize if(x < 0) or if(x >= 0) */
1693 /* No sign so it's always false */
1697 /* Just load in the top most bit */
1698 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1699 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1700 genIfxJump (ifx,"7");
1704 emitcode("rlc","a");
1710 /* Do a long subtract */
1711 MOVA(aopGet(AOP(left),offset,FALSE));
1712 if (sign && size == 0) {
1713 /* Case where it's signed and we've hit the end */
1714 /* PENDING: This is almost certanitly wrong.
1715 On the 8051 xrl doesnt change C, but xor does.
1717 emitcode("xor","a,#0x80");
1718 if (AOP_TYPE(right) == AOP_LIT){
1719 unsigned long lit = (unsigned long)
1720 floatFromVal(AOP(right)->aopu.aop_lit);
1721 emitcode("sbc","a,#0x%02x",
1722 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1724 /* The bad way... */
1725 emitcode("push", "af");
1726 emitcode("ld","a,%s",aopGet(AOP(right),offset++,FALSE));
1727 emitcode("xor", "a,#0x80");
1728 emitcode("ld", "l,a");
1729 emitcode("pop", "af");
1730 emitcode("sbc","a,l");
1733 /* Subtract through, propagating the carry */
1735 emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1738 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1745 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1748 /* if the result is used in the next
1749 ifx conditional branch then generate
1750 code a little differently */
1752 genIfxJump (ifx,"c");
1755 /* leave the result in acc */
1759 /*-----------------------------------------------------------------*/
1760 /* genCmpGt :- greater than comparison */
1761 /*-----------------------------------------------------------------*/
1762 static void genCmpGt (iCode *ic, iCode *ifx)
1764 operand *left, *right, *result;
1765 link *letype , *retype;
1769 right= IC_RIGHT(ic);
1770 result = IC_RESULT(ic);
1772 letype = getSpec(operandType(left));
1773 retype =getSpec(operandType(right));
1774 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1775 /* assign the amsops */
1776 aopOp (left,ic,FALSE);
1777 aopOp (right,ic,FALSE);
1778 aopOp (result,ic,TRUE);
1780 genCmp(right, left, result, ifx, sign);
1782 freeAsmop(left,NULL,ic);
1783 freeAsmop(right,NULL,ic);
1784 freeAsmop(result,NULL,ic);
1787 /*-----------------------------------------------------------------*/
1788 /* genCmpLt - less than comparisons */
1789 /*-----------------------------------------------------------------*/
1790 static void genCmpLt (iCode *ic, iCode *ifx)
1792 operand *left, *right, *result;
1793 link *letype , *retype;
1797 right= IC_RIGHT(ic);
1798 result = IC_RESULT(ic);
1800 letype = getSpec(operandType(left));
1801 retype =getSpec(operandType(right));
1802 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1804 /* assign the amsops */
1805 aopOp (left,ic,FALSE);
1806 aopOp (right,ic,FALSE);
1807 aopOp (result,ic,TRUE);
1809 genCmp(left, right, result, ifx, sign);
1811 freeAsmop(left,NULL,ic);
1812 freeAsmop(right,NULL,ic);
1813 freeAsmop(result,NULL,ic);
1816 /*-----------------------------------------------------------------*/
1817 /* gencjneshort - compare and jump if not equal */
1818 /*-----------------------------------------------------------------*/
1819 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1821 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1823 unsigned long lit = 0L;
1825 /* Swap the left and right if it makes the computation easier */
1826 if (AOP_TYPE(left) == AOP_LIT) {
1832 if(AOP_TYPE(right) == AOP_LIT)
1833 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1835 /* if the right side is a literal then anything goes */
1836 if (AOP_TYPE(right) == AOP_LIT &&
1837 AOP_TYPE(left) != AOP_DIR ) {
1839 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1840 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1841 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1845 /* if the right side is in a register or in direct space or
1846 if the left is a pointer register & right is not */
1847 else if (AOP_TYPE(right) == AOP_REG ||
1848 AOP_TYPE(right) == AOP_DIR ||
1849 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1851 MOVA(aopGet(AOP(left),offset,FALSE));
1852 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1853 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1855 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1857 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1858 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1863 /* right is a pointer reg need both a & b */
1864 /* PENDING: is this required? */
1866 char *l = aopGet(AOP(left),offset,FALSE);
1867 MOVA(aopGet(AOP(right),offset,FALSE));
1868 emitcode("cp", "%s", l);
1869 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
1875 /*-----------------------------------------------------------------*/
1876 /* gencjne - compare and jump if not equal */
1877 /*-----------------------------------------------------------------*/
1878 static void gencjne(operand *left, operand *right, symbol *lbl)
1880 symbol *tlbl = newiTempLabel(NULL);
1882 gencjneshort(left, right, lbl);
1885 emitcode("ld","a,%s",one);
1886 emitcode("jp", LABEL_STR ,tlbl->key+100);
1887 emitcode("", LABEL_STR ":",lbl->key+100);
1888 emitcode("xor","a,a");
1889 emitcode("", LABEL_STR ":",tlbl->key+100);
1892 /*-----------------------------------------------------------------*/
1893 /* genCmpEq - generates code for equal to */
1894 /*-----------------------------------------------------------------*/
1895 static void genCmpEq (iCode *ic, iCode *ifx)
1897 operand *left, *right, *result;
1899 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1900 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1901 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1903 /* Swap operands if it makes the operation easier. ie if:
1904 1. Left is a literal.
1906 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1907 operand *t = IC_RIGHT(ic);
1908 IC_RIGHT(ic) = IC_LEFT(ic);
1912 if (ifx && !AOP_SIZE(result)){
1914 /* if they are both bit variables */
1915 if (AOP_TYPE(left) == AOP_CRY &&
1916 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1919 tlbl = newiTempLabel(NULL);
1920 gencjneshort(left, right, tlbl);
1921 if ( IC_TRUE(ifx) ) {
1922 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1923 emitcode("", LABEL_STR ":",tlbl->key+100);
1925 /* PENDING: do this better */
1926 symbol *lbl = newiTempLabel(NULL);
1927 emitcode("jp", LABEL_STR ,lbl->key+100);
1928 emitcode("", LABEL_STR ":",tlbl->key+100);
1929 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1930 emitcode("", LABEL_STR ":",lbl->key+100);
1933 /* mark the icode as generated */
1938 /* if they are both bit variables */
1939 if (AOP_TYPE(left) == AOP_CRY &&
1940 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1943 gencjne(left,right,newiTempLabel(NULL));
1944 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1948 genIfxJump(ifx,"a");
1951 /* if the result is used in an arithmetic operation
1952 then put the result in place */
1953 if (AOP_TYPE(result) != AOP_CRY) {
1956 /* leave the result in acc */
1960 freeAsmop(left,NULL,ic);
1961 freeAsmop(right,NULL,ic);
1962 freeAsmop(result,NULL,ic);
1965 /*-----------------------------------------------------------------*/
1966 /* ifxForOp - returns the icode containing the ifx for operand */
1967 /*-----------------------------------------------------------------*/
1968 static iCode *ifxForOp ( operand *op, iCode *ic )
1970 /* if true symbol then needs to be assigned */
1971 if (IS_TRUE_SYMOP(op))
1974 /* if this has register type condition and
1975 the next instruction is ifx with the same operand
1976 and live to of the operand is upto the ifx only then */
1978 ic->next->op == IFX &&
1979 IC_COND(ic->next)->key == op->key &&
1980 OP_SYMBOL(op)->liveTo <= ic->next->seq )
1986 /*-----------------------------------------------------------------*/
1987 /* genAndOp - for && operation */
1988 /*-----------------------------------------------------------------*/
1989 static void genAndOp (iCode *ic)
1991 operand *left,*right, *result;
1994 /* note here that && operations that are in an if statement are
1995 taken away by backPatchLabels only those used in arthmetic
1996 operations remain */
1997 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1998 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1999 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2001 /* if both are bit variables */
2002 if (AOP_TYPE(left) == AOP_CRY &&
2003 AOP_TYPE(right) == AOP_CRY ) {
2006 tlbl = newiTempLabel(NULL);
2008 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2010 emitcode("", LABEL_STR ":",tlbl->key+100);
2014 freeAsmop(left,NULL,ic);
2015 freeAsmop(right,NULL,ic);
2016 freeAsmop(result,NULL,ic);
2019 /*-----------------------------------------------------------------*/
2020 /* genOrOp - for || operation */
2021 /*-----------------------------------------------------------------*/
2022 static void genOrOp (iCode *ic)
2024 operand *left,*right, *result;
2027 /* note here that || operations that are in an
2028 if statement are taken away by backPatchLabels
2029 only those used in arthmetic operations remain */
2030 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2031 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2032 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2034 /* if both are bit variables */
2035 if (AOP_TYPE(left) == AOP_CRY &&
2036 AOP_TYPE(right) == AOP_CRY ) {
2039 tlbl = newiTempLabel(NULL);
2041 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2043 emitcode("", LABEL_STR,tlbl->key+100);
2047 freeAsmop(left,NULL,ic);
2048 freeAsmop(right,NULL,ic);
2049 freeAsmop(result,NULL,ic);
2052 /*-----------------------------------------------------------------*/
2053 /* isLiteralBit - test if lit == 2^n */
2054 /*-----------------------------------------------------------------*/
2055 int isLiteralBit(unsigned long lit)
2057 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2058 0x100L,0x200L,0x400L,0x800L,
2059 0x1000L,0x2000L,0x4000L,0x8000L,
2060 0x10000L,0x20000L,0x40000L,0x80000L,
2061 0x100000L,0x200000L,0x400000L,0x800000L,
2062 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2063 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2066 for(idx = 0; idx < 32; idx++)
2072 /*-----------------------------------------------------------------*/
2073 /* genAnd - code for and */
2074 /*-----------------------------------------------------------------*/
2075 static void genAnd (iCode *ic, iCode *ifx)
2077 operand *left, *right, *result;
2079 unsigned long lit = 0L;
2082 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2083 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2084 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2087 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2089 AOP_TYPE(left), AOP_TYPE(right));
2090 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2092 AOP_SIZE(left), AOP_SIZE(right));
2095 /* if left is a literal & right is not then exchange them */
2096 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2097 AOP_NEEDSACC(left)) {
2098 operand *tmp = right ;
2103 /* if result = right then exchange them */
2104 if(sameRegs(AOP(result),AOP(right))){
2105 operand *tmp = right ;
2110 /* if right is bit then exchange them */
2111 if (AOP_TYPE(right) == AOP_CRY &&
2112 AOP_TYPE(left) != AOP_CRY){
2113 operand *tmp = right ;
2117 if(AOP_TYPE(right) == AOP_LIT)
2118 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2120 size = AOP_SIZE(result);
2122 if (AOP_TYPE(left) == AOP_CRY){
2127 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2128 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2129 if((AOP_TYPE(right) == AOP_LIT) &&
2130 (AOP_TYPE(result) == AOP_CRY) &&
2131 (AOP_TYPE(left) != AOP_CRY)) {
2132 int posbit = isLiteralBit(lit);
2136 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2140 emitcode("mov","c,acc.%d",posbit&0x07);
2145 sprintf(buffer, "%d", posbit&0x07);
2146 genIfxJump(ifx, buffer);
2154 symbol *tlbl = newiTempLabel(NULL);
2155 int sizel = AOP_SIZE(left);
2158 emitcode("setb","c");
2161 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2162 MOVA( aopGet(AOP(left),offset,FALSE));
2164 if((posbit = isLiteralBit(bytelit)) != 0) {
2166 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2169 if(bytelit != 0x0FFL)
2170 emitcode("and","a,%s",
2171 aopGet(AOP(right),offset,FALSE));
2172 emitcode("jr","nz, %05d$",tlbl->key+100);
2177 // bit = left & literal
2179 emitcode("clr","c");
2180 emitcode("","%05d$:",tlbl->key+100);
2182 // if(left & literal)
2186 jmpTrueOrFalse(ifx, tlbl);
2197 /* if left is same as result */
2198 if(sameRegs(AOP(result),AOP(left))){
2199 for(;size--; offset++) {
2200 if(AOP_TYPE(right) == AOP_LIT){
2201 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2205 aopPut(AOP(result),zero,offset);
2207 MOVA(aopGet(AOP(left),offset,FALSE));
2208 emitcode("and","a,%s",
2209 aopGet(AOP(right),offset,FALSE));
2210 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2215 if (AOP_TYPE(left) == AOP_ACC) {
2219 MOVA(aopGet(AOP(right),offset,FALSE));
2220 emitcode("and","%s,a",
2221 aopGet(AOP(left),offset,FALSE));
2226 // left & result in different registers
2227 if(AOP_TYPE(result) == AOP_CRY){
2230 for(;(size--);offset++) {
2232 // result = left & right
2233 if(AOP_TYPE(right) == AOP_LIT){
2234 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2236 aopGet(AOP(left),offset,FALSE),
2239 } else if(bytelit == 0){
2240 aopPut(AOP(result),zero,offset);
2244 // faster than result <- left, anl result,right
2245 // and better if result is SFR
2246 if (AOP_TYPE(left) == AOP_ACC)
2247 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2249 MOVA(aopGet(AOP(right),offset,FALSE));
2250 emitcode("and","a,%s",
2251 aopGet(AOP(left),offset,FALSE));
2253 aopPut(AOP(result),"a",offset);
2260 freeAsmop(left,NULL,ic);
2261 freeAsmop(right,NULL,ic);
2262 freeAsmop(result,NULL,ic);
2265 /*-----------------------------------------------------------------*/
2266 /* genOr - code for or */
2267 /*-----------------------------------------------------------------*/
2268 static void genOr (iCode *ic, iCode *ifx)
2270 operand *left, *right, *result;
2272 unsigned long lit = 0L;
2274 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2275 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2276 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2279 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2281 AOP_TYPE(left), AOP_TYPE(right));
2282 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2284 AOP_SIZE(left), AOP_SIZE(right));
2287 /* if left is a literal & right is not then exchange them */
2288 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2289 AOP_NEEDSACC(left)) {
2290 operand *tmp = right ;
2295 /* if result = right then exchange them */
2296 if(sameRegs(AOP(result),AOP(right))){
2297 operand *tmp = right ;
2302 /* if right is bit then exchange them */
2303 if (AOP_TYPE(right) == AOP_CRY &&
2304 AOP_TYPE(left) != AOP_CRY){
2305 operand *tmp = right ;
2309 if(AOP_TYPE(right) == AOP_LIT)
2310 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2312 size = AOP_SIZE(result);
2314 if (AOP_TYPE(left) == AOP_CRY){
2319 if((AOP_TYPE(right) == AOP_LIT) &&
2320 (AOP_TYPE(result) == AOP_CRY) &&
2321 (AOP_TYPE(left) != AOP_CRY)){
2326 /* if left is same as result */
2327 if(sameRegs(AOP(result),AOP(left))){
2328 for(;size--; offset++) {
2329 if(AOP_TYPE(right) == AOP_LIT){
2330 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2333 emitcode("or","%s,%s",
2334 aopGet(AOP(left),offset,FALSE),
2335 aopGet(AOP(right),offset,FALSE));
2337 if (AOP_TYPE(left) == AOP_ACC)
2338 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2340 MOVA(aopGet(AOP(right),offset,FALSE));
2341 emitcode("or","a,%s",
2342 aopGet(AOP(left),offset,FALSE));
2343 aopPut(AOP(result),"a",0);
2348 // left & result in different registers
2349 if(AOP_TYPE(result) == AOP_CRY){
2351 } else for(;(size--);offset++){
2353 // result = left & right
2354 if(AOP_TYPE(right) == AOP_LIT){
2355 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2357 aopGet(AOP(left),offset,FALSE),
2362 // faster than result <- left, anl result,right
2363 // and better if result is SFR
2364 if (AOP_TYPE(left) == AOP_ACC)
2365 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2367 MOVA(aopGet(AOP(right),offset,FALSE));
2368 emitcode("or","a,%s",
2369 aopGet(AOP(left),offset,FALSE));
2370 aopPut(AOP(result),"a",0);
2372 aopPut(AOP(result),"a",offset);
2377 freeAsmop(left,NULL,ic);
2378 freeAsmop(right,NULL,ic);
2379 freeAsmop(result,NULL,ic);
2382 /*-----------------------------------------------------------------*/
2383 /* genXor - code for xclusive or */
2384 /*-----------------------------------------------------------------*/
2385 static void genXor (iCode *ic, iCode *ifx)
2387 operand *left, *right, *result;
2389 unsigned long lit = 0L;
2391 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2392 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2393 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2395 /* if left is a literal & right is not then exchange them */
2396 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2397 AOP_NEEDSACC(left)) {
2398 operand *tmp = right ;
2403 /* if result = right then exchange them */
2404 if(sameRegs(AOP(result),AOP(right))){
2405 operand *tmp = right ;
2410 /* if right is bit then exchange them */
2411 if (AOP_TYPE(right) == AOP_CRY &&
2412 AOP_TYPE(left) != AOP_CRY){
2413 operand *tmp = right ;
2417 if(AOP_TYPE(right) == AOP_LIT)
2418 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2420 size = AOP_SIZE(result);
2422 if (AOP_TYPE(left) == AOP_CRY){
2427 if((AOP_TYPE(right) == AOP_LIT) &&
2428 (AOP_TYPE(result) == AOP_CRY) &&
2429 (AOP_TYPE(left) != AOP_CRY)){
2434 /* if left is same as result */
2435 if(sameRegs(AOP(result),AOP(left))){
2436 for(;size--; offset++) {
2437 if(AOP_TYPE(right) == AOP_LIT){
2438 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2441 MOVA(aopGet(AOP(right),offset,FALSE));
2442 emitcode("xor","a,%s",
2443 aopGet(AOP(left),offset,FALSE));
2444 aopPut(AOP(result),"a",0);
2447 if (AOP_TYPE(left) == AOP_ACC)
2448 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2450 MOVA(aopGet(AOP(right),offset,FALSE));
2451 emitcode("xor","a,%s",
2452 aopGet(AOP(left),offset,FALSE));
2453 aopPut(AOP(result),"a",0);
2458 // left & result in different registers
2459 if(AOP_TYPE(result) == AOP_CRY){
2461 } else for(;(size--);offset++){
2463 // result = left & right
2464 if(AOP_TYPE(right) == AOP_LIT){
2465 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2467 aopGet(AOP(left),offset,FALSE),
2472 // faster than result <- left, anl result,right
2473 // and better if result is SFR
2474 if (AOP_TYPE(left) == AOP_ACC)
2475 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2477 MOVA(aopGet(AOP(right),offset,FALSE));
2478 emitcode("xor","a,%s",
2479 aopGet(AOP(left),offset,FALSE));
2480 aopPut(AOP(result),"a",0);
2482 aopPut(AOP(result),"a",offset);
2487 freeAsmop(left,NULL,ic);
2488 freeAsmop(right,NULL,ic);
2489 freeAsmop(result,NULL,ic);
2492 /*-----------------------------------------------------------------*/
2493 /* genInline - write the inline code out */
2494 /*-----------------------------------------------------------------*/
2495 static void genInline (iCode *ic)
2497 char buffer[MAX_INLINEASM];
2501 inLine += (!options.asmpeep);
2502 strcpy(buffer,IC_INLINE(ic));
2504 /* emit each line as a code */
2523 /* emitcode("",buffer); */
2524 inLine -= (!options.asmpeep);
2527 /*-----------------------------------------------------------------*/
2528 /* genRRC - rotate right with carry */
2529 /*-----------------------------------------------------------------*/
2530 static void genRRC (iCode *ic)
2535 /*-----------------------------------------------------------------*/
2536 /* genRLC - generate code for rotate left with carry */
2537 /*-----------------------------------------------------------------*/
2538 static void genRLC (iCode *ic)
2543 /*-----------------------------------------------------------------*/
2544 /* shiftR2Left2Result - shift right two bytes from left to result */
2545 /*-----------------------------------------------------------------*/
2546 static void shiftR2Left2Result (operand *left, int offl,
2547 operand *result, int offr,
2548 int shCount, int sign)
2550 if(sameRegs(AOP(result), AOP(left)) &&
2551 ((offl + MSB16) == offr)){
2554 movLeft2Result(left, offl, result, offr, 0);
2555 movLeft2Result(left, offl+1, result, offr+1, 0);
2562 /* if (AOP(result)->type == AOP_REG) {*/
2565 symbol *tlbl , *tlbl1;
2568 /* Left is already in result - so now do the shift */
2570 emitcode("ld","a,#%u+1", shCount);
2571 tlbl = newiTempLabel(NULL);
2572 tlbl1 = newiTempLabel(NULL);
2573 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2574 emitcode("", LABEL_STR ":",tlbl->key+100);
2577 emitcode("or", "a,a");
2580 l = aopGet(AOP(result), --offset, FALSE);
2581 emitcode("rr","%s", l);
2584 emitcode("", LABEL_STR ":",tlbl1->key+100);
2585 emitcode("dec", "a");
2586 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2591 /*-----------------------------------------------------------------*/
2592 /* shiftL2Left2Result - shift left two bytes from left to result */
2593 /*-----------------------------------------------------------------*/
2594 static void shiftL2Left2Result (operand *left, int offl,
2595 operand *result, int offr, int shCount)
2597 if(sameRegs(AOP(result), AOP(left)) &&
2598 ((offl + MSB16) == offr)){
2601 /* Copy left into result */
2602 movLeft2Result(left,offl, result, offr, 0);
2604 /* PENDING: for now just see if it'll work. */
2605 /*if (AOP(result)->type == AOP_REG) { */
2609 symbol *tlbl , *tlbl1;
2612 /* Left is already in result - so now do the shift */
2614 emitcode("ld","a,#%u+1", shCount);
2615 tlbl = newiTempLabel(NULL);
2616 tlbl1 = newiTempLabel(NULL);
2617 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2618 emitcode("", LABEL_STR ":",tlbl->key+100);
2621 emitcode("or", "a,a");
2623 l = aopGet(AOP(result),offset++,FALSE);
2624 emitcode("rl","%s", l);
2627 emitcode("", LABEL_STR ":",tlbl1->key+100);
2628 emitcode("dec", "a");
2629 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2634 /*-----------------------------------------------------------------*/
2635 /* AccRol - rotate left accumulator by known count */
2636 /*-----------------------------------------------------------------*/
2637 static void AccRol (int shCount)
2639 shCount &= 0x0007; // shCount : 0..7
2676 /*-----------------------------------------------------------------*/
2677 /* AccLsh - left shift accumulator by known count */
2678 /*-----------------------------------------------------------------*/
2679 static void AccLsh (int shCount)
2683 emitcode("add","a,a");
2686 emitcode("add","a,a");
2687 emitcode("add","a,a");
2689 /* rotate left accumulator */
2691 /* and kill the lower order bits */
2692 emitcode("and","a,#0x%02x", SLMask[shCount]);
2697 /*-----------------------------------------------------------------*/
2698 /* shiftL1Left2Result - shift left one byte from left to result */
2699 /*-----------------------------------------------------------------*/
2700 static void shiftL1Left2Result (operand *left, int offl,
2701 operand *result, int offr, int shCount)
2704 l = aopGet(AOP(left),offl,FALSE);
2706 /* shift left accumulator */
2708 aopPut(AOP(result),"a",offr);
2712 /*-----------------------------------------------------------------*/
2713 /* genlshTwo - left shift two bytes by known amount != 0 */
2714 /*-----------------------------------------------------------------*/
2715 static void genlshTwo (operand *result,operand *left, int shCount)
2717 int size = AOP_SIZE(result);
2721 /* if shCount >= 8 */
2727 movLeft2Result(left, LSB, result, MSB16, 0);
2728 aopPut(AOP(result),zero, 0);
2729 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2732 movLeft2Result(left, LSB, result, MSB16, 0);
2733 aopPut(AOP(result),zero, 0);
2736 aopPut(AOP(result),zero,LSB);
2738 /* 1 <= shCount <= 7 */
2744 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2749 /*-----------------------------------------------------------------*/
2750 /* genlshOne - left shift a one byte quantity by known count */
2751 /*-----------------------------------------------------------------*/
2752 static void genlshOne (operand *result, operand *left, int shCount)
2754 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2757 /*-----------------------------------------------------------------*/
2758 /* genLeftShiftLiteral - left shifting by known count */
2759 /*-----------------------------------------------------------------*/
2760 static void genLeftShiftLiteral (operand *left,
2765 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2768 freeAsmop(right,NULL,ic);
2770 aopOp(left,ic,FALSE);
2771 aopOp(result,ic,FALSE);
2773 size = getSize(operandType(result));
2776 emitcode("; shift left ","result %d, left %d",size,
2780 /* I suppose that the left size >= result size */
2785 else if(shCount >= (size * 8))
2787 aopPut(AOP(result),zero,size);
2791 genlshOne (result,left,shCount);
2794 genlshTwo (result,left,shCount);
2803 freeAsmop(left,NULL,ic);
2804 freeAsmop(result,NULL,ic);
2807 /*-----------------------------------------------------------------*/
2808 /* genLeftShift - generates code for left shifting */
2809 /*-----------------------------------------------------------------*/
2810 static void genLeftShift (iCode *ic)
2814 symbol *tlbl , *tlbl1;
2815 operand *left,*right, *result;
2817 right = IC_RIGHT(ic);
2819 result = IC_RESULT(ic);
2821 aopOp(right,ic,FALSE);
2823 /* if the shift count is known then do it
2824 as efficiently as possible */
2825 if (AOP_TYPE(right) == AOP_LIT) {
2826 genLeftShiftLiteral (left,right,result,ic);
2830 /* shift count is unknown then we have to form a loop get the loop
2831 count in B : Note: we take only the lower order byte since
2832 shifting more that 32 bits make no sense anyway, ( the largest
2833 size of an object can be only 32 bits ) */
2834 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2835 emitcode("inc","a");
2836 freeAsmop (right,NULL,ic);
2837 aopOp(left,ic,FALSE);
2838 aopOp(result,ic,FALSE);
2840 /* now move the left to the result if they are not the
2843 if (!sameRegs(AOP(left),AOP(result))) {
2845 size = AOP_SIZE(result);
2848 l = aopGet(AOP(left),offset,FALSE);
2849 aopPut(AOP(result),l,offset);
2854 size = AOP_SIZE(result);
2857 l = aopGet(AOP(left),offset,FALSE);
2858 aopPut(AOP(result),l,offset);
2864 tlbl = newiTempLabel(NULL);
2865 size = AOP_SIZE(result);
2867 tlbl1 = newiTempLabel(NULL);
2869 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2870 emitcode("", LABEL_STR ":",tlbl->key+100);
2871 l = aopGet(AOP(result),offset,FALSE);
2872 emitcode("or", "a,a");
2874 l = aopGet(AOP(result),offset++,FALSE);
2875 emitcode("rl","%s", l);
2877 emitcode("", LABEL_STR ":",tlbl1->key+100);
2878 emitcode("dec", "a");
2879 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2881 freeAsmop(left,NULL,ic);
2882 freeAsmop(result,NULL,ic);
2885 /* genlshTwo - left shift two bytes by known amount != 0 */
2886 /*-----------------------------------------------------------------*/
2887 static void genrshOne (operand *result,operand *left, int shCount)
2890 int size = AOP_SIZE(result);
2896 l = aopGet(AOP(left),0,FALSE);
2897 if (AOP(result)->type == AOP_REG) {
2898 aopPut(AOP(result), l, 0);
2899 l = aopGet(AOP(result), 0, FALSE);
2901 emitcode("srl", "%s", l);
2906 emitcode("srl", "a");
2908 aopPut(AOP(result),"a",0);
2912 /*-----------------------------------------------------------------*/
2913 /* AccRsh - right shift accumulator by known count */
2914 /*-----------------------------------------------------------------*/
2915 static void AccRsh (int shCount)
2922 /* rotate right accumulator */
2923 AccRol(8 - shCount);
2924 /* and kill the higher order bits */
2925 emitcode("and","a,#0x%02x", SRMask[shCount]);
2930 /*-----------------------------------------------------------------*/
2931 /* shiftR1Left2Result - shift right one byte from left to result */
2932 /*-----------------------------------------------------------------*/
2933 static void shiftR1Left2Result (operand *left, int offl,
2934 operand *result, int offr,
2935 int shCount, int sign)
2937 MOVA(aopGet(AOP(left),offl,FALSE));
2944 aopPut(AOP(result),"a",offr);
2947 /*-----------------------------------------------------------------*/
2948 /* genrshTwo - right shift two bytes by known amount != 0 */
2949 /*-----------------------------------------------------------------*/
2950 static void genrshTwo (operand *result,operand *left,
2951 int shCount, int sign)
2953 /* if shCount >= 8 */
2958 shiftR1Left2Result(left, MSB16, result, LSB,
2962 movLeft2Result(left, MSB16, result, LSB, sign);
2963 aopPut(AOP(result),zero,1);
2966 /* 1 <= shCount <= 7 */
2968 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
2972 /*-----------------------------------------------------------------*/
2973 /* genRightShiftLiteral - left shifting by known count */
2974 /*-----------------------------------------------------------------*/
2975 static void genRightShiftLiteral (operand *left,
2980 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2983 freeAsmop(right,NULL,ic);
2985 aopOp(left,ic,FALSE);
2986 aopOp(result,ic,FALSE);
2988 size = getSize(operandType(result));
2990 emitcode("; shift right ","result %d, left %d",size,
2993 /* I suppose that the left size >= result size */
2998 else if(shCount >= (size * 8))
3000 aopPut(AOP(result),zero,size);
3004 genrshOne(result, left, shCount);
3007 /* PENDING: sign support */
3008 genrshTwo(result, left, shCount, FALSE);
3017 freeAsmop(left,NULL,ic);
3018 freeAsmop(result,NULL,ic);
3021 /*-----------------------------------------------------------------*/
3022 /* genRightShift - generate code for right shifting */
3023 /*-----------------------------------------------------------------*/
3024 static void genRightShift (iCode *ic)
3026 operand *left,*right, *result;
3028 right = IC_RIGHT(ic);
3030 result = IC_RESULT(ic);
3032 aopOp(right,ic,FALSE);
3034 /* if the shift count is known then do it
3035 as efficiently as possible */
3036 if (AOP_TYPE(right) == AOP_LIT) {
3037 genRightShiftLiteral (left,right,result,ic);
3045 /*-----------------------------------------------------------------*/
3046 /* genGenPointerGet - gget value from generic pointer space */
3047 /*-----------------------------------------------------------------*/
3048 static void genGenPointerGet (operand *left,
3049 operand *result, iCode *ic)
3052 link *retype = getSpec(operandType(result));
3054 aopOp(left,ic,FALSE);
3055 aopOp(result,ic,FALSE);
3057 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3059 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3060 aopPut(AOP(result),"a", 0);
3061 freeAsmop(left,NULL,ic);
3065 /* For now we always load into IY */
3066 /* if this is remateriazable */
3067 if (AOP_TYPE(left) == AOP_IMMD)
3068 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3069 else { /* we need to get it byte by byte */
3070 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3071 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3073 /* so iy now contains the address */
3074 freeAsmop(left,NULL,ic);
3076 /* if bit then unpack */
3077 if (IS_BITVAR(retype)) {
3081 size = AOP_SIZE(result);
3085 /* PENDING: make this better */
3086 if (AOP(result)->type == AOP_REG) {
3087 aopPut(AOP(result),"(hl)",offset++);
3090 emitcode("ld", "a,(hl)", offset);
3091 aopPut(AOP(result),"a",offset++);
3094 emitcode("inc", "hl");
3100 freeAsmop(result,NULL,ic);
3103 /*-----------------------------------------------------------------*/
3104 /* genPointerGet - generate code for pointer get */
3105 /*-----------------------------------------------------------------*/
3106 static void genPointerGet (iCode *ic)
3108 operand *left, *result ;
3112 result = IC_RESULT(ic) ;
3114 /* depending on the type of pointer we need to
3115 move it to the correct pointer register */
3116 type = operandType(left);
3117 etype = getSpec(type);
3119 genGenPointerGet (left,result,ic);
3122 bool isRegOrLit(asmop *aop)
3124 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3129 /*-----------------------------------------------------------------*/
3130 /* genGenPointerSet - stores the value into a pointer location */
3131 /*-----------------------------------------------------------------*/
3132 static void genGenPointerSet (operand *right,
3133 operand *result, iCode *ic)
3136 link *retype = getSpec(operandType(right));
3138 aopOp(result,ic,FALSE);
3139 aopOp(right,ic,FALSE);
3141 /* Handle the exceptions first */
3142 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3144 char *l = aopGet(AOP(right), 0, FALSE);
3146 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3147 freeAsmop(result,NULL,ic);
3151 /* if the operand is already in dptr
3152 then we do nothing else we move the value to dptr */
3153 if (AOP_TYPE(result) != AOP_STR) {
3154 /* if this is remateriazable */
3155 if (AOP_TYPE(result) == AOP_IMMD) {
3156 emitcode("", "; Error 2");
3157 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3159 else { /* we need to get it byte by byte */
3160 /* PENDING: do this better */
3161 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3162 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3165 /* so hl know contains the address */
3166 freeAsmop(result,NULL,ic);
3168 /* if bit then unpack */
3169 if (IS_BITVAR(retype)) {
3173 size = AOP_SIZE(right);
3177 char *l = aopGet(AOP(right),offset,FALSE);
3179 if (isRegOrLit(AOP(right))) {
3180 emitcode("ld", "(hl),%s", l);
3184 emitcode("ld", "(hl),a", offset);
3187 emitcode("inc", "hl");
3193 freeAsmop(right,NULL,ic);
3196 /*-----------------------------------------------------------------*/
3197 /* genPointerSet - stores the value into a pointer location */
3198 /*-----------------------------------------------------------------*/
3199 static void genPointerSet (iCode *ic)
3201 operand *right, *result ;
3204 right = IC_RIGHT(ic);
3205 result = IC_RESULT(ic) ;
3207 /* depending on the type of pointer we need to
3208 move it to the correct pointer register */
3209 type = operandType(result);
3210 etype = getSpec(type);
3212 genGenPointerSet (right,result,ic);
3215 /*-----------------------------------------------------------------*/
3216 /* genIfx - generate code for Ifx statement */
3217 /*-----------------------------------------------------------------*/
3218 static void genIfx (iCode *ic, iCode *popIc)
3220 operand *cond = IC_COND(ic);
3223 aopOp(cond,ic,FALSE);
3225 /* get the value into acc */
3226 if (AOP_TYPE(cond) != AOP_CRY)
3230 /* the result is now in the accumulator */
3231 freeAsmop(cond,NULL,ic);
3233 /* if there was something to be popped then do it */
3237 /* if the condition is a bit variable */
3238 if (isbit && IS_ITEMP(cond) &&
3240 genIfxJump(ic,SPIL_LOC(cond)->rname);
3242 if (isbit && !IS_ITEMP(cond))
3243 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3250 /*-----------------------------------------------------------------*/
3251 /* genAddrOf - generates code for address of */
3252 /*-----------------------------------------------------------------*/
3253 static void genAddrOf (iCode *ic)
3255 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3257 aopOp(IC_RESULT(ic),ic,FALSE);
3259 /* if the operand is on the stack then we
3260 need to get the stack offset of this
3263 /* if it has an offset then we need to compute it */
3264 emitcode("push", "de");
3265 emitcode("push", "ix");
3266 emitcode("pop", "hl");
3267 emitcode("ld", "de,#%d", sym->stack);
3268 emitcode("add", "hl,de");
3269 emitcode("pop", "de");
3272 emitcode("ld", "hl,#%s", sym->rname);
3274 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3275 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3277 freeAsmop(IC_RESULT(ic),NULL,ic);
3280 /*-----------------------------------------------------------------*/
3281 /* genAssign - generate code for assignment */
3282 /*-----------------------------------------------------------------*/
3283 static void genAssign (iCode *ic)
3285 operand *result, *right;
3287 unsigned long lit = 0L;
3289 result = IC_RESULT(ic);
3290 right = IC_RIGHT(ic) ;
3293 /* Dont bother assigning if they are the same */
3294 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3295 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3300 aopOp(right,ic,FALSE);
3301 aopOp(result,ic,TRUE);
3303 /* if they are the same registers */
3304 if (sameRegs(AOP(right),AOP(result))) {
3305 emitcode("", "; (registers are the same)");
3309 /* if the result is a bit */
3310 if (AOP_TYPE(result) == AOP_CRY) {
3315 size = AOP_SIZE(result);
3318 if(AOP_TYPE(right) == AOP_LIT)
3319 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3321 (AOP_TYPE(result) != AOP_REG) &&
3322 (AOP_TYPE(right) == AOP_LIT) &&
3323 !IS_FLOAT(operandType(right)) &&
3325 emitcode("xor","a,a");
3326 /* Work from the top down.
3327 Done this way so that we can use the cached copy of 0
3328 in A for a fast clear */
3330 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3331 aopPut(AOP(result),"a",size);
3334 aopGet(AOP(right),size,FALSE),
3340 aopGet(AOP(right),offset,FALSE),
3347 freeAsmop(right,NULL,ic);
3348 freeAsmop(result,NULL,ic);
3351 /*-----------------------------------------------------------------*/
3352 /* genJumpTab - genrates code for jump table */
3353 /*-----------------------------------------------------------------*/
3354 static void genJumpTab (iCode *ic)
3359 aopOp(IC_JTCOND(ic),ic,FALSE);
3360 /* get the condition into accumulator */
3361 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3363 emitcode("push", "de");
3364 emitcode("ld", "e,%s", l);
3365 emitcode("ld", "d,#0");
3366 jtab = newiTempLabel(NULL);
3367 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3368 emitcode("add", "hl,de");
3369 emitcode("add", "hl,de");
3370 freeAsmop(IC_JTCOND(ic),NULL,ic);
3371 emitcode("pop", "de");
3372 emitcode("jp", "(hl)");
3373 emitcode("","%05d$:",jtab->key+100);
3374 /* now generate the jump labels */
3375 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3376 jtab = setNextItem(IC_JTLABELS(ic)))
3377 emitcode("jp", LABEL_STR, jtab->key+100);
3380 /*-----------------------------------------------------------------*/
3381 /* genCast - gen code for casting */
3382 /*-----------------------------------------------------------------*/
3383 static void genCast (iCode *ic)
3385 operand *result = IC_RESULT(ic);
3386 link *ctype = operandType(IC_LEFT(ic));
3387 operand *right = IC_RIGHT(ic);
3390 /* if they are equivalent then do nothing */
3391 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3394 aopOp(right,ic,FALSE) ;
3395 aopOp(result,ic,FALSE);
3397 /* if the result is a bit */
3398 if (AOP_TYPE(result) == AOP_CRY) {
3402 /* if they are the same size : or less */
3403 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3405 /* if they are in the same place */
3406 if (sameRegs(AOP(right),AOP(result)))
3409 /* if they in different places then copy */
3410 size = AOP_SIZE(result);
3414 aopGet(AOP(right),offset,FALSE),
3421 /* if the result is of type pointer */
3422 if (IS_PTR(ctype)) {
3426 /* so we now know that the size of destination is greater
3427 than the size of the source */
3428 /* we move to result for the size of source */
3429 size = AOP_SIZE(right);
3433 aopGet(AOP(right),offset,FALSE),
3438 /* now depending on the sign of the destination */
3439 size = AOP_SIZE(result) - AOP_SIZE(right);
3440 /* Unsigned or not an integral type - right fill with zeros */
3441 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3443 aopPut(AOP(result),zero,offset++);
3445 /* we need to extend the sign :{ */
3446 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3449 emitcode("", "; genCast: sign extend untested.");
3450 emitcode("rla", "");
3451 emitcode("sbc", "a,a");
3453 aopPut(AOP(result),"a",offset++);
3457 freeAsmop(right, NULL, ic);
3458 freeAsmop(result, NULL, ic);
3461 /*-----------------------------------------------------------------*/
3462 /* genReceive - generate code for a receive iCode */
3463 /*-----------------------------------------------------------------*/
3464 static void genReceive (iCode *ic)
3466 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3467 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3468 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3472 aopOp(IC_RESULT(ic),ic,FALSE);
3474 assignResultValue(IC_RESULT(ic));
3477 freeAsmop(IC_RESULT(ic),NULL,ic);
3480 /*-----------------------------------------------------------------*/
3481 /* genZ80Code - generate code for Z80 based controllers */
3482 /*-----------------------------------------------------------------*/
3483 void genZ80Code (iCode *lic)
3488 lineHead = lineCurr = NULL;
3490 /* if debug information required */
3491 if (options.debug && currFunc) {
3492 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3494 if (IS_STATIC(currFunc->etype))
3495 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3497 emitcode("","G$%s$0$0 ==.",currFunc->name);
3500 /* stack pointer name */
3504 for (ic = lic ; ic ; ic = ic->next ) {
3506 if ( cln != ic->lineno ) {
3507 if ( options.debug ) {
3509 emitcode("","C$%s$%d$%d$%d ==.",
3510 ic->filename,ic->lineno,
3511 ic->level,ic->block);
3514 emitcode(";","%s %d",ic->filename,ic->lineno);
3517 /* if the result is marked as
3518 spilt and rematerializable or code for
3519 this has already been generated then
3521 if (resultRemat(ic) || ic->generated )
3524 /* depending on the operation */
3527 emitcode("", "; genNot");
3532 emitcode("", "; genCpl");
3537 emitcode("", "; genUminus");
3542 emitcode("", "; genIpush");
3547 /* IPOP happens only when trying to restore a
3548 spilt live range, if there is an ifx statement
3549 following this pop then the if statement might
3550 be using some of the registers being popped which
3551 would destory the contents of the register so
3552 we need to check for this condition and handle it */
3554 ic->next->op == IFX &&
3555 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3556 emitcode("", "; genIfx");
3557 genIfx (ic->next,ic);
3560 emitcode("", "; genIpop");
3566 emitcode("", "; genCall");
3571 emitcode("", "; genPcall");
3576 emitcode("", "; genFunction");
3581 emitcode("", "; genEndFunction");
3582 genEndFunction (ic);
3586 emitcode("", "; genRet");
3591 emitcode("", "; genLabel");
3596 emitcode("", "; genGoto");
3601 emitcode("", "; genPlus");
3606 emitcode("", "; genMinus");
3611 emitcode("", "; genMult");
3616 emitcode("", "; genDiv");
3621 emitcode("", "; genMod");
3626 emitcode("", "; genCmpGt");
3627 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3631 emitcode("", "; genCmpLt");
3632 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3639 /* note these two are xlated by algebraic equivalence
3640 during parsing SDCC.y */
3641 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3642 "got '>=' or '<=' shouldn't have come here");
3646 emitcode("", "; genCmpEq");
3647 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3651 emitcode("", "; genAndOp");
3656 emitcode("", "; genOrOp");
3661 emitcode("", "; genXor");
3662 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3666 emitcode("", "; genOr");
3667 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3671 emitcode("", "; genAnd");
3672 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3676 emitcode("", "; genInline");
3681 emitcode("", "; genRRC");
3686 emitcode("", "; genRLC");
3691 emitcode("", "; genHBIT");
3695 emitcode("", "; genLeftShift");
3700 emitcode("", "; genRightShift");
3704 case GET_VALUE_AT_ADDRESS:
3705 emitcode("", "; genPointerGet");
3711 if (POINTER_SET(ic)) {
3712 emitcode("", "; genAssign (pointer)");
3716 emitcode("", "; genAssign");
3722 emitcode("", "; genIfx");
3727 emitcode("", "; genAddrOf");
3732 emitcode("", "; genJumpTab");
3737 emitcode("", "; genCast");
3742 emitcode("", "; genReceive");
3747 emitcode("", "; addSet");
3748 addSet(&sendSet,ic);
3753 /* piCode(ic,stdout); */
3759 /* now we are ready to call the
3760 peep hole optimizer */
3761 /* if (!options.nopeep)
3762 peepHole (&lineHead); */
3764 /* now do the actual printing */
3765 printLine (lineHead,codeOutFile);