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 /* PENDING: callee-save etc */
1194 /* adjust the stack for the function */
1195 emitcode("push", "de");
1196 emitcode("push", "bc");
1197 emitcode("push", "ix");
1198 emitcode("ld", "ix,#0");
1199 emitcode("add", "ix,sp");
1201 _lastStack = sym->stack;
1204 emitcode("ld", "hl,#-%d", sym->stack);
1205 emitcode("add", "hl,sp");
1206 emitcode("ld", "sp,hl");
1210 /*-----------------------------------------------------------------*/
1211 /* genEndFunction - generates epilogue for functions */
1212 /*-----------------------------------------------------------------*/
1213 static void genEndFunction (iCode *ic)
1215 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1217 if (IS_ISR(sym->etype)) {
1221 if (SPEC_CRTCL(sym->etype))
1224 if (sym->calleeSave) {
1225 /* Handled by cret */
1231 /* if debug then send end of function */
1232 if (options.debug && currFunc) {
1234 emitcode("","C$%s$%d$%d$%d ==.",
1235 ic->filename,currFunc->lastLine,
1236 ic->level,ic->block);
1237 if (IS_STATIC(currFunc->etype))
1238 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1240 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1243 emitcode("ld", "sp,ix");
1244 emitcode("pop", "ix");
1245 emitcode("pop", "bc");
1246 emitcode("pop", "de");
1247 emitcode("ret", "");
1252 /*-----------------------------------------------------------------*/
1253 /* genRet - generate code for return statement */
1254 /*-----------------------------------------------------------------*/
1255 static void genRet (iCode *ic)
1258 /* Errk. This is a hack until I can figure out how
1259 to cause dehl to spill on a call */
1260 int size,offset = 0;
1262 /* if we have no return value then
1263 just generate the "ret" */
1267 /* we have something to return then
1268 move the return value into place */
1269 aopOp(IC_LEFT(ic),ic,FALSE);
1270 size = AOP_SIZE(IC_LEFT(ic));
1272 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1273 emitcode("ld", "hl,%s", l);
1277 l = aopGet(AOP(IC_LEFT(ic)),offset,
1279 if (strcmp(fReturn[offset],l))
1280 emitcode("ld","%s,%s",fReturn[offset++],l);
1283 freeAsmop (IC_LEFT(ic),NULL,ic);
1286 /* generate a jump to the return label
1287 if the next is not the return statement */
1288 if (!(ic->next && ic->next->op == LABEL &&
1289 IC_LABEL(ic->next) == returnLabel))
1291 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1294 /*-----------------------------------------------------------------*/
1295 /* genLabel - generates a label */
1296 /*-----------------------------------------------------------------*/
1297 static void genLabel (iCode *ic)
1299 /* special case never generate */
1300 if (IC_LABEL(ic) == entryLabel)
1303 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1306 /*-----------------------------------------------------------------*/
1307 /* genGoto - generates a ljmp */
1308 /*-----------------------------------------------------------------*/
1309 static void genGoto (iCode *ic)
1311 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1314 /*-----------------------------------------------------------------*/
1315 /* genPlusIncr :- does addition with increment if possible */
1316 /*-----------------------------------------------------------------*/
1317 static bool genPlusIncr (iCode *ic)
1319 unsigned int icount ;
1320 unsigned int size = getDataSize(IC_RESULT(ic));
1322 /* will try to generate an increment */
1323 /* if the right side is not a literal
1325 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1328 /* if the literal value of the right hand side
1329 is greater than 4 then it is not worth it */
1330 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1334 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1335 isPair(AOP(IC_RESULT(ic)))) {
1337 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1341 /* if increment 16 bits in register */
1342 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1345 symbol *tlbl = newiTempLabel(NULL);
1346 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1347 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1349 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1353 emitcode("", LABEL_STR ":",tlbl->key+100);
1357 /* If result is a pair */
1358 if (isPair(AOP(IC_RESULT(ic)))) {
1359 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1360 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1362 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1366 /* if the sizes are greater than 1 then we cannot */
1367 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1368 AOP_SIZE(IC_LEFT(ic)) > 1 )
1371 /* we can if the aops of the left & result match or
1372 if they are in registers and the registers are the
1374 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1376 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1384 /*-----------------------------------------------------------------*/
1385 /* outBitAcc - output a bit in acc */
1386 /*-----------------------------------------------------------------*/
1387 void outBitAcc(operand *result)
1389 symbol *tlbl = newiTempLabel(NULL);
1390 /* if the result is a bit */
1391 if (AOP_TYPE(result) == AOP_CRY){
1395 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1396 emitcode("ld","a,%s",one);
1397 emitcode("", LABEL_STR ":",tlbl->key+100);
1402 /*-----------------------------------------------------------------*/
1403 /* genPlus - generates code for addition */
1404 /*-----------------------------------------------------------------*/
1405 static void genPlus (iCode *ic)
1407 int size, offset = 0;
1409 /* special cases :- */
1411 aopOp (IC_LEFT(ic),ic,FALSE);
1412 aopOp (IC_RIGHT(ic),ic,FALSE);
1413 aopOp (IC_RESULT(ic),ic,TRUE);
1415 /* Swap the left and right operands if:
1417 if literal, literal on the right or
1418 if left requires ACC or right is already
1421 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1422 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1423 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1424 operand *t = IC_RIGHT(ic);
1425 IC_RIGHT(ic) = IC_LEFT(ic);
1429 /* if both left & right are in bit
1431 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1432 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1437 /* if left in bit space & right literal */
1438 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1439 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1440 /* Can happen I guess */
1444 /* if I can do an increment instead
1445 of add then GOOD for ME */
1446 if (genPlusIncr (ic) == TRUE)
1449 size = getDataSize(IC_RESULT(ic));
1452 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1453 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1455 emitcode("add","a,%s",
1456 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1458 emitcode("adc","a,%s",
1459 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1461 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1463 emitcode("add","a,%s",
1464 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1466 emitcode("adc","a,%s",
1467 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1469 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1472 /* Some kind of pointer arith. */
1473 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1474 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1475 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1478 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1479 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1480 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1485 freeAsmop(IC_LEFT(ic),NULL,ic);
1486 freeAsmop(IC_RIGHT(ic),NULL,ic);
1487 freeAsmop(IC_RESULT(ic),NULL,ic);
1491 /*-----------------------------------------------------------------*/
1492 /* genMinusDec :- does subtraction with deccrement if possible */
1493 /*-----------------------------------------------------------------*/
1494 static bool genMinusDec (iCode *ic)
1496 unsigned int icount ;
1497 unsigned int size = getDataSize(IC_RESULT(ic));
1499 /* will try to generate an increment */
1500 /* if the right side is not a literal we cannot */
1501 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1504 /* if the literal value of the right hand side
1505 is greater than 4 then it is not worth it */
1506 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1509 size = getDataSize(IC_RESULT(ic));
1510 /* if decrement 16 bits in register */
1511 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1512 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1514 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1518 /* If result is a pair */
1519 if (isPair(AOP(IC_RESULT(ic)))) {
1520 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1521 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1523 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1527 /* if the sizes are greater than 1 then we cannot */
1528 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1529 AOP_SIZE(IC_LEFT(ic)) > 1 )
1532 /* we can if the aops of the left & result match or if they are in
1533 registers and the registers are the same */
1534 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1536 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1543 /*-----------------------------------------------------------------*/
1544 /* genMinus - generates code for subtraction */
1545 /*-----------------------------------------------------------------*/
1546 static void genMinus (iCode *ic)
1548 int size, offset = 0;
1549 unsigned long lit = 0L;
1551 aopOp (IC_LEFT(ic),ic,FALSE);
1552 aopOp (IC_RIGHT(ic),ic,FALSE);
1553 aopOp (IC_RESULT(ic),ic,TRUE);
1555 /* special cases :- */
1556 /* if both left & right are in bit space */
1557 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1558 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1563 /* if I can do an decrement instead of subtract then GOOD for ME */
1564 if (genMinusDec (ic) == TRUE)
1567 size = getDataSize(IC_RESULT(ic));
1569 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1573 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1578 /* if literal, add a,#-lit, else normal subb */
1580 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1581 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1582 emitcode("sbc","a,%s",
1583 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1585 /* first add without previous c */
1587 emitcode("add","a,#0x%02x",
1588 (unsigned int)(lit & 0x0FFL));
1590 emitcode("adc","a,#0x%02x",
1591 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1593 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1596 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1597 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1598 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1602 freeAsmop(IC_LEFT(ic),NULL,ic);
1603 freeAsmop(IC_RIGHT(ic),NULL,ic);
1604 freeAsmop(IC_RESULT(ic),NULL,ic);
1607 /*-----------------------------------------------------------------*/
1608 /* genMult - generates code for multiplication */
1609 /*-----------------------------------------------------------------*/
1610 static void genMult (iCode *ic)
1612 /* Shouldn't occur - all done through function calls */
1616 /*-----------------------------------------------------------------*/
1617 /* genDiv - generates code for division */
1618 /*-----------------------------------------------------------------*/
1619 static void genDiv (iCode *ic)
1621 /* Shouldn't occur - all done through function calls */
1625 /*-----------------------------------------------------------------*/
1626 /* genMod - generates code for division */
1627 /*-----------------------------------------------------------------*/
1628 static void genMod (iCode *ic)
1630 /* Shouldn't occur - all done through function calls */
1634 /*-----------------------------------------------------------------*/
1635 /* genIfxJump :- will create a jump depending on the ifx */
1636 /*-----------------------------------------------------------------*/
1637 static void genIfxJump (iCode *ic, char *jval)
1642 /* if true label then we jump if condition
1644 if ( IC_TRUE(ic) ) {
1646 if (!strcmp(jval, "a")) {
1649 else if (!strcmp(jval, "c")) {
1653 /* The buffer contains the bit on A that we should test */
1658 /* false label is present */
1659 jlbl = IC_FALSE(ic) ;
1660 if (!strcmp(jval, "a")) {
1663 else if (!strcmp(jval, "c")) {
1667 /* The buffer contains the bit on A that we should test */
1671 /* Z80 can do a conditional long jump */
1672 if (!strcmp(jval, "a")) {
1673 emitcode("or", "a,a");
1675 else if (!strcmp(jval, "c")) {
1678 emitcode("bit", "%s,a", jval);
1680 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1682 /* mark the icode as generated */
1686 /** Generic compare for > or <
1688 static void genCmp (operand *left,operand *right,
1689 operand *result, iCode *ifx, int sign)
1691 int size, offset = 0 ;
1692 unsigned long lit = 0L;
1694 /* if left & right are bit variables */
1695 if (AOP_TYPE(left) == AOP_CRY &&
1696 AOP_TYPE(right) == AOP_CRY ) {
1697 /* Cant happen on the Z80 */
1700 /* subtract right from left if at the
1701 end the carry flag is set then we know that
1702 left is greater than right */
1703 size = max(AOP_SIZE(left),AOP_SIZE(right));
1705 /* if unsigned char cmp with lit, just compare */
1706 if((size == 1) && !sign &&
1707 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1708 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1709 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1712 if(AOP_TYPE(right) == AOP_LIT) {
1713 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1714 /* optimize if(x < 0) or if(x >= 0) */
1717 /* No sign so it's always false */
1721 /* Just load in the top most bit */
1722 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1723 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1725 genIfxJump (ifx,"acc.7");
1729 emitcode("rlc","a");
1735 /* Do a long subtract */
1736 MOVA(aopGet(AOP(left),offset,FALSE));
1737 if (sign && size == 0) {
1738 /* Case where it's signed and we've hit the end */
1741 /* Subtract through, propagating the carry */
1743 emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1746 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1753 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1756 /* if the result is used in the next
1757 ifx conditional branch then generate
1758 code a little differently */
1760 genIfxJump (ifx,"c");
1763 /* leave the result in acc */
1767 /*-----------------------------------------------------------------*/
1768 /* genCmpGt :- greater than comparison */
1769 /*-----------------------------------------------------------------*/
1770 static void genCmpGt (iCode *ic, iCode *ifx)
1772 operand *left, *right, *result;
1773 link *letype , *retype;
1777 right= IC_RIGHT(ic);
1778 result = IC_RESULT(ic);
1780 letype = getSpec(operandType(left));
1781 retype =getSpec(operandType(right));
1782 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1783 /* assign the amsops */
1784 aopOp (left,ic,FALSE);
1785 aopOp (right,ic,FALSE);
1786 aopOp (result,ic,TRUE);
1788 genCmp(right, left, result, ifx, sign);
1790 freeAsmop(left,NULL,ic);
1791 freeAsmop(right,NULL,ic);
1792 freeAsmop(result,NULL,ic);
1795 /*-----------------------------------------------------------------*/
1796 /* genCmpLt - less than comparisons */
1797 /*-----------------------------------------------------------------*/
1798 static void genCmpLt (iCode *ic, iCode *ifx)
1800 operand *left, *right, *result;
1801 link *letype , *retype;
1805 right= IC_RIGHT(ic);
1806 result = IC_RESULT(ic);
1808 letype = getSpec(operandType(left));
1809 retype =getSpec(operandType(right));
1810 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1812 /* assign the amsops */
1813 aopOp (left,ic,FALSE);
1814 aopOp (right,ic,FALSE);
1815 aopOp (result,ic,TRUE);
1817 genCmp(left, right, result, ifx, sign);
1819 freeAsmop(left,NULL,ic);
1820 freeAsmop(right,NULL,ic);
1821 freeAsmop(result,NULL,ic);
1824 /*-----------------------------------------------------------------*/
1825 /* gencjneshort - compare and jump if not equal */
1826 /*-----------------------------------------------------------------*/
1827 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1829 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1831 unsigned long lit = 0L;
1833 /* Swap the left and right if it makes the computation easier */
1834 if (AOP_TYPE(left) == AOP_LIT) {
1840 if(AOP_TYPE(right) == AOP_LIT)
1841 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1843 /* if the right side is a literal then anything goes */
1844 if (AOP_TYPE(right) == AOP_LIT &&
1845 AOP_TYPE(left) != AOP_DIR ) {
1847 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1848 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1849 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1853 /* if the right side is in a register or in direct space or
1854 if the left is a pointer register & right is not */
1855 else if (AOP_TYPE(right) == AOP_REG ||
1856 AOP_TYPE(right) == AOP_DIR ||
1857 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1859 MOVA(aopGet(AOP(left),offset,FALSE));
1860 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1861 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1863 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1865 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1866 emitcode("jp", "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 if (AOP(result)->type == AOP_REG) {
2607 symbol *tlbl , *tlbl1;
2610 /* Left is already in result - so now do the shift */
2612 emitcode("ld","a,#%u+1", shCount);
2613 tlbl = newiTempLabel(NULL);
2614 tlbl1 = newiTempLabel(NULL);
2615 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2616 emitcode("", LABEL_STR ":",tlbl->key+100);
2619 emitcode("or", "a,a");
2621 l = aopGet(AOP(result),offset++,FALSE);
2622 emitcode("rl","%s", l);
2625 emitcode("", LABEL_STR ":",tlbl1->key+100);
2626 emitcode("dec", "a");
2627 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2631 /* PENDING: do something */
2636 /*-----------------------------------------------------------------*/
2637 /* AccRol - rotate left accumulator by known count */
2638 /*-----------------------------------------------------------------*/
2639 static void AccRol (int shCount)
2641 shCount &= 0x0007; // shCount : 0..7
2678 /*-----------------------------------------------------------------*/
2679 /* AccLsh - left shift accumulator by known count */
2680 /*-----------------------------------------------------------------*/
2681 static void AccLsh (int shCount)
2685 emitcode("add","a,a");
2688 emitcode("add","a,a");
2689 emitcode("add","a,a");
2691 /* rotate left accumulator */
2693 /* and kill the lower order bits */
2694 emitcode("and","a,#0x%02x", SLMask[shCount]);
2699 /*-----------------------------------------------------------------*/
2700 /* shiftL1Left2Result - shift left one byte from left to result */
2701 /*-----------------------------------------------------------------*/
2702 static void shiftL1Left2Result (operand *left, int offl,
2703 operand *result, int offr, int shCount)
2706 l = aopGet(AOP(left),offl,FALSE);
2708 /* shift left accumulator */
2710 aopPut(AOP(result),"a",offr);
2714 /*-----------------------------------------------------------------*/
2715 /* genlshTwo - left shift two bytes by known amount != 0 */
2716 /*-----------------------------------------------------------------*/
2717 static void genlshTwo (operand *result,operand *left, int shCount)
2719 int size = AOP_SIZE(result);
2723 /* if shCount >= 8 */
2729 movLeft2Result(left, LSB, result, MSB16, 0);
2730 aopPut(AOP(result),zero, 0);
2731 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2734 movLeft2Result(left, LSB, result, MSB16, 0);
2735 aopPut(AOP(result),zero, 0);
2738 aopPut(AOP(result),zero,LSB);
2740 /* 1 <= shCount <= 7 */
2746 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2751 /*-----------------------------------------------------------------*/
2752 /* genlshOne - left shift a one byte quantity by known count */
2753 /*-----------------------------------------------------------------*/
2754 static void genlshOne (operand *result, operand *left, int shCount)
2756 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2759 /*-----------------------------------------------------------------*/
2760 /* genLeftShiftLiteral - left shifting by known count */
2761 /*-----------------------------------------------------------------*/
2762 static void genLeftShiftLiteral (operand *left,
2767 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2770 freeAsmop(right,NULL,ic);
2772 aopOp(left,ic,FALSE);
2773 aopOp(result,ic,FALSE);
2775 size = getSize(operandType(result));
2778 emitcode("; shift left ","result %d, left %d",size,
2782 /* I suppose that the left size >= result size */
2787 else if(shCount >= (size * 8))
2789 aopPut(AOP(result),zero,size);
2793 genlshOne (result,left,shCount);
2796 genlshTwo (result,left,shCount);
2805 freeAsmop(left,NULL,ic);
2806 freeAsmop(result,NULL,ic);
2809 /*-----------------------------------------------------------------*/
2810 /* genLeftShift - generates code for left shifting */
2811 /*-----------------------------------------------------------------*/
2812 static void genLeftShift (iCode *ic)
2816 symbol *tlbl , *tlbl1;
2817 operand *left,*right, *result;
2819 right = IC_RIGHT(ic);
2821 result = IC_RESULT(ic);
2823 aopOp(right,ic,FALSE);
2825 /* if the shift count is known then do it
2826 as efficiently as possible */
2827 if (AOP_TYPE(right) == AOP_LIT) {
2828 genLeftShiftLiteral (left,right,result,ic);
2832 /* shift count is unknown then we have to form a loop get the loop
2833 count in B : Note: we take only the lower order byte since
2834 shifting more that 32 bits make no sense anyway, ( the largest
2835 size of an object can be only 32 bits ) */
2836 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2837 emitcode("inc","a");
2838 freeAsmop (right,NULL,ic);
2839 aopOp(left,ic,FALSE);
2840 aopOp(result,ic,FALSE);
2842 /* now move the left to the result if they are not the
2845 if (!sameRegs(AOP(left),AOP(result))) {
2847 size = AOP_SIZE(result);
2850 l = aopGet(AOP(left),offset,FALSE);
2851 aopPut(AOP(result),l,offset);
2856 size = AOP_SIZE(result);
2859 l = aopGet(AOP(left),offset,FALSE);
2860 aopPut(AOP(result),l,offset);
2866 tlbl = newiTempLabel(NULL);
2867 size = AOP_SIZE(result);
2869 tlbl1 = newiTempLabel(NULL);
2871 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2872 emitcode("", LABEL_STR ":",tlbl->key+100);
2873 l = aopGet(AOP(result),offset,FALSE);
2874 emitcode("or", "a,a");
2876 l = aopGet(AOP(result),offset++,FALSE);
2877 emitcode("rl","%s", l);
2879 emitcode("", LABEL_STR ":",tlbl1->key+100);
2880 emitcode("dec", "a");
2881 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2883 freeAsmop(left,NULL,ic);
2884 freeAsmop(result,NULL,ic);
2887 /* genlshTwo - left shift two bytes by known amount != 0 */
2888 /*-----------------------------------------------------------------*/
2889 static void genrshOne (operand *result,operand *left, int shCount)
2892 int size = AOP_SIZE(result);
2898 l = aopGet(AOP(left),0,FALSE);
2899 if (AOP(result)->type == AOP_REG) {
2900 aopPut(AOP(result), l, 0);
2901 l = aopGet(AOP(result), 0, FALSE);
2903 emitcode("srl", "%s", l);
2908 emitcode("srl", "a");
2910 aopPut(AOP(result),"a",0);
2914 /*-----------------------------------------------------------------*/
2915 /* AccRsh - right shift accumulator by known count */
2916 /*-----------------------------------------------------------------*/
2917 static void AccRsh (int shCount)
2924 /* rotate right accumulator */
2925 AccRol(8 - shCount);
2926 /* and kill the higher order bits */
2927 emitcode("and","a,#0x%02x", SRMask[shCount]);
2932 /*-----------------------------------------------------------------*/
2933 /* shiftR1Left2Result - shift right one byte from left to result */
2934 /*-----------------------------------------------------------------*/
2935 static void shiftR1Left2Result (operand *left, int offl,
2936 operand *result, int offr,
2937 int shCount, int sign)
2939 MOVA(aopGet(AOP(left),offl,FALSE));
2946 aopPut(AOP(result),"a",offr);
2949 /*-----------------------------------------------------------------*/
2950 /* genrshTwo - right shift two bytes by known amount != 0 */
2951 /*-----------------------------------------------------------------*/
2952 static void genrshTwo (operand *result,operand *left,
2953 int shCount, int sign)
2955 /* if shCount >= 8 */
2960 shiftR1Left2Result(left, MSB16, result, LSB,
2964 movLeft2Result(left, MSB16, result, LSB, sign);
2965 aopPut(AOP(result),zero,1);
2968 /* 1 <= shCount <= 7 */
2970 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
2974 /*-----------------------------------------------------------------*/
2975 /* genRightShiftLiteral - left shifting by known count */
2976 /*-----------------------------------------------------------------*/
2977 static void genRightShiftLiteral (operand *left,
2982 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2985 freeAsmop(right,NULL,ic);
2987 aopOp(left,ic,FALSE);
2988 aopOp(result,ic,FALSE);
2990 size = getSize(operandType(result));
2992 emitcode("; shift right ","result %d, left %d",size,
2995 /* I suppose that the left size >= result size */
3000 else if(shCount >= (size * 8))
3002 aopPut(AOP(result),zero,size);
3006 genrshOne(result, left, shCount);
3009 /* PENDING: sign support */
3010 genrshTwo(result, left, shCount, FALSE);
3019 freeAsmop(left,NULL,ic);
3020 freeAsmop(result,NULL,ic);
3023 /*-----------------------------------------------------------------*/
3024 /* genRightShift - generate code for right shifting */
3025 /*-----------------------------------------------------------------*/
3026 static void genRightShift (iCode *ic)
3028 operand *left,*right, *result;
3030 right = IC_RIGHT(ic);
3032 result = IC_RESULT(ic);
3034 aopOp(right,ic,FALSE);
3036 /* if the shift count is known then do it
3037 as efficiently as possible */
3038 if (AOP_TYPE(right) == AOP_LIT) {
3039 genRightShiftLiteral (left,right,result,ic);
3047 /*-----------------------------------------------------------------*/
3048 /* genGenPointerGet - gget value from generic pointer space */
3049 /*-----------------------------------------------------------------*/
3050 static void genGenPointerGet (operand *left,
3051 operand *result, iCode *ic)
3054 link *retype = getSpec(operandType(result));
3056 aopOp(left,ic,FALSE);
3057 aopOp(result,ic,FALSE);
3059 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3061 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3062 aopPut(AOP(result),"a", 0);
3063 freeAsmop(left,NULL,ic);
3067 /* For now we always load into IY */
3068 /* if this is remateriazable */
3069 if (AOP_TYPE(left) == AOP_IMMD)
3070 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3071 else { /* we need to get it byte by byte */
3072 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3073 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3075 /* so iy now contains the address */
3076 freeAsmop(left,NULL,ic);
3078 /* if bit then unpack */
3079 if (IS_BITVAR(retype)) {
3083 size = AOP_SIZE(result);
3087 /* PENDING: make this better */
3088 if (AOP(result)->type == AOP_REG) {
3089 aopPut(AOP(result),"(hl)",offset++);
3092 emitcode("ld", "a,(hl)", offset);
3093 aopPut(AOP(result),"a",offset++);
3096 emitcode("inc", "hl");
3102 freeAsmop(result,NULL,ic);
3105 /*-----------------------------------------------------------------*/
3106 /* genPointerGet - generate code for pointer get */
3107 /*-----------------------------------------------------------------*/
3108 static void genPointerGet (iCode *ic)
3110 operand *left, *result ;
3114 result = IC_RESULT(ic) ;
3116 /* depending on the type of pointer we need to
3117 move it to the correct pointer register */
3118 type = operandType(left);
3119 etype = getSpec(type);
3121 genGenPointerGet (left,result,ic);
3124 bool isRegOrLit(asmop *aop)
3126 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3131 /*-----------------------------------------------------------------*/
3132 /* genGenPointerSet - stores the value into a pointer location */
3133 /*-----------------------------------------------------------------*/
3134 static void genGenPointerSet (operand *right,
3135 operand *result, iCode *ic)
3138 link *retype = getSpec(operandType(right));
3140 aopOp(result,ic,FALSE);
3141 aopOp(right,ic,FALSE);
3143 /* Handle the exceptions first */
3144 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3146 char *l = aopGet(AOP(right), 0, FALSE);
3148 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3149 freeAsmop(result,NULL,ic);
3153 /* if the operand is already in dptr
3154 then we do nothing else we move the value to dptr */
3155 if (AOP_TYPE(result) != AOP_STR) {
3156 /* if this is remateriazable */
3157 if (AOP_TYPE(result) == AOP_IMMD) {
3158 emitcode("", "; Error 2");
3159 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3161 else { /* we need to get it byte by byte */
3162 /* PENDING: do this better */
3163 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3164 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3167 /* so hl know contains the address */
3168 freeAsmop(result,NULL,ic);
3170 /* if bit then unpack */
3171 if (IS_BITVAR(retype)) {
3175 size = AOP_SIZE(right);
3179 char *l = aopGet(AOP(right),offset,FALSE);
3181 if (isRegOrLit(AOP(right))) {
3182 emitcode("ld", "(hl),%s", l);
3186 emitcode("ld", "(hl),a", offset);
3189 emitcode("inc", "hl");
3195 freeAsmop(right,NULL,ic);
3198 /*-----------------------------------------------------------------*/
3199 /* genPointerSet - stores the value into a pointer location */
3200 /*-----------------------------------------------------------------*/
3201 static void genPointerSet (iCode *ic)
3203 operand *right, *result ;
3206 right = IC_RIGHT(ic);
3207 result = IC_RESULT(ic) ;
3209 /* depending on the type of pointer we need to
3210 move it to the correct pointer register */
3211 type = operandType(result);
3212 etype = getSpec(type);
3214 genGenPointerSet (right,result,ic);
3217 /*-----------------------------------------------------------------*/
3218 /* genIfx - generate code for Ifx statement */
3219 /*-----------------------------------------------------------------*/
3220 static void genIfx (iCode *ic, iCode *popIc)
3222 operand *cond = IC_COND(ic);
3225 aopOp(cond,ic,FALSE);
3227 /* get the value into acc */
3228 if (AOP_TYPE(cond) != AOP_CRY)
3232 /* the result is now in the accumulator */
3233 freeAsmop(cond,NULL,ic);
3235 /* if there was something to be popped then do it */
3239 /* if the condition is a bit variable */
3240 if (isbit && IS_ITEMP(cond) &&
3242 genIfxJump(ic,SPIL_LOC(cond)->rname);
3244 if (isbit && !IS_ITEMP(cond))
3245 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3252 /*-----------------------------------------------------------------*/
3253 /* genAddrOf - generates code for address of */
3254 /*-----------------------------------------------------------------*/
3255 static void genAddrOf (iCode *ic)
3257 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3259 aopOp(IC_RESULT(ic),ic,FALSE);
3261 /* if the operand is on the stack then we
3262 need to get the stack offset of this
3265 /* if it has an offset then we need to compute it */
3266 emitcode("push", "de");
3267 emitcode("push", "ix");
3268 emitcode("pop", "hl");
3269 emitcode("ld", "de,#%d", sym->stack);
3270 emitcode("add", "hl,de");
3271 emitcode("pop", "de");
3274 emitcode("ld", "hl,#%s", sym->rname);
3276 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3277 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3279 freeAsmop(IC_RESULT(ic),NULL,ic);
3282 /*-----------------------------------------------------------------*/
3283 /* genAssign - generate code for assignment */
3284 /*-----------------------------------------------------------------*/
3285 static void genAssign (iCode *ic)
3287 operand *result, *right;
3289 unsigned long lit = 0L;
3291 result = IC_RESULT(ic);
3292 right = IC_RIGHT(ic) ;
3294 /* Dont bother assigning if they are the same */
3295 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3296 emitcode("", "; (operands are equal)");
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 /*-----------------------------------------------------------------*/
3360 /* genCast - gen code for casting */
3361 /*-----------------------------------------------------------------*/
3362 static void genCast (iCode *ic)
3364 operand *result = IC_RESULT(ic);
3365 link *ctype = operandType(IC_LEFT(ic));
3366 operand *right = IC_RIGHT(ic);
3369 /* if they are equivalent then do nothing */
3370 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3373 aopOp(right,ic,FALSE) ;
3374 aopOp(result,ic,FALSE);
3376 /* if the result is a bit */
3377 if (AOP_TYPE(result) == AOP_CRY) {
3381 /* if they are the same size : or less */
3382 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3384 /* if they are in the same place */
3385 if (sameRegs(AOP(right),AOP(result)))
3388 /* if they in different places then copy */
3389 size = AOP_SIZE(result);
3393 aopGet(AOP(right),offset,FALSE),
3400 /* if the result is of type pointer */
3401 if (IS_PTR(ctype)) {
3405 /* so we now know that the size of destination is greater
3406 than the size of the source */
3407 /* we move to result for the size of source */
3408 size = AOP_SIZE(right);
3412 aopGet(AOP(right),offset,FALSE),
3417 /* now depending on the sign of the destination */
3418 size = AOP_SIZE(result) - AOP_SIZE(right);
3419 /* Unsigned or not an integral type - right fill with zeros */
3420 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3422 aopPut(AOP(result),zero,offset++);
3424 /* we need to extend the sign :{ */
3425 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3428 emitcode("", "; genCast: sign extend untested.");
3429 emitcode("rla", "");
3430 emitcode("sbc", "a,a");
3432 aopPut(AOP(result),"a",offset++);
3436 freeAsmop(right, NULL, ic);
3437 freeAsmop(result, NULL, ic);
3440 /*-----------------------------------------------------------------*/
3441 /* genReceive - generate code for a receive iCode */
3442 /*-----------------------------------------------------------------*/
3443 static void genReceive (iCode *ic)
3445 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3446 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3447 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3451 aopOp(IC_RESULT(ic),ic,FALSE);
3453 assignResultValue(IC_RESULT(ic));
3456 freeAsmop(IC_RESULT(ic),NULL,ic);
3459 /*-----------------------------------------------------------------*/
3460 /* genZ80Code - generate code for Z80 based controllers */
3461 /*-----------------------------------------------------------------*/
3462 void genZ80Code (iCode *lic)
3467 lineHead = lineCurr = NULL;
3469 /* if debug information required */
3470 if (options.debug && currFunc) {
3471 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3473 if (IS_STATIC(currFunc->etype))
3474 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3476 emitcode("","G$%s$0$0 ==.",currFunc->name);
3479 /* stack pointer name */
3483 for (ic = lic ; ic ; ic = ic->next ) {
3485 if ( cln != ic->lineno ) {
3486 if ( options.debug ) {
3488 emitcode("","C$%s$%d$%d$%d ==.",
3489 ic->filename,ic->lineno,
3490 ic->level,ic->block);
3493 emitcode(";","%s %d",ic->filename,ic->lineno);
3496 /* if the result is marked as
3497 spilt and rematerializable or code for
3498 this has already been generated then
3500 if (resultRemat(ic) || ic->generated )
3503 /* depending on the operation */
3506 emitcode("", "; genNot");
3511 emitcode("", "; genCpl");
3516 emitcode("", "; genUminus");
3521 emitcode("", "; genIpush");
3526 /* IPOP happens only when trying to restore a
3527 spilt live range, if there is an ifx statement
3528 following this pop then the if statement might
3529 be using some of the registers being popped which
3530 would destory the contents of the register so
3531 we need to check for this condition and handle it */
3533 ic->next->op == IFX &&
3534 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3535 emitcode("", "; genIfx");
3536 genIfx (ic->next,ic);
3539 emitcode("", "; genIpop");
3545 emitcode("", "; genCall");
3550 emitcode("", "; genPcall");
3555 emitcode("", "; genFunction");
3560 emitcode("", "; genEndFunction");
3561 genEndFunction (ic);
3565 emitcode("", "; genRet");
3570 emitcode("", "; genLabel");
3575 emitcode("", "; genGoto");
3580 emitcode("", "; genPlus");
3585 emitcode("", "; genMinus");
3590 emitcode("", "; genMult");
3595 emitcode("", "; genDiv");
3600 emitcode("", "; genMod");
3605 emitcode("", "; genCmpGt");
3606 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3610 emitcode("", "; genCmpLt");
3611 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3618 /* note these two are xlated by algebraic equivalence
3619 during parsing SDCC.y */
3620 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3621 "got '>=' or '<=' shouldn't have come here");
3625 emitcode("", "; genCmpEq");
3626 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3630 emitcode("", "; genAndOp");
3635 emitcode("", "; genOrOp");
3640 emitcode("", "; genXor");
3641 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3645 emitcode("", "; genOr");
3646 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3650 emitcode("", "; genAnd");
3651 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3655 emitcode("", "; genInline");
3660 emitcode("", "; genRRC");
3665 emitcode("", "; genRLC");
3670 emitcode("", "; genHBIT");
3674 emitcode("", "; genLeftShift");
3679 emitcode("", "; genRightShift");
3683 case GET_VALUE_AT_ADDRESS:
3684 emitcode("", "; genPointerGet");
3690 if (POINTER_SET(ic)) {
3691 emitcode("", "; genAssign (pointer)");
3695 emitcode("", "; genAssign");
3701 emitcode("", "; genIfx");
3706 emitcode("", "; genAddrOf");
3711 emitcode("", "; genJumpTab");
3716 emitcode("", "; genCast");
3721 emitcode("", "; genReceive");
3726 emitcode("", "; addSet");
3727 addSet(&sendSet,ic);
3732 /* piCode(ic,stdout); */
3738 /* now we are ready to call the
3739 peep hole optimizer */
3740 /* if (!options.nopeep)
3741 peepHole (&lineHead); */
3743 /* now do the actual printing */
3744 printLine (lineHead,codeOutFile);