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)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define __FUNCTION__ __FILE__
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #include "SDCCpeeph.h"
60 //char *aopLiteral (value *val, int offset);
61 char *pic14aopLiteral (value *val, int offset);
63 /* this is the down and dirty file with all kinds of
64 kludgy & hacky stuff. This is what it is all about
65 CODE GENERATION for a specific MCU . some of the
66 routines may be reusable, will have to see */
68 static char *zero = "#0x00";
69 static char *one = "#0x01";
70 static char *spname = "sp";
72 char *fReturnpic14[] = {"fsr","dph","b","a" };
73 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
74 static unsigned fReturnSize = 4; /* shared with ralloc.c */
75 static char **fReturn = fReturnpic14;
77 static char *accUse[] = {"a","b"};
79 //static short rbank = -1;
91 extern int pic14_ptrRegReq ;
92 extern int pic14_nRegs;
93 extern FILE *codeOutFile;
94 static void saverbank (int, iCode *,bool);
95 #define RESULTONSTACK(x) \
96 (IC_RESULT(x) && IC_RESULT(x)->aop && \
97 IC_RESULT(x)->aop->type == AOP_STK )
99 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
100 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
102 #define BIT_NUMBER(x) (x & 7)
103 #define BIT_REGISTER(x) (x>>3)
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
119 #define FUNCTION_LABEL_INC 20
120 static int labelOffset=0;
121 static int debug_verbose=0;
124 /*-----------------------------------------------------------------*/
125 /* Macros for emitting instructions */
126 /*-----------------------------------------------------------------*/
127 #define emitSKPC emitcode("btfss","status,c")
128 #define emitSKPNC emitcode("btfsc","status,c")
129 #define emitSKPZ emitcode("btfss","status,z")
130 #define emitSKPNZ emitcode("btfsc","status,z")
132 /*-----------------------------------------------------------------*/
133 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
134 /* exponent of 2 is returned, otherwise -1 is */
136 /* note that this is similar to the function `powof2' in SDCCsymt */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
144 if( (num & (num-1)) == 0) {
158 /*-----------------------------------------------------------------*/
159 /* emitcode - writes the code into a file : for now it is simple */
160 /*-----------------------------------------------------------------*/
161 static void emitcode (char *inst,char *fmt, ...)
164 char lb[MAX_INLINEASM];
171 sprintf(lb,"%s\t",inst);
173 sprintf(lb,"%s",inst);
174 vsprintf(lb+(strlen(lb)),fmt,ap);
178 while (isspace(*lbp)) lbp++;
181 lineCurr = (lineCurr ?
182 connectLine(lineCurr,newLineNode(lb)) :
183 (lineHead = newLineNode(lb)));
184 lineCurr->isInline = _G.inLine;
185 lineCurr->isDebug = _G.debugLine;
189 static void DEBUGemitcode (char *inst,char *fmt, ...)
192 char lb[MAX_INLINEASM];
202 sprintf(lb,"%s\t",inst);
204 sprintf(lb,"%s",inst);
205 vsprintf(lb+(strlen(lb)),fmt,ap);
209 while (isspace(*lbp)) lbp++;
212 lineCurr = (lineCurr ?
213 connectLine(lineCurr,newLineNode(lb)) :
214 (lineHead = newLineNode(lb)));
215 lineCurr->isInline = _G.inLine;
216 lineCurr->isDebug = _G.debugLine;
221 /*-----------------------------------------------------------------*/
222 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
223 /*-----------------------------------------------------------------*/
224 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
226 bool r0iu = FALSE , r1iu = FALSE;
227 bool r0ou = FALSE , r1ou = FALSE;
229 /* the logic: if r0 & r1 used in the instruction
230 then we are in trouble otherwise */
232 /* first check if r0 & r1 are used by this
233 instruction, in which case we are in trouble */
234 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
235 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
240 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
241 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
243 /* if no usage of r0 then return it */
244 if (!r0iu && !r0ou) {
245 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
246 (*aopp)->type = AOP_R0;
248 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
251 /* if no usage of r1 then return it */
252 if (!r1iu && !r1ou) {
253 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
254 (*aopp)->type = AOP_R1;
256 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
259 /* now we know they both have usage */
260 /* if r0 not used in this instruction */
262 /* push it if not already pushed */
264 emitcode ("push","%s",
265 pic14_regWithIdx(R0_IDX)->dname);
269 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
270 (*aopp)->type = AOP_R0;
272 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
275 /* if r1 not used then */
278 /* push it if not already pushed */
280 emitcode ("push","%s",
281 pic14_regWithIdx(R1_IDX)->dname);
285 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
286 (*aopp)->type = AOP_R1;
287 return pic14_regWithIdx(R1_IDX);
291 /* I said end of world but not quite end of world yet */
292 /* if this is a result then we can push it on the stack*/
294 (*aopp)->type = AOP_STK;
299 /* other wise this is true end of the world */
300 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
301 "getFreePtr should never reach here");
305 /*-----------------------------------------------------------------*/
306 /* newAsmop - creates a new asmOp */
307 /*-----------------------------------------------------------------*/
308 static asmop *newAsmop (short type)
312 ALLOC(aop,sizeof(asmop));
317 static void genSetDPTR(int n)
321 emitcode(";", "Select standard DPTR");
322 emitcode("mov", "dps, #0x00");
326 emitcode(";", "Select alternate DPTR");
327 emitcode("mov", "dps, #0x01");
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type */
333 /*-----------------------------------------------------------------*/
334 static int pointerCode (sym_link *etype)
337 return PTR_TYPE(SPEC_OCLS(etype));
341 /*-----------------------------------------------------------------*/
342 /* aopForSym - for a true symbol */
343 /*-----------------------------------------------------------------*/
344 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
347 memmap *space= SPEC_OCLS(sym->etype);
349 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
350 /* if already has one */
354 /* assign depending on the storage class */
355 /* if it is on the stack or indirectly addressable */
356 /* space we need to assign either r0 or r1 to it */
357 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
358 sym->aop = aop = newAsmop(0);
359 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
360 aop->size = getSize(sym->type);
362 /* now assign the address of the variable to
363 the pointer register */
364 if (aop->type != AOP_STK) {
368 emitcode("push","acc");
370 emitcode("mov","a,_bp");
371 emitcode("add","a,#0x%02x",
373 ((char)(sym->stack - _G.nRegsSaved )) :
374 ((char)sym->stack)) & 0xff);
375 emitcode("mov","%s,a",
376 aop->aopu.aop_ptr->name);
379 emitcode("pop","acc");
381 emitcode("mov","%s,#%s",
382 aop->aopu.aop_ptr->name,
384 aop->paged = space->paged;
386 aop->aopu.aop_stk = sym->stack;
390 if (sym->onStack && options.stack10bit)
392 /* It's on the 10 bit stack, which is located in
396 //DEBUGemitcode(";","%d",__LINE__);
399 emitcode("push","acc");
401 emitcode("mov","a,_bp");
402 emitcode("add","a,#0x%02x",
404 ((char)(sym->stack - _G.nRegsSaved )) :
405 ((char)sym->stack)) & 0xff);
408 emitcode ("mov","dpx1,#0x40");
409 emitcode ("mov","dph1,#0x00");
410 emitcode ("mov","dpl1, a");
414 emitcode("pop","acc");
416 sym->aop = aop = newAsmop(AOP_DPTR2);
417 aop->size = getSize(sym->type);
421 //DEBUGemitcode(";","%d",__LINE__);
422 /* if in bit space */
423 if (IN_BITSPACE(space)) {
424 sym->aop = aop = newAsmop (AOP_CRY);
425 aop->aopu.aop_dir = sym->rname ;
426 aop->size = getSize(sym->type);
427 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
430 /* if it is in direct space */
431 if (IN_DIRSPACE(space)) {
432 sym->aop = aop = newAsmop (AOP_DIR);
433 aop->aopu.aop_dir = sym->rname ;
434 aop->size = getSize(sym->type);
435 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
439 /* special case for a function */
440 if (IS_FUNC(sym->type)) {
441 sym->aop = aop = newAsmop(AOP_IMMD);
442 ALLOC(aop->aopu.aop_immd,strlen(sym->rname)+1);
443 strcpy(aop->aopu.aop_immd,sym->rname);
444 aop->size = FPTRSIZE;
449 /* only remaining is far space */
450 /* in which case DPTR gets the address */
451 sym->aop = aop = newAsmop(AOP_DPTR);
452 emitcode ("mov","dptr,#%s", sym->rname);
453 aop->size = getSize(sym->type);
455 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
456 /* if it is in code space */
457 if (IN_CODESPACE(space))
463 /*-----------------------------------------------------------------*/
464 /* aopForRemat - rematerialzes an object */
465 /*-----------------------------------------------------------------*/
466 static asmop *aopForRemat (symbol *sym)
468 iCode *ic = sym->rematiCode;
469 asmop *aop = newAsmop(AOP_IMMD);
471 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
474 val += operandLitValue(IC_RIGHT(ic));
475 else if (ic->op == '-')
476 val -= operandLitValue(IC_RIGHT(ic));
480 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
484 sprintf(buffer,"(%s %c 0x%04x)",
485 OP_SYMBOL(IC_LEFT(ic))->rname,
486 val >= 0 ? '+' : '-',
489 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
491 //DEBUGemitcode(";","%s",buffer);
492 ALLOC(aop->aopu.aop_immd,strlen(buffer)+1);
493 strcpy(aop->aopu.aop_immd,buffer);
497 /*-----------------------------------------------------------------*/
498 /* regsInCommon - two operands have some registers in common */
499 /*-----------------------------------------------------------------*/
500 static bool regsInCommon (operand *op1, operand *op2)
505 /* if they have registers in common */
506 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
509 sym1 = OP_SYMBOL(op1);
510 sym2 = OP_SYMBOL(op2);
512 if (sym1->nRegs == 0 || sym2->nRegs == 0)
515 for (i = 0 ; i < sym1->nRegs ; i++) {
520 for (j = 0 ; j < sym2->nRegs ;j++ ) {
524 if (sym2->regs[j] == sym1->regs[i])
532 /*-----------------------------------------------------------------*/
533 /* operandsEqu - equivalent */
534 /*-----------------------------------------------------------------*/
535 static bool operandsEqu ( operand *op1, operand *op2)
539 /* if they not symbols */
540 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
543 sym1 = OP_SYMBOL(op1);
544 sym2 = OP_SYMBOL(op2);
546 /* if both are itemps & one is spilt
547 and the other is not then false */
548 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
549 sym1->isspilt != sym2->isspilt )
552 /* if they are the same */
556 if (strcmp(sym1->rname,sym2->rname) == 0)
560 /* if left is a tmp & right is not */
564 (sym1->usl.spillLoc == sym2))
571 (sym2->usl.spillLoc == sym1))
577 /*-----------------------------------------------------------------*/
578 /* sameRegs - two asmops have the same registers */
579 /*-----------------------------------------------------------------*/
580 static bool sameRegs (asmop *aop1, asmop *aop2 )
587 if (aop1->type != AOP_REG ||
588 aop2->type != AOP_REG )
591 if (aop1->size != aop2->size )
594 for (i = 0 ; i < aop1->size ; i++ )
595 if (aop1->aopu.aop_reg[i] !=
596 aop2->aopu.aop_reg[i] )
602 /*-----------------------------------------------------------------*/
603 /* aopOp - allocates an asmop for an operand : */
604 /*-----------------------------------------------------------------*/
605 static void aopOp (operand *op, iCode *ic, bool result)
614 DEBUGemitcode(";","%d",__LINE__);
615 /* if this a literal */
616 if (IS_OP_LITERAL(op)) {
617 DEBUGemitcode(";","%d",__LINE__);
618 op->aop = aop = newAsmop(AOP_LIT);
619 aop->aopu.aop_lit = op->operand.valOperand;
620 aop->size = getSize(operandType(op));
624 /* if already has a asmop then continue */
628 /* if the underlying symbol has a aop */
629 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
630 DEBUGemitcode(";","%d",__LINE__);
631 op->aop = OP_SYMBOL(op)->aop;
635 /* if this is a true symbol */
636 if (IS_TRUE_SYMOP(op)) {
637 DEBUGemitcode(";","%d",__LINE__);
638 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
642 /* this is a temporary : this has
648 e) can be a return use only */
653 /* if the type is a conditional */
654 if (sym->regType == REG_CND) {
655 DEBUGemitcode(";","%d",__LINE__);
656 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
661 /* if it is spilt then two situations
663 b) has a spill location */
664 if (sym->isspilt || sym->nRegs == 0) {
666 DEBUGemitcode(";","%d",__LINE__);
667 /* rematerialize it NOW */
669 sym->aop = op->aop = aop =
671 aop->size = getSize(sym->type);
672 DEBUGemitcode(";","%d",__LINE__);
678 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
679 aop->size = getSize(sym->type);
680 for ( i = 0 ; i < 2 ; i++ )
681 aop->aopu.aop_str[i] = accUse[i];
682 DEBUGemitcode(";","%d",__LINE__);
688 aop = op->aop = sym->aop = newAsmop(AOP_STR);
689 aop->size = getSize(sym->type);
690 for ( i = 0 ; i < fReturnSize ; i++ )
691 aop->aopu.aop_str[i] = fReturn[i];
692 DEBUGemitcode(";","%d",__LINE__);
696 /* else spill location */
697 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
698 sym->aop = op->aop = aop =
699 aopForSym(ic,sym->usl.spillLoc,result);
700 aop->size = getSize(sym->type);
704 /* must be in a register */
705 sym->aop = op->aop = aop = newAsmop(AOP_REG);
706 aop->size = sym->nRegs;
707 for ( i = 0 ; i < sym->nRegs ;i++)
708 aop->aopu.aop_reg[i] = sym->regs[i];
711 /*-----------------------------------------------------------------*/
712 /* freeAsmop - free up the asmop given to an operand */
713 /*----------------------------------------------------------------*/
714 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
731 /* depending on the asmop type only three cases need work AOP_RO
732 , AOP_R1 && AOP_STK */
737 emitcode ("pop","ar0");
741 bitVectUnSetBit(ic->rUsed,R0_IDX);
747 emitcode ("pop","ar1");
751 bitVectUnSetBit(ic->rUsed,R1_IDX);
757 int stk = aop->aopu.aop_stk + aop->size;
758 bitVectUnSetBit(ic->rUsed,R0_IDX);
759 bitVectUnSetBit(ic->rUsed,R1_IDX);
761 getFreePtr(ic,&aop,FALSE);
763 if (options.stack10bit)
765 /* I'm not sure what to do here yet... */
768 "*** Warning: probably generating bad code for "
769 "10 bit stack mode.\n");
773 emitcode ("mov","a,_bp");
774 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
775 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
777 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
781 emitcode("pop","acc");
782 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
784 emitcode("dec","%s",aop->aopu.aop_ptr->name);
787 freeAsmop(op,NULL,ic,TRUE);
789 emitcode("pop","ar0");
794 emitcode("pop","ar1");
801 /* all other cases just dealloc */
805 OP_SYMBOL(op)->aop = NULL;
806 /* if the symbol has a spill */
808 SPIL_LOC(op)->aop = NULL;
813 /*-----------------------------------------------------------------*/
814 /* aopGet - for fetching value of the aop */
815 /*-----------------------------------------------------------------*/
816 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
821 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
822 /* offset is greater than
824 if (offset > (aop->size - 1) &&
825 aop->type != AOP_LIT)
828 /* depending on type */
833 DEBUGemitcode(";","%d",__LINE__);
834 /* if we need to increment it */
835 while (offset > aop->coff) {
836 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
840 while (offset < aop->coff) {
841 emitcode("dec","%s",aop->aopu.aop_ptr->name);
847 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
848 return (dname ? "acc" : "a");
850 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
851 ALLOC(rs,strlen(s)+1);
857 DEBUGemitcode(";","%d",__LINE__);
858 if (aop->type == AOP_DPTR2)
863 while (offset > aop->coff) {
864 emitcode ("inc","dptr");
868 while (offset < aop->coff) {
869 emitcode("lcall","__decdptr");
876 emitcode("movc","a,@a+dptr");
879 emitcode("movx","a,@dptr");
882 if (aop->type == AOP_DPTR2)
887 return (dname ? "acc" : "a");
891 DEBUGemitcode(";","%d",__LINE__);
893 sprintf (s,"%s",aop->aopu.aop_immd);
896 sprintf(s,"(%s >> %d)",
902 ALLOC(rs,strlen(s)+1);
908 sprintf(s,"(%s + %d)",
912 sprintf(s,"%s",aop->aopu.aop_dir);
913 ALLOC(rs,strlen(s)+1);
918 DEBUGemitcode(";","%d",__LINE__);
920 return aop->aopu.aop_reg[offset]->dname;
922 return aop->aopu.aop_reg[offset]->name;
925 emitcode(";","%d",__LINE__);
926 //emitcode("clr","a");
927 //emitcode("mov","c,%s",aop->aopu.aop_dir);
928 //emitcode("rlc","a") ;
929 //return (dname ? "acc" : "a");
930 return aop->aopu.aop_dir;
933 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
934 //if (!offset && dname)
936 //return aop->aopu.aop_str[offset];
937 return "AOP_accumulator_bug";
940 DEBUGemitcode(";","%d",__LINE__);
941 return pic14aopLiteral (aop->aopu.aop_lit,offset);
944 DEBUGemitcode(";","%d",__LINE__);
946 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
950 return aop->aopu.aop_str[offset];
954 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
955 "aopget got unsupported aop->type");
958 /*-----------------------------------------------------------------*/
959 /* aopPut - puts a string for a aop */
960 /*-----------------------------------------------------------------*/
961 static void aopPut (asmop *aop, char *s, int offset)
966 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
968 if (aop->size && offset > ( aop->size - 1)) {
969 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
970 "aopPut got offset > aop->size");
974 /* will assign value to value */
975 /* depending on where it is ofcourse */
979 sprintf(d,"(%s + %d)",
980 aop->aopu.aop_dir,offset);
982 sprintf(d,"%s",aop->aopu.aop_dir);
985 DEBUGemitcode(";","%d",__LINE__);
987 emitcode("movf","%s,w",s);
988 emitcode("movwf","%s",d);
993 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
994 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
997 strcmp(s,"r0") == 0 ||
998 strcmp(s,"r1") == 0 ||
999 strcmp(s,"r2") == 0 ||
1000 strcmp(s,"r3") == 0 ||
1001 strcmp(s,"r4") == 0 ||
1002 strcmp(s,"r5") == 0 ||
1003 strcmp(s,"r6") == 0 ||
1004 strcmp(s,"r7") == 0 )
1005 emitcode("mov","%s,%s ; %d",
1006 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1011 emitcode("movf","%s,w ; %d",s,__LINE__);
1013 emitcode("movwf","%s",
1014 aop->aopu.aop_reg[offset]->name);
1022 if (aop->type == AOP_DPTR2)
1028 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1029 "aopPut writting to code space");
1033 while (offset > aop->coff) {
1035 emitcode ("inc","dptr");
1038 while (offset < aop->coff) {
1040 emitcode("lcall","__decdptr");
1045 /* if not in accumulater */
1048 emitcode ("movx","@dptr,a");
1050 if (aop->type == AOP_DPTR2)
1058 while (offset > aop->coff) {
1060 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1062 while (offset < aop->coff) {
1064 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1070 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1075 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1077 if (strcmp(s,"r0") == 0 ||
1078 strcmp(s,"r1") == 0 ||
1079 strcmp(s,"r2") == 0 ||
1080 strcmp(s,"r3") == 0 ||
1081 strcmp(s,"r4") == 0 ||
1082 strcmp(s,"r5") == 0 ||
1083 strcmp(s,"r6") == 0 ||
1084 strcmp(s,"r7") == 0 ) {
1086 sprintf(buffer,"a%s",s);
1087 emitcode("mov","@%s,%s",
1088 aop->aopu.aop_ptr->name,buffer);
1090 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1095 if (strcmp(s,"a") == 0)
1096 emitcode("push","acc");
1098 emitcode("push","%s",s);
1103 /* if bit variable */
1104 if (!aop->aopu.aop_dir) {
1105 emitcode("clr","a");
1106 emitcode("rlc","a");
1109 emitcode("clr","%s",aop->aopu.aop_dir);
1112 emitcode("setb","%s",aop->aopu.aop_dir);
1115 emitcode("mov","%s,c",aop->aopu.aop_dir);
1117 lbl = newiTempLabel(NULL);
1119 if (strcmp(s,"a")) {
1122 emitcode("clr","c");
1123 emitcode("jz","%05d_DS_",lbl->key+100);
1124 emitcode("cpl","c");
1125 emitcode("","%05d_DS_:",lbl->key+100);
1126 emitcode("mov","%s,c",aop->aopu.aop_dir);
1133 if (strcmp(aop->aopu.aop_str[offset],s))
1134 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1139 if (!offset && (strcmp(s,"acc") == 0))
1142 if (strcmp(aop->aopu.aop_str[offset],s))
1143 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1147 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1148 "aopPut got unsupported aop->type");
1154 /*-----------------------------------------------------------------*/
1155 /* reAdjustPreg - points a register back to where it should */
1156 /*-----------------------------------------------------------------*/
1157 static void reAdjustPreg (asmop *aop)
1161 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1163 if ((size = aop->size) <= 1)
1166 switch (aop->type) {
1170 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1174 if (aop->type == AOP_DPTR2)
1180 emitcode("lcall","__decdptr");
1183 if (aop->type == AOP_DPTR2)
1193 #define AOP(op) op->aop
1194 #define AOP_TYPE(op) AOP(op)->type
1195 #define AOP_SIZE(op) AOP(op)->size
1196 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1197 AOP_TYPE(x) == AOP_R0))
1199 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1200 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1203 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1204 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1205 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1207 /*-----------------------------------------------------------------*/
1208 /* genNotFloat - generates not for float operations */
1209 /*-----------------------------------------------------------------*/
1210 static void genNotFloat (operand *op, operand *res)
1216 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1217 /* we will put 127 in the first byte of
1219 aopPut(AOP(res),"#127",0);
1220 size = AOP_SIZE(op) - 1;
1223 l = aopGet(op->aop,offset++,FALSE,FALSE);
1227 emitcode("orl","a,%s",
1229 offset++,FALSE,FALSE));
1231 tlbl = newiTempLabel(NULL);
1233 tlbl = newiTempLabel(NULL);
1234 aopPut(res->aop,one,1);
1235 emitcode("jz","%05d_DS_",(tlbl->key+100));
1236 aopPut(res->aop,zero,1);
1237 emitcode("","%05d_DS_:",(tlbl->key+100));
1239 size = res->aop->size - 2;
1241 /* put zeros in the rest */
1243 aopPut(res->aop,zero,offset++);
1247 /*-----------------------------------------------------------------*/
1248 /* opIsGptr: returns non-zero if the passed operand is */
1249 /* a generic pointer type. */
1250 /*-----------------------------------------------------------------*/
1251 static int opIsGptr(operand *op)
1253 sym_link *type = operandType(op);
1255 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1256 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1264 /*-----------------------------------------------------------------*/
1265 /* getDataSize - get the operand data size */
1266 /*-----------------------------------------------------------------*/
1267 static int getDataSize(operand *op)
1269 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1272 return AOP_SIZE(op);
1274 // tsd- in the pic port, the genptr size is 1, so this code here
1275 // fails. ( in the 8051 port, the size was 4).
1278 size = AOP_SIZE(op);
1279 if (size == GPTRSIZE)
1281 sym_link *type = operandType(op);
1282 if (IS_GENPTR(type))
1284 /* generic pointer; arithmetic operations
1285 * should ignore the high byte (pointer type).
1288 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1295 /*-----------------------------------------------------------------*/
1296 /* outAcc - output Acc */
1297 /*-----------------------------------------------------------------*/
1298 static void outAcc(operand *result)
1301 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1302 size = getDataSize(result);
1304 aopPut(AOP(result),"a",0);
1307 /* unsigned or positive */
1309 aopPut(AOP(result),zero,offset++);
1314 /*-----------------------------------------------------------------*/
1315 /* outBitC - output a bit C */
1316 /*-----------------------------------------------------------------*/
1317 static void outBitC(operand *result)
1320 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1321 /* if the result is bit */
1322 if (AOP_TYPE(result) == AOP_CRY)
1323 aopPut(AOP(result),"c",0);
1325 emitcode("clr","a ; %d", __LINE__);
1326 emitcode("rlc","a");
1331 /*-----------------------------------------------------------------*/
1332 /* toBoolean - emit code for orl a,operator(sizeop) */
1333 /*-----------------------------------------------------------------*/
1334 static void toBoolean(operand *oper)
1336 int size = AOP_SIZE(oper) - 1;
1339 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1341 if ( AOP_TYPE(oper) != AOP_ACC)
1342 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1345 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1349 /*-----------------------------------------------------------------*/
1350 /* genNot - generate code for ! operation */
1351 /*-----------------------------------------------------------------*/
1352 static void genNot (iCode *ic)
1355 sym_link *optype = operandType(IC_LEFT(ic));
1357 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1358 /* assign asmOps to operand & result */
1359 aopOp (IC_LEFT(ic),ic,FALSE);
1360 aopOp (IC_RESULT(ic),ic,TRUE);
1362 /* if in bit space then a special case */
1363 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1364 emitcode("movlw","1<<%s");
1365 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1366 //emitcode("cpl","c");
1367 //outBitC(IC_RESULT(ic));
1371 /* if type float then do float */
1372 if (IS_FLOAT(optype)) {
1373 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1377 toBoolean(IC_LEFT(ic));
1379 tlbl = newiTempLabel(NULL);
1380 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1381 emitcode("","%05d_DS_:",tlbl->key+100);
1382 outBitC(IC_RESULT(ic));
1385 /* release the aops */
1386 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1387 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1391 /*-----------------------------------------------------------------*/
1392 /* genCpl - generate code for complement */
1393 /*-----------------------------------------------------------------*/
1394 static void genCpl (iCode *ic)
1400 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1401 /* assign asmOps to operand & result */
1402 aopOp (IC_LEFT(ic),ic,FALSE);
1403 aopOp (IC_RESULT(ic),ic,TRUE);
1405 /* if both are in bit space then
1407 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1408 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1410 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1411 emitcode("cpl","c");
1412 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1416 size = AOP_SIZE(IC_RESULT(ic));
1418 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1420 emitcode("cpl","a");
1421 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1426 /* release the aops */
1427 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1428 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1431 /*-----------------------------------------------------------------*/
1432 /* genUminusFloat - unary minus for floating points */
1433 /*-----------------------------------------------------------------*/
1434 static void genUminusFloat(operand *op,operand *result)
1436 int size ,offset =0 ;
1439 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1440 /* for this we just need to flip the
1441 first it then copy the rest in place */
1442 size = AOP_SIZE(op) - 1;
1443 l = aopGet(AOP(op),3,FALSE,FALSE);
1447 emitcode("cpl","acc.7");
1448 aopPut(AOP(result),"a",3);
1452 aopGet(AOP(op),offset,FALSE,FALSE),
1458 /*-----------------------------------------------------------------*/
1459 /* genUminus - unary minus code generation */
1460 /*-----------------------------------------------------------------*/
1461 static void genUminus (iCode *ic)
1464 sym_link *optype, *rtype;
1467 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1469 aopOp(IC_LEFT(ic),ic,FALSE);
1470 aopOp(IC_RESULT(ic),ic,TRUE);
1472 /* if both in bit space then special
1474 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1475 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1477 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1478 emitcode("cpl","c");
1479 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1483 optype = operandType(IC_LEFT(ic));
1484 rtype = operandType(IC_RESULT(ic));
1486 /* if float then do float stuff */
1487 if (IS_FLOAT(optype)) {
1488 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1492 /* otherwise subtract from zero */
1493 size = AOP_SIZE(IC_LEFT(ic));
1497 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1498 if (!strcmp(l,"a")) {
1499 emitcode("cpl","a");
1500 emitcode("inc","a");
1502 emitcode("clr","a");
1503 emitcode("subb","a,%s",l);
1505 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1508 /* if any remaining bytes in the result */
1509 /* we just need to propagate the sign */
1510 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1511 emitcode("rlc","a");
1512 emitcode("subb","a,acc");
1514 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1518 /* release the aops */
1519 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1520 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1523 /*-----------------------------------------------------------------*/
1524 /* saveRegisters - will look for a call and save the registers */
1525 /*-----------------------------------------------------------------*/
1526 static void saveRegisters(iCode *lic)
1533 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1535 for (ic = lic ; ic ; ic = ic->next)
1536 if (ic->op == CALL || ic->op == PCALL)
1540 fprintf(stderr,"found parameter push with no function call\n");
1544 /* if the registers have been saved already then
1546 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1549 /* find the registers in use at this time
1550 and push them away to safety */
1551 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1555 if (options.useXstack) {
1556 if (bitVectBitValue(rsave,R0_IDX))
1557 emitcode("mov","b,r0");
1558 emitcode("mov","r0,%s",spname);
1559 for (i = 0 ; i < pic14_nRegs ; i++) {
1560 if (bitVectBitValue(rsave,i)) {
1562 emitcode("mov","a,b");
1564 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1565 emitcode("movx","@r0,a");
1566 emitcode("inc","r0");
1569 emitcode("mov","%s,r0",spname);
1570 if (bitVectBitValue(rsave,R0_IDX))
1571 emitcode("mov","r0,b");
1573 for (i = 0 ; i < pic14_nRegs ; i++) {
1574 if (bitVectBitValue(rsave,i))
1575 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1578 detype = getSpec(operandType(IC_LEFT(ic)));
1580 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1581 IS_ISR(currFunc->etype) &&
1584 saverbank(SPEC_BANK(detype),ic,TRUE);
1587 /*-----------------------------------------------------------------*/
1588 /* unsaveRegisters - pop the pushed registers */
1589 /*-----------------------------------------------------------------*/
1590 static void unsaveRegisters (iCode *ic)
1595 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1596 /* find the registers in use at this time
1597 and push them away to safety */
1598 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1601 if (options.useXstack) {
1602 emitcode("mov","r0,%s",spname);
1603 for (i = pic14_nRegs ; i >= 0 ; i--) {
1604 if (bitVectBitValue(rsave,i)) {
1605 emitcode("dec","r0");
1606 emitcode("movx","a,@r0");
1608 emitcode("mov","b,a");
1610 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1614 emitcode("mov","%s,r0",spname);
1615 if (bitVectBitValue(rsave,R0_IDX))
1616 emitcode("mov","r0,b");
1618 for (i = pic14_nRegs ; i >= 0 ; i--) {
1619 if (bitVectBitValue(rsave,i))
1620 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1626 /*-----------------------------------------------------------------*/
1628 /*-----------------------------------------------------------------*/
1629 static void pushSide(operand * oper, int size)
1632 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1634 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1635 if (AOP_TYPE(oper) != AOP_REG &&
1636 AOP_TYPE(oper) != AOP_DIR &&
1638 emitcode("mov","a,%s",l);
1639 emitcode("push","acc");
1641 emitcode("push","%s",l);
1645 /*-----------------------------------------------------------------*/
1646 /* assignResultValue - */
1647 /*-----------------------------------------------------------------*/
1648 static void assignResultValue(operand * oper)
1651 int size = AOP_SIZE(oper);
1653 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 // The last byte in the assignment is in W
1656 aopPut(AOP(oper),"W",size-1);
1660 aopPut(AOP(oper),fReturn[offset],offset);
1668 /*-----------------------------------------------------------------*/
1669 /* genXpush - pushes onto the external stack */
1670 /*-----------------------------------------------------------------*/
1671 static void genXpush (iCode *ic)
1673 asmop *aop = newAsmop(0);
1675 int size,offset = 0;
1677 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1678 aopOp(IC_LEFT(ic),ic,FALSE);
1679 r = getFreePtr(ic,&aop,FALSE);
1682 emitcode("mov","%s,_spx",r->name);
1684 size = AOP_SIZE(IC_LEFT(ic));
1687 char *l = aopGet(AOP(IC_LEFT(ic)),
1688 offset++,FALSE,FALSE);
1690 emitcode("movx","@%s,a",r->name);
1691 emitcode("inc","%s",r->name);
1696 emitcode("mov","_spx,%s",r->name);
1698 freeAsmop(NULL,aop,ic,TRUE);
1699 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1702 /*-----------------------------------------------------------------*/
1703 /* genIpush - genrate code for pushing this gets a little complex */
1704 /*-----------------------------------------------------------------*/
1705 static void genIpush (iCode *ic)
1707 int size, offset = 0 ;
1711 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1712 /* if this is not a parm push : ie. it is spill push
1713 and spill push is always done on the local stack */
1714 if (!ic->parmPush) {
1716 /* and the item is spilt then do nothing */
1717 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1720 aopOp(IC_LEFT(ic),ic,FALSE);
1721 size = AOP_SIZE(IC_LEFT(ic));
1722 /* push it on the stack */
1724 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1729 emitcode("push","%s",l);
1734 /* this is a paramter push: in this case we call
1735 the routine to find the call and save those
1736 registers that need to be saved */
1739 /* if use external stack then call the external
1740 stack pushing routine */
1741 if (options.useXstack) {
1746 /* then do the push */
1747 aopOp(IC_LEFT(ic),ic,FALSE);
1750 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1751 size = AOP_SIZE(IC_LEFT(ic));
1754 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1755 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1756 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1758 emitcode("mov","a,%s",l);
1759 emitcode("push","acc");
1761 emitcode("push","%s",l);
1764 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1767 /*-----------------------------------------------------------------*/
1768 /* genIpop - recover the registers: can happen only for spilling */
1769 /*-----------------------------------------------------------------*/
1770 static void genIpop (iCode *ic)
1775 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1776 /* if the temp was not pushed then */
1777 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1780 aopOp(IC_LEFT(ic),ic,FALSE);
1781 size = AOP_SIZE(IC_LEFT(ic));
1784 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1787 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1790 /*-----------------------------------------------------------------*/
1791 /* unsaverbank - restores the resgister bank from stack */
1792 /*-----------------------------------------------------------------*/
1793 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1799 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1801 if (options.useXstack) {
1803 r = getFreePtr(ic,&aop,FALSE);
1806 emitcode("mov","%s,_spx",r->name);
1807 emitcode("movx","a,@%s",r->name);
1808 emitcode("mov","psw,a");
1809 emitcode("dec","%s",r->name);
1812 emitcode ("pop","psw");
1815 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1816 if (options.useXstack) {
1817 emitcode("movx","a,@%s",r->name);
1818 //emitcode("mov","(%s+%d),a",
1819 // regspic14[i].base,8*bank+regspic14[i].offset);
1820 emitcode("dec","%s",r->name);
1823 emitcode("pop",""); //"(%s+%d)",
1824 //regspic14[i].base,8*bank); //+regspic14[i].offset);
1827 if (options.useXstack) {
1829 emitcode("mov","_spx,%s",r->name);
1830 freeAsmop(NULL,aop,ic,TRUE);
1835 /*-----------------------------------------------------------------*/
1836 /* saverbank - saves an entire register bank on the stack */
1837 /*-----------------------------------------------------------------*/
1838 static void saverbank (int bank, iCode *ic, bool pushPsw)
1844 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1845 if (options.useXstack) {
1848 r = getFreePtr(ic,&aop,FALSE);
1849 emitcode("mov","%s,_spx",r->name);
1853 for (i = 0 ; i < pic14_nRegs ;i++) {
1854 if (options.useXstack) {
1855 emitcode("inc","%s",r->name);
1856 //emitcode("mov","a,(%s+%d)",
1857 // regspic14[i].base,8*bank+regspic14[i].offset);
1858 emitcode("movx","@%s,a",r->name);
1860 emitcode("push","");// "(%s+%d)",
1861 //regspic14[i].base,8*bank+regspic14[i].offset);
1865 if (options.useXstack) {
1866 emitcode("mov","a,psw");
1867 emitcode("movx","@%s,a",r->name);
1868 emitcode("inc","%s",r->name);
1869 emitcode("mov","_spx,%s",r->name);
1870 freeAsmop (NULL,aop,ic,TRUE);
1873 emitcode("push","psw");
1875 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1881 /*-----------------------------------------------------------------*/
1882 /* genCall - generates a call statement */
1883 /*-----------------------------------------------------------------*/
1884 static void genCall (iCode *ic)
1888 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1890 /* if caller saves & we have not saved then */
1894 /* if we are calling a function that is not using
1895 the same register bank then we need to save the
1896 destination registers on the stack */
1897 detype = getSpec(operandType(IC_LEFT(ic)));
1899 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1900 IS_ISR(currFunc->etype) &&
1903 saverbank(SPEC_BANK(detype),ic,TRUE);
1905 /* if send set is not empty the assign */
1909 for (sic = setFirstItem(_G.sendSet) ; sic ;
1910 sic = setNextItem(_G.sendSet)) {
1911 int size, offset = 0;
1913 aopOp(IC_LEFT(sic),sic,FALSE);
1914 size = AOP_SIZE(IC_LEFT(sic));
1916 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1918 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
1920 if (strcmp(l,fReturn[offset])) {
1922 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
1923 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
1924 emitcode("movlw","%s",l);
1926 emitcode("movf","%s,w",l);
1927 // The last one is past in W
1929 emitcode("movwf","%s",fReturn[offset]);
1933 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1938 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1939 OP_SYMBOL(IC_LEFT(ic))->rname :
1940 OP_SYMBOL(IC_LEFT(ic))->name));
1942 /* if we need assign a result value */
1943 if ((IS_ITEMP(IC_RESULT(ic)) &&
1944 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1945 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1946 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1949 aopOp(IC_RESULT(ic),ic,FALSE);
1952 assignResultValue(IC_RESULT(ic));
1954 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1957 /* adjust the stack for parameters if
1959 if (IC_LEFT(ic)->parmBytes) {
1961 if (IC_LEFT(ic)->parmBytes > 3) {
1962 emitcode("mov","a,%s",spname);
1963 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1964 emitcode("mov","%s,a",spname);
1966 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1967 emitcode("dec","%s",spname);
1971 /* if register bank was saved then pop them */
1973 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1975 /* if we hade saved some registers then unsave them */
1976 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1977 unsaveRegisters (ic);
1982 /*-----------------------------------------------------------------*/
1983 /* genPcall - generates a call by pointer statement */
1984 /*-----------------------------------------------------------------*/
1985 static void genPcall (iCode *ic)
1988 symbol *rlbl = newiTempLabel(NULL);
1991 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1992 /* if caller saves & we have not saved then */
1996 /* if we are calling a function that is not using
1997 the same register bank then we need to save the
1998 destination registers on the stack */
1999 detype = getSpec(operandType(IC_LEFT(ic)));
2001 IS_ISR(currFunc->etype) &&
2002 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2003 saverbank(SPEC_BANK(detype),ic,TRUE);
2006 /* push the return address on to the stack */
2007 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2008 emitcode("push","acc");
2009 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2010 emitcode("push","acc");
2012 if (options.model == MODEL_FLAT24)
2014 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2015 emitcode("push","acc");
2018 /* now push the calling address */
2019 aopOp(IC_LEFT(ic),ic,FALSE);
2021 pushSide(IC_LEFT(ic), FPTRSIZE);
2023 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2025 /* if send set is not empty the assign */
2029 for (sic = setFirstItem(_G.sendSet) ; sic ;
2030 sic = setNextItem(_G.sendSet)) {
2031 int size, offset = 0;
2032 aopOp(IC_LEFT(sic),sic,FALSE);
2033 size = AOP_SIZE(IC_LEFT(sic));
2035 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2037 if (strcmp(l,fReturn[offset]))
2038 emitcode("mov","%s,%s",
2043 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2049 emitcode("","%05d_DS_:",(rlbl->key+100));
2052 /* if we need assign a result value */
2053 if ((IS_ITEMP(IC_RESULT(ic)) &&
2054 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2055 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2056 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2059 aopOp(IC_RESULT(ic),ic,FALSE);
2062 assignResultValue(IC_RESULT(ic));
2064 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2067 /* adjust the stack for parameters if
2069 if (IC_LEFT(ic)->parmBytes) {
2071 if (IC_LEFT(ic)->parmBytes > 3) {
2072 emitcode("mov","a,%s",spname);
2073 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2074 emitcode("mov","%s,a",spname);
2076 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2077 emitcode("dec","%s",spname);
2081 /* if register bank was saved then unsave them */
2083 (SPEC_BANK(currFunc->etype) !=
2085 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2087 /* if we hade saved some registers then
2090 unsaveRegisters (ic);
2094 /*-----------------------------------------------------------------*/
2095 /* resultRemat - result is rematerializable */
2096 /*-----------------------------------------------------------------*/
2097 static int resultRemat (iCode *ic)
2099 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2100 if (SKIP_IC(ic) || ic->op == IFX)
2103 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2104 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2105 if (sym->remat && !POINTER_SET(ic))
2112 #if defined(__BORLANDC__) || defined(_MSC_VER)
2113 #define STRCASECMP stricmp
2115 #define STRCASECMP strcasecmp
2118 /*-----------------------------------------------------------------*/
2119 /* inExcludeList - return 1 if the string is in exclude Reg list */
2120 /*-----------------------------------------------------------------*/
2121 static bool inExcludeList(char *s)
2125 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2126 if (options.excludeRegs[i] &&
2127 STRCASECMP(options.excludeRegs[i],"none") == 0)
2130 for ( i = 0 ; options.excludeRegs[i]; i++) {
2131 if (options.excludeRegs[i] &&
2132 STRCASECMP(s,options.excludeRegs[i]) == 0)
2138 /*-----------------------------------------------------------------*/
2139 /* genFunction - generated code for function entry */
2140 /*-----------------------------------------------------------------*/
2141 static void genFunction (iCode *ic)
2146 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2147 labelOffset += FUNCTION_LABEL_INC;
2150 /* create the function header */
2151 emitcode(";","-----------------------------------------");
2152 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2153 emitcode(";","-----------------------------------------");
2155 emitcode("","%s:",sym->rname);
2156 fetype = getSpec(operandType(IC_LEFT(ic)));
2158 /* if critical function then turn interrupts off */
2159 if (SPEC_CRTCL(fetype))
2160 emitcode("clr","ea");
2162 /* here we need to generate the equates for the
2163 register bank if required */
2165 if (SPEC_BANK(fetype) != rbank) {
2168 rbank = SPEC_BANK(fetype);
2169 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2170 if (strcmp(regspic14[i].base,"0") == 0)
2171 emitcode("","%s = 0x%02x",
2173 8*rbank+regspic14[i].offset);
2175 emitcode ("","%s = %s + 0x%02x",
2178 8*rbank+regspic14[i].offset);
2183 /* if this is an interrupt service routine then
2184 save acc, b, dpl, dph */
2185 if (IS_ISR(sym->etype)) {
2187 if (!inExcludeList("acc"))
2188 emitcode ("push","acc");
2189 if (!inExcludeList("b"))
2190 emitcode ("push","b");
2191 if (!inExcludeList("dpl"))
2192 emitcode ("push","dpl");
2193 if (!inExcludeList("dph"))
2194 emitcode ("push","dph");
2195 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2197 emitcode ("push", "dpx");
2198 /* Make sure we're using standard DPTR */
2199 emitcode ("push", "dps");
2200 emitcode ("mov", "dps, #0x00");
2201 if (options.stack10bit)
2203 /* This ISR could conceivably use DPTR2. Better save it. */
2204 emitcode ("push", "dpl1");
2205 emitcode ("push", "dph1");
2206 emitcode ("push", "dpx1");
2209 /* if this isr has no bank i.e. is going to
2210 run with bank 0 , then we need to save more
2212 if (!SPEC_BANK(sym->etype)) {
2214 /* if this function does not call any other
2215 function then we can be economical and
2216 save only those registers that are used */
2217 if (! sym->hasFcall) {
2220 /* if any registers used */
2221 if (sym->regsUsed) {
2222 /* save the registers used */
2223 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2224 if (bitVectBitValue(sym->regsUsed,i) ||
2225 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2226 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2231 /* this function has a function call cannot
2232 determines register usage so we will have the
2234 saverbank(0,ic,FALSE);
2238 /* if callee-save to be used for this function
2239 then save the registers being used in this function */
2240 if (sym->calleeSave) {
2243 /* if any registers used */
2244 if (sym->regsUsed) {
2245 /* save the registers used */
2246 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2247 if (bitVectBitValue(sym->regsUsed,i) ||
2248 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2249 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2257 /* set the register bank to the desired value */
2258 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2259 emitcode("push","psw");
2260 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2263 if (IS_RENT(sym->etype) || options.stackAuto) {
2265 if (options.useXstack) {
2266 emitcode("mov","r0,%s",spname);
2267 emitcode("mov","a,_bp");
2268 emitcode("movx","@r0,a");
2269 emitcode("inc","%s",spname);
2273 /* set up the stack */
2274 emitcode ("push","_bp"); /* save the callers stack */
2276 emitcode ("mov","_bp,%s",spname);
2279 /* adjust the stack for the function */
2284 werror(W_STACK_OVERFLOW,sym->name);
2286 if (i > 3 && sym->recvSize < 4) {
2288 emitcode ("mov","a,sp");
2289 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2290 emitcode ("mov","sp,a");
2295 emitcode("inc","sp");
2300 emitcode ("mov","a,_spx");
2301 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2302 emitcode ("mov","_spx,a");
2307 /*-----------------------------------------------------------------*/
2308 /* genEndFunction - generates epilogue for functions */
2309 /*-----------------------------------------------------------------*/
2310 static void genEndFunction (iCode *ic)
2312 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2314 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2316 if (IS_RENT(sym->etype) || options.stackAuto)
2318 emitcode ("mov","%s,_bp",spname);
2321 /* if use external stack but some variables were
2322 added to the local stack then decrement the
2324 if (options.useXstack && sym->stack) {
2325 emitcode("mov","a,sp");
2326 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2327 emitcode("mov","sp,a");
2331 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2332 if (options.useXstack) {
2333 emitcode("mov","r0,%s",spname);
2334 emitcode("movx","a,@r0");
2335 emitcode("mov","_bp,a");
2336 emitcode("dec","%s",spname);
2340 emitcode ("pop","_bp");
2344 /* restore the register bank */
2345 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2346 emitcode ("pop","psw");
2348 if (IS_ISR(sym->etype)) {
2350 /* now we need to restore the registers */
2351 /* if this isr has no bank i.e. is going to
2352 run with bank 0 , then we need to save more
2354 if (!SPEC_BANK(sym->etype)) {
2356 /* if this function does not call any other
2357 function then we can be economical and
2358 save only those registers that are used */
2359 if (! sym->hasFcall) {
2362 /* if any registers used */
2363 if (sym->regsUsed) {
2364 /* save the registers used */
2365 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2366 if (bitVectBitValue(sym->regsUsed,i) ||
2367 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2368 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2373 /* this function has a function call cannot
2374 determines register usage so we will have the
2376 unsaverbank(0,ic,FALSE);
2380 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2382 if (options.stack10bit)
2384 emitcode ("pop", "dpx1");
2385 emitcode ("pop", "dph1");
2386 emitcode ("pop", "dpl1");
2388 emitcode ("pop", "dps");
2389 emitcode ("pop", "dpx");
2391 if (!inExcludeList("dph"))
2392 emitcode ("pop","dph");
2393 if (!inExcludeList("dpl"))
2394 emitcode ("pop","dpl");
2395 if (!inExcludeList("b"))
2396 emitcode ("pop","b");
2397 if (!inExcludeList("acc"))
2398 emitcode ("pop","acc");
2400 if (SPEC_CRTCL(sym->etype))
2401 emitcode("setb","ea");
2403 /* if debug then send end of function */
2404 /* if (options.debug && currFunc) { */
2407 emitcode(";","C$%s$%d$%d$%d ==.",
2408 ic->filename,currFunc->lastLine,
2409 ic->level,ic->block);
2410 if (IS_STATIC(currFunc->etype))
2411 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2413 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2417 emitcode ("reti","");
2420 if (SPEC_CRTCL(sym->etype))
2421 emitcode("setb","ea");
2423 if (sym->calleeSave) {
2426 /* if any registers used */
2427 if (sym->regsUsed) {
2428 /* save the registers used */
2429 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2430 if (bitVectBitValue(sym->regsUsed,i) ||
2431 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2432 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2438 /* if debug then send end of function */
2441 emitcode(";","C$%s$%d$%d$%d ==.",
2442 ic->filename,currFunc->lastLine,
2443 ic->level,ic->block);
2444 if (IS_STATIC(currFunc->etype))
2445 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2447 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2451 emitcode ("return","");
2456 /*-----------------------------------------------------------------*/
2457 /* genRet - generate code for return statement */
2458 /*-----------------------------------------------------------------*/
2459 static void genRet (iCode *ic)
2461 int size,offset = 0 , pushed = 0;
2463 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2464 /* if we have no return value then
2465 just generate the "ret" */
2469 /* we have something to return then
2470 move the return value into place */
2471 aopOp(IC_LEFT(ic),ic,FALSE);
2472 size = AOP_SIZE(IC_LEFT(ic));
2476 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2478 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2480 emitcode("push","%s",l);
2483 l = aopGet(AOP(IC_LEFT(ic)),offset,
2485 if (strcmp(fReturn[offset],l)) {
2486 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2487 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2488 emitcode("movlw","%s",l);
2490 emitcode("movf","%s,w",l);
2492 emitcode("movwf","%s",fReturn[offset]);
2501 if (strcmp(fReturn[pushed],"a"))
2502 emitcode("pop",fReturn[pushed]);
2504 emitcode("pop","acc");
2507 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2510 /* generate a jump to the return label
2511 if the next is not the return statement */
2512 if (!(ic->next && ic->next->op == LABEL &&
2513 IC_LABEL(ic->next) == returnLabel))
2515 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2519 /*-----------------------------------------------------------------*/
2520 /* genLabel - generates a label */
2521 /*-----------------------------------------------------------------*/
2522 static void genLabel (iCode *ic)
2524 /* special case never generate */
2525 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2526 if (IC_LABEL(ic) == entryLabel)
2529 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2532 /*-----------------------------------------------------------------*/
2533 /* genGoto - generates a goto */
2534 /*-----------------------------------------------------------------*/
2536 static void genGoto (iCode *ic)
2538 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2541 /*-----------------------------------------------------------------*/
2542 /* findLabelBackwards: walks back through the iCode chain looking */
2543 /* for the given label. Returns number of iCode instructions */
2544 /* between that label and given ic. */
2545 /* Returns zero if label not found. */
2546 /*-----------------------------------------------------------------*/
2548 static int findLabelBackwards(iCode *ic, int key)
2552 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2558 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2560 /* printf("findLabelBackwards = %d\n", count); */
2568 /*-----------------------------------------------------------------*/
2569 /* genPlusIncr :- does addition with increment if possible */
2570 /*-----------------------------------------------------------------*/
2571 static bool genPlusIncr (iCode *ic)
2573 unsigned int icount ;
2574 unsigned int size = getDataSize(IC_RESULT(ic));
2576 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2577 DEBUGemitcode ("; ","result %d, left %d, right %d",
2578 AOP_TYPE(IC_RESULT(ic)),
2579 AOP_TYPE(IC_LEFT(ic)),
2580 AOP_TYPE(IC_RIGHT(ic)));
2582 /* will try to generate an increment */
2583 /* if the right side is not a literal
2585 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2588 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2589 /* if the literal value of the right hand side
2590 is greater than 1 then it is faster to add */
2591 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2594 /* if increment 16 bits in register */
2595 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2600 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2604 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2610 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2611 /* if left is in accumulator - probably a bit operation*/
2612 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2613 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2615 emitcode("bcf","(%s >> 3), (%s & 7)",
2616 AOP(IC_RESULT(ic))->aopu.aop_dir,
2617 AOP(IC_RESULT(ic))->aopu.aop_dir);
2619 emitcode("xorlw","1");
2621 emitcode("andlw","1");
2624 emitcode("bsf","(%s >> 3), (%s & 7)",
2625 AOP(IC_RESULT(ic))->aopu.aop_dir,
2626 AOP(IC_RESULT(ic))->aopu.aop_dir);
2633 /* if the sizes are greater than 1 then we cannot */
2634 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2635 AOP_SIZE(IC_LEFT(ic)) > 1 )
2638 /* If we are incrementing the same register by two: */
2640 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2643 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2648 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2649 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2650 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2654 /*-----------------------------------------------------------------*/
2655 /* outBitAcc - output a bit in acc */
2656 /*-----------------------------------------------------------------*/
2657 static void outBitAcc(operand *result)
2659 symbol *tlbl = newiTempLabel(NULL);
2660 /* if the result is a bit */
2661 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2663 if (AOP_TYPE(result) == AOP_CRY){
2664 aopPut(AOP(result),"a",0);
2667 emitcode("jz","%05d_DS_",tlbl->key+100);
2668 emitcode("mov","a,%s",one);
2669 emitcode("","%05d_DS_:",tlbl->key+100);
2674 /*-----------------------------------------------------------------*/
2675 /* genPlusBits - generates code for addition of two bits */
2676 /*-----------------------------------------------------------------*/
2677 static void genPlusBits (iCode *ic)
2680 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2682 The following block of code will add two bits.
2683 Note that it'll even work if the destination is
2684 the carry (C in the status register).
2685 It won't work if the 'Z' bit is a source or destination.
2688 /* If the result is stored in the accumulator (w) */
2689 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2690 emitcode("movlw","(1 << (%s & 7))",
2691 AOP(IC_RESULT(ic))->aopu.aop_dir,
2692 AOP(IC_RESULT(ic))->aopu.aop_dir);
2693 emitcode("bcf","(%s >> 3), (%s & 7)",
2694 AOP(IC_RESULT(ic))->aopu.aop_dir,
2695 AOP(IC_RESULT(ic))->aopu.aop_dir);
2696 emitcode("btfsc","(%s >> 3), (%s & 7)",
2697 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2698 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2699 emitcode("xorwf","(%s >>3),f",
2700 AOP(IC_RESULT(ic))->aopu.aop_dir);
2701 emitcode("btfsc","(%s >> 3), (%s & 7)",
2702 AOP(IC_LEFT(ic))->aopu.aop_dir,
2703 AOP(IC_LEFT(ic))->aopu.aop_dir);
2704 emitcode("xorwf","(%s>>3),f",
2705 AOP(IC_RESULT(ic))->aopu.aop_dir);
2708 emitcode("clrw","");
2709 emitcode("btfsc","(%s >> 3), (%s & 7)",
2710 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2711 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2712 emitcode("xorlw","1");
2713 emitcode("btfsc","(%s >> 3), (%s & 7)",
2714 AOP(IC_LEFT(ic))->aopu.aop_dir,
2715 AOP(IC_LEFT(ic))->aopu.aop_dir);
2716 emitcode("xorlw","1");
2722 /* This is the original version of this code.
2724 * This is being kept around for reference,
2725 * because I am not entirely sure I got it right...
2727 static void adjustArithmeticResult(iCode *ic)
2729 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2730 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2731 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2732 aopPut(AOP(IC_RESULT(ic)),
2733 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2736 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2737 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2738 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2739 aopPut(AOP(IC_RESULT(ic)),
2740 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2743 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2744 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2745 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2746 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2749 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2750 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2754 /* This is the pure and virtuous version of this code.
2755 * I'm pretty certain it's right, but not enough to toss the old
2758 static void adjustArithmeticResult(iCode *ic)
2760 if (opIsGptr(IC_RESULT(ic)) &&
2761 opIsGptr(IC_LEFT(ic)) &&
2762 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2764 aopPut(AOP(IC_RESULT(ic)),
2765 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2769 if (opIsGptr(IC_RESULT(ic)) &&
2770 opIsGptr(IC_RIGHT(ic)) &&
2771 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2773 aopPut(AOP(IC_RESULT(ic)),
2774 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2778 if (opIsGptr(IC_RESULT(ic)) &&
2779 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2780 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2781 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2782 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2784 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2785 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2790 /*-----------------------------------------------------------------*/
2791 /* genPlus - generates code for addition */
2792 /*-----------------------------------------------------------------*/
2793 static void genPlus (iCode *ic)
2795 int size, offset = 0;
2797 /* special cases :- */
2798 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2800 aopOp (IC_LEFT(ic),ic,FALSE);
2801 aopOp (IC_RIGHT(ic),ic,FALSE);
2802 aopOp (IC_RESULT(ic),ic,TRUE);
2804 /* if literal, literal on the right or
2805 if left requires ACC or right is already
2808 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2809 operand *t = IC_RIGHT(ic);
2810 IC_RIGHT(ic) = IC_LEFT(ic);
2814 /* if both left & right are in bit space */
2815 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2816 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2821 /* if left in bit space & right literal */
2822 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2823 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2824 /* if result in bit space */
2825 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2826 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
2827 emitcode("movlw","(1 << (%s & 7)) ;%d",AOP(IC_RESULT(ic))->aopu.aop_dir,__LINE__);
2828 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2829 emitcode("btfsc","(%s >> 3), (%s & 7)",
2830 AOP(IC_LEFT(ic))->aopu.aop_dir,
2831 AOP(IC_LEFT(ic))->aopu.aop_dir);
2833 emitcode("xorwf","(%s>>3),f",AOP(IC_RESULT(ic))->aopu.aop_dir);
2836 size = getDataSize(IC_RESULT(ic));
2838 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2839 emitcode("addc","a,#00 ;%d",__LINE__);
2840 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2846 /* if I can do an increment instead
2847 of add then GOOD for ME */
2848 if (genPlusIncr (ic) == TRUE)
2851 size = getDataSize(IC_RESULT(ic));
2853 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2854 /* Add a literal to something else */
2856 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2860 DEBUGemitcode(";","adding lit to something. size %d",size);
2863 DEBUGemitcode(";","size %d",size);
2865 switch (lit & 0xff) {
2869 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2870 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2873 emitcode("incf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2874 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2875 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2879 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2880 emitcode("decf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2883 emitcode("decf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2884 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2885 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2889 if( !know_W || ( (lit&0xff) != l1) ) {
2891 emitcode("movlw","0x%x", lit&0xff);
2893 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2894 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2897 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2898 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2901 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
2911 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2913 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2914 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2915 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2917 /* here we are adding a bit to a char or int */
2919 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2921 emitcode("btfsc","(%s >> 3), (%s & 7)",
2922 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2923 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2924 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2927 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2928 emitcode("btfsc","(%s >> 3), (%s & 7)",
2929 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2930 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2931 emitcode(" xorlw","1");
2933 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2934 emitcode("btfsc","(%s >> 3), (%s & 7)",
2935 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2936 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2937 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2940 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
2942 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2943 emitcode("andlw","1");
2944 emitcode("bcf","(%s >> 3), (%s & 7)",
2945 AOP(IC_RESULT(ic))->aopu.aop_dir,
2946 AOP(IC_RESULT(ic))->aopu.aop_dir);
2948 emitcode("bsf","(%s >> 3), (%s & 7)",
2949 AOP(IC_RESULT(ic))->aopu.aop_dir,
2950 AOP(IC_RESULT(ic))->aopu.aop_dir);
2953 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2960 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2961 emitcode("clrz","");
2963 emitcode("btfsc","(%s >> 3), (%s & 7)",
2964 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2965 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2966 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2970 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2971 emitcode("btfsc","(%s >> 3), (%s & 7)",
2972 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2973 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2974 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2975 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2981 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2988 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2989 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2990 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2992 //if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2993 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2994 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2995 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2996 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2999 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3001 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3002 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3004 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3005 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3006 emitcode("addlw","%s", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3008 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3009 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3010 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3020 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3021 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3022 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3024 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3026 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3027 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3033 //adjustArithmeticResult(ic);
3036 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3037 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3038 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3041 /*-----------------------------------------------------------------*/
3042 /* genMinusDec :- does subtraction with decrement if possible */
3043 /*-----------------------------------------------------------------*/
3044 static bool genMinusDec (iCode *ic)
3046 unsigned int icount ;
3047 unsigned int size = getDataSize(IC_RESULT(ic));
3049 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3050 /* will try to generate an increment */
3051 /* if the right side is not a literal
3053 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3056 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3058 /* if the literal value of the right hand side
3059 is greater than 4 then it is not worth it */
3060 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3063 /* if decrement 16 bits in register */
3064 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3069 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3070 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3071 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3073 /* size is 3 or 4 */
3074 emitcode("movlw","0xff");
3075 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3078 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3080 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3083 emitcode("skpnc","");
3085 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3094 /* if the sizes are greater than 1 then we cannot */
3095 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3096 AOP_SIZE(IC_LEFT(ic)) > 1 )
3099 /* we can if the aops of the left & result match or
3100 if they are in registers and the registers are the
3102 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3105 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3110 DEBUGemitcode ("; returning"," result=%s, left=%s",
3111 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3112 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3114 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3115 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3122 /*-----------------------------------------------------------------*/
3123 /* addSign - complete with sign */
3124 /*-----------------------------------------------------------------*/
3125 static void addSign(operand *result, int offset, int sign)
3127 int size = (getDataSize(result) - offset);
3128 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3131 emitcode("rlc","a");
3132 emitcode("subb","a,acc");
3134 aopPut(AOP(result),"a",offset++);
3137 aopPut(AOP(result),zero,offset++);
3141 /*-----------------------------------------------------------------*/
3142 /* genMinusBits - generates code for subtraction of two bits */
3143 /*-----------------------------------------------------------------*/
3144 static void genMinusBits (iCode *ic)
3146 symbol *lbl = newiTempLabel(NULL);
3147 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3148 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3149 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3150 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3151 emitcode("cpl","c");
3152 emitcode("","%05d_DS_:",(lbl->key+100));
3153 outBitC(IC_RESULT(ic));
3156 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3157 emitcode("subb","a,acc");
3158 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3159 emitcode("inc","a");
3160 emitcode("","%05d_DS_:",(lbl->key+100));
3161 aopPut(AOP(IC_RESULT(ic)),"a",0);
3162 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3166 /*-----------------------------------------------------------------*/
3167 /* genMinus - generates code for subtraction */
3168 /*-----------------------------------------------------------------*/
3169 static void genMinus (iCode *ic)
3171 int size, offset = 0;
3172 unsigned long lit = 0L;
3174 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3175 aopOp (IC_LEFT(ic),ic,FALSE);
3176 aopOp (IC_RIGHT(ic),ic,FALSE);
3177 aopOp (IC_RESULT(ic),ic,TRUE);
3179 /* special cases :- */
3180 /* if both left & right are in bit space */
3181 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3182 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3187 /* if I can do an decrement instead
3188 of subtract then GOOD for ME */
3189 if (genMinusDec (ic) == TRUE)
3192 size = getDataSize(IC_RESULT(ic));
3194 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3195 /* Add a literal to something else */
3197 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3200 /* add the first byte: */
3201 emitcode("movlw","0x%x", lit & 0xff);
3202 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3209 emitcode("rlf","_known_zero,w");
3210 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3214 emitcode("movlw","0x%x", lit & 0xff);
3215 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3223 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3224 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3230 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3232 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3233 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3240 // adjustArithmeticResult(ic);
3243 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3244 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3245 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3249 /*-----------------------------------------------------------------*/
3250 /* genMultbits :- multiplication of bits */
3251 /*-----------------------------------------------------------------*/
3252 static void genMultbits (operand *left,
3256 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3258 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3259 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3264 /*-----------------------------------------------------------------*/
3265 /* genMultOneByte : 8 bit multiplication & division */
3266 /*-----------------------------------------------------------------*/
3267 static void genMultOneByte (operand *left,
3271 sym_link *opetype = operandType(result);
3276 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3277 /* (if two literals, the value is computed before) */
3278 /* if one literal, literal on the right */
3279 if (AOP_TYPE(left) == AOP_LIT){
3285 size = AOP_SIZE(result);
3286 /* signed or unsigned */
3287 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3288 l = aopGet(AOP(left),0,FALSE,FALSE);
3290 emitcode("mul","ab");
3291 /* if result size = 1, mul signed = mul unsigned */
3292 aopPut(AOP(result),"a",0);
3294 if (SPEC_USIGN(opetype)){
3295 aopPut(AOP(result),"b",1);
3297 /* for filling the MSBs */
3298 emitcode("clr","a");
3301 emitcode("mov","a,b");
3303 /* adjust the MSB if left or right neg */
3305 /* if one literal */
3306 if (AOP_TYPE(right) == AOP_LIT){
3307 /* AND literal negative */
3308 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3309 /* adjust MSB (c==0 after mul) */
3310 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3314 lbl = newiTempLabel(NULL);
3315 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3316 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3317 emitcode("","%05d_DS_:",(lbl->key+100));
3318 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3319 lbl = newiTempLabel(NULL);
3320 emitcode("jc","%05d_DS_",(lbl->key+100));
3321 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3322 emitcode("","%05d_DS_:",(lbl->key+100));
3325 lbl = newiTempLabel(NULL);
3326 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3327 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3328 emitcode("","%05d_DS_:",(lbl->key+100));
3329 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3330 lbl = newiTempLabel(NULL);
3331 emitcode("jc","%05d_DS_",(lbl->key+100));
3332 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3333 emitcode("","%05d_DS_:",(lbl->key+100));
3335 aopPut(AOP(result),"a",1);
3338 emitcode("rlc","a");
3339 emitcode("subb","a,acc");
3346 aopPut(AOP(result),"a",offset++);
3350 /*-----------------------------------------------------------------*/
3351 /* genMult - generates code for multiplication */
3352 /*-----------------------------------------------------------------*/
3353 static void genMult (iCode *ic)
3355 operand *left = IC_LEFT(ic);
3356 operand *right = IC_RIGHT(ic);
3357 operand *result= IC_RESULT(ic);
3359 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3360 /* assign the amsops */
3361 aopOp (left,ic,FALSE);
3362 aopOp (right,ic,FALSE);
3363 aopOp (result,ic,TRUE);
3365 /* special cases first */
3367 if (AOP_TYPE(left) == AOP_CRY &&
3368 AOP_TYPE(right)== AOP_CRY) {
3369 genMultbits(left,right,result);
3373 /* if both are of size == 1 */
3374 if (AOP_SIZE(left) == 1 &&
3375 AOP_SIZE(right) == 1 ) {
3376 genMultOneByte(left,right,result);
3380 /* should have been converted to function call */
3384 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3385 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3386 freeAsmop(result,NULL,ic,TRUE);
3389 /*-----------------------------------------------------------------*/
3390 /* genDivbits :- division of bits */
3391 /*-----------------------------------------------------------------*/
3392 static void genDivbits (operand *left,
3399 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3400 /* the result must be bit */
3401 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3402 l = aopGet(AOP(left),0,FALSE,FALSE);
3406 emitcode("div","ab");
3407 emitcode("rrc","a");
3408 aopPut(AOP(result),"c",0);
3411 /*-----------------------------------------------------------------*/
3412 /* genDivOneByte : 8 bit division */
3413 /*-----------------------------------------------------------------*/
3414 static void genDivOneByte (operand *left,
3418 sym_link *opetype = operandType(result);
3423 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3424 size = AOP_SIZE(result) - 1;
3426 /* signed or unsigned */
3427 if (SPEC_USIGN(opetype)) {
3428 /* unsigned is easy */
3429 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3430 l = aopGet(AOP(left),0,FALSE,FALSE);
3432 emitcode("div","ab");
3433 aopPut(AOP(result),"a",0);
3435 aopPut(AOP(result),zero,offset++);
3439 /* signed is a little bit more difficult */
3441 /* save the signs of the operands */
3442 l = aopGet(AOP(left),0,FALSE,FALSE);
3444 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3445 emitcode("push","acc"); /* save it on the stack */
3447 /* now sign adjust for both left & right */
3448 l = aopGet(AOP(right),0,FALSE,FALSE);
3450 lbl = newiTempLabel(NULL);
3451 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3452 emitcode("cpl","a");
3453 emitcode("inc","a");
3454 emitcode("","%05d_DS_:",(lbl->key+100));
3455 emitcode("mov","b,a");
3457 /* sign adjust left side */
3458 l = aopGet(AOP(left),0,FALSE,FALSE);
3461 lbl = newiTempLabel(NULL);
3462 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3463 emitcode("cpl","a");
3464 emitcode("inc","a");
3465 emitcode("","%05d_DS_:",(lbl->key+100));
3467 /* now the division */
3468 emitcode("div","ab");
3469 /* we are interested in the lower order
3471 emitcode("mov","b,a");
3472 lbl = newiTempLabel(NULL);
3473 emitcode("pop","acc");
3474 /* if there was an over flow we don't
3475 adjust the sign of the result */
3476 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3477 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3479 emitcode("clr","a");
3480 emitcode("subb","a,b");
3481 emitcode("mov","b,a");
3482 emitcode("","%05d_DS_:",(lbl->key+100));
3484 /* now we are done */
3485 aopPut(AOP(result),"b",0);
3487 emitcode("mov","c,b.7");
3488 emitcode("subb","a,acc");
3491 aopPut(AOP(result),"a",offset++);
3495 /*-----------------------------------------------------------------*/
3496 /* genDiv - generates code for division */
3497 /*-----------------------------------------------------------------*/
3498 static void genDiv (iCode *ic)
3500 operand *left = IC_LEFT(ic);
3501 operand *right = IC_RIGHT(ic);
3502 operand *result= IC_RESULT(ic);
3504 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3505 /* assign the amsops */
3506 aopOp (left,ic,FALSE);
3507 aopOp (right,ic,FALSE);
3508 aopOp (result,ic,TRUE);
3510 /* special cases first */
3512 if (AOP_TYPE(left) == AOP_CRY &&
3513 AOP_TYPE(right)== AOP_CRY) {
3514 genDivbits(left,right,result);
3518 /* if both are of size == 1 */
3519 if (AOP_SIZE(left) == 1 &&
3520 AOP_SIZE(right) == 1 ) {
3521 genDivOneByte(left,right,result);
3525 /* should have been converted to function call */
3528 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3529 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3530 freeAsmop(result,NULL,ic,TRUE);
3533 /*-----------------------------------------------------------------*/
3534 /* genModbits :- modulus of bits */
3535 /*-----------------------------------------------------------------*/
3536 static void genModbits (operand *left,
3543 /* the result must be bit */
3544 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3545 l = aopGet(AOP(left),0,FALSE,FALSE);
3549 emitcode("div","ab");
3550 emitcode("mov","a,b");
3551 emitcode("rrc","a");
3552 aopPut(AOP(result),"c",0);
3555 /*-----------------------------------------------------------------*/
3556 /* genModOneByte : 8 bit modulus */
3557 /*-----------------------------------------------------------------*/
3558 static void genModOneByte (operand *left,
3562 sym_link *opetype = operandType(result);
3566 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3567 /* signed or unsigned */
3568 if (SPEC_USIGN(opetype)) {
3569 /* unsigned is easy */
3570 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3571 l = aopGet(AOP(left),0,FALSE,FALSE);
3573 emitcode("div","ab");
3574 aopPut(AOP(result),"b",0);
3578 /* signed is a little bit more difficult */
3580 /* save the signs of the operands */
3581 l = aopGet(AOP(left),0,FALSE,FALSE);
3584 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3585 emitcode("push","acc"); /* save it on the stack */
3587 /* now sign adjust for both left & right */
3588 l = aopGet(AOP(right),0,FALSE,FALSE);
3591 lbl = newiTempLabel(NULL);
3592 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3593 emitcode("cpl","a");
3594 emitcode("inc","a");
3595 emitcode("","%05d_DS_:",(lbl->key+100));
3596 emitcode("mov","b,a");
3598 /* sign adjust left side */
3599 l = aopGet(AOP(left),0,FALSE,FALSE);
3602 lbl = newiTempLabel(NULL);
3603 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3604 emitcode("cpl","a");
3605 emitcode("inc","a");
3606 emitcode("","%05d_DS_:",(lbl->key+100));
3608 /* now the multiplication */
3609 emitcode("div","ab");
3610 /* we are interested in the lower order
3612 lbl = newiTempLabel(NULL);
3613 emitcode("pop","acc");
3614 /* if there was an over flow we don't
3615 adjust the sign of the result */
3616 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3617 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3619 emitcode("clr","a");
3620 emitcode("subb","a,b");
3621 emitcode("mov","b,a");
3622 emitcode("","%05d_DS_:",(lbl->key+100));
3624 /* now we are done */
3625 aopPut(AOP(result),"b",0);
3629 /*-----------------------------------------------------------------*/
3630 /* genMod - generates code for division */
3631 /*-----------------------------------------------------------------*/
3632 static void genMod (iCode *ic)
3634 operand *left = IC_LEFT(ic);
3635 operand *right = IC_RIGHT(ic);
3636 operand *result= IC_RESULT(ic);
3638 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3639 /* assign the amsops */
3640 aopOp (left,ic,FALSE);
3641 aopOp (right,ic,FALSE);
3642 aopOp (result,ic,TRUE);
3644 /* special cases first */
3646 if (AOP_TYPE(left) == AOP_CRY &&
3647 AOP_TYPE(right)== AOP_CRY) {
3648 genModbits(left,right,result);
3652 /* if both are of size == 1 */
3653 if (AOP_SIZE(left) == 1 &&
3654 AOP_SIZE(right) == 1 ) {
3655 genModOneByte(left,right,result);
3659 /* should have been converted to function call */
3663 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3664 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3665 freeAsmop(result,NULL,ic,TRUE);
3668 /*-----------------------------------------------------------------*/
3669 /* genIfxJump :- will create a jump depending on the ifx */
3670 /*-----------------------------------------------------------------*/
3671 static void genIfxJump (iCode *ic, char *jval)
3674 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3675 /* if true label then we jump if condition
3677 if ( IC_TRUE(ic) ) {
3679 if(strcmp(jval,"a") == 0)
3681 else if (strcmp(jval,"c") == 0)
3684 emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3686 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3690 /* false label is present */
3691 if(strcmp(jval,"a") == 0)
3693 else if (strcmp(jval,"c") == 0)
3696 emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
3698 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3703 /* mark the icode as generated */
3707 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3710 static void genSkip(iCode *ifx,int status_bit)
3715 if ( IC_TRUE(ifx) ) {
3716 switch(status_bit) {
3726 emitcode("skpndc","");
3731 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3735 switch(status_bit) {
3746 emitcode("skpdc","");
3749 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3755 /*-----------------------------------------------------------------*/
3757 /*-----------------------------------------------------------------*/
3758 static void genSkipc(iCode *ifx, int condition)
3769 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3771 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3775 /*-----------------------------------------------------------------*/
3777 /*-----------------------------------------------------------------*/
3778 static void genSkipz(iCode *ifx, int condition)
3789 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3791 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3794 /*-----------------------------------------------------------------*/
3795 /* genCmp :- greater or less than comparison */
3796 /*-----------------------------------------------------------------*/
3797 static void genCmp (operand *left,operand *right,
3798 operand *result, iCode *ifx, int sign)
3800 int size, offset = 0 ;
3801 unsigned long lit = 0L,i = 0;
3803 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3804 /* if left & right are bit variables */
3805 if (AOP_TYPE(left) == AOP_CRY &&
3806 AOP_TYPE(right) == AOP_CRY ) {
3807 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3808 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3810 /* subtract right from left if at the
3811 end the carry flag is set then we know that
3812 left is greater than right */
3813 size = max(AOP_SIZE(left),AOP_SIZE(right));
3815 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3816 if((size == 1) && !sign &&
3817 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3818 symbol *lbl = newiTempLabel(NULL);
3819 emitcode("cjne","%s,%s,%05d_DS_",
3820 aopGet(AOP(left),offset,FALSE,FALSE),
3821 aopGet(AOP(right),offset,FALSE,FALSE),
3823 emitcode("","%05d_DS_:",lbl->key+100);
3826 if(AOP_TYPE(right) == AOP_LIT) {
3828 DEBUGemitcode(";right lit","%d",sign);
3830 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3833 i = (lit >> (size*8)) & 0xff;
3835 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3836 genSkipz(ifx,IC_TRUE(ifx) == NULL);
3838 emitcode("movlw","0x%x",i);
3839 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3840 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3847 if(AOP_TYPE(left) == AOP_LIT) {
3849 DEBUGemitcode(";left lit","%d",sign);
3851 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3855 i = (lit >> (size*8)) & 0xff;
3857 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3858 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3859 } else if( i == 1 ) {
3860 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3861 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3864 emitcode("movlw","0x%x",i);
3865 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3866 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3875 DEBUGemitcode(";sign","%d",sign);
3876 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3877 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3881 /*if (AOP_TYPE(right) == AOP_LIT){
3882 unsigned long lit = (unsigned long)
3883 floatFromVal(AOP(right)->aopu.aop_lit);
3884 emitcode("subb","a,#0x%02x",
3885 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3887 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3888 emitcode("xrl","b,#0x80");
3889 emitcode("subb","a,b");
3892 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3894 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3896 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3897 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3904 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3907 /* if the result is used in the next
3908 ifx conditional branch then generate
3909 code a little differently */
3911 genIfxJump (ifx,"c");
3914 /* leave the result in acc */
3919 /*-----------------------------------------------------------------*/
3920 /* genCmpGt :- greater than comparison */
3921 /*-----------------------------------------------------------------*/
3922 static void genCmpGt (iCode *ic, iCode *ifx)
3924 operand *left, *right, *result;
3925 sym_link *letype , *retype;
3928 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3930 right= IC_RIGHT(ic);
3931 result = IC_RESULT(ic);
3933 letype = getSpec(operandType(left));
3934 retype =getSpec(operandType(right));
3935 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3936 /* assign the amsops */
3937 aopOp (left,ic,FALSE);
3938 aopOp (right,ic,FALSE);
3939 aopOp (result,ic,TRUE);
3941 genCmp(right, left, result, ifx, sign);
3943 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3944 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3945 freeAsmop(result,NULL,ic,TRUE);
3948 /*-----------------------------------------------------------------*/
3949 /* genCmpLt - less than comparisons */
3950 /*-----------------------------------------------------------------*/
3951 static void genCmpLt (iCode *ic, iCode *ifx)
3953 operand *left, *right, *result;
3954 sym_link *letype , *retype;
3957 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3959 right= IC_RIGHT(ic);
3960 result = IC_RESULT(ic);
3962 letype = getSpec(operandType(left));
3963 retype =getSpec(operandType(right));
3964 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3966 /* assign the amsops */
3967 aopOp (left,ic,FALSE);
3968 aopOp (right,ic,FALSE);
3969 aopOp (result,ic,TRUE);
3971 genCmp(left, right, result, ifx, sign);
3973 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3974 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975 freeAsmop(result,NULL,ic,TRUE);
3978 /*-----------------------------------------------------------------*/
3979 /* gencjneshort - compare and jump if not equal */
3980 /*-----------------------------------------------------------------*/
3981 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3983 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3985 unsigned long lit = 0L;
3987 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3988 /* if the left side is a literal or
3989 if the right is in a pointer register and left
3991 if ((AOP_TYPE(left) == AOP_LIT) ||
3992 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3997 if(AOP_TYPE(right) == AOP_LIT)
3998 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4000 /* if the right side is a literal then anything goes */
4001 if (AOP_TYPE(right) == AOP_LIT &&
4002 AOP_TYPE(left) != AOP_DIR ) {
4005 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4006 emitcode("xorlw","0x%x",lit & 0xff);
4008 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4011 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4017 /* if the right side is in a register or in direct space or
4018 if the left is a pointer register & right is not */
4019 else if (AOP_TYPE(right) == AOP_REG ||
4020 AOP_TYPE(right) == AOP_DIR ||
4021 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4022 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4024 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4025 ( (lit & 0xff) != 0)) {
4026 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4027 emitcode("xorlw","0x%x",lit & 0xff);
4030 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4033 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4036 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4037 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4038 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4039 emitcode("jnz","%05d_DS_",lbl->key+100);
4041 emitcode("cjne","a,%s,%05d_DS_",
4042 aopGet(AOP(right),offset,FALSE,TRUE),
4048 /* right is a pointer reg need both a & b */
4050 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4052 emitcode("mov","b,%s",l);
4053 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4054 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4060 /*-----------------------------------------------------------------*/
4061 /* gencjne - compare and jump if not equal */
4062 /*-----------------------------------------------------------------*/
4063 static void gencjne(operand *left, operand *right, symbol *lbl)
4065 symbol *tlbl = newiTempLabel(NULL);
4067 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4068 gencjneshort(left, right, lbl);
4070 emitcode("mov","a,%s",one);
4071 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4072 emitcode("","%05d_DS_:",lbl->key+100);
4073 emitcode("clr","a");
4074 emitcode("","%05d_DS_:",tlbl->key+100);
4078 /*-----------------------------------------------------------------*/
4079 /* genCmpEq - generates code for equal to */
4080 /*-----------------------------------------------------------------*/
4081 static void genCmpEq (iCode *ic, iCode *ifx)
4083 operand *left, *right, *result;
4084 unsigned long lit = 0L;
4087 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4089 DEBUGemitcode ("; ifx is non-null","");
4091 DEBUGemitcode ("; ifx is null","");
4093 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4094 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4095 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4097 size = max(AOP_SIZE(left),AOP_SIZE(right));
4099 /* if literal, literal on the right or
4100 if the right is in a pointer register and left
4102 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4103 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4104 operand *t = IC_RIGHT(ic);
4105 IC_RIGHT(ic) = IC_LEFT(ic);
4109 if(ifx && !AOP_SIZE(result)){
4111 /* if they are both bit variables */
4112 if (AOP_TYPE(left) == AOP_CRY &&
4113 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4114 if(AOP_TYPE(right) == AOP_LIT){
4115 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4117 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4118 emitcode("cpl","c");
4119 } else if(lit == 1L) {
4120 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4122 emitcode("clr","c");
4124 /* AOP_TYPE(right) == AOP_CRY */
4126 symbol *lbl = newiTempLabel(NULL);
4127 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4128 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4129 emitcode("cpl","c");
4130 emitcode("","%05d_DS_:",(lbl->key+100));
4132 /* if true label then we jump if condition
4134 tlbl = newiTempLabel(NULL);
4135 if ( IC_TRUE(ifx) ) {
4136 emitcode("jnc","%05d_DS_",tlbl->key+100);
4137 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4139 emitcode("jc","%05d_DS_",tlbl->key+100);
4140 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4142 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4145 /* They're not both bit variables. Is the right a literal? */
4146 if(AOP_TYPE(right) == AOP_LIT) {
4148 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4153 int h = (lit>>8) & 0xff;
4156 /* Check special cases for integers */
4157 switch(lit & 0xffff) {
4159 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4160 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4165 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4166 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4171 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4172 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4177 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4178 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4183 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4184 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4190 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4191 emitcode("xorlw","0x%x",l);
4192 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4195 } else if (l == 0) {
4196 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4197 emitcode("xorlw","0x%x",h);
4198 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4202 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4203 emitcode("xorlw","0x%x",l);
4204 emitcode("movlw","0x%x",h);
4206 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4222 switch(lit & 0xff) {
4224 if ( IC_TRUE(ifx) ) {
4225 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4227 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4229 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4230 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4234 if ( IC_TRUE(ifx) ) {
4235 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4237 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4239 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4240 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4244 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4246 emitcode("xorlw","0x%x",lit & 0xff);
4251 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4252 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4257 } else if(AOP_TYPE(right) == AOP_CRY ) {
4258 /* we know the left is not a bit, but that the right is */
4259 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4261 emitcode("btfsc","(%s >> 3), (%s & 7)",
4262 AOP(right)->aopu.aop_dir,
4263 AOP(right)->aopu.aop_dir);
4265 emitcode("btfss","(%s >> 3), (%s & 7)",
4266 AOP(right)->aopu.aop_dir,
4267 AOP(right)->aopu.aop_dir);
4269 emitcode("xorlw","1");
4271 /* if the two are equal, then W will be 0 and the Z bit is set
4272 * we could test Z now, or go ahead and check the high order bytes if
4273 * the variable we're comparing is larger than a byte. */
4276 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4278 if ( IC_TRUE(ifx) ) {
4280 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4283 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4287 /* They're both variables that are larger than bits */
4290 tlbl = newiTempLabel(NULL);
4294 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4295 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4297 if ( IC_TRUE(ifx) ) {
4300 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4303 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4307 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4311 if(s>1 && IC_TRUE(ifx))
4312 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4315 /* mark the icode as generated */
4320 /* if they are both bit variables */
4321 if (AOP_TYPE(left) == AOP_CRY &&
4322 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4323 if(AOP_TYPE(right) == AOP_LIT){
4324 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4326 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4327 emitcode("cpl","c");
4328 } else if(lit == 1L) {
4329 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4331 emitcode("clr","c");
4333 /* AOP_TYPE(right) == AOP_CRY */
4335 symbol *lbl = newiTempLabel(NULL);
4336 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4337 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4338 emitcode("cpl","c");
4339 emitcode("","%05d_DS_:",(lbl->key+100));
4342 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4347 genIfxJump (ifx,"c");
4350 /* if the result is used in an arithmetic operation
4351 then put the result in place */
4354 gencjne(left,right,newiTempLabel(NULL));
4355 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4356 aopPut(AOP(result),"a",0);
4360 genIfxJump (ifx,"a");
4363 /* if the result is used in an arithmetic operation
4364 then put the result in place */
4365 if (AOP_TYPE(result) != AOP_CRY)
4367 /* leave the result in acc */
4371 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4372 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4373 freeAsmop(result,NULL,ic,TRUE);
4376 /*-----------------------------------------------------------------*/
4377 /* ifxForOp - returns the icode containing the ifx for operand */
4378 /*-----------------------------------------------------------------*/
4379 static iCode *ifxForOp ( operand *op, iCode *ic )
4381 /* if true symbol then needs to be assigned */
4382 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4383 if (IS_TRUE_SYMOP(op))
4386 /* if this has register type condition and
4387 the next instruction is ifx with the same operand
4388 and live to of the operand is upto the ifx only then */
4390 ic->next->op == IFX &&
4391 IC_COND(ic->next)->key == op->key &&
4392 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4397 /*-----------------------------------------------------------------*/
4398 /* genAndOp - for && operation */
4399 /*-----------------------------------------------------------------*/
4400 static void genAndOp (iCode *ic)
4402 operand *left,*right, *result;
4405 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4406 /* note here that && operations that are in an
4407 if statement are taken away by backPatchLabels
4408 only those used in arthmetic operations remain */
4409 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4410 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4411 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4413 /* if both are bit variables */
4414 if (AOP_TYPE(left) == AOP_CRY &&
4415 AOP_TYPE(right) == AOP_CRY ) {
4416 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4417 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4420 tlbl = newiTempLabel(NULL);
4422 emitcode("jz","%05d_DS_",tlbl->key+100);
4424 emitcode("","%05d_DS_:",tlbl->key+100);
4428 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4429 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4430 freeAsmop(result,NULL,ic,TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* genOrOp - for || operation */
4436 /*-----------------------------------------------------------------*/
4439 modified this code, but it doesn't appear to ever get called
4442 static void genOrOp (iCode *ic)
4444 operand *left,*right, *result;
4447 /* note here that || operations that are in an
4448 if statement are taken away by backPatchLabels
4449 only those used in arthmetic operations remain */
4450 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4451 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4452 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4453 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4455 /* if both are bit variables */
4456 if (AOP_TYPE(left) == AOP_CRY &&
4457 AOP_TYPE(right) == AOP_CRY ) {
4458 emitcode("clrc","");
4459 emitcode("btfss","(%s >> 3), (%s & 7)",
4460 AOP(left)->aopu.aop_dir,
4461 AOP(left)->aopu.aop_dir);
4462 emitcode("btfsc","(%s >> 3), (%s & 7)",
4463 AOP(right)->aopu.aop_dir,
4464 AOP(right)->aopu.aop_dir);
4465 emitcode("setc","");
4468 tlbl = newiTempLabel(NULL);
4471 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4473 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4478 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4479 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4480 freeAsmop(result,NULL,ic,TRUE);
4483 /*-----------------------------------------------------------------*/
4484 /* isLiteralBit - test if lit == 2^n */
4485 /*-----------------------------------------------------------------*/
4486 static int isLiteralBit(unsigned long lit)
4488 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4489 0x100L,0x200L,0x400L,0x800L,
4490 0x1000L,0x2000L,0x4000L,0x8000L,
4491 0x10000L,0x20000L,0x40000L,0x80000L,
4492 0x100000L,0x200000L,0x400000L,0x800000L,
4493 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4494 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4497 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4498 for(idx = 0; idx < 32; idx++)
4504 /*-----------------------------------------------------------------*/
4505 /* continueIfTrue - */
4506 /*-----------------------------------------------------------------*/
4507 static void continueIfTrue (iCode *ic)
4509 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4511 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4515 /*-----------------------------------------------------------------*/
4517 /*-----------------------------------------------------------------*/
4518 static void jumpIfTrue (iCode *ic)
4520 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4522 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4526 /*-----------------------------------------------------------------*/
4527 /* jmpTrueOrFalse - */
4528 /*-----------------------------------------------------------------*/
4529 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4531 // ugly but optimized by peephole
4532 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4534 symbol *nlbl = newiTempLabel(NULL);
4535 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4536 emitcode("","%05d_DS_:",tlbl->key+100);
4537 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4538 emitcode("","%05d_DS_:",nlbl->key+100);
4541 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4542 emitcode("","%05d_DS_:",tlbl->key+100);
4547 /*-----------------------------------------------------------------*/
4548 /* genAnd - code for and */
4549 /*-----------------------------------------------------------------*/
4550 static void genAnd (iCode *ic, iCode *ifx)
4552 operand *left, *right, *result;
4554 unsigned long lit = 0L;
4558 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4559 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4560 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4561 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4564 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4566 AOP_TYPE(left), AOP_TYPE(right));
4567 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4569 AOP_SIZE(left), AOP_SIZE(right));
4572 /* if left is a literal & right is not then exchange them */
4573 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4574 AOP_NEEDSACC(left)) {
4575 operand *tmp = right ;
4580 /* if result = right then exchange them */
4581 if(sameRegs(AOP(result),AOP(right))){
4582 operand *tmp = right ;
4587 /* if right is bit then exchange them */
4588 if (AOP_TYPE(right) == AOP_CRY &&
4589 AOP_TYPE(left) != AOP_CRY){
4590 operand *tmp = right ;
4594 if(AOP_TYPE(right) == AOP_LIT)
4595 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4597 size = AOP_SIZE(result);
4600 // result = bit & yy;
4601 if (AOP_TYPE(left) == AOP_CRY){
4602 // c = bit & literal;
4603 if(AOP_TYPE(right) == AOP_LIT){
4605 if(size && sameRegs(AOP(result),AOP(left)))
4608 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4611 if(size && (AOP_TYPE(result) == AOP_CRY)){
4612 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4615 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4619 emitcode("clr","c");
4622 if (AOP_TYPE(right) == AOP_CRY){
4624 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4625 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4628 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4630 emitcode("rrc","a");
4631 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4639 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4640 genIfxJump(ifx, "c");
4644 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4645 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4646 if((AOP_TYPE(right) == AOP_LIT) &&
4647 (AOP_TYPE(result) == AOP_CRY) &&
4648 (AOP_TYPE(left) != AOP_CRY)){
4649 int posbit = isLiteralBit(lit);
4653 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4656 emitcode("mov","c,acc.%d",posbit&0x07);
4660 sprintf(buffer,"acc.%d",posbit&0x07);
4661 genIfxJump(ifx, buffer);
4666 symbol *tlbl = newiTempLabel(NULL);
4667 int sizel = AOP_SIZE(left);
4669 emitcode("setb","c");
4671 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4672 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4674 if((posbit = isLiteralBit(bytelit)) != 0)
4675 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4677 if(bytelit != 0x0FFL)
4678 emitcode("anl","a,%s",
4679 aopGet(AOP(right),offset,FALSE,TRUE));
4680 emitcode("jnz","%05d_DS_",tlbl->key+100);
4685 // bit = left & literal
4687 emitcode("clr","c");
4688 emitcode("","%05d_DS_:",tlbl->key+100);
4690 // if(left & literal)
4693 jmpTrueOrFalse(ifx, tlbl);
4701 /* if left is same as result */
4702 if(sameRegs(AOP(result),AOP(left))){
4703 for(;size--; offset++,lit>>=8) {
4704 if(AOP_TYPE(right) == AOP_LIT){
4705 switch(lit & 0xff) {
4707 /* and'ing with 0 has clears the result */
4708 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4711 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4716 int p = my_powof2( (~lit) & 0xff );
4718 /* only one bit is set in the literal, so use a bcf instruction */
4719 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4721 emitcode("movlw","0x%x", (lit & 0xff));
4722 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4727 if (AOP_TYPE(left) == AOP_ACC)
4728 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4730 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4731 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4738 // left & result in different registers
4739 if(AOP_TYPE(result) == AOP_CRY){
4741 // if(size), result in bit
4742 // if(!size && ifx), conditional oper: if(left & right)
4743 symbol *tlbl = newiTempLabel(NULL);
4744 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4746 emitcode("setb","c");
4748 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4749 emitcode("anl","a,%s",
4750 aopGet(AOP(left),offset,FALSE,FALSE));
4751 emitcode("jnz","%05d_DS_",tlbl->key+100);
4756 emitcode("","%05d_DS_:",tlbl->key+100);
4759 jmpTrueOrFalse(ifx, tlbl);
4761 for(;(size--);offset++) {
4763 // result = left & right
4764 if(AOP_TYPE(right) == AOP_LIT){
4765 int t = (lit >> (offset*8)) & 0x0FFL;
4768 emitcode("clrf","%s",
4769 aopGet(AOP(result),offset,FALSE,FALSE));
4772 emitcode("movf","%s,w",
4773 aopGet(AOP(left),offset,FALSE,FALSE));
4774 emitcode("movwf","%s",
4775 aopGet(AOP(result),offset,FALSE,FALSE));
4778 emitcode("movlw","0x%x",t);
4779 emitcode("andwf","%s,w",
4780 aopGet(AOP(left),offset,FALSE,FALSE));
4781 emitcode("movwf","%s",
4782 aopGet(AOP(result),offset,FALSE,FALSE));
4788 if (AOP_TYPE(left) == AOP_ACC)
4789 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4791 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4792 emitcode("andwf","%s,w",
4793 aopGet(AOP(left),offset,FALSE,FALSE));
4795 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4801 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4802 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803 freeAsmop(result,NULL,ic,TRUE);
4806 /*-----------------------------------------------------------------*/
4807 /* genOr - code for or */
4808 /*-----------------------------------------------------------------*/
4809 static void genOr (iCode *ic, iCode *ifx)
4811 operand *left, *right, *result;
4813 unsigned long lit = 0L;
4815 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4817 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4818 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4819 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4822 /* if left is a literal & right is not then exchange them */
4823 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4824 AOP_NEEDSACC(left)) {
4825 operand *tmp = right ;
4830 /* if result = right then exchange them */
4831 if(sameRegs(AOP(result),AOP(right))){
4832 operand *tmp = right ;
4837 /* if right is bit then exchange them */
4838 if (AOP_TYPE(right) == AOP_CRY &&
4839 AOP_TYPE(left) != AOP_CRY){
4840 operand *tmp = right ;
4845 if(AOP_TYPE(right) == AOP_LIT)
4846 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4848 size = AOP_SIZE(result);
4852 if (AOP_TYPE(left) == AOP_CRY){
4853 if(AOP_TYPE(right) == AOP_LIT){
4854 // c = bit & literal;
4856 // lit != 0 => result = 1
4857 if(AOP_TYPE(result) == AOP_CRY){
4859 emitcode("bsf","(%s >> 3), (%s & 7)",
4860 AOP(result)->aopu.aop_dir,
4861 AOP(result)->aopu.aop_dir);
4863 continueIfTrue(ifx);
4866 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4868 // lit == 0 => result = left
4869 if(size && sameRegs(AOP(result),AOP(left)))
4871 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4874 if (AOP_TYPE(right) == AOP_CRY){
4875 if(sameRegs(AOP(result),AOP(left))){
4877 emitcode("bcf","(%s >> 3), (%s & 7)",
4878 AOP(result)->aopu.aop_dir,
4879 AOP(result)->aopu.aop_dir);
4880 emitcode("btfsc","(%s >> 3), (%s & 7)",
4881 AOP(right)->aopu.aop_dir,
4882 AOP(right)->aopu.aop_dir);
4883 emitcode("bsf","(%s >> 3), (%s & 7)",
4884 AOP(result)->aopu.aop_dir,
4885 AOP(result)->aopu.aop_dir);
4888 emitcode("bcf","(%s >> 3), (%s & 7)",
4889 AOP(result)->aopu.aop_dir,
4890 AOP(result)->aopu.aop_dir);
4891 emitcode("btfss","(%s >> 3), (%s & 7)",
4892 AOP(right)->aopu.aop_dir,
4893 AOP(right)->aopu.aop_dir);
4894 emitcode("btfsc","(%s >> 3), (%s & 7)",
4895 AOP(left)->aopu.aop_dir,
4896 AOP(left)->aopu.aop_dir);
4897 emitcode("bsf","(%s >> 3), (%s & 7)",
4898 AOP(result)->aopu.aop_dir,
4899 AOP(result)->aopu.aop_dir);
4904 symbol *tlbl = newiTempLabel(NULL);
4905 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4906 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4907 emitcode(";XXX setb","c");
4908 emitcode(";XXX jb","%s,%05d_DS_",
4909 AOP(left)->aopu.aop_dir,tlbl->key+100);
4911 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4912 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4913 jmpTrueOrFalse(ifx, tlbl);
4917 emitcode("","%05d_DS_:",tlbl->key+100);
4926 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4927 genIfxJump(ifx, "c");
4931 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4932 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4933 if((AOP_TYPE(right) == AOP_LIT) &&
4934 (AOP_TYPE(result) == AOP_CRY) &&
4935 (AOP_TYPE(left) != AOP_CRY)){
4937 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4940 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4942 continueIfTrue(ifx);
4945 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4946 // lit = 0, result = boolean(left)
4948 emitcode(";XXX setb","c");
4951 symbol *tlbl = newiTempLabel(NULL);
4952 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4954 emitcode("","%05d_DS_:",tlbl->key+100);
4956 genIfxJump (ifx,"a");
4964 /* if left is same as result */
4965 if(sameRegs(AOP(result),AOP(left))){
4966 for(;size--; offset++,lit>>=8) {
4967 if(AOP_TYPE(right) == AOP_LIT){
4968 if((lit & 0xff) == 0)
4969 /* or'ing with 0 has no effect */
4972 int p = my_powof2(lit & 0xff);
4974 /* only one bit is set in the literal, so use a bsf instruction */
4975 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4977 emitcode("movlw","0x%x", (lit & 0xff));
4978 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4983 if (AOP_TYPE(left) == AOP_ACC)
4984 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4986 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4987 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4993 // left & result in different registers
4994 if(AOP_TYPE(result) == AOP_CRY){
4996 // if(size), result in bit
4997 // if(!size && ifx), conditional oper: if(left | right)
4998 symbol *tlbl = newiTempLabel(NULL);
4999 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5000 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5003 emitcode(";XXX setb","c");
5005 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5006 emitcode(";XXX orl","a,%s",
5007 aopGet(AOP(left),offset,FALSE,FALSE));
5008 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5013 emitcode("","%05d_DS_:",tlbl->key+100);
5016 jmpTrueOrFalse(ifx, tlbl);
5017 } else for(;(size--);offset++){
5019 // result = left & right
5020 if(AOP_TYPE(right) == AOP_LIT){
5021 int t = (lit >> (offset*8)) & 0x0FFL;
5024 emitcode("movf","%s,w",
5025 aopGet(AOP(left),offset,FALSE,FALSE));
5026 emitcode("movwf","%s",
5027 aopGet(AOP(result),offset,FALSE,FALSE));
5030 emitcode("movlw","0x%x",t);
5031 emitcode("iorwf","%s,w",
5032 aopGet(AOP(left),offset,FALSE,FALSE));
5033 emitcode("movwf","%s",
5034 aopGet(AOP(result),offset,FALSE,FALSE));
5040 // faster than result <- left, anl result,right
5041 // and better if result is SFR
5042 if (AOP_TYPE(left) == AOP_ACC)
5043 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5045 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5046 emitcode("iorwf","%s,w",
5047 aopGet(AOP(left),offset,FALSE,FALSE));
5049 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5054 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5055 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5056 freeAsmop(result,NULL,ic,TRUE);
5059 /*-----------------------------------------------------------------*/
5060 /* genXor - code for xclusive or */
5061 /*-----------------------------------------------------------------*/
5062 static void genXor (iCode *ic, iCode *ifx)
5064 operand *left, *right, *result;
5066 unsigned long lit = 0L;
5068 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5070 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5071 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5072 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5074 /* if left is a literal & right is not ||
5075 if left needs acc & right does not */
5076 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5077 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5078 operand *tmp = right ;
5083 /* if result = right then exchange them */
5084 if(sameRegs(AOP(result),AOP(right))){
5085 operand *tmp = right ;
5090 /* if right is bit then exchange them */
5091 if (AOP_TYPE(right) == AOP_CRY &&
5092 AOP_TYPE(left) != AOP_CRY){
5093 operand *tmp = right ;
5097 if(AOP_TYPE(right) == AOP_LIT)
5098 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5100 size = AOP_SIZE(result);
5104 if (AOP_TYPE(left) == AOP_CRY){
5105 if(AOP_TYPE(right) == AOP_LIT){
5106 // c = bit & literal;
5108 // lit>>1 != 0 => result = 1
5109 if(AOP_TYPE(result) == AOP_CRY){
5111 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5113 continueIfTrue(ifx);
5116 emitcode("setb","c");
5120 // lit == 0, result = left
5121 if(size && sameRegs(AOP(result),AOP(left)))
5123 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5125 // lit == 1, result = not(left)
5126 if(size && sameRegs(AOP(result),AOP(left))){
5127 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5130 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5131 emitcode("cpl","c");
5138 symbol *tlbl = newiTempLabel(NULL);
5139 if (AOP_TYPE(right) == AOP_CRY){
5141 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5144 int sizer = AOP_SIZE(right);
5146 // if val>>1 != 0, result = 1
5147 emitcode("setb","c");
5149 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5151 // test the msb of the lsb
5152 emitcode("anl","a,#0xfe");
5153 emitcode("jnz","%05d_DS_",tlbl->key+100);
5157 emitcode("rrc","a");
5159 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5160 emitcode("cpl","c");
5161 emitcode("","%05d_DS_:",(tlbl->key+100));
5168 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5169 genIfxJump(ifx, "c");
5173 if(sameRegs(AOP(result),AOP(left))){
5174 /* if left is same as result */
5175 for(;size--; offset++) {
5176 if(AOP_TYPE(right) == AOP_LIT){
5177 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5180 if (IS_AOP_PREG(left)) {
5181 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5182 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5183 aopPut(AOP(result),"a",offset);
5185 emitcode("xrl","%s,%s",
5186 aopGet(AOP(left),offset,FALSE,TRUE),
5187 aopGet(AOP(right),offset,FALSE,FALSE));
5189 if (AOP_TYPE(left) == AOP_ACC)
5190 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5192 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5193 if (IS_AOP_PREG(left)) {
5194 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5195 aopPut(AOP(result),"a",offset);
5197 emitcode("xrl","%s,a",
5198 aopGet(AOP(left),offset,FALSE,TRUE));
5203 // left & result in different registers
5204 if(AOP_TYPE(result) == AOP_CRY){
5206 // if(size), result in bit
5207 // if(!size && ifx), conditional oper: if(left ^ right)
5208 symbol *tlbl = newiTempLabel(NULL);
5209 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5211 emitcode("setb","c");
5213 if((AOP_TYPE(right) == AOP_LIT) &&
5214 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5215 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5217 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5218 emitcode("xrl","a,%s",
5219 aopGet(AOP(left),offset,FALSE,FALSE));
5221 emitcode("jnz","%05d_DS_",tlbl->key+100);
5226 emitcode("","%05d_DS_:",tlbl->key+100);
5229 jmpTrueOrFalse(ifx, tlbl);
5230 } else for(;(size--);offset++){
5232 // result = left & right
5233 if(AOP_TYPE(right) == AOP_LIT){
5234 int t = (lit >> (offset*8)) & 0x0FFL;
5237 emitcode("movf","%s,w",
5238 aopGet(AOP(left),offset,FALSE,FALSE));
5239 emitcode("movwf","%s",
5240 aopGet(AOP(result),offset,FALSE,FALSE));
5243 emitcode("comf","%s,w",
5244 aopGet(AOP(left),offset,FALSE,FALSE));
5245 emitcode("movwf","%s",
5246 aopGet(AOP(result),offset,FALSE,FALSE));
5249 emitcode("movlw","0x%x",t);
5250 emitcode("xorwf","%s,w",
5251 aopGet(AOP(left),offset,FALSE,FALSE));
5252 emitcode("movwf","%s",
5253 aopGet(AOP(result),offset,FALSE,FALSE));
5259 // faster than result <- left, anl result,right
5260 // and better if result is SFR
5261 if (AOP_TYPE(left) == AOP_ACC)
5262 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5264 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5265 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5267 if ( AOP_TYPE(result) != AOP_ACC)
5268 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5273 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5274 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275 freeAsmop(result,NULL,ic,TRUE);
5278 /*-----------------------------------------------------------------*/
5279 /* genInline - write the inline code out */
5280 /*-----------------------------------------------------------------*/
5281 static void genInline (iCode *ic)
5283 char buffer[MAX_INLINEASM];
5287 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5289 _G.inLine += (!options.asmpeep);
5290 strcpy(buffer,IC_INLINE(ic));
5292 /* emit each line as a code */
5311 /* emitcode("",buffer); */
5312 _G.inLine -= (!options.asmpeep);
5315 /*-----------------------------------------------------------------*/
5316 /* genRRC - rotate right with carry */
5317 /*-----------------------------------------------------------------*/
5318 static void genRRC (iCode *ic)
5320 operand *left , *result ;
5321 int size, offset = 0;
5324 /* rotate right with carry */
5326 result=IC_RESULT(ic);
5327 aopOp (left,ic,FALSE);
5328 aopOp (result,ic,FALSE);
5330 /* move it to the result */
5331 size = AOP_SIZE(result);
5335 l = aopGet(AOP(left),offset,FALSE,FALSE);
5337 emitcode("rrc","a");
5338 if (AOP_SIZE(result) > 1)
5339 aopPut(AOP(result),"a",offset--);
5341 /* now we need to put the carry into the
5342 highest order byte of the result */
5343 if (AOP_SIZE(result) > 1) {
5344 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5347 emitcode("mov","acc.7,c");
5348 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5349 freeAsmop(left,NULL,ic,TRUE);
5350 freeAsmop(result,NULL,ic,TRUE);
5353 /*-----------------------------------------------------------------*/
5354 /* genRLC - generate code for rotate left with carry */
5355 /*-----------------------------------------------------------------*/
5356 static void genRLC (iCode *ic)
5358 operand *left , *result ;
5359 int size, offset = 0;
5362 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5363 /* rotate right with carry */
5365 result=IC_RESULT(ic);
5366 aopOp (left,ic,FALSE);
5367 aopOp (result,ic,FALSE);
5369 /* move it to the result */
5370 size = AOP_SIZE(result);
5373 l = aopGet(AOP(left),offset,FALSE,FALSE);
5375 emitcode("add","a,acc");
5376 if (AOP_SIZE(result) > 1)
5377 aopPut(AOP(result),"a",offset++);
5379 l = aopGet(AOP(left),offset,FALSE,FALSE);
5381 emitcode("rlc","a");
5382 if (AOP_SIZE(result) > 1)
5383 aopPut(AOP(result),"a",offset++);
5386 /* now we need to put the carry into the
5387 highest order byte of the result */
5388 if (AOP_SIZE(result) > 1) {
5389 l = aopGet(AOP(result),0,FALSE,FALSE);
5392 emitcode("mov","acc.0,c");
5393 aopPut(AOP(result),"a",0);
5394 freeAsmop(left,NULL,ic,TRUE);
5395 freeAsmop(result,NULL,ic,TRUE);
5398 /*-----------------------------------------------------------------*/
5399 /* genGetHbit - generates code get highest order bit */
5400 /*-----------------------------------------------------------------*/
5401 static void genGetHbit (iCode *ic)
5403 operand *left, *result;
5405 result=IC_RESULT(ic);
5406 aopOp (left,ic,FALSE);
5407 aopOp (result,ic,FALSE);
5409 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5410 /* get the highest order byte into a */
5411 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5412 if(AOP_TYPE(result) == AOP_CRY){
5413 emitcode("rlc","a");
5418 emitcode("anl","a,#0x01");
5423 freeAsmop(left,NULL,ic,TRUE);
5424 freeAsmop(result,NULL,ic,TRUE);
5427 /*-----------------------------------------------------------------*/
5428 /* AccRol - rotate left accumulator by known count */
5429 /*-----------------------------------------------------------------*/
5430 static void AccRol (int shCount)
5432 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5433 shCount &= 0x0007; // shCount : 0..7
5445 emitcode("swap","a");
5449 emitcode("swap","a");
5452 emitcode("swap","a");
5465 /*-----------------------------------------------------------------*/
5466 /* AccLsh - left shift accumulator by known count */
5467 /*-----------------------------------------------------------------*/
5468 static void AccLsh (int shCount)
5470 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5473 emitcode("add","a,acc");
5476 emitcode("add","a,acc");
5477 emitcode("add","a,acc");
5479 /* rotate left accumulator */
5481 /* and kill the lower order bits */
5482 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5487 /*-----------------------------------------------------------------*/
5488 /* AccRsh - right shift accumulator by known count */
5489 /*-----------------------------------------------------------------*/
5490 static void AccRsh (int shCount)
5492 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5496 emitcode("rrc","a");
5498 /* rotate right accumulator */
5499 AccRol(8 - shCount);
5500 /* and kill the higher order bits */
5501 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5506 /*-----------------------------------------------------------------*/
5507 /* AccSRsh - signed right shift accumulator by known count */
5508 /*-----------------------------------------------------------------*/
5509 static void AccSRsh (int shCount)
5512 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5515 emitcode("mov","c,acc.7");
5516 emitcode("rrc","a");
5517 } else if(shCount == 2){
5518 emitcode("mov","c,acc.7");
5519 emitcode("rrc","a");
5520 emitcode("mov","c,acc.7");
5521 emitcode("rrc","a");
5523 tlbl = newiTempLabel(NULL);
5524 /* rotate right accumulator */
5525 AccRol(8 - shCount);
5526 /* and kill the higher order bits */
5527 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5528 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5529 emitcode("orl","a,#0x%02x",
5530 (unsigned char)~SRMask[shCount]);
5531 emitcode("","%05d_DS_:",tlbl->key+100);
5536 /*-----------------------------------------------------------------*/
5537 /* shiftR1Left2Result - shift right one byte from left to result */
5538 /*-----------------------------------------------------------------*/
5539 static void shiftR1Left2Result (operand *left, int offl,
5540 operand *result, int offr,
5541 int shCount, int sign)
5543 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5544 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5545 /* shift right accumulator */
5550 aopPut(AOP(result),"a",offr);
5553 /*-----------------------------------------------------------------*/
5554 /* shiftL1Left2Result - shift left one byte from left to result */
5555 /*-----------------------------------------------------------------*/
5556 static void shiftL1Left2Result (operand *left, int offl,
5557 operand *result, int offr, int shCount)
5560 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5561 l = aopGet(AOP(left),offl,FALSE,FALSE);
5563 /* shift left accumulator */
5565 aopPut(AOP(result),"a",offr);
5568 /*-----------------------------------------------------------------*/
5569 /* movLeft2Result - move byte from left to result */
5570 /*-----------------------------------------------------------------*/
5571 static void movLeft2Result (operand *left, int offl,
5572 operand *result, int offr, int sign)
5575 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5576 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5577 l = aopGet(AOP(left),offl,FALSE,FALSE);
5579 if (*l == '@' && (IS_AOP_PREG(result))) {
5580 emitcode("mov","a,%s",l);
5581 aopPut(AOP(result),"a",offr);
5584 aopPut(AOP(result),l,offr);
5586 /* MSB sign in acc.7 ! */
5587 if(getDataSize(left) == offl+1){
5588 emitcode("mov","a,%s",l);
5589 aopPut(AOP(result),"a",offr);
5596 /*-----------------------------------------------------------------*/
5597 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5598 /*-----------------------------------------------------------------*/
5599 static void AccAXRrl1 (char *x)
5601 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5602 emitcode("rrc","a");
5603 emitcode("xch","a,%s", x);
5604 emitcode("rrc","a");
5605 emitcode("xch","a,%s", x);
5608 /*-----------------------------------------------------------------*/
5609 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5610 /*-----------------------------------------------------------------*/
5611 static void AccAXLrl1 (char *x)
5613 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5614 emitcode("xch","a,%s",x);
5615 emitcode("rlc","a");
5616 emitcode("xch","a,%s",x);
5617 emitcode("rlc","a");
5620 /*-----------------------------------------------------------------*/
5621 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5622 /*-----------------------------------------------------------------*/
5623 static void AccAXLsh1 (char *x)
5625 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5626 emitcode("xch","a,%s",x);
5627 emitcode("add","a,acc");
5628 emitcode("xch","a,%s",x);
5629 emitcode("rlc","a");
5632 /*-----------------------------------------------------------------*/
5633 /* AccAXLsh - left shift a:x by known count (0..7) */
5634 /*-----------------------------------------------------------------*/
5635 static void AccAXLsh (char *x, int shCount)
5637 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5650 case 5 : // AAAAABBB:CCCCCDDD
5651 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5652 emitcode("anl","a,#0x%02x",
5653 SLMask[shCount]); // BBB00000:CCCCCDDD
5654 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5655 AccRol(shCount); // DDDCCCCC:BBB00000
5656 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5657 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5658 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5659 emitcode("anl","a,#0x%02x",
5660 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5661 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5662 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5664 case 6 : // AAAAAABB:CCCCCCDD
5665 emitcode("anl","a,#0x%02x",
5666 SRMask[shCount]); // 000000BB:CCCCCCDD
5667 emitcode("mov","c,acc.0"); // c = B
5668 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5669 AccAXRrl1(x); // BCCCCCCD:D000000B
5670 AccAXRrl1(x); // BBCCCCCC:DD000000
5672 case 7 : // a:x <<= 7
5673 emitcode("anl","a,#0x%02x",
5674 SRMask[shCount]); // 0000000B:CCCCCCCD
5675 emitcode("mov","c,acc.0"); // c = B
5676 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5677 AccAXRrl1(x); // BCCCCCCC:D0000000
5684 /*-----------------------------------------------------------------*/
5685 /* AccAXRsh - right shift a:x known count (0..7) */
5686 /*-----------------------------------------------------------------*/
5687 static void AccAXRsh (char *x, int shCount)
5689 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5695 AccAXRrl1(x); // 0->a:x
5699 AccAXRrl1(x); // 0->a:x
5701 AccAXRrl1(x); // 0->a:x
5705 case 5 : // AAAAABBB:CCCCCDDD = a:x
5706 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5707 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5708 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5709 emitcode("anl","a,#0x%02x",
5710 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5711 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5712 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5713 emitcode("anl","a,#0x%02x",
5714 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5715 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5716 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5717 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5719 case 6 : // AABBBBBB:CCDDDDDD
5720 emitcode("mov","c,acc.7");
5721 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5722 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5723 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5724 emitcode("anl","a,#0x%02x",
5725 SRMask[shCount]); // 000000AA:BBBBBBCC
5727 case 7 : // ABBBBBBB:CDDDDDDD
5728 emitcode("mov","c,acc.7"); // c = A
5729 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5730 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5731 emitcode("anl","a,#0x%02x",
5732 SRMask[shCount]); // 0000000A:BBBBBBBC
5739 /*-----------------------------------------------------------------*/
5740 /* AccAXRshS - right shift signed a:x known count (0..7) */
5741 /*-----------------------------------------------------------------*/
5742 static void AccAXRshS (char *x, int shCount)
5745 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5750 emitcode("mov","c,acc.7");
5751 AccAXRrl1(x); // s->a:x
5754 emitcode("mov","c,acc.7");
5755 AccAXRrl1(x); // s->a:x
5756 emitcode("mov","c,acc.7");
5757 AccAXRrl1(x); // s->a:x
5761 case 5 : // AAAAABBB:CCCCCDDD = a:x
5762 tlbl = newiTempLabel(NULL);
5763 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5764 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5765 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5766 emitcode("anl","a,#0x%02x",
5767 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5768 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5769 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5770 emitcode("anl","a,#0x%02x",
5771 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5772 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5773 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5774 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5775 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5776 emitcode("orl","a,#0x%02x",
5777 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5778 emitcode("","%05d_DS_:",tlbl->key+100);
5779 break; // SSSSAAAA:BBBCCCCC
5780 case 6 : // AABBBBBB:CCDDDDDD
5781 tlbl = newiTempLabel(NULL);
5782 emitcode("mov","c,acc.7");
5783 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5784 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5785 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5786 emitcode("anl","a,#0x%02x",
5787 SRMask[shCount]); // 000000AA:BBBBBBCC
5788 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5789 emitcode("orl","a,#0x%02x",
5790 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5791 emitcode("","%05d_DS_:",tlbl->key+100);
5793 case 7 : // ABBBBBBB:CDDDDDDD
5794 tlbl = newiTempLabel(NULL);
5795 emitcode("mov","c,acc.7"); // c = A
5796 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5797 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5798 emitcode("anl","a,#0x%02x",
5799 SRMask[shCount]); // 0000000A:BBBBBBBC
5800 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5801 emitcode("orl","a,#0x%02x",
5802 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5803 emitcode("","%05d_DS_:",tlbl->key+100);
5810 /*-----------------------------------------------------------------*/
5811 /* shiftL2Left2Result - shift left two bytes from left to result */
5812 /*-----------------------------------------------------------------*/
5813 static void shiftL2Left2Result (operand *left, int offl,
5814 operand *result, int offr, int shCount)
5816 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5817 if(sameRegs(AOP(result), AOP(left)) &&
5818 ((offl + MSB16) == offr)){
5819 /* don't crash result[offr] */
5820 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5821 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5823 movLeft2Result(left,offl, result, offr, 0);
5824 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5826 /* ax << shCount (x = lsb(result))*/
5827 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5828 aopPut(AOP(result),"a",offr+MSB16);
5832 /*-----------------------------------------------------------------*/
5833 /* shiftR2Left2Result - shift right two bytes from left to result */
5834 /*-----------------------------------------------------------------*/
5835 static void shiftR2Left2Result (operand *left, int offl,
5836 operand *result, int offr,
5837 int shCount, int sign)
5839 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5840 if(sameRegs(AOP(result), AOP(left)) &&
5841 ((offl + MSB16) == offr)){
5842 /* don't crash result[offr] */
5843 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5844 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5846 movLeft2Result(left,offl, result, offr, 0);
5847 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5849 /* a:x >> shCount (x = lsb(result))*/
5851 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5853 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5854 if(getDataSize(result) > 1)
5855 aopPut(AOP(result),"a",offr+MSB16);
5858 /*-----------------------------------------------------------------*/
5859 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5860 /*-----------------------------------------------------------------*/
5861 static void shiftLLeftOrResult (operand *left, int offl,
5862 operand *result, int offr, int shCount)
5864 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5865 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5866 /* shift left accumulator */
5868 /* or with result */
5869 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5870 /* back to result */
5871 aopPut(AOP(result),"a",offr);
5874 /*-----------------------------------------------------------------*/
5875 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5876 /*-----------------------------------------------------------------*/
5877 static void shiftRLeftOrResult (operand *left, int offl,
5878 operand *result, int offr, int shCount)
5880 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5881 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5882 /* shift right accumulator */
5884 /* or with result */
5885 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5886 /* back to result */
5887 aopPut(AOP(result),"a",offr);
5890 /*-----------------------------------------------------------------*/
5891 /* genlshOne - left shift a one byte quantity by known count */
5892 /*-----------------------------------------------------------------*/
5893 static void genlshOne (operand *result, operand *left, int shCount)
5895 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5896 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5899 /*-----------------------------------------------------------------*/
5900 /* genlshTwo - left shift two bytes by known amount != 0 */
5901 /*-----------------------------------------------------------------*/
5902 static void genlshTwo (operand *result,operand *left, int shCount)
5906 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5907 size = getDataSize(result);
5909 /* if shCount >= 8 */
5915 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5917 movLeft2Result(left, LSB, result, MSB16, 0);
5919 aopPut(AOP(result),zero,LSB);
5922 /* 1 <= shCount <= 7 */
5925 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5927 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5931 /*-----------------------------------------------------------------*/
5932 /* shiftLLong - shift left one long from left to result */
5933 /* offl = LSB or MSB16 */
5934 /*-----------------------------------------------------------------*/
5935 static void shiftLLong (operand *left, operand *result, int offr )
5938 int size = AOP_SIZE(result);
5940 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5941 if(size >= LSB+offr){
5942 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5944 emitcode("add","a,acc");
5945 if (sameRegs(AOP(left),AOP(result)) &&
5946 size >= MSB16+offr && offr != LSB )
5947 emitcode("xch","a,%s",
5948 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5950 aopPut(AOP(result),"a",LSB+offr);
5953 if(size >= MSB16+offr){
5954 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5955 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5958 emitcode("rlc","a");
5959 if (sameRegs(AOP(left),AOP(result)) &&
5960 size >= MSB24+offr && offr != LSB)
5961 emitcode("xch","a,%s",
5962 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5964 aopPut(AOP(result),"a",MSB16+offr);
5967 if(size >= MSB24+offr){
5968 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5969 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5972 emitcode("rlc","a");
5973 if (sameRegs(AOP(left),AOP(result)) &&
5974 size >= MSB32+offr && offr != LSB )
5975 emitcode("xch","a,%s",
5976 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5978 aopPut(AOP(result),"a",MSB24+offr);
5981 if(size > MSB32+offr){
5982 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5983 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5986 emitcode("rlc","a");
5987 aopPut(AOP(result),"a",MSB32+offr);
5990 aopPut(AOP(result),zero,LSB);
5993 /*-----------------------------------------------------------------*/
5994 /* genlshFour - shift four byte by a known amount != 0 */
5995 /*-----------------------------------------------------------------*/
5996 static void genlshFour (operand *result, operand *left, int shCount)
6000 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6001 size = AOP_SIZE(result);
6003 /* if shifting more that 3 bytes */
6004 if (shCount >= 24 ) {
6007 /* lowest order of left goes to the highest
6008 order of the destination */
6009 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6011 movLeft2Result(left, LSB, result, MSB32, 0);
6012 aopPut(AOP(result),zero,LSB);
6013 aopPut(AOP(result),zero,MSB16);
6014 aopPut(AOP(result),zero,MSB32);
6018 /* more than two bytes */
6019 else if ( shCount >= 16 ) {
6020 /* lower order two bytes goes to higher order two bytes */
6022 /* if some more remaining */
6024 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6026 movLeft2Result(left, MSB16, result, MSB32, 0);
6027 movLeft2Result(left, LSB, result, MSB24, 0);
6029 aopPut(AOP(result),zero,MSB16);
6030 aopPut(AOP(result),zero,LSB);
6034 /* if more than 1 byte */
6035 else if ( shCount >= 8 ) {
6036 /* lower order three bytes goes to higher order three bytes */
6040 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6042 movLeft2Result(left, LSB, result, MSB16, 0);
6044 else{ /* size = 4 */
6046 movLeft2Result(left, MSB24, result, MSB32, 0);
6047 movLeft2Result(left, MSB16, result, MSB24, 0);
6048 movLeft2Result(left, LSB, result, MSB16, 0);
6049 aopPut(AOP(result),zero,LSB);
6051 else if(shCount == 1)
6052 shiftLLong(left, result, MSB16);
6054 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6055 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6056 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6057 aopPut(AOP(result),zero,LSB);
6062 /* 1 <= shCount <= 7 */
6063 else if(shCount <= 2){
6064 shiftLLong(left, result, LSB);
6066 shiftLLong(result, result, LSB);
6068 /* 3 <= shCount <= 7, optimize */
6070 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6071 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6072 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6076 /*-----------------------------------------------------------------*/
6077 /* genLeftShiftLiteral - left shifting by known count */
6078 /*-----------------------------------------------------------------*/
6079 static void genLeftShiftLiteral (operand *left,
6084 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6087 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6088 freeAsmop(right,NULL,ic,TRUE);
6090 aopOp(left,ic,FALSE);
6091 aopOp(result,ic,FALSE);
6093 size = getSize(operandType(result));
6096 emitcode("; shift left ","result %d, left %d",size,
6100 /* I suppose that the left size >= result size */
6103 movLeft2Result(left, size, result, size, 0);
6107 else if(shCount >= (size * 8))
6109 aopPut(AOP(result),zero,size);
6113 genlshOne (result,left,shCount);
6118 genlshTwo (result,left,shCount);
6122 genlshFour (result,left,shCount);
6126 freeAsmop(left,NULL,ic,TRUE);
6127 freeAsmop(result,NULL,ic,TRUE);
6130 /*-----------------------------------------------------------------*/
6131 /* genLeftShift - generates code for left shifting */
6132 /*-----------------------------------------------------------------*/
6133 static void genLeftShift (iCode *ic)
6135 operand *left,*right, *result;
6138 symbol *tlbl , *tlbl1;
6140 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6142 right = IC_RIGHT(ic);
6144 result = IC_RESULT(ic);
6146 aopOp(right,ic,FALSE);
6148 /* if the shift count is known then do it
6149 as efficiently as possible */
6150 if (AOP_TYPE(right) == AOP_LIT) {
6151 genLeftShiftLiteral (left,right,result,ic);
6155 /* shift count is unknown then we have to form
6156 a loop get the loop count in B : Note: we take
6157 only the lower order byte since shifting
6158 more that 32 bits make no sense anyway, ( the
6159 largest size of an object can be only 32 bits ) */
6161 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6162 emitcode("inc","b");
6163 freeAsmop (right,NULL,ic,TRUE);
6164 aopOp(left,ic,FALSE);
6165 aopOp(result,ic,FALSE);
6167 /* now move the left to the result if they are not the
6169 if (!sameRegs(AOP(left),AOP(result)) &&
6170 AOP_SIZE(result) > 1) {
6172 size = AOP_SIZE(result);
6175 l = aopGet(AOP(left),offset,FALSE,TRUE);
6176 if (*l == '@' && (IS_AOP_PREG(result))) {
6178 emitcode("mov","a,%s",l);
6179 aopPut(AOP(result),"a",offset);
6181 aopPut(AOP(result),l,offset);
6186 tlbl = newiTempLabel(NULL);
6187 size = AOP_SIZE(result);
6189 tlbl1 = newiTempLabel(NULL);
6191 /* if it is only one byte then */
6193 symbol *tlbl1 = newiTempLabel(NULL);
6195 l = aopGet(AOP(left),0,FALSE,FALSE);
6197 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6198 emitcode("","%05d_DS_:",tlbl->key+100);
6199 emitcode("add","a,acc");
6200 emitcode("","%05d_DS_:",tlbl1->key+100);
6201 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6202 aopPut(AOP(result),"a",0);
6206 reAdjustPreg(AOP(result));
6208 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6209 emitcode("","%05d_DS_:",tlbl->key+100);
6210 l = aopGet(AOP(result),offset,FALSE,FALSE);
6212 emitcode("add","a,acc");
6213 aopPut(AOP(result),"a",offset++);
6215 l = aopGet(AOP(result),offset,FALSE,FALSE);
6217 emitcode("rlc","a");
6218 aopPut(AOP(result),"a",offset++);
6220 reAdjustPreg(AOP(result));
6222 emitcode("","%05d_DS_:",tlbl1->key+100);
6223 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6225 freeAsmop(left,NULL,ic,TRUE);
6226 freeAsmop(result,NULL,ic,TRUE);
6229 /*-----------------------------------------------------------------*/
6230 /* genrshOne - right shift a one byte quantity by known count */
6231 /*-----------------------------------------------------------------*/
6232 static void genrshOne (operand *result, operand *left,
6233 int shCount, int sign)
6235 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6236 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6239 /*-----------------------------------------------------------------*/
6240 /* genrshTwo - right shift two bytes by known amount != 0 */
6241 /*-----------------------------------------------------------------*/
6242 static void genrshTwo (operand *result,operand *left,
6243 int shCount, int sign)
6245 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6246 /* if shCount >= 8 */
6250 shiftR1Left2Result(left, MSB16, result, LSB,
6253 movLeft2Result(left, MSB16, result, LSB, sign);
6254 addSign(result, MSB16, sign);
6257 /* 1 <= shCount <= 7 */
6259 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6262 /*-----------------------------------------------------------------*/
6263 /* shiftRLong - shift right one long from left to result */
6264 /* offl = LSB or MSB16 */
6265 /*-----------------------------------------------------------------*/
6266 static void shiftRLong (operand *left, int offl,
6267 operand *result, int sign)
6269 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6271 emitcode("clr","c");
6272 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6274 emitcode("mov","c,acc.7");
6275 emitcode("rrc","a");
6276 aopPut(AOP(result),"a",MSB32-offl);
6278 /* add sign of "a" */
6279 addSign(result, MSB32, sign);
6281 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6282 emitcode("rrc","a");
6283 aopPut(AOP(result),"a",MSB24-offl);
6285 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6286 emitcode("rrc","a");
6287 aopPut(AOP(result),"a",MSB16-offl);
6290 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6291 emitcode("rrc","a");
6292 aopPut(AOP(result),"a",LSB);
6296 /*-----------------------------------------------------------------*/
6297 /* genrshFour - shift four byte by a known amount != 0 */
6298 /*-----------------------------------------------------------------*/
6299 static void genrshFour (operand *result, operand *left,
6300 int shCount, int sign)
6302 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6303 /* if shifting more that 3 bytes */
6304 if(shCount >= 24 ) {
6307 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6309 movLeft2Result(left, MSB32, result, LSB, sign);
6310 addSign(result, MSB16, sign);
6312 else if(shCount >= 16){
6315 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6317 movLeft2Result(left, MSB24, result, LSB, 0);
6318 movLeft2Result(left, MSB32, result, MSB16, sign);
6320 addSign(result, MSB24, sign);
6322 else if(shCount >= 8){
6325 shiftRLong(left, MSB16, result, sign);
6326 else if(shCount == 0){
6327 movLeft2Result(left, MSB16, result, LSB, 0);
6328 movLeft2Result(left, MSB24, result, MSB16, 0);
6329 movLeft2Result(left, MSB32, result, MSB24, sign);
6330 addSign(result, MSB32, sign);
6333 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6334 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6335 /* the last shift is signed */
6336 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6337 addSign(result, MSB32, sign);
6340 else{ /* 1 <= shCount <= 7 */
6342 shiftRLong(left, LSB, result, sign);
6344 shiftRLong(result, LSB, result, sign);
6347 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6348 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6349 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6354 /*-----------------------------------------------------------------*/
6355 /* genRightShiftLiteral - right shifting by known count */
6356 /*-----------------------------------------------------------------*/
6357 static void genRightShiftLiteral (operand *left,
6363 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6366 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6367 freeAsmop(right,NULL,ic,TRUE);
6369 aopOp(left,ic,FALSE);
6370 aopOp(result,ic,FALSE);
6373 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6377 size = getDataSize(left);
6378 /* test the LEFT size !!! */
6380 /* I suppose that the left size >= result size */
6382 size = getDataSize(result);
6384 movLeft2Result(left, size, result, size, 0);
6387 else if(shCount >= (size * 8)){
6389 /* get sign in acc.7 */
6390 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6391 addSign(result, LSB, sign);
6395 genrshOne (result,left,shCount,sign);
6399 genrshTwo (result,left,shCount,sign);
6403 genrshFour (result,left,shCount,sign);
6409 freeAsmop(left,NULL,ic,TRUE);
6410 freeAsmop(result,NULL,ic,TRUE);
6414 /*-----------------------------------------------------------------*/
6415 /* genSignedRightShift - right shift of signed number */
6416 /*-----------------------------------------------------------------*/
6417 static void genSignedRightShift (iCode *ic)
6419 operand *right, *left, *result;
6422 symbol *tlbl, *tlbl1 ;
6424 /* we do it the hard way put the shift count in b
6425 and loop thru preserving the sign */
6426 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6428 right = IC_RIGHT(ic);
6430 result = IC_RESULT(ic);
6432 aopOp(right,ic,FALSE);
6435 if ( AOP_TYPE(right) == AOP_LIT) {
6436 genRightShiftLiteral (left,right,result,ic,1);
6439 /* shift count is unknown then we have to form
6440 a loop get the loop count in B : Note: we take
6441 only the lower order byte since shifting
6442 more that 32 bits make no sense anyway, ( the
6443 largest size of an object can be only 32 bits ) */
6445 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6446 emitcode("inc","b");
6447 freeAsmop (right,NULL,ic,TRUE);
6448 aopOp(left,ic,FALSE);
6449 aopOp(result,ic,FALSE);
6451 /* now move the left to the result if they are not the
6453 if (!sameRegs(AOP(left),AOP(result)) &&
6454 AOP_SIZE(result) > 1) {
6456 size = AOP_SIZE(result);
6459 l = aopGet(AOP(left),offset,FALSE,TRUE);
6460 if (*l == '@' && IS_AOP_PREG(result)) {
6462 emitcode("mov","a,%s",l);
6463 aopPut(AOP(result),"a",offset);
6465 aopPut(AOP(result),l,offset);
6470 /* mov the highest order bit to OVR */
6471 tlbl = newiTempLabel(NULL);
6472 tlbl1= newiTempLabel(NULL);
6474 size = AOP_SIZE(result);
6476 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6477 emitcode("rlc","a");
6478 emitcode("mov","ov,c");
6479 /* if it is only one byte then */
6481 l = aopGet(AOP(left),0,FALSE,FALSE);
6483 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6484 emitcode("","%05d_DS_:",tlbl->key+100);
6485 emitcode("mov","c,ov");
6486 emitcode("rrc","a");
6487 emitcode("","%05d_DS_:",tlbl1->key+100);
6488 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6489 aopPut(AOP(result),"a",0);
6493 reAdjustPreg(AOP(result));
6494 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6495 emitcode("","%05d_DS_:",tlbl->key+100);
6496 emitcode("mov","c,ov");
6498 l = aopGet(AOP(result),offset,FALSE,FALSE);
6500 emitcode("rrc","a");
6501 aopPut(AOP(result),"a",offset--);
6503 reAdjustPreg(AOP(result));
6504 emitcode("","%05d_DS_:",tlbl1->key+100);
6505 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6508 freeAsmop(left,NULL,ic,TRUE);
6509 freeAsmop(result,NULL,ic,TRUE);
6512 /*-----------------------------------------------------------------*/
6513 /* genRightShift - generate code for right shifting */
6514 /*-----------------------------------------------------------------*/
6515 static void genRightShift (iCode *ic)
6517 operand *right, *left, *result;
6521 symbol *tlbl, *tlbl1 ;
6523 /* if signed then we do it the hard way preserve the
6524 sign bit moving it inwards */
6525 retype = getSpec(operandType(IC_RESULT(ic)));
6526 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6528 if (!SPEC_USIGN(retype)) {
6529 genSignedRightShift (ic);
6533 /* signed & unsigned types are treated the same : i.e. the
6534 signed is NOT propagated inwards : quoting from the
6535 ANSI - standard : "for E1 >> E2, is equivalent to division
6536 by 2**E2 if unsigned or if it has a non-negative value,
6537 otherwise the result is implementation defined ", MY definition
6538 is that the sign does not get propagated */
6540 right = IC_RIGHT(ic);
6542 result = IC_RESULT(ic);
6544 aopOp(right,ic,FALSE);
6546 /* if the shift count is known then do it
6547 as efficiently as possible */
6548 if (AOP_TYPE(right) == AOP_LIT) {
6549 genRightShiftLiteral (left,right,result,ic, 0);
6553 /* shift count is unknown then we have to form
6554 a loop get the loop count in B : Note: we take
6555 only the lower order byte since shifting
6556 more that 32 bits make no sense anyway, ( the
6557 largest size of an object can be only 32 bits ) */
6559 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6560 emitcode("inc","b");
6561 freeAsmop (right,NULL,ic,TRUE);
6562 aopOp(left,ic,FALSE);
6563 aopOp(result,ic,FALSE);
6565 /* now move the left to the result if they are not the
6567 if (!sameRegs(AOP(left),AOP(result)) &&
6568 AOP_SIZE(result) > 1) {
6570 size = AOP_SIZE(result);
6573 l = aopGet(AOP(left),offset,FALSE,TRUE);
6574 if (*l == '@' && IS_AOP_PREG(result)) {
6576 emitcode("mov","a,%s",l);
6577 aopPut(AOP(result),"a",offset);
6579 aopPut(AOP(result),l,offset);
6584 tlbl = newiTempLabel(NULL);
6585 tlbl1= newiTempLabel(NULL);
6586 size = AOP_SIZE(result);
6589 /* if it is only one byte then */
6591 l = aopGet(AOP(left),0,FALSE,FALSE);
6593 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6594 emitcode("","%05d_DS_:",tlbl->key+100);
6596 emitcode("rrc","a");
6597 emitcode("","%05d_DS_:",tlbl1->key+100);
6598 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6599 aopPut(AOP(result),"a",0);
6603 reAdjustPreg(AOP(result));
6604 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6605 emitcode("","%05d_DS_:",tlbl->key+100);
6608 l = aopGet(AOP(result),offset,FALSE,FALSE);
6610 emitcode("rrc","a");
6611 aopPut(AOP(result),"a",offset--);
6613 reAdjustPreg(AOP(result));
6615 emitcode("","%05d_DS_:",tlbl1->key+100);
6616 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6619 freeAsmop(left,NULL,ic,TRUE);
6620 freeAsmop(result,NULL,ic,TRUE);
6623 /*-----------------------------------------------------------------*/
6624 /* genUnpackBits - generates code for unpacking bits */
6625 /*-----------------------------------------------------------------*/
6626 static void genUnpackBits (operand *result, char *rname, int ptype)
6633 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6634 etype = getSpec(operandType(result));
6636 /* read the first byte */
6641 emitcode("mov","a,@%s",rname);
6645 emitcode("movx","a,@%s",rname);
6649 emitcode("movx","a,@dptr");
6653 emitcode("clr","a");
6654 emitcode("movc","a","@a+dptr");
6658 emitcode("lcall","__gptrget");
6662 /* if we have bitdisplacement then it fits */
6663 /* into this byte completely or if length is */
6664 /* less than a byte */
6665 if ((shCnt = SPEC_BSTR(etype)) ||
6666 (SPEC_BLEN(etype) <= 8)) {
6668 /* shift right acc */
6671 emitcode("anl","a,#0x%02x",
6672 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6673 aopPut(AOP(result),"a",offset);
6677 /* bit field did not fit in a byte */
6678 rlen = SPEC_BLEN(etype) - 8;
6679 aopPut(AOP(result),"a",offset++);
6686 emitcode("inc","%s",rname);
6687 emitcode("mov","a,@%s",rname);
6691 emitcode("inc","%s",rname);
6692 emitcode("movx","a,@%s",rname);
6696 emitcode("inc","dptr");
6697 emitcode("movx","a,@dptr");
6701 emitcode("clr","a");
6702 emitcode("inc","dptr");
6703 emitcode("movc","a","@a+dptr");
6707 emitcode("inc","dptr");
6708 emitcode("lcall","__gptrget");
6713 /* if we are done */
6717 aopPut(AOP(result),"a",offset++);
6722 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6723 aopPut(AOP(result),"a",offset);
6730 /*-----------------------------------------------------------------*/
6731 /* genDataPointerGet - generates code when ptr offset is known */
6732 /*-----------------------------------------------------------------*/
6733 static void genDataPointerGet (operand *left,
6739 int size , offset = 0;
6740 aopOp(result,ic,TRUE);
6742 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6744 /* get the string representation of the name */
6745 l = aopGet(AOP(left),0,FALSE,TRUE);
6746 size = AOP_SIZE(result);
6747 // tsd, was l+1 - the underline `_' prefix was being stripped
6750 sprintf(buffer,"(%s + %d)",l,offset);
6752 sprintf(buffer,"%s",l);
6753 aopPut(AOP(result),buffer,offset++);
6756 freeAsmop(left,NULL,ic,TRUE);
6757 freeAsmop(result,NULL,ic,TRUE);
6760 /*-----------------------------------------------------------------*/
6761 /* genNearPointerGet - emitcode for near pointer fetch */
6762 /*-----------------------------------------------------------------*/
6763 static void genNearPointerGet (operand *left,
6770 sym_link *rtype, *retype;
6771 sym_link *ltype = operandType(left);
6774 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6776 rtype = operandType(result);
6777 retype= getSpec(rtype);
6779 aopOp(left,ic,FALSE);
6781 /* if left is rematerialisable and
6782 result is not bit variable type and
6783 the left is pointer to data space i.e
6784 lower 128 bytes of space */
6785 if (AOP_TYPE(left) == AOP_IMMD &&
6786 !IS_BITVAR(retype) &&
6787 DCL_TYPE(ltype) == POINTER) {
6788 genDataPointerGet (left,result,ic);
6792 /* if the value is already in a pointer register
6793 then don't need anything more */
6794 if (!AOP_INPREG(AOP(left))) {
6795 /* otherwise get a free pointer register */
6797 preg = getFreePtr(ic,&aop,FALSE);
6798 emitcode("mov","%s,%s",
6800 aopGet(AOP(left),0,FALSE,TRUE));
6801 rname = preg->name ;
6803 rname = aopGet(AOP(left),0,FALSE,FALSE);
6805 freeAsmop(left,NULL,ic,TRUE);
6806 aopOp (result,ic,FALSE);
6808 /* if bitfield then unpack the bits */
6809 if (IS_BITVAR(retype))
6810 genUnpackBits (result,rname,POINTER);
6812 /* we have can just get the values */
6813 int size = AOP_SIZE(result);
6817 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6819 emitcode("mov","a,@%s",rname);
6820 aopPut(AOP(result),"a",offset);
6822 sprintf(buffer,"@%s",rname);
6823 aopPut(AOP(result),buffer,offset);
6827 emitcode("inc","%s",rname);
6831 /* now some housekeeping stuff */
6833 /* we had to allocate for this iCode */
6834 freeAsmop(NULL,aop,ic,TRUE);
6836 /* we did not allocate which means left
6837 already in a pointer register, then
6838 if size > 0 && this could be used again
6839 we have to point it back to where it
6841 if (AOP_SIZE(result) > 1 &&
6842 !OP_SYMBOL(left)->remat &&
6843 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6845 int size = AOP_SIZE(result) - 1;
6847 emitcode("dec","%s",rname);
6852 freeAsmop(result,NULL,ic,TRUE);
6856 /*-----------------------------------------------------------------*/
6857 /* genPagedPointerGet - emitcode for paged pointer fetch */
6858 /*-----------------------------------------------------------------*/
6859 static void genPagedPointerGet (operand *left,
6866 sym_link *rtype, *retype;
6868 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6870 rtype = operandType(result);
6871 retype= getSpec(rtype);
6873 aopOp(left,ic,FALSE);
6875 /* if the value is already in a pointer register
6876 then don't need anything more */
6877 if (!AOP_INPREG(AOP(left))) {
6878 /* otherwise get a free pointer register */
6880 preg = getFreePtr(ic,&aop,FALSE);
6881 emitcode("mov","%s,%s",
6883 aopGet(AOP(left),0,FALSE,TRUE));
6884 rname = preg->name ;
6886 rname = aopGet(AOP(left),0,FALSE,FALSE);
6888 freeAsmop(left,NULL,ic,TRUE);
6889 aopOp (result,ic,FALSE);
6891 /* if bitfield then unpack the bits */
6892 if (IS_BITVAR(retype))
6893 genUnpackBits (result,rname,PPOINTER);
6895 /* we have can just get the values */
6896 int size = AOP_SIZE(result);
6901 emitcode("movx","a,@%s",rname);
6902 aopPut(AOP(result),"a",offset);
6907 emitcode("inc","%s",rname);
6911 /* now some housekeeping stuff */
6913 /* we had to allocate for this iCode */
6914 freeAsmop(NULL,aop,ic,TRUE);
6916 /* we did not allocate which means left
6917 already in a pointer register, then
6918 if size > 0 && this could be used again
6919 we have to point it back to where it
6921 if (AOP_SIZE(result) > 1 &&
6922 !OP_SYMBOL(left)->remat &&
6923 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6925 int size = AOP_SIZE(result) - 1;
6927 emitcode("dec","%s",rname);
6932 freeAsmop(result,NULL,ic,TRUE);
6937 /*-----------------------------------------------------------------*/
6938 /* genFarPointerGet - gget value from far space */
6939 /*-----------------------------------------------------------------*/
6940 static void genFarPointerGet (operand *left,
6941 operand *result, iCode *ic)
6944 sym_link *retype = getSpec(operandType(result));
6946 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6948 aopOp(left,ic,FALSE);
6950 /* if the operand is already in dptr
6951 then we do nothing else we move the value to dptr */
6952 if (AOP_TYPE(left) != AOP_STR) {
6953 /* if this is remateriazable */
6954 if (AOP_TYPE(left) == AOP_IMMD)
6955 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6956 else { /* we need to get it byte by byte */
6957 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6958 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6959 if (options.model == MODEL_FLAT24)
6961 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6965 /* so dptr know contains the address */
6966 freeAsmop(left,NULL,ic,TRUE);
6967 aopOp(result,ic,FALSE);
6969 /* if bit then unpack */
6970 if (IS_BITVAR(retype))
6971 genUnpackBits(result,"dptr",FPOINTER);
6973 size = AOP_SIZE(result);
6977 emitcode("movx","a,@dptr");
6978 aopPut(AOP(result),"a",offset++);
6980 emitcode("inc","dptr");
6984 freeAsmop(result,NULL,ic,TRUE);
6987 /*-----------------------------------------------------------------*/
6988 /* emitcodePointerGet - gget value from code space */
6989 /*-----------------------------------------------------------------*/
6990 static void emitcodePointerGet (operand *left,
6991 operand *result, iCode *ic)
6994 sym_link *retype = getSpec(operandType(result));
6996 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6998 aopOp(left,ic,FALSE);
7000 /* if the operand is already in dptr
7001 then we do nothing else we move the value to dptr */
7002 if (AOP_TYPE(left) != AOP_STR) {
7003 /* if this is remateriazable */
7004 if (AOP_TYPE(left) == AOP_IMMD)
7005 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7006 else { /* we need to get it byte by byte */
7007 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7008 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7009 if (options.model == MODEL_FLAT24)
7011 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7015 /* so dptr know contains the address */
7016 freeAsmop(left,NULL,ic,TRUE);
7017 aopOp(result,ic,FALSE);
7019 /* if bit then unpack */
7020 if (IS_BITVAR(retype))
7021 genUnpackBits(result,"dptr",CPOINTER);
7023 size = AOP_SIZE(result);
7027 emitcode("clr","a");
7028 emitcode("movc","a,@a+dptr");
7029 aopPut(AOP(result),"a",offset++);
7031 emitcode("inc","dptr");
7035 freeAsmop(result,NULL,ic,TRUE);
7038 /*-----------------------------------------------------------------*/
7039 /* genGenPointerGet - gget value from generic pointer space */
7040 /*-----------------------------------------------------------------*/
7041 static void genGenPointerGet (operand *left,
7042 operand *result, iCode *ic)
7045 sym_link *retype = getSpec(operandType(result));
7047 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7048 aopOp(left,ic,FALSE);
7050 /* if the operand is already in dptr
7051 then we do nothing else we move the value to dptr */
7052 if (AOP_TYPE(left) != AOP_STR) {
7053 /* if this is remateriazable */
7054 if (AOP_TYPE(left) == AOP_IMMD) {
7055 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7056 emitcode("mov","b,#%d",pointerCode(retype));
7058 else { /* we need to get it byte by byte */
7060 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7061 emitcode("movwf","FSR");
7063 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7064 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7065 if (options.model == MODEL_FLAT24)
7067 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7068 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7072 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7077 /* so dptr know contains the address */
7078 freeAsmop(left,NULL,ic,TRUE);
7079 aopOp(result,ic,FALSE);
7081 /* if bit then unpack */
7082 if (IS_BITVAR(retype))
7083 genUnpackBits(result,"dptr",GPOINTER);
7085 size = AOP_SIZE(result);
7089 //emitcode("lcall","__gptrget");
7090 emitcode("movf","indf,w");
7091 //aopPut(AOP(result),"a",offset++);
7092 emitcode("movwf","%s",
7093 aopGet(AOP(result),offset++,FALSE,FALSE));
7095 emitcode("incf","fsr,f");
7099 freeAsmop(result,NULL,ic,TRUE);
7102 /*-----------------------------------------------------------------*/
7103 /* genPointerGet - generate code for pointer get */
7104 /*-----------------------------------------------------------------*/
7105 static void genPointerGet (iCode *ic)
7107 operand *left, *result ;
7108 sym_link *type, *etype;
7111 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7114 result = IC_RESULT(ic) ;
7116 /* depending on the type of pointer we need to
7117 move it to the correct pointer register */
7118 type = operandType(left);
7119 etype = getSpec(type);
7120 /* if left is of type of pointer then it is simple */
7121 if (IS_PTR(type) && !IS_FUNC(type->next))
7122 p_type = DCL_TYPE(type);
7124 /* we have to go by the storage class */
7125 p_type = PTR_TYPE(SPEC_OCLS(etype));
7127 /* if (SPEC_OCLS(etype)->codesp ) { */
7128 /* p_type = CPOINTER ; */
7131 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7132 /* p_type = FPOINTER ; */
7134 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7135 /* p_type = PPOINTER; */
7137 /* if (SPEC_OCLS(etype) == idata ) */
7138 /* p_type = IPOINTER; */
7140 /* p_type = POINTER ; */
7143 /* now that we have the pointer type we assign
7144 the pointer values */
7149 genNearPointerGet (left,result,ic);
7153 genPagedPointerGet(left,result,ic);
7157 genFarPointerGet (left,result,ic);
7161 emitcodePointerGet (left,result,ic);
7165 genGenPointerGet (left,result,ic);
7171 /*-----------------------------------------------------------------*/
7172 /* genPackBits - generates code for packed bit storage */
7173 /*-----------------------------------------------------------------*/
7174 static void genPackBits (sym_link *etype ,
7176 char *rname, int p_type)
7184 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7185 blen = SPEC_BLEN(etype);
7186 bstr = SPEC_BSTR(etype);
7188 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7191 /* if the bit lenth is less than or */
7192 /* it exactly fits a byte then */
7193 if (SPEC_BLEN(etype) <= 8 ) {
7194 shCount = SPEC_BSTR(etype) ;
7196 /* shift left acc */
7199 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7204 emitcode ("mov","b,a");
7205 emitcode("mov","a,@%s",rname);
7209 emitcode ("mov","b,a");
7210 emitcode("movx","a,@dptr");
7214 emitcode ("push","b");
7215 emitcode ("push","acc");
7216 emitcode ("lcall","__gptrget");
7217 emitcode ("pop","b");
7221 emitcode ("anl","a,#0x%02x",(unsigned char)
7222 ((unsigned char)(0xFF << (blen+bstr)) |
7223 (unsigned char)(0xFF >> (8-bstr)) ) );
7224 emitcode ("orl","a,b");
7225 if (p_type == GPOINTER)
7226 emitcode("pop","b");
7232 emitcode("mov","@%s,a",rname);
7236 emitcode("movx","@dptr,a");
7240 DEBUGemitcode(";lcall","__gptrput");
7245 if ( SPEC_BLEN(etype) <= 8 )
7248 emitcode("inc","%s",rname);
7249 rLen = SPEC_BLEN(etype) ;
7251 /* now generate for lengths greater than one byte */
7254 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7264 emitcode("mov","@%s,a",rname);
7266 emitcode("mov","@%s,%s",rname,l);
7271 emitcode("movx","@dptr,a");
7276 DEBUGemitcode(";lcall","__gptrput");
7279 emitcode ("inc","%s",rname);
7284 /* last last was not complete */
7286 /* save the byte & read byte */
7289 emitcode ("mov","b,a");
7290 emitcode("mov","a,@%s",rname);
7294 emitcode ("mov","b,a");
7295 emitcode("movx","a,@dptr");
7299 emitcode ("push","b");
7300 emitcode ("push","acc");
7301 emitcode ("lcall","__gptrget");
7302 emitcode ("pop","b");
7306 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7307 emitcode ("orl","a,b");
7310 if (p_type == GPOINTER)
7311 emitcode("pop","b");
7316 emitcode("mov","@%s,a",rname);
7320 emitcode("movx","@dptr,a");
7324 DEBUGemitcode(";lcall","__gptrput");
7328 /*-----------------------------------------------------------------*/
7329 /* genDataPointerSet - remat pointer to data space */
7330 /*-----------------------------------------------------------------*/
7331 static void genDataPointerSet(operand *right,
7335 int size, offset = 0 ;
7336 char *l, buffer[256];
7338 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7339 aopOp(right,ic,FALSE);
7341 l = aopGet(AOP(result),0,FALSE,TRUE);
7342 size = AOP_SIZE(right);
7343 // tsd, was l+1 - the underline `_' prefix was being stripped
7346 sprintf(buffer,"(%s + %d)",l,offset);
7348 sprintf(buffer,"%s",l);
7350 if (AOP_TYPE(right) == AOP_LIT) {
7351 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7352 lit = lit >> (8*offset);
7354 emitcode("movlw","%s",lit);
7355 emitcode("movwf","%s",buffer);
7357 emitcode("clrf","%s",buffer);
7359 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7360 emitcode("movwf","%s",buffer);
7366 freeAsmop(right,NULL,ic,TRUE);
7367 freeAsmop(result,NULL,ic,TRUE);
7370 /*-----------------------------------------------------------------*/
7371 /* genNearPointerSet - emitcode for near pointer put */
7372 /*-----------------------------------------------------------------*/
7373 static void genNearPointerSet (operand *right,
7380 sym_link *ptype = operandType(result);
7383 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7384 retype= getSpec(operandType(right));
7386 aopOp(result,ic,FALSE);
7388 /* if the result is rematerializable &
7389 in data space & not a bit variable */
7390 if (AOP_TYPE(result) == AOP_IMMD &&
7391 DCL_TYPE(ptype) == POINTER &&
7392 !IS_BITVAR(retype)) {
7393 genDataPointerSet (right,result,ic);
7397 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7399 /* if the value is already in a pointer register
7400 then don't need anything more */
7401 if (!AOP_INPREG(AOP(result))) {
7402 /* otherwise get a free pointer register */
7403 //aop = newAsmop(0);
7404 //preg = getFreePtr(ic,&aop,FALSE);
7405 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7406 //emitcode("mov","%s,%s",
7408 // aopGet(AOP(result),0,FALSE,TRUE));
7409 //rname = preg->name ;
7410 emitcode("movwf","fsr");
7412 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7414 freeAsmop(result,NULL,ic,TRUE);
7415 aopOp (right,ic,FALSE);
7416 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7418 /* if bitfield then unpack the bits */
7419 if (IS_BITVAR(retype)) {
7420 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7421 "The programmer is obviously confused");
7422 //genPackBits (retype,right,rname,POINTER);
7426 /* we have can just get the values */
7427 int size = AOP_SIZE(right);
7430 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7432 l = aopGet(AOP(right),offset,FALSE,TRUE);
7435 //emitcode("mov","@%s,a",rname);
7436 emitcode("movf","indf,w ;1");
7439 if (AOP_TYPE(right) == AOP_LIT) {
7440 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7442 emitcode("movlw","%s",l);
7443 emitcode("movwf","indf ;2");
7445 emitcode("clrf","indf");
7447 emitcode("movf","%s,w",l);
7448 emitcode("movwf","indf ;2");
7450 //emitcode("mov","@%s,%s",rname,l);
7453 emitcode("incf","fsr,f ;3");
7454 //emitcode("inc","%s",rname);
7459 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7460 /* now some housekeeping stuff */
7462 /* we had to allocate for this iCode */
7463 freeAsmop(NULL,aop,ic,TRUE);
7465 /* we did not allocate which means left
7466 already in a pointer register, then
7467 if size > 0 && this could be used again
7468 we have to point it back to where it
7470 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7471 if (AOP_SIZE(right) > 1 &&
7472 !OP_SYMBOL(result)->remat &&
7473 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7475 int size = AOP_SIZE(right) - 1;
7477 emitcode("decf","fsr,f");
7478 //emitcode("dec","%s",rname);
7482 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7484 freeAsmop(right,NULL,ic,TRUE);
7489 /*-----------------------------------------------------------------*/
7490 /* genPagedPointerSet - emitcode for Paged pointer put */
7491 /*-----------------------------------------------------------------*/
7492 static void genPagedPointerSet (operand *right,
7501 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7503 retype= getSpec(operandType(right));
7505 aopOp(result,ic,FALSE);
7507 /* if the value is already in a pointer register
7508 then don't need anything more */
7509 if (!AOP_INPREG(AOP(result))) {
7510 /* otherwise get a free pointer register */
7512 preg = getFreePtr(ic,&aop,FALSE);
7513 emitcode("mov","%s,%s",
7515 aopGet(AOP(result),0,FALSE,TRUE));
7516 rname = preg->name ;
7518 rname = aopGet(AOP(result),0,FALSE,FALSE);
7520 freeAsmop(result,NULL,ic,TRUE);
7521 aopOp (right,ic,FALSE);
7523 /* if bitfield then unpack the bits */
7524 if (IS_BITVAR(retype))
7525 genPackBits (retype,right,rname,PPOINTER);
7527 /* we have can just get the values */
7528 int size = AOP_SIZE(right);
7532 l = aopGet(AOP(right),offset,FALSE,TRUE);
7535 emitcode("movx","@%s,a",rname);
7538 emitcode("inc","%s",rname);
7544 /* now some housekeeping stuff */
7546 /* we had to allocate for this iCode */
7547 freeAsmop(NULL,aop,ic,TRUE);
7549 /* we did not allocate which means left
7550 already in a pointer register, then
7551 if size > 0 && this could be used again
7552 we have to point it back to where it
7554 if (AOP_SIZE(right) > 1 &&
7555 !OP_SYMBOL(result)->remat &&
7556 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7558 int size = AOP_SIZE(right) - 1;
7560 emitcode("dec","%s",rname);
7565 freeAsmop(right,NULL,ic,TRUE);
7570 /*-----------------------------------------------------------------*/
7571 /* genFarPointerSet - set value from far space */
7572 /*-----------------------------------------------------------------*/
7573 static void genFarPointerSet (operand *right,
7574 operand *result, iCode *ic)
7577 sym_link *retype = getSpec(operandType(right));
7579 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7580 aopOp(result,ic,FALSE);
7582 /* if the operand is already in dptr
7583 then we do nothing else we move the value to dptr */
7584 if (AOP_TYPE(result) != AOP_STR) {
7585 /* if this is remateriazable */
7586 if (AOP_TYPE(result) == AOP_IMMD)
7587 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7588 else { /* we need to get it byte by byte */
7589 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7590 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7591 if (options.model == MODEL_FLAT24)
7593 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7597 /* so dptr know contains the address */
7598 freeAsmop(result,NULL,ic,TRUE);
7599 aopOp(right,ic,FALSE);
7601 /* if bit then unpack */
7602 if (IS_BITVAR(retype))
7603 genPackBits(retype,right,"dptr",FPOINTER);
7605 size = AOP_SIZE(right);
7609 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7611 emitcode("movx","@dptr,a");
7613 emitcode("inc","dptr");
7617 freeAsmop(right,NULL,ic,TRUE);
7620 /*-----------------------------------------------------------------*/
7621 /* genGenPointerSet - set value from generic pointer space */
7622 /*-----------------------------------------------------------------*/
7623 static void genGenPointerSet (operand *right,
7624 operand *result, iCode *ic)
7627 sym_link *retype = getSpec(operandType(right));
7629 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7631 aopOp(result,ic,FALSE);
7633 /* if the operand is already in dptr
7634 then we do nothing else we move the value to dptr */
7635 if (AOP_TYPE(result) != AOP_STR) {
7636 /* if this is remateriazable */
7637 if (AOP_TYPE(result) == AOP_IMMD) {
7638 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7639 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7641 else { /* we need to get it byte by byte */
7642 char *l = aopGet(AOP(result),0,FALSE,FALSE);
7644 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7646 emitcode("movwf","INDF");
7649 /* so dptr know contains the address */
7650 freeAsmop(result,NULL,ic,TRUE);
7651 aopOp(right,ic,FALSE);
7653 /* if bit then unpack */
7654 if (IS_BITVAR(retype))
7655 genPackBits(retype,right,"dptr",GPOINTER);
7657 size = AOP_SIZE(right);
7661 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7663 emitcode("incf","fsr,f");
7664 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7665 emitcode("movwf","indf");
7667 //DEBUGemitcode(";lcall","__gptrput");
7669 // emitcode("inc","dptr");
7673 freeAsmop(right,NULL,ic,TRUE);
7676 /*-----------------------------------------------------------------*/
7677 /* genPointerSet - stores the value into a pointer location */
7678 /*-----------------------------------------------------------------*/
7679 static void genPointerSet (iCode *ic)
7681 operand *right, *result ;
7682 sym_link *type, *etype;
7685 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7687 right = IC_RIGHT(ic);
7688 result = IC_RESULT(ic) ;
7690 /* depending on the type of pointer we need to
7691 move it to the correct pointer register */
7692 type = operandType(result);
7693 etype = getSpec(type);
7694 /* if left is of type of pointer then it is simple */
7695 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7696 p_type = DCL_TYPE(type);
7699 /* we have to go by the storage class */
7700 p_type = PTR_TYPE(SPEC_OCLS(etype));
7702 /* if (SPEC_OCLS(etype)->codesp ) { */
7703 /* p_type = CPOINTER ; */
7706 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7707 /* p_type = FPOINTER ; */
7709 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7710 /* p_type = PPOINTER ; */
7712 /* if (SPEC_OCLS(etype) == idata ) */
7713 /* p_type = IPOINTER ; */
7715 /* p_type = POINTER ; */
7718 /* now that we have the pointer type we assign
7719 the pointer values */
7724 genNearPointerSet (right,result,ic);
7728 genPagedPointerSet (right,result,ic);
7732 genFarPointerSet (right,result,ic);
7736 genGenPointerSet (right,result,ic);
7742 /*-----------------------------------------------------------------*/
7743 /* genIfx - generate code for Ifx statement */
7744 /*-----------------------------------------------------------------*/
7745 static void genIfx (iCode *ic, iCode *popIc)
7747 operand *cond = IC_COND(ic);
7750 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7751 aopOp(cond,ic,FALSE);
7753 /* get the value into acc */
7754 if (AOP_TYPE(cond) != AOP_CRY)
7758 /* the result is now in the accumulator */
7759 freeAsmop(cond,NULL,ic,TRUE);
7761 /* if there was something to be popped then do it */
7765 /* if the condition is a bit variable */
7766 if (isbit && IS_ITEMP(cond) &&
7768 genIfxJump(ic,SPIL_LOC(cond)->rname);
7769 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7773 if (isbit && !IS_ITEMP(cond))
7774 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7776 DEBUGemitcode ("; isbit","a");
7779 if (isbit && !IS_ITEMP(cond))
7780 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7787 /*-----------------------------------------------------------------*/
7788 /* genAddrOf - generates code for address of */
7789 /*-----------------------------------------------------------------*/
7790 static void genAddrOf (iCode *ic)
7792 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7795 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7797 aopOp(IC_RESULT(ic),ic,FALSE);
7799 /* if the operand is on the stack then we
7800 need to get the stack offset of this
7803 /* if it has an offset then we need to compute
7806 emitcode("mov","a,_bp");
7807 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7808 aopPut(AOP(IC_RESULT(ic)),"a",0);
7810 /* we can just move _bp */
7811 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7813 /* fill the result with zero */
7814 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7817 if (options.stack10bit && size < (FPTRSIZE - 1))
7820 "*** warning: pointer to stack var truncated.\n");
7827 if (options.stack10bit && offset == 2)
7829 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7833 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7840 /* object not on stack then we need the name */
7841 size = AOP_SIZE(IC_RESULT(ic));
7845 char s[SDCC_NAME_MAX];
7847 sprintf(s,"#(%s >> %d)",
7851 sprintf(s,"#%s",sym->rname);
7852 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7856 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7861 /*-----------------------------------------------------------------*/
7862 /* genFarFarAssign - assignment when both are in far space */
7863 /*-----------------------------------------------------------------*/
7864 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7866 int size = AOP_SIZE(right);
7869 /* first push the right side on to the stack */
7871 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7873 emitcode ("push","acc");
7876 freeAsmop(right,NULL,ic,FALSE);
7877 /* now assign DPTR to result */
7878 aopOp(result,ic,FALSE);
7879 size = AOP_SIZE(result);
7881 emitcode ("pop","acc");
7882 aopPut(AOP(result),"a",--offset);
7884 freeAsmop(result,NULL,ic,FALSE);
7889 /*-----------------------------------------------------------------*/
7890 /* genAssign - generate code for assignment */
7891 /*-----------------------------------------------------------------*/
7892 static void genAssign (iCode *ic)
7894 operand *result, *right;
7896 unsigned long lit = 0L;
7898 result = IC_RESULT(ic);
7899 right = IC_RIGHT(ic) ;
7901 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7903 /* if they are the same */
7904 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7907 aopOp(right,ic,FALSE);
7908 aopOp(result,ic,TRUE);
7910 /* if they are the same registers */
7911 if (sameRegs(AOP(right),AOP(result)))
7914 /* if the result is a bit */
7915 if (AOP_TYPE(result) == AOP_CRY) {
7917 /* if the right size is a literal then
7918 we know what the value is */
7919 if (AOP_TYPE(right) == AOP_LIT) {
7920 if (((int) operandLitValue(right)))
7921 emitcode("bsf","(%s >> 3),(%s & 7)",
7922 AOP(result)->aopu.aop_dir,
7923 AOP(result)->aopu.aop_dir);
7925 emitcode("bcf","(%s >> 3),(%s & 7)",
7926 AOP(result)->aopu.aop_dir,
7927 AOP(result)->aopu.aop_dir);
7931 /* the right is also a bit variable */
7932 if (AOP_TYPE(right) == AOP_CRY) {
7933 emitcode("bcf","(%s >> 3),(%s & 7)",
7934 AOP(result)->aopu.aop_dir,
7935 AOP(result)->aopu.aop_dir);
7936 emitcode("btfsc","(%s >> 3),(%s & 7)",
7937 AOP(right)->aopu.aop_dir,
7938 AOP(right)->aopu.aop_dir);
7939 emitcode("bsf","(%s >> 3),(%s & 7)",
7940 AOP(result)->aopu.aop_dir,
7941 AOP(result)->aopu.aop_dir);
7947 aopPut(AOP(result),"a",0);
7951 /* bit variables done */
7953 size = AOP_SIZE(result);
7955 if(AOP_TYPE(right) == AOP_LIT)
7956 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7957 if((AOP_TYPE(result) != AOP_REG) &&
7958 (AOP_TYPE(right) == AOP_LIT) &&
7959 !IS_FLOAT(operandType(right)) &&
7963 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7964 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7966 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7967 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7972 if(AOP_TYPE(right) == AOP_LIT)
7973 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7975 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7977 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7983 freeAsmop (right,NULL,ic,FALSE);
7984 freeAsmop (result,NULL,ic,TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genJumpTab - genrates code for jump table */
7989 /*-----------------------------------------------------------------*/
7990 static void genJumpTab (iCode *ic)
7995 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7997 aopOp(IC_JTCOND(ic),ic,FALSE);
7998 /* get the condition into accumulator */
7999 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8001 /* multiply by three */
8002 emitcode("add","a,acc");
8003 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8004 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8006 jtab = newiTempLabel(NULL);
8007 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8008 emitcode("jmp","@a+dptr");
8009 emitcode("","%05d_DS_:",jtab->key+100);
8010 /* now generate the jump labels */
8011 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8012 jtab = setNextItem(IC_JTLABELS(ic)))
8013 emitcode("ljmp","%05d_DS_",jtab->key+100);
8017 /*-----------------------------------------------------------------*/
8018 /* genMixedOperation - gen code for operators between mixed types */
8019 /*-----------------------------------------------------------------*/
8021 TSD - Written for the PIC port - but this unfortunately is buggy.
8022 This routine is good in that it is able to efficiently promote
8023 types to different (larger) sizes. Unfortunately, the temporary
8024 variables that are optimized out by this routine are sometimes
8025 used in other places. So until I know how to really parse the
8026 iCode tree, I'm going to not be using this routine :(.
8028 static int genMixedOperation (iCode *ic)
8031 operand *result = IC_RESULT(ic);
8032 sym_link *ctype = operandType(IC_LEFT(ic));
8033 operand *right = IC_RIGHT(ic);
8039 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8041 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8047 nextright = IC_RIGHT(nextic);
8048 nextleft = IC_LEFT(nextic);
8049 nextresult = IC_RESULT(nextic);
8051 aopOp(right,ic,FALSE);
8052 aopOp(result,ic,FALSE);
8053 aopOp(nextright, nextic, FALSE);
8054 aopOp(nextleft, nextic, FALSE);
8055 aopOp(nextresult, nextic, FALSE);
8057 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8063 emitcode(";remove right +","");
8065 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8071 emitcode(";remove left +","");
8075 big = AOP_SIZE(nextleft);
8076 small = AOP_SIZE(nextright);
8078 switch(nextic->op) {
8081 emitcode(";optimize a +","");
8082 /* if unsigned or not an integral type */
8083 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8084 emitcode(";add a bit to something","");
8087 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8089 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8090 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8091 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8093 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8101 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8102 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8103 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8106 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8108 emitcode("btfsc","(%s >> 3), (%s & 7)",
8109 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8110 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8111 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8112 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8115 emitcode("rlf","known_zero,w");
8122 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8123 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8124 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8126 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8136 freeAsmop(right,NULL,ic,TRUE);
8137 freeAsmop(result,NULL,ic,TRUE);
8138 freeAsmop(nextright,NULL,ic,TRUE);
8139 freeAsmop(nextleft,NULL,ic,TRUE);
8141 nextic->generated = 1;
8148 /*-----------------------------------------------------------------*/
8149 /* genCast - gen code for casting */
8150 /*-----------------------------------------------------------------*/
8151 static void genCast (iCode *ic)
8153 operand *result = IC_RESULT(ic);
8154 sym_link *ctype = operandType(IC_LEFT(ic));
8155 operand *right = IC_RIGHT(ic);
8158 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8159 /* if they are equivalent then do nothing */
8160 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8163 aopOp(right,ic,FALSE) ;
8164 aopOp(result,ic,FALSE);
8166 /* if the result is a bit */
8167 if (AOP_TYPE(result) == AOP_CRY) {
8168 /* if the right size is a literal then
8169 we know what the value is */
8170 if (AOP_TYPE(right) == AOP_LIT) {
8171 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
8172 if (((int) operandLitValue(right)))
8173 emitcode("bsf","(%s >> 3), (%s & 7)",
8174 AOP(result)->aopu.aop_dir,
8175 AOP(result)->aopu.aop_dir);
8177 emitcode("bcf","(%s >> 3), (%s & 7)",
8178 AOP(result)->aopu.aop_dir,
8179 AOP(result)->aopu.aop_dir);
8184 /* the right is also a bit variable */
8185 if (AOP_TYPE(right) == AOP_CRY) {
8186 emitcode("clrc","");
8187 emitcode("btfsc","(%s >> 3), (%s & 7)",
8188 AOP(right)->aopu.aop_dir,
8189 AOP(right)->aopu.aop_dir);
8190 aopPut(AOP(result),"c",0);
8196 aopPut(AOP(result),"a",0);
8200 /* if they are the same size : or less */
8201 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8203 /* if they are in the same place */
8204 if (sameRegs(AOP(right),AOP(result)))
8207 /* if they in different places then copy */
8208 size = AOP_SIZE(result);
8212 aopGet(AOP(right),offset,FALSE,FALSE),
8220 /* if the result is of type pointer */
8221 if (IS_PTR(ctype)) {
8224 sym_link *type = operandType(right);
8225 sym_link *etype = getSpec(type);
8227 /* pointer to generic pointer */
8228 if (IS_GENPTR(ctype)) {
8232 p_type = DCL_TYPE(type);
8234 /* we have to go by the storage class */
8235 p_type = PTR_TYPE(SPEC_OCLS(etype));
8237 /* if (SPEC_OCLS(etype)->codesp ) */
8238 /* p_type = CPOINTER ; */
8240 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8241 /* p_type = FPOINTER ; */
8243 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8244 /* p_type = PPOINTER; */
8246 /* if (SPEC_OCLS(etype) == idata ) */
8247 /* p_type = IPOINTER ; */
8249 /* p_type = POINTER ; */
8252 /* the first two bytes are known */
8253 size = GPTRSIZE - 1;
8257 aopGet(AOP(right),offset,FALSE,FALSE),
8261 /* the last byte depending on type */
8278 /* this should never happen */
8279 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8280 "got unknown pointer type");
8283 aopPut(AOP(result),l, GPTRSIZE - 1);
8287 /* just copy the pointers */
8288 size = AOP_SIZE(result);
8292 aopGet(AOP(right),offset,FALSE,FALSE),
8300 if (AOP_TYPE(right) == AOP_CRY) {
8302 size = AOP_SIZE(right);
8304 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8305 emitcode("btfsc","(%s >> 3), (%s & 7)",
8306 AOP(right)->aopu.aop_dir,
8307 AOP(right)->aopu.aop_dir);
8308 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8310 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8315 /* so we now know that the size of destination is greater
8316 than the size of the source.
8317 Now, if the next iCode is an operator then we might be
8318 able to optimize the operation without performing a cast.
8320 if(genMixedOperation(ic))
8324 /* we move to result for the size of source */
8325 size = AOP_SIZE(right);
8328 emitcode(";","%d",__LINE__);
8330 aopGet(AOP(right),offset,FALSE,FALSE),
8335 /* now depending on the sign of the destination */
8336 size = AOP_SIZE(result) - AOP_SIZE(right);
8337 /* if unsigned or not an integral type */
8338 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8340 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8342 /* we need to extend the sign :{ */
8343 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8346 emitcode("clrw","");
8347 emitcode("btfsc","(%s >> 3), (%s & 7)",
8348 AOP(right)->aopu.aop_dir,
8349 AOP(right)->aopu.aop_dir);
8350 emitcode("movlw","0xff");
8352 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8353 // aopPut(AOP(result),"a",offset++);
8358 /* we are done hurray !!!! */
8361 freeAsmop(right,NULL,ic,TRUE);
8362 freeAsmop(result,NULL,ic,TRUE);
8366 /*-----------------------------------------------------------------*/
8367 /* genDjnz - generate decrement & jump if not zero instrucion */
8368 /*-----------------------------------------------------------------*/
8369 static int genDjnz (iCode *ic, iCode *ifx)
8372 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8377 /* if the if condition has a false label
8378 then we cannot save */
8382 /* if the minus is not of the form
8384 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8385 !IS_OP_LITERAL(IC_RIGHT(ic)))
8388 if (operandLitValue(IC_RIGHT(ic)) != 1)
8391 /* if the size of this greater than one then no
8393 if (getSize(operandType(IC_RESULT(ic))) > 1)
8396 /* otherwise we can save BIG */
8397 lbl = newiTempLabel(NULL);
8398 lbl1= newiTempLabel(NULL);
8400 aopOp(IC_RESULT(ic),ic,FALSE);
8402 if (IS_AOP_PREG(IC_RESULT(ic))) {
8403 emitcode("dec","%s",
8404 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8405 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8406 emitcode("jnz","%05d_DS_",lbl->key+100);
8408 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8409 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8412 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8413 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8414 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8415 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8418 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8423 /*-----------------------------------------------------------------*/
8424 /* genReceive - generate code for a receive iCode */
8425 /*-----------------------------------------------------------------*/
8426 static void genReceive (iCode *ic)
8428 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8430 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8431 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8432 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8434 int size = getSize(operandType(IC_RESULT(ic)));
8435 int offset = fReturnSize - size;
8437 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8438 fReturn[fReturnSize - offset - 1] : "acc"));
8441 aopOp(IC_RESULT(ic),ic,FALSE);
8442 size = AOP_SIZE(IC_RESULT(ic));
8445 emitcode ("pop","acc");
8446 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8451 aopOp(IC_RESULT(ic),ic,FALSE);
8453 assignResultValue(IC_RESULT(ic));
8456 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* genpic14Code - generate code for pic14 based controllers */
8461 /*-----------------------------------------------------------------*/
8462 void genpic14Code (iCode *lic)
8467 lineHead = lineCurr = NULL;
8469 /* if debug information required */
8470 /* if (options.debug && currFunc) { */
8472 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8474 if (IS_STATIC(currFunc->etype))
8475 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8477 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8482 for (ic = lic ; ic ; ic = ic->next ) {
8484 DEBUGemitcode(";ic","");
8485 if ( cln != ic->lineno ) {
8486 if ( options.debug ) {
8488 emitcode("",";C$%s$%d$%d$%d ==.",
8489 ic->filename,ic->lineno,
8490 ic->level,ic->block);
8493 emitcode(";","%s %d",ic->filename,ic->lineno);
8496 /* if the result is marked as
8497 spilt and rematerializable or code for
8498 this has already been generated then
8500 if (resultRemat(ic) || ic->generated )
8503 /* depending on the operation */
8522 /* IPOP happens only when trying to restore a
8523 spilt live range, if there is an ifx statement
8524 following this pop then the if statement might
8525 be using some of the registers being popped which
8526 would destory the contents of the register so
8527 we need to check for this condition and handle it */
8529 ic->next->op == IFX &&
8530 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8531 genIfx (ic->next,ic);
8549 genEndFunction (ic);
8569 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8586 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8590 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8597 /* note these two are xlated by algebraic equivalence
8598 during parsing SDCC.y */
8599 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8600 "got '>=' or '<=' shouldn't have come here");
8604 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8616 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8620 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8624 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8651 case GET_VALUE_AT_ADDRESS:
8656 if (POINTER_SET(ic))
8683 addSet(&_G.sendSet,ic);
8688 /* piCode(ic,stdout); */
8694 /* now we are ready to call the
8695 peep hole optimizer */
8696 if (!options.nopeep) {
8697 printf("peep hole optimizing\n");
8698 peepHole (&lineHead);
8700 /* now do the actual printing */
8701 printLine (lineHead,codeOutFile);