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"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 //char *aopLiteral (value *val, int offset);
57 char *pic14aopLiteral (value *val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
66 static char *spname = "sp";
68 char *fReturnpic14[] = {"dpl","dph","b","a" };
69 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
70 static unsigned fReturnSize = 4; /* shared with ralloc.c */
71 static char **fReturn = fReturnpic14;
73 static char *accUse[] = {"a","b"};
75 static short rbank = -1;
87 extern int pic14_ptrRegReq ;
88 extern int pic14_nRegs;
89 extern FILE *codeOutFile;
90 static void saverbank (int, iCode *,bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
96 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
98 static lineNode *lineHead = NULL;
99 static lineNode *lineCurr = NULL;
101 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
112 #define FUNCTION_LABEL_INC 20
113 static int labelOffset=0;
114 static int debug_verbose=1;
116 /*-----------------------------------------------------------------*/
117 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
118 /* exponent of 2 is returned, otherwise -1 is */
120 /* note that this is similar to the function `powof2' in SDCCsymt */
124 /*-----------------------------------------------------------------*/
125 static int my_powof2 (unsigned long num)
128 if( (num & (num-1)) == 0) {
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
145 static void emitcode (char *inst,char *fmt, ...)
148 char lb[MAX_INLINEASM];
155 sprintf(lb,"%s\t",inst);
157 sprintf(lb,"%s",inst);
158 vsprintf(lb+(strlen(lb)),fmt,ap);
162 while (isspace(*lbp)) lbp++;
165 lineCurr = (lineCurr ?
166 connectLine(lineCurr,newLineNode(lb)) :
167 (lineHead = newLineNode(lb)));
168 lineCurr->isInline = _G.inLine;
169 lineCurr->isDebug = _G.debugLine;
173 static void DEBUGemitcode (char *inst,char *fmt, ...)
176 char lb[MAX_INLINEASM];
186 sprintf(lb,"%s\t",inst);
188 sprintf(lb,"%s",inst);
189 vsprintf(lb+(strlen(lb)),fmt,ap);
193 while (isspace(*lbp)) lbp++;
196 lineCurr = (lineCurr ?
197 connectLine(lineCurr,newLineNode(lb)) :
198 (lineHead = newLineNode(lb)));
199 lineCurr->isInline = _G.inLine;
200 lineCurr->isDebug = _G.debugLine;
205 /*-----------------------------------------------------------------*/
206 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
207 /*-----------------------------------------------------------------*/
208 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
210 bool r0iu = FALSE , r1iu = FALSE;
211 bool r0ou = FALSE , r1ou = FALSE;
213 /* the logic: if r0 & r1 used in the instruction
214 then we are in trouble otherwise */
216 /* first check if r0 & r1 are used by this
217 instruction, in which case we are in trouble */
218 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
219 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
224 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
225 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
227 /* if no usage of r0 then return it */
228 if (!r0iu && !r0ou) {
229 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
230 (*aopp)->type = AOP_R0;
232 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
235 /* if no usage of r1 then return it */
236 if (!r1iu && !r1ou) {
237 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
238 (*aopp)->type = AOP_R1;
240 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
243 /* now we know they both have usage */
244 /* if r0 not used in this instruction */
246 /* push it if not already pushed */
248 emitcode ("push","%s",
249 pic14_regWithIdx(R0_IDX)->dname);
253 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
254 (*aopp)->type = AOP_R0;
256 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
259 /* if r1 not used then */
262 /* push it if not already pushed */
264 emitcode ("push","%s",
265 pic14_regWithIdx(R1_IDX)->dname);
269 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
270 (*aopp)->type = AOP_R1;
271 return pic14_regWithIdx(R1_IDX);
275 /* I said end of world but not quite end of world yet */
276 /* if this is a result then we can push it on the stack*/
278 (*aopp)->type = AOP_STK;
283 /* other wise this is true end of the world */
284 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
285 "getFreePtr should never reach here");
289 /*-----------------------------------------------------------------*/
290 /* newAsmop - creates a new asmOp */
291 /*-----------------------------------------------------------------*/
292 static asmop *newAsmop (short type)
296 ALLOC(aop,sizeof(asmop));
301 static void genSetDPTR(int n)
305 emitcode(";", "Select standard DPTR");
306 emitcode("mov", "dps, #0x00");
310 emitcode(";", "Select alternate DPTR");
311 emitcode("mov", "dps, #0x01");
315 /*-----------------------------------------------------------------*/
316 /* pointerCode - returns the code for a pointer type */
317 /*-----------------------------------------------------------------*/
318 static int pointerCode (sym_link *etype)
321 return PTR_TYPE(SPEC_OCLS(etype));
325 /*-----------------------------------------------------------------*/
326 /* aopForSym - for a true symbol */
327 /*-----------------------------------------------------------------*/
328 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
331 memmap *space= SPEC_OCLS(sym->etype);
333 /* if already has one */
337 /* assign depending on the storage class */
338 /* if it is on the stack or indirectly addressable */
339 /* space we need to assign either r0 or r1 to it */
340 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
341 sym->aop = aop = newAsmop(0);
342 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
343 aop->size = getSize(sym->type);
345 /* now assign the address of the variable to
346 the pointer register */
347 if (aop->type != AOP_STK) {
351 emitcode("push","acc");
353 emitcode("mov","a,_bp");
354 emitcode("add","a,#0x%02x",
356 ((char)(sym->stack - _G.nRegsSaved )) :
357 ((char)sym->stack)) & 0xff);
358 emitcode("mov","%s,a",
359 aop->aopu.aop_ptr->name);
362 emitcode("pop","acc");
364 emitcode("mov","%s,#%s",
365 aop->aopu.aop_ptr->name,
367 aop->paged = space->paged;
369 aop->aopu.aop_stk = sym->stack;
373 if (sym->onStack && options.stack10bit)
375 /* It's on the 10 bit stack, which is located in
380 emitcode("push","acc");
382 emitcode("mov","a,_bp");
383 emitcode("add","a,#0x%02x",
385 ((char)(sym->stack - _G.nRegsSaved )) :
386 ((char)sym->stack)) & 0xff);
389 emitcode ("mov","dpx1,#0x40");
390 emitcode ("mov","dph1,#0x00");
391 emitcode ("mov","dpl1, a");
395 emitcode("pop","acc");
397 sym->aop = aop = newAsmop(AOP_DPTR2);
398 aop->size = getSize(sym->type);
402 /* if in bit space */
403 if (IN_BITSPACE(space)) {
404 sym->aop = aop = newAsmop (AOP_CRY);
405 aop->aopu.aop_dir = sym->rname ;
406 aop->size = getSize(sym->type);
409 /* if it is in direct space */
410 if (IN_DIRSPACE(space)) {
411 sym->aop = aop = newAsmop (AOP_DIR);
412 aop->aopu.aop_dir = sym->rname ;
413 aop->size = getSize(sym->type);
417 /* special case for a function */
418 if (IS_FUNC(sym->type)) {
419 sym->aop = aop = newAsmop(AOP_IMMD);
420 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
421 strcpy(aop->aopu.aop_immd,sym->rname);
422 aop->size = FPTRSIZE;
426 /* only remaining is far space */
427 /* in which case DPTR gets the address */
428 sym->aop = aop = newAsmop(AOP_DPTR);
429 emitcode ("mov","dptr,#%s", sym->rname);
430 aop->size = getSize(sym->type);
432 /* if it is in code space */
433 if (IN_CODESPACE(space))
439 /*-----------------------------------------------------------------*/
440 /* aopForRemat - rematerialzes an object */
441 /*-----------------------------------------------------------------*/
442 static asmop *aopForRemat (symbol *sym)
444 iCode *ic = sym->rematiCode;
445 asmop *aop = newAsmop(AOP_IMMD);
447 emitcode(";","%s",__FUNCTION__);
450 val += operandLitValue(IC_RIGHT(ic));
451 else if (ic->op == '-')
452 val -= operandLitValue(IC_RIGHT(ic));
456 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
460 sprintf(buffer,"(%s %c 0x%04x)",
461 OP_SYMBOL(IC_LEFT(ic))->rname,
462 val >= 0 ? '+' : '-',
465 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
467 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
468 strcpy(aop->aopu.aop_immd,buffer);
472 /*-----------------------------------------------------------------*/
473 /* regsInCommon - two operands have some registers in common */
474 /*-----------------------------------------------------------------*/
475 static bool regsInCommon (operand *op1, operand *op2)
480 /* if they have registers in common */
481 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
484 sym1 = OP_SYMBOL(op1);
485 sym2 = OP_SYMBOL(op2);
487 if (sym1->nRegs == 0 || sym2->nRegs == 0)
490 for (i = 0 ; i < sym1->nRegs ; i++) {
495 for (j = 0 ; j < sym2->nRegs ;j++ ) {
499 if (sym2->regs[j] == sym1->regs[i])
507 /*-----------------------------------------------------------------*/
508 /* operandsEqu - equivalent */
509 /*-----------------------------------------------------------------*/
510 static bool operandsEqu ( operand *op1, operand *op2)
514 /* if they not symbols */
515 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
518 sym1 = OP_SYMBOL(op1);
519 sym2 = OP_SYMBOL(op2);
521 /* if both are itemps & one is spilt
522 and the other is not then false */
523 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
524 sym1->isspilt != sym2->isspilt )
527 /* if they are the same */
531 if (strcmp(sym1->rname,sym2->rname) == 0)
535 /* if left is a tmp & right is not */
539 (sym1->usl.spillLoc == sym2))
546 (sym2->usl.spillLoc == sym1))
552 /*-----------------------------------------------------------------*/
553 /* sameRegs - two asmops have the same registers */
554 /*-----------------------------------------------------------------*/
555 static bool sameRegs (asmop *aop1, asmop *aop2 )
562 if (aop1->type != AOP_REG ||
563 aop2->type != AOP_REG )
566 if (aop1->size != aop2->size )
569 for (i = 0 ; i < aop1->size ; i++ )
570 if (aop1->aopu.aop_reg[i] !=
571 aop2->aopu.aop_reg[i] )
577 /*-----------------------------------------------------------------*/
578 /* aopOp - allocates an asmop for an operand : */
579 /*-----------------------------------------------------------------*/
580 static void aopOp (operand *op, iCode *ic, bool result)
589 /* if this a literal */
590 if (IS_OP_LITERAL(op)) {
591 op->aop = aop = newAsmop(AOP_LIT);
592 aop->aopu.aop_lit = op->operand.valOperand;
593 aop->size = getSize(operandType(op));
597 /* if already has a asmop then continue */
601 /* if the underlying symbol has a aop */
602 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
603 op->aop = OP_SYMBOL(op)->aop;
607 /* if this is a true symbol */
608 if (IS_TRUE_SYMOP(op)) {
609 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
613 /* this is a temporary : this has
619 e) can be a return use only */
624 /* if the type is a conditional */
625 if (sym->regType == REG_CND) {
626 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
631 /* if it is spilt then two situations
633 b) has a spill location */
634 if (sym->isspilt || sym->nRegs == 0) {
636 /* rematerialize it NOW */
638 sym->aop = op->aop = aop =
640 aop->size = getSize(sym->type);
646 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
647 aop->size = getSize(sym->type);
648 for ( i = 0 ; i < 2 ; i++ )
649 aop->aopu.aop_str[i] = accUse[i];
655 aop = op->aop = sym->aop = newAsmop(AOP_STR);
656 aop->size = getSize(sym->type);
657 for ( i = 0 ; i < fReturnSize ; i++ )
658 aop->aopu.aop_str[i] = fReturn[i];
662 /* else spill location */
663 sym->aop = op->aop = aop =
664 aopForSym(ic,sym->usl.spillLoc,result);
665 aop->size = getSize(sym->type);
669 /* must be in a register */
670 sym->aop = op->aop = aop = newAsmop(AOP_REG);
671 aop->size = sym->nRegs;
672 for ( i = 0 ; i < sym->nRegs ;i++)
673 aop->aopu.aop_reg[i] = sym->regs[i];
676 /*-----------------------------------------------------------------*/
677 /* freeAsmop - free up the asmop given to an operand */
678 /*----------------------------------------------------------------*/
679 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
696 /* depending on the asmop type only three cases need work AOP_RO
697 , AOP_R1 && AOP_STK */
702 emitcode ("pop","ar0");
706 bitVectUnSetBit(ic->rUsed,R0_IDX);
712 emitcode ("pop","ar1");
716 bitVectUnSetBit(ic->rUsed,R1_IDX);
722 int stk = aop->aopu.aop_stk + aop->size;
723 bitVectUnSetBit(ic->rUsed,R0_IDX);
724 bitVectUnSetBit(ic->rUsed,R1_IDX);
726 getFreePtr(ic,&aop,FALSE);
728 if (options.stack10bit)
730 /* I'm not sure what to do here yet... */
733 "*** Warning: probably generating bad code for "
734 "10 bit stack mode.\n");
738 emitcode ("mov","a,_bp");
739 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
740 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
742 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
746 emitcode("pop","acc");
747 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
749 emitcode("dec","%s",aop->aopu.aop_ptr->name);
752 freeAsmop(op,NULL,ic,TRUE);
754 emitcode("pop","ar0");
759 emitcode("pop","ar1");
766 /* all other cases just dealloc */
770 OP_SYMBOL(op)->aop = NULL;
771 /* if the symbol has a spill */
773 SPIL_LOC(op)->aop = NULL;
778 /*-----------------------------------------------------------------*/
779 /* aopGet - for fetching value of the aop */
780 /*-----------------------------------------------------------------*/
781 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
786 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
787 /* offset is greater than
789 if (offset > (aop->size - 1) &&
790 aop->type != AOP_LIT)
793 /* depending on type */
798 DEBUGemitcode(";","%d",__LINE__);
799 /* if we need to increment it */
800 while (offset > aop->coff) {
801 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
805 while (offset < aop->coff) {
806 emitcode("dec","%s",aop->aopu.aop_ptr->name);
812 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
813 return (dname ? "acc" : "a");
815 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
816 ALLOC_ATOMIC(rs,strlen(s)+1);
822 DEBUGemitcode(";","%d",__LINE__);
823 if (aop->type == AOP_DPTR2)
828 while (offset > aop->coff) {
829 emitcode ("inc","dptr");
833 while (offset < aop->coff) {
834 emitcode("lcall","__decdptr");
841 emitcode("movc","a,@a+dptr");
844 emitcode("movx","a,@dptr");
847 if (aop->type == AOP_DPTR2)
852 return (dname ? "acc" : "a");
856 DEBUGemitcode(";","%d",__LINE__);
858 sprintf (s,"#%s",aop->aopu.aop_immd);
861 sprintf(s,"#(%s >> %d)",
867 ALLOC_ATOMIC(rs,strlen(s)+1);
873 sprintf(s,"(%s + %d)",
877 sprintf(s,"%s",aop->aopu.aop_dir);
878 ALLOC_ATOMIC(rs,strlen(s)+1);
883 DEBUGemitcode(";","%d",__LINE__);
885 return aop->aopu.aop_reg[offset]->dname;
887 return aop->aopu.aop_reg[offset]->name;
890 emitcode(";","%d",__LINE__);
891 //emitcode("clr","a");
892 //emitcode("mov","c,%s",aop->aopu.aop_dir);
893 //emitcode("rlc","a") ;
894 //return (dname ? "acc" : "a");
898 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
899 //if (!offset && dname)
901 //return aop->aopu.aop_str[offset];
902 return "AOP_accumulator_bug";
905 DEBUGemitcode(";","%d",__LINE__);
906 return pic14aopLiteral (aop->aopu.aop_lit,offset);
909 DEBUGemitcode(";","%d",__LINE__);
911 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
915 return aop->aopu.aop_str[offset];
919 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
920 "aopget got unsupported aop->type");
923 /*-----------------------------------------------------------------*/
924 /* aopPut - puts a string for a aop */
925 /*-----------------------------------------------------------------*/
926 static void aopPut (asmop *aop, char *s, int offset)
931 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
933 if (aop->size && offset > ( aop->size - 1)) {
934 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
935 "aopPut got offset > aop->size");
939 /* will assign value to value */
940 /* depending on where it is ofcourse */
944 sprintf(d,"(%s + %d)",
945 aop->aopu.aop_dir,offset);
947 sprintf(d,"%s",aop->aopu.aop_dir);
950 emitcode("movf","%s,w ; %d",s,__LINE__);
951 emitcode("movwf","%s",d);
956 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
957 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
959 strcmp(s,"r0") == 0 ||
960 strcmp(s,"r1") == 0 ||
961 strcmp(s,"r2") == 0 ||
962 strcmp(s,"r3") == 0 ||
963 strcmp(s,"r4") == 0 ||
964 strcmp(s,"r5") == 0 ||
965 strcmp(s,"r6") == 0 ||
966 strcmp(s,"r7") == 0 )
967 emitcode("mov","%s,%s ; %d",
968 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
970 emitcode("mov","%s,%s ; %d",
971 aop->aopu.aop_reg[offset]->name,s,__LINE__);
978 if (aop->type == AOP_DPTR2)
984 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
985 "aopPut writting to code space");
989 while (offset > aop->coff) {
991 emitcode ("inc","dptr");
994 while (offset < aop->coff) {
996 emitcode("lcall","__decdptr");
1001 /* if not in accumulater */
1004 emitcode ("movx","@dptr,a");
1006 if (aop->type == AOP_DPTR2)
1014 while (offset > aop->coff) {
1016 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1018 while (offset < aop->coff) {
1020 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1026 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1031 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1033 if (strcmp(s,"r0") == 0 ||
1034 strcmp(s,"r1") == 0 ||
1035 strcmp(s,"r2") == 0 ||
1036 strcmp(s,"r3") == 0 ||
1037 strcmp(s,"r4") == 0 ||
1038 strcmp(s,"r5") == 0 ||
1039 strcmp(s,"r6") == 0 ||
1040 strcmp(s,"r7") == 0 ) {
1042 sprintf(buffer,"a%s",s);
1043 emitcode("mov","@%s,%s",
1044 aop->aopu.aop_ptr->name,buffer);
1046 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1051 if (strcmp(s,"a") == 0)
1052 emitcode("push","acc");
1054 emitcode("push","%s",s);
1059 /* if bit variable */
1060 if (!aop->aopu.aop_dir) {
1061 emitcode("clr","a");
1062 emitcode("rlc","a");
1065 emitcode("clr","%s",aop->aopu.aop_dir);
1068 emitcode("setb","%s",aop->aopu.aop_dir);
1071 emitcode("mov","%s,c",aop->aopu.aop_dir);
1073 lbl = newiTempLabel(NULL);
1075 if (strcmp(s,"a")) {
1078 emitcode("clr","c");
1079 emitcode("jz","%05d_DS_",lbl->key+100);
1080 emitcode("cpl","c");
1081 emitcode("","%05d_DS_:",lbl->key+100);
1082 emitcode("mov","%s,c",aop->aopu.aop_dir);
1089 if (strcmp(aop->aopu.aop_str[offset],s))
1090 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1095 if (!offset && (strcmp(s,"acc") == 0))
1098 if (strcmp(aop->aopu.aop_str[offset],s))
1099 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1103 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1104 "aopPut got unsupported aop->type");
1110 /*-----------------------------------------------------------------*/
1111 /* reAdjustPreg - points a register back to where it should */
1112 /*-----------------------------------------------------------------*/
1113 static void reAdjustPreg (asmop *aop)
1117 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1119 if ((size = aop->size) <= 1)
1122 switch (aop->type) {
1126 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130 if (aop->type == AOP_DPTR2)
1136 emitcode("lcall","__decdptr");
1139 if (aop->type == AOP_DPTR2)
1149 #define AOP(op) op->aop
1150 #define AOP_TYPE(op) AOP(op)->type
1151 #define AOP_SIZE(op) AOP(op)->size
1152 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1153 AOP_TYPE(x) == AOP_R0))
1155 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1156 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1159 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1160 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1161 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1163 /*-----------------------------------------------------------------*/
1164 /* genNotFloat - generates not for float operations */
1165 /*-----------------------------------------------------------------*/
1166 static void genNotFloat (operand *op, operand *res)
1172 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1173 /* we will put 127 in the first byte of
1175 aopPut(AOP(res),"#127",0);
1176 size = AOP_SIZE(op) - 1;
1179 l = aopGet(op->aop,offset++,FALSE,FALSE);
1183 emitcode("orl","a,%s",
1185 offset++,FALSE,FALSE));
1187 tlbl = newiTempLabel(NULL);
1189 tlbl = newiTempLabel(NULL);
1190 aopPut(res->aop,one,1);
1191 emitcode("jz","%05d_DS_",(tlbl->key+100));
1192 aopPut(res->aop,zero,1);
1193 emitcode("","%05d_DS_:",(tlbl->key+100));
1195 size = res->aop->size - 2;
1197 /* put zeros in the rest */
1199 aopPut(res->aop,zero,offset++);
1202 /*-----------------------------------------------------------------*/
1203 /* opIsGptr: returns non-zero if the passed operand is */
1204 /* a generic pointer type. */
1205 /*-----------------------------------------------------------------*/
1206 static int opIsGptr(operand *op)
1208 sym_link *type = operandType(op);
1210 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1211 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1218 /*-----------------------------------------------------------------*/
1219 /* getDataSize - get the operand data size */
1220 /*-----------------------------------------------------------------*/
1221 static int getDataSize(operand *op)
1224 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1225 size = AOP_SIZE(op);
1226 if (size == GPTRSIZE)
1228 sym_link *type = operandType(op);
1229 if (IS_GENPTR(type))
1231 /* generic pointer; arithmetic operations
1232 * should ignore the high byte (pointer type).
1240 /*-----------------------------------------------------------------*/
1241 /* outAcc - output Acc */
1242 /*-----------------------------------------------------------------*/
1243 static void outAcc(operand *result)
1246 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1247 size = getDataSize(result);
1249 aopPut(AOP(result),"a",0);
1252 /* unsigned or positive */
1254 aopPut(AOP(result),zero,offset++);
1259 /*-----------------------------------------------------------------*/
1260 /* outBitC - output a bit C */
1261 /*-----------------------------------------------------------------*/
1262 static void outBitC(operand *result)
1265 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1266 /* if the result is bit */
1267 if (AOP_TYPE(result) == AOP_CRY)
1268 aopPut(AOP(result),"c",0);
1270 emitcode("clr","a ; %d", __LINE__);
1271 emitcode("rlc","a");
1276 /*-----------------------------------------------------------------*/
1277 /* toBoolean - emit code for orl a,operator(sizeop) */
1278 /*-----------------------------------------------------------------*/
1279 static void toBoolean(operand *oper)
1281 int size = AOP_SIZE(oper) - 1;
1284 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1286 if ( AOP_TYPE(oper) != AOP_ACC)
1287 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1290 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1294 /*-----------------------------------------------------------------*/
1295 /* genNot - generate code for ! operation */
1296 /*-----------------------------------------------------------------*/
1297 static void genNot (iCode *ic)
1300 sym_link *optype = operandType(IC_LEFT(ic));
1302 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1303 /* assign asmOps to operand & result */
1304 aopOp (IC_LEFT(ic),ic,FALSE);
1305 aopOp (IC_RESULT(ic),ic,TRUE);
1307 /* if in bit space then a special case */
1308 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1309 emitcode("movlw","1<<%s");
1310 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1311 //emitcode("cpl","c");
1312 //outBitC(IC_RESULT(ic));
1316 /* if type float then do float */
1317 if (IS_FLOAT(optype)) {
1318 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1322 toBoolean(IC_LEFT(ic));
1324 tlbl = newiTempLabel(NULL);
1325 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1326 emitcode("","%05d_DS_:",tlbl->key+100);
1327 outBitC(IC_RESULT(ic));
1330 /* release the aops */
1331 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1332 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1336 /*-----------------------------------------------------------------*/
1337 /* genCpl - generate code for complement */
1338 /*-----------------------------------------------------------------*/
1339 static void genCpl (iCode *ic)
1345 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1346 /* assign asmOps to operand & result */
1347 aopOp (IC_LEFT(ic),ic,FALSE);
1348 aopOp (IC_RESULT(ic),ic,TRUE);
1350 /* if both are in bit space then
1352 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1353 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1355 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1356 emitcode("cpl","c");
1357 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1361 size = AOP_SIZE(IC_RESULT(ic));
1363 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1365 emitcode("cpl","a");
1366 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1371 /* release the aops */
1372 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1373 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1376 /*-----------------------------------------------------------------*/
1377 /* genUminusFloat - unary minus for floating points */
1378 /*-----------------------------------------------------------------*/
1379 static void genUminusFloat(operand *op,operand *result)
1381 int size ,offset =0 ;
1384 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1385 /* for this we just need to flip the
1386 first it then copy the rest in place */
1387 size = AOP_SIZE(op) - 1;
1388 l = aopGet(AOP(op),3,FALSE,FALSE);
1392 emitcode("cpl","acc.7");
1393 aopPut(AOP(result),"a",3);
1397 aopGet(AOP(op),offset,FALSE,FALSE),
1403 /*-----------------------------------------------------------------*/
1404 /* genUminus - unary minus code generation */
1405 /*-----------------------------------------------------------------*/
1406 static void genUminus (iCode *ic)
1409 sym_link *optype, *rtype;
1412 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1414 aopOp(IC_LEFT(ic),ic,FALSE);
1415 aopOp(IC_RESULT(ic),ic,TRUE);
1417 /* if both in bit space then special
1419 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1420 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1422 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1423 emitcode("cpl","c");
1424 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1428 optype = operandType(IC_LEFT(ic));
1429 rtype = operandType(IC_RESULT(ic));
1431 /* if float then do float stuff */
1432 if (IS_FLOAT(optype)) {
1433 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1437 /* otherwise subtract from zero */
1438 size = AOP_SIZE(IC_LEFT(ic));
1442 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1443 if (!strcmp(l,"a")) {
1444 emitcode("cpl","a");
1445 emitcode("inc","a");
1447 emitcode("clr","a");
1448 emitcode("subb","a,%s",l);
1450 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1453 /* if any remaining bytes in the result */
1454 /* we just need to propagate the sign */
1455 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1456 emitcode("rlc","a");
1457 emitcode("subb","a,acc");
1459 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1463 /* release the aops */
1464 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1465 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1468 /*-----------------------------------------------------------------*/
1469 /* saveRegisters - will look for a call and save the registers */
1470 /*-----------------------------------------------------------------*/
1471 static void saveRegisters(iCode *lic)
1478 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1480 for (ic = lic ; ic ; ic = ic->next)
1481 if (ic->op == CALL || ic->op == PCALL)
1485 fprintf(stderr,"found parameter push with no function call\n");
1489 /* if the registers have been saved already then
1491 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1494 /* find the registers in use at this time
1495 and push them away to safety */
1496 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1500 if (options.useXstack) {
1501 if (bitVectBitValue(rsave,R0_IDX))
1502 emitcode("mov","b,r0");
1503 emitcode("mov","r0,%s",spname);
1504 for (i = 0 ; i < pic14_nRegs ; i++) {
1505 if (bitVectBitValue(rsave,i)) {
1507 emitcode("mov","a,b");
1509 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1510 emitcode("movx","@r0,a");
1511 emitcode("inc","r0");
1514 emitcode("mov","%s,r0",spname);
1515 if (bitVectBitValue(rsave,R0_IDX))
1516 emitcode("mov","r0,b");
1518 for (i = 0 ; i < pic14_nRegs ; i++) {
1519 if (bitVectBitValue(rsave,i))
1520 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1523 detype = getSpec(operandType(IC_LEFT(ic)));
1525 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1526 IS_ISR(currFunc->etype) &&
1529 saverbank(SPEC_BANK(detype),ic,TRUE);
1532 /*-----------------------------------------------------------------*/
1533 /* unsaveRegisters - pop the pushed registers */
1534 /*-----------------------------------------------------------------*/
1535 static void unsaveRegisters (iCode *ic)
1540 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1541 /* find the registers in use at this time
1542 and push them away to safety */
1543 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1546 if (options.useXstack) {
1547 emitcode("mov","r0,%s",spname);
1548 for (i = pic14_nRegs ; i >= 0 ; i--) {
1549 if (bitVectBitValue(rsave,i)) {
1550 emitcode("dec","r0");
1551 emitcode("movx","a,@r0");
1553 emitcode("mov","b,a");
1555 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1559 emitcode("mov","%s,r0",spname);
1560 if (bitVectBitValue(rsave,R0_IDX))
1561 emitcode("mov","r0,b");
1563 for (i = pic14_nRegs ; i >= 0 ; i--) {
1564 if (bitVectBitValue(rsave,i))
1565 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1571 /*-----------------------------------------------------------------*/
1573 /*-----------------------------------------------------------------*/
1574 static void pushSide(operand * oper, int size)
1577 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1579 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1580 if (AOP_TYPE(oper) != AOP_REG &&
1581 AOP_TYPE(oper) != AOP_DIR &&
1583 emitcode("mov","a,%s",l);
1584 emitcode("push","acc");
1586 emitcode("push","%s",l);
1590 /*-----------------------------------------------------------------*/
1591 /* assignResultValue - */
1592 /*-----------------------------------------------------------------*/
1593 static void assignResultValue(operand * oper)
1596 int size = AOP_SIZE(oper);
1598 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1601 aopPut(AOP(oper),fReturn[offset],offset);
1607 /*-----------------------------------------------------------------*/
1608 /* genXpush - pushes onto the external stack */
1609 /*-----------------------------------------------------------------*/
1610 static void genXpush (iCode *ic)
1612 asmop *aop = newAsmop(0);
1614 int size,offset = 0;
1616 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1617 aopOp(IC_LEFT(ic),ic,FALSE);
1618 r = getFreePtr(ic,&aop,FALSE);
1621 emitcode("mov","%s,_spx",r->name);
1623 size = AOP_SIZE(IC_LEFT(ic));
1626 char *l = aopGet(AOP(IC_LEFT(ic)),
1627 offset++,FALSE,FALSE);
1629 emitcode("movx","@%s,a",r->name);
1630 emitcode("inc","%s",r->name);
1635 emitcode("mov","_spx,%s",r->name);
1637 freeAsmop(NULL,aop,ic,TRUE);
1638 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1641 /*-----------------------------------------------------------------*/
1642 /* genIpush - genrate code for pushing this gets a little complex */
1643 /*-----------------------------------------------------------------*/
1644 static void genIpush (iCode *ic)
1646 int size, offset = 0 ;
1650 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1651 /* if this is not a parm push : ie. it is spill push
1652 and spill push is always done on the local stack */
1653 if (!ic->parmPush) {
1655 /* and the item is spilt then do nothing */
1656 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1659 aopOp(IC_LEFT(ic),ic,FALSE);
1660 size = AOP_SIZE(IC_LEFT(ic));
1661 /* push it on the stack */
1663 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1668 emitcode("push","%s",l);
1673 /* this is a paramter push: in this case we call
1674 the routine to find the call and save those
1675 registers that need to be saved */
1678 /* if use external stack then call the external
1679 stack pushing routine */
1680 if (options.useXstack) {
1685 /* then do the push */
1686 aopOp(IC_LEFT(ic),ic,FALSE);
1689 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1690 size = AOP_SIZE(IC_LEFT(ic));
1693 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1694 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1695 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1697 emitcode("mov","a,%s",l);
1698 emitcode("push","acc");
1700 emitcode("push","%s",l);
1703 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1706 /*-----------------------------------------------------------------*/
1707 /* genIpop - recover the registers: can happen only for spilling */
1708 /*-----------------------------------------------------------------*/
1709 static void genIpop (iCode *ic)
1714 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1715 /* if the temp was not pushed then */
1716 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1719 aopOp(IC_LEFT(ic),ic,FALSE);
1720 size = AOP_SIZE(IC_LEFT(ic));
1723 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1726 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1729 /*-----------------------------------------------------------------*/
1730 /* unsaverbank - restores the resgister bank from stack */
1731 /*-----------------------------------------------------------------*/
1732 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1738 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1740 if (options.useXstack) {
1742 r = getFreePtr(ic,&aop,FALSE);
1745 emitcode("mov","%s,_spx",r->name);
1746 emitcode("movx","a,@%s",r->name);
1747 emitcode("mov","psw,a");
1748 emitcode("dec","%s",r->name);
1751 emitcode ("pop","psw");
1754 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1755 if (options.useXstack) {
1756 emitcode("movx","a,@%s",r->name);
1757 emitcode("mov","(%s+%d),a",
1758 regspic14[i].base,8*bank+regspic14[i].offset);
1759 emitcode("dec","%s",r->name);
1762 emitcode("pop","(%s+%d)",
1763 regspic14[i].base,8*bank+regspic14[i].offset);
1766 if (options.useXstack) {
1768 emitcode("mov","_spx,%s",r->name);
1769 freeAsmop(NULL,aop,ic,TRUE);
1774 /*-----------------------------------------------------------------*/
1775 /* saverbank - saves an entire register bank on the stack */
1776 /*-----------------------------------------------------------------*/
1777 static void saverbank (int bank, iCode *ic, bool pushPsw)
1783 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1784 if (options.useXstack) {
1787 r = getFreePtr(ic,&aop,FALSE);
1788 emitcode("mov","%s,_spx",r->name);
1792 for (i = 0 ; i < pic14_nRegs ;i++) {
1793 if (options.useXstack) {
1794 emitcode("inc","%s",r->name);
1795 emitcode("mov","a,(%s+%d)",
1796 regspic14[i].base,8*bank+regspic14[i].offset);
1797 emitcode("movx","@%s,a",r->name);
1799 emitcode("push","(%s+%d)",
1800 regspic14[i].base,8*bank+regspic14[i].offset);
1804 if (options.useXstack) {
1805 emitcode("mov","a,psw");
1806 emitcode("movx","@%s,a",r->name);
1807 emitcode("inc","%s",r->name);
1808 emitcode("mov","_spx,%s",r->name);
1809 freeAsmop (NULL,aop,ic,TRUE);
1812 emitcode("push","psw");
1814 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1820 /*-----------------------------------------------------------------*/
1821 /* genCall - generates a call statement */
1822 /*-----------------------------------------------------------------*/
1823 static void genCall (iCode *ic)
1827 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1829 /* if caller saves & we have not saved then */
1833 /* if we are calling a function that is not using
1834 the same register bank then we need to save the
1835 destination registers on the stack */
1836 detype = getSpec(operandType(IC_LEFT(ic)));
1838 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1839 IS_ISR(currFunc->etype) &&
1842 saverbank(SPEC_BANK(detype),ic,TRUE);
1844 /* if send set is not empty the assign */
1848 for (sic = setFirstItem(_G.sendSet) ; sic ;
1849 sic = setNextItem(_G.sendSet)) {
1850 int size, offset = 0;
1851 aopOp(IC_LEFT(sic),sic,FALSE);
1852 size = AOP_SIZE(IC_LEFT(sic));
1854 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1856 if (strcmp(l,fReturn[offset]))
1857 emitcode("mov","%s,%s",
1862 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1867 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1868 OP_SYMBOL(IC_LEFT(ic))->rname :
1869 OP_SYMBOL(IC_LEFT(ic))->name));
1871 /* if we need assign a result value */
1872 if ((IS_ITEMP(IC_RESULT(ic)) &&
1873 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1874 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1875 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1878 aopOp(IC_RESULT(ic),ic,FALSE);
1881 assignResultValue(IC_RESULT(ic));
1883 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1886 /* adjust the stack for parameters if
1888 if (IC_LEFT(ic)->parmBytes) {
1890 if (IC_LEFT(ic)->parmBytes > 3) {
1891 emitcode("mov","a,%s",spname);
1892 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1893 emitcode("mov","%s,a",spname);
1895 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1896 emitcode("dec","%s",spname);
1900 /* if register bank was saved then pop them */
1902 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1904 /* if we hade saved some registers then unsave them */
1905 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1906 unsaveRegisters (ic);
1911 /*-----------------------------------------------------------------*/
1912 /* genPcall - generates a call by pointer statement */
1913 /*-----------------------------------------------------------------*/
1914 static void genPcall (iCode *ic)
1917 symbol *rlbl = newiTempLabel(NULL);
1920 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1921 /* if caller saves & we have not saved then */
1925 /* if we are calling a function that is not using
1926 the same register bank then we need to save the
1927 destination registers on the stack */
1928 detype = getSpec(operandType(IC_LEFT(ic)));
1930 IS_ISR(currFunc->etype) &&
1931 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1932 saverbank(SPEC_BANK(detype),ic,TRUE);
1935 /* push the return address on to the stack */
1936 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
1937 emitcode("push","acc");
1938 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
1939 emitcode("push","acc");
1941 if (options.model == MODEL_FLAT24)
1943 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
1944 emitcode("push","acc");
1947 /* now push the calling address */
1948 aopOp(IC_LEFT(ic),ic,FALSE);
1950 pushSide(IC_LEFT(ic), FPTRSIZE);
1952 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1954 /* if send set is not empty the assign */
1958 for (sic = setFirstItem(_G.sendSet) ; sic ;
1959 sic = setNextItem(_G.sendSet)) {
1960 int size, offset = 0;
1961 aopOp(IC_LEFT(sic),sic,FALSE);
1962 size = AOP_SIZE(IC_LEFT(sic));
1964 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1966 if (strcmp(l,fReturn[offset]))
1967 emitcode("mov","%s,%s",
1972 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1978 emitcode("","%05d_DS_:",(rlbl->key+100));
1981 /* if we need assign a result value */
1982 if ((IS_ITEMP(IC_RESULT(ic)) &&
1983 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1984 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1985 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1988 aopOp(IC_RESULT(ic),ic,FALSE);
1991 assignResultValue(IC_RESULT(ic));
1993 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1996 /* adjust the stack for parameters if
1998 if (IC_LEFT(ic)->parmBytes) {
2000 if (IC_LEFT(ic)->parmBytes > 3) {
2001 emitcode("mov","a,%s",spname);
2002 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2003 emitcode("mov","%s,a",spname);
2005 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2006 emitcode("dec","%s",spname);
2010 /* if register bank was saved then unsave them */
2012 (SPEC_BANK(currFunc->etype) !=
2014 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2016 /* if we hade saved some registers then
2019 unsaveRegisters (ic);
2023 /*-----------------------------------------------------------------*/
2024 /* resultRemat - result is rematerializable */
2025 /*-----------------------------------------------------------------*/
2026 static int resultRemat (iCode *ic)
2028 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2029 if (SKIP_IC(ic) || ic->op == IFX)
2032 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2033 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2034 if (sym->remat && !POINTER_SET(ic))
2042 #define STRCASECMP stricmp
2044 #define STRCASECMP strcasecmp
2047 /*-----------------------------------------------------------------*/
2048 /* inExcludeList - return 1 if the string is in exclude Reg list */
2049 /*-----------------------------------------------------------------*/
2050 static bool inExcludeList(char *s)
2054 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2055 if (options.excludeRegs[i] &&
2056 STRCASECMP(options.excludeRegs[i],"none") == 0)
2059 for ( i = 0 ; options.excludeRegs[i]; i++) {
2060 if (options.excludeRegs[i] &&
2061 STRCASECMP(s,options.excludeRegs[i]) == 0)
2067 /*-----------------------------------------------------------------*/
2068 /* genFunction - generated code for function entry */
2069 /*-----------------------------------------------------------------*/
2070 static void genFunction (iCode *ic)
2075 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2076 labelOffset += FUNCTION_LABEL_INC;
2079 /* create the function header */
2080 emitcode(";","-----------------------------------------");
2081 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2082 emitcode(";","-----------------------------------------");
2084 emitcode("","%s:",sym->rname);
2085 fetype = getSpec(operandType(IC_LEFT(ic)));
2087 /* if critical function then turn interrupts off */
2088 if (SPEC_CRTCL(fetype))
2089 emitcode("clr","ea");
2091 /* here we need to generate the equates for the
2092 register bank if required */
2094 if (SPEC_BANK(fetype) != rbank) {
2097 rbank = SPEC_BANK(fetype);
2098 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2099 if (strcmp(regspic14[i].base,"0") == 0)
2100 emitcode("","%s = 0x%02x",
2102 8*rbank+regspic14[i].offset);
2104 emitcode ("","%s = %s + 0x%02x",
2107 8*rbank+regspic14[i].offset);
2112 /* if this is an interrupt service routine then
2113 save acc, b, dpl, dph */
2114 if (IS_ISR(sym->etype)) {
2116 if (!inExcludeList("acc"))
2117 emitcode ("push","acc");
2118 if (!inExcludeList("b"))
2119 emitcode ("push","b");
2120 if (!inExcludeList("dpl"))
2121 emitcode ("push","dpl");
2122 if (!inExcludeList("dph"))
2123 emitcode ("push","dph");
2124 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2126 emitcode ("push", "dpx");
2127 /* Make sure we're using standard DPTR */
2128 emitcode ("push", "dps");
2129 emitcode ("mov", "dps, #0x00");
2130 if (options.stack10bit)
2132 /* This ISR could conceivably use DPTR2. Better save it. */
2133 emitcode ("push", "dpl1");
2134 emitcode ("push", "dph1");
2135 emitcode ("push", "dpx1");
2138 /* if this isr has no bank i.e. is going to
2139 run with bank 0 , then we need to save more
2141 if (!SPEC_BANK(sym->etype)) {
2143 /* if this function does not call any other
2144 function then we can be economical and
2145 save only those registers that are used */
2146 if (! sym->hasFcall) {
2149 /* if any registers used */
2150 if (sym->regsUsed) {
2151 /* save the registers used */
2152 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2153 if (bitVectBitValue(sym->regsUsed,i) ||
2154 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2155 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2160 /* this function has a function call cannot
2161 determines register usage so we will have the
2163 saverbank(0,ic,FALSE);
2167 /* if callee-save to be used for this function
2168 then save the registers being used in this function */
2169 if (sym->calleeSave) {
2172 /* if any registers used */
2173 if (sym->regsUsed) {
2174 /* save the registers used */
2175 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2176 if (bitVectBitValue(sym->regsUsed,i) ||
2177 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2178 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2186 /* set the register bank to the desired value */
2187 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2188 emitcode("push","psw");
2189 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2192 if (IS_RENT(sym->etype) || options.stackAuto) {
2194 if (options.useXstack) {
2195 emitcode("mov","r0,%s",spname);
2196 emitcode("mov","a,_bp");
2197 emitcode("movx","@r0,a");
2198 emitcode("inc","%s",spname);
2202 /* set up the stack */
2203 emitcode ("push","_bp"); /* save the callers stack */
2205 emitcode ("mov","_bp,%s",spname);
2208 /* adjust the stack for the function */
2213 werror(W_STACK_OVERFLOW,sym->name);
2215 if (i > 3 && sym->recvSize < 4) {
2217 emitcode ("mov","a,sp");
2218 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2219 emitcode ("mov","sp,a");
2224 emitcode("inc","sp");
2229 emitcode ("mov","a,_spx");
2230 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2231 emitcode ("mov","_spx,a");
2236 /*-----------------------------------------------------------------*/
2237 /* genEndFunction - generates epilogue for functions */
2238 /*-----------------------------------------------------------------*/
2239 static void genEndFunction (iCode *ic)
2241 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2243 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2245 if (IS_RENT(sym->etype) || options.stackAuto)
2247 emitcode ("mov","%s,_bp",spname);
2250 /* if use external stack but some variables were
2251 added to the local stack then decrement the
2253 if (options.useXstack && sym->stack) {
2254 emitcode("mov","a,sp");
2255 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2256 emitcode("mov","sp,a");
2260 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2261 if (options.useXstack) {
2262 emitcode("mov","r0,%s",spname);
2263 emitcode("movx","a,@r0");
2264 emitcode("mov","_bp,a");
2265 emitcode("dec","%s",spname);
2269 emitcode ("pop","_bp");
2273 /* restore the register bank */
2274 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2275 emitcode ("pop","psw");
2277 if (IS_ISR(sym->etype)) {
2279 /* now we need to restore the registers */
2280 /* if this isr has no bank i.e. is going to
2281 run with bank 0 , then we need to save more
2283 if (!SPEC_BANK(sym->etype)) {
2285 /* if this function does not call any other
2286 function then we can be economical and
2287 save only those registers that are used */
2288 if (! sym->hasFcall) {
2291 /* if any registers used */
2292 if (sym->regsUsed) {
2293 /* save the registers used */
2294 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2295 if (bitVectBitValue(sym->regsUsed,i) ||
2296 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2297 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2302 /* this function has a function call cannot
2303 determines register usage so we will have the
2305 unsaverbank(0,ic,FALSE);
2309 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2311 if (options.stack10bit)
2313 emitcode ("pop", "dpx1");
2314 emitcode ("pop", "dph1");
2315 emitcode ("pop", "dpl1");
2317 emitcode ("pop", "dps");
2318 emitcode ("pop", "dpx");
2320 if (!inExcludeList("dph"))
2321 emitcode ("pop","dph");
2322 if (!inExcludeList("dpl"))
2323 emitcode ("pop","dpl");
2324 if (!inExcludeList("b"))
2325 emitcode ("pop","b");
2326 if (!inExcludeList("acc"))
2327 emitcode ("pop","acc");
2329 if (SPEC_CRTCL(sym->etype))
2330 emitcode("setb","ea");
2332 /* if debug then send end of function */
2333 /* if (options.debug && currFunc) { */
2336 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2337 ic->filename,currFunc->lastLine,
2338 ic->level,ic->block);
2339 if (IS_STATIC(currFunc->etype))
2340 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2342 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2346 emitcode ("reti","");
2349 if (SPEC_CRTCL(sym->etype))
2350 emitcode("setb","ea");
2352 if (sym->calleeSave) {
2355 /* if any registers used */
2356 if (sym->regsUsed) {
2357 /* save the registers used */
2358 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2359 if (bitVectBitValue(sym->regsUsed,i) ||
2360 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2361 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2367 /* if debug then send end of function */
2370 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2371 ic->filename,currFunc->lastLine,
2372 ic->level,ic->block);
2373 if (IS_STATIC(currFunc->etype))
2374 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2376 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2380 emitcode ("return","");
2385 /*-----------------------------------------------------------------*/
2386 /* genRet - generate code for return statement */
2387 /*-----------------------------------------------------------------*/
2388 static void genRet (iCode *ic)
2390 int size,offset = 0 , pushed = 0;
2392 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2393 /* if we have no return value then
2394 just generate the "ret" */
2398 /* we have something to return then
2399 move the return value into place */
2400 aopOp(IC_LEFT(ic),ic,FALSE);
2401 size = AOP_SIZE(IC_LEFT(ic));
2405 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2407 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2409 emitcode("push","%s",l);
2412 l = aopGet(AOP(IC_LEFT(ic)),offset,
2414 if (strcmp(fReturn[offset],l))
2415 emitcode("mov","%s,%s",fReturn[offset++],l);
2422 if (strcmp(fReturn[pushed],"a"))
2423 emitcode("pop",fReturn[pushed]);
2425 emitcode("pop","acc");
2428 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2431 /* generate a jump to the return label
2432 if the next is not the return statement */
2433 if (!(ic->next && ic->next->op == LABEL &&
2434 IC_LABEL(ic->next) == returnLabel))
2436 emitcode("goto","_%05d_DS_",(returnLabel->key+100));
2440 /*-----------------------------------------------------------------*/
2441 /* genLabel - generates a label */
2442 /*-----------------------------------------------------------------*/
2443 static void genLabel (iCode *ic)
2445 /* special case never generate */
2446 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2447 if (IC_LABEL(ic) == entryLabel)
2450 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2453 /*-----------------------------------------------------------------*/
2454 /* genGoto - generates a goto */
2455 /*-----------------------------------------------------------------*/
2457 static void genGoto (iCode *ic)
2459 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100));
2462 /*-----------------------------------------------------------------*/
2463 /* findLabelBackwards: walks back through the iCode chain looking */
2464 /* for the given label. Returns number of iCode instructions */
2465 /* between that label and given ic. */
2466 /* Returns zero if label not found. */
2467 /*-----------------------------------------------------------------*/
2468 static int findLabelBackwards(iCode *ic, int key)
2472 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2478 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2480 /* printf("findLabelBackwards = %d\n", count); */
2488 /*-----------------------------------------------------------------*/
2489 /* genPlusIncr :- does addition with increment if possible */
2490 /*-----------------------------------------------------------------*/
2491 static bool genPlusIncr (iCode *ic)
2493 unsigned int icount ;
2494 unsigned int size = getDataSize(IC_RESULT(ic));
2496 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2497 /* will try to generate an increment */
2498 /* if the right side is not a literal
2500 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2503 /* if the literal value of the right hand side
2504 is greater than 1 then it is faster to add */
2505 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2508 /* if increment 16 bits in register */
2509 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2514 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2517 emitcode("skpnz","");
2518 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2524 /* if the sizes are greater than 1 then we cannot */
2525 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2526 AOP_SIZE(IC_LEFT(ic)) > 1 )
2529 /* If we are incrementing the same register by two: */
2531 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2534 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2542 /*-----------------------------------------------------------------*/
2543 /* outBitAcc - output a bit in acc */
2544 /*-----------------------------------------------------------------*/
2545 static void outBitAcc(operand *result)
2547 symbol *tlbl = newiTempLabel(NULL);
2548 /* if the result is a bit */
2549 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2551 if (AOP_TYPE(result) == AOP_CRY){
2552 aopPut(AOP(result),"a",0);
2555 emitcode("jz","%05d_DS_",tlbl->key+100);
2556 emitcode("mov","a,%s",one);
2557 emitcode("","%05d_DS_:",tlbl->key+100);
2562 /*-----------------------------------------------------------------*/
2563 /* genPlusBits - generates code for addition of two bits */
2564 /*-----------------------------------------------------------------*/
2565 static void genPlusBits (iCode *ic)
2568 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2570 The following block of code will add two bits.
2571 Note that it'll even work if the destination is
2572 the carry (C in the status register).
2573 It won't work if the 'Z' bit is a source or destination.
2575 emitcode("movlw","(1 << (%s & 7))",
2576 AOP(IC_RESULT(ic))->aopu.aop_dir,
2577 AOP(IC_RESULT(ic))->aopu.aop_dir);
2578 emitcode("bcf","(%s >> 3), (%s & 7)",
2579 AOP(IC_RESULT(ic))->aopu.aop_dir,
2580 AOP(IC_RESULT(ic))->aopu.aop_dir);
2581 emitcode("btfsc","(%s >> 3), (%s & 7)",
2582 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2583 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2584 emitcode("xorwf","%s,f",
2585 AOP(IC_RESULT(ic))->aopu.aop_dir);
2586 emitcode("btfsc","(%s >> 3), (%s & 7)",
2587 AOP(IC_LEFT(ic))->aopu.aop_dir,
2588 AOP(IC_LEFT(ic))->aopu.aop_dir);
2589 emitcode("xorwf","%s,f",
2590 AOP(IC_RESULT(ic))->aopu.aop_dir);
2594 /* This is the original version of this code.
2596 * This is being kept around for reference,
2597 * because I am not entirely sure I got it right...
2599 static void adjustArithmeticResult(iCode *ic)
2601 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2602 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2603 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2604 aopPut(AOP(IC_RESULT(ic)),
2605 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2608 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2609 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2610 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2611 aopPut(AOP(IC_RESULT(ic)),
2612 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2615 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2616 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2617 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2618 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2619 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2621 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2622 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2626 /* This is the pure and virtuous version of this code.
2627 * I'm pretty certain it's right, but not enough to toss the old
2630 static void adjustArithmeticResult(iCode *ic)
2632 if (opIsGptr(IC_RESULT(ic)) &&
2633 opIsGptr(IC_LEFT(ic)) &&
2634 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2636 aopPut(AOP(IC_RESULT(ic)),
2637 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2641 if (opIsGptr(IC_RESULT(ic)) &&
2642 opIsGptr(IC_RIGHT(ic)) &&
2643 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2645 aopPut(AOP(IC_RESULT(ic)),
2646 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2650 if (opIsGptr(IC_RESULT(ic)) &&
2651 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2652 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2653 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2654 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2656 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2657 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2662 /*-----------------------------------------------------------------*/
2663 /* genPlus - generates code for addition */
2664 /*-----------------------------------------------------------------*/
2665 static void genPlus (iCode *ic)
2667 int size, offset = 0;
2669 /* special cases :- */
2670 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2672 aopOp (IC_LEFT(ic),ic,FALSE);
2673 aopOp (IC_RIGHT(ic),ic,FALSE);
2674 aopOp (IC_RESULT(ic),ic,TRUE);
2676 /* if literal, literal on the right or
2677 if left requires ACC or right is already
2679 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2680 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2681 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2682 operand *t = IC_RIGHT(ic);
2683 IC_RIGHT(ic) = IC_LEFT(ic);
2687 /* if both left & right are in bit
2689 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2690 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2695 /* if left in bit space & right literal */
2696 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2697 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2698 emitcode("mov","c,%s ;%d",AOP(IC_LEFT(ic))->aopu.aop_dir,__LINE__);
2699 /* if result in bit space */
2700 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2701 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2702 emitcode("cpl","c ;%d",__LINE__);
2703 outBitC(IC_RESULT(ic));
2705 size = getDataSize(IC_RESULT(ic));
2707 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2708 emitcode("addc","a,#00 ;%d",__LINE__);
2709 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2715 /* if I can do an increment instead
2716 of add then GOOD for ME */
2717 if (genPlusIncr (ic) == TRUE)
2720 size = getDataSize(IC_RESULT(ic));
2722 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2723 /* Add a literal to something else */
2725 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2727 /* add the first byte: */
2728 emitcode("movlw","0x%x", lit & 0xff);
2729 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2736 emitcode("rlf","_known_zero,w");
2737 emitcode(" addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2741 emitcode("movlw","0x%x", lit & 0xff);
2742 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2748 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2750 /* here we are adding a bit to a char or int */
2752 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2754 emitcode("btfsc","(%s >> 3), (%s & 7)",
2755 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2756 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2757 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2760 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2761 emitcode("btfsc","(%s >> 3), (%s & 7)",
2762 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2763 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2764 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2765 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2771 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2772 emitcode("clrz","");
2774 emitcode("btfsc","(%s >> 3), (%s & 7)",
2775 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2776 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2777 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2781 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2782 emitcode("btfsc","(%s >> 3), (%s & 7)",
2783 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2784 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2785 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2786 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2791 emitcode("skpz","");
2792 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2799 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2800 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2801 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2803 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2805 if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2806 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2809 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2810 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2812 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2813 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2822 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2823 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2824 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2826 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2827 emitcode("skpnc","");
2828 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2829 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2835 //adjustArithmeticResult(ic);
2838 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2839 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2840 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2843 /*-----------------------------------------------------------------*/
2844 /* genMinusDec :- does subtraction with deccrement if possible */
2845 /*-----------------------------------------------------------------*/
2846 static bool genMinusDec (iCode *ic)
2848 unsigned int icount ;
2849 unsigned int size = getDataSize(IC_RESULT(ic));
2851 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2852 /* will try to generate an increment */
2853 /* if the right side is not a literal
2855 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2858 /* if the literal value of the right hand side
2859 is greater than 4 then it is not worth it */
2860 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2863 /* if decrement 16 bits in register */
2864 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2869 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2870 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2871 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2873 /* size is 3 or 4 */
2874 emitcode("movlw","0xff");
2875 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2877 emitcode("skpnc","");
2878 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2879 emitcode("skpnc","");
2880 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2883 emitcode("skpnc","");
2884 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2893 /* if the sizes are greater than 1 then we cannot */
2894 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2895 AOP_SIZE(IC_LEFT(ic)) > 1 )
2898 /* we can if the aops of the left & result match or
2899 if they are in registers and the registers are the
2901 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2904 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2912 /*-----------------------------------------------------------------*/
2913 /* addSign - complete with sign */
2914 /*-----------------------------------------------------------------*/
2915 static void addSign(operand *result, int offset, int sign)
2917 int size = (getDataSize(result) - offset);
2918 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2921 emitcode("rlc","a");
2922 emitcode("subb","a,acc");
2924 aopPut(AOP(result),"a",offset++);
2927 aopPut(AOP(result),zero,offset++);
2931 /*-----------------------------------------------------------------*/
2932 /* genMinusBits - generates code for subtraction of two bits */
2933 /*-----------------------------------------------------------------*/
2934 static void genMinusBits (iCode *ic)
2936 symbol *lbl = newiTempLabel(NULL);
2937 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2938 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2939 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2940 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2941 emitcode("cpl","c");
2942 emitcode("","%05d_DS_:",(lbl->key+100));
2943 outBitC(IC_RESULT(ic));
2946 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2947 emitcode("subb","a,acc");
2948 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2949 emitcode("inc","a");
2950 emitcode("","%05d_DS_:",(lbl->key+100));
2951 aopPut(AOP(IC_RESULT(ic)),"a",0);
2952 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2956 /*-----------------------------------------------------------------*/
2957 /* genMinus - generates code for subtraction */
2958 /*-----------------------------------------------------------------*/
2959 static void genMinus (iCode *ic)
2961 int size, offset = 0;
2962 unsigned long lit = 0L;
2964 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2965 aopOp (IC_LEFT(ic),ic,FALSE);
2966 aopOp (IC_RIGHT(ic),ic,FALSE);
2967 aopOp (IC_RESULT(ic),ic,TRUE);
2969 /* special cases :- */
2970 /* if both left & right are in bit space */
2971 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2972 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2977 /* if I can do an decrement instead
2978 of subtract then GOOD for ME */
2979 if (genMinusDec (ic) == TRUE)
2982 size = getDataSize(IC_RESULT(ic));
2984 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2985 /* Add a literal to something else */
2987 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2990 /* add the first byte: */
2991 emitcode("movlw","0x%x", lit & 0xff);
2992 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2999 emitcode("rlf","_known_zero,w");
3000 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3004 emitcode("movlw","0x%x", lit & 0xff);
3005 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3013 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3014 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3020 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3021 emitcode("skpnc","");
3022 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3023 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3030 // adjustArithmeticResult(ic);
3033 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3034 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3035 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3039 /*-----------------------------------------------------------------*/
3040 /* genMultbits :- multiplication of bits */
3041 /*-----------------------------------------------------------------*/
3042 static void genMultbits (operand *left,
3046 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3048 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3049 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3054 /*-----------------------------------------------------------------*/
3055 /* genMultOneByte : 8 bit multiplication & division */
3056 /*-----------------------------------------------------------------*/
3057 static void genMultOneByte (operand *left,
3061 sym_link *opetype = operandType(result);
3066 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3067 /* (if two literals, the value is computed before) */
3068 /* if one literal, literal on the right */
3069 if (AOP_TYPE(left) == AOP_LIT){
3075 size = AOP_SIZE(result);
3076 /* signed or unsigned */
3077 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3078 l = aopGet(AOP(left),0,FALSE,FALSE);
3080 emitcode("mul","ab");
3081 /* if result size = 1, mul signed = mul unsigned */
3082 aopPut(AOP(result),"a",0);
3084 if (SPEC_USIGN(opetype)){
3085 aopPut(AOP(result),"b",1);
3087 /* for filling the MSBs */
3088 emitcode("clr","a");
3091 emitcode("mov","a,b");
3093 /* adjust the MSB if left or right neg */
3095 /* if one literal */
3096 if (AOP_TYPE(right) == AOP_LIT){
3097 /* AND literal negative */
3098 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3099 /* adjust MSB (c==0 after mul) */
3100 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3104 lbl = newiTempLabel(NULL);
3105 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3106 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3107 emitcode("","%05d_DS_:",(lbl->key+100));
3108 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3109 lbl = newiTempLabel(NULL);
3110 emitcode("jc","%05d_DS_",(lbl->key+100));
3111 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3112 emitcode("","%05d_DS_:",(lbl->key+100));
3115 lbl = newiTempLabel(NULL);
3116 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3117 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3118 emitcode("","%05d_DS_:",(lbl->key+100));
3119 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3120 lbl = newiTempLabel(NULL);
3121 emitcode("jc","%05d_DS_",(lbl->key+100));
3122 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3123 emitcode("","%05d_DS_:",(lbl->key+100));
3125 aopPut(AOP(result),"a",1);
3128 emitcode("rlc","a");
3129 emitcode("subb","a,acc");
3136 aopPut(AOP(result),"a",offset++);
3140 /*-----------------------------------------------------------------*/
3141 /* genMult - generates code for multiplication */
3142 /*-----------------------------------------------------------------*/
3143 static void genMult (iCode *ic)
3145 operand *left = IC_LEFT(ic);
3146 operand *right = IC_RIGHT(ic);
3147 operand *result= IC_RESULT(ic);
3149 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3150 /* assign the amsops */
3151 aopOp (left,ic,FALSE);
3152 aopOp (right,ic,FALSE);
3153 aopOp (result,ic,TRUE);
3155 /* special cases first */
3157 if (AOP_TYPE(left) == AOP_CRY &&
3158 AOP_TYPE(right)== AOP_CRY) {
3159 genMultbits(left,right,result);
3163 /* if both are of size == 1 */
3164 if (AOP_SIZE(left) == 1 &&
3165 AOP_SIZE(right) == 1 ) {
3166 genMultOneByte(left,right,result);
3170 /* should have been converted to function call */
3174 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3175 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3176 freeAsmop(result,NULL,ic,TRUE);
3179 /*-----------------------------------------------------------------*/
3180 /* genDivbits :- division of bits */
3181 /*-----------------------------------------------------------------*/
3182 static void genDivbits (operand *left,
3189 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3190 /* the result must be bit */
3191 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3192 l = aopGet(AOP(left),0,FALSE,FALSE);
3196 emitcode("div","ab");
3197 emitcode("rrc","a");
3198 aopPut(AOP(result),"c",0);
3201 /*-----------------------------------------------------------------*/
3202 /* genDivOneByte : 8 bit division */
3203 /*-----------------------------------------------------------------*/
3204 static void genDivOneByte (operand *left,
3208 sym_link *opetype = operandType(result);
3213 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3214 size = AOP_SIZE(result) - 1;
3216 /* signed or unsigned */
3217 if (SPEC_USIGN(opetype)) {
3218 /* unsigned is easy */
3219 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3220 l = aopGet(AOP(left),0,FALSE,FALSE);
3222 emitcode("div","ab");
3223 aopPut(AOP(result),"a",0);
3225 aopPut(AOP(result),zero,offset++);
3229 /* signed is a little bit more difficult */
3231 /* save the signs of the operands */
3232 l = aopGet(AOP(left),0,FALSE,FALSE);
3234 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3235 emitcode("push","acc"); /* save it on the stack */
3237 /* now sign adjust for both left & right */
3238 l = aopGet(AOP(right),0,FALSE,FALSE);
3240 lbl = newiTempLabel(NULL);
3241 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3242 emitcode("cpl","a");
3243 emitcode("inc","a");
3244 emitcode("","%05d_DS_:",(lbl->key+100));
3245 emitcode("mov","b,a");
3247 /* sign adjust left side */
3248 l = aopGet(AOP(left),0,FALSE,FALSE);
3251 lbl = newiTempLabel(NULL);
3252 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3253 emitcode("cpl","a");
3254 emitcode("inc","a");
3255 emitcode("","%05d_DS_:",(lbl->key+100));
3257 /* now the division */
3258 emitcode("div","ab");
3259 /* we are interested in the lower order
3261 emitcode("mov","b,a");
3262 lbl = newiTempLabel(NULL);
3263 emitcode("pop","acc");
3264 /* if there was an over flow we don't
3265 adjust the sign of the result */
3266 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3267 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3269 emitcode("clr","a");
3270 emitcode("subb","a,b");
3271 emitcode("mov","b,a");
3272 emitcode("","%05d_DS_:",(lbl->key+100));
3274 /* now we are done */
3275 aopPut(AOP(result),"b",0);
3277 emitcode("mov","c,b.7");
3278 emitcode("subb","a,acc");
3281 aopPut(AOP(result),"a",offset++);
3285 /*-----------------------------------------------------------------*/
3286 /* genDiv - generates code for division */
3287 /*-----------------------------------------------------------------*/
3288 static void genDiv (iCode *ic)
3290 operand *left = IC_LEFT(ic);
3291 operand *right = IC_RIGHT(ic);
3292 operand *result= IC_RESULT(ic);
3294 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3295 /* assign the amsops */
3296 aopOp (left,ic,FALSE);
3297 aopOp (right,ic,FALSE);
3298 aopOp (result,ic,TRUE);
3300 /* special cases first */
3302 if (AOP_TYPE(left) == AOP_CRY &&
3303 AOP_TYPE(right)== AOP_CRY) {
3304 genDivbits(left,right,result);
3308 /* if both are of size == 1 */
3309 if (AOP_SIZE(left) == 1 &&
3310 AOP_SIZE(right) == 1 ) {
3311 genDivOneByte(left,right,result);
3315 /* should have been converted to function call */
3318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3320 freeAsmop(result,NULL,ic,TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genModbits :- modulus of bits */
3325 /*-----------------------------------------------------------------*/
3326 static void genModbits (operand *left,
3333 /* the result must be bit */
3334 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3335 l = aopGet(AOP(left),0,FALSE,FALSE);
3339 emitcode("div","ab");
3340 emitcode("mov","a,b");
3341 emitcode("rrc","a");
3342 aopPut(AOP(result),"c",0);
3345 /*-----------------------------------------------------------------*/
3346 /* genModOneByte : 8 bit modulus */
3347 /*-----------------------------------------------------------------*/
3348 static void genModOneByte (operand *left,
3352 sym_link *opetype = operandType(result);
3356 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3357 /* signed or unsigned */
3358 if (SPEC_USIGN(opetype)) {
3359 /* unsigned is easy */
3360 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3361 l = aopGet(AOP(left),0,FALSE,FALSE);
3363 emitcode("div","ab");
3364 aopPut(AOP(result),"b",0);
3368 /* signed is a little bit more difficult */
3370 /* save the signs of the operands */
3371 l = aopGet(AOP(left),0,FALSE,FALSE);
3374 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3375 emitcode("push","acc"); /* save it on the stack */
3377 /* now sign adjust for both left & right */
3378 l = aopGet(AOP(right),0,FALSE,FALSE);
3381 lbl = newiTempLabel(NULL);
3382 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3383 emitcode("cpl","a");
3384 emitcode("inc","a");
3385 emitcode("","%05d_DS_:",(lbl->key+100));
3386 emitcode("mov","b,a");
3388 /* sign adjust left side */
3389 l = aopGet(AOP(left),0,FALSE,FALSE);
3392 lbl = newiTempLabel(NULL);
3393 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3394 emitcode("cpl","a");
3395 emitcode("inc","a");
3396 emitcode("","%05d_DS_:",(lbl->key+100));
3398 /* now the multiplication */
3399 emitcode("div","ab");
3400 /* we are interested in the lower order
3402 lbl = newiTempLabel(NULL);
3403 emitcode("pop","acc");
3404 /* if there was an over flow we don't
3405 adjust the sign of the result */
3406 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3407 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3409 emitcode("clr","a");
3410 emitcode("subb","a,b");
3411 emitcode("mov","b,a");
3412 emitcode("","%05d_DS_:",(lbl->key+100));
3414 /* now we are done */
3415 aopPut(AOP(result),"b",0);
3419 /*-----------------------------------------------------------------*/
3420 /* genMod - generates code for division */
3421 /*-----------------------------------------------------------------*/
3422 static void genMod (iCode *ic)
3424 operand *left = IC_LEFT(ic);
3425 operand *right = IC_RIGHT(ic);
3426 operand *result= IC_RESULT(ic);
3428 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3429 /* assign the amsops */
3430 aopOp (left,ic,FALSE);
3431 aopOp (right,ic,FALSE);
3432 aopOp (result,ic,TRUE);
3434 /* special cases first */
3436 if (AOP_TYPE(left) == AOP_CRY &&
3437 AOP_TYPE(right)== AOP_CRY) {
3438 genModbits(left,right,result);
3442 /* if both are of size == 1 */
3443 if (AOP_SIZE(left) == 1 &&
3444 AOP_SIZE(right) == 1 ) {
3445 genModOneByte(left,right,result);
3449 /* should have been converted to function call */
3453 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3454 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3455 freeAsmop(result,NULL,ic,TRUE);
3458 /*-----------------------------------------------------------------*/
3459 /* genIfxJump :- will create a jump depending on the ifx */
3460 /*-----------------------------------------------------------------*/
3461 static void genIfxJump (iCode *ic, char *jval)
3464 symbol *tlbl = newiTempLabel(NULL);
3467 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3468 /* if true label then we jump if condition
3470 if ( IC_TRUE(ic) ) {
3472 if(strcmp(jval,"a") == 0)
3473 emitcode("skpz","");
3474 else if (strcmp(jval,"c") == 0)
3475 emitcode("skpc","");
3477 emitcode("skpnc","");
3479 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3483 /* false label is present */
3484 if(strcmp(jval,"a") == 0)
3485 emitcode("skpnz","");
3486 else if (strcmp(jval,"c") == 0)
3487 emitcode("skpnc","");
3489 emitcode("skpc","");
3491 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3497 /* mark the icode as generated */
3501 /*-----------------------------------------------------------------*/
3503 /*-----------------------------------------------------------------*/
3504 static void genSkip(iCode *ifx,int status_bit)
3509 if ( IC_TRUE(ifx) ) {
3510 switch(status_bit) {
3512 emitcode("skpnz","");
3516 emitcode("skpnc","");
3520 emitcode("skpndc","");
3525 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3529 switch(status_bit) {
3532 emitcode("skpz","");
3536 emitcode("skpc","");
3540 emitcode("skpdc","");
3543 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3549 /*-----------------------------------------------------------------*/
3551 /*-----------------------------------------------------------------*/
3552 static void genSkipc(iCode *ifx, int condition)
3558 emitcode("skpnc","");
3560 emitcode("skpc","");
3563 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3565 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3569 /*-----------------------------------------------------------------*/
3571 /*-----------------------------------------------------------------*/
3572 static void genSkipz(iCode *ifx, int condition)
3578 emitcode("skpnz","");
3580 emitcode("skpz","");
3583 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3585 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3588 /*-----------------------------------------------------------------*/
3589 /* genCmp :- greater or less than comparison */
3590 /*-----------------------------------------------------------------*/
3591 static void genCmp (operand *left,operand *right,
3592 operand *result, iCode *ifx, int sign)
3594 int size, offset = 0 ;
3595 unsigned long lit = 0L,i = 0;
3597 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3598 /* if left & right are bit variables */
3599 if (AOP_TYPE(left) == AOP_CRY &&
3600 AOP_TYPE(right) == AOP_CRY ) {
3601 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3602 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3604 /* subtract right from left if at the
3605 end the carry flag is set then we know that
3606 left is greater than right */
3607 size = max(AOP_SIZE(left),AOP_SIZE(right));
3609 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3610 if((size == 1) && !sign &&
3611 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3612 symbol *lbl = newiTempLabel(NULL);
3613 emitcode("cjne","%s,%s,%05d_DS_",
3614 aopGet(AOP(left),offset,FALSE,FALSE),
3615 aopGet(AOP(right),offset,FALSE,FALSE),
3617 emitcode("","%05d_DS_:",lbl->key+100);
3620 if(AOP_TYPE(right) == AOP_LIT) {
3622 DEBUGemitcode(";right lit","%d",sign);
3624 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3627 i = (lit >> (size*8)) & 0xff;
3629 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3630 genSkipz(ifx,IC_TRUE(ifx) == NULL);
3632 emitcode("movlw","0x%x",i);
3633 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3634 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3641 if(AOP_TYPE(left) == AOP_LIT) {
3643 DEBUGemitcode(";left lit","%d",sign);
3645 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3649 i = (lit >> (size*8)) & 0xff;
3651 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3652 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3653 } else if( i == 1 ) {
3654 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3655 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3658 emitcode("movlw","0x%x",i);
3659 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3660 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3669 DEBUGemitcode(";sign","%d",sign);
3670 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3671 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3675 /*if (AOP_TYPE(right) == AOP_LIT){
3676 unsigned long lit = (unsigned long)
3677 floatFromVal(AOP(right)->aopu.aop_lit);
3678 emitcode("subb","a,#0x%02x",
3679 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3681 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3682 emitcode("xrl","b,#0x80");
3683 emitcode("subb","a,b");
3686 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3688 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3689 emitcode("skpc","");
3690 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3691 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3698 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3701 /* if the result is used in the next
3702 ifx conditional branch then generate
3703 code a little differently */
3705 genIfxJump (ifx,"c");
3708 /* leave the result in acc */
3713 /*-----------------------------------------------------------------*/
3714 /* genCmpGt :- greater than comparison */
3715 /*-----------------------------------------------------------------*/
3716 static void genCmpGt (iCode *ic, iCode *ifx)
3718 operand *left, *right, *result;
3719 sym_link *letype , *retype;
3722 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3724 right= IC_RIGHT(ic);
3725 result = IC_RESULT(ic);
3727 letype = getSpec(operandType(left));
3728 retype =getSpec(operandType(right));
3729 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3730 /* assign the amsops */
3731 aopOp (left,ic,FALSE);
3732 aopOp (right,ic,FALSE);
3733 aopOp (result,ic,TRUE);
3735 genCmp(right, left, result, ifx, sign);
3737 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3738 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3739 freeAsmop(result,NULL,ic,TRUE);
3742 /*-----------------------------------------------------------------*/
3743 /* genCmpLt - less than comparisons */
3744 /*-----------------------------------------------------------------*/
3745 static void genCmpLt (iCode *ic, iCode *ifx)
3747 operand *left, *right, *result;
3748 sym_link *letype , *retype;
3751 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3753 right= IC_RIGHT(ic);
3754 result = IC_RESULT(ic);
3756 letype = getSpec(operandType(left));
3757 retype =getSpec(operandType(right));
3758 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3760 /* assign the amsops */
3761 aopOp (left,ic,FALSE);
3762 aopOp (right,ic,FALSE);
3763 aopOp (result,ic,TRUE);
3765 genCmp(left, right, result, ifx, sign);
3767 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3768 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3769 freeAsmop(result,NULL,ic,TRUE);
3772 /*-----------------------------------------------------------------*/
3773 /* gencjneshort - compare and jump if not equal */
3774 /*-----------------------------------------------------------------*/
3775 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3777 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3779 unsigned long lit = 0L;
3781 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3782 /* if the left side is a literal or
3783 if the right is in a pointer register and left
3785 if ((AOP_TYPE(left) == AOP_LIT) ||
3786 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3791 if(AOP_TYPE(right) == AOP_LIT)
3792 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3794 /* if the right side is a literal then anything goes */
3795 if (AOP_TYPE(right) == AOP_LIT &&
3796 AOP_TYPE(left) != AOP_DIR ) {
3799 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3800 emitcode("xorlw","0x%x",lit & 0xff);
3802 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3804 emitcode("skpnz","");
3805 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3811 /* if the right side is in a register or in direct space or
3812 if the left is a pointer register & right is not */
3813 else if (AOP_TYPE(right) == AOP_REG ||
3814 AOP_TYPE(right) == AOP_DIR ||
3815 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3816 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3818 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3819 ( (lit & 0xff) != 0)) {
3820 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3821 emitcode("xorlw","0x%x",lit & 0xff);
3824 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3826 emitcode("skpz","");
3827 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3830 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3831 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3832 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3833 emitcode("jnz","%05d_DS_",lbl->key+100);
3835 emitcode("cjne","a,%s,%05d_DS_",
3836 aopGet(AOP(right),offset,FALSE,TRUE),
3842 /* right is a pointer reg need both a & b */
3844 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3846 emitcode("mov","b,%s",l);
3847 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3848 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
3854 /*-----------------------------------------------------------------*/
3855 /* gencjne - compare and jump if not equal */
3856 /*-----------------------------------------------------------------*/
3857 static void gencjne(operand *left, operand *right, symbol *lbl)
3859 symbol *tlbl = newiTempLabel(NULL);
3861 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3862 gencjneshort(left, right, lbl);
3864 emitcode("mov","a,%s",one);
3865 emitcode("sjmp","%05d_DS_",tlbl->key+100);
3866 emitcode("","%05d_DS_:",lbl->key+100);
3867 emitcode("clr","a");
3868 emitcode("","%05d_DS_:",tlbl->key+100);
3872 /*-----------------------------------------------------------------*/
3873 /* genCmpEq - generates code for equal to */
3874 /*-----------------------------------------------------------------*/
3875 static void genCmpEq (iCode *ic, iCode *ifx)
3877 operand *left, *right, *result;
3878 unsigned long lit = 0L;
3881 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3883 DEBUGemitcode ("; ifx is non-null","");
3885 DEBUGemitcode ("; ifx is null","");
3887 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3888 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3889 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3891 size = max(AOP_SIZE(left),AOP_SIZE(right));
3893 /* if literal, literal on the right or
3894 if the right is in a pointer register and left
3896 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3897 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3898 operand *t = IC_RIGHT(ic);
3899 IC_RIGHT(ic) = IC_LEFT(ic);
3903 if(ifx && !AOP_SIZE(result)){
3905 /* if they are both bit variables */
3906 if (AOP_TYPE(left) == AOP_CRY &&
3907 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3908 if(AOP_TYPE(right) == AOP_LIT){
3909 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3911 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3912 emitcode("cpl","c");
3913 } else if(lit == 1L) {
3914 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3916 emitcode("clr","c");
3918 /* AOP_TYPE(right) == AOP_CRY */
3920 symbol *lbl = newiTempLabel(NULL);
3921 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3922 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
3923 emitcode("cpl","c");
3924 emitcode("","%05d_DS_:",(lbl->key+100));
3926 /* if true label then we jump if condition
3928 tlbl = newiTempLabel(NULL);
3929 if ( IC_TRUE(ifx) ) {
3930 emitcode("jnc","%05d_DS_",tlbl->key+100);
3931 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
3933 emitcode("jc","%05d_DS_",tlbl->key+100);
3934 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
3936 emitcode("","%05d_DS_:",tlbl->key+100);
3939 /* They're not both bit variables. Is the right a literal? */
3940 if(AOP_TYPE(right) == AOP_LIT) {
3942 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3947 int h = (lit>>8) & 0xff;
3950 /* Check special cases for integers */
3951 switch(lit & 0xffff) {
3953 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3954 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3959 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3960 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3965 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3966 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3971 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3972 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3977 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3978 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3984 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3985 emitcode("xorlw","0x%x",l);
3986 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3989 } else if (l == 0) {
3990 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3991 emitcode("xorlw","0x%x",h);
3992 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3996 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3997 emitcode("xorlw","0x%x",l);
3998 emitcode("movlw","0x%x",h);
3999 emitcode("skpz","");
4000 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4016 switch(lit & 0xff) {
4018 if ( IC_TRUE(ifx) ) {
4019 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4020 emitcode("skpnz","");
4021 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4023 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4024 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4028 if ( IC_TRUE(ifx) ) {
4029 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4030 emitcode("skpnz","");
4031 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4033 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4034 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4038 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4040 emitcode("xorlw","0x%x",lit & 0xff);
4045 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4046 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4052 /* They're both variables that are larger than bits */
4055 tlbl = newiTempLabel(NULL);
4059 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4060 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4062 if ( IC_TRUE(ifx) ) {
4064 emitcode("skpz","");
4065 emitcode(" goto","_%05d_DS_",tlbl->key+100);
4067 emitcode("skpnz","");
4068 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4071 emitcode("skpz","");
4072 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4076 if(s>1 && IC_TRUE(ifx))
4077 emitcode("","_%05d_DS_:",tlbl->key+100);
4080 /* mark the icode as generated */
4085 /* if they are both bit variables */
4086 if (AOP_TYPE(left) == AOP_CRY &&
4087 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4088 if(AOP_TYPE(right) == AOP_LIT){
4089 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4091 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4092 emitcode("cpl","c");
4093 } else if(lit == 1L) {
4094 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4096 emitcode("clr","c");
4098 /* AOP_TYPE(right) == AOP_CRY */
4100 symbol *lbl = newiTempLabel(NULL);
4101 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4102 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4103 emitcode("cpl","c");
4104 emitcode("","%05d_DS_:",(lbl->key+100));
4107 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4112 genIfxJump (ifx,"c");
4115 /* if the result is used in an arithmetic operation
4116 then put the result in place */
4119 gencjne(left,right,newiTempLabel(NULL));
4120 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4121 aopPut(AOP(result),"a",0);
4125 genIfxJump (ifx,"a");
4128 /* if the result is used in an arithmetic operation
4129 then put the result in place */
4130 if (AOP_TYPE(result) != AOP_CRY)
4132 /* leave the result in acc */
4136 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4138 freeAsmop(result,NULL,ic,TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* ifxForOp - returns the icode containing the ifx for operand */
4143 /*-----------------------------------------------------------------*/
4144 static iCode *ifxForOp ( operand *op, iCode *ic )
4146 /* if true symbol then needs to be assigned */
4147 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4148 if (IS_TRUE_SYMOP(op))
4151 /* if this has register type condition and
4152 the next instruction is ifx with the same operand
4153 and live to of the operand is upto the ifx only then */
4155 ic->next->op == IFX &&
4156 IC_COND(ic->next)->key == op->key &&
4157 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4162 /*-----------------------------------------------------------------*/
4163 /* genAndOp - for && operation */
4164 /*-----------------------------------------------------------------*/
4165 static void genAndOp (iCode *ic)
4167 operand *left,*right, *result;
4170 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4171 /* note here that && operations that are in an
4172 if statement are taken away by backPatchLabels
4173 only those used in arthmetic operations remain */
4174 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4175 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4176 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4178 /* if both are bit variables */
4179 if (AOP_TYPE(left) == AOP_CRY &&
4180 AOP_TYPE(right) == AOP_CRY ) {
4181 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4182 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4185 tlbl = newiTempLabel(NULL);
4187 emitcode("jz","%05d_DS_",tlbl->key+100);
4189 emitcode("","%05d_DS_:",tlbl->key+100);
4193 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4194 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4195 freeAsmop(result,NULL,ic,TRUE);
4199 /*-----------------------------------------------------------------*/
4200 /* genOrOp - for || operation */
4201 /*-----------------------------------------------------------------*/
4204 modified this code, but it doesn't appear to ever get called
4207 static void genOrOp (iCode *ic)
4209 operand *left,*right, *result;
4212 /* note here that || operations that are in an
4213 if statement are taken away by backPatchLabels
4214 only those used in arthmetic operations remain */
4215 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4216 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4217 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4218 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4220 /* if both are bit variables */
4221 if (AOP_TYPE(left) == AOP_CRY &&
4222 AOP_TYPE(right) == AOP_CRY ) {
4223 emitcode("clrc","");
4224 emitcode("btfss","(%s >> 3), (%s & 7)",
4225 AOP(left)->aopu.aop_dir,
4226 AOP(left)->aopu.aop_dir);
4227 emitcode("btfsc","(%s >> 3), (%s & 7)",
4228 AOP(right)->aopu.aop_dir,
4229 AOP(right)->aopu.aop_dir);
4230 emitcode("setc","");
4233 tlbl = newiTempLabel(NULL);
4235 emitcode("skpz","");
4236 emitcode("goto","%05d_DS_",tlbl->key+100);
4238 emitcode("","%05d_DS_:",tlbl->key+100);
4243 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4244 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4245 freeAsmop(result,NULL,ic,TRUE);
4248 /*-----------------------------------------------------------------*/
4249 /* isLiteralBit - test if lit == 2^n */
4250 /*-----------------------------------------------------------------*/
4251 static int isLiteralBit(unsigned long lit)
4253 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4254 0x100L,0x200L,0x400L,0x800L,
4255 0x1000L,0x2000L,0x4000L,0x8000L,
4256 0x10000L,0x20000L,0x40000L,0x80000L,
4257 0x100000L,0x200000L,0x400000L,0x800000L,
4258 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4259 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4262 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4263 for(idx = 0; idx < 32; idx++)
4269 /*-----------------------------------------------------------------*/
4270 /* continueIfTrue - */
4271 /*-----------------------------------------------------------------*/
4272 static void continueIfTrue (iCode *ic)
4274 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4276 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4280 /*-----------------------------------------------------------------*/
4282 /*-----------------------------------------------------------------*/
4283 static void jumpIfTrue (iCode *ic)
4285 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4287 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4291 /*-----------------------------------------------------------------*/
4292 /* jmpTrueOrFalse - */
4293 /*-----------------------------------------------------------------*/
4294 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4296 // ugly but optimized by peephole
4297 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4299 symbol *nlbl = newiTempLabel(NULL);
4300 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4301 emitcode("","%05d_DS_:",tlbl->key+100);
4302 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4303 emitcode("","%05d_DS_:",nlbl->key+100);
4306 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4307 emitcode("","%05d_DS_:",tlbl->key+100);
4312 /*-----------------------------------------------------------------*/
4313 /* genAnd - code for and */
4314 /*-----------------------------------------------------------------*/
4315 static void genAnd (iCode *ic, iCode *ifx)
4317 operand *left, *right, *result;
4319 unsigned long lit = 0L;
4323 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4324 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4325 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4326 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4329 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4331 AOP_TYPE(left), AOP_TYPE(right));
4332 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4334 AOP_SIZE(left), AOP_SIZE(right));
4337 /* if left is a literal & right is not then exchange them */
4338 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4339 AOP_NEEDSACC(left)) {
4340 operand *tmp = right ;
4345 /* if result = right then exchange them */
4346 if(sameRegs(AOP(result),AOP(right))){
4347 operand *tmp = right ;
4352 /* if right is bit then exchange them */
4353 if (AOP_TYPE(right) == AOP_CRY &&
4354 AOP_TYPE(left) != AOP_CRY){
4355 operand *tmp = right ;
4359 if(AOP_TYPE(right) == AOP_LIT)
4360 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4362 size = AOP_SIZE(result);
4365 // result = bit & yy;
4366 if (AOP_TYPE(left) == AOP_CRY){
4367 // c = bit & literal;
4368 if(AOP_TYPE(right) == AOP_LIT){
4370 if(size && sameRegs(AOP(result),AOP(left)))
4373 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4376 if(size && (AOP_TYPE(result) == AOP_CRY)){
4377 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4380 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4384 emitcode("clr","c");
4387 if (AOP_TYPE(right) == AOP_CRY){
4389 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4390 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4393 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4395 emitcode("rrc","a");
4396 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4404 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4405 genIfxJump(ifx, "c");
4409 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4410 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4411 if((AOP_TYPE(right) == AOP_LIT) &&
4412 (AOP_TYPE(result) == AOP_CRY) &&
4413 (AOP_TYPE(left) != AOP_CRY)){
4414 int posbit = isLiteralBit(lit);
4418 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4421 emitcode("mov","c,acc.%d",posbit&0x07);
4425 sprintf(buffer,"acc.%d",posbit&0x07);
4426 genIfxJump(ifx, buffer);
4431 symbol *tlbl = newiTempLabel(NULL);
4432 int sizel = AOP_SIZE(left);
4434 emitcode("setb","c");
4436 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4437 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4439 if((posbit = isLiteralBit(bytelit)) != 0)
4440 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4442 if(bytelit != 0x0FFL)
4443 emitcode("anl","a,%s",
4444 aopGet(AOP(right),offset,FALSE,TRUE));
4445 emitcode("jnz","%05d_DS_",tlbl->key+100);
4450 // bit = left & literal
4452 emitcode("clr","c");
4453 emitcode("","%05d_DS_:",tlbl->key+100);
4455 // if(left & literal)
4458 jmpTrueOrFalse(ifx, tlbl);
4466 /* if left is same as result */
4467 if(sameRegs(AOP(result),AOP(left))){
4468 for(;size--; offset++,lit>>=8) {
4469 if(AOP_TYPE(right) == AOP_LIT){
4470 switch(lit & 0xff) {
4472 /* and'ing with 0 has clears the result */
4473 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4476 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4481 int p = my_powof2( (~lit) & 0xff );
4483 /* only one bit is set in the literal, so use a bcf instruction */
4484 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4486 emitcode("movlw","0x%x", (lit & 0xff));
4487 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4492 if (AOP_TYPE(left) == AOP_ACC)
4493 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4495 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4496 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4503 // left & result in different registers
4504 if(AOP_TYPE(result) == AOP_CRY){
4506 // if(size), result in bit
4507 // if(!size && ifx), conditional oper: if(left & right)
4508 symbol *tlbl = newiTempLabel(NULL);
4509 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4511 emitcode("setb","c");
4513 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4514 emitcode("anl","a,%s",
4515 aopGet(AOP(left),offset,FALSE,FALSE));
4516 emitcode("jnz","%05d_DS_",tlbl->key+100);
4521 emitcode("","%05d_DS_:",tlbl->key+100);
4524 jmpTrueOrFalse(ifx, tlbl);
4526 for(;(size--);offset++) {
4528 // result = left & right
4529 if(AOP_TYPE(right) == AOP_LIT){
4530 int t = (lit >> (offset*8)) & 0x0FFL;
4533 emitcode("clrf","%s",
4534 aopGet(AOP(result),offset,FALSE,FALSE));
4537 emitcode("movf","%s,w",
4538 aopGet(AOP(left),offset,FALSE,FALSE));
4539 emitcode("movwf","%s",
4540 aopGet(AOP(result),offset,FALSE,FALSE));
4543 emitcode("movlw","0x%x",t);
4544 emitcode("andwf","%s,w",
4545 aopGet(AOP(left),offset,FALSE,FALSE));
4546 emitcode("movwf","%s",
4547 aopGet(AOP(result),offset,FALSE,FALSE));
4553 if (AOP_TYPE(left) == AOP_ACC)
4554 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4556 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4557 emitcode("andwf","%s,w",
4558 aopGet(AOP(left),offset,FALSE,FALSE));
4560 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4566 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4567 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568 freeAsmop(result,NULL,ic,TRUE);
4571 /*-----------------------------------------------------------------*/
4572 /* genOr - code for or */
4573 /*-----------------------------------------------------------------*/
4574 static void genOr (iCode *ic, iCode *ifx)
4576 operand *left, *right, *result;
4578 unsigned long lit = 0L;
4580 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4582 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4583 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4584 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4587 /* if left is a literal & right is not then exchange them */
4588 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4589 AOP_NEEDSACC(left)) {
4590 operand *tmp = right ;
4595 /* if result = right then exchange them */
4596 if(sameRegs(AOP(result),AOP(right))){
4597 operand *tmp = right ;
4602 /* if right is bit then exchange them */
4603 if (AOP_TYPE(right) == AOP_CRY &&
4604 AOP_TYPE(left) != AOP_CRY){
4605 operand *tmp = right ;
4610 if(AOP_TYPE(right) == AOP_LIT)
4611 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4613 size = AOP_SIZE(result);
4617 if (AOP_TYPE(left) == AOP_CRY){
4618 if(AOP_TYPE(right) == AOP_LIT){
4619 // c = bit & literal;
4621 // lit != 0 => result = 1
4622 if(AOP_TYPE(result) == AOP_CRY){
4624 emitcode("bsf","(%s >> 3), (%s & 7)",
4625 AOP(result)->aopu.aop_dir,
4626 AOP(result)->aopu.aop_dir);
4628 continueIfTrue(ifx);
4631 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4633 // lit == 0 => result = left
4634 if(size && sameRegs(AOP(result),AOP(left)))
4636 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4639 if (AOP_TYPE(right) == AOP_CRY){
4640 if(sameRegs(AOP(result),AOP(left))){
4642 emitcode("bcf","(%s >> 3), (%s & 7)",
4643 AOP(result)->aopu.aop_dir,
4644 AOP(result)->aopu.aop_dir);
4645 emitcode("btfsc","(%s >> 3), (%s & 7)",
4646 AOP(right)->aopu.aop_dir,
4647 AOP(right)->aopu.aop_dir);
4648 emitcode("bsf","(%s >> 3), (%s & 7)",
4649 AOP(result)->aopu.aop_dir,
4650 AOP(result)->aopu.aop_dir);
4653 emitcode("bcf","(%s >> 3), (%s & 7)",
4654 AOP(result)->aopu.aop_dir,
4655 AOP(result)->aopu.aop_dir);
4656 emitcode("btfss","(%s >> 3), (%s & 7)",
4657 AOP(right)->aopu.aop_dir,
4658 AOP(right)->aopu.aop_dir);
4659 emitcode("btfsc","(%s >> 3), (%s & 7)",
4660 AOP(left)->aopu.aop_dir,
4661 AOP(left)->aopu.aop_dir);
4662 emitcode("bsf","(%s >> 3), (%s & 7)",
4663 AOP(result)->aopu.aop_dir,
4664 AOP(result)->aopu.aop_dir);
4669 symbol *tlbl = newiTempLabel(NULL);
4670 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4671 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4672 emitcode(";XXX setb","c");
4673 emitcode(";XXX jb","%s,%05d_DS_",
4674 AOP(left)->aopu.aop_dir,tlbl->key+100);
4676 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4677 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4678 jmpTrueOrFalse(ifx, tlbl);
4682 emitcode("","%05d_DS_:",tlbl->key+100);
4691 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4692 genIfxJump(ifx, "c");
4696 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4697 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4698 if((AOP_TYPE(right) == AOP_LIT) &&
4699 (AOP_TYPE(result) == AOP_CRY) &&
4700 (AOP_TYPE(left) != AOP_CRY)){
4702 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4705 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4707 continueIfTrue(ifx);
4710 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4711 // lit = 0, result = boolean(left)
4713 emitcode(";XXX setb","c");
4716 symbol *tlbl = newiTempLabel(NULL);
4717 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4719 emitcode("","%05d_DS_:",tlbl->key+100);
4721 genIfxJump (ifx,"a");
4729 /* if left is same as result */
4730 if(sameRegs(AOP(result),AOP(left))){
4731 for(;size--; offset++,lit>>=8) {
4732 if(AOP_TYPE(right) == AOP_LIT){
4733 if((lit & 0xff) == 0)
4734 /* or'ing with 0 has no effect */
4737 int p = my_powof2(lit & 0xff);
4739 /* only one bit is set in the literal, so use a bsf instruction */
4740 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4742 emitcode("movlw","0x%x", (lit & 0xff));
4743 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4748 if (AOP_TYPE(left) == AOP_ACC)
4749 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4751 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4752 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4758 // left & result in different registers
4759 if(AOP_TYPE(result) == AOP_CRY){
4761 // if(size), result in bit
4762 // if(!size && ifx), conditional oper: if(left | right)
4763 symbol *tlbl = newiTempLabel(NULL);
4764 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4765 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4768 emitcode(";XXX setb","c");
4770 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4771 emitcode(";XXX orl","a,%s",
4772 aopGet(AOP(left),offset,FALSE,FALSE));
4773 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4778 emitcode("","%05d_DS_:",tlbl->key+100);
4781 jmpTrueOrFalse(ifx, tlbl);
4782 } else for(;(size--);offset++){
4784 // result = left & right
4785 if(AOP_TYPE(right) == AOP_LIT){
4786 int t = (lit >> (offset*8)) & 0x0FFL;
4789 emitcode("movf","%s,w",
4790 aopGet(AOP(left),offset,FALSE,FALSE));
4791 emitcode("movwf","%s",
4792 aopGet(AOP(result),offset,FALSE,FALSE));
4795 emitcode("movlw","0x%x",t);
4796 emitcode("iorwf","%s,w",
4797 aopGet(AOP(left),offset,FALSE,FALSE));
4798 emitcode("movwf","%s",
4799 aopGet(AOP(result),offset,FALSE,FALSE));
4805 // faster than result <- left, anl result,right
4806 // and better if result is SFR
4807 if (AOP_TYPE(left) == AOP_ACC)
4808 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4810 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4811 emitcode("iorwf","%s,w",
4812 aopGet(AOP(left),offset,FALSE,FALSE));
4814 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4819 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4820 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4821 freeAsmop(result,NULL,ic,TRUE);
4824 /*-----------------------------------------------------------------*/
4825 /* genXor - code for xclusive or */
4826 /*-----------------------------------------------------------------*/
4827 static void genXor (iCode *ic, iCode *ifx)
4829 operand *left, *right, *result;
4831 unsigned long lit = 0L;
4833 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4835 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4836 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4837 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4839 /* if left is a literal & right is not ||
4840 if left needs acc & right does not */
4841 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4842 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4843 operand *tmp = right ;
4848 /* if result = right then exchange them */
4849 if(sameRegs(AOP(result),AOP(right))){
4850 operand *tmp = right ;
4855 /* if right is bit then exchange them */
4856 if (AOP_TYPE(right) == AOP_CRY &&
4857 AOP_TYPE(left) != AOP_CRY){
4858 operand *tmp = right ;
4862 if(AOP_TYPE(right) == AOP_LIT)
4863 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4865 size = AOP_SIZE(result);
4869 if (AOP_TYPE(left) == AOP_CRY){
4870 if(AOP_TYPE(right) == AOP_LIT){
4871 // c = bit & literal;
4873 // lit>>1 != 0 => result = 1
4874 if(AOP_TYPE(result) == AOP_CRY){
4876 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4878 continueIfTrue(ifx);
4881 emitcode("setb","c");
4885 // lit == 0, result = left
4886 if(size && sameRegs(AOP(result),AOP(left)))
4888 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4890 // lit == 1, result = not(left)
4891 if(size && sameRegs(AOP(result),AOP(left))){
4892 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4895 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4896 emitcode("cpl","c");
4903 symbol *tlbl = newiTempLabel(NULL);
4904 if (AOP_TYPE(right) == AOP_CRY){
4906 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4909 int sizer = AOP_SIZE(right);
4911 // if val>>1 != 0, result = 1
4912 emitcode("setb","c");
4914 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4916 // test the msb of the lsb
4917 emitcode("anl","a,#0xfe");
4918 emitcode("jnz","%05d_DS_",tlbl->key+100);
4922 emitcode("rrc","a");
4924 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4925 emitcode("cpl","c");
4926 emitcode("","%05d_DS_:",(tlbl->key+100));
4933 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4934 genIfxJump(ifx, "c");
4938 if(sameRegs(AOP(result),AOP(left))){
4939 /* if left is same as result */
4940 for(;size--; offset++) {
4941 if(AOP_TYPE(right) == AOP_LIT){
4942 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4945 if (IS_AOP_PREG(left)) {
4946 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4947 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4948 aopPut(AOP(result),"a",offset);
4950 emitcode("xrl","%s,%s",
4951 aopGet(AOP(left),offset,FALSE,TRUE),
4952 aopGet(AOP(right),offset,FALSE,FALSE));
4954 if (AOP_TYPE(left) == AOP_ACC)
4955 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4957 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4958 if (IS_AOP_PREG(left)) {
4959 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4960 aopPut(AOP(result),"a",offset);
4962 emitcode("xrl","%s,a",
4963 aopGet(AOP(left),offset,FALSE,TRUE));
4968 // left & result in different registers
4969 if(AOP_TYPE(result) == AOP_CRY){
4971 // if(size), result in bit
4972 // if(!size && ifx), conditional oper: if(left ^ right)
4973 symbol *tlbl = newiTempLabel(NULL);
4974 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4976 emitcode("setb","c");
4978 if((AOP_TYPE(right) == AOP_LIT) &&
4979 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4980 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4982 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4983 emitcode("xrl","a,%s",
4984 aopGet(AOP(left),offset,FALSE,FALSE));
4986 emitcode("jnz","%05d_DS_",tlbl->key+100);
4991 emitcode("","%05d_DS_:",tlbl->key+100);
4994 jmpTrueOrFalse(ifx, tlbl);
4995 } else for(;(size--);offset++){
4997 // result = left & right
4998 if(AOP_TYPE(right) == AOP_LIT){
4999 int t = (lit >> (offset*8)) & 0x0FFL;
5002 emitcode("movf","%s,w",
5003 aopGet(AOP(left),offset,FALSE,FALSE));
5004 emitcode("movwf","%s",
5005 aopGet(AOP(result),offset,FALSE,FALSE));
5008 emitcode("comf","%s,w",
5009 aopGet(AOP(left),offset,FALSE,FALSE));
5010 emitcode("movwf","%s",
5011 aopGet(AOP(result),offset,FALSE,FALSE));
5014 emitcode("movlw","0x%x",t);
5015 emitcode("xorwf","%s,w",
5016 aopGet(AOP(left),offset,FALSE,FALSE));
5017 emitcode("movwf","%s",
5018 aopGet(AOP(result),offset,FALSE,FALSE));
5024 // faster than result <- left, anl result,right
5025 // and better if result is SFR
5026 if (AOP_TYPE(left) == AOP_ACC)
5027 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5029 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5030 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5032 if ( AOP_TYPE(result) != AOP_ACC)
5033 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5038 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5039 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5040 freeAsmop(result,NULL,ic,TRUE);
5043 /*-----------------------------------------------------------------*/
5044 /* genInline - write the inline code out */
5045 /*-----------------------------------------------------------------*/
5046 static void genInline (iCode *ic)
5048 char buffer[MAX_INLINEASM];
5052 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5054 _G.inLine += (!options.asmpeep);
5055 strcpy(buffer,IC_INLINE(ic));
5057 /* emit each line as a code */
5076 /* emitcode("",buffer); */
5077 _G.inLine -= (!options.asmpeep);
5080 /*-----------------------------------------------------------------*/
5081 /* genRRC - rotate right with carry */
5082 /*-----------------------------------------------------------------*/
5083 static void genRRC (iCode *ic)
5085 operand *left , *result ;
5086 int size, offset = 0;
5089 /* rotate right with carry */
5091 result=IC_RESULT(ic);
5092 aopOp (left,ic,FALSE);
5093 aopOp (result,ic,FALSE);
5095 /* move it to the result */
5096 size = AOP_SIZE(result);
5100 l = aopGet(AOP(left),offset,FALSE,FALSE);
5102 emitcode("rrc","a");
5103 if (AOP_SIZE(result) > 1)
5104 aopPut(AOP(result),"a",offset--);
5106 /* now we need to put the carry into the
5107 highest order byte of the result */
5108 if (AOP_SIZE(result) > 1) {
5109 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5112 emitcode("mov","acc.7,c");
5113 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5114 freeAsmop(left,NULL,ic,TRUE);
5115 freeAsmop(result,NULL,ic,TRUE);
5118 /*-----------------------------------------------------------------*/
5119 /* genRLC - generate code for rotate left with carry */
5120 /*-----------------------------------------------------------------*/
5121 static void genRLC (iCode *ic)
5123 operand *left , *result ;
5124 int size, offset = 0;
5127 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5128 /* rotate right with carry */
5130 result=IC_RESULT(ic);
5131 aopOp (left,ic,FALSE);
5132 aopOp (result,ic,FALSE);
5134 /* move it to the result */
5135 size = AOP_SIZE(result);
5138 l = aopGet(AOP(left),offset,FALSE,FALSE);
5140 emitcode("add","a,acc");
5141 if (AOP_SIZE(result) > 1)
5142 aopPut(AOP(result),"a",offset++);
5144 l = aopGet(AOP(left),offset,FALSE,FALSE);
5146 emitcode("rlc","a");
5147 if (AOP_SIZE(result) > 1)
5148 aopPut(AOP(result),"a",offset++);
5151 /* now we need to put the carry into the
5152 highest order byte of the result */
5153 if (AOP_SIZE(result) > 1) {
5154 l = aopGet(AOP(result),0,FALSE,FALSE);
5157 emitcode("mov","acc.0,c");
5158 aopPut(AOP(result),"a",0);
5159 freeAsmop(left,NULL,ic,TRUE);
5160 freeAsmop(result,NULL,ic,TRUE);
5163 /*-----------------------------------------------------------------*/
5164 /* genGetHbit - generates code get highest order bit */
5165 /*-----------------------------------------------------------------*/
5166 static void genGetHbit (iCode *ic)
5168 operand *left, *result;
5170 result=IC_RESULT(ic);
5171 aopOp (left,ic,FALSE);
5172 aopOp (result,ic,FALSE);
5174 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5175 /* get the highest order byte into a */
5176 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5177 if(AOP_TYPE(result) == AOP_CRY){
5178 emitcode("rlc","a");
5183 emitcode("anl","a,#0x01");
5188 freeAsmop(left,NULL,ic,TRUE);
5189 freeAsmop(result,NULL,ic,TRUE);
5192 /*-----------------------------------------------------------------*/
5193 /* AccRol - rotate left accumulator by known count */
5194 /*-----------------------------------------------------------------*/
5195 static void AccRol (int shCount)
5197 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5198 shCount &= 0x0007; // shCount : 0..7
5210 emitcode("swap","a");
5214 emitcode("swap","a");
5217 emitcode("swap","a");
5230 /*-----------------------------------------------------------------*/
5231 /* AccLsh - left shift accumulator by known count */
5232 /*-----------------------------------------------------------------*/
5233 static void AccLsh (int shCount)
5235 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5238 emitcode("add","a,acc");
5241 emitcode("add","a,acc");
5242 emitcode("add","a,acc");
5244 /* rotate left accumulator */
5246 /* and kill the lower order bits */
5247 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5252 /*-----------------------------------------------------------------*/
5253 /* AccRsh - right shift accumulator by known count */
5254 /*-----------------------------------------------------------------*/
5255 static void AccRsh (int shCount)
5257 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5261 emitcode("rrc","a");
5263 /* rotate right accumulator */
5264 AccRol(8 - shCount);
5265 /* and kill the higher order bits */
5266 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5271 /*-----------------------------------------------------------------*/
5272 /* AccSRsh - signed right shift accumulator by known count */
5273 /*-----------------------------------------------------------------*/
5274 static void AccSRsh (int shCount)
5277 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5280 emitcode("mov","c,acc.7");
5281 emitcode("rrc","a");
5282 } else if(shCount == 2){
5283 emitcode("mov","c,acc.7");
5284 emitcode("rrc","a");
5285 emitcode("mov","c,acc.7");
5286 emitcode("rrc","a");
5288 tlbl = newiTempLabel(NULL);
5289 /* rotate right accumulator */
5290 AccRol(8 - shCount);
5291 /* and kill the higher order bits */
5292 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5293 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5294 emitcode("orl","a,#0x%02x",
5295 (unsigned char)~SRMask[shCount]);
5296 emitcode("","%05d_DS_:",tlbl->key+100);
5301 /*-----------------------------------------------------------------*/
5302 /* shiftR1Left2Result - shift right one byte from left to result */
5303 /*-----------------------------------------------------------------*/
5304 static void shiftR1Left2Result (operand *left, int offl,
5305 operand *result, int offr,
5306 int shCount, int sign)
5308 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5309 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5310 /* shift right accumulator */
5315 aopPut(AOP(result),"a",offr);
5318 /*-----------------------------------------------------------------*/
5319 /* shiftL1Left2Result - shift left one byte from left to result */
5320 /*-----------------------------------------------------------------*/
5321 static void shiftL1Left2Result (operand *left, int offl,
5322 operand *result, int offr, int shCount)
5325 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5326 l = aopGet(AOP(left),offl,FALSE,FALSE);
5328 /* shift left accumulator */
5330 aopPut(AOP(result),"a",offr);
5333 /*-----------------------------------------------------------------*/
5334 /* movLeft2Result - move byte from left to result */
5335 /*-----------------------------------------------------------------*/
5336 static void movLeft2Result (operand *left, int offl,
5337 operand *result, int offr, int sign)
5340 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5341 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5342 l = aopGet(AOP(left),offl,FALSE,FALSE);
5344 if (*l == '@' && (IS_AOP_PREG(result))) {
5345 emitcode("mov","a,%s",l);
5346 aopPut(AOP(result),"a",offr);
5349 aopPut(AOP(result),l,offr);
5351 /* MSB sign in acc.7 ! */
5352 if(getDataSize(left) == offl+1){
5353 emitcode("mov","a,%s",l);
5354 aopPut(AOP(result),"a",offr);
5361 /*-----------------------------------------------------------------*/
5362 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5363 /*-----------------------------------------------------------------*/
5364 static void AccAXRrl1 (char *x)
5366 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5367 emitcode("rrc","a");
5368 emitcode("xch","a,%s", x);
5369 emitcode("rrc","a");
5370 emitcode("xch","a,%s", x);
5373 /*-----------------------------------------------------------------*/
5374 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5375 /*-----------------------------------------------------------------*/
5376 static void AccAXLrl1 (char *x)
5378 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5379 emitcode("xch","a,%s",x);
5380 emitcode("rlc","a");
5381 emitcode("xch","a,%s",x);
5382 emitcode("rlc","a");
5385 /*-----------------------------------------------------------------*/
5386 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5387 /*-----------------------------------------------------------------*/
5388 static void AccAXLsh1 (char *x)
5390 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5391 emitcode("xch","a,%s",x);
5392 emitcode("add","a,acc");
5393 emitcode("xch","a,%s",x);
5394 emitcode("rlc","a");
5397 /*-----------------------------------------------------------------*/
5398 /* AccAXLsh - left shift a:x by known count (0..7) */
5399 /*-----------------------------------------------------------------*/
5400 static void AccAXLsh (char *x, int shCount)
5402 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5415 case 5 : // AAAAABBB:CCCCCDDD
5416 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5417 emitcode("anl","a,#0x%02x",
5418 SLMask[shCount]); // BBB00000:CCCCCDDD
5419 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5420 AccRol(shCount); // DDDCCCCC:BBB00000
5421 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5422 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5423 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5424 emitcode("anl","a,#0x%02x",
5425 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5426 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5427 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5429 case 6 : // AAAAAABB:CCCCCCDD
5430 emitcode("anl","a,#0x%02x",
5431 SRMask[shCount]); // 000000BB:CCCCCCDD
5432 emitcode("mov","c,acc.0"); // c = B
5433 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5434 AccAXRrl1(x); // BCCCCCCD:D000000B
5435 AccAXRrl1(x); // BBCCCCCC:DD000000
5437 case 7 : // a:x <<= 7
5438 emitcode("anl","a,#0x%02x",
5439 SRMask[shCount]); // 0000000B:CCCCCCCD
5440 emitcode("mov","c,acc.0"); // c = B
5441 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5442 AccAXRrl1(x); // BCCCCCCC:D0000000
5449 /*-----------------------------------------------------------------*/
5450 /* AccAXRsh - right shift a:x known count (0..7) */
5451 /*-----------------------------------------------------------------*/
5452 static void AccAXRsh (char *x, int shCount)
5454 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5460 AccAXRrl1(x); // 0->a:x
5464 AccAXRrl1(x); // 0->a:x
5466 AccAXRrl1(x); // 0->a:x
5470 case 5 : // AAAAABBB:CCCCCDDD = a:x
5471 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5472 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5473 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5474 emitcode("anl","a,#0x%02x",
5475 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5476 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5477 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5478 emitcode("anl","a,#0x%02x",
5479 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5480 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5481 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5482 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5484 case 6 : // AABBBBBB:CCDDDDDD
5485 emitcode("mov","c,acc.7");
5486 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5487 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5488 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5489 emitcode("anl","a,#0x%02x",
5490 SRMask[shCount]); // 000000AA:BBBBBBCC
5492 case 7 : // ABBBBBBB:CDDDDDDD
5493 emitcode("mov","c,acc.7"); // c = A
5494 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5495 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5496 emitcode("anl","a,#0x%02x",
5497 SRMask[shCount]); // 0000000A:BBBBBBBC
5504 /*-----------------------------------------------------------------*/
5505 /* AccAXRshS - right shift signed a:x known count (0..7) */
5506 /*-----------------------------------------------------------------*/
5507 static void AccAXRshS (char *x, int shCount)
5510 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5515 emitcode("mov","c,acc.7");
5516 AccAXRrl1(x); // s->a:x
5519 emitcode("mov","c,acc.7");
5520 AccAXRrl1(x); // s->a:x
5521 emitcode("mov","c,acc.7");
5522 AccAXRrl1(x); // s->a:x
5526 case 5 : // AAAAABBB:CCCCCDDD = a:x
5527 tlbl = newiTempLabel(NULL);
5528 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5529 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5530 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5531 emitcode("anl","a,#0x%02x",
5532 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5533 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5534 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5535 emitcode("anl","a,#0x%02x",
5536 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5537 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5538 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5539 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5540 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5541 emitcode("orl","a,#0x%02x",
5542 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5543 emitcode("","%05d_DS_:",tlbl->key+100);
5544 break; // SSSSAAAA:BBBCCCCC
5545 case 6 : // AABBBBBB:CCDDDDDD
5546 tlbl = newiTempLabel(NULL);
5547 emitcode("mov","c,acc.7");
5548 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5549 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5550 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5551 emitcode("anl","a,#0x%02x",
5552 SRMask[shCount]); // 000000AA:BBBBBBCC
5553 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5554 emitcode("orl","a,#0x%02x",
5555 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5556 emitcode("","%05d_DS_:",tlbl->key+100);
5558 case 7 : // ABBBBBBB:CDDDDDDD
5559 tlbl = newiTempLabel(NULL);
5560 emitcode("mov","c,acc.7"); // c = A
5561 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5562 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5563 emitcode("anl","a,#0x%02x",
5564 SRMask[shCount]); // 0000000A:BBBBBBBC
5565 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5566 emitcode("orl","a,#0x%02x",
5567 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5568 emitcode("","%05d_DS_:",tlbl->key+100);
5575 /*-----------------------------------------------------------------*/
5576 /* shiftL2Left2Result - shift left two bytes from left to result */
5577 /*-----------------------------------------------------------------*/
5578 static void shiftL2Left2Result (operand *left, int offl,
5579 operand *result, int offr, int shCount)
5581 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5582 if(sameRegs(AOP(result), AOP(left)) &&
5583 ((offl + MSB16) == offr)){
5584 /* don't crash result[offr] */
5585 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5586 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5588 movLeft2Result(left,offl, result, offr, 0);
5589 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5591 /* ax << shCount (x = lsb(result))*/
5592 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5593 aopPut(AOP(result),"a",offr+MSB16);
5597 /*-----------------------------------------------------------------*/
5598 /* shiftR2Left2Result - shift right two bytes from left to result */
5599 /*-----------------------------------------------------------------*/
5600 static void shiftR2Left2Result (operand *left, int offl,
5601 operand *result, int offr,
5602 int shCount, int sign)
5604 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5605 if(sameRegs(AOP(result), AOP(left)) &&
5606 ((offl + MSB16) == offr)){
5607 /* don't crash result[offr] */
5608 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5609 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5611 movLeft2Result(left,offl, result, offr, 0);
5612 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5614 /* a:x >> shCount (x = lsb(result))*/
5616 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5618 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5619 if(getDataSize(result) > 1)
5620 aopPut(AOP(result),"a",offr+MSB16);
5623 /*-----------------------------------------------------------------*/
5624 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5625 /*-----------------------------------------------------------------*/
5626 static void shiftLLeftOrResult (operand *left, int offl,
5627 operand *result, int offr, int shCount)
5629 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5630 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5631 /* shift left accumulator */
5633 /* or with result */
5634 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5635 /* back to result */
5636 aopPut(AOP(result),"a",offr);
5639 /*-----------------------------------------------------------------*/
5640 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5641 /*-----------------------------------------------------------------*/
5642 static void shiftRLeftOrResult (operand *left, int offl,
5643 operand *result, int offr, int shCount)
5645 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5646 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5647 /* shift right accumulator */
5649 /* or with result */
5650 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5651 /* back to result */
5652 aopPut(AOP(result),"a",offr);
5655 /*-----------------------------------------------------------------*/
5656 /* genlshOne - left shift a one byte quantity by known count */
5657 /*-----------------------------------------------------------------*/
5658 static void genlshOne (operand *result, operand *left, int shCount)
5660 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5661 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5664 /*-----------------------------------------------------------------*/
5665 /* genlshTwo - left shift two bytes by known amount != 0 */
5666 /*-----------------------------------------------------------------*/
5667 static void genlshTwo (operand *result,operand *left, int shCount)
5671 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5672 size = getDataSize(result);
5674 /* if shCount >= 8 */
5680 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5682 movLeft2Result(left, LSB, result, MSB16, 0);
5684 aopPut(AOP(result),zero,LSB);
5687 /* 1 <= shCount <= 7 */
5690 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5692 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5696 /*-----------------------------------------------------------------*/
5697 /* shiftLLong - shift left one long from left to result */
5698 /* offl = LSB or MSB16 */
5699 /*-----------------------------------------------------------------*/
5700 static void shiftLLong (operand *left, operand *result, int offr )
5703 int size = AOP_SIZE(result);
5705 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5706 if(size >= LSB+offr){
5707 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5709 emitcode("add","a,acc");
5710 if (sameRegs(AOP(left),AOP(result)) &&
5711 size >= MSB16+offr && offr != LSB )
5712 emitcode("xch","a,%s",
5713 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5715 aopPut(AOP(result),"a",LSB+offr);
5718 if(size >= MSB16+offr){
5719 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5720 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5723 emitcode("rlc","a");
5724 if (sameRegs(AOP(left),AOP(result)) &&
5725 size >= MSB24+offr && offr != LSB)
5726 emitcode("xch","a,%s",
5727 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5729 aopPut(AOP(result),"a",MSB16+offr);
5732 if(size >= MSB24+offr){
5733 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5734 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5737 emitcode("rlc","a");
5738 if (sameRegs(AOP(left),AOP(result)) &&
5739 size >= MSB32+offr && offr != LSB )
5740 emitcode("xch","a,%s",
5741 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5743 aopPut(AOP(result),"a",MSB24+offr);
5746 if(size > MSB32+offr){
5747 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5748 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5751 emitcode("rlc","a");
5752 aopPut(AOP(result),"a",MSB32+offr);
5755 aopPut(AOP(result),zero,LSB);
5758 /*-----------------------------------------------------------------*/
5759 /* genlshFour - shift four byte by a known amount != 0 */
5760 /*-----------------------------------------------------------------*/
5761 static void genlshFour (operand *result, operand *left, int shCount)
5765 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5766 size = AOP_SIZE(result);
5768 /* if shifting more that 3 bytes */
5769 if (shCount >= 24 ) {
5772 /* lowest order of left goes to the highest
5773 order of the destination */
5774 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5776 movLeft2Result(left, LSB, result, MSB32, 0);
5777 aopPut(AOP(result),zero,LSB);
5778 aopPut(AOP(result),zero,MSB16);
5779 aopPut(AOP(result),zero,MSB32);
5783 /* more than two bytes */
5784 else if ( shCount >= 16 ) {
5785 /* lower order two bytes goes to higher order two bytes */
5787 /* if some more remaining */
5789 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5791 movLeft2Result(left, MSB16, result, MSB32, 0);
5792 movLeft2Result(left, LSB, result, MSB24, 0);
5794 aopPut(AOP(result),zero,MSB16);
5795 aopPut(AOP(result),zero,LSB);
5799 /* if more than 1 byte */
5800 else if ( shCount >= 8 ) {
5801 /* lower order three bytes goes to higher order three bytes */
5805 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5807 movLeft2Result(left, LSB, result, MSB16, 0);
5809 else{ /* size = 4 */
5811 movLeft2Result(left, MSB24, result, MSB32, 0);
5812 movLeft2Result(left, MSB16, result, MSB24, 0);
5813 movLeft2Result(left, LSB, result, MSB16, 0);
5814 aopPut(AOP(result),zero,LSB);
5816 else if(shCount == 1)
5817 shiftLLong(left, result, MSB16);
5819 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5820 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5821 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5822 aopPut(AOP(result),zero,LSB);
5827 /* 1 <= shCount <= 7 */
5828 else if(shCount <= 2){
5829 shiftLLong(left, result, LSB);
5831 shiftLLong(result, result, LSB);
5833 /* 3 <= shCount <= 7, optimize */
5835 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5836 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5837 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5841 /*-----------------------------------------------------------------*/
5842 /* genLeftShiftLiteral - left shifting by known count */
5843 /*-----------------------------------------------------------------*/
5844 static void genLeftShiftLiteral (operand *left,
5849 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5852 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5853 freeAsmop(right,NULL,ic,TRUE);
5855 aopOp(left,ic,FALSE);
5856 aopOp(result,ic,FALSE);
5858 size = getSize(operandType(result));
5861 emitcode("; shift left ","result %d, left %d",size,
5865 /* I suppose that the left size >= result size */
5868 movLeft2Result(left, size, result, size, 0);
5872 else if(shCount >= (size * 8))
5874 aopPut(AOP(result),zero,size);
5878 genlshOne (result,left,shCount);
5883 genlshTwo (result,left,shCount);
5887 genlshFour (result,left,shCount);
5891 freeAsmop(left,NULL,ic,TRUE);
5892 freeAsmop(result,NULL,ic,TRUE);
5895 /*-----------------------------------------------------------------*/
5896 /* genLeftShift - generates code for left shifting */
5897 /*-----------------------------------------------------------------*/
5898 static void genLeftShift (iCode *ic)
5900 operand *left,*right, *result;
5903 symbol *tlbl , *tlbl1;
5905 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5907 right = IC_RIGHT(ic);
5909 result = IC_RESULT(ic);
5911 aopOp(right,ic,FALSE);
5913 /* if the shift count is known then do it
5914 as efficiently as possible */
5915 if (AOP_TYPE(right) == AOP_LIT) {
5916 genLeftShiftLiteral (left,right,result,ic);
5920 /* shift count is unknown then we have to form
5921 a loop get the loop count in B : Note: we take
5922 only the lower order byte since shifting
5923 more that 32 bits make no sense anyway, ( the
5924 largest size of an object can be only 32 bits ) */
5926 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5927 emitcode("inc","b");
5928 freeAsmop (right,NULL,ic,TRUE);
5929 aopOp(left,ic,FALSE);
5930 aopOp(result,ic,FALSE);
5932 /* now move the left to the result if they are not the
5934 if (!sameRegs(AOP(left),AOP(result)) &&
5935 AOP_SIZE(result) > 1) {
5937 size = AOP_SIZE(result);
5940 l = aopGet(AOP(left),offset,FALSE,TRUE);
5941 if (*l == '@' && (IS_AOP_PREG(result))) {
5943 emitcode("mov","a,%s",l);
5944 aopPut(AOP(result),"a",offset);
5946 aopPut(AOP(result),l,offset);
5951 tlbl = newiTempLabel(NULL);
5952 size = AOP_SIZE(result);
5954 tlbl1 = newiTempLabel(NULL);
5956 /* if it is only one byte then */
5958 symbol *tlbl1 = newiTempLabel(NULL);
5960 l = aopGet(AOP(left),0,FALSE,FALSE);
5962 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
5963 emitcode("","%05d_DS_:",tlbl->key+100);
5964 emitcode("add","a,acc");
5965 emitcode("","%05d_DS_:",tlbl1->key+100);
5966 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
5967 aopPut(AOP(result),"a",0);
5971 reAdjustPreg(AOP(result));
5973 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
5974 emitcode("","%05d_DS_:",tlbl->key+100);
5975 l = aopGet(AOP(result),offset,FALSE,FALSE);
5977 emitcode("add","a,acc");
5978 aopPut(AOP(result),"a",offset++);
5980 l = aopGet(AOP(result),offset,FALSE,FALSE);
5982 emitcode("rlc","a");
5983 aopPut(AOP(result),"a",offset++);
5985 reAdjustPreg(AOP(result));
5987 emitcode("","%05d_DS_:",tlbl1->key+100);
5988 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
5990 freeAsmop(left,NULL,ic,TRUE);
5991 freeAsmop(result,NULL,ic,TRUE);
5994 /*-----------------------------------------------------------------*/
5995 /* genrshOne - right shift a one byte quantity by known count */
5996 /*-----------------------------------------------------------------*/
5997 static void genrshOne (operand *result, operand *left,
5998 int shCount, int sign)
6000 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6001 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6004 /*-----------------------------------------------------------------*/
6005 /* genrshTwo - right shift two bytes by known amount != 0 */
6006 /*-----------------------------------------------------------------*/
6007 static void genrshTwo (operand *result,operand *left,
6008 int shCount, int sign)
6010 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6011 /* if shCount >= 8 */
6015 shiftR1Left2Result(left, MSB16, result, LSB,
6018 movLeft2Result(left, MSB16, result, LSB, sign);
6019 addSign(result, MSB16, sign);
6022 /* 1 <= shCount <= 7 */
6024 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6027 /*-----------------------------------------------------------------*/
6028 /* shiftRLong - shift right one long from left to result */
6029 /* offl = LSB or MSB16 */
6030 /*-----------------------------------------------------------------*/
6031 static void shiftRLong (operand *left, int offl,
6032 operand *result, int sign)
6034 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6036 emitcode("clr","c");
6037 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6039 emitcode("mov","c,acc.7");
6040 emitcode("rrc","a");
6041 aopPut(AOP(result),"a",MSB32-offl);
6043 /* add sign of "a" */
6044 addSign(result, MSB32, sign);
6046 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6047 emitcode("rrc","a");
6048 aopPut(AOP(result),"a",MSB24-offl);
6050 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6051 emitcode("rrc","a");
6052 aopPut(AOP(result),"a",MSB16-offl);
6055 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6056 emitcode("rrc","a");
6057 aopPut(AOP(result),"a",LSB);
6061 /*-----------------------------------------------------------------*/
6062 /* genrshFour - shift four byte by a known amount != 0 */
6063 /*-----------------------------------------------------------------*/
6064 static void genrshFour (operand *result, operand *left,
6065 int shCount, int sign)
6067 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6068 /* if shifting more that 3 bytes */
6069 if(shCount >= 24 ) {
6072 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6074 movLeft2Result(left, MSB32, result, LSB, sign);
6075 addSign(result, MSB16, sign);
6077 else if(shCount >= 16){
6080 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6082 movLeft2Result(left, MSB24, result, LSB, 0);
6083 movLeft2Result(left, MSB32, result, MSB16, sign);
6085 addSign(result, MSB24, sign);
6087 else if(shCount >= 8){
6090 shiftRLong(left, MSB16, result, sign);
6091 else if(shCount == 0){
6092 movLeft2Result(left, MSB16, result, LSB, 0);
6093 movLeft2Result(left, MSB24, result, MSB16, 0);
6094 movLeft2Result(left, MSB32, result, MSB24, sign);
6095 addSign(result, MSB32, sign);
6098 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6099 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6100 /* the last shift is signed */
6101 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6102 addSign(result, MSB32, sign);
6105 else{ /* 1 <= shCount <= 7 */
6107 shiftRLong(left, LSB, result, sign);
6109 shiftRLong(result, LSB, result, sign);
6112 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6113 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6114 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6119 /*-----------------------------------------------------------------*/
6120 /* genRightShiftLiteral - right shifting by known count */
6121 /*-----------------------------------------------------------------*/
6122 static void genRightShiftLiteral (operand *left,
6128 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6131 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6132 freeAsmop(right,NULL,ic,TRUE);
6134 aopOp(left,ic,FALSE);
6135 aopOp(result,ic,FALSE);
6138 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6142 size = getDataSize(left);
6143 /* test the LEFT size !!! */
6145 /* I suppose that the left size >= result size */
6147 size = getDataSize(result);
6149 movLeft2Result(left, size, result, size, 0);
6152 else if(shCount >= (size * 8)){
6154 /* get sign in acc.7 */
6155 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6156 addSign(result, LSB, sign);
6160 genrshOne (result,left,shCount,sign);
6164 genrshTwo (result,left,shCount,sign);
6168 genrshFour (result,left,shCount,sign);
6174 freeAsmop(left,NULL,ic,TRUE);
6175 freeAsmop(result,NULL,ic,TRUE);
6179 /*-----------------------------------------------------------------*/
6180 /* genSignedRightShift - right shift of signed number */
6181 /*-----------------------------------------------------------------*/
6182 static void genSignedRightShift (iCode *ic)
6184 operand *right, *left, *result;
6187 symbol *tlbl, *tlbl1 ;
6189 /* we do it the hard way put the shift count in b
6190 and loop thru preserving the sign */
6191 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6193 right = IC_RIGHT(ic);
6195 result = IC_RESULT(ic);
6197 aopOp(right,ic,FALSE);
6200 if ( AOP_TYPE(right) == AOP_LIT) {
6201 genRightShiftLiteral (left,right,result,ic,1);
6204 /* shift count is unknown then we have to form
6205 a loop get the loop count in B : Note: we take
6206 only the lower order byte since shifting
6207 more that 32 bits make no sense anyway, ( the
6208 largest size of an object can be only 32 bits ) */
6210 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6211 emitcode("inc","b");
6212 freeAsmop (right,NULL,ic,TRUE);
6213 aopOp(left,ic,FALSE);
6214 aopOp(result,ic,FALSE);
6216 /* now move the left to the result if they are not the
6218 if (!sameRegs(AOP(left),AOP(result)) &&
6219 AOP_SIZE(result) > 1) {
6221 size = AOP_SIZE(result);
6224 l = aopGet(AOP(left),offset,FALSE,TRUE);
6225 if (*l == '@' && IS_AOP_PREG(result)) {
6227 emitcode("mov","a,%s",l);
6228 aopPut(AOP(result),"a",offset);
6230 aopPut(AOP(result),l,offset);
6235 /* mov the highest order bit to OVR */
6236 tlbl = newiTempLabel(NULL);
6237 tlbl1= newiTempLabel(NULL);
6239 size = AOP_SIZE(result);
6241 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6242 emitcode("rlc","a");
6243 emitcode("mov","ov,c");
6244 /* if it is only one byte then */
6246 l = aopGet(AOP(left),0,FALSE,FALSE);
6248 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6249 emitcode("","%05d_DS_:",tlbl->key+100);
6250 emitcode("mov","c,ov");
6251 emitcode("rrc","a");
6252 emitcode("","%05d_DS_:",tlbl1->key+100);
6253 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6254 aopPut(AOP(result),"a",0);
6258 reAdjustPreg(AOP(result));
6259 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6260 emitcode("","%05d_DS_:",tlbl->key+100);
6261 emitcode("mov","c,ov");
6263 l = aopGet(AOP(result),offset,FALSE,FALSE);
6265 emitcode("rrc","a");
6266 aopPut(AOP(result),"a",offset--);
6268 reAdjustPreg(AOP(result));
6269 emitcode("","%05d_DS_:",tlbl1->key+100);
6270 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6273 freeAsmop(left,NULL,ic,TRUE);
6274 freeAsmop(result,NULL,ic,TRUE);
6277 /*-----------------------------------------------------------------*/
6278 /* genRightShift - generate code for right shifting */
6279 /*-----------------------------------------------------------------*/
6280 static void genRightShift (iCode *ic)
6282 operand *right, *left, *result;
6286 symbol *tlbl, *tlbl1 ;
6288 /* if signed then we do it the hard way preserve the
6289 sign bit moving it inwards */
6290 retype = getSpec(operandType(IC_RESULT(ic)));
6291 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6293 if (!SPEC_USIGN(retype)) {
6294 genSignedRightShift (ic);
6298 /* signed & unsigned types are treated the same : i.e. the
6299 signed is NOT propagated inwards : quoting from the
6300 ANSI - standard : "for E1 >> E2, is equivalent to division
6301 by 2**E2 if unsigned or if it has a non-negative value,
6302 otherwise the result is implementation defined ", MY definition
6303 is that the sign does not get propagated */
6305 right = IC_RIGHT(ic);
6307 result = IC_RESULT(ic);
6309 aopOp(right,ic,FALSE);
6311 /* if the shift count is known then do it
6312 as efficiently as possible */
6313 if (AOP_TYPE(right) == AOP_LIT) {
6314 genRightShiftLiteral (left,right,result,ic, 0);
6318 /* shift count is unknown then we have to form
6319 a loop get the loop count in B : Note: we take
6320 only the lower order byte since shifting
6321 more that 32 bits make no sense anyway, ( the
6322 largest size of an object can be only 32 bits ) */
6324 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6325 emitcode("inc","b");
6326 freeAsmop (right,NULL,ic,TRUE);
6327 aopOp(left,ic,FALSE);
6328 aopOp(result,ic,FALSE);
6330 /* now move the left to the result if they are not the
6332 if (!sameRegs(AOP(left),AOP(result)) &&
6333 AOP_SIZE(result) > 1) {
6335 size = AOP_SIZE(result);
6338 l = aopGet(AOP(left),offset,FALSE,TRUE);
6339 if (*l == '@' && IS_AOP_PREG(result)) {
6341 emitcode("mov","a,%s",l);
6342 aopPut(AOP(result),"a",offset);
6344 aopPut(AOP(result),l,offset);
6349 tlbl = newiTempLabel(NULL);
6350 tlbl1= newiTempLabel(NULL);
6351 size = AOP_SIZE(result);
6354 /* if it is only one byte then */
6356 l = aopGet(AOP(left),0,FALSE,FALSE);
6358 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6359 emitcode("","%05d_DS_:",tlbl->key+100);
6361 emitcode("rrc","a");
6362 emitcode("","%05d_DS_:",tlbl1->key+100);
6363 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6364 aopPut(AOP(result),"a",0);
6368 reAdjustPreg(AOP(result));
6369 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6370 emitcode("","%05d_DS_:",tlbl->key+100);
6373 l = aopGet(AOP(result),offset,FALSE,FALSE);
6375 emitcode("rrc","a");
6376 aopPut(AOP(result),"a",offset--);
6378 reAdjustPreg(AOP(result));
6380 emitcode("","%05d_DS_:",tlbl1->key+100);
6381 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6384 freeAsmop(left,NULL,ic,TRUE);
6385 freeAsmop(result,NULL,ic,TRUE);
6388 /*-----------------------------------------------------------------*/
6389 /* genUnpackBits - generates code for unpacking bits */
6390 /*-----------------------------------------------------------------*/
6391 static void genUnpackBits (operand *result, char *rname, int ptype)
6398 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6399 etype = getSpec(operandType(result));
6401 /* read the first byte */
6406 emitcode("mov","a,@%s",rname);
6410 emitcode("movx","a,@%s",rname);
6414 emitcode("movx","a,@dptr");
6418 emitcode("clr","a");
6419 emitcode("movc","a","@a+dptr");
6423 emitcode("lcall","__gptrget");
6427 /* if we have bitdisplacement then it fits */
6428 /* into this byte completely or if length is */
6429 /* less than a byte */
6430 if ((shCnt = SPEC_BSTR(etype)) ||
6431 (SPEC_BLEN(etype) <= 8)) {
6433 /* shift right acc */
6436 emitcode("anl","a,#0x%02x",
6437 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6438 aopPut(AOP(result),"a",offset);
6442 /* bit field did not fit in a byte */
6443 rlen = SPEC_BLEN(etype) - 8;
6444 aopPut(AOP(result),"a",offset++);
6451 emitcode("inc","%s",rname);
6452 emitcode("mov","a,@%s",rname);
6456 emitcode("inc","%s",rname);
6457 emitcode("movx","a,@%s",rname);
6461 emitcode("inc","dptr");
6462 emitcode("movx","a,@dptr");
6466 emitcode("clr","a");
6467 emitcode("inc","dptr");
6468 emitcode("movc","a","@a+dptr");
6472 emitcode("inc","dptr");
6473 emitcode("lcall","__gptrget");
6478 /* if we are done */
6482 aopPut(AOP(result),"a",offset++);
6487 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6488 aopPut(AOP(result),"a",offset);
6495 /*-----------------------------------------------------------------*/
6496 /* genDataPointerGet - generates code when ptr offset is known */
6497 /*-----------------------------------------------------------------*/
6498 static void genDataPointerGet (operand *left,
6504 int size , offset = 0;
6505 aopOp(result,ic,TRUE);
6507 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6508 /* get the string representation of the name */
6509 l = aopGet(AOP(left),0,FALSE,TRUE);
6510 size = AOP_SIZE(result);
6513 sprintf(buffer,"(%s + %d)",l+1,offset);
6515 sprintf(buffer,"%s",l+1);
6516 aopPut(AOP(result),buffer,offset++);
6519 freeAsmop(left,NULL,ic,TRUE);
6520 freeAsmop(result,NULL,ic,TRUE);
6523 /*-----------------------------------------------------------------*/
6524 /* genNearPointerGet - emitcode for near pointer fetch */
6525 /*-----------------------------------------------------------------*/
6526 static void genNearPointerGet (operand *left,
6533 sym_link *rtype, *retype;
6534 sym_link *ltype = operandType(left);
6537 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6539 rtype = operandType(result);
6540 retype= getSpec(rtype);
6542 aopOp(left,ic,FALSE);
6544 /* if left is rematerialisable and
6545 result is not bit variable type and
6546 the left is pointer to data space i.e
6547 lower 128 bytes of space */
6548 if (AOP_TYPE(left) == AOP_IMMD &&
6549 !IS_BITVAR(retype) &&
6550 DCL_TYPE(ltype) == POINTER) {
6551 genDataPointerGet (left,result,ic);
6555 /* if the value is already in a pointer register
6556 then don't need anything more */
6557 if (!AOP_INPREG(AOP(left))) {
6558 /* otherwise get a free pointer register */
6560 preg = getFreePtr(ic,&aop,FALSE);
6561 emitcode("mov","%s,%s",
6563 aopGet(AOP(left),0,FALSE,TRUE));
6564 rname = preg->name ;
6566 rname = aopGet(AOP(left),0,FALSE,FALSE);
6568 freeAsmop(left,NULL,ic,TRUE);
6569 aopOp (result,ic,FALSE);
6571 /* if bitfield then unpack the bits */
6572 if (IS_BITVAR(retype))
6573 genUnpackBits (result,rname,POINTER);
6575 /* we have can just get the values */
6576 int size = AOP_SIZE(result);
6580 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6582 emitcode("mov","a,@%s",rname);
6583 aopPut(AOP(result),"a",offset);
6585 sprintf(buffer,"@%s",rname);
6586 aopPut(AOP(result),buffer,offset);
6590 emitcode("inc","%s",rname);
6594 /* now some housekeeping stuff */
6596 /* we had to allocate for this iCode */
6597 freeAsmop(NULL,aop,ic,TRUE);
6599 /* we did not allocate which means left
6600 already in a pointer register, then
6601 if size > 0 && this could be used again
6602 we have to point it back to where it
6604 if (AOP_SIZE(result) > 1 &&
6605 !OP_SYMBOL(left)->remat &&
6606 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6608 int size = AOP_SIZE(result) - 1;
6610 emitcode("dec","%s",rname);
6615 freeAsmop(result,NULL,ic,TRUE);
6619 /*-----------------------------------------------------------------*/
6620 /* genPagedPointerGet - emitcode for paged pointer fetch */
6621 /*-----------------------------------------------------------------*/
6622 static void genPagedPointerGet (operand *left,
6629 sym_link *rtype, *retype;
6631 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6633 rtype = operandType(result);
6634 retype= getSpec(rtype);
6636 aopOp(left,ic,FALSE);
6638 /* if the value is already in a pointer register
6639 then don't need anything more */
6640 if (!AOP_INPREG(AOP(left))) {
6641 /* otherwise get a free pointer register */
6643 preg = getFreePtr(ic,&aop,FALSE);
6644 emitcode("mov","%s,%s",
6646 aopGet(AOP(left),0,FALSE,TRUE));
6647 rname = preg->name ;
6649 rname = aopGet(AOP(left),0,FALSE,FALSE);
6651 freeAsmop(left,NULL,ic,TRUE);
6652 aopOp (result,ic,FALSE);
6654 /* if bitfield then unpack the bits */
6655 if (IS_BITVAR(retype))
6656 genUnpackBits (result,rname,PPOINTER);
6658 /* we have can just get the values */
6659 int size = AOP_SIZE(result);
6664 emitcode("movx","a,@%s",rname);
6665 aopPut(AOP(result),"a",offset);
6670 emitcode("inc","%s",rname);
6674 /* now some housekeeping stuff */
6676 /* we had to allocate for this iCode */
6677 freeAsmop(NULL,aop,ic,TRUE);
6679 /* we did not allocate which means left
6680 already in a pointer register, then
6681 if size > 0 && this could be used again
6682 we have to point it back to where it
6684 if (AOP_SIZE(result) > 1 &&
6685 !OP_SYMBOL(left)->remat &&
6686 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6688 int size = AOP_SIZE(result) - 1;
6690 emitcode("dec","%s",rname);
6695 freeAsmop(result,NULL,ic,TRUE);
6700 /*-----------------------------------------------------------------*/
6701 /* genFarPointerGet - gget value from far space */
6702 /*-----------------------------------------------------------------*/
6703 static void genFarPointerGet (operand *left,
6704 operand *result, iCode *ic)
6707 sym_link *retype = getSpec(operandType(result));
6709 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6711 aopOp(left,ic,FALSE);
6713 /* if the operand is already in dptr
6714 then we do nothing else we move the value to dptr */
6715 if (AOP_TYPE(left) != AOP_STR) {
6716 /* if this is remateriazable */
6717 if (AOP_TYPE(left) == AOP_IMMD)
6718 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6719 else { /* we need to get it byte by byte */
6720 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6721 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6722 if (options.model == MODEL_FLAT24)
6724 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6728 /* so dptr know contains the address */
6729 freeAsmop(left,NULL,ic,TRUE);
6730 aopOp(result,ic,FALSE);
6732 /* if bit then unpack */
6733 if (IS_BITVAR(retype))
6734 genUnpackBits(result,"dptr",FPOINTER);
6736 size = AOP_SIZE(result);
6740 emitcode("movx","a,@dptr");
6741 aopPut(AOP(result),"a",offset++);
6743 emitcode("inc","dptr");
6747 freeAsmop(result,NULL,ic,TRUE);
6750 /*-----------------------------------------------------------------*/
6751 /* emitcodePointerGet - gget value from code space */
6752 /*-----------------------------------------------------------------*/
6753 static void emitcodePointerGet (operand *left,
6754 operand *result, iCode *ic)
6757 sym_link *retype = getSpec(operandType(result));
6759 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6761 aopOp(left,ic,FALSE);
6763 /* if the operand is already in dptr
6764 then we do nothing else we move the value to dptr */
6765 if (AOP_TYPE(left) != AOP_STR) {
6766 /* if this is remateriazable */
6767 if (AOP_TYPE(left) == AOP_IMMD)
6768 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6769 else { /* we need to get it byte by byte */
6770 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6771 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6772 if (options.model == MODEL_FLAT24)
6774 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6778 /* so dptr know contains the address */
6779 freeAsmop(left,NULL,ic,TRUE);
6780 aopOp(result,ic,FALSE);
6782 /* if bit then unpack */
6783 if (IS_BITVAR(retype))
6784 genUnpackBits(result,"dptr",CPOINTER);
6786 size = AOP_SIZE(result);
6790 emitcode("clr","a");
6791 emitcode("movc","a,@a+dptr");
6792 aopPut(AOP(result),"a",offset++);
6794 emitcode("inc","dptr");
6798 freeAsmop(result,NULL,ic,TRUE);
6801 /*-----------------------------------------------------------------*/
6802 /* genGenPointerGet - gget value from generic pointer space */
6803 /*-----------------------------------------------------------------*/
6804 static void genGenPointerGet (operand *left,
6805 operand *result, iCode *ic)
6808 sym_link *retype = getSpec(operandType(result));
6810 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6811 aopOp(left,ic,FALSE);
6813 /* if the operand is already in dptr
6814 then we do nothing else we move the value to dptr */
6815 if (AOP_TYPE(left) != AOP_STR) {
6816 /* if this is remateriazable */
6817 if (AOP_TYPE(left) == AOP_IMMD) {
6818 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6819 emitcode("mov","b,#%d",pointerCode(retype));
6821 else { /* we need to get it byte by byte */
6822 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6823 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6824 if (options.model == MODEL_FLAT24)
6826 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6827 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6831 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6835 /* so dptr know contains the address */
6836 freeAsmop(left,NULL,ic,TRUE);
6837 aopOp(result,ic,FALSE);
6839 /* if bit then unpack */
6840 if (IS_BITVAR(retype))
6841 genUnpackBits(result,"dptr",GPOINTER);
6843 size = AOP_SIZE(result);
6847 emitcode("lcall","__gptrget");
6848 aopPut(AOP(result),"a",offset++);
6850 emitcode("inc","dptr");
6854 freeAsmop(result,NULL,ic,TRUE);
6857 /*-----------------------------------------------------------------*/
6858 /* genPointerGet - generate code for pointer get */
6859 /*-----------------------------------------------------------------*/
6860 static void genPointerGet (iCode *ic)
6862 operand *left, *result ;
6863 sym_link *type, *etype;
6866 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6869 result = IC_RESULT(ic) ;
6871 /* depending on the type of pointer we need to
6872 move it to the correct pointer register */
6873 type = operandType(left);
6874 etype = getSpec(type);
6875 /* if left is of type of pointer then it is simple */
6876 if (IS_PTR(type) && !IS_FUNC(type->next))
6877 p_type = DCL_TYPE(type);
6879 /* we have to go by the storage class */
6880 p_type = PTR_TYPE(SPEC_OCLS(etype));
6882 /* if (SPEC_OCLS(etype)->codesp ) { */
6883 /* p_type = CPOINTER ; */
6886 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6887 /* p_type = FPOINTER ; */
6889 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6890 /* p_type = PPOINTER; */
6892 /* if (SPEC_OCLS(etype) == idata ) */
6893 /* p_type = IPOINTER; */
6895 /* p_type = POINTER ; */
6898 /* now that we have the pointer type we assign
6899 the pointer values */
6904 genNearPointerGet (left,result,ic);
6908 genPagedPointerGet(left,result,ic);
6912 genFarPointerGet (left,result,ic);
6916 emitcodePointerGet (left,result,ic);
6920 genGenPointerGet (left,result,ic);
6926 /*-----------------------------------------------------------------*/
6927 /* genPackBits - generates code for packed bit storage */
6928 /*-----------------------------------------------------------------*/
6929 static void genPackBits (sym_link *etype ,
6931 char *rname, int p_type)
6939 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6940 blen = SPEC_BLEN(etype);
6941 bstr = SPEC_BSTR(etype);
6943 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6946 /* if the bit lenth is less than or */
6947 /* it exactly fits a byte then */
6948 if (SPEC_BLEN(etype) <= 8 ) {
6949 shCount = SPEC_BSTR(etype) ;
6951 /* shift left acc */
6954 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6959 emitcode ("mov","b,a");
6960 emitcode("mov","a,@%s",rname);
6964 emitcode ("mov","b,a");
6965 emitcode("movx","a,@dptr");
6969 emitcode ("push","b");
6970 emitcode ("push","acc");
6971 emitcode ("lcall","__gptrget");
6972 emitcode ("pop","b");
6976 emitcode ("anl","a,#0x%02x",(unsigned char)
6977 ((unsigned char)(0xFF << (blen+bstr)) |
6978 (unsigned char)(0xFF >> (8-bstr)) ) );
6979 emitcode ("orl","a,b");
6980 if (p_type == GPOINTER)
6981 emitcode("pop","b");
6987 emitcode("mov","@%s,a",rname);
6991 emitcode("movx","@dptr,a");
6995 emitcode("lcall","__gptrput");
7000 if ( SPEC_BLEN(etype) <= 8 )
7003 emitcode("inc","%s",rname);
7004 rLen = SPEC_BLEN(etype) ;
7006 /* now generate for lengths greater than one byte */
7009 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7019 emitcode("mov","@%s,a",rname);
7021 emitcode("mov","@%s,%s",rname,l);
7026 emitcode("movx","@dptr,a");
7031 emitcode("lcall","__gptrput");
7034 emitcode ("inc","%s",rname);
7039 /* last last was not complete */
7041 /* save the byte & read byte */
7044 emitcode ("mov","b,a");
7045 emitcode("mov","a,@%s",rname);
7049 emitcode ("mov","b,a");
7050 emitcode("movx","a,@dptr");
7054 emitcode ("push","b");
7055 emitcode ("push","acc");
7056 emitcode ("lcall","__gptrget");
7057 emitcode ("pop","b");
7061 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7062 emitcode ("orl","a,b");
7065 if (p_type == GPOINTER)
7066 emitcode("pop","b");
7071 emitcode("mov","@%s,a",rname);
7075 emitcode("movx","@dptr,a");
7079 emitcode("lcall","__gptrput");
7083 /*-----------------------------------------------------------------*/
7084 /* genDataPointerSet - remat pointer to data space */
7085 /*-----------------------------------------------------------------*/
7086 static void genDataPointerSet(operand *right,
7090 int size, offset = 0 ;
7091 char *l, buffer[256];
7093 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7094 aopOp(right,ic,FALSE);
7096 l = aopGet(AOP(result),0,FALSE,TRUE);
7097 size = AOP_SIZE(right);
7100 sprintf(buffer,"(%s + %d)",l+1,offset);
7102 sprintf(buffer,"%s",l+1);
7103 emitcode("mov","%s,%s",buffer,
7104 aopGet(AOP(right),offset++,FALSE,FALSE));
7107 freeAsmop(right,NULL,ic,TRUE);
7108 freeAsmop(result,NULL,ic,TRUE);
7111 /*-----------------------------------------------------------------*/
7112 /* genNearPointerSet - emitcode for near pointer put */
7113 /*-----------------------------------------------------------------*/
7114 static void genNearPointerSet (operand *right,
7122 sym_link *ptype = operandType(result);
7124 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7125 retype= getSpec(operandType(right));
7127 aopOp(result,ic,FALSE);
7129 /* if the result is rematerializable &
7130 in data space & not a bit variable */
7131 if (AOP_TYPE(result) == AOP_IMMD &&
7132 DCL_TYPE(ptype) == POINTER &&
7133 !IS_BITVAR(retype)) {
7134 genDataPointerSet (right,result,ic);
7138 /* if the value is already in a pointer register
7139 then don't need anything more */
7140 if (!AOP_INPREG(AOP(result))) {
7141 /* otherwise get a free pointer register */
7143 preg = getFreePtr(ic,&aop,FALSE);
7144 emitcode("mov","%s,%s",
7146 aopGet(AOP(result),0,FALSE,TRUE));
7147 rname = preg->name ;
7149 rname = aopGet(AOP(result),0,FALSE,FALSE);
7151 freeAsmop(result,NULL,ic,TRUE);
7152 aopOp (right,ic,FALSE);
7154 /* if bitfield then unpack the bits */
7155 if (IS_BITVAR(retype))
7156 genPackBits (retype,right,rname,POINTER);
7158 /* we have can just get the values */
7159 int size = AOP_SIZE(right);
7163 l = aopGet(AOP(right),offset,FALSE,TRUE);
7166 emitcode("mov","@%s,a",rname);
7168 emitcode("mov","@%s,%s",rname,l);
7170 emitcode("inc","%s",rname);
7175 /* now some housekeeping stuff */
7177 /* we had to allocate for this iCode */
7178 freeAsmop(NULL,aop,ic,TRUE);
7180 /* we did not allocate which means left
7181 already in a pointer register, then
7182 if size > 0 && this could be used again
7183 we have to point it back to where it
7185 if (AOP_SIZE(right) > 1 &&
7186 !OP_SYMBOL(result)->remat &&
7187 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7189 int size = AOP_SIZE(right) - 1;
7191 emitcode("dec","%s",rname);
7196 freeAsmop(right,NULL,ic,TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* genPagedPointerSet - emitcode for Paged pointer put */
7203 /*-----------------------------------------------------------------*/
7204 static void genPagedPointerSet (operand *right,
7213 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7215 retype= getSpec(operandType(right));
7217 aopOp(result,ic,FALSE);
7219 /* if the value is already in a pointer register
7220 then don't need anything more */
7221 if (!AOP_INPREG(AOP(result))) {
7222 /* otherwise get a free pointer register */
7224 preg = getFreePtr(ic,&aop,FALSE);
7225 emitcode("mov","%s,%s",
7227 aopGet(AOP(result),0,FALSE,TRUE));
7228 rname = preg->name ;
7230 rname = aopGet(AOP(result),0,FALSE,FALSE);
7232 freeAsmop(result,NULL,ic,TRUE);
7233 aopOp (right,ic,FALSE);
7235 /* if bitfield then unpack the bits */
7236 if (IS_BITVAR(retype))
7237 genPackBits (retype,right,rname,PPOINTER);
7239 /* we have can just get the values */
7240 int size = AOP_SIZE(right);
7244 l = aopGet(AOP(right),offset,FALSE,TRUE);
7247 emitcode("movx","@%s,a",rname);
7250 emitcode("inc","%s",rname);
7256 /* now some housekeeping stuff */
7258 /* we had to allocate for this iCode */
7259 freeAsmop(NULL,aop,ic,TRUE);
7261 /* we did not allocate which means left
7262 already in a pointer register, then
7263 if size > 0 && this could be used again
7264 we have to point it back to where it
7266 if (AOP_SIZE(right) > 1 &&
7267 !OP_SYMBOL(result)->remat &&
7268 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7270 int size = AOP_SIZE(right) - 1;
7272 emitcode("dec","%s",rname);
7277 freeAsmop(right,NULL,ic,TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* genFarPointerSet - set value from far space */
7284 /*-----------------------------------------------------------------*/
7285 static void genFarPointerSet (operand *right,
7286 operand *result, iCode *ic)
7289 sym_link *retype = getSpec(operandType(right));
7291 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7292 aopOp(result,ic,FALSE);
7294 /* if the operand is already in dptr
7295 then we do nothing else we move the value to dptr */
7296 if (AOP_TYPE(result) != AOP_STR) {
7297 /* if this is remateriazable */
7298 if (AOP_TYPE(result) == AOP_IMMD)
7299 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7300 else { /* we need to get it byte by byte */
7301 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7302 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7303 if (options.model == MODEL_FLAT24)
7305 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7309 /* so dptr know contains the address */
7310 freeAsmop(result,NULL,ic,TRUE);
7311 aopOp(right,ic,FALSE);
7313 /* if bit then unpack */
7314 if (IS_BITVAR(retype))
7315 genPackBits(retype,right,"dptr",FPOINTER);
7317 size = AOP_SIZE(right);
7321 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7323 emitcode("movx","@dptr,a");
7325 emitcode("inc","dptr");
7329 freeAsmop(right,NULL,ic,TRUE);
7332 /*-----------------------------------------------------------------*/
7333 /* genGenPointerSet - set value from generic pointer space */
7334 /*-----------------------------------------------------------------*/
7335 static void genGenPointerSet (operand *right,
7336 operand *result, iCode *ic)
7339 sym_link *retype = getSpec(operandType(right));
7341 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7343 aopOp(result,ic,FALSE);
7345 /* if the operand is already in dptr
7346 then we do nothing else we move the value to dptr */
7347 if (AOP_TYPE(result) != AOP_STR) {
7348 /* if this is remateriazable */
7349 if (AOP_TYPE(result) == AOP_IMMD) {
7350 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7351 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7353 else { /* we need to get it byte by byte */
7354 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7355 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7356 if (options.model == MODEL_FLAT24)
7358 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7359 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7363 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7367 /* so dptr know contains the address */
7368 freeAsmop(result,NULL,ic,TRUE);
7369 aopOp(right,ic,FALSE);
7371 /* if bit then unpack */
7372 if (IS_BITVAR(retype))
7373 genPackBits(retype,right,"dptr",GPOINTER);
7375 size = AOP_SIZE(right);
7379 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7381 emitcode("lcall","__gptrput");
7383 emitcode("inc","dptr");
7387 freeAsmop(right,NULL,ic,TRUE);
7390 /*-----------------------------------------------------------------*/
7391 /* genPointerSet - stores the value into a pointer location */
7392 /*-----------------------------------------------------------------*/
7393 static void genPointerSet (iCode *ic)
7395 operand *right, *result ;
7396 sym_link *type, *etype;
7399 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7401 right = IC_RIGHT(ic);
7402 result = IC_RESULT(ic) ;
7404 /* depending on the type of pointer we need to
7405 move it to the correct pointer register */
7406 type = operandType(result);
7407 etype = getSpec(type);
7408 /* if left is of type of pointer then it is simple */
7409 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7410 p_type = DCL_TYPE(type);
7413 /* we have to go by the storage class */
7414 p_type = PTR_TYPE(SPEC_OCLS(etype));
7416 /* if (SPEC_OCLS(etype)->codesp ) { */
7417 /* p_type = CPOINTER ; */
7420 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7421 /* p_type = FPOINTER ; */
7423 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7424 /* p_type = PPOINTER ; */
7426 /* if (SPEC_OCLS(etype) == idata ) */
7427 /* p_type = IPOINTER ; */
7429 /* p_type = POINTER ; */
7432 /* now that we have the pointer type we assign
7433 the pointer values */
7438 genNearPointerSet (right,result,ic);
7442 genPagedPointerSet (right,result,ic);
7446 genFarPointerSet (right,result,ic);
7450 genGenPointerSet (right,result,ic);
7456 /*-----------------------------------------------------------------*/
7457 /* genIfx - generate code for Ifx statement */
7458 /*-----------------------------------------------------------------*/
7459 static void genIfx (iCode *ic, iCode *popIc)
7461 operand *cond = IC_COND(ic);
7464 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7465 aopOp(cond,ic,FALSE);
7467 /* get the value into acc */
7468 if (AOP_TYPE(cond) != AOP_CRY)
7472 /* the result is now in the accumulator */
7473 freeAsmop(cond,NULL,ic,TRUE);
7475 /* if there was something to be popped then do it */
7479 /* if the condition is a bit variable */
7480 if (isbit && IS_ITEMP(cond) &&
7482 genIfxJump(ic,SPIL_LOC(cond)->rname);
7484 if (isbit && !IS_ITEMP(cond))
7485 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7492 /*-----------------------------------------------------------------*/
7493 /* genAddrOf - generates code for address of */
7494 /*-----------------------------------------------------------------*/
7495 static void genAddrOf (iCode *ic)
7497 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7500 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7502 aopOp(IC_RESULT(ic),ic,FALSE);
7504 /* if the operand is on the stack then we
7505 need to get the stack offset of this
7508 /* if it has an offset then we need to compute
7511 emitcode("mov","a,_bp");
7512 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7513 aopPut(AOP(IC_RESULT(ic)),"a",0);
7515 /* we can just move _bp */
7516 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7518 /* fill the result with zero */
7519 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7522 if (options.stack10bit && size < (FPTRSIZE - 1))
7525 "*** warning: pointer to stack var truncated.\n");
7532 if (options.stack10bit && offset == 2)
7534 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7538 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7545 /* object not on stack then we need the name */
7546 size = AOP_SIZE(IC_RESULT(ic));
7550 char s[SDCC_NAME_MAX];
7552 sprintf(s,"#(%s >> %d)",
7556 sprintf(s,"#%s",sym->rname);
7557 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7561 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7565 /*-----------------------------------------------------------------*/
7566 /* genFarFarAssign - assignment when both are in far space */
7567 /*-----------------------------------------------------------------*/
7568 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7570 int size = AOP_SIZE(right);
7573 /* first push the right side on to the stack */
7575 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7577 emitcode ("push","acc");
7580 freeAsmop(right,NULL,ic,FALSE);
7581 /* now assign DPTR to result */
7582 aopOp(result,ic,FALSE);
7583 size = AOP_SIZE(result);
7585 emitcode ("pop","acc");
7586 aopPut(AOP(result),"a",--offset);
7588 freeAsmop(result,NULL,ic,FALSE);
7592 /*-----------------------------------------------------------------*/
7593 /* genAssign - generate code for assignment */
7594 /*-----------------------------------------------------------------*/
7595 static void genAssign (iCode *ic)
7597 operand *result, *right;
7599 unsigned long lit = 0L;
7601 result = IC_RESULT(ic);
7602 right = IC_RIGHT(ic) ;
7604 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7606 /* if they are the same */
7607 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7610 aopOp(right,ic,FALSE);
7611 aopOp(result,ic,TRUE);
7613 /* if they are the same registers */
7614 if (sameRegs(AOP(right),AOP(result)))
7617 /* if the result is a bit */
7618 if (AOP_TYPE(result) == AOP_CRY) {
7620 /* if the right size is a literal then
7621 we know what the value is */
7622 if (AOP_TYPE(right) == AOP_LIT) {
7623 if (((int) operandLitValue(right)))
7624 emitcode("bsf","(%s >> 3),(%s & 7)",
7625 AOP(result)->aopu.aop_dir,
7626 AOP(result)->aopu.aop_dir);
7628 emitcode("bcf","(%s >> 3),(%s & 7)",
7629 AOP(result)->aopu.aop_dir,
7630 AOP(result)->aopu.aop_dir);
7634 /* the right is also a bit variable */
7635 if (AOP_TYPE(right) == AOP_CRY) {
7636 emitcode("bcf","(%s >> 3),(%s & 7)",
7637 AOP(result)->aopu.aop_dir,
7638 AOP(result)->aopu.aop_dir);
7639 emitcode("btfsc","(%s >> 3),(%s & 7)",
7640 AOP(right)->aopu.aop_dir,
7641 AOP(right)->aopu.aop_dir);
7642 emitcode("bsf","(%s >> 3),(%s & 7)",
7643 AOP(result)->aopu.aop_dir,
7644 AOP(result)->aopu.aop_dir);
7650 aopPut(AOP(result),"a",0);
7654 /* bit variables done */
7656 size = AOP_SIZE(result);
7658 if(AOP_TYPE(right) == AOP_LIT)
7659 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7660 if((AOP_TYPE(result) != AOP_REG) &&
7661 (AOP_TYPE(right) == AOP_LIT) &&
7662 !IS_FLOAT(operandType(right)) &&
7666 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7667 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7669 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7670 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7675 if(AOP_TYPE(right) == AOP_LIT)
7676 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7678 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7680 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7686 freeAsmop (right,NULL,ic,FALSE);
7687 freeAsmop (result,NULL,ic,TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genJumpTab - genrates code for jump table */
7692 /*-----------------------------------------------------------------*/
7693 static void genJumpTab (iCode *ic)
7698 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7700 aopOp(IC_JTCOND(ic),ic,FALSE);
7701 /* get the condition into accumulator */
7702 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7704 /* multiply by three */
7705 emitcode("add","a,acc");
7706 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7707 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7709 jtab = newiTempLabel(NULL);
7710 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
7711 emitcode("jmp","@a+dptr");
7712 emitcode("","%05d_DS_:",jtab->key+100);
7713 /* now generate the jump labels */
7714 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7715 jtab = setNextItem(IC_JTLABELS(ic)))
7716 emitcode("ljmp","%05d_DS_",jtab->key+100);
7720 /*-----------------------------------------------------------------*/
7721 /* genMixedOperation - gen code for operators between mixed types */
7722 /*-----------------------------------------------------------------*/
7724 TSD - Written for the PIC port - but this unfortunately is buggy.
7725 This routine is good in that it is able to efficiently promote
7726 types to different (larger) sizes. Unfortunately, the temporary
7727 variables that are optimized out by this routine are sometimes
7728 used in other places. So until I know how to really parse the
7729 iCode tree, I'm going to not be using this routine :(.
7731 static int genMixedOperation (iCode *ic)
7734 operand *result = IC_RESULT(ic);
7735 sym_link *ctype = operandType(IC_LEFT(ic));
7736 operand *right = IC_RIGHT(ic);
7742 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
7744 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
7750 nextright = IC_RIGHT(nextic);
7751 nextleft = IC_LEFT(nextic);
7752 nextresult = IC_RESULT(nextic);
7754 aopOp(right,ic,FALSE);
7755 aopOp(result,ic,FALSE);
7756 aopOp(nextright, nextic, FALSE);
7757 aopOp(nextleft, nextic, FALSE);
7758 aopOp(nextresult, nextic, FALSE);
7760 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
7766 emitcode(";remove right +","");
7768 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
7774 emitcode(";remove left +","");
7778 big = AOP_SIZE(nextleft);
7779 small = AOP_SIZE(nextright);
7781 switch(nextic->op) {
7784 emitcode(";optimize a +","");
7785 /* if unsigned or not an integral type */
7786 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
7787 emitcode(";add a bit to something","");
7790 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
7792 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
7793 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
7794 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
7796 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
7804 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
7805 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7806 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7809 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7810 emitcode("skpnc","");
7811 emitcode("btfsc","(%s >> 3), (%s & 7)",
7812 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
7813 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
7814 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7815 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
7818 emitcode("rlf","known_zero,w");
7825 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
7826 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7827 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7829 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7839 freeAsmop(right,NULL,ic,TRUE);
7840 freeAsmop(result,NULL,ic,TRUE);
7841 freeAsmop(nextright,NULL,ic,TRUE);
7842 freeAsmop(nextleft,NULL,ic,TRUE);
7844 nextic->generated = 1;
7851 /*-----------------------------------------------------------------*/
7852 /* genCast - gen code for casting */
7853 /*-----------------------------------------------------------------*/
7854 static void genCast (iCode *ic)
7856 operand *result = IC_RESULT(ic);
7857 sym_link *ctype = operandType(IC_LEFT(ic));
7858 operand *right = IC_RIGHT(ic);
7861 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
7862 /* if they are equivalent then do nothing */
7863 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7866 aopOp(right,ic,FALSE) ;
7867 aopOp(result,ic,FALSE);
7869 /* if the result is a bit */
7870 if (AOP_TYPE(result) == AOP_CRY) {
7871 /* if the right size is a literal then
7872 we know what the value is */
7873 if (AOP_TYPE(right) == AOP_LIT) {
7874 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
7875 if (((int) operandLitValue(right)))
7876 emitcode("bsf","(%s >> 3), (%s & 7)",
7877 AOP(result)->aopu.aop_dir,
7878 AOP(result)->aopu.aop_dir);
7880 emitcode("bcf","(%s >> 3), (%s & 7)",
7881 AOP(result)->aopu.aop_dir,
7882 AOP(result)->aopu.aop_dir);
7887 /* the right is also a bit variable */
7888 if (AOP_TYPE(right) == AOP_CRY) {
7889 emitcode("clrc","");
7890 emitcode("btfsc","(%s >> 3), (%s & 7)",
7891 AOP(right)->aopu.aop_dir,
7892 AOP(right)->aopu.aop_dir);
7893 aopPut(AOP(result),"c",0);
7899 aopPut(AOP(result),"a",0);
7903 /* if they are the same size : or less */
7904 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7906 /* if they are in the same place */
7907 if (sameRegs(AOP(right),AOP(result)))
7910 /* if they in different places then copy */
7911 size = AOP_SIZE(result);
7915 aopGet(AOP(right),offset,FALSE,FALSE),
7923 /* if the result is of type pointer */
7924 if (IS_PTR(ctype)) {
7927 sym_link *type = operandType(right);
7928 sym_link *etype = getSpec(type);
7930 /* pointer to generic pointer */
7931 if (IS_GENPTR(ctype)) {
7935 p_type = DCL_TYPE(type);
7937 /* we have to go by the storage class */
7938 p_type = PTR_TYPE(SPEC_OCLS(etype));
7940 /* if (SPEC_OCLS(etype)->codesp ) */
7941 /* p_type = CPOINTER ; */
7943 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7944 /* p_type = FPOINTER ; */
7946 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7947 /* p_type = PPOINTER; */
7949 /* if (SPEC_OCLS(etype) == idata ) */
7950 /* p_type = IPOINTER ; */
7952 /* p_type = POINTER ; */
7955 /* the first two bytes are known */
7956 size = GPTRSIZE - 1;
7960 aopGet(AOP(right),offset,FALSE,FALSE),
7964 /* the last byte depending on type */
7981 /* this should never happen */
7982 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7983 "got unknown pointer type");
7986 aopPut(AOP(result),l, GPTRSIZE - 1);
7990 /* just copy the pointers */
7991 size = AOP_SIZE(result);
7995 aopGet(AOP(right),offset,FALSE,FALSE),
8003 if (AOP_TYPE(right) == AOP_CRY) {
8005 size = AOP_SIZE(right);
8007 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8008 emitcode("btfsc","(%s >> 3), (%s & 7)",
8009 AOP(right)->aopu.aop_dir,
8010 AOP(right)->aopu.aop_dir);
8011 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8013 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8018 /* so we now know that the size of destination is greater
8019 than the size of the source.
8020 Now, if the next iCode is an operator then we might be
8021 able to optimize the operation without performing a cast.
8023 if(genMixedOperation(ic))
8027 /* we move to result for the size of source */
8028 size = AOP_SIZE(right);
8031 emitcode(";","%d",__LINE__);
8033 aopGet(AOP(right),offset,FALSE,FALSE),
8038 /* now depending on the sign of the destination */
8039 size = AOP_SIZE(result) - AOP_SIZE(right);
8040 /* if unsigned or not an integral type */
8041 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8043 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8045 /* we need to extend the sign :{ */
8046 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8049 emitcode("clrw","");
8050 emitcode("btfsc","(%s >> 3), (%s & 7)",
8051 AOP(right)->aopu.aop_dir,
8052 AOP(right)->aopu.aop_dir);
8053 emitcode("movlw","0xff");
8055 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8056 // aopPut(AOP(result),"a",offset++);
8061 /* we are done hurray !!!! */
8064 freeAsmop(right,NULL,ic,TRUE);
8065 freeAsmop(result,NULL,ic,TRUE);
8069 /*-----------------------------------------------------------------*/
8070 /* genDjnz - generate decrement & jump if not zero instrucion */
8071 /*-----------------------------------------------------------------*/
8072 static int genDjnz (iCode *ic, iCode *ifx)
8075 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8080 /* if the if condition has a false label
8081 then we cannot save */
8085 /* if the minus is not of the form
8087 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8088 !IS_OP_LITERAL(IC_RIGHT(ic)))
8091 if (operandLitValue(IC_RIGHT(ic)) != 1)
8094 /* if the size of this greater than one then no
8096 if (getSize(operandType(IC_RESULT(ic))) > 1)
8099 /* otherwise we can save BIG */
8100 lbl = newiTempLabel(NULL);
8101 lbl1= newiTempLabel(NULL);
8103 aopOp(IC_RESULT(ic),ic,FALSE);
8105 if (IS_AOP_PREG(IC_RESULT(ic))) {
8106 emitcode("dec","%s",
8107 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8108 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8109 emitcode("jnz","%05d_DS_",lbl->key+100);
8111 emitcode ("djnz","%s,%05d_DS_",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
8114 emitcode ("sjmp","%05d_DS_",lbl1->key+100);
8115 emitcode ("","%05d_DS_:",lbl->key+100);
8116 emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
8117 emitcode ("","%05d_DS_:",lbl1->key+100);
8119 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8124 /*-----------------------------------------------------------------*/
8125 /* genReceive - generate code for a receive iCode */
8126 /*-----------------------------------------------------------------*/
8127 static void genReceive (iCode *ic)
8129 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8131 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8132 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8133 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8135 int size = getSize(operandType(IC_RESULT(ic)));
8136 int offset = fReturnSize - size;
8138 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8139 fReturn[fReturnSize - offset - 1] : "acc"));
8142 aopOp(IC_RESULT(ic),ic,FALSE);
8143 size = AOP_SIZE(IC_RESULT(ic));
8146 emitcode ("pop","acc");
8147 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8152 aopOp(IC_RESULT(ic),ic,FALSE);
8154 assignResultValue(IC_RESULT(ic));
8157 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8160 /*-----------------------------------------------------------------*/
8161 /* genpic14Code - generate code for pic14 based controllers */
8162 /*-----------------------------------------------------------------*/
8163 void genpic14Code (iCode *lic)
8168 lineHead = lineCurr = NULL;
8170 /* if debug information required */
8171 /* if (options.debug && currFunc) { */
8173 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8175 if (IS_STATIC(currFunc->etype))
8176 emitcode("",";F%s_DS_%s_DS_0_DS_0 %d",moduleName,currFunc->name,__LINE__);
8178 emitcode("",";G_DS_%s_DS_0_DS_0 %d",currFunc->name,__LINE__);
8183 for (ic = lic ; ic ; ic = ic->next ) {
8185 DEBUGemitcode(";ic","");
8186 if ( cln != ic->lineno ) {
8187 if ( options.debug ) {
8189 emitcode("",";C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
8190 ic->filename,ic->lineno,
8191 ic->level,ic->block);
8194 emitcode(";","%s %d",ic->filename,ic->lineno);
8197 /* if the result is marked as
8198 spilt and rematerializable or code for
8199 this has already been generated then
8201 if (resultRemat(ic) || ic->generated )
8204 /* depending on the operation */
8223 /* IPOP happens only when trying to restore a
8224 spilt live range, if there is an ifx statement
8225 following this pop then the if statement might
8226 be using some of the registers being popped which
8227 would destory the contents of the register so
8228 we need to check for this condition and handle it */
8230 ic->next->op == IFX &&
8231 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8232 genIfx (ic->next,ic);
8250 genEndFunction (ic);
8270 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8287 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8291 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8298 /* note these two are xlated by algebraic equivalence
8299 during parsing SDCC.y */
8300 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8301 "got '>=' or '<=' shouldn't have come here");
8305 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8317 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8321 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8325 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8352 case GET_VALUE_AT_ADDRESS:
8357 if (POINTER_SET(ic))
8384 addSet(&_G.sendSet,ic);
8389 /* piCode(ic,stdout); */
8395 /* now we are ready to call the
8396 peep hole optimizer */
8397 if (!options.nopeep) {
8398 printf("peep hole optimizing\n");
8399 peepHole (&lineHead);
8401 /* now do the actual printing */
8402 printLine (lineHead,codeOutFile);