1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
40 #include "SDCChasht.h"
43 #include "SDCCicode.h"
44 #include "SDCClabel.h"
45 #include "SDCCBBlock.h"
48 #include "SDCCcflow.h"
49 #include "SDCCdflow.h"
50 #include "SDCClrange.h"
53 #include "SDCCpeeph.h"
55 /* this is the down and dirty file with all kinds of kludgy & hacky
56 stuff. This is what it is all about CODE GENERATION for a specific MCU.
57 Some of the routines may be reusable, will have to see */
59 static char *zero = "#0x00";
60 static char *one = "#0x01";
62 static char *fReturn[] = {"l", "h", "e", "d" };
63 static char *accUse[] = {"a" };
69 extern int ptrRegReq ;
71 extern FILE *codeOutFile;
73 #define RESULTONSTACK(x) \
74 (IC_RESULT(x) && IC_RESULT(x)->aop && \
75 IC_RESULT(x)->aop->type == AOP_STK )
77 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
78 #define CLRC emitcode("xor","a,a");
80 #define LABEL_STR "%05d$"
82 lineNode *lineHead = NULL;
83 lineNode *lineCurr = NULL;
85 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
86 0xE0, 0xC0, 0x80, 0x00};
87 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
88 0x07, 0x03, 0x01, 0x00};
90 static int _lastStack = 0;
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple */
107 /*-----------------------------------------------------------------*/
108 void emitcode (const char *inst, const char *fmt, ...)
111 char lb[MAX_INLINEASM];
117 sprintf(lb,"%s\t",inst);
118 vsprintf(lb+(strlen(lb)),fmt,ap);
122 while (isspace(*lbp)) lbp++;
125 lineCurr = (lineCurr ?
126 connectLine(lineCurr,newLineNode(lb)) :
127 (lineHead = newLineNode(lb)));
128 lineCurr->isInline = inLine;
129 lineCurr->isDebug = debugLine;
133 const char *getPairName(asmop *aop)
135 if (aop->type == AOP_REG) {
136 switch (aop->aopu.aop_reg[0]->rIdx) {
148 else if (aop->type == AOP_STR) {
149 switch (*aop->aopu.aop_str[0]) {
165 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
166 bool isPair(asmop *aop)
168 if (aop->size == 2) {
169 if (aop->type == AOP_REG) {
170 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
173 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
176 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
180 if (aop->type == AOP_STR) {
181 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
184 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
187 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
195 /** Push a register pair onto the stack */
196 void genPairPush(asmop *aop)
198 emitcode("push", "%s", getPairName(aop));
201 /*-----------------------------------------------------------------*/
202 /* newAsmop - creates a new asmOp */
203 /*-----------------------------------------------------------------*/
204 static asmop *newAsmop (short type)
208 ALLOC(aop,sizeof(asmop));
213 /*-----------------------------------------------------------------*/
214 /* aopForSym - for a true symbol */
215 /*-----------------------------------------------------------------*/
216 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
219 memmap *space= SPEC_OCLS(sym->etype);
221 /* if already has one */
225 /* Assign depending on the storage class */
226 if (sym->onStack || sym->iaccess) {
227 sym->aop = aop = newAsmop(AOP_STK);
228 aop->size = getSize(sym->type);
230 aop->aopu.aop_stk = sym->stack;
234 /* special case for a function */
235 if (IS_FUNC(sym->type)) {
236 sym->aop = aop = newAsmop(AOP_IMMD);
237 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
238 strcpy(aop->aopu.aop_immd,sym->rname);
243 /* only remaining is far space */
244 /* in which case DPTR gets the address */
245 sym->aop = aop = newAsmop(AOP_IY);
246 emitcode ("ld","iy,#%s", sym->rname);
247 aop->size = getSize(sym->type);
248 aop->aopu.aop_dir = sym->rname;
250 /* if it is in code space */
251 if (IN_CODESPACE(space))
257 /*-----------------------------------------------------------------*/
258 /* aopForRemat - rematerialzes an object */
259 /*-----------------------------------------------------------------*/
260 static asmop *aopForRemat (symbol *sym)
263 iCode *ic = sym->rematiCode;
264 asmop *aop = newAsmop(AOP_IMMD);
267 /* if plus or minus print the right hand side */
268 if (ic->op == '+' || ic->op == '-') {
269 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
272 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
275 /* we reached the end */
276 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
280 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
281 strcpy(aop->aopu.aop_immd,buffer);
285 /*-----------------------------------------------------------------*/
286 /* regsInCommon - two operands have some registers in common */
287 /*-----------------------------------------------------------------*/
288 bool regsInCommon (operand *op1, operand *op2)
293 /* if they have registers in common */
294 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
297 sym1 = OP_SYMBOL(op1);
298 sym2 = OP_SYMBOL(op2);
300 if (sym1->nRegs == 0 || sym2->nRegs == 0)
303 for (i = 0 ; i < sym1->nRegs ; i++) {
308 for (j = 0 ; j < sym2->nRegs ;j++ ) {
312 if (sym2->regs[j] == sym1->regs[i])
320 /*-----------------------------------------------------------------*/
321 /* operandsEqu - equivalent */
322 /*-----------------------------------------------------------------*/
323 bool operandsEqu ( operand *op1, operand *op2)
327 /* if they not symbols */
328 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
331 sym1 = OP_SYMBOL(op1);
332 sym2 = OP_SYMBOL(op2);
334 /* if both are itemps & one is spilt
335 and the other is not then false */
336 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
337 sym1->isspilt != sym2->isspilt )
340 /* if they are the same */
344 if (strcmp(sym1->rname,sym2->rname) == 0)
348 /* if left is a tmp & right is not */
352 (sym1->usl.spillLoc == sym2))
358 (sym2->usl.spillLoc == sym1))
364 /*-----------------------------------------------------------------*/
365 /* sameRegs - two asmops have the same registers */
366 /*-----------------------------------------------------------------*/
367 bool sameRegs (asmop *aop1, asmop *aop2 )
374 if (aop1->type != AOP_REG ||
375 aop2->type != AOP_REG )
378 if (aop1->size != aop2->size)
381 for (i = 0 ; i < aop1->size ; i++ )
382 if (aop1->aopu.aop_reg[i] !=
383 aop2->aopu.aop_reg[i] )
389 /*-----------------------------------------------------------------*/
390 /* aopOp - allocates an asmop for an operand : */
391 /*-----------------------------------------------------------------*/
392 static void aopOp (operand *op, iCode *ic, bool result)
401 /* if this a literal */
402 if (IS_OP_LITERAL(op)) {
403 op->aop = aop = newAsmop(AOP_LIT);
404 aop->aopu.aop_lit = op->operand.valOperand;
405 aop->size = getSize(operandType(op));
409 /* if already has a asmop then continue */
413 /* if the underlying symbol has a aop */
414 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
415 op->aop = OP_SYMBOL(op)->aop;
419 /* if this is a true symbol */
420 if (IS_TRUE_SYMOP(op)) {
421 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
425 /* this is a temporary : this has
431 e) can be a return use only */
435 /* if the type is a conditional */
436 if (sym->regType == REG_CND) {
437 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
442 /* if it is spilt then two situations
444 b) has a spill location */
445 if (sym->isspilt || sym->nRegs == 0) {
446 /* rematerialize it NOW */
448 sym->aop = op->aop = aop =
450 aop->size = getSize(sym->type);
456 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
457 aop->size = getSize(sym->type);
458 for ( i = 0 ; i < 2 ; i++ )
459 aop->aopu.aop_str[i] = accUse[i];
465 aop = op->aop = sym->aop = newAsmop(AOP_STR);
466 aop->size = getSize(sym->type);
467 for ( i = 0 ; i < 4 ; i++ )
468 aop->aopu.aop_str[i] = fReturn[i];
472 /* else spill location */
473 sym->aop = op->aop = aop =
474 aopForSym(ic,sym->usl.spillLoc,result);
475 aop->size = getSize(sym->type);
479 /* must be in a register */
480 sym->aop = op->aop = aop = newAsmop(AOP_REG);
481 aop->size = sym->nRegs;
482 for ( i = 0 ; i < sym->nRegs ;i++)
483 aop->aopu.aop_reg[i] = sym->regs[i];
486 /*-----------------------------------------------------------------*/
487 /* freeAsmop - free up the asmop given to an operand */
488 /*----------------------------------------------------------------*/
489 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
512 /* all other cases just dealloc */
516 OP_SYMBOL(op)->aop = NULL;
517 /* if the symbol has a spill */
519 SPIL_LOC(op)->aop = NULL;
524 /*-----------------------------------------------------------------*/
525 /* aopLiteral - string from a literal value */
526 /*-----------------------------------------------------------------*/
527 char *aopLiteral (value *val, int offset)
531 /* if it is a float then it gets tricky */
532 /* otherwise it is fairly simple */
533 if (!IS_FLOAT(val->type)) {
534 unsigned long v = floatFromVal(val);
537 sprintf(buffer,"#0x%02x",((char) v) & 0xff);
538 ALLOC_ATOMIC(rs,strlen(buffer)+1);
539 return strcpy (rs,buffer);
545 char *aopGetWord(asmop *aop, int offset)
550 assert(aop->size == 2);
553 /* depending on type */
556 sprintf (s,"#%s",aop->aopu.aop_immd);
557 ALLOC_ATOMIC(rs,strlen(s)+1);
562 value * val = aop->aopu.aop_lit;
563 /* if it is a float then it gets tricky */
564 /* otherwise it is fairly simple */
565 if (!IS_FLOAT(val->type)) {
566 unsigned long v = floatFromVal(val);
568 sprintf(buffer,"#0x%04lx", v);
569 ALLOC_ATOMIC(rs,strlen(buffer)+1);
570 return strcpy (rs,buffer);
579 /*-----------------------------------------------------------------*/
580 /* aopGet - for fetching value of the aop */
581 /*-----------------------------------------------------------------*/
582 static char *aopGet (asmop *aop, int offset, bool bit16)
587 /* offset is greater than size then zero */
588 if (offset > (aop->size - 1) &&
589 aop->type != AOP_LIT)
592 /* depending on type */
596 sprintf (s,"#%s",aop->aopu.aop_immd);
606 ALLOC_ATOMIC(rs,strlen(s)+1);
612 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
614 ALLOC_ATOMIC(rs,strlen(s)+1);
619 return aop->aopu.aop_reg[offset]->name;
622 sprintf(s,"%d(iy)", offset);
623 ALLOC_ATOMIC(rs,strlen(s)+1);
628 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
629 ALLOC_ATOMIC(rs,strlen(s)+1);
643 return aopLiteral (aop->aopu.aop_lit,offset);
647 return aop->aopu.aop_str[offset];
650 fprintf(stderr, "Type %u\n", aop->type);
652 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
653 "aopget got unsupported aop->type");
657 bool isRegString(char *s)
659 if (!strcmp(s, "b") ||
670 bool isConstant(char *s)
675 bool canAssignToPtr(char *s)
684 /*-----------------------------------------------------------------*/
685 /* aopPut - puts a string for a aop */
686 /*-----------------------------------------------------------------*/
687 static void aopPut (asmop *aop, char *s, int offset)
691 if (aop->size && offset > ( aop->size - 1)) {
692 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
693 "aopPut got offset > aop->size");
697 /* will assign value to value */
698 /* depending on where it is ofcourse */
703 emitcode("ld", "a,%s", s);
704 emitcode("ld", "(%s+%d),a", d, offset);
708 /* Dont bother if it's a ld x,x */
709 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
710 emitcode("ld","%s,%s",
711 aop->aopu.aop_reg[offset]->name,s);
716 if (!canAssignToPtr(s)) {
717 emitcode("ld", "a,%s", s);
718 emitcode("ld", "%d(iy),a", offset);
721 emitcode("ld", "%d(iy),%s", offset, s);
725 if (!canAssignToPtr(s)) {
726 emitcode("ld", "a,%s", s);
727 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
730 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
734 /* if bit variable */
735 if (!aop->aopu.aop_dir) {
736 emitcode("ld", "a,#0");
739 /* In bit space but not in C - cant happen */
746 if (strcmp(aop->aopu.aop_str[offset],s)) {
747 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
753 if (!offset && (strcmp(s,"acc") == 0))
756 emitcode("", "; Error aopPut AOP_ACC");
759 if (strcmp(aop->aopu.aop_str[offset],s))
760 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
765 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
766 "aopPut got unsupported aop->type");
771 #define AOP(op) op->aop
772 #define AOP_TYPE(op) AOP(op)->type
773 #define AOP_SIZE(op) AOP(op)->size
774 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
776 /*-----------------------------------------------------------------*/
777 /* getDataSize - get the operand data size */
778 /*-----------------------------------------------------------------*/
779 int getDataSize(operand *op)
790 /*-----------------------------------------------------------------*/
791 /* movLeft2Result - move byte from left to result */
792 /*-----------------------------------------------------------------*/
793 static void movLeft2Result (operand *left, int offl,
794 operand *result, int offr, int sign)
797 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
798 l = aopGet(AOP(left),offl,FALSE);
801 aopPut(AOP(result),l,offr);
810 /** Put Acc into a register set
812 void outAcc(operand *result)
815 size = getDataSize(result);
817 aopPut(AOP(result),"a",0);
820 /* unsigned or positive */
822 aopPut(AOP(result),zero,offset++);
827 /** Take the value in carry and put it into a register
829 void outBitC(operand *result)
831 /* if the result is bit */
832 if (AOP_TYPE(result) == AOP_CRY) {
833 emitcode("", "; Note: outBitC form 1");
834 aopPut(AOP(result),"blah",0);
837 emitcode("ld", "a,#0");
843 /*-----------------------------------------------------------------*/
844 /* toBoolean - emit code for orl a,operator(sizeop) */
845 /*-----------------------------------------------------------------*/
846 void toBoolean(operand *oper)
848 int size = AOP_SIZE(oper);
851 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
854 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
858 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
862 /*-----------------------------------------------------------------*/
863 /* genNot - generate code for ! operation */
864 /*-----------------------------------------------------------------*/
865 static void genNot (iCode *ic)
867 link *optype = operandType(IC_LEFT(ic));
869 /* assign asmOps to operand & result */
870 aopOp (IC_LEFT(ic),ic,FALSE);
871 aopOp (IC_RESULT(ic),ic,TRUE);
873 /* if in bit space then a special case */
874 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
878 /* if type float then do float */
879 if (IS_FLOAT(optype)) {
883 toBoolean(IC_LEFT(ic));
888 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
889 emitcode("sub", "a,#0x01");
890 outBitC(IC_RESULT(ic));
892 /* release the aops */
893 freeAsmop(IC_LEFT(ic),NULL,ic);
894 freeAsmop(IC_RESULT(ic),NULL,ic);
897 /*-----------------------------------------------------------------*/
898 /* genCpl - generate code for complement */
899 /*-----------------------------------------------------------------*/
900 static void genCpl (iCode *ic)
906 /* assign asmOps to operand & result */
907 aopOp (IC_LEFT(ic),ic,FALSE);
908 aopOp (IC_RESULT(ic),ic,TRUE);
910 /* if both are in bit space then
912 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
913 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
917 size = AOP_SIZE(IC_RESULT(ic));
919 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
922 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
925 /* release the aops */
926 freeAsmop(IC_LEFT(ic),NULL,ic);
927 freeAsmop(IC_RESULT(ic),NULL,ic);
930 /*-----------------------------------------------------------------*/
931 /* genUminus - unary minus code generation */
932 /*-----------------------------------------------------------------*/
933 static void genUminus (iCode *ic)
939 /*-----------------------------------------------------------------*/
940 /* assignResultValue - */
941 /*-----------------------------------------------------------------*/
942 void assignResultValue(operand * oper)
945 int size = AOP_SIZE(oper);
947 aopPut(AOP(oper),fReturn[offset],offset);
952 /*-----------------------------------------------------------------*/
953 /* genIpush - genrate code for pushing this gets a little complex */
954 /*-----------------------------------------------------------------*/
955 static void genIpush (iCode *ic)
957 int size, offset = 0 ;
961 /* if this is not a parm push : ie. it is spill push
962 and spill push is always done on the local stack */
964 /* and the item is spilt then do nothing */
965 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
968 aopOp(IC_LEFT(ic),ic,FALSE);
969 size = AOP_SIZE(IC_LEFT(ic));
970 /* push it on the stack */
971 if (isPair(AOP(IC_LEFT(ic)))) {
972 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
977 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
978 /* Simple for now - load into A and PUSH AF */
979 emitcode("ld", "a,%s", l);
980 emitcode("push", "af");
981 emitcode("inc", "sp");
987 /* Hmmm... what about saving the currently used registers
990 /* then do the push */
991 aopOp(IC_LEFT(ic),ic,FALSE);
993 size = AOP_SIZE(IC_LEFT(ic));
995 if (isPair(AOP(IC_LEFT(ic)))) {
996 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1000 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1002 emitcode("ld", "hl,%s", s);
1003 emitcode("push", "hl");
1009 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1010 emitcode("ld", "a,%s", l);
1011 emitcode("push", "af");
1012 emitcode("inc", "sp");
1016 freeAsmop(IC_LEFT(ic),NULL,ic);
1019 /*-----------------------------------------------------------------*/
1020 /* genIpop - recover the registers: can happen only for spilling */
1021 /*-----------------------------------------------------------------*/
1022 static void genIpop (iCode *ic)
1027 /* if the temp was not pushed then */
1028 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1031 aopOp(IC_LEFT(ic),ic,FALSE);
1032 size = AOP_SIZE(IC_LEFT(ic));
1034 if (isPair(AOP(IC_LEFT(ic)))) {
1035 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1039 emitcode("dec", "sp");
1040 emitcode("pop", "hl");
1041 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1045 freeAsmop(IC_LEFT(ic),NULL,ic);
1048 /** Emit the code for a call statement
1050 static void emitCall (iCode *ic, bool ispcall)
1052 /* if caller saves & we have not saved then */
1053 if (!ic->regsSaved) {
1057 /* if send set is not empty then assign */
1061 for (sic = setFirstItem(sendSet) ; sic ;
1062 sic = setNextItem(sendSet)) {
1063 int size, offset = 0;
1064 aopOp(IC_LEFT(sic),sic,FALSE);
1065 size = AOP_SIZE(IC_LEFT(sic));
1067 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1069 if (strcmp(l,fReturn[offset]))
1070 emitcode("ld","%s,%s",
1075 freeAsmop (IC_LEFT(sic),NULL,sic);
1081 symbol *rlbl = newiTempLabel(NULL);
1083 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1084 emitcode("push", "hl");
1086 aopOp(IC_LEFT(ic),ic,FALSE);
1087 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1088 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1089 freeAsmop(IC_LEFT(ic),NULL,ic);
1091 emitcode("jp", "(hl)");
1092 emitcode("","%05d$:",(rlbl->key+100));
1096 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1097 OP_SYMBOL(IC_LEFT(ic))->rname :
1098 OP_SYMBOL(IC_LEFT(ic))->name));
1101 /* if we need assign a result value */
1102 if ((IS_ITEMP(IC_RESULT(ic)) &&
1103 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1104 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1105 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1108 aopOp(IC_RESULT(ic),ic,FALSE);
1111 assignResultValue(IC_RESULT(ic));
1113 freeAsmop(IC_RESULT(ic),NULL, ic);
1116 /* adjust the stack for parameters if required */
1117 if (IC_LEFT(ic)->parmBytes) {
1118 int i = IC_LEFT(ic)->parmBytes;
1119 /* PENDING: do better */
1121 emitcode("pop", "hl");
1125 emitcode("inc", "sp");
1130 /*-----------------------------------------------------------------*/
1131 /* genCall - generates a call statement */
1132 /*-----------------------------------------------------------------*/
1133 static void genCall (iCode *ic)
1135 emitCall(ic, FALSE);
1138 /*-----------------------------------------------------------------*/
1139 /* genPcall - generates a call by pointer statement */
1140 /*-----------------------------------------------------------------*/
1141 static void genPcall (iCode *ic)
1146 /*-----------------------------------------------------------------*/
1147 /* resultRemat - result is rematerializable */
1148 /*-----------------------------------------------------------------*/
1149 static int resultRemat (iCode *ic)
1151 if (SKIP_IC(ic) || ic->op == IFX)
1154 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1155 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1156 if (sym->remat && !POINTER_SET(ic))
1163 /*-----------------------------------------------------------------*/
1164 /* genFunction - generated code for function entry */
1165 /*-----------------------------------------------------------------*/
1166 static void genFunction (iCode *ic)
1172 /* create the function header */
1173 emitcode(";","-----------------------------------------");
1174 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1175 emitcode(";","-----------------------------------------");
1177 emitcode("","%s:",sym->rname);
1178 fetype = getSpec(operandType(IC_LEFT(ic)));
1180 /* if critical function then turn interrupts off */
1181 if (SPEC_CRTCL(fetype))
1184 /* if this is an interrupt service routine then
1185 save acc, b, dpl, dph */
1186 if (IS_ISR(sym->etype)) {
1187 emitcode("push", "af");
1188 emitcode("push", "bc");
1189 emitcode("push", "de");
1190 emitcode("push", "hl");
1192 /* if callee-save to be used for this function
1193 then save the registers being used in this function */
1194 if (sym->calleeSave) {
1195 /* Handled by ncsv/csv */
1202 /* adjust the stack for the function */
1203 emitcode("push", "de");
1204 emitcode("push", "bc");
1205 emitcode("push", "ix");
1206 emitcode("ld", "ix,#0");
1207 emitcode("add", "ix,sp");
1209 _lastStack = sym->stack;
1212 emitcode("ld", "hl,#-%d", sym->stack);
1213 emitcode("add", "hl,sp");
1214 emitcode("ld", "sp,hl");
1218 /*-----------------------------------------------------------------*/
1219 /* genEndFunction - generates epilogue for functions */
1220 /*-----------------------------------------------------------------*/
1221 static void genEndFunction (iCode *ic)
1223 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1225 if (IS_ISR(sym->etype)) {
1229 if (SPEC_CRTCL(sym->etype))
1232 if (sym->calleeSave) {
1233 /* Handled by cret */
1239 /* if debug then send end of function */
1240 if (options.debug && currFunc) {
1242 emitcode("","C$%s$%d$%d$%d ==.",
1243 ic->filename,currFunc->lastLine,
1244 ic->level,ic->block);
1245 if (IS_STATIC(currFunc->etype))
1246 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1248 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1251 emitcode("ld", "sp,ix");
1252 emitcode("pop", "ix");
1253 emitcode("pop", "bc");
1254 emitcode("pop", "de");
1255 emitcode("ret", "");
1260 /*-----------------------------------------------------------------*/
1261 /* genRet - generate code for return statement */
1262 /*-----------------------------------------------------------------*/
1263 static void genRet (iCode *ic)
1266 /* Errk. This is a hack until I can figure out how
1267 to cause dehl to spill on a call */
1268 int size,offset = 0;
1270 /* if we have no return value then
1271 just generate the "ret" */
1275 /* we have something to return then
1276 move the return value into place */
1277 aopOp(IC_LEFT(ic),ic,FALSE);
1278 size = AOP_SIZE(IC_LEFT(ic));
1280 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1281 emitcode("ld", "hl,%s", l);
1285 l = aopGet(AOP(IC_LEFT(ic)),offset,
1287 if (strcmp(fReturn[offset],l))
1288 emitcode("ld","%s,%s",fReturn[offset++],l);
1291 freeAsmop (IC_LEFT(ic),NULL,ic);
1294 /* generate a jump to the return label
1295 if the next is not the return statement */
1296 if (!(ic->next && ic->next->op == LABEL &&
1297 IC_LABEL(ic->next) == returnLabel))
1299 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1302 /*-----------------------------------------------------------------*/
1303 /* genLabel - generates a label */
1304 /*-----------------------------------------------------------------*/
1305 static void genLabel (iCode *ic)
1307 /* special case never generate */
1308 if (IC_LABEL(ic) == entryLabel)
1311 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1314 /*-----------------------------------------------------------------*/
1315 /* genGoto - generates a ljmp */
1316 /*-----------------------------------------------------------------*/
1317 static void genGoto (iCode *ic)
1319 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1322 /*-----------------------------------------------------------------*/
1323 /* genPlusIncr :- does addition with increment if possible */
1324 /*-----------------------------------------------------------------*/
1325 static bool genPlusIncr (iCode *ic)
1327 unsigned int icount ;
1328 unsigned int size = getDataSize(IC_RESULT(ic));
1330 /* will try to generate an increment */
1331 /* if the right side is not a literal
1333 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1336 /* if the literal value of the right hand side
1337 is greater than 4 then it is not worth it */
1338 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1342 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1343 isPair(AOP(IC_RESULT(ic)))) {
1345 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1349 /* if increment 16 bits in register */
1350 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1353 symbol *tlbl = newiTempLabel(NULL);
1354 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1355 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1357 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1361 emitcode("", LABEL_STR ":",tlbl->key+100);
1365 /* If result is a pair */
1366 if (isPair(AOP(IC_RESULT(ic)))) {
1367 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1368 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1370 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1374 /* if the sizes are greater than 1 then we cannot */
1375 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1376 AOP_SIZE(IC_LEFT(ic)) > 1 )
1379 /* we can if the aops of the left & result match or
1380 if they are in registers and the registers are the
1382 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1384 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1392 /*-----------------------------------------------------------------*/
1393 /* outBitAcc - output a bit in acc */
1394 /*-----------------------------------------------------------------*/
1395 void outBitAcc(operand *result)
1397 symbol *tlbl = newiTempLabel(NULL);
1398 /* if the result is a bit */
1399 if (AOP_TYPE(result) == AOP_CRY){
1403 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1404 emitcode("ld","a,%s",one);
1405 emitcode("", LABEL_STR ":",tlbl->key+100);
1410 /*-----------------------------------------------------------------*/
1411 /* genPlus - generates code for addition */
1412 /*-----------------------------------------------------------------*/
1413 static void genPlus (iCode *ic)
1415 int size, offset = 0;
1417 /* special cases :- */
1419 aopOp (IC_LEFT(ic),ic,FALSE);
1420 aopOp (IC_RIGHT(ic),ic,FALSE);
1421 aopOp (IC_RESULT(ic),ic,TRUE);
1423 /* Swap the left and right operands if:
1425 if literal, literal on the right or
1426 if left requires ACC or right is already
1429 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1430 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1431 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1432 operand *t = IC_RIGHT(ic);
1433 IC_RIGHT(ic) = IC_LEFT(ic);
1437 /* if both left & right are in bit
1439 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1440 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1445 /* if left in bit space & right literal */
1446 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1447 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1448 /* Can happen I guess */
1452 /* if I can do an increment instead
1453 of add then GOOD for ME */
1454 if (genPlusIncr (ic) == TRUE)
1457 size = getDataSize(IC_RESULT(ic));
1460 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1461 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1463 emitcode("add","a,%s",
1464 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1466 emitcode("adc","a,%s",
1467 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1469 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1471 emitcode("add","a,%s",
1472 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1474 emitcode("adc","a,%s",
1475 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1477 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1480 /* Some kind of pointer arith. */
1481 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1482 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1483 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1486 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1487 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1488 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1493 freeAsmop(IC_LEFT(ic),NULL,ic);
1494 freeAsmop(IC_RIGHT(ic),NULL,ic);
1495 freeAsmop(IC_RESULT(ic),NULL,ic);
1499 /*-----------------------------------------------------------------*/
1500 /* genMinusDec :- does subtraction with deccrement if possible */
1501 /*-----------------------------------------------------------------*/
1502 static bool genMinusDec (iCode *ic)
1504 unsigned int icount ;
1505 unsigned int size = getDataSize(IC_RESULT(ic));
1507 /* will try to generate an increment */
1508 /* if the right side is not a literal we cannot */
1509 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1512 /* if the literal value of the right hand side
1513 is greater than 4 then it is not worth it */
1514 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1517 size = getDataSize(IC_RESULT(ic));
1518 /* if decrement 16 bits in register */
1519 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1520 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1522 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1526 /* If result is a pair */
1527 if (isPair(AOP(IC_RESULT(ic)))) {
1528 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1529 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1531 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1535 /* if the sizes are greater than 1 then we cannot */
1536 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1537 AOP_SIZE(IC_LEFT(ic)) > 1 )
1540 /* we can if the aops of the left & result match or if they are in
1541 registers and the registers are the same */
1542 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1544 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1551 /*-----------------------------------------------------------------*/
1552 /* genMinus - generates code for subtraction */
1553 /*-----------------------------------------------------------------*/
1554 static void genMinus (iCode *ic)
1556 int size, offset = 0;
1557 unsigned long lit = 0L;
1559 aopOp (IC_LEFT(ic),ic,FALSE);
1560 aopOp (IC_RIGHT(ic),ic,FALSE);
1561 aopOp (IC_RESULT(ic),ic,TRUE);
1563 /* special cases :- */
1564 /* if both left & right are in bit space */
1565 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1566 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1571 /* if I can do an decrement instead of subtract then GOOD for ME */
1572 if (genMinusDec (ic) == TRUE)
1575 size = getDataSize(IC_RESULT(ic));
1577 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1581 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1586 /* if literal, add a,#-lit, else normal subb */
1588 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1589 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1590 emitcode("sbc","a,%s",
1591 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1593 /* first add without previous c */
1595 emitcode("add","a,#0x%02x",
1596 (unsigned int)(lit & 0x0FFL));
1598 emitcode("adc","a,#0x%02x",
1599 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1601 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1604 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1605 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1606 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1610 freeAsmop(IC_LEFT(ic),NULL,ic);
1611 freeAsmop(IC_RIGHT(ic),NULL,ic);
1612 freeAsmop(IC_RESULT(ic),NULL,ic);
1615 /*-----------------------------------------------------------------*/
1616 /* genMult - generates code for multiplication */
1617 /*-----------------------------------------------------------------*/
1618 static void genMult (iCode *ic)
1620 /* Shouldn't occur - all done through function calls */
1624 /*-----------------------------------------------------------------*/
1625 /* genDiv - generates code for division */
1626 /*-----------------------------------------------------------------*/
1627 static void genDiv (iCode *ic)
1629 /* Shouldn't occur - all done through function calls */
1633 /*-----------------------------------------------------------------*/
1634 /* genMod - generates code for division */
1635 /*-----------------------------------------------------------------*/
1636 static void genMod (iCode *ic)
1638 /* Shouldn't occur - all done through function calls */
1642 /*-----------------------------------------------------------------*/
1643 /* genIfxJump :- will create a jump depending on the ifx */
1644 /*-----------------------------------------------------------------*/
1645 static void genIfxJump (iCode *ic, char *jval)
1650 /* if true label then we jump if condition
1652 if ( IC_TRUE(ic) ) {
1654 if (!strcmp(jval, "a")) {
1657 else if (!strcmp(jval, "c")) {
1661 /* The buffer contains the bit on A that we should test */
1666 /* false label is present */
1667 jlbl = IC_FALSE(ic) ;
1668 if (!strcmp(jval, "a")) {
1671 else if (!strcmp(jval, "c")) {
1675 /* The buffer contains the bit on A that we should test */
1679 /* Z80 can do a conditional long jump */
1680 if (!strcmp(jval, "a")) {
1681 emitcode("or", "a,a");
1683 else if (!strcmp(jval, "c")) {
1686 emitcode("bit", "%s,a", jval);
1688 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1690 /* mark the icode as generated */
1694 /** Generic compare for > or <
1696 static void genCmp (operand *left,operand *right,
1697 operand *result, iCode *ifx, int sign)
1699 int size, offset = 0 ;
1700 unsigned long lit = 0L;
1702 /* if left & right are bit variables */
1703 if (AOP_TYPE(left) == AOP_CRY &&
1704 AOP_TYPE(right) == AOP_CRY ) {
1705 /* Cant happen on the Z80 */
1708 /* subtract right from left if at the
1709 end the carry flag is set then we know that
1710 left is greater than right */
1711 size = max(AOP_SIZE(left),AOP_SIZE(right));
1713 /* if unsigned char cmp with lit, just compare */
1714 if((size == 1) && !sign &&
1715 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1716 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1717 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1720 if(AOP_TYPE(right) == AOP_LIT) {
1721 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1722 /* optimize if(x < 0) or if(x >= 0) */
1725 /* No sign so it's always false */
1729 /* Just load in the top most bit */
1730 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1731 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1733 genIfxJump (ifx,"acc.7");
1737 emitcode("rlc","a");
1743 /* Do a long subtract */
1744 MOVA(aopGet(AOP(left),offset,FALSE));
1745 if (sign && size == 0) {
1746 /* Case where it's signed and we've hit the end */
1749 /* Subtract through, propagating the carry */
1751 emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1754 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1761 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1764 /* if the result is used in the next
1765 ifx conditional branch then generate
1766 code a little differently */
1768 genIfxJump (ifx,"c");
1771 /* leave the result in acc */
1775 /*-----------------------------------------------------------------*/
1776 /* genCmpGt :- greater than comparison */
1777 /*-----------------------------------------------------------------*/
1778 static void genCmpGt (iCode *ic, iCode *ifx)
1780 operand *left, *right, *result;
1781 link *letype , *retype;
1785 right= IC_RIGHT(ic);
1786 result = IC_RESULT(ic);
1788 letype = getSpec(operandType(left));
1789 retype =getSpec(operandType(right));
1790 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1791 /* assign the amsops */
1792 aopOp (left,ic,FALSE);
1793 aopOp (right,ic,FALSE);
1794 aopOp (result,ic,TRUE);
1796 genCmp(right, left, result, ifx, sign);
1798 freeAsmop(left,NULL,ic);
1799 freeAsmop(right,NULL,ic);
1800 freeAsmop(result,NULL,ic);
1803 /*-----------------------------------------------------------------*/
1804 /* genCmpLt - less than comparisons */
1805 /*-----------------------------------------------------------------*/
1806 static void genCmpLt (iCode *ic, iCode *ifx)
1808 operand *left, *right, *result;
1809 link *letype , *retype;
1813 right= IC_RIGHT(ic);
1814 result = IC_RESULT(ic);
1816 letype = getSpec(operandType(left));
1817 retype =getSpec(operandType(right));
1818 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1820 /* assign the amsops */
1821 aopOp (left,ic,FALSE);
1822 aopOp (right,ic,FALSE);
1823 aopOp (result,ic,TRUE);
1825 genCmp(left, right, result, ifx, sign);
1827 freeAsmop(left,NULL,ic);
1828 freeAsmop(right,NULL,ic);
1829 freeAsmop(result,NULL,ic);
1832 /*-----------------------------------------------------------------*/
1833 /* gencjneshort - compare and jump if not equal */
1834 /*-----------------------------------------------------------------*/
1835 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1837 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1839 unsigned long lit = 0L;
1841 /* Swap the left and right if it makes the computation easier */
1842 if (AOP_TYPE(left) == AOP_LIT) {
1848 if(AOP_TYPE(right) == AOP_LIT)
1849 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1851 /* if the right side is a literal then anything goes */
1852 if (AOP_TYPE(right) == AOP_LIT &&
1853 AOP_TYPE(left) != AOP_DIR ) {
1855 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1856 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1857 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1861 /* if the right side is in a register or in direct space or
1862 if the left is a pointer register & right is not */
1863 else if (AOP_TYPE(right) == AOP_REG ||
1864 AOP_TYPE(right) == AOP_DIR ||
1865 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1867 MOVA(aopGet(AOP(left),offset,FALSE));
1868 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1869 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1871 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1873 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1874 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1883 /*-----------------------------------------------------------------*/
1884 /* gencjne - compare and jump if not equal */
1885 /*-----------------------------------------------------------------*/
1886 static void gencjne(operand *left, operand *right, symbol *lbl)
1888 symbol *tlbl = newiTempLabel(NULL);
1890 gencjneshort(left, right, lbl);
1893 emitcode("ld","a,%s",one);
1894 emitcode("jp", LABEL_STR ,tlbl->key+100);
1895 emitcode("", LABEL_STR ":",lbl->key+100);
1896 emitcode("xor","a,a");
1897 emitcode("", LABEL_STR ":",tlbl->key+100);
1900 /*-----------------------------------------------------------------*/
1901 /* genCmpEq - generates code for equal to */
1902 /*-----------------------------------------------------------------*/
1903 static void genCmpEq (iCode *ic, iCode *ifx)
1905 operand *left, *right, *result;
1907 aopOp((left=IC_LEFT(ic)),ic,FALSE);
1908 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1909 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1911 /* Swap operands if it makes the operation easier. ie if:
1912 1. Left is a literal.
1914 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1915 operand *t = IC_RIGHT(ic);
1916 IC_RIGHT(ic) = IC_LEFT(ic);
1920 if (ifx && !AOP_SIZE(result)){
1922 /* if they are both bit variables */
1923 if (AOP_TYPE(left) == AOP_CRY &&
1924 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1927 tlbl = newiTempLabel(NULL);
1928 gencjneshort(left, right, tlbl);
1929 if ( IC_TRUE(ifx) ) {
1930 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1931 emitcode("", LABEL_STR ":",tlbl->key+100);
1933 /* PENDING: do this better */
1934 symbol *lbl = newiTempLabel(NULL);
1935 emitcode("jp", LABEL_STR ,lbl->key+100);
1936 emitcode("", LABEL_STR ":",tlbl->key+100);
1937 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1938 emitcode("", LABEL_STR ":",lbl->key+100);
1941 /* mark the icode as generated */
1946 /* if they are both bit variables */
1947 if (AOP_TYPE(left) == AOP_CRY &&
1948 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1951 gencjne(left,right,newiTempLabel(NULL));
1952 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1956 genIfxJump(ifx,"a");
1959 /* if the result is used in an arithmetic operation
1960 then put the result in place */
1961 if (AOP_TYPE(result) != AOP_CRY) {
1964 /* leave the result in acc */
1968 freeAsmop(left,NULL,ic);
1969 freeAsmop(right,NULL,ic);
1970 freeAsmop(result,NULL,ic);
1973 /*-----------------------------------------------------------------*/
1974 /* ifxForOp - returns the icode containing the ifx for operand */
1975 /*-----------------------------------------------------------------*/
1976 static iCode *ifxForOp ( operand *op, iCode *ic )
1978 /* if true symbol then needs to be assigned */
1979 if (IS_TRUE_SYMOP(op))
1982 /* if this has register type condition and
1983 the next instruction is ifx with the same operand
1984 and live to of the operand is upto the ifx only then */
1986 ic->next->op == IFX &&
1987 IC_COND(ic->next)->key == op->key &&
1988 OP_SYMBOL(op)->liveTo <= ic->next->seq )
1994 /*-----------------------------------------------------------------*/
1995 /* genAndOp - for && operation */
1996 /*-----------------------------------------------------------------*/
1997 static void genAndOp (iCode *ic)
1999 operand *left,*right, *result;
2002 /* note here that && operations that are in an if statement are
2003 taken away by backPatchLabels only those used in arthmetic
2004 operations remain */
2005 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2006 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2007 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2009 /* if both are bit variables */
2010 if (AOP_TYPE(left) == AOP_CRY &&
2011 AOP_TYPE(right) == AOP_CRY ) {
2014 tlbl = newiTempLabel(NULL);
2016 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2018 emitcode("", LABEL_STR ":",tlbl->key+100);
2022 freeAsmop(left,NULL,ic);
2023 freeAsmop(right,NULL,ic);
2024 freeAsmop(result,NULL,ic);
2027 /*-----------------------------------------------------------------*/
2028 /* genOrOp - for || operation */
2029 /*-----------------------------------------------------------------*/
2030 static void genOrOp (iCode *ic)
2032 operand *left,*right, *result;
2035 /* note here that || operations that are in an
2036 if statement are taken away by backPatchLabels
2037 only those used in arthmetic operations remain */
2038 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2039 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2040 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2042 /* if both are bit variables */
2043 if (AOP_TYPE(left) == AOP_CRY &&
2044 AOP_TYPE(right) == AOP_CRY ) {
2047 tlbl = newiTempLabel(NULL);
2049 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2051 emitcode("", LABEL_STR,tlbl->key+100);
2055 freeAsmop(left,NULL,ic);
2056 freeAsmop(right,NULL,ic);
2057 freeAsmop(result,NULL,ic);
2060 /*-----------------------------------------------------------------*/
2061 /* isLiteralBit - test if lit == 2^n */
2062 /*-----------------------------------------------------------------*/
2063 int isLiteralBit(unsigned long lit)
2065 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2066 0x100L,0x200L,0x400L,0x800L,
2067 0x1000L,0x2000L,0x4000L,0x8000L,
2068 0x10000L,0x20000L,0x40000L,0x80000L,
2069 0x100000L,0x200000L,0x400000L,0x800000L,
2070 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2071 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2074 for(idx = 0; idx < 32; idx++)
2080 /*-----------------------------------------------------------------*/
2081 /* genAnd - code for and */
2082 /*-----------------------------------------------------------------*/
2083 static void genAnd (iCode *ic, iCode *ifx)
2085 operand *left, *right, *result;
2087 unsigned long lit = 0L;
2090 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2091 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2092 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2095 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2097 AOP_TYPE(left), AOP_TYPE(right));
2098 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2100 AOP_SIZE(left), AOP_SIZE(right));
2103 /* if left is a literal & right is not then exchange them */
2104 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2105 AOP_NEEDSACC(left)) {
2106 operand *tmp = right ;
2111 /* if result = right then exchange them */
2112 if(sameRegs(AOP(result),AOP(right))){
2113 operand *tmp = right ;
2118 /* if right is bit then exchange them */
2119 if (AOP_TYPE(right) == AOP_CRY &&
2120 AOP_TYPE(left) != AOP_CRY){
2121 operand *tmp = right ;
2125 if(AOP_TYPE(right) == AOP_LIT)
2126 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2128 size = AOP_SIZE(result);
2130 if (AOP_TYPE(left) == AOP_CRY){
2135 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2136 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2137 if((AOP_TYPE(right) == AOP_LIT) &&
2138 (AOP_TYPE(result) == AOP_CRY) &&
2139 (AOP_TYPE(left) != AOP_CRY)) {
2140 int posbit = isLiteralBit(lit);
2144 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2148 emitcode("mov","c,acc.%d",posbit&0x07);
2153 sprintf(buffer, "%d", posbit&0x07);
2154 genIfxJump(ifx, buffer);
2162 symbol *tlbl = newiTempLabel(NULL);
2163 int sizel = AOP_SIZE(left);
2166 emitcode("setb","c");
2169 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2170 MOVA( aopGet(AOP(left),offset,FALSE));
2172 if((posbit = isLiteralBit(bytelit)) != 0) {
2174 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2177 if(bytelit != 0x0FFL)
2178 emitcode("and","a,%s",
2179 aopGet(AOP(right),offset,FALSE));
2180 emitcode("jr","nz, %05d$",tlbl->key+100);
2185 // bit = left & literal
2187 emitcode("clr","c");
2188 emitcode("","%05d$:",tlbl->key+100);
2190 // if(left & literal)
2194 jmpTrueOrFalse(ifx, tlbl);
2205 /* if left is same as result */
2206 if(sameRegs(AOP(result),AOP(left))){
2207 for(;size--; offset++) {
2208 if(AOP_TYPE(right) == AOP_LIT){
2209 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2213 aopPut(AOP(result),zero,offset);
2215 MOVA(aopGet(AOP(left),offset,FALSE));
2216 emitcode("and","a,%s",
2217 aopGet(AOP(right),offset,FALSE));
2218 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2223 if (AOP_TYPE(left) == AOP_ACC) {
2227 MOVA(aopGet(AOP(right),offset,FALSE));
2228 emitcode("and","%s,a",
2229 aopGet(AOP(left),offset,FALSE));
2234 // left & result in different registers
2235 if(AOP_TYPE(result) == AOP_CRY){
2238 for(;(size--);offset++) {
2240 // result = left & right
2241 if(AOP_TYPE(right) == AOP_LIT){
2242 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2244 aopGet(AOP(left),offset,FALSE),
2247 } else if(bytelit == 0){
2248 aopPut(AOP(result),zero,offset);
2252 // faster than result <- left, anl result,right
2253 // and better if result is SFR
2254 if (AOP_TYPE(left) == AOP_ACC)
2255 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2257 MOVA(aopGet(AOP(right),offset,FALSE));
2258 emitcode("and","a,%s",
2259 aopGet(AOP(left),offset,FALSE));
2261 aopPut(AOP(result),"a",offset);
2268 freeAsmop(left,NULL,ic);
2269 freeAsmop(right,NULL,ic);
2270 freeAsmop(result,NULL,ic);
2273 /*-----------------------------------------------------------------*/
2274 /* genOr - code for or */
2275 /*-----------------------------------------------------------------*/
2276 static void genOr (iCode *ic, iCode *ifx)
2278 operand *left, *right, *result;
2280 unsigned long lit = 0L;
2282 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2283 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2284 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2287 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2289 AOP_TYPE(left), AOP_TYPE(right));
2290 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2292 AOP_SIZE(left), AOP_SIZE(right));
2295 /* if left is a literal & right is not then exchange them */
2296 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2297 AOP_NEEDSACC(left)) {
2298 operand *tmp = right ;
2303 /* if result = right then exchange them */
2304 if(sameRegs(AOP(result),AOP(right))){
2305 operand *tmp = right ;
2310 /* if right is bit then exchange them */
2311 if (AOP_TYPE(right) == AOP_CRY &&
2312 AOP_TYPE(left) != AOP_CRY){
2313 operand *tmp = right ;
2317 if(AOP_TYPE(right) == AOP_LIT)
2318 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2320 size = AOP_SIZE(result);
2322 if (AOP_TYPE(left) == AOP_CRY){
2327 if((AOP_TYPE(right) == AOP_LIT) &&
2328 (AOP_TYPE(result) == AOP_CRY) &&
2329 (AOP_TYPE(left) != AOP_CRY)){
2334 /* if left is same as result */
2335 if(sameRegs(AOP(result),AOP(left))){
2336 for(;size--; offset++) {
2337 if(AOP_TYPE(right) == AOP_LIT){
2338 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2341 emitcode("or","%s,%s",
2342 aopGet(AOP(left),offset,FALSE),
2343 aopGet(AOP(right),offset,FALSE));
2345 if (AOP_TYPE(left) == AOP_ACC)
2346 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2348 MOVA(aopGet(AOP(right),offset,FALSE));
2349 emitcode("or","a,%s",
2350 aopGet(AOP(left),offset,FALSE));
2351 aopPut(AOP(result),"a",0);
2356 // left & result in different registers
2357 if(AOP_TYPE(result) == AOP_CRY){
2359 } else for(;(size--);offset++){
2361 // result = left & right
2362 if(AOP_TYPE(right) == AOP_LIT){
2363 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2365 aopGet(AOP(left),offset,FALSE),
2370 // faster than result <- left, anl result,right
2371 // and better if result is SFR
2372 if (AOP_TYPE(left) == AOP_ACC)
2373 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2375 MOVA(aopGet(AOP(right),offset,FALSE));
2376 emitcode("or","a,%s",
2377 aopGet(AOP(left),offset,FALSE));
2378 aopPut(AOP(result),"a",0);
2380 aopPut(AOP(result),"a",offset);
2385 freeAsmop(left,NULL,ic);
2386 freeAsmop(right,NULL,ic);
2387 freeAsmop(result,NULL,ic);
2390 /*-----------------------------------------------------------------*/
2391 /* genXor - code for xclusive or */
2392 /*-----------------------------------------------------------------*/
2393 static void genXor (iCode *ic, iCode *ifx)
2395 operand *left, *right, *result;
2397 unsigned long lit = 0L;
2399 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2400 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2401 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2403 /* if left is a literal & right is not then exchange them */
2404 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2405 AOP_NEEDSACC(left)) {
2406 operand *tmp = right ;
2411 /* if result = right then exchange them */
2412 if(sameRegs(AOP(result),AOP(right))){
2413 operand *tmp = right ;
2418 /* if right is bit then exchange them */
2419 if (AOP_TYPE(right) == AOP_CRY &&
2420 AOP_TYPE(left) != AOP_CRY){
2421 operand *tmp = right ;
2425 if(AOP_TYPE(right) == AOP_LIT)
2426 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2428 size = AOP_SIZE(result);
2430 if (AOP_TYPE(left) == AOP_CRY){
2435 if((AOP_TYPE(right) == AOP_LIT) &&
2436 (AOP_TYPE(result) == AOP_CRY) &&
2437 (AOP_TYPE(left) != AOP_CRY)){
2442 /* if left is same as result */
2443 if(sameRegs(AOP(result),AOP(left))){
2444 for(;size--; offset++) {
2445 if(AOP_TYPE(right) == AOP_LIT){
2446 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2449 MOVA(aopGet(AOP(right),offset,FALSE));
2450 emitcode("xor","a,%s",
2451 aopGet(AOP(left),offset,FALSE));
2452 aopPut(AOP(result),"a",0);
2455 if (AOP_TYPE(left) == AOP_ACC)
2456 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2458 MOVA(aopGet(AOP(right),offset,FALSE));
2459 emitcode("xor","a,%s",
2460 aopGet(AOP(left),offset,FALSE));
2461 aopPut(AOP(result),"a",0);
2466 // left & result in different registers
2467 if(AOP_TYPE(result) == AOP_CRY){
2469 } else for(;(size--);offset++){
2471 // result = left & right
2472 if(AOP_TYPE(right) == AOP_LIT){
2473 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2475 aopGet(AOP(left),offset,FALSE),
2480 // faster than result <- left, anl result,right
2481 // and better if result is SFR
2482 if (AOP_TYPE(left) == AOP_ACC)
2483 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2485 MOVA(aopGet(AOP(right),offset,FALSE));
2486 emitcode("xor","a,%s",
2487 aopGet(AOP(left),offset,FALSE));
2488 aopPut(AOP(result),"a",0);
2490 aopPut(AOP(result),"a",offset);
2495 freeAsmop(left,NULL,ic);
2496 freeAsmop(right,NULL,ic);
2497 freeAsmop(result,NULL,ic);
2500 /*-----------------------------------------------------------------*/
2501 /* genInline - write the inline code out */
2502 /*-----------------------------------------------------------------*/
2503 static void genInline (iCode *ic)
2505 char buffer[MAX_INLINEASM];
2509 inLine += (!options.asmpeep);
2510 strcpy(buffer,IC_INLINE(ic));
2512 /* emit each line as a code */
2531 /* emitcode("",buffer); */
2532 inLine -= (!options.asmpeep);
2535 /*-----------------------------------------------------------------*/
2536 /* genRRC - rotate right with carry */
2537 /*-----------------------------------------------------------------*/
2538 static void genRRC (iCode *ic)
2543 /*-----------------------------------------------------------------*/
2544 /* genRLC - generate code for rotate left with carry */
2545 /*-----------------------------------------------------------------*/
2546 static void genRLC (iCode *ic)
2551 /*-----------------------------------------------------------------*/
2552 /* shiftR2Left2Result - shift right two bytes from left to result */
2553 /*-----------------------------------------------------------------*/
2554 static void shiftR2Left2Result (operand *left, int offl,
2555 operand *result, int offr,
2556 int shCount, int sign)
2558 if(sameRegs(AOP(result), AOP(left)) &&
2559 ((offl + MSB16) == offr)){
2562 movLeft2Result(left, offl, result, offr, 0);
2563 movLeft2Result(left, offl+1, result, offr+1, 0);
2570 /* if (AOP(result)->type == AOP_REG) {*/
2573 symbol *tlbl , *tlbl1;
2576 /* Left is already in result - so now do the shift */
2578 emitcode("ld","a,#%u+1", shCount);
2579 tlbl = newiTempLabel(NULL);
2580 tlbl1 = newiTempLabel(NULL);
2581 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2582 emitcode("", LABEL_STR ":",tlbl->key+100);
2585 emitcode("or", "a,a");
2588 l = aopGet(AOP(result), --offset, FALSE);
2589 emitcode("rr","%s", l);
2592 emitcode("", LABEL_STR ":",tlbl1->key+100);
2593 emitcode("dec", "a");
2594 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2599 /*-----------------------------------------------------------------*/
2600 /* shiftL2Left2Result - shift left two bytes from left to result */
2601 /*-----------------------------------------------------------------*/
2602 static void shiftL2Left2Result (operand *left, int offl,
2603 operand *result, int offr, int shCount)
2605 if(sameRegs(AOP(result), AOP(left)) &&
2606 ((offl + MSB16) == offr)){
2609 /* Copy left into result */
2610 movLeft2Result(left,offl, result, offr, 0);
2612 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);
2639 /* PENDING: do something */
2644 /*-----------------------------------------------------------------*/
2645 /* AccRol - rotate left accumulator by known count */
2646 /*-----------------------------------------------------------------*/
2647 static void AccRol (int shCount)
2649 shCount &= 0x0007; // shCount : 0..7
2686 /*-----------------------------------------------------------------*/
2687 /* AccLsh - left shift accumulator by known count */
2688 /*-----------------------------------------------------------------*/
2689 static void AccLsh (int shCount)
2693 emitcode("add","a,a");
2696 emitcode("add","a,a");
2697 emitcode("add","a,a");
2699 /* rotate left accumulator */
2701 /* and kill the lower order bits */
2702 emitcode("and","a,#0x%02x", SLMask[shCount]);
2707 /*-----------------------------------------------------------------*/
2708 /* shiftL1Left2Result - shift left one byte from left to result */
2709 /*-----------------------------------------------------------------*/
2710 static void shiftL1Left2Result (operand *left, int offl,
2711 operand *result, int offr, int shCount)
2714 l = aopGet(AOP(left),offl,FALSE);
2716 /* shift left accumulator */
2718 aopPut(AOP(result),"a",offr);
2722 /*-----------------------------------------------------------------*/
2723 /* genlshTwo - left shift two bytes by known amount != 0 */
2724 /*-----------------------------------------------------------------*/
2725 static void genlshTwo (operand *result,operand *left, int shCount)
2727 int size = AOP_SIZE(result);
2731 /* if shCount >= 8 */
2737 movLeft2Result(left, LSB, result, MSB16, 0);
2738 aopPut(AOP(result),zero, 0);
2739 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2742 movLeft2Result(left, LSB, result, MSB16, 0);
2743 aopPut(AOP(result),zero, 0);
2746 aopPut(AOP(result),zero,LSB);
2748 /* 1 <= shCount <= 7 */
2754 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2759 /*-----------------------------------------------------------------*/
2760 /* genlshOne - left shift a one byte quantity by known count */
2761 /*-----------------------------------------------------------------*/
2762 static void genlshOne (operand *result, operand *left, int shCount)
2764 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2767 /*-----------------------------------------------------------------*/
2768 /* genLeftShiftLiteral - left shifting by known count */
2769 /*-----------------------------------------------------------------*/
2770 static void genLeftShiftLiteral (operand *left,
2775 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2778 freeAsmop(right,NULL,ic);
2780 aopOp(left,ic,FALSE);
2781 aopOp(result,ic,FALSE);
2783 size = getSize(operandType(result));
2786 emitcode("; shift left ","result %d, left %d",size,
2790 /* I suppose that the left size >= result size */
2795 else if(shCount >= (size * 8))
2797 aopPut(AOP(result),zero,size);
2801 genlshOne (result,left,shCount);
2804 genlshTwo (result,left,shCount);
2813 freeAsmop(left,NULL,ic);
2814 freeAsmop(result,NULL,ic);
2817 /*-----------------------------------------------------------------*/
2818 /* genLeftShift - generates code for left shifting */
2819 /*-----------------------------------------------------------------*/
2820 static void genLeftShift (iCode *ic)
2824 symbol *tlbl , *tlbl1;
2825 operand *left,*right, *result;
2827 right = IC_RIGHT(ic);
2829 result = IC_RESULT(ic);
2831 aopOp(right,ic,FALSE);
2833 /* if the shift count is known then do it
2834 as efficiently as possible */
2835 if (AOP_TYPE(right) == AOP_LIT) {
2836 genLeftShiftLiteral (left,right,result,ic);
2840 /* shift count is unknown then we have to form a loop get the loop
2841 count in B : Note: we take only the lower order byte since
2842 shifting more that 32 bits make no sense anyway, ( the largest
2843 size of an object can be only 32 bits ) */
2844 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2845 emitcode("inc","a");
2846 freeAsmop (right,NULL,ic);
2847 aopOp(left,ic,FALSE);
2848 aopOp(result,ic,FALSE);
2850 /* now move the left to the result if they are not the
2853 if (!sameRegs(AOP(left),AOP(result))) {
2855 size = AOP_SIZE(result);
2858 l = aopGet(AOP(left),offset,FALSE);
2859 aopPut(AOP(result),l,offset);
2864 size = AOP_SIZE(result);
2867 l = aopGet(AOP(left),offset,FALSE);
2868 aopPut(AOP(result),l,offset);
2874 tlbl = newiTempLabel(NULL);
2875 size = AOP_SIZE(result);
2877 tlbl1 = newiTempLabel(NULL);
2879 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2880 emitcode("", LABEL_STR ":",tlbl->key+100);
2881 l = aopGet(AOP(result),offset,FALSE);
2882 emitcode("or", "a,a");
2884 l = aopGet(AOP(result),offset++,FALSE);
2885 emitcode("rl","%s", l);
2887 emitcode("", LABEL_STR ":",tlbl1->key+100);
2888 emitcode("dec", "a");
2889 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2891 freeAsmop(left,NULL,ic);
2892 freeAsmop(result,NULL,ic);
2895 /* genlshTwo - left shift two bytes by known amount != 0 */
2896 /*-----------------------------------------------------------------*/
2897 static void genrshOne (operand *result,operand *left, int shCount)
2900 int size = AOP_SIZE(result);
2906 l = aopGet(AOP(left),0,FALSE);
2907 if (AOP(result)->type == AOP_REG) {
2908 aopPut(AOP(result), l, 0);
2909 l = aopGet(AOP(result), 0, FALSE);
2911 emitcode("srl", "%s", l);
2916 emitcode("srl", "a");
2918 aopPut(AOP(result),"a",0);
2922 /*-----------------------------------------------------------------*/
2923 /* AccRsh - right shift accumulator by known count */
2924 /*-----------------------------------------------------------------*/
2925 static void AccRsh (int shCount)
2932 /* rotate right accumulator */
2933 AccRol(8 - shCount);
2934 /* and kill the higher order bits */
2935 emitcode("and","a,#0x%02x", SRMask[shCount]);
2940 /*-----------------------------------------------------------------*/
2941 /* shiftR1Left2Result - shift right one byte from left to result */
2942 /*-----------------------------------------------------------------*/
2943 static void shiftR1Left2Result (operand *left, int offl,
2944 operand *result, int offr,
2945 int shCount, int sign)
2947 MOVA(aopGet(AOP(left),offl,FALSE));
2954 aopPut(AOP(result),"a",offr);
2957 /*-----------------------------------------------------------------*/
2958 /* genrshTwo - right shift two bytes by known amount != 0 */
2959 /*-----------------------------------------------------------------*/
2960 static void genrshTwo (operand *result,operand *left,
2961 int shCount, int sign)
2963 /* if shCount >= 8 */
2968 shiftR1Left2Result(left, MSB16, result, LSB,
2972 movLeft2Result(left, MSB16, result, LSB, sign);
2973 aopPut(AOP(result),zero,1);
2976 /* 1 <= shCount <= 7 */
2978 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
2982 /*-----------------------------------------------------------------*/
2983 /* genRightShiftLiteral - left shifting by known count */
2984 /*-----------------------------------------------------------------*/
2985 static void genRightShiftLiteral (operand *left,
2990 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2993 freeAsmop(right,NULL,ic);
2995 aopOp(left,ic,FALSE);
2996 aopOp(result,ic,FALSE);
2998 size = getSize(operandType(result));
3000 emitcode("; shift right ","result %d, left %d",size,
3003 /* I suppose that the left size >= result size */
3008 else if(shCount >= (size * 8))
3010 aopPut(AOP(result),zero,size);
3014 genrshOne(result, left, shCount);
3017 /* PENDING: sign support */
3018 genrshTwo(result, left, shCount, FALSE);
3027 freeAsmop(left,NULL,ic);
3028 freeAsmop(result,NULL,ic);
3031 /*-----------------------------------------------------------------*/
3032 /* genRightShift - generate code for right shifting */
3033 /*-----------------------------------------------------------------*/
3034 static void genRightShift (iCode *ic)
3036 operand *left,*right, *result;
3038 right = IC_RIGHT(ic);
3040 result = IC_RESULT(ic);
3042 aopOp(right,ic,FALSE);
3044 /* if the shift count is known then do it
3045 as efficiently as possible */
3046 if (AOP_TYPE(right) == AOP_LIT) {
3047 genRightShiftLiteral (left,right,result,ic);
3055 /*-----------------------------------------------------------------*/
3056 /* genGenPointerGet - gget value from generic pointer space */
3057 /*-----------------------------------------------------------------*/
3058 static void genGenPointerGet (operand *left,
3059 operand *result, iCode *ic)
3062 link *retype = getSpec(operandType(result));
3064 aopOp(left,ic,FALSE);
3065 aopOp(result,ic,FALSE);
3067 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3069 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3070 aopPut(AOP(result),"a", 0);
3071 freeAsmop(left,NULL,ic);
3075 /* For now we always load into IY */
3076 /* if this is remateriazable */
3077 if (AOP_TYPE(left) == AOP_IMMD)
3078 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3079 else { /* we need to get it byte by byte */
3080 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3081 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3083 /* so iy now contains the address */
3084 freeAsmop(left,NULL,ic);
3086 /* if bit then unpack */
3087 if (IS_BITVAR(retype)) {
3091 size = AOP_SIZE(result);
3095 /* PENDING: make this better */
3096 if (AOP(result)->type == AOP_REG) {
3097 aopPut(AOP(result),"(hl)",offset++);
3100 emitcode("ld", "a,(hl)", offset);
3101 aopPut(AOP(result),"a",offset++);
3104 emitcode("inc", "hl");
3110 freeAsmop(result,NULL,ic);
3113 /*-----------------------------------------------------------------*/
3114 /* genPointerGet - generate code for pointer get */
3115 /*-----------------------------------------------------------------*/
3116 static void genPointerGet (iCode *ic)
3118 operand *left, *result ;
3122 result = IC_RESULT(ic) ;
3124 /* depending on the type of pointer we need to
3125 move it to the correct pointer register */
3126 type = operandType(left);
3127 etype = getSpec(type);
3129 genGenPointerGet (left,result,ic);
3132 bool isRegOrLit(asmop *aop)
3134 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3139 /*-----------------------------------------------------------------*/
3140 /* genGenPointerSet - stores the value into a pointer location */
3141 /*-----------------------------------------------------------------*/
3142 static void genGenPointerSet (operand *right,
3143 operand *result, iCode *ic)
3146 link *retype = getSpec(operandType(right));
3148 aopOp(result,ic,FALSE);
3149 aopOp(right,ic,FALSE);
3151 /* Handle the exceptions first */
3152 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3154 char *l = aopGet(AOP(right), 0, FALSE);
3156 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3157 freeAsmop(result,NULL,ic);
3161 /* if the operand is already in dptr
3162 then we do nothing else we move the value to dptr */
3163 if (AOP_TYPE(result) != AOP_STR) {
3164 /* if this is remateriazable */
3165 if (AOP_TYPE(result) == AOP_IMMD) {
3166 emitcode("", "; Error 2");
3167 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3169 else { /* we need to get it byte by byte */
3170 /* PENDING: do this better */
3171 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3172 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3175 /* so hl know contains the address */
3176 freeAsmop(result,NULL,ic);
3178 /* if bit then unpack */
3179 if (IS_BITVAR(retype)) {
3183 size = AOP_SIZE(right);
3187 char *l = aopGet(AOP(right),offset,FALSE);
3189 if (isRegOrLit(AOP(right))) {
3190 emitcode("ld", "(hl),%s", l);
3194 emitcode("ld", "(hl),a", offset);
3197 emitcode("inc", "hl");
3203 freeAsmop(right,NULL,ic);
3206 /*-----------------------------------------------------------------*/
3207 /* genPointerSet - stores the value into a pointer location */
3208 /*-----------------------------------------------------------------*/
3209 static void genPointerSet (iCode *ic)
3211 operand *right, *result ;
3214 right = IC_RIGHT(ic);
3215 result = IC_RESULT(ic) ;
3217 /* depending on the type of pointer we need to
3218 move it to the correct pointer register */
3219 type = operandType(result);
3220 etype = getSpec(type);
3222 genGenPointerSet (right,result,ic);
3225 /*-----------------------------------------------------------------*/
3226 /* genIfx - generate code for Ifx statement */
3227 /*-----------------------------------------------------------------*/
3228 static void genIfx (iCode *ic, iCode *popIc)
3230 operand *cond = IC_COND(ic);
3233 aopOp(cond,ic,FALSE);
3235 /* get the value into acc */
3236 if (AOP_TYPE(cond) != AOP_CRY)
3240 /* the result is now in the accumulator */
3241 freeAsmop(cond,NULL,ic);
3243 /* if there was something to be popped then do it */
3247 /* if the condition is a bit variable */
3248 if (isbit && IS_ITEMP(cond) &&
3250 genIfxJump(ic,SPIL_LOC(cond)->rname);
3252 if (isbit && !IS_ITEMP(cond))
3253 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3260 /*-----------------------------------------------------------------*/
3261 /* genAddrOf - generates code for address of */
3262 /*-----------------------------------------------------------------*/
3263 static void genAddrOf (iCode *ic)
3265 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3267 aopOp(IC_RESULT(ic),ic,FALSE);
3269 /* if the operand is on the stack then we
3270 need to get the stack offset of this
3273 /* if it has an offset then we need to compute it */
3274 emitcode("push", "de");
3275 emitcode("push", "ix");
3276 emitcode("pop", "hl");
3277 emitcode("ld", "de,#%d", sym->stack);
3278 emitcode("add", "hl,de");
3279 emitcode("pop", "de");
3282 emitcode("ld", "hl,#%s", sym->rname);
3284 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3285 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3287 freeAsmop(IC_RESULT(ic),NULL,ic);
3290 /*-----------------------------------------------------------------*/
3291 /* genAssign - generate code for assignment */
3292 /*-----------------------------------------------------------------*/
3293 static void genAssign (iCode *ic)
3295 operand *result, *right;
3297 unsigned long lit = 0L;
3299 result = IC_RESULT(ic);
3300 right = IC_RIGHT(ic) ;
3302 /* Dont bother assigning if they are the same */
3303 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3304 emitcode("", "; (operands are equal)");
3308 aopOp(right,ic,FALSE);
3309 aopOp(result,ic,TRUE);
3311 /* if they are the same registers */
3312 if (sameRegs(AOP(right),AOP(result))) {
3313 emitcode("", "; (registers are the same)");
3317 /* if the result is a bit */
3318 if (AOP_TYPE(result) == AOP_CRY) {
3323 size = AOP_SIZE(result);
3326 if(AOP_TYPE(right) == AOP_LIT)
3327 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3329 (AOP_TYPE(result) != AOP_REG) &&
3330 (AOP_TYPE(right) == AOP_LIT) &&
3331 !IS_FLOAT(operandType(right)) &&
3333 emitcode("xor","a,a");
3334 /* Work from the top down.
3335 Done this way so that we can use the cached copy of 0
3336 in A for a fast clear */
3338 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3339 aopPut(AOP(result),"a",size);
3342 aopGet(AOP(right),size,FALSE),
3348 aopGet(AOP(right),offset,FALSE),
3355 freeAsmop(right,NULL,ic);
3356 freeAsmop(result,NULL,ic);
3359 /*-----------------------------------------------------------------*/
3360 /* genJumpTab - genrates code for jump table */
3361 /*-----------------------------------------------------------------*/
3362 static void genJumpTab (iCode *ic)
3367 /*-----------------------------------------------------------------*/
3368 /* genCast - gen code for casting */
3369 /*-----------------------------------------------------------------*/
3370 static void genCast (iCode *ic)
3372 operand *result = IC_RESULT(ic);
3373 link *ctype = operandType(IC_LEFT(ic));
3374 operand *right = IC_RIGHT(ic);
3377 /* if they are equivalent then do nothing */
3378 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3381 aopOp(right,ic,FALSE) ;
3382 aopOp(result,ic,FALSE);
3384 /* if the result is a bit */
3385 if (AOP_TYPE(result) == AOP_CRY) {
3389 /* if they are the same size : or less */
3390 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3392 /* if they are in the same place */
3393 if (sameRegs(AOP(right),AOP(result)))
3396 /* if they in different places then copy */
3397 size = AOP_SIZE(result);
3401 aopGet(AOP(right),offset,FALSE),
3408 /* if the result is of type pointer */
3409 if (IS_PTR(ctype)) {
3413 /* so we now know that the size of destination is greater
3414 than the size of the source */
3415 /* we move to result for the size of source */
3416 size = AOP_SIZE(right);
3420 aopGet(AOP(right),offset,FALSE),
3425 /* now depending on the sign of the destination */
3426 size = AOP_SIZE(result) - AOP_SIZE(right);
3427 /* Unsigned or not an integral type - right fill with zeros */
3428 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3430 aopPut(AOP(result),zero,offset++);
3432 /* we need to extend the sign :{ */
3433 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3436 emitcode("", "; genCast: sign extend untested.");
3437 emitcode("rla", "");
3438 emitcode("sbc", "a,a");
3440 aopPut(AOP(result),"a",offset++);
3444 freeAsmop(right, NULL, ic);
3445 freeAsmop(result, NULL, ic);
3448 /*-----------------------------------------------------------------*/
3449 /* genReceive - generate code for a receive iCode */
3450 /*-----------------------------------------------------------------*/
3451 static void genReceive (iCode *ic)
3453 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3454 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3455 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3459 aopOp(IC_RESULT(ic),ic,FALSE);
3461 assignResultValue(IC_RESULT(ic));
3464 freeAsmop(IC_RESULT(ic),NULL,ic);
3467 /*-----------------------------------------------------------------*/
3468 /* genZ80Code - generate code for Z80 based controllers */
3469 /*-----------------------------------------------------------------*/
3470 void genZ80Code (iCode *lic)
3475 lineHead = lineCurr = NULL;
3477 /* if debug information required */
3478 if (options.debug && currFunc) {
3479 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3481 if (IS_STATIC(currFunc->etype))
3482 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3484 emitcode("","G$%s$0$0 ==.",currFunc->name);
3487 /* stack pointer name */
3491 for (ic = lic ; ic ; ic = ic->next ) {
3493 if ( cln != ic->lineno ) {
3494 if ( options.debug ) {
3496 emitcode("","C$%s$%d$%d$%d ==.",
3497 ic->filename,ic->lineno,
3498 ic->level,ic->block);
3501 emitcode(";","%s %d",ic->filename,ic->lineno);
3504 /* if the result is marked as
3505 spilt and rematerializable or code for
3506 this has already been generated then
3508 if (resultRemat(ic) || ic->generated )
3511 /* depending on the operation */
3514 emitcode("", "; genNot");
3519 emitcode("", "; genCpl");
3524 emitcode("", "; genUminus");
3529 emitcode("", "; genIpush");
3534 /* IPOP happens only when trying to restore a
3535 spilt live range, if there is an ifx statement
3536 following this pop then the if statement might
3537 be using some of the registers being popped which
3538 would destory the contents of the register so
3539 we need to check for this condition and handle it */
3541 ic->next->op == IFX &&
3542 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3543 emitcode("", "; genIfx");
3544 genIfx (ic->next,ic);
3547 emitcode("", "; genIpop");
3553 emitcode("", "; genCall");
3558 emitcode("", "; genPcall");
3563 emitcode("", "; genFunction");
3568 emitcode("", "; genEndFunction");
3569 genEndFunction (ic);
3573 emitcode("", "; genRet");
3578 emitcode("", "; genLabel");
3583 emitcode("", "; genGoto");
3588 emitcode("", "; genPlus");
3593 emitcode("", "; genMinus");
3598 emitcode("", "; genMult");
3603 emitcode("", "; genDiv");
3608 emitcode("", "; genMod");
3613 emitcode("", "; genCmpGt");
3614 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3618 emitcode("", "; genCmpLt");
3619 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3626 /* note these two are xlated by algebraic equivalence
3627 during parsing SDCC.y */
3628 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3629 "got '>=' or '<=' shouldn't have come here");
3633 emitcode("", "; genCmpEq");
3634 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3638 emitcode("", "; genAndOp");
3643 emitcode("", "; genOrOp");
3648 emitcode("", "; genXor");
3649 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3653 emitcode("", "; genOr");
3654 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3658 emitcode("", "; genAnd");
3659 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3663 emitcode("", "; genInline");
3668 emitcode("", "; genRRC");
3673 emitcode("", "; genRLC");
3678 emitcode("", "; genHBIT");
3682 emitcode("", "; genLeftShift");
3687 emitcode("", "; genRightShift");
3691 case GET_VALUE_AT_ADDRESS:
3692 emitcode("", "; genPointerGet");
3698 if (POINTER_SET(ic)) {
3699 emitcode("", "; genAssign (pointer)");
3703 emitcode("", "; genAssign");
3709 emitcode("", "; genIfx");
3714 emitcode("", "; genAddrOf");
3719 emitcode("", "; genJumpTab");
3724 emitcode("", "; genCast");
3729 emitcode("", "; genReceive");
3734 emitcode("", "; addSet");
3735 addSet(&sendSet,ic);
3740 /* piCode(ic,stdout); */
3746 /* now we are ready to call the
3747 peep hole optimizer */
3748 /* if (!options.nopeep)
3749 peepHole (&lineHead); */
3751 /* now do the actual printing */
3752 printLine (lineHead,codeOutFile);