PIC port pcode. Added pcode peephole feature.
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
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)
8   
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
12   later version.
13   
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.
18   
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.
22   
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!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #if defined(_MSC_VER)
40 #define __FUNCTION__            __FILE__
41 #endif
42
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
45 #else
46 #ifdef HAVE_ENDIAN_H
47 #include <endian.h>
48 #else
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62 //char *aopLiteral (value *val, int offset);
63 unsigned int pic14aopLiteral (value *val, int offset);
64
65 /* this is the down and dirty file with all kinds of 
66    kludgy & hacky stuff. This is what it is all about
67    CODE GENERATION for a specific MCU . some of the
68    routines may be reusable, will have to see */
69
70 static char *zero = "#0x00";
71 static char *one  = "#0x01";
72 static char *spname = "sp";
73
74 char *fReturnpic14[] = {"FSR","dph","b","a" };
75 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
76 static unsigned fReturnSize = 4; /* shared with ralloc.c */
77 static char **fReturn = fReturnpic14;
78
79 static char *accUse[] = {"a","b"};
80
81 //static short rbank = -1;
82
83 static struct {
84     short r0Pushed;
85     short r1Pushed;
86     short accInUse;
87     short inLine;
88     short debugLine;
89     short nRegsSaved;
90     set *sendSet;
91 } _G;
92
93 extern int pic14_ptrRegReq ;
94 extern int pic14_nRegs;
95 extern FILE *codeOutFile;
96 static void saverbank (int, iCode *,bool);
97 #define RESULTONSTACK(x) \
98                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
99                          IC_RESULT(x)->aop->type == AOP_STK )
100
101 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
102 #define CLRC    emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
103
104 #define BIT_NUMBER(x) (x & 7)
105 #define BIT_REGISTER(x) (x>>3)
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
111 0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119
120
121 #define FUNCTION_LABEL_INC  20
122 static int labelOffset=0;
123 static int debug_verbose=1;
124
125 static  pBlock *pb;
126
127 /*-----------------------------------------------------------------*/
128 /* Macros for emitting instructions                                */
129 /*-----------------------------------------------------------------*/
130
131 #define emitSKPC    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPNC   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
133 #define emitSKPZ    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitSKPNZ   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRZ    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
136 #define emitCLRC    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
137 #define emitSETZ    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
138 #define emitSETC    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
139
140 //#define emitSKPC    emitcode("btfss","status,c")
141 //#define emitSKPNC   emitcode("btfsc","status,c")
142 //#define emitSKPZ    emitcode("btfss","status,z")
143 //#define emitSKPNZ   emitcode("btfsc","status,z")
144
145 /*-----------------------------------------------------------------*/
146 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
147 /*                 exponent of 2 is returned, otherwise -1 is      */
148 /*                 returned.                                       */
149 /* note that this is similar to the function `powof2' in SDCCsymt  */
150 /* if(n == 2^y)                                                    */
151 /*   return y;                                                     */
152 /* return -1;                                                      */
153 /*-----------------------------------------------------------------*/
154 static int my_powof2 (unsigned long num)
155 {
156   if(num) {
157     if( (num & (num-1)) == 0) {
158       int nshifts = -1;
159       while(num) {
160         num>>=1;
161         nshifts++;
162       }
163       return nshifts;
164     }
165   }
166
167   return -1;
168 }
169
170 static void emitpLabel(int key)
171 {
172   addpCode2pBlock(pb,newpCodeLabel(key));
173 }
174
175 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
176 {
177
178   addpCode2pBlock(pb,newpCode(poc,pcop));
179
180 }
181 /*-----------------------------------------------------------------*/
182 /* emitcode - writes the code into a file : for now it is simple    */
183 /*-----------------------------------------------------------------*/
184 static void emitcode (char *inst,char *fmt, ...)
185 {
186     va_list ap;
187     char lb[MAX_INLINEASM];  
188     char *lbp = lb;
189
190     va_start(ap,fmt);   
191
192     if (inst && *inst) {
193         if (fmt && *fmt)
194             sprintf(lb,"%s\t",inst);
195         else
196             sprintf(lb,"%s",inst);
197         vsprintf(lb+(strlen(lb)),fmt,ap);
198     }  else
199         vsprintf(lb,fmt,ap);
200
201     while (isspace(*lbp)) lbp++;
202
203     if (lbp && *lbp) 
204         lineCurr = (lineCurr ?
205                     connectLine(lineCurr,newLineNode(lb)) :
206                     (lineHead = newLineNode(lb)));
207     lineCurr->isInline = _G.inLine;
208     lineCurr->isDebug  = _G.debugLine;
209
210     addpCode2pBlock(pb,newpCodeCharP(lb));
211
212     va_end(ap);
213 }
214
215 static void DEBUGemitcode (char *inst,char *fmt, ...)
216 {
217     va_list ap;
218     char lb[MAX_INLINEASM];  
219     char *lbp = lb;
220
221     if(!debug_verbose)
222       return;
223
224     va_start(ap,fmt);   
225
226     if (inst && *inst) {
227         if (fmt && *fmt)
228             sprintf(lb,"%s\t",inst);
229         else
230             sprintf(lb,"%s",inst);
231         vsprintf(lb+(strlen(lb)),fmt,ap);
232     }  else
233         vsprintf(lb,fmt,ap);
234
235     while (isspace(*lbp)) lbp++;
236
237     if (lbp && *lbp) 
238         lineCurr = (lineCurr ?
239                     connectLine(lineCurr,newLineNode(lb)) :
240                     (lineHead = newLineNode(lb)));
241     lineCurr->isInline = _G.inLine;
242     lineCurr->isDebug  = _G.debugLine;
243
244     addpCode2pBlock(pb,newpCodeCharP(lb));
245
246     va_end(ap);
247 }
248
249
250 /*-----------------------------------------------------------------*/
251 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
252 /*-----------------------------------------------------------------*/
253 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
254 {
255     bool r0iu = FALSE , r1iu = FALSE;
256     bool r0ou = FALSE , r1ou = FALSE;
257
258     /* the logic: if r0 & r1 used in the instruction
259     then we are in trouble otherwise */
260
261     /* first check if r0 & r1 are used by this
262     instruction, in which case we are in trouble */
263     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
264         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
265     {
266         goto endOfWorld;      
267     }
268
269     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
270     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
271
272     /* if no usage of r0 then return it */
273     if (!r0iu && !r0ou) {
274         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
275         (*aopp)->type = AOP_R0;
276         
277         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
278     }
279
280     /* if no usage of r1 then return it */
281     if (!r1iu && !r1ou) {
282         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
283         (*aopp)->type = AOP_R1;
284
285         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
286     }    
287
288     /* now we know they both have usage */
289     /* if r0 not used in this instruction */
290     if (!r0iu) {
291         /* push it if not already pushed */
292         if (!_G.r0Pushed) {
293             emitcode ("push","%s",
294                       pic14_regWithIdx(R0_IDX)->dname);
295             _G.r0Pushed++ ;
296         }
297         
298         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
299         (*aopp)->type = AOP_R0;
300
301         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
302     }
303
304     /* if r1 not used then */
305
306     if (!r1iu) {
307         /* push it if not already pushed */
308         if (!_G.r1Pushed) {
309             emitcode ("push","%s",
310                       pic14_regWithIdx(R1_IDX)->dname);
311             _G.r1Pushed++ ;
312         }
313         
314         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
315         (*aopp)->type = AOP_R1;
316         return pic14_regWithIdx(R1_IDX);
317     }
318
319 endOfWorld :
320     /* I said end of world but not quite end of world yet */
321     /* if this is a result then we can push it on the stack*/
322     if (result) {
323         (*aopp)->type = AOP_STK;    
324         return NULL;
325     }
326
327     piCode(ic,stdout);
328     /* other wise this is true end of the world */
329     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
330            "getFreePtr should never reach here");
331     exit(0);
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* newAsmop - creates a new asmOp                                  */
336 /*-----------------------------------------------------------------*/
337 static asmop *newAsmop (short type)
338 {
339     asmop *aop;
340
341     aop = Safe_calloc(1,sizeof(asmop));
342     aop->type = type;
343     return aop;
344 }
345
346 static void genSetDPTR(int n)
347 {
348     if (!n)
349     {
350         emitcode(";", "Select standard DPTR");
351         emitcode("mov", "dps, #0x00");
352     }
353     else
354     {
355         emitcode(";", "Select alternate DPTR");
356         emitcode("mov", "dps, #0x01");
357     }
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* pointerCode - returns the code for a pointer type               */
362 /*-----------------------------------------------------------------*/
363 static int pointerCode (sym_link *etype)
364 {
365
366     return PTR_TYPE(SPEC_OCLS(etype));
367
368 }
369
370 /*-----------------------------------------------------------------*/
371 /* aopForSym - for a true symbol                                   */
372 /*-----------------------------------------------------------------*/
373 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
374 {
375     asmop *aop;
376     memmap *space= SPEC_OCLS(sym->etype);
377
378     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
379     /* if already has one */
380     if (sym->aop)
381         return sym->aop;
382
383     /* assign depending on the storage class */
384     /* if it is on the stack or indirectly addressable */
385     /* space we need to assign either r0 or r1 to it   */    
386     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
387         sym->aop = aop = newAsmop(0);
388         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
389         aop->size = getSize(sym->type);
390
391         /* now assign the address of the variable to 
392         the pointer register */
393         if (aop->type != AOP_STK) {
394
395             if (sym->onStack) {
396                     if ( _G.accInUse )
397                         emitcode("push","acc");
398
399                     emitcode("mov","a,_bp");
400                     emitcode("add","a,#0x%02x",
401                              ((sym->stack < 0) ?
402                               ((char)(sym->stack - _G.nRegsSaved )) :
403                               ((char)sym->stack)) & 0xff);
404                     emitcode("mov","%s,a",
405                              aop->aopu.aop_ptr->name);
406
407                     if ( _G.accInUse )
408                         emitcode("pop","acc");
409             } else
410                 emitcode("mov","%s,#%s",
411                          aop->aopu.aop_ptr->name,
412                          sym->rname);
413             aop->paged = space->paged;
414         } else
415             aop->aopu.aop_stk = sym->stack;
416         return aop;
417     }
418     
419     if (sym->onStack && options.stack10bit)
420     {
421         /* It's on the 10 bit stack, which is located in
422          * far data space.
423          */
424          
425       //DEBUGemitcode(";","%d",__LINE__);
426
427         if ( _G.accInUse )
428                 emitcode("push","acc");
429
430         emitcode("mov","a,_bp");
431         emitcode("add","a,#0x%02x",
432                  ((sym->stack < 0) ?
433                    ((char)(sym->stack - _G.nRegsSaved )) :
434                    ((char)sym->stack)) & 0xff);
435         
436         genSetDPTR(1);
437         emitcode ("mov","dpx1,#0x40");
438         emitcode ("mov","dph1,#0x00");
439         emitcode ("mov","dpl1, a");
440         genSetDPTR(0);
441         
442         if ( _G.accInUse )
443             emitcode("pop","acc");
444             
445         sym->aop = aop = newAsmop(AOP_DPTR2);
446         aop->size = getSize(sym->type); 
447         return aop;
448     }
449
450     //DEBUGemitcode(";","%d",__LINE__);
451     /* if in bit space */
452     if (IN_BITSPACE(space)) {
453         sym->aop = aop = newAsmop (AOP_CRY);
454         aop->aopu.aop_dir = sym->rname ;
455         aop->size = getSize(sym->type);
456         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
457         return aop;
458     }
459     /* if it is in direct space */
460     if (IN_DIRSPACE(space)) {
461         sym->aop = aop = newAsmop (AOP_DIR);
462         aop->aopu.aop_dir = sym->rname ;
463         aop->size = getSize(sym->type);
464         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
465         return aop;
466     }
467
468     /* special case for a function */
469     if (IS_FUNC(sym->type)) {   
470         sym->aop = aop = newAsmop(AOP_IMMD);    
471         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
472         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
473         strcpy(aop->aopu.aop_immd,sym->rname);
474         aop->size = FPTRSIZE; 
475         return aop;
476     }
477
478
479     /* only remaining is far space */
480     /* in which case DPTR gets the address */
481     sym->aop = aop = newAsmop(AOP_DPTR);
482     emitcode ("mov","dptr,#%s", sym->rname);
483     aop->size = getSize(sym->type);
484
485     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
486     /* if it is in code space */
487     if (IN_CODESPACE(space))
488         aop->code = 1;
489
490     return aop;     
491 }
492
493 /*-----------------------------------------------------------------*/
494 /* aopForRemat - rematerialzes an object                           */
495 /*-----------------------------------------------------------------*/
496 static asmop *aopForRemat (symbol *sym)
497 {
498     iCode *ic = sym->rematiCode;
499     asmop *aop = newAsmop(AOP_IMMD);
500     int val = 0;
501     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
502     for (;;) {
503         if (ic->op == '+')
504             val += operandLitValue(IC_RIGHT(ic));
505         else if (ic->op == '-')
506             val -= operandLitValue(IC_RIGHT(ic));
507         else
508             break;
509         
510         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
511     }
512
513     if (val)
514         sprintf(buffer,"(%s %c 0x%04x)",
515                 OP_SYMBOL(IC_LEFT(ic))->rname, 
516                 val >= 0 ? '+' : '-',
517                 abs(val) & 0xffff);
518     else
519         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
520
521     //DEBUGemitcode(";","%s",buffer);
522     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
523     strcpy(aop->aopu.aop_immd,buffer);    
524     return aop;        
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* regsInCommon - two operands have some registers in common       */
529 /*-----------------------------------------------------------------*/
530 static bool regsInCommon (operand *op1, operand *op2)
531 {
532     symbol *sym1, *sym2;
533     int i;
534
535     /* if they have registers in common */
536     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
537         return FALSE ;
538
539     sym1 = OP_SYMBOL(op1);
540     sym2 = OP_SYMBOL(op2);
541
542     if (sym1->nRegs == 0 || sym2->nRegs == 0)
543         return FALSE ;
544
545     for (i = 0 ; i < sym1->nRegs ; i++) {
546         int j;
547         if (!sym1->regs[i])
548             continue ;
549
550         for (j = 0 ; j < sym2->nRegs ;j++ ) {
551             if (!sym2->regs[j])
552                 continue ;
553
554             if (sym2->regs[j] == sym1->regs[i])
555                 return TRUE ;
556         }
557     }
558
559     return FALSE ;
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* operandsEqu - equivalent                                        */
564 /*-----------------------------------------------------------------*/
565 static bool operandsEqu ( operand *op1, operand *op2)
566 {
567     symbol *sym1, *sym2;
568
569     /* if they not symbols */
570     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
571         return FALSE;
572
573     sym1 = OP_SYMBOL(op1);
574     sym2 = OP_SYMBOL(op2);
575
576     /* if both are itemps & one is spilt
577        and the other is not then false */
578     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
579         sym1->isspilt != sym2->isspilt )
580         return FALSE ;
581
582     /* if they are the same */
583     if (sym1 == sym2)
584         return TRUE ;
585
586     if (strcmp(sym1->rname,sym2->rname) == 0)
587         return TRUE;
588
589
590     /* if left is a tmp & right is not */
591     if (IS_ITEMP(op1)  && 
592         !IS_ITEMP(op2) &&
593         sym1->isspilt  &&
594         (sym1->usl.spillLoc == sym2))
595         return TRUE;
596
597     if (IS_ITEMP(op2)  && 
598         !IS_ITEMP(op1) &&
599         sym2->isspilt  &&
600         sym1->level > 0 &&
601         (sym2->usl.spillLoc == sym1))
602         return TRUE ;
603
604     return FALSE ;
605 }
606
607 /*-----------------------------------------------------------------*/
608 /* sameRegs - two asmops have the same registers                   */
609 /*-----------------------------------------------------------------*/
610 static bool sameRegs (asmop *aop1, asmop *aop2 )
611 {
612     int i;
613
614     if (aop1 == aop2)
615         return TRUE ;
616
617     if (aop1->type != AOP_REG ||
618         aop2->type != AOP_REG )
619         return FALSE ;
620
621     if (aop1->size != aop2->size )
622         return FALSE ;
623
624     for (i = 0 ; i < aop1->size ; i++ )
625         if (aop1->aopu.aop_reg[i] !=
626             aop2->aopu.aop_reg[i] )
627             return FALSE ;
628
629     return TRUE ;
630 }
631
632 /*-----------------------------------------------------------------*/
633 /* aopOp - allocates an asmop for an operand  :                    */
634 /*-----------------------------------------------------------------*/
635 static void aopOp (operand *op, iCode *ic, bool result)
636 {
637     asmop *aop;
638     symbol *sym;
639     int i;
640
641     if (!op)
642         return ;
643
644     DEBUGemitcode(";","%d",__LINE__);
645     /* if this a literal */
646     if (IS_OP_LITERAL(op)) {
647       DEBUGemitcode(";","%d",__LINE__);
648         op->aop = aop = newAsmop(AOP_LIT);
649         aop->aopu.aop_lit = op->operand.valOperand;
650         aop->size = getSize(operandType(op));
651         return;
652     }
653
654     /* if already has a asmop then continue */
655     if (op->aop)
656         return ;
657
658     /* if the underlying symbol has a aop */
659     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
660       DEBUGemitcode(";","%d",__LINE__);
661         op->aop = OP_SYMBOL(op)->aop;
662         return;
663     }
664
665     /* if this is a true symbol */
666     if (IS_TRUE_SYMOP(op)) {    
667       DEBUGemitcode(";","%d",__LINE__);
668         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
669         return ;
670     }
671
672     /* this is a temporary : this has
673     only four choices :
674     a) register
675     b) spillocation
676     c) rematerialize 
677     d) conditional   
678     e) can be a return use only */
679
680     sym = OP_SYMBOL(op);
681
682
683     /* if the type is a conditional */
684     if (sym->regType == REG_CND) {
685       DEBUGemitcode(";","%d",__LINE__);
686         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
687         aop->size = 0;
688         return;
689     }
690
691     /* if it is spilt then two situations
692     a) is rematerialize 
693     b) has a spill location */
694     if (sym->isspilt || sym->nRegs == 0) {
695
696       DEBUGemitcode(";","%d",__LINE__);
697         /* rematerialize it NOW */
698         if (sym->remat) {
699             sym->aop = op->aop = aop =
700                                       aopForRemat (sym);
701             aop->size = getSize(sym->type);
702             DEBUGemitcode(";","%d",__LINE__);
703             return;
704         }
705
706         if (sym->accuse) {
707             int i;
708             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
709             aop->size = getSize(sym->type);
710             for ( i = 0 ; i < 2 ; i++ )
711                 aop->aopu.aop_str[i] = accUse[i];
712             DEBUGemitcode(";","%d",__LINE__);
713             return;  
714         }
715
716         if (sym->ruonly ) {
717             int i;
718             aop = op->aop = sym->aop = newAsmop(AOP_STR);
719             aop->size = getSize(sym->type);
720             for ( i = 0 ; i < fReturnSize ; i++ )
721               aop->aopu.aop_str[i] = fReturn[i];
722             DEBUGemitcode(";","%d",__LINE__);
723             return;
724         }
725
726         /* else spill location  */
727         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
728         sym->aop = op->aop = aop = 
729                                   aopForSym(ic,sym->usl.spillLoc,result);
730         aop->size = getSize(sym->type);
731         return;
732     }
733
734     /* must be in a register */
735     sym->aop = op->aop = aop = newAsmop(AOP_REG);
736     aop->size = sym->nRegs;
737     for ( i = 0 ; i < sym->nRegs ;i++)
738         aop->aopu.aop_reg[i] = sym->regs[i];
739 }
740
741 /*-----------------------------------------------------------------*/
742 /* freeAsmop - free up the asmop given to an operand               */
743 /*----------------------------------------------------------------*/
744 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
745 {   
746     asmop *aop ;
747
748     if (!op)
749         aop = aaop;
750     else 
751         aop = op->aop;
752
753     if (!aop)
754         return ;
755
756     if (aop->freed)
757         goto dealloc; 
758
759     aop->freed = 1;
760
761     /* depending on the asmop type only three cases need work AOP_RO
762        , AOP_R1 && AOP_STK */
763     switch (aop->type) {
764         case AOP_R0 :
765             if (_G.r0Pushed ) {
766                 if (pop) {
767                     emitcode ("pop","ar0");     
768                     _G.r0Pushed--;
769                 }
770             }
771             bitVectUnSetBit(ic->rUsed,R0_IDX);
772             break;
773
774         case AOP_R1 :
775             if (_G.r1Pushed ) {
776                 if (pop) {
777                     emitcode ("pop","ar1");
778                     _G.r1Pushed--;
779                 }
780             }
781             bitVectUnSetBit(ic->rUsed,R1_IDX);          
782             break;
783
784         case AOP_STK :
785         {
786             int sz = aop->size;    
787             int stk = aop->aopu.aop_stk + aop->size;
788             bitVectUnSetBit(ic->rUsed,R0_IDX);
789             bitVectUnSetBit(ic->rUsed,R1_IDX);          
790
791             getFreePtr(ic,&aop,FALSE);
792             
793             if (options.stack10bit)
794             {
795                 /* I'm not sure what to do here yet... */
796                 /* #STUB */
797                 fprintf(stderr, 
798                         "*** Warning: probably generating bad code for "
799                         "10 bit stack mode.\n");
800             }
801             
802             if (stk) {
803                 emitcode ("mov","a,_bp");
804                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
805                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
806             } else {
807                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
808             }
809
810             while (sz--) {
811                 emitcode("pop","acc");
812                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
813                 if (!sz) break;
814                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
815             }
816             op->aop = aop;
817             freeAsmop(op,NULL,ic,TRUE);
818             if (_G.r0Pushed) {
819                 emitcode("pop","ar0");
820                 _G.r0Pushed--;
821             }
822
823             if (_G.r1Pushed) {
824                 emitcode("pop","ar1");
825                 _G.r1Pushed--;
826             }       
827         }
828     }
829
830 dealloc:
831     /* all other cases just dealloc */
832     if (op ) {
833         op->aop = NULL;
834         if (IS_SYMOP(op)) {
835             OP_SYMBOL(op)->aop = NULL;    
836             /* if the symbol has a spill */
837             if (SPIL_LOC(op))
838                 SPIL_LOC(op)->aop = NULL;
839         }
840     }
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* aopGet - for fetching value of the aop                          */
845 /*-----------------------------------------------------------------*/
846 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
847 {
848     char *s = buffer ;
849     char *rs;
850
851     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
852     /* offset is greater than
853     size then zero */
854     if (offset > (aop->size - 1) &&
855         aop->type != AOP_LIT)
856         return zero;
857
858     /* depending on type */
859     switch (aop->type) {
860         
861     case AOP_R0:
862     case AOP_R1:
863         DEBUGemitcode(";","%d",__LINE__);
864         /* if we need to increment it */       
865         while (offset > aop->coff) {        
866             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
867             aop->coff++;
868         }
869         
870         while (offset < aop->coff) {
871             emitcode("dec","%s",aop->aopu.aop_ptr->name);
872             aop->coff--;
873         }
874         
875         aop->coff = offset ;
876         if (aop->paged) {
877             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
878             return (dname ? "acc" : "a");
879         }       
880         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
881         rs = Safe_calloc(1,strlen(s)+1);
882         strcpy(rs,s);   
883         return rs;
884         
885     case AOP_DPTR:
886     case AOP_DPTR2:
887         DEBUGemitcode(";","%d",__LINE__);
888     if (aop->type == AOP_DPTR2)
889     {
890         genSetDPTR(1);
891     }
892     
893         while (offset > aop->coff) {
894             emitcode ("inc","dptr");
895             aop->coff++;
896         }
897         
898         while (offset < aop->coff) {        
899             emitcode("lcall","__decdptr");
900             aop->coff--;
901         }
902         
903         aop->coff = offset;
904         if (aop->code) {
905             emitcode("clr","a");
906             emitcode("movc","a,@a+dptr");
907         }
908     else {
909             emitcode("movx","a,@dptr");
910     }
911             
912     if (aop->type == AOP_DPTR2)
913     {
914         genSetDPTR(0);
915     }
916             
917     return (dname ? "acc" : "a");
918         
919         
920     case AOP_IMMD:
921       DEBUGemitcode(";","%d",__LINE__);
922         if (bit16) 
923             sprintf (s,"%s",aop->aopu.aop_immd);
924         else
925             if (offset) 
926                 sprintf(s,"(%s >> %d)",
927                         aop->aopu.aop_immd,
928                         offset*8);
929             else
930                 sprintf(s,"%s",
931                         aop->aopu.aop_immd);
932         rs = Safe_calloc(1,strlen(s)+1);
933         strcpy(rs,s);   
934         return rs;
935         
936     case AOP_DIR:
937         if (offset)
938             sprintf(s,"(%s + %d)",
939                     aop->aopu.aop_dir,
940                     offset);
941         else
942             sprintf(s,"%s",aop->aopu.aop_dir);
943         rs = Safe_calloc(1,strlen(s)+1);
944         strcpy(rs,s);   
945         return rs;
946         
947     case AOP_REG:
948       DEBUGemitcode(";","%d",__LINE__);
949         if (dname) 
950             return aop->aopu.aop_reg[offset]->dname;
951         else
952             return aop->aopu.aop_reg[offset]->name;
953         
954     case AOP_CRY:
955       emitcode(";","%d",__LINE__);
956       //emitcode("clr","a");
957       //emitcode("mov","c,%s",aop->aopu.aop_dir);
958       //emitcode("rlc","a") ;
959       //return (dname ? "acc" : "a");
960       return aop->aopu.aop_dir;
961         
962     case AOP_ACC:
963         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
964         //if (!offset && dname)
965         //    return "acc";
966         //return aop->aopu.aop_str[offset];
967         return "AOP_accumulator_bug";
968
969     case AOP_LIT:
970         DEBUGemitcode(";","%d",__LINE__);
971         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
972         rs = Safe_calloc(1,strlen(s)+1);
973         strcpy(rs,s);   
974         return rs;
975         
976     case AOP_STR:
977         DEBUGemitcode(";","%d",__LINE__);
978         aop->coff = offset ;
979         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
980             dname)
981             return "acc";
982         
983         return aop->aopu.aop_str[offset];
984         
985     }
986
987     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
988            "aopget got unsupported aop->type");
989     exit(0);
990 }
991
992 /*-----------------------------------------------------------------*/
993 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
994 /*-----------------------------------------------------------------*/
995 static pCodeOp *popGetLabel(unsigned int key)
996 {
997   return newpCodeOpLabel(key+100+labelOffset);
998 }
999
1000 /*-----------------------------------------------------------------*/
1001 /* popCopy - copy a pcode operator                                 */
1002 /*-----------------------------------------------------------------*/
1003 static pCodeOp *popCopy(pCodeOp *pc)
1004 {
1005   pCodeOp *pcop;
1006
1007   pcop = Safe_calloc(1,sizeof(pCodeOp) );
1008   pcop->type = pc->type;
1009   if(!(pcop->name = strdup(pc->name)))
1010     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1011
1012   return pcop;
1013 }
1014
1015 /*-----------------------------------------------------------------*/
1016 /* popCopy - copy a pcode operator                                 */
1017 /*-----------------------------------------------------------------*/
1018 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1019 {
1020   pCodeOp *pcop;
1021
1022   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1023   pcop->type = PO_BIT;
1024   if(!(pcop->name = strdup(pc->name)))
1025     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1026   ((pCodeOpBit *)pcop)->bit = bitval;
1027
1028   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1029
1030   return pcop;
1031 }
1032
1033 /*-----------------------------------------------------------------*/
1034 /* popGet - asm operator to pcode operator conversion              */
1035 /*-----------------------------------------------------------------*/
1036 static pCodeOp *popGetLit(unsigned int lit)
1037 {
1038
1039   return newpCodeOpLit(lit);
1040 }
1041
1042
1043 /*-----------------------------------------------------------------*/
1044 /* popGet - asm operator to pcode operator conversion              */
1045 /*-----------------------------------------------------------------*/
1046 static pCodeOp *popGetWithString(char *str)
1047 {
1048   pCodeOp *pcop;
1049
1050
1051   if(!str) {
1052     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1053     exit (1);
1054   }
1055
1056   pcop = newpCodeOp(str,PO_STR);
1057
1058   return pcop;
1059 }
1060 /*-----------------------------------------------------------------*/
1061 /* popGet - asm operator to pcode operator conversion              */
1062 /*-----------------------------------------------------------------*/
1063 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1064 {
1065     char *s = buffer ;
1066     char *rs;
1067
1068     pCodeOp *pcop;
1069
1070     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1071     /* offset is greater than
1072     size then zero */
1073
1074     if (offset > (aop->size - 1) &&
1075         aop->type != AOP_LIT)
1076       return NULL;  //zero;
1077
1078     /* depending on type */
1079     switch (aop->type) {
1080         
1081     case AOP_R0:
1082     case AOP_R1:
1083     case AOP_DPTR:
1084     case AOP_DPTR2:
1085     case AOP_ACC:
1086         DEBUGemitcode(";8051 legacy","%d",__LINE__);
1087         return NULL;
1088         
1089     case AOP_IMMD:
1090       DEBUGemitcode(";","%d",__LINE__);
1091         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1092         pcop->type = PO_IMMEDIATE;
1093         if (bit16) 
1094             sprintf (s,"%s",aop->aopu.aop_immd);
1095         else
1096             if (offset) 
1097                 sprintf(s,"(%s >> %d)",
1098                         aop->aopu.aop_immd,
1099                         offset*8);
1100             else
1101                 sprintf(s,"%s",
1102                         aop->aopu.aop_immd);
1103         pcop->name = Safe_calloc(1,strlen(s)+1);
1104         strcpy(pcop->name,s);   
1105         return pcop;
1106         
1107     case AOP_DIR:
1108         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1109         pcop->type = PO_DIR;
1110         if (offset)
1111             sprintf(s,"(%s + %d)",
1112                     aop->aopu.aop_dir,
1113                     offset);
1114         else
1115             sprintf(s,"%s",aop->aopu.aop_dir);
1116         pcop->name = Safe_calloc(1,strlen(s)+1);
1117         strcpy(pcop->name,s);   
1118         return pcop;
1119         
1120     case AOP_REG:
1121       DEBUGemitcode(";","%d",__LINE__);
1122       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1123       pcop->type = PO_GPR_REGISTER;
1124       if (dname)
1125         rs = aop->aopu.aop_reg[offset]->dname;
1126       else 
1127         rs = aop->aopu.aop_reg[offset]->name;
1128
1129       DEBUGemitcode(";","%d  %s",__LINE__,rs);
1130       pcop->name = Safe_calloc(1,(strlen(rs)+1));
1131       strcpy(pcop->name,rs);   
1132       return pcop;
1133
1134     case AOP_CRY:
1135       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1136       return pcop;
1137         
1138     case AOP_LIT:
1139       DEBUGemitcode(";","%d",__LINE__);
1140       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1141
1142     case AOP_STR:
1143       DEBUGemitcode(";","%d",__LINE__);
1144
1145       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1146       pcop->type = PO_STR;
1147
1148       //aop->coff = offset ;
1149         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1150           sprintf(s,"%s","acc");
1151         else
1152           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1153         pcop->name = Safe_calloc(1,strlen(s)+1);
1154         strcpy(pcop->name,s);   
1155         return pcop;
1156         
1157     }
1158
1159     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1160            "popGet got unsupported aop->type");
1161     exit(0);
1162 }
1163 /*-----------------------------------------------------------------*/
1164 /* aopPut - puts a string for a aop                                */
1165 /*-----------------------------------------------------------------*/
1166 static void aopPut (asmop *aop, char *s, int offset)
1167 {
1168     char *d = buffer ;
1169     symbol *lbl ;
1170
1171     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1172
1173     if (aop->size && offset > ( aop->size - 1)) {
1174         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1175                "aopPut got offset > aop->size");
1176         exit(0);
1177     }
1178
1179     /* will assign value to value */
1180     /* depending on where it is ofcourse */
1181     switch (aop->type) {
1182     case AOP_DIR:
1183         if (offset)
1184             sprintf(d,"(%s + %d)",
1185                     aop->aopu.aop_dir,offset);
1186         else
1187             sprintf(d,"%s",aop->aopu.aop_dir);
1188         
1189         if (strcmp(d,s)) {
1190           DEBUGemitcode(";","%d",__LINE__);
1191           if(strcmp(s,"W"))
1192             emitcode("movf","%s,w",s);
1193           emitcode("movwf","%s",d);
1194
1195           if(strcmp(s,"W"))
1196             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1197           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1198
1199
1200         }
1201         break;
1202         
1203     case AOP_REG:
1204         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1205             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1206           /*
1207             if (*s == '@'           ||
1208                 strcmp(s,"r0") == 0 ||
1209                 strcmp(s,"r1") == 0 ||
1210                 strcmp(s,"r2") == 0 ||
1211                 strcmp(s,"r3") == 0 ||
1212                 strcmp(s,"r4") == 0 ||
1213                 strcmp(s,"r5") == 0 ||
1214                 strcmp(s,"r6") == 0 || 
1215                 strcmp(s,"r7") == 0 )
1216                 emitcode("mov","%s,%s  ; %d",
1217                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1218             else
1219           */
1220
1221           if(strcmp(s,"W"))
1222             emitcode("movf","%s,w  ; %d",s,__LINE__);
1223
1224           emitcode("movwf","%s",
1225                    aop->aopu.aop_reg[offset]->name);
1226
1227           if(strcmp(s,"W"))
1228             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1229           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1230
1231         }
1232         break;
1233         
1234     case AOP_DPTR:
1235     case AOP_DPTR2:
1236     
1237     if (aop->type == AOP_DPTR2)
1238     {
1239         genSetDPTR(1);
1240     }
1241     
1242         if (aop->code) {
1243             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1244                    "aopPut writting to code space");
1245             exit(0);
1246         }
1247         
1248         while (offset > aop->coff) {
1249             aop->coff++;
1250             emitcode ("inc","dptr");
1251         }
1252         
1253         while (offset < aop->coff) {
1254             aop->coff-- ;
1255             emitcode("lcall","__decdptr");
1256         }
1257         
1258         aop->coff = offset;
1259         
1260         /* if not in accumulater */
1261         MOVA(s);        
1262         
1263         emitcode ("movx","@dptr,a");
1264         
1265     if (aop->type == AOP_DPTR2)
1266     {
1267         genSetDPTR(0);
1268     }
1269         break;
1270         
1271     case AOP_R0:
1272     case AOP_R1:
1273         while (offset > aop->coff) {
1274             aop->coff++;
1275             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1276         }
1277         while (offset < aop->coff) {
1278             aop->coff-- ;
1279             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1280         }
1281         aop->coff = offset;
1282         
1283         if (aop->paged) {
1284             MOVA(s);           
1285             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1286             
1287         } else
1288             if (*s == '@') {
1289                 MOVA(s);
1290                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1291             } else
1292                 if (strcmp(s,"r0") == 0 ||
1293                     strcmp(s,"r1") == 0 ||
1294                     strcmp(s,"r2") == 0 ||
1295                     strcmp(s,"r3") == 0 ||
1296                     strcmp(s,"r4") == 0 ||
1297                     strcmp(s,"r5") == 0 ||
1298                     strcmp(s,"r6") == 0 || 
1299                     strcmp(s,"r7") == 0 ) {
1300                     char buffer[10];
1301                     sprintf(buffer,"a%s",s);
1302                     emitcode("mov","@%s,%s",
1303                              aop->aopu.aop_ptr->name,buffer);
1304                 } else
1305                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1306         
1307         break;
1308         
1309     case AOP_STK:
1310         if (strcmp(s,"a") == 0)
1311             emitcode("push","acc");
1312         else
1313             emitcode("push","%s",s);
1314         
1315         break;
1316         
1317     case AOP_CRY:
1318         /* if bit variable */
1319         if (!aop->aopu.aop_dir) {
1320             emitcode("clr","a");
1321             emitcode("rlc","a");
1322         } else {
1323             if (s == zero) 
1324                 emitcode("clr","%s",aop->aopu.aop_dir);
1325             else
1326                 if (s == one)
1327                     emitcode("setb","%s",aop->aopu.aop_dir);
1328                 else
1329                     if (!strcmp(s,"c"))
1330                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1331                     else {
1332                         lbl = newiTempLabel(NULL);
1333                         
1334                         if (strcmp(s,"a")) {
1335                             MOVA(s);
1336                         }
1337                         emitcode("clr","c");
1338                         emitcode("jz","%05d_DS_",lbl->key+100);
1339                         emitcode("cpl","c");
1340                         emitcode("","%05d_DS_:",lbl->key+100);
1341                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1342                     }
1343         }
1344         break;
1345         
1346     case AOP_STR:
1347         aop->coff = offset;
1348         if (strcmp(aop->aopu.aop_str[offset],s))
1349             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1350         break;
1351         
1352     case AOP_ACC:
1353         aop->coff = offset;
1354         if (!offset && (strcmp(s,"acc") == 0))
1355             break;
1356         
1357         if (strcmp(aop->aopu.aop_str[offset],s))
1358             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1359         break;
1360
1361     default :
1362         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1363                "aopPut got unsupported aop->type");
1364         exit(0);    
1365     }    
1366
1367 }
1368
1369 /*-----------------------------------------------------------------*/
1370 /* reAdjustPreg - points a register back to where it should        */
1371 /*-----------------------------------------------------------------*/
1372 static void reAdjustPreg (asmop *aop)
1373 {
1374     int size ;
1375
1376     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1377     aop->coff = 0;
1378     if ((size = aop->size) <= 1)
1379         return ;
1380     size-- ;
1381     switch (aop->type) {
1382         case AOP_R0 :
1383         case AOP_R1 :
1384             while (size--)
1385                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1386             break;          
1387         case AOP_DPTR :
1388         case AOP_DPTR2:
1389             if (aop->type == AOP_DPTR2)
1390             {
1391                 genSetDPTR(1);
1392             } 
1393             while (size--)
1394             {
1395                 emitcode("lcall","__decdptr");
1396             }
1397                 
1398             if (aop->type == AOP_DPTR2)
1399             {
1400                 genSetDPTR(0);
1401             }                
1402             break;  
1403
1404     }   
1405
1406 }
1407
1408 #define AOP(op) op->aop
1409 #define AOP_TYPE(op) AOP(op)->type
1410 #define AOP_SIZE(op) AOP(op)->size
1411 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1412                        AOP_TYPE(x) == AOP_R0))
1413
1414 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1415                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1416                          AOP(x)->paged)) 
1417
1418 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1419                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1420                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1421
1422 /*-----------------------------------------------------------------*/
1423 /* genNotFloat - generates not for float operations              */
1424 /*-----------------------------------------------------------------*/
1425 static void genNotFloat (operand *op, operand *res)
1426 {
1427     int size, offset;
1428     char *l;
1429     symbol *tlbl ;
1430
1431     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1432     /* we will put 127 in the first byte of 
1433     the result */
1434     aopPut(AOP(res),"#127",0);
1435     size = AOP_SIZE(op) - 1;
1436     offset = 1;
1437
1438     l = aopGet(op->aop,offset++,FALSE,FALSE);
1439     MOVA(l);    
1440
1441     while(size--) {
1442         emitcode("orl","a,%s",
1443                  aopGet(op->aop,
1444                         offset++,FALSE,FALSE));
1445     }
1446     tlbl = newiTempLabel(NULL);
1447
1448     tlbl = newiTempLabel(NULL);
1449     aopPut(res->aop,one,1);
1450     emitcode("jz","%05d_DS_",(tlbl->key+100));
1451     aopPut(res->aop,zero,1);
1452     emitcode("","%05d_DS_:",(tlbl->key+100));
1453
1454     size = res->aop->size - 2;
1455     offset = 2;    
1456     /* put zeros in the rest */
1457     while (size--) 
1458         aopPut(res->aop,zero,offset++);
1459 }
1460
1461 #if 0
1462 /*-----------------------------------------------------------------*/
1463 /* opIsGptr: returns non-zero if the passed operand is             */   
1464 /* a generic pointer type.                                         */
1465 /*-----------------------------------------------------------------*/ 
1466 static int opIsGptr(operand *op)
1467 {
1468     sym_link *type = operandType(op);
1469     
1470     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1471     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1472     {
1473         return 1;
1474     }
1475     return 0;        
1476 }
1477 #endif
1478
1479 /*-----------------------------------------------------------------*/
1480 /* getDataSize - get the operand data size                         */
1481 /*-----------------------------------------------------------------*/
1482 static int getDataSize(operand *op)
1483 {
1484     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1485
1486
1487     return AOP_SIZE(op);
1488
1489     // tsd- in the pic port, the genptr size is 1, so this code here
1490     // fails. ( in the 8051 port, the size was 4).
1491 #if 0
1492     int size;
1493     size = AOP_SIZE(op);
1494     if (size == GPTRSIZE)
1495     {
1496         sym_link *type = operandType(op);
1497         if (IS_GENPTR(type))
1498         {
1499             /* generic pointer; arithmetic operations
1500              * should ignore the high byte (pointer type).
1501              */
1502             size--;
1503     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1504         }
1505     }
1506     return size;
1507 #endif
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* outAcc - output Acc                                             */
1512 /*-----------------------------------------------------------------*/
1513 static void outAcc(operand *result)
1514 {
1515     int size, offset;
1516     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1517     size = getDataSize(result);
1518     if(size){
1519         aopPut(AOP(result),"a",0);
1520         size--;
1521         offset = 1;
1522         /* unsigned or positive */
1523         while(size--){
1524             aopPut(AOP(result),zero,offset++);
1525         }
1526     }
1527 }
1528
1529 /*-----------------------------------------------------------------*/
1530 /* outBitC - output a bit C                                        */
1531 /*-----------------------------------------------------------------*/
1532 static void outBitC(operand *result)
1533 {
1534
1535     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1536     /* if the result is bit */
1537     if (AOP_TYPE(result) == AOP_CRY) 
1538         aopPut(AOP(result),"c",0);
1539     else {
1540         emitcode("clr","a  ; %d", __LINE__);
1541         emitcode("rlc","a");
1542         outAcc(result);
1543     }
1544 }
1545
1546 /*-----------------------------------------------------------------*/
1547 /* toBoolean - emit code for orl a,operator(sizeop)                */
1548 /*-----------------------------------------------------------------*/
1549 static void toBoolean(operand *oper)
1550 {
1551     int size = AOP_SIZE(oper) - 1;
1552     int offset = 1;
1553
1554     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1555
1556     if ( AOP_TYPE(oper) != AOP_ACC) {
1557       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1558       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1559     }
1560     while (size--) {
1561       emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1562       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1563     }
1564 }
1565
1566
1567 /*-----------------------------------------------------------------*/
1568 /* genNot - generate code for ! operation                          */
1569 /*-----------------------------------------------------------------*/
1570 static void genNot (iCode *ic)
1571 {
1572     symbol *tlbl;
1573     sym_link *optype = operandType(IC_LEFT(ic));
1574
1575     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1576     /* assign asmOps to operand & result */
1577     aopOp (IC_LEFT(ic),ic,FALSE);
1578     aopOp (IC_RESULT(ic),ic,TRUE);
1579
1580     /* if in bit space then a special case */
1581     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1582       emitcode("movlw","1<<%s");
1583       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1584       //emitcode("cpl","c"); 
1585       //outBitC(IC_RESULT(ic));
1586       goto release;
1587     }
1588
1589     /* if type float then do float */
1590     if (IS_FLOAT(optype)) {
1591         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1592         goto release;
1593     }
1594
1595     toBoolean(IC_LEFT(ic));
1596
1597     tlbl = newiTempLabel(NULL);
1598     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1599     emitcode("","%05d_DS_:",tlbl->key+100);
1600     outBitC(IC_RESULT(ic));
1601
1602 release:    
1603     /* release the aops */
1604     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1605     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1606 }
1607
1608
1609 /*-----------------------------------------------------------------*/
1610 /* genCpl - generate code for complement                           */
1611 /*-----------------------------------------------------------------*/
1612 static void genCpl (iCode *ic)
1613 {
1614     int offset = 0;
1615     int size ;
1616
1617
1618     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1619     /* assign asmOps to operand & result */
1620     aopOp (IC_LEFT(ic),ic,FALSE);
1621     aopOp (IC_RESULT(ic),ic,TRUE);
1622
1623     /* if both are in bit space then 
1624     a special case */
1625     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1626         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1627
1628         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1629         emitcode("cpl","c"); 
1630         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1631         goto release; 
1632     } 
1633
1634     size = AOP_SIZE(IC_RESULT(ic));
1635     while (size--) {
1636         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1637         MOVA(l);       
1638         emitcode("cpl","a");
1639         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1640     }
1641
1642
1643 release:
1644     /* release the aops */
1645     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1646     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* genUminusFloat - unary minus for floating points                */
1651 /*-----------------------------------------------------------------*/
1652 static void genUminusFloat(operand *op,operand *result)
1653 {
1654     int size ,offset =0 ;
1655     char *l;
1656
1657     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1658     /* for this we just need to flip the 
1659     first it then copy the rest in place */
1660     size = AOP_SIZE(op) - 1;
1661     l = aopGet(AOP(op),3,FALSE,FALSE);
1662
1663     MOVA(l);    
1664
1665     emitcode("cpl","acc.7");
1666     aopPut(AOP(result),"a",3);    
1667
1668     while(size--) {
1669         aopPut(AOP(result),
1670                aopGet(AOP(op),offset,FALSE,FALSE),
1671                offset);
1672         offset++;
1673     }          
1674 }
1675
1676 /*-----------------------------------------------------------------*/
1677 /* genUminus - unary minus code generation                         */
1678 /*-----------------------------------------------------------------*/
1679 static void genUminus (iCode *ic)
1680 {
1681     int offset ,size ;
1682     sym_link *optype, *rtype;
1683
1684
1685     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1686     /* assign asmops */
1687     aopOp(IC_LEFT(ic),ic,FALSE);
1688     aopOp(IC_RESULT(ic),ic,TRUE);
1689
1690     /* if both in bit space then special
1691     case */
1692     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1693         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1694
1695         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1696         emitcode("cpl","c"); 
1697         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1698         goto release; 
1699     } 
1700
1701     optype = operandType(IC_LEFT(ic));
1702     rtype = operandType(IC_RESULT(ic));
1703
1704     /* if float then do float stuff */
1705     if (IS_FLOAT(optype)) {
1706         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1707         goto release;
1708     }
1709
1710     /* otherwise subtract from zero */
1711     size = AOP_SIZE(IC_LEFT(ic));
1712     offset = 0 ;
1713     CLRC ;
1714     while(size--) {
1715         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1716         if (!strcmp(l,"a")) {
1717             emitcode("cpl","a");
1718             emitcode("inc","a");
1719         } else {
1720             emitcode("clr","a");
1721             emitcode("subb","a,%s",l);
1722         }       
1723         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1724     }
1725
1726     /* if any remaining bytes in the result */
1727     /* we just need to propagate the sign   */
1728     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1729         emitcode("rlc","a");
1730         emitcode("subb","a,acc");
1731         while (size--) 
1732             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1733     }       
1734
1735 release:
1736     /* release the aops */
1737     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1738     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* saveRegisters - will look for a call and save the registers     */
1743 /*-----------------------------------------------------------------*/
1744 static void saveRegisters(iCode *lic) 
1745 {
1746     int i;
1747     iCode *ic;
1748     bitVect *rsave;
1749     sym_link *detype;
1750
1751     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1752     /* look for call */
1753     for (ic = lic ; ic ; ic = ic->next) 
1754         if (ic->op == CALL || ic->op == PCALL)
1755             break;
1756
1757     if (!ic) {
1758         fprintf(stderr,"found parameter push with no function call\n");
1759         return ;
1760     }
1761
1762     /* if the registers have been saved already then
1763     do nothing */
1764     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1765         return ;
1766
1767     /* find the registers in use at this time 
1768     and push them away to safety */
1769     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1770                           ic->rUsed);
1771
1772     ic->regsSaved = 1;
1773     if (options.useXstack) {
1774         if (bitVectBitValue(rsave,R0_IDX))
1775             emitcode("mov","b,r0");
1776         emitcode("mov","r0,%s",spname);
1777         for (i = 0 ; i < pic14_nRegs ; i++) {
1778             if (bitVectBitValue(rsave,i)) {
1779                 if (i == R0_IDX)
1780                     emitcode("mov","a,b");
1781                 else
1782                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1783                 emitcode("movx","@r0,a");
1784                 emitcode("inc","r0");
1785             }
1786         }
1787         emitcode("mov","%s,r0",spname);
1788         if (bitVectBitValue(rsave,R0_IDX))
1789             emitcode("mov","r0,b");         
1790     } else
1791         for (i = 0 ; i < pic14_nRegs ; i++) {
1792             if (bitVectBitValue(rsave,i))
1793                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1794         }
1795
1796     detype = getSpec(operandType(IC_LEFT(ic)));
1797     if (detype        && 
1798         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1799         IS_ISR(currFunc->etype) &&
1800         !ic->bankSaved) 
1801
1802         saverbank(SPEC_BANK(detype),ic,TRUE);
1803
1804 }
1805 /*-----------------------------------------------------------------*/
1806 /* unsaveRegisters - pop the pushed registers                      */
1807 /*-----------------------------------------------------------------*/
1808 static void unsaveRegisters (iCode *ic)
1809 {
1810     int i;
1811     bitVect *rsave;
1812
1813     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1814     /* find the registers in use at this time 
1815     and push them away to safety */
1816     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1817                           ic->rUsed);
1818     
1819     if (options.useXstack) {
1820         emitcode("mov","r0,%s",spname); 
1821         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1822             if (bitVectBitValue(rsave,i)) {
1823                 emitcode("dec","r0");
1824                 emitcode("movx","a,@r0");
1825                 if (i == R0_IDX)
1826                     emitcode("mov","b,a");
1827                 else
1828                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1829             }       
1830
1831         }
1832         emitcode("mov","%s,r0",spname);
1833         if (bitVectBitValue(rsave,R0_IDX))
1834             emitcode("mov","r0,b");
1835     } else
1836         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1837             if (bitVectBitValue(rsave,i))
1838                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1839         }
1840
1841 }  
1842
1843
1844 /*-----------------------------------------------------------------*/
1845 /* pushSide -                                                      */
1846 /*-----------------------------------------------------------------*/
1847 static void pushSide(operand * oper, int size)
1848 {
1849         int offset = 0;
1850     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1851         while (size--) {
1852                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1853                 if (AOP_TYPE(oper) != AOP_REG &&
1854                     AOP_TYPE(oper) != AOP_DIR &&
1855                     strcmp(l,"a") ) {
1856                         emitcode("mov","a,%s",l);
1857                         emitcode("push","acc");
1858                 } else
1859                         emitcode("push","%s",l);
1860         }
1861 }
1862
1863 /*-----------------------------------------------------------------*/
1864 /* assignResultValue -                                             */
1865 /*-----------------------------------------------------------------*/
1866 static void assignResultValue(operand * oper)
1867 {
1868         int offset = 0;
1869         int size = AOP_SIZE(oper);
1870
1871     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1872
1873     // The last byte in the assignment is in W
1874     aopPut(AOP(oper),"W",size-1);
1875
1876     if(size>1) {
1877       while (--size) {
1878         aopPut(AOP(oper),fReturn[offset],offset);
1879         offset++;
1880
1881       }
1882     }
1883 }
1884
1885
1886 /*-----------------------------------------------------------------*/
1887 /* genXpush - pushes onto the external stack                       */
1888 /*-----------------------------------------------------------------*/
1889 static void genXpush (iCode *ic)
1890 {
1891     asmop *aop = newAsmop(0);
1892     regs *r ;
1893     int size,offset = 0;
1894
1895     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1896     aopOp(IC_LEFT(ic),ic,FALSE);
1897     r = getFreePtr(ic,&aop,FALSE);
1898
1899     
1900     emitcode("mov","%s,_spx",r->name);
1901
1902     size = AOP_SIZE(IC_LEFT(ic));
1903     while(size--) {
1904
1905         char *l = aopGet(AOP(IC_LEFT(ic)),
1906                          offset++,FALSE,FALSE); 
1907         MOVA(l);            
1908         emitcode("movx","@%s,a",r->name);       
1909         emitcode("inc","%s",r->name);
1910
1911     }
1912
1913         
1914     emitcode("mov","_spx,%s",r->name);
1915
1916     freeAsmop(NULL,aop,ic,TRUE);
1917     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* genIpush - genrate code for pushing this gets a little complex  */
1922 /*-----------------------------------------------------------------*/
1923 static void genIpush (iCode *ic)
1924 {
1925     int size, offset = 0 ;
1926     char *l;
1927
1928
1929     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1930     /* if this is not a parm push : ie. it is spill push 
1931     and spill push is always done on the local stack */
1932     if (!ic->parmPush) {
1933
1934         /* and the item is spilt then do nothing */
1935         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1936             return ;
1937
1938         aopOp(IC_LEFT(ic),ic,FALSE);
1939         size = AOP_SIZE(IC_LEFT(ic));
1940         /* push it on the stack */
1941         while(size--) {
1942             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1943             if (*l == '#') {
1944                 MOVA(l);
1945                 l = "acc";
1946             }
1947             emitcode("push","%s",l);
1948         }
1949         return ;        
1950     }
1951
1952     /* this is a paramter push: in this case we call
1953     the routine to find the call and save those
1954     registers that need to be saved */   
1955     saveRegisters(ic);
1956
1957     /* if use external stack then call the external
1958     stack pushing routine */
1959     if (options.useXstack) {
1960         genXpush(ic);
1961         return ;
1962     }
1963
1964     /* then do the push */
1965     aopOp(IC_LEFT(ic),ic,FALSE);
1966
1967
1968         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1969     size = AOP_SIZE(IC_LEFT(ic));
1970
1971     while (size--) {
1972         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1973         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1974             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1975             strcmp(l,"a") ) {
1976             emitcode("mov","a,%s",l);
1977             emitcode("push","acc");
1978         } else
1979             emitcode("push","%s",l);
1980     }       
1981
1982     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1983 }
1984
1985 /*-----------------------------------------------------------------*/
1986 /* genIpop - recover the registers: can happen only for spilling   */
1987 /*-----------------------------------------------------------------*/
1988 static void genIpop (iCode *ic)
1989 {
1990     int size,offset ;
1991
1992
1993     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1994     /* if the temp was not pushed then */
1995     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1996         return ;
1997
1998     aopOp(IC_LEFT(ic),ic,FALSE);
1999     size = AOP_SIZE(IC_LEFT(ic));
2000     offset = (size-1);
2001     while (size--) 
2002         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2003                                    FALSE,TRUE));
2004
2005     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2006 }
2007
2008 /*-----------------------------------------------------------------*/
2009 /* unsaverbank - restores the resgister bank from stack            */
2010 /*-----------------------------------------------------------------*/
2011 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2012 {
2013     int i;
2014     asmop *aop ;
2015     regs *r = NULL;
2016
2017     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2018     if (popPsw) {
2019         if (options.useXstack) {
2020             aop = newAsmop(0);
2021             r = getFreePtr(ic,&aop,FALSE);
2022             
2023             
2024             emitcode("mov","%s,_spx",r->name);
2025             emitcode("movx","a,@%s",r->name);
2026             emitcode("mov","psw,a");
2027             emitcode("dec","%s",r->name);
2028             
2029         }else
2030             emitcode ("pop","psw");
2031     }
2032
2033     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2034         if (options.useXstack) {       
2035             emitcode("movx","a,@%s",r->name);
2036             //emitcode("mov","(%s+%d),a",
2037             //       regspic14[i].base,8*bank+regspic14[i].offset);
2038             emitcode("dec","%s",r->name);
2039
2040         } else 
2041           emitcode("pop",""); //"(%s+%d)",
2042         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2043     }
2044
2045     if (options.useXstack) {
2046
2047         emitcode("mov","_spx,%s",r->name);
2048         freeAsmop(NULL,aop,ic,TRUE);
2049
2050     } 
2051 }
2052
2053 /*-----------------------------------------------------------------*/
2054 /* saverbank - saves an entire register bank on the stack          */
2055 /*-----------------------------------------------------------------*/
2056 static void saverbank (int bank, iCode *ic, bool pushPsw)
2057 {
2058     int i;
2059     asmop *aop ;
2060     regs *r = NULL;
2061
2062     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2063     if (options.useXstack) {
2064
2065         aop = newAsmop(0);
2066         r = getFreePtr(ic,&aop,FALSE);  
2067         emitcode("mov","%s,_spx",r->name);
2068
2069     }
2070
2071     for (i = 0 ; i < pic14_nRegs ;i++) {
2072         if (options.useXstack) {
2073             emitcode("inc","%s",r->name);
2074             //emitcode("mov","a,(%s+%d)",
2075             //         regspic14[i].base,8*bank+regspic14[i].offset);
2076             emitcode("movx","@%s,a",r->name);           
2077         } else 
2078           emitcode("push","");// "(%s+%d)",
2079                      //regspic14[i].base,8*bank+regspic14[i].offset);
2080     }
2081     
2082     if (pushPsw) {
2083         if (options.useXstack) {
2084             emitcode("mov","a,psw");
2085             emitcode("movx","@%s,a",r->name);   
2086             emitcode("inc","%s",r->name);
2087             emitcode("mov","_spx,%s",r->name);       
2088             freeAsmop (NULL,aop,ic,TRUE);
2089             
2090         } else
2091             emitcode("push","psw");
2092         
2093         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2094     }
2095     ic->bankSaved = 1;
2096
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* genCall - generates a call statement                            */
2101 /*-----------------------------------------------------------------*/
2102 static void genCall (iCode *ic)
2103 {
2104     sym_link *detype;   
2105
2106     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2107
2108     /* if caller saves & we have not saved then */
2109     if (!ic->regsSaved)
2110         saveRegisters(ic);
2111
2112     /* if we are calling a function that is not using
2113     the same register bank then we need to save the
2114     destination registers on the stack */
2115     detype = getSpec(operandType(IC_LEFT(ic)));
2116     if (detype        && 
2117         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2118         IS_ISR(currFunc->etype) &&
2119         !ic->bankSaved) 
2120
2121         saverbank(SPEC_BANK(detype),ic,TRUE);
2122
2123     /* if send set is not empty the assign */
2124     if (_G.sendSet) {
2125         iCode *sic ;
2126
2127         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2128              sic = setNextItem(_G.sendSet)) {
2129             int size, offset = 0;
2130
2131             aopOp(IC_LEFT(sic),sic,FALSE);
2132             size = AOP_SIZE(IC_LEFT(sic));
2133             while (size--) {
2134                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2135                                 FALSE,FALSE);
2136                 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2137
2138                 if (strcmp(l,fReturn[offset])) {
2139
2140                   if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2141                        ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2142                     emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2143                   //emitcode("movlw","%s",l);
2144                   else
2145                     emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2146                   //emitcode("movf","%s,w",l);
2147
2148                   // The last one is passed in W
2149                   if(size)
2150                     emitcode("movwf","%s",fReturn[offset]);
2151                 }
2152                 offset++;
2153             }
2154             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2155         }
2156         _G.sendSet = NULL;
2157     }
2158     /* make the call */
2159     emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2160                                         OP_SYMBOL(IC_LEFT(ic))->rname :
2161                                         OP_SYMBOL(IC_LEFT(ic))->name));
2162
2163     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2164                            OP_SYMBOL(IC_LEFT(ic))->rname :
2165                            OP_SYMBOL(IC_LEFT(ic))->name));
2166
2167     /* if we need assign a result value */
2168     if ((IS_ITEMP(IC_RESULT(ic)) && 
2169          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2170           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2171         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2172
2173         _G.accInUse++;
2174         aopOp(IC_RESULT(ic),ic,FALSE);
2175         _G.accInUse--;
2176
2177         assignResultValue(IC_RESULT(ic));
2178                 
2179         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2180     }
2181
2182     /* adjust the stack for parameters if 
2183     required */
2184     if (ic->parmBytes) {
2185         int i;
2186         if (ic->parmBytes > 3) {
2187             emitcode("mov","a,%s",spname);
2188             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2189             emitcode("mov","%s,a",spname);
2190         } else 
2191             for ( i = 0 ; i <  ic->parmBytes ;i++)
2192                 emitcode("dec","%s",spname);
2193
2194     }
2195
2196     /* if register bank was saved then pop them */
2197     if (ic->bankSaved)
2198         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2199
2200     /* if we hade saved some registers then unsave them */
2201     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2202         unsaveRegisters (ic);
2203
2204
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* genPcall - generates a call by pointer statement                */
2209 /*-----------------------------------------------------------------*/
2210 static void genPcall (iCode *ic)
2211 {
2212     sym_link *detype;
2213     symbol *rlbl = newiTempLabel(NULL);
2214
2215
2216     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2217     /* if caller saves & we have not saved then */
2218     if (!ic->regsSaved)
2219         saveRegisters(ic);
2220
2221     /* if we are calling a function that is not using
2222     the same register bank then we need to save the
2223     destination registers on the stack */
2224     detype = getSpec(operandType(IC_LEFT(ic)));
2225     if (detype        && 
2226         IS_ISR(currFunc->etype) &&
2227         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2228         saverbank(SPEC_BANK(detype),ic,TRUE);
2229
2230
2231     /* push the return address on to the stack */
2232     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2233     emitcode("push","acc");    
2234     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2235     emitcode("push","acc");
2236     
2237     if (options.model == MODEL_FLAT24)
2238     {
2239         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2240         emitcode("push","acc");    
2241     }
2242
2243     /* now push the calling address */
2244     aopOp(IC_LEFT(ic),ic,FALSE);
2245
2246     pushSide(IC_LEFT(ic), FPTRSIZE);
2247
2248     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2249
2250     /* if send set is not empty the assign */
2251     if (_G.sendSet) {
2252         iCode *sic ;
2253
2254         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2255              sic = setNextItem(_G.sendSet)) {
2256             int size, offset = 0;
2257             aopOp(IC_LEFT(sic),sic,FALSE);
2258             size = AOP_SIZE(IC_LEFT(sic));
2259             while (size--) {
2260                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2261                                 FALSE,FALSE);
2262                 if (strcmp(l,fReturn[offset]))
2263                     emitcode("mov","%s,%s",
2264                              fReturn[offset],
2265                              l);
2266                 offset++;
2267             }
2268             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2269         }
2270         _G.sendSet = NULL;
2271     }
2272
2273     emitcode("ret","");
2274     emitcode("","%05d_DS_:",(rlbl->key+100));
2275
2276
2277     /* if we need assign a result value */
2278     if ((IS_ITEMP(IC_RESULT(ic)) &&
2279          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2280           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2281         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2282
2283         _G.accInUse++;
2284         aopOp(IC_RESULT(ic),ic,FALSE);
2285         _G.accInUse--;
2286         
2287         assignResultValue(IC_RESULT(ic));
2288
2289         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2290     }
2291
2292     /* adjust the stack for parameters if 
2293     required */
2294     if (ic->parmBytes) {
2295         int i;
2296         if (ic->parmBytes > 3) {
2297             emitcode("mov","a,%s",spname);
2298             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2299             emitcode("mov","%s,a",spname);
2300         } else 
2301             for ( i = 0 ; i <  ic->parmBytes ;i++)
2302                 emitcode("dec","%s",spname);
2303
2304     }
2305
2306     /* if register bank was saved then unsave them */
2307     if (detype        && 
2308         (SPEC_BANK(currFunc->etype) != 
2309          SPEC_BANK(detype)))
2310         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2311
2312     /* if we hade saved some registers then
2313     unsave them */
2314     if (ic->regsSaved)
2315         unsaveRegisters (ic);
2316
2317 }
2318
2319 /*-----------------------------------------------------------------*/
2320 /* resultRemat - result  is rematerializable                       */
2321 /*-----------------------------------------------------------------*/
2322 static int resultRemat (iCode *ic)
2323 {
2324     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2325     if (SKIP_IC(ic) || ic->op == IFX)
2326         return 0;
2327
2328     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2329         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2330         if (sym->remat && !POINTER_SET(ic)) 
2331             return 1;
2332     }
2333
2334     return 0;
2335 }
2336
2337 #if defined(__BORLANDC__) || defined(_MSC_VER)
2338 #define STRCASECMP stricmp
2339 #else
2340 #define STRCASECMP strcasecmp
2341 #endif
2342
2343 /*-----------------------------------------------------------------*/
2344 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2345 /*-----------------------------------------------------------------*/
2346 static bool inExcludeList(char *s)
2347 {
2348     int i =0;
2349     
2350     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2351     if (options.excludeRegs[i] &&
2352     STRCASECMP(options.excludeRegs[i],"none") == 0)
2353         return FALSE ;
2354
2355     for ( i = 0 ; options.excludeRegs[i]; i++) {
2356         if (options.excludeRegs[i] &&
2357         STRCASECMP(s,options.excludeRegs[i]) == 0)
2358             return TRUE;
2359     }
2360     return FALSE ;
2361 }
2362
2363 /*-----------------------------------------------------------------*/
2364 /* genFunction - generated code for function entry                 */
2365 /*-----------------------------------------------------------------*/
2366 static void genFunction (iCode *ic)
2367 {
2368     symbol *sym;
2369     sym_link *fetype;
2370
2371     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2372     labelOffset += FUNCTION_LABEL_INC;
2373
2374     _G.nRegsSaved = 0;
2375     /* create the function header */
2376     emitcode(";","-----------------------------------------");
2377     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2378     emitcode(";","-----------------------------------------");
2379
2380     emitcode("","%s:",sym->rname);
2381     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2382
2383     fetype = getSpec(operandType(IC_LEFT(ic)));
2384
2385     /* if critical function then turn interrupts off */
2386     if (SPEC_CRTCL(fetype))
2387         emitcode("clr","ea");
2388
2389     /* here we need to generate the equates for the
2390        register bank if required */
2391 #if 0
2392     if (SPEC_BANK(fetype) != rbank) {
2393         int i ;
2394
2395         rbank = SPEC_BANK(fetype);
2396         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2397             if (strcmp(regspic14[i].base,"0") == 0)
2398                 emitcode("","%s = 0x%02x",
2399                          regspic14[i].dname,
2400                          8*rbank+regspic14[i].offset);
2401             else
2402                 emitcode ("","%s = %s + 0x%02x",
2403                           regspic14[i].dname,
2404                           regspic14[i].base,
2405                           8*rbank+regspic14[i].offset);
2406         }
2407     }
2408 #endif
2409
2410     /* if this is an interrupt service routine then
2411     save acc, b, dpl, dph  */
2412     if (IS_ISR(sym->etype)) {
2413         
2414         if (!inExcludeList("acc"))          
2415             emitcode ("push","acc");    
2416         if (!inExcludeList("b"))
2417             emitcode ("push","b");
2418         if (!inExcludeList("dpl"))
2419             emitcode ("push","dpl");
2420         if (!inExcludeList("dph"))
2421             emitcode ("push","dph");
2422         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2423         {
2424             emitcode ("push", "dpx");
2425             /* Make sure we're using standard DPTR */
2426             emitcode ("push", "dps");
2427             emitcode ("mov", "dps, #0x00");
2428             if (options.stack10bit)
2429             {   
2430                 /* This ISR could conceivably use DPTR2. Better save it. */
2431                 emitcode ("push", "dpl1");
2432                 emitcode ("push", "dph1");
2433                 emitcode ("push", "dpx1");
2434             }
2435         }
2436         /* if this isr has no bank i.e. is going to
2437            run with bank 0 , then we need to save more
2438            registers :-) */
2439         if (!SPEC_BANK(sym->etype)) {
2440
2441             /* if this function does not call any other
2442                function then we can be economical and
2443                save only those registers that are used */
2444             if (! sym->hasFcall) {
2445                 int i;
2446
2447                 /* if any registers used */
2448                 if (sym->regsUsed) {
2449                     /* save the registers used */
2450                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2451                         if (bitVectBitValue(sym->regsUsed,i) ||
2452                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2453                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2454                     }
2455                 }
2456                 
2457             } else {
2458                 /* this function has  a function call cannot
2459                    determines register usage so we will have the
2460                    entire bank */
2461                 saverbank(0,ic,FALSE);
2462             }       
2463         }
2464     } else {
2465         /* if callee-save to be used for this function
2466            then save the registers being used in this function */
2467         if (sym->calleeSave) {
2468             int i;
2469             
2470             /* if any registers used */
2471             if (sym->regsUsed) {
2472                 /* save the registers used */
2473                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2474                     if (bitVectBitValue(sym->regsUsed,i) ||
2475                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2476                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2477                         _G.nRegsSaved++;
2478                     }
2479                 }
2480             }
2481         }
2482     }
2483
2484     /* set the register bank to the desired value */
2485     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2486         emitcode("push","psw");
2487         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2488     }
2489
2490     if (IS_RENT(sym->etype) || options.stackAuto) {
2491
2492         if (options.useXstack) {
2493             emitcode("mov","r0,%s",spname);
2494             emitcode("mov","a,_bp");
2495             emitcode("movx","@r0,a");
2496             emitcode("inc","%s",spname);
2497         }
2498         else
2499         {
2500             /* set up the stack */
2501             emitcode ("push","_bp");     /* save the callers stack  */
2502         }
2503         emitcode ("mov","_bp,%s",spname);
2504     }
2505
2506     /* adjust the stack for the function */
2507     if (sym->stack) {
2508
2509         int i = sym->stack;
2510         if (i > 256 ) 
2511             werror(W_STACK_OVERFLOW,sym->name);
2512
2513         if (i > 3 && sym->recvSize < 4) {              
2514
2515             emitcode ("mov","a,sp");
2516             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2517             emitcode ("mov","sp,a");
2518            
2519         }
2520         else
2521             while(i--)
2522                 emitcode("inc","sp");
2523     }
2524
2525      if (sym->xstack) {
2526
2527         emitcode ("mov","a,_spx");
2528         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2529         emitcode ("mov","_spx,a");
2530     }    
2531
2532 }
2533
2534 /*-----------------------------------------------------------------*/
2535 /* genEndFunction - generates epilogue for functions               */
2536 /*-----------------------------------------------------------------*/
2537 static void genEndFunction (iCode *ic)
2538 {
2539     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2540
2541     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2542
2543     if (IS_RENT(sym->etype) || options.stackAuto)
2544     {
2545         emitcode ("mov","%s,_bp",spname);
2546     }
2547
2548     /* if use external stack but some variables were
2549     added to the local stack then decrement the
2550     local stack */
2551     if (options.useXstack && sym->stack) {      
2552         emitcode("mov","a,sp");
2553         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2554         emitcode("mov","sp,a");
2555     }
2556
2557
2558     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2559         if (options.useXstack) {
2560             emitcode("mov","r0,%s",spname);
2561             emitcode("movx","a,@r0");
2562             emitcode("mov","_bp,a");
2563             emitcode("dec","%s",spname);
2564         }
2565         else
2566         {
2567             emitcode ("pop","_bp");
2568         }
2569     }
2570
2571     /* restore the register bank  */    
2572     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2573         emitcode ("pop","psw");
2574
2575     if (IS_ISR(sym->etype)) {
2576
2577         /* now we need to restore the registers */
2578         /* if this isr has no bank i.e. is going to
2579            run with bank 0 , then we need to save more
2580            registers :-) */
2581         if (!SPEC_BANK(sym->etype)) {
2582             
2583             /* if this function does not call any other
2584                function then we can be economical and
2585                save only those registers that are used */
2586             if (! sym->hasFcall) {
2587                 int i;
2588                 
2589                 /* if any registers used */
2590                 if (sym->regsUsed) {
2591                     /* save the registers used */
2592                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2593                         if (bitVectBitValue(sym->regsUsed,i) ||
2594                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2595                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2596                     }
2597                 }
2598                 
2599             } else {
2600                 /* this function has  a function call cannot
2601                    determines register usage so we will have the
2602                    entire bank */
2603                 unsaverbank(0,ic,FALSE);
2604             }       
2605         }
2606
2607         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2608         {
2609             if (options.stack10bit)
2610             {
2611                 emitcode ("pop", "dpx1");
2612                 emitcode ("pop", "dph1");
2613                 emitcode ("pop", "dpl1");
2614             }   
2615             emitcode ("pop", "dps");
2616             emitcode ("pop", "dpx");
2617         }
2618         if (!inExcludeList("dph"))
2619             emitcode ("pop","dph");
2620         if (!inExcludeList("dpl"))
2621             emitcode ("pop","dpl");
2622         if (!inExcludeList("b"))
2623             emitcode ("pop","b");
2624         if (!inExcludeList("acc"))
2625             emitcode ("pop","acc");
2626
2627         if (SPEC_CRTCL(sym->etype))
2628             emitcode("setb","ea");
2629
2630         /* if debug then send end of function */
2631 /*      if (options.debug && currFunc) { */
2632         if (currFunc) {
2633             _G.debugLine = 1;
2634             emitcode(";","C$%s$%d$%d$%d ==.",
2635                      FileBaseName(ic->filename),currFunc->lastLine,
2636                      ic->level,ic->block); 
2637             if (IS_STATIC(currFunc->etype))         
2638                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2639             else
2640                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2641             _G.debugLine = 0;
2642         }
2643         
2644         emitcode ("reti","");
2645     }
2646     else {
2647         if (SPEC_CRTCL(sym->etype))
2648             emitcode("setb","ea");
2649         
2650         if (sym->calleeSave) {
2651             int i;
2652             
2653             /* if any registers used */
2654             if (sym->regsUsed) {
2655                 /* save the registers used */
2656                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2657                     if (bitVectBitValue(sym->regsUsed,i) ||
2658                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2659                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2660                 }
2661             }
2662             
2663         }
2664
2665         /* if debug then send end of function */
2666         if (currFunc) {
2667             _G.debugLine = 1;
2668             emitcode(";","C$%s$%d$%d$%d ==.",
2669                      FileBaseName(ic->filename),currFunc->lastLine,
2670                      ic->level,ic->block); 
2671             if (IS_STATIC(currFunc->etype))         
2672                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2673             else
2674                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2675             _G.debugLine = 0;
2676         }
2677
2678         emitcode ("return","");
2679         emitpcode(POC_RETURN,NULL);
2680
2681         /* Mark the end of a function */
2682         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2683     }
2684
2685 }
2686
2687 /*-----------------------------------------------------------------*/
2688 /* genRet - generate code for return statement                     */
2689 /*-----------------------------------------------------------------*/
2690 static void genRet (iCode *ic)
2691 {
2692     int size,offset = 0 , pushed = 0;
2693     
2694     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2695     /* if we have no return value then
2696        just generate the "ret" */
2697     if (!IC_LEFT(ic)) 
2698         goto jumpret;       
2699     
2700     /* we have something to return then
2701        move the return value into place */
2702     aopOp(IC_LEFT(ic),ic,FALSE);
2703     size = AOP_SIZE(IC_LEFT(ic));
2704     
2705     while (size--) {
2706             char *l ;
2707             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2708                     /* #NOCHANGE */
2709                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2710                            FALSE,TRUE);
2711                     emitcode("push","%s",l);
2712                     pushed++;
2713             } else {
2714                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2715                                FALSE,FALSE);
2716                     if (strcmp(fReturn[offset],l)) {
2717                       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2718                           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2719                         emitcode("movlw","%s",l);
2720                       else
2721                         emitcode("movf","%s,w",l);
2722                       if(size)
2723                         emitcode("movwf","%s",fReturn[offset]);
2724                       offset++;
2725                     }
2726             }
2727     }    
2728
2729     if (pushed) {
2730         while(pushed) {
2731             pushed--;
2732             if (strcmp(fReturn[pushed],"a"))
2733                 emitcode("pop",fReturn[pushed]);
2734             else
2735                 emitcode("pop","acc");
2736         }
2737     }
2738     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2739     
2740  jumpret:
2741         /* generate a jump to the return label
2742            if the next is not the return statement */
2743     if (!(ic->next && ic->next->op == LABEL &&
2744           IC_LABEL(ic->next) == returnLabel))
2745         
2746         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2747     
2748 }
2749
2750 /*-----------------------------------------------------------------*/
2751 /* genLabel - generates a label                                    */
2752 /*-----------------------------------------------------------------*/
2753 static void genLabel (iCode *ic)
2754 {
2755     /* special case never generate */
2756     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2757     if (IC_LABEL(ic) == entryLabel)
2758         return ;
2759
2760     emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2761     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2762 }
2763
2764 /*-----------------------------------------------------------------*/
2765 /* genGoto - generates a goto                                      */
2766 /*-----------------------------------------------------------------*/
2767 //tsd
2768 static void genGoto (iCode *ic)
2769 {
2770     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2771 }
2772
2773 /*-----------------------------------------------------------------*/
2774 /* findLabelBackwards: walks back through the iCode chain looking  */
2775 /* for the given label. Returns number of iCode instructions       */
2776 /* between that label and given ic.                                */
2777 /* Returns zero if label not found.                                */
2778 /*-----------------------------------------------------------------*/
2779 #if 0
2780 static int findLabelBackwards(iCode *ic, int key)
2781 {
2782     int count = 0;
2783     
2784     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2785     while (ic->prev)
2786     {
2787         ic = ic->prev;
2788         count++;
2789         
2790         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2791         {
2792             /* printf("findLabelBackwards = %d\n", count); */
2793             return count;
2794         }
2795     }
2796     
2797     return 0;
2798 }
2799 #endif
2800 /*-----------------------------------------------------------------*/
2801 /* genPlusIncr :- does addition with increment if possible         */
2802 /*-----------------------------------------------------------------*/
2803 static bool genPlusIncr (iCode *ic)
2804 {
2805     unsigned int icount ;
2806     unsigned int size = getDataSize(IC_RESULT(ic));
2807
2808     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2809     DEBUGemitcode ("; ","result %d, left %d, right %d",
2810                    AOP_TYPE(IC_RESULT(ic)),
2811                    AOP_TYPE(IC_LEFT(ic)),
2812                    AOP_TYPE(IC_RIGHT(ic)));
2813
2814     /* will try to generate an increment */
2815     /* if the right side is not a literal 
2816        we cannot */
2817     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2818         return FALSE ;
2819     
2820     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2821     /* if the literal value of the right hand side
2822        is greater than 1 then it is faster to add */
2823     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2824         return FALSE ;
2825     
2826     /* if increment 16 bits in register */
2827     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2828         (icount == 1)) {
2829
2830       int offset = MSB16;
2831
2832       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2833       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2834
2835       while(--size) {
2836         emitSKPNZ;
2837         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2838         //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2839       }
2840
2841       return TRUE;
2842     }
2843     
2844     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2845     /* if left is in accumulator  - probably a bit operation*/
2846     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2847         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2848       
2849       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2850       emitcode("bcf","(%s >> 3), (%s & 7)",
2851                AOP(IC_RESULT(ic))->aopu.aop_dir,
2852                AOP(IC_RESULT(ic))->aopu.aop_dir);
2853       if(icount)
2854         emitpcode(POC_XORLW,popGetLit(1));
2855       //emitcode("xorlw","1");
2856       else
2857         emitpcode(POC_ANDLW,popGetLit(1));
2858       //emitcode("andlw","1");
2859
2860       emitSKPZ;
2861       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2862       emitcode("bsf","(%s >> 3), (%s & 7)",
2863                AOP(IC_RESULT(ic))->aopu.aop_dir,
2864                AOP(IC_RESULT(ic))->aopu.aop_dir);
2865
2866       return TRUE;
2867     }
2868
2869
2870
2871     /* if the sizes are greater than 1 then we cannot */
2872     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2873         AOP_SIZE(IC_LEFT(ic)) > 1   )
2874         return FALSE ;
2875     
2876     /* If we are incrementing the same register by two: */
2877
2878     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2879         
2880       while (icount--) 
2881         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2882       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2883         
2884       return TRUE ;
2885     }
2886     
2887     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2888                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2889                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2890     return FALSE ;
2891 }
2892
2893 /*-----------------------------------------------------------------*/
2894 /* outBitAcc - output a bit in acc                                 */
2895 /*-----------------------------------------------------------------*/
2896 static void outBitAcc(operand *result)
2897 {
2898     symbol *tlbl = newiTempLabel(NULL);
2899     /* if the result is a bit */
2900     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2901
2902     if (AOP_TYPE(result) == AOP_CRY){
2903         aopPut(AOP(result),"a",0);
2904     }
2905     else {
2906         emitcode("jz","%05d_DS_",tlbl->key+100);
2907         emitcode("mov","a,%s",one);
2908         emitcode("","%05d_DS_:",tlbl->key+100);
2909         outAcc(result);
2910     }
2911 }
2912
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusBits - generates code for addition of two bits           */
2915 /*-----------------------------------------------------------------*/
2916 static void genPlusBits (iCode *ic)
2917 {
2918
2919     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2920     /*
2921       The following block of code will add two bits. 
2922       Note that it'll even work if the destination is
2923       the carry (C in the status register).
2924       It won't work if the 'Z' bit is a source or destination.
2925     */
2926
2927     /* If the result is stored in the accumulator (w) */
2928     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2929       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2930       //              popGet(AOP(result),0,FALSE,FALSE));
2931
2932       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2933       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2934       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2935       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2936       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2937       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2938
2939         emitcode("movlw","(1 << (%s & 7))",
2940                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2941                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2942         emitcode("bcf","(%s >> 3), (%s & 7)",
2943                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2944                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2945         emitcode("btfsc","(%s >> 3), (%s & 7)",
2946                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2947                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2948         emitcode("xorwf","(%s >>3),f",
2949                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2950         emitcode("btfsc","(%s >> 3), (%s & 7)",
2951                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2952                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2953         emitcode("xorwf","(%s>>3),f",
2954                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2955     } else { 
2956
2957       emitpcode(POC_CLRW, NULL);
2958       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2959       emitpcode(POC_XORLW, popGetLit(1));
2960       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2961       emitpcode(POC_XORLW, popGetLit(1));
2962
2963       emitcode("clrw","");
2964       emitcode("btfsc","(%s >> 3), (%s & 7)",
2965                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2966                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2967       emitcode("xorlw","1");
2968       emitcode("btfsc","(%s >> 3), (%s & 7)",
2969                AOP(IC_LEFT(ic))->aopu.aop_dir,
2970                AOP(IC_LEFT(ic))->aopu.aop_dir);
2971       emitcode("xorlw","1");
2972     }
2973
2974 }
2975
2976 #if 0
2977 /* This is the original version of this code.
2978  *
2979  * This is being kept around for reference, 
2980  * because I am not entirely sure I got it right...
2981  */
2982 static void adjustArithmeticResult(iCode *ic)
2983 {
2984     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2985         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2986         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2987         aopPut(AOP(IC_RESULT(ic)),
2988                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2989                2);
2990
2991     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2992         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2993         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2994         aopPut(AOP(IC_RESULT(ic)),
2995                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2996                2);
2997     
2998     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2999         AOP_SIZE(IC_LEFT(ic)) < 3    &&
3000         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
3001         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3002         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3003         char buffer[5];
3004         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3005         aopPut(AOP(IC_RESULT(ic)),buffer,2);
3006     }
3007 }
3008 //#else
3009 /* This is the pure and virtuous version of this code.
3010  * I'm pretty certain it's right, but not enough to toss the old 
3011  * code just yet...
3012  */
3013 static void adjustArithmeticResult(iCode *ic)
3014 {
3015     if (opIsGptr(IC_RESULT(ic)) &&
3016         opIsGptr(IC_LEFT(ic))   &&
3017         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3018     {
3019         aopPut(AOP(IC_RESULT(ic)),
3020                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3021                GPTRSIZE - 1);
3022     }
3023
3024     if (opIsGptr(IC_RESULT(ic)) &&
3025         opIsGptr(IC_RIGHT(ic))   &&
3026         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3027     {
3028         aopPut(AOP(IC_RESULT(ic)),
3029                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3030                GPTRSIZE - 1);
3031     }
3032
3033     if (opIsGptr(IC_RESULT(ic))            &&
3034         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
3035         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
3036          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3037          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3038          char buffer[5];
3039          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3040          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3041      }
3042 }
3043 #endif
3044
3045 /*-----------------------------------------------------------------*/
3046 /* genPlus - generates code for addition                           */
3047 /*-----------------------------------------------------------------*/
3048 static void genPlus (iCode *ic)
3049 {
3050     int size, offset = 0;
3051
3052     /* special cases :- */
3053     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3054
3055     aopOp (IC_LEFT(ic),ic,FALSE);
3056     aopOp (IC_RIGHT(ic),ic,FALSE);
3057     aopOp (IC_RESULT(ic),ic,TRUE);
3058
3059     /* if literal, literal on the right or
3060        if left requires ACC or right is already
3061        in ACC */
3062
3063     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3064         operand *t = IC_RIGHT(ic);
3065         IC_RIGHT(ic) = IC_LEFT(ic);
3066         IC_LEFT(ic) = t;
3067     }
3068
3069     /* if both left & right are in bit space */
3070     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3071         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3072         genPlusBits (ic);
3073         goto release ;
3074     }
3075
3076     /* if left in bit space & right literal */
3077     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3078         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3079         /* if result in bit space */
3080         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3081           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3082             emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3083             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3084               emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3085             emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3086           }
3087         } else {
3088             size = getDataSize(IC_RESULT(ic));
3089             while (size--) {
3090                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
3091                 emitcode("addc","a,#00  ;%d",__LINE__);
3092                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3093             }
3094         }
3095         goto release ;
3096     }
3097
3098     /* if I can do an increment instead
3099     of add then GOOD for ME */
3100     if (genPlusIncr (ic) == TRUE)
3101         goto release;   
3102
3103     size = getDataSize(IC_RESULT(ic));
3104
3105     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3106       /* Add a literal to something else */
3107       bool know_W=0;
3108       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3109       unsigned l1=0;
3110
3111       offset = 0;
3112       DEBUGemitcode(";","adding lit to something. size %d",size);
3113       while(size--){
3114
3115       DEBUGemitcode(";","size %d",size);
3116
3117         switch (lit & 0xff) {
3118         case 0:
3119           break;
3120         case 1:
3121           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3122             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3123           else {
3124             know_W = 0;
3125             emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3126             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3127               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3128           }
3129           break;
3130         case 0xff:
3131           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3132             emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3133           else {
3134             know_W = 0;
3135             emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3136             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3137               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3138           }
3139           break;
3140         default:
3141           if( !know_W || ( (lit&0xff) != l1)  ) {
3142             know_W = 1;
3143             emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3144           }
3145           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3146             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3147           else {
3148             know_W = 0;
3149             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3150             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3151             if(size) {
3152               emitSKPNC;
3153               emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3154             }
3155           }
3156         }
3157
3158         l1 = lit & 0xff;
3159         lit >>= 8;
3160         offset++;
3161       }
3162
3163     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3164
3165       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3166       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3167       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3168
3169       /* here we are adding a bit to a char or int */
3170       if(size == 1) {
3171         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3172
3173           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3174           emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3175
3176           emitcode("btfsc","(%s >> 3), (%s & 7)",
3177                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3178                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3179           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3180         } else {
3181
3182           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3183             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3184             emitpcode(POC_XORLW , popGetLit(1));
3185
3186             emitcode("btfsc","(%s >> 3), (%s & 7)",
3187                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3188                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3189             emitcode(" xorlw","1");
3190           } else {
3191             emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3192             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3193             emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3194
3195             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3196             emitcode("btfsc","(%s >> 3), (%s & 7)",
3197                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3198                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3199             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3200           }
3201           
3202           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3203             
3204             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3205               emitpcode(POC_ANDLW , popGetLit(1));
3206               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3207               emitSKPZ;
3208               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3209 /*
3210               emitcode("andlw","1");
3211               emitcode("bcf","(%s >> 3), (%s & 7)",
3212                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3213                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3214               emitSKPZ;
3215               emitcode("bsf","(%s >> 3), (%s & 7)",
3216                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3217                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3218 */
3219
3220             } else {
3221               emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3222               emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3223             }
3224           }
3225         }
3226
3227       } else {
3228         int offset = 1;
3229
3230         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3231           emitCLRZ;
3232           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3233           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3234
3235           emitcode("clrz","");
3236
3237           emitcode("btfsc","(%s >> 3), (%s & 7)",
3238                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3239                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3240           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3241
3242         } else {
3243
3244           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3245           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3246           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3247           emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3248
3249
3250           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3251           emitcode("btfsc","(%s >> 3), (%s & 7)",
3252                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3253                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3254           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3255           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3256
3257         }
3258
3259         while(--size){
3260           emitSKPZ;
3261           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3262       //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3263         }
3264
3265       }
3266       
3267     } else {
3268     
3269       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3270         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3271         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3272       } else {
3273
3274         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3275           emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3276           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3277             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3278         } else {
3279
3280           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3281
3282           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3283             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3284           else {
3285             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3286                 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3287               emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3288             } else {
3289               emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3290               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3291                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3292             }
3293           }
3294         }
3295       }
3296
3297       offset = 1;
3298       size--;
3299
3300       while(size--){
3301         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3302           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3303           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3304
3305           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3306           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3307         }
3308
3309         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3310         emitSKPNC;
3311         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3312         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3313
3314         /*
3315         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3316         emitSKPNC;
3317         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3318         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3319         */
3320
3321         offset++;
3322       }
3323
3324     }
3325
3326     //adjustArithmeticResult(ic);
3327
3328  release:
3329       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3331       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3332 }
3333
3334 /*-----------------------------------------------------------------*/
3335 /* genMinusDec :- does subtraction with decrement if possible     */
3336 /*-----------------------------------------------------------------*/
3337 static bool genMinusDec (iCode *ic)
3338 {
3339     unsigned int icount ;
3340     unsigned int size = getDataSize(IC_RESULT(ic));
3341
3342     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3343     /* will try to generate an increment */
3344     /* if the right side is not a literal 
3345     we cannot */
3346     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3347         return FALSE ;
3348
3349     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3350
3351     /* if the literal value of the right hand side
3352     is greater than 4 then it is not worth it */
3353     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3354         return FALSE ;
3355
3356     /* if decrement 16 bits in register */
3357     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3358         (size > 1) &&
3359         (icount == 1)) {
3360
3361       if(size == 2) { 
3362         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3363         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3364         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3365       } else {
3366         /* size is 3 or 4 */
3367         emitcode("movlw","0xff");
3368         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3369
3370         emitSKPNC;
3371         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3372         emitSKPNC;
3373         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3374
3375         if(size > 3) {
3376           emitcode("skpnc","");
3377           emitSKPNC;
3378           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3379         }
3380
3381       }
3382
3383       return TRUE;
3384
3385     }
3386
3387     /* if the sizes are greater than 1 then we cannot */
3388     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3389         AOP_SIZE(IC_LEFT(ic)) > 1   )
3390         return FALSE ;
3391
3392     /* we can if the aops of the left & result match or
3393     if they are in registers and the registers are the
3394     same */
3395     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3396
3397       while (icount--) 
3398         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3399
3400         //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3401
3402         return TRUE ;
3403     }
3404
3405     DEBUGemitcode ("; returning"," result=%s, left=%s",
3406                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3407                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3408     if(size==1) {
3409       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3410       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3411       return TRUE;
3412     }
3413
3414     return FALSE ;
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* addSign - complete with sign                                    */
3419 /*-----------------------------------------------------------------*/
3420 static void addSign(operand *result, int offset, int sign)
3421 {
3422     int size = (getDataSize(result) - offset);
3423     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3424     if(size > 0){
3425         if(sign){
3426             emitcode("rlc","a");
3427             emitcode("subb","a,acc");
3428             while(size--)
3429                 aopPut(AOP(result),"a",offset++); 
3430         } else
3431             while(size--)
3432                 aopPut(AOP(result),zero,offset++);
3433     }
3434 }
3435
3436 /*-----------------------------------------------------------------*/
3437 /* genMinusBits - generates code for subtraction  of two bits      */
3438 /*-----------------------------------------------------------------*/
3439 static void genMinusBits (iCode *ic)
3440 {
3441     symbol *lbl = newiTempLabel(NULL);
3442     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3443     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3444         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3445         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3446         emitcode("cpl","c");
3447         emitcode("","%05d_DS_:",(lbl->key+100));
3448         outBitC(IC_RESULT(ic));
3449     }
3450     else{
3451         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3452         emitcode("subb","a,acc");
3453         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3454         emitcode("inc","a");
3455         emitcode("","%05d_DS_:",(lbl->key+100));
3456         aopPut(AOP(IC_RESULT(ic)),"a",0);
3457         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3458     }
3459 }
3460
3461 /*-----------------------------------------------------------------*/
3462 /* genMinus - generates code for subtraction                       */
3463 /*-----------------------------------------------------------------*/
3464 static void genMinus (iCode *ic)
3465 {
3466     int size, offset = 0;
3467     unsigned long lit = 0L;
3468
3469     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3470     aopOp (IC_LEFT(ic),ic,FALSE);
3471     aopOp (IC_RIGHT(ic),ic,FALSE);
3472     aopOp (IC_RESULT(ic),ic,TRUE);
3473
3474     /* special cases :- */
3475     /* if both left & right are in bit space */
3476     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3477         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3478         genMinusBits (ic);
3479         goto release ;
3480     }
3481
3482     /* if I can do an decrement instead
3483     of subtract then GOOD for ME */
3484     if (genMinusDec (ic) == TRUE)
3485         goto release;   
3486
3487     size = getDataSize(IC_RESULT(ic));   
3488
3489     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3490       /* Add a literal to something else */
3491
3492       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3493       lit = - (long)lit;
3494
3495       /* add the first byte: */
3496       emitcode("movlw","0x%x", lit & 0xff);
3497       emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3498
3499       offset = 1;
3500       size--;
3501
3502       while(size--){
3503
3504         emitcode("rlf","_known_zero,w");
3505         emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3506
3507         lit >>= 8;
3508         if(lit & 0xff) {
3509           emitcode("movlw","0x%x", lit & 0xff);
3510           emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3511           
3512         }
3513         offset++;
3514       }
3515
3516     } else {
3517
3518       emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3519       emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3520
3521       offset = 1;
3522       size--;
3523
3524       while(size--){
3525         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3526         emitSKPNC;
3527         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3528         emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3529         
3530       }
3531
3532     }
3533
3534
3535     //    adjustArithmeticResult(ic);
3536         
3537 release:
3538     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3539     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3540     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3541 }
3542
3543
3544 /*-----------------------------------------------------------------*/
3545 /* genMultbits :- multiplication of bits                           */
3546 /*-----------------------------------------------------------------*/
3547 static void genMultbits (operand *left, 
3548                          operand *right, 
3549                          operand *result)
3550 {
3551     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3552
3553     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3554     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3555     outBitC(result);
3556 }
3557
3558
3559 /*-----------------------------------------------------------------*/
3560 /* genMultOneByte : 8 bit multiplication & division                */
3561 /*-----------------------------------------------------------------*/
3562 static void genMultOneByte (operand *left,
3563                             operand *right,
3564                             operand *result)
3565 {
3566     sym_link *opetype = operandType(result);
3567     char *l ;
3568     symbol *lbl ;
3569     int size,offset;
3570
3571     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3572     /* (if two literals, the value is computed before) */
3573     /* if one literal, literal on the right */
3574     if (AOP_TYPE(left) == AOP_LIT){
3575         operand *t = right;
3576         right = left;
3577         left = t;
3578     }
3579
3580     size = AOP_SIZE(result);
3581     /* signed or unsigned */
3582     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3583     l = aopGet(AOP(left),0,FALSE,FALSE);
3584     MOVA(l);       
3585     emitcode("mul","ab");
3586     /* if result size = 1, mul signed = mul unsigned */
3587     aopPut(AOP(result),"a",0);
3588     if (size > 1){
3589         if (SPEC_USIGN(opetype)){
3590             aopPut(AOP(result),"b",1);
3591             if (size > 2)
3592                 /* for filling the MSBs */
3593                 emitcode("clr","a");
3594         }
3595         else{
3596             emitcode("mov","a,b");
3597
3598             /* adjust the MSB if left or right neg */
3599
3600             /* if one literal */
3601             if (AOP_TYPE(right) == AOP_LIT){
3602                 /* AND literal negative */
3603                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3604                     /* adjust MSB (c==0 after mul) */
3605                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3606                 }
3607             }
3608             else{
3609                 lbl = newiTempLabel(NULL);
3610                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3611                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3612                 emitcode("","%05d_DS_:",(lbl->key+100));
3613                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3614                 lbl = newiTempLabel(NULL);      
3615                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3616                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3617                 emitcode("","%05d_DS_:",(lbl->key+100));
3618             }
3619
3620             lbl = newiTempLabel(NULL);
3621             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3622             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3623             emitcode("","%05d_DS_:",(lbl->key+100));
3624             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3625             lbl = newiTempLabel(NULL);      
3626             emitcode("jc","%05d_DS_",(lbl->key+100));          
3627             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3628             emitcode("","%05d_DS_:",(lbl->key+100));
3629
3630             aopPut(AOP(result),"a",1);
3631             if(size > 2){
3632                 /* get the sign */
3633                 emitcode("rlc","a");
3634                 emitcode("subb","a,acc");
3635             }
3636         }
3637         size -= 2;   
3638         offset = 2;
3639         if (size > 0)
3640             while (size--)
3641                 aopPut(AOP(result),"a",offset++);
3642     }
3643 }
3644
3645 /*-----------------------------------------------------------------*/
3646 /* genMult - generates code for multiplication                     */
3647 /*-----------------------------------------------------------------*/
3648 static void genMult (iCode *ic)
3649 {
3650     operand *left = IC_LEFT(ic);
3651     operand *right = IC_RIGHT(ic);
3652     operand *result= IC_RESULT(ic);   
3653
3654     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3655     /* assign the amsops */
3656     aopOp (left,ic,FALSE);
3657     aopOp (right,ic,FALSE);
3658     aopOp (result,ic,TRUE);
3659
3660     /* special cases first */
3661     /* both are bits */
3662     if (AOP_TYPE(left) == AOP_CRY &&
3663         AOP_TYPE(right)== AOP_CRY) {
3664         genMultbits(left,right,result);
3665         goto release ;
3666     }
3667
3668     /* if both are of size == 1 */
3669     if (AOP_SIZE(left) == 1 &&
3670         AOP_SIZE(right) == 1 ) {
3671         genMultOneByte(left,right,result);
3672         goto release ;
3673     }
3674
3675     /* should have been converted to function call */       
3676     assert(1) ;
3677
3678 release :
3679     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3680     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3681     freeAsmop(result,NULL,ic,TRUE); 
3682 }
3683
3684 /*-----------------------------------------------------------------*/
3685 /* genDivbits :- division of bits                                  */
3686 /*-----------------------------------------------------------------*/
3687 static void genDivbits (operand *left, 
3688                         operand *right, 
3689                         operand *result)
3690 {
3691
3692     char *l;
3693
3694     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3695     /* the result must be bit */    
3696     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3697     l = aopGet(AOP(left),0,FALSE,FALSE);
3698
3699     MOVA(l);    
3700
3701     emitcode("div","ab");
3702     emitcode("rrc","a");
3703     aopPut(AOP(result),"c",0);
3704 }
3705
3706 /*-----------------------------------------------------------------*/
3707 /* genDivOneByte : 8 bit division                                  */
3708 /*-----------------------------------------------------------------*/
3709 static void genDivOneByte (operand *left,
3710                            operand *right,
3711                            operand *result)
3712 {
3713     sym_link *opetype = operandType(result);
3714     char *l ;
3715     symbol *lbl ;
3716     int size,offset;
3717
3718     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3719     size = AOP_SIZE(result) - 1;
3720     offset = 1;
3721     /* signed or unsigned */
3722     if (SPEC_USIGN(opetype)) {
3723         /* unsigned is easy */
3724         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3725         l = aopGet(AOP(left),0,FALSE,FALSE);
3726         MOVA(l);        
3727         emitcode("div","ab");
3728         aopPut(AOP(result),"a",0);
3729         while (size--)
3730             aopPut(AOP(result),zero,offset++);
3731         return ;
3732     }
3733
3734     /* signed is a little bit more difficult */
3735
3736     /* save the signs of the operands */
3737     l = aopGet(AOP(left),0,FALSE,FALSE);    
3738     MOVA(l);    
3739     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3740     emitcode("push","acc"); /* save it on the stack */
3741
3742     /* now sign adjust for both left & right */
3743     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3744     MOVA(l);       
3745     lbl = newiTempLabel(NULL);
3746     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3747     emitcode("cpl","a");   
3748     emitcode("inc","a");
3749     emitcode("","%05d_DS_:",(lbl->key+100));
3750     emitcode("mov","b,a");
3751
3752     /* sign adjust left side */
3753     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3754     MOVA(l);
3755
3756     lbl = newiTempLabel(NULL);
3757     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3758     emitcode("cpl","a");
3759     emitcode("inc","a");
3760     emitcode("","%05d_DS_:",(lbl->key+100));
3761
3762     /* now the division */
3763     emitcode("div","ab");
3764     /* we are interested in the lower order
3765     only */
3766     emitcode("mov","b,a");
3767     lbl = newiTempLabel(NULL);
3768     emitcode("pop","acc");   
3769     /* if there was an over flow we don't 
3770     adjust the sign of the result */
3771     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3772     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3773     CLRC;
3774     emitcode("clr","a");
3775     emitcode("subb","a,b");
3776     emitcode("mov","b,a");
3777     emitcode("","%05d_DS_:",(lbl->key+100));
3778
3779     /* now we are done */
3780     aopPut(AOP(result),"b",0);
3781     if(size > 0){
3782         emitcode("mov","c,b.7");
3783         emitcode("subb","a,acc");   
3784     }
3785     while (size--)
3786         aopPut(AOP(result),"a",offset++);
3787
3788 }
3789
3790 /*-----------------------------------------------------------------*/
3791 /* genDiv - generates code for division                            */
3792 /*-----------------------------------------------------------------*/
3793 static void genDiv (iCode *ic)
3794 {
3795     operand *left = IC_LEFT(ic);
3796     operand *right = IC_RIGHT(ic);
3797     operand *result= IC_RESULT(ic);   
3798
3799     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3800     /* assign the amsops */
3801     aopOp (left,ic,FALSE);
3802     aopOp (right,ic,FALSE);
3803     aopOp (result,ic,TRUE);
3804
3805     /* special cases first */
3806     /* both are bits */
3807     if (AOP_TYPE(left) == AOP_CRY &&
3808         AOP_TYPE(right)== AOP_CRY) {
3809         genDivbits(left,right,result);
3810         goto release ;
3811     }
3812
3813     /* if both are of size == 1 */
3814     if (AOP_SIZE(left) == 1 &&
3815         AOP_SIZE(right) == 1 ) {
3816         genDivOneByte(left,right,result);
3817         goto release ;
3818     }
3819
3820     /* should have been converted to function call */
3821     assert(1);
3822 release :
3823     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3824     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3825     freeAsmop(result,NULL,ic,TRUE); 
3826 }
3827
3828 /*-----------------------------------------------------------------*/
3829 /* genModbits :- modulus of bits                                   */
3830 /*-----------------------------------------------------------------*/
3831 static void genModbits (operand *left, 
3832                         operand *right, 
3833                         operand *result)
3834 {
3835
3836     char *l;
3837
3838     /* the result must be bit */    
3839     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3840     l = aopGet(AOP(left),0,FALSE,FALSE);
3841
3842     MOVA(l);       
3843
3844     emitcode("div","ab");
3845     emitcode("mov","a,b");
3846     emitcode("rrc","a");
3847     aopPut(AOP(result),"c",0);
3848 }
3849
3850 /*-----------------------------------------------------------------*/
3851 /* genModOneByte : 8 bit modulus                                   */
3852 /*-----------------------------------------------------------------*/
3853 static void genModOneByte (operand *left,
3854                            operand *right,
3855                            operand *result)
3856 {
3857     sym_link *opetype = operandType(result);
3858     char *l ;
3859     symbol *lbl ;
3860
3861     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3862     /* signed or unsigned */
3863     if (SPEC_USIGN(opetype)) {
3864         /* unsigned is easy */
3865         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3866         l = aopGet(AOP(left),0,FALSE,FALSE);
3867         MOVA(l);    
3868         emitcode("div","ab");
3869         aopPut(AOP(result),"b",0);
3870         return ;
3871     }
3872
3873     /* signed is a little bit more difficult */
3874
3875     /* save the signs of the operands */
3876     l = aopGet(AOP(left),0,FALSE,FALSE);    
3877     MOVA(l);
3878
3879     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3880     emitcode("push","acc"); /* save it on the stack */
3881
3882     /* now sign adjust for both left & right */
3883     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3884     MOVA(l);
3885
3886     lbl = newiTempLabel(NULL);
3887     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3888     emitcode("cpl","a");   
3889     emitcode("inc","a");
3890     emitcode("","%05d_DS_:",(lbl->key+100));
3891     emitcode("mov","b,a"); 
3892
3893     /* sign adjust left side */
3894     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3895     MOVA(l);
3896
3897     lbl = newiTempLabel(NULL);
3898     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3899     emitcode("cpl","a");   
3900     emitcode("inc","a");
3901     emitcode("","%05d_DS_:",(lbl->key+100));
3902
3903     /* now the multiplication */
3904     emitcode("div","ab");
3905     /* we are interested in the lower order
3906     only */
3907     lbl = newiTempLabel(NULL);
3908     emitcode("pop","acc");   
3909     /* if there was an over flow we don't 
3910     adjust the sign of the result */
3911     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3912     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3913     CLRC ;
3914     emitcode("clr","a");
3915     emitcode("subb","a,b");
3916     emitcode("mov","b,a");
3917     emitcode("","%05d_DS_:",(lbl->key+100));
3918
3919     /* now we are done */
3920     aopPut(AOP(result),"b",0);
3921
3922 }
3923
3924 /*-----------------------------------------------------------------*/
3925 /* genMod - generates code for division                            */
3926 /*-----------------------------------------------------------------*/
3927 static void genMod (iCode *ic)
3928 {
3929     operand *left = IC_LEFT(ic);
3930     operand *right = IC_RIGHT(ic);
3931     operand *result= IC_RESULT(ic);  
3932
3933     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3934     /* assign the amsops */
3935     aopOp (left,ic,FALSE);
3936     aopOp (right,ic,FALSE);
3937     aopOp (result,ic,TRUE);
3938
3939     /* special cases first */
3940     /* both are bits */
3941     if (AOP_TYPE(left) == AOP_CRY &&
3942         AOP_TYPE(right)== AOP_CRY) {
3943         genModbits(left,right,result);
3944         goto release ;
3945     }
3946
3947     /* if both are of size == 1 */
3948     if (AOP_SIZE(left) == 1 &&
3949         AOP_SIZE(right) == 1 ) {
3950         genModOneByte(left,right,result);
3951         goto release ;
3952     }
3953
3954     /* should have been converted to function call */
3955     assert(1);
3956
3957 release :
3958     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3959     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3960     freeAsmop(result,NULL,ic,TRUE); 
3961 }
3962
3963 /*-----------------------------------------------------------------*/
3964 /* genIfxJump :- will create a jump depending on the ifx           */
3965 /*-----------------------------------------------------------------*/
3966 static void genIfxJump (iCode *ic, char *jval)
3967 {
3968
3969     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3970     /* if true label then we jump if condition
3971     supplied is true */
3972     if ( IC_TRUE(ic) ) {
3973
3974         if(strcmp(jval,"a") == 0)
3975           emitSKPZ;
3976         else if (strcmp(jval,"c") == 0)
3977           emitSKPC;
3978         else {
3979           //pCodeOp *p = popGetWithString(jval);
3980           //p->type = PO_BIT;
3981           //emitpcode(POC_BTFSC,  p);
3982           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,0));
3983         //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3984         }
3985
3986         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3987         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3988
3989     }
3990     else {
3991         /* false label is present */
3992         if(strcmp(jval,"a") == 0)
3993           emitSKPNZ;
3994         else if (strcmp(jval,"c") == 0)
3995           emitSKPNC;
3996         else {
3997           //pCodeOp *p = popGetWithString(jval);
3998           //p->type = PO_BIT;
3999           //emitpcode(POC_BTFSS,  p);
4000           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,0));
4001
4002         //        emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4003         }
4004
4005         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4006         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4007
4008     }
4009
4010
4011     /* mark the icode as generated */
4012     ic->generated = 1;
4013 }
4014
4015 /*-----------------------------------------------------------------*/
4016 /* genSkip                                                         */
4017 /*-----------------------------------------------------------------*/
4018 static void genSkip(iCode *ifx,int status_bit)
4019 {
4020   if(!ifx)
4021     return;
4022
4023   if ( IC_TRUE(ifx) ) {
4024     switch(status_bit) {
4025     case 'z':
4026       emitSKPNZ;
4027       break;
4028
4029     case 'c':
4030       emitSKPNC;
4031       break;
4032
4033     case 'd':
4034       emitcode("skpndc","");
4035       break;
4036
4037     }
4038
4039     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4040     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4041
4042   } else {
4043
4044     switch(status_bit) {
4045
4046     case 'z':
4047       emitSKPZ;
4048       break;
4049
4050     case 'c':
4051       emitSKPC;
4052       break;
4053
4054     case 'd':
4055       emitcode("skpdc","");
4056       break;
4057     }
4058     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4059     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4060
4061   }
4062
4063 }
4064
4065 /*-----------------------------------------------------------------*/
4066 /* genSkipc                                                        */
4067 /*-----------------------------------------------------------------*/
4068 static void genSkipc(iCode *ifx, int condition)
4069 {
4070   if(!ifx)
4071     return;
4072
4073   if(condition)
4074     emitSKPNC;
4075   else
4076     emitSKPC;
4077
4078   if ( IC_TRUE(ifx) )
4079     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4080   else
4081     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4082
4083   if ( IC_TRUE(ifx) )
4084     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4085   else
4086     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4087
4088 }
4089
4090 /*-----------------------------------------------------------------*/
4091 /* genSkipz                                                        */
4092 /*-----------------------------------------------------------------*/
4093 static void genSkipz(iCode *ifx, int condition)
4094 {
4095   if(!ifx)
4096     return;
4097
4098   if(condition)
4099     emitSKPNZ;
4100   else
4101     emitSKPZ;
4102
4103   if ( IC_TRUE(ifx) )
4104     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4105   else
4106     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4107
4108   if ( IC_TRUE(ifx) )
4109     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4110   else
4111     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4112
4113 }
4114 /*-----------------------------------------------------------------*/
4115 /* genCmp :- greater or less than comparison                       */
4116 /*-----------------------------------------------------------------*/
4117 static void genCmp (operand *left,operand *right,
4118                     operand *result, iCode *ifx, int sign)
4119 {
4120   int size, offset = 0 ;
4121   unsigned long lit = 0L,i = 0;
4122
4123   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4124   /* if left & right are bit variables */
4125   if (AOP_TYPE(left) == AOP_CRY &&
4126       AOP_TYPE(right) == AOP_CRY ) {
4127     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4128     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4129   } else {
4130     /* subtract right from left if at the
4131        end the carry flag is set then we know that
4132        left is greater than right */
4133     size = max(AOP_SIZE(left),AOP_SIZE(right));
4134
4135     /* if unsigned char cmp with lit, do cjne left,#right,zz */
4136     if((size == 1) && !sign &&
4137        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4138       symbol *lbl  = newiTempLabel(NULL);
4139       emitcode("cjne","%s,%s,%05d_DS_",
4140                aopGet(AOP(left),offset,FALSE,FALSE),
4141                aopGet(AOP(right),offset,FALSE,FALSE),
4142                lbl->key+100);
4143       emitcode("","%05d_DS_:",lbl->key+100);
4144     } else {
4145
4146       if(AOP_TYPE(right) == AOP_LIT) {
4147
4148         DEBUGemitcode(";right lit","%d",sign);
4149
4150         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4151         //default:
4152         while(size--) {
4153           i = (lit >> (size*8)) & 0xff;
4154           if(i == 0) {
4155             emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4156             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4157             genSkipz(ifx,IC_TRUE(ifx) == NULL);
4158           } else {
4159             emitpcode(POC_MOVLW, popGetLit(i));
4160             emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4161
4162             emitcode("movlw","0x%x",i);
4163             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4164             genSkipc(ifx,IC_TRUE(ifx) == NULL);
4165           }
4166
4167         }
4168         ifx->generated = 1;
4169         return;
4170       }
4171       if(AOP_TYPE(left) == AOP_LIT) {
4172
4173         DEBUGemitcode(";left lit","%d",sign);
4174
4175         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4176
4177         //default:
4178         while(size--) {
4179           i = (lit >> (size*8)) & 0xff;
4180           if(i == 0) {
4181             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4182             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4183             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4184           } else if( i == 1 ) {
4185             emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4186             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4187             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4188
4189           } else {
4190             emitpcode(POC_MOVLW, popGetLit(i));
4191             emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4192
4193             emitcode("movlw","0x%x",i);
4194             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4195             genSkipc(ifx,IC_TRUE(ifx) != NULL);
4196           }
4197         }
4198         ifx->generated = 1;
4199         return;
4200       }
4201
4202
4203       // CLRC;
4204       DEBUGemitcode(";sign","%d",sign);
4205
4206       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4207       emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4208
4209       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4210       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4211
4212       size--;
4213       while (size--) {
4214
4215         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
4216         emitSKPC;
4217         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4218         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
4219
4220 /*
4221         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4222         emitSKPC;
4223         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4224         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4225 */
4226         offset++;
4227       }
4228     }
4229   }
4230
4231   //release:
4232   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4233     outBitC(result);
4234   } else {
4235     /* if the result is used in the next
4236        ifx conditional branch then generate
4237        code a little differently */
4238     if (ifx )
4239       genIfxJump (ifx,"c");
4240     else
4241       outBitC(result);
4242     /* leave the result in acc */
4243   }
4244
4245 }
4246
4247 /*-----------------------------------------------------------------*/
4248 /* genCmpGt :- greater than comparison                             */
4249 /*-----------------------------------------------------------------*/
4250 static void genCmpGt (iCode *ic, iCode *ifx)
4251 {
4252     operand *left, *right, *result;
4253     sym_link *letype , *retype;
4254     int sign ;
4255
4256     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4257     left = IC_LEFT(ic);
4258     right= IC_RIGHT(ic);
4259     result = IC_RESULT(ic);
4260
4261     letype = getSpec(operandType(left));
4262     retype =getSpec(operandType(right));
4263     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4264     /* assign the amsops */
4265     aopOp (left,ic,FALSE);
4266     aopOp (right,ic,FALSE);
4267     aopOp (result,ic,TRUE);
4268
4269     genCmp(right, left, result, ifx, sign);
4270
4271     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273     freeAsmop(result,NULL,ic,TRUE); 
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genCmpLt - less than comparisons                                */
4278 /*-----------------------------------------------------------------*/
4279 static void genCmpLt (iCode *ic, iCode *ifx)
4280 {
4281     operand *left, *right, *result;
4282     sym_link *letype , *retype;
4283     int sign ;
4284
4285     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4286     left = IC_LEFT(ic);
4287     right= IC_RIGHT(ic);
4288     result = IC_RESULT(ic);
4289
4290     letype = getSpec(operandType(left));
4291     retype =getSpec(operandType(right));
4292     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4293
4294     /* assign the amsops */
4295     aopOp (left,ic,FALSE);
4296     aopOp (right,ic,FALSE);
4297     aopOp (result,ic,TRUE);
4298
4299     genCmp(left, right, result, ifx, sign);
4300
4301     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4302     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4303     freeAsmop(result,NULL,ic,TRUE); 
4304 }
4305
4306 /*-----------------------------------------------------------------*/
4307 /* gencjneshort - compare and jump if not equal                    */
4308 /*-----------------------------------------------------------------*/
4309 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4310 {
4311     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4312     int offset = 0;
4313     unsigned long lit = 0L;
4314
4315     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4316     /* if the left side is a literal or 
4317     if the right is in a pointer register and left 
4318     is not */
4319     if ((AOP_TYPE(left) == AOP_LIT) || 
4320         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4321         operand *t = right;
4322         right = left;
4323         left = t;
4324     }
4325     if(AOP_TYPE(right) == AOP_LIT)
4326         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4327
4328     /* if the right side is a literal then anything goes */
4329     if (AOP_TYPE(right) == AOP_LIT &&
4330         AOP_TYPE(left) != AOP_DIR ) {
4331         while (size--) {
4332           if(lit & 0xff) {
4333             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4334             emitcode("xorlw","0x%x",lit & 0xff);
4335           } else
4336             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4337
4338           emitSKPNZ;
4339           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4340           offset++;
4341           lit >>= 8;
4342         }
4343     }
4344
4345     /* if the right side is in a register or in direct space or
4346     if the left is a pointer register & right is not */    
4347     else if (AOP_TYPE(right) == AOP_REG ||
4348              AOP_TYPE(right) == AOP_DIR || 
4349              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4350              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4351         while (size--) {
4352           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4353              ( (lit & 0xff) != 0)) {
4354             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4355             emitcode("xorlw","0x%x",lit & 0xff);
4356             lit >>= 8;
4357           } else
4358             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4359
4360           emitSKPZ;
4361           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4362           offset++;
4363 /*
4364             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4365             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4366                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4367                 emitcode("jnz","%05d_DS_",lbl->key+100);
4368             else
4369                 emitcode("cjne","a,%s,%05d_DS_",
4370                          aopGet(AOP(right),offset,FALSE,TRUE),
4371                          lbl->key+100);
4372             offset++;
4373 */
4374         }
4375     } else {
4376         /* right is a pointer reg need both a & b */
4377         while(size--) {
4378             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4379             if(strcmp(l,"b"))
4380                 emitcode("mov","b,%s",l);
4381             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4382             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4383             offset++;
4384         }
4385     }
4386 }
4387
4388 /*-----------------------------------------------------------------*/
4389 /* gencjne - compare and jump if not equal                         */
4390 /*-----------------------------------------------------------------*/
4391 static void gencjne(operand *left, operand *right, symbol *lbl)
4392 {
4393     symbol *tlbl  = newiTempLabel(NULL);
4394
4395     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4396     gencjneshort(left, right, lbl);
4397
4398     emitcode("mov","a,%s",one);
4399     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4400     emitcode("","%05d_DS_:",lbl->key+100);
4401     emitcode("clr","a");
4402     emitcode("","%05d_DS_:",tlbl->key+100);
4403 }
4404
4405
4406 /*-----------------------------------------------------------------*/
4407 /* genCmpEq - generates code for equal to                          */
4408 /*-----------------------------------------------------------------*/
4409 static void genCmpEq (iCode *ic, iCode *ifx)
4410 {
4411     operand *left, *right, *result;
4412     unsigned long lit = 0L;
4413     int size,offset=0;
4414
4415     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4416     if(ifx)
4417       DEBUGemitcode ("; ifx is non-null","");
4418     else
4419       DEBUGemitcode ("; ifx is null","");
4420
4421     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4422     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4423     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4424
4425     size = max(AOP_SIZE(left),AOP_SIZE(right));
4426
4427     /* if literal, literal on the right or 
4428     if the right is in a pointer register and left 
4429     is not */
4430     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4431         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4432         operand *t = IC_RIGHT(ic);
4433         IC_RIGHT(ic) = IC_LEFT(ic);
4434         IC_LEFT(ic) = t;
4435     }
4436
4437     if(ifx && !AOP_SIZE(result)){
4438         symbol *tlbl;
4439         /* if they are both bit variables */
4440         if (AOP_TYPE(left) == AOP_CRY &&
4441             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4442             if(AOP_TYPE(right) == AOP_LIT){
4443                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4444                 if(lit == 0L){
4445                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4446                     emitcode("cpl","c");
4447                 } else if(lit == 1L) {
4448                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4449                 } else {
4450                     emitcode("clr","c");
4451                 }
4452                 /* AOP_TYPE(right) == AOP_CRY */
4453             } else {
4454                 symbol *lbl = newiTempLabel(NULL);
4455                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4456                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4457                 emitcode("cpl","c");
4458                 emitcode("","%05d_DS_:",(lbl->key+100));
4459             }
4460             /* if true label then we jump if condition
4461             supplied is true */
4462             tlbl = newiTempLabel(NULL);
4463             if ( IC_TRUE(ifx) ) {
4464                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4465                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4466             } else {
4467                 emitcode("jc","%05d_DS_",tlbl->key+100);
4468                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4469             }
4470             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4471         } else {
4472
4473           /* They're not both bit variables. Is the right a literal? */
4474           if(AOP_TYPE(right) == AOP_LIT) {
4475
4476             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4477             while (size--) {
4478
4479               if(size >= 1) {
4480                 int l = lit & 0xff;
4481                 int h = (lit>>8) & 0xff;
4482                 int optimized=0;
4483
4484                 /* Check special cases for integers */
4485                 switch(lit & 0xffff) {
4486                 case 0x0000:
4487                   emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4488                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4489                   //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4490                   //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4491                   genSkip(ifx,'z');
4492                   optimized++;
4493                   break;
4494                 case 0x0001:
4495                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4496                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4497                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4498                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4499                   genSkip(ifx,'z');
4500                   optimized++;
4501                   break;
4502                 case 0x0100:
4503                   emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4504                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4505                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4506                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4507                   genSkip(ifx,'z');
4508                   optimized++;
4509                   break;
4510                 case 0x00ff:
4511                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4512                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4513                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4514                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4515                   genSkip(ifx,'z');
4516                   optimized++;
4517                   break;
4518                 case 0xff00:
4519                   emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4520                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4521                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4522                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4523                   genSkip(ifx,'z');
4524                   optimized++;
4525                   break;
4526                 default:
4527                   if(h == 0) {
4528                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4529                     emitpcode(POC_XORLW,popGetLit(l));
4530                     emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4531
4532                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4533                     emitcode("xorlw","0x%x",l);
4534                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4535                     optimized++;
4536                     genSkip(ifx,'z');
4537                   } else if (l == 0) {
4538                     emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4539                     emitpcode(POC_XORLW,popGetLit(h));
4540                     emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4541
4542                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4543                     emitcode("xorlw","0x%x",h);
4544                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4545                     optimized++;
4546                     genSkip(ifx,'z');
4547                   } else {
4548                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4549                     emitpcode(POC_XORLW,popGetLit(l));
4550                     emitpcode(POC_MOVLW,popGetLit(h));
4551                     emitSKPZ;
4552                     emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4553 /*
4554                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4555                     emitcode("xorlw","0x%x",l);
4556                     emitcode("movlw","0x%x",h);
4557                     emitSKPZ;
4558                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4559 */
4560                     optimized++;
4561                     genSkip(ifx,'z');
4562                   }
4563
4564                 }
4565                 if(optimized) {
4566                   size--;
4567                   offset+=2;
4568                   lit>>=16;
4569
4570                   continue;
4571                 }
4572                   
4573               }
4574                 
4575               switch(lit & 0xff) {
4576               case 1:
4577                 if ( IC_TRUE(ifx) ) {
4578
4579                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4580
4581                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4582                   emitSKPNZ;
4583                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4584
4585                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4586                 } else {
4587                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4588                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4589
4590                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4591                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4592                 }
4593                 break;
4594               case 0xff:
4595                 if ( IC_TRUE(ifx) ) {
4596                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4597
4598                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4599                   emitSKPNZ;
4600                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4601
4602                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4603                 } else {
4604                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4605                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4606
4607                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4608                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4609                 }
4610                 break;
4611               default:
4612                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4613                 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4614                 if(lit)
4615                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4616                 //emitcode("xorlw","0x%x",lit & 0xff);
4617                 genSkip(ifx,'z');
4618               }
4619
4620
4621               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4622               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4623               offset++;
4624               lit >>= 8;
4625             }
4626
4627           } else if(AOP_TYPE(right) == AOP_CRY ) {
4628             /* we know the left is not a bit, but that the right is */
4629             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4630             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4631                       popGet(AOP(right),offset,FALSE,FALSE));
4632             emitpcode(POC_XORLW,popGetLit(1));
4633
4634             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4635             if ( IC_TRUE(ifx) )
4636               emitcode("btfsc","(%s >> 3), (%s & 7)",
4637                        AOP(right)->aopu.aop_dir,
4638                        AOP(right)->aopu.aop_dir);
4639             else
4640               emitcode("btfss","(%s >> 3), (%s & 7)",
4641                        AOP(right)->aopu.aop_dir,
4642                        AOP(right)->aopu.aop_dir);
4643
4644             emitcode("xorlw","1");
4645
4646             /* if the two are equal, then W will be 0 and the Z bit is set
4647              * we could test Z now, or go ahead and check the high order bytes if
4648              * the variable we're comparing is larger than a byte. */
4649
4650             while(--size)
4651               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4652             //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4653
4654             if ( IC_TRUE(ifx) ) {
4655               emitSKPNZ;
4656               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4657               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4658             } else {
4659               emitSKPZ;
4660               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4661               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4662             }
4663
4664           } else {
4665             /* They're both variables that are larger than bits */
4666             int s = size;
4667
4668             tlbl = newiTempLabel(NULL);
4669
4670             while(size--) {
4671               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4672               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4673
4674               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4675               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4676
4677               if ( IC_TRUE(ifx) ) {
4678                 if(size) {
4679                   emitSKPZ;
4680                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4681                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4682                 } else {
4683                   emitSKPNZ;
4684                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4685                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4686                 }
4687               } else {
4688                 emitSKPZ;
4689                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4690                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4691               }
4692               offset++;
4693             }
4694             if(s>1 && IC_TRUE(ifx)) {
4695               emitpLabel(tlbl->key+100+labelOffset);
4696               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4697             }
4698           }
4699         }
4700         /* mark the icode as generated */
4701         ifx->generated = 1;
4702         goto release ;
4703     }
4704
4705     /* if they are both bit variables */
4706     if (AOP_TYPE(left) == AOP_CRY &&
4707         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4708         if(AOP_TYPE(right) == AOP_LIT){
4709             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4710             if(lit == 0L){
4711                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4712                 emitcode("cpl","c");
4713             } else if(lit == 1L) {
4714                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4715             } else {
4716                 emitcode("clr","c");
4717             }
4718             /* AOP_TYPE(right) == AOP_CRY */
4719         } else {
4720             symbol *lbl = newiTempLabel(NULL);
4721             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4722             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4723             emitcode("cpl","c");
4724             emitcode("","%05d_DS_:",(lbl->key+100));
4725         }
4726         /* c = 1 if egal */
4727         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4728             outBitC(result);
4729             goto release ;
4730         }
4731         if (ifx) {
4732             genIfxJump (ifx,"c");
4733             goto release ;
4734         }
4735         /* if the result is used in an arithmetic operation
4736         then put the result in place */
4737         outBitC(result);
4738     } else {
4739         gencjne(left,right,newiTempLabel(NULL));    
4740         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4741             aopPut(AOP(result),"a",0);
4742             goto release ;
4743         }
4744         if (ifx) {
4745             genIfxJump (ifx,"a");
4746             goto release ;
4747         }
4748         /* if the result is used in an arithmetic operation
4749         then put the result in place */
4750         if (AOP_TYPE(result) != AOP_CRY) 
4751             outAcc(result);
4752         /* leave the result in acc */
4753     }
4754
4755 release:
4756     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4757     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4758     freeAsmop(result,NULL,ic,TRUE);
4759 }
4760
4761 /*-----------------------------------------------------------------*/
4762 /* ifxForOp - returns the icode containing the ifx for operand     */
4763 /*-----------------------------------------------------------------*/
4764 static iCode *ifxForOp ( operand *op, iCode *ic )
4765 {
4766     /* if true symbol then needs to be assigned */
4767     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4768     if (IS_TRUE_SYMOP(op))
4769         return NULL ;
4770
4771     /* if this has register type condition and
4772     the next instruction is ifx with the same operand
4773     and live to of the operand is upto the ifx only then */
4774     if (ic->next &&
4775         ic->next->op == IFX &&
4776         IC_COND(ic->next)->key == op->key &&
4777         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4778         return ic->next;
4779
4780     return NULL;
4781 }
4782 /*-----------------------------------------------------------------*/
4783 /* genAndOp - for && operation                                     */
4784 /*-----------------------------------------------------------------*/
4785 static void genAndOp (iCode *ic)
4786 {
4787     operand *left,*right, *result;
4788     symbol *tlbl;
4789
4790     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4791     /* note here that && operations that are in an
4792     if statement are taken away by backPatchLabels
4793     only those used in arthmetic operations remain */
4794     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4795     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4796     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4797
4798     /* if both are bit variables */
4799     if (AOP_TYPE(left) == AOP_CRY &&
4800         AOP_TYPE(right) == AOP_CRY ) {
4801         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4802         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4803         outBitC(result);
4804     } else {
4805         tlbl = newiTempLabel(NULL);
4806         toBoolean(left);    
4807         emitcode("jz","%05d_DS_",tlbl->key+100);
4808         toBoolean(right);
4809         emitcode("","%05d_DS_:",tlbl->key+100);
4810         outBitAcc(result);
4811     }
4812
4813     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4814     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4815     freeAsmop(result,NULL,ic,TRUE);
4816 }
4817
4818
4819 /*-----------------------------------------------------------------*/
4820 /* genOrOp - for || operation                                      */
4821 /*-----------------------------------------------------------------*/
4822 /*
4823   tsd pic port -
4824   modified this code, but it doesn't appear to ever get called
4825 */
4826
4827 static void genOrOp (iCode *ic)
4828 {
4829     operand *left,*right, *result;
4830     symbol *tlbl;
4831
4832     /* note here that || operations that are in an
4833     if statement are taken away by backPatchLabels
4834     only those used in arthmetic operations remain */
4835     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4836     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4837     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4838     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4839
4840     /* if both are bit variables */
4841     if (AOP_TYPE(left) == AOP_CRY &&
4842         AOP_TYPE(right) == AOP_CRY ) {
4843       emitcode("clrc","");
4844       emitcode("btfss","(%s >> 3), (%s & 7)",
4845                AOP(left)->aopu.aop_dir,
4846                AOP(left)->aopu.aop_dir);
4847       emitcode("btfsc","(%s >> 3), (%s & 7)",
4848                AOP(right)->aopu.aop_dir,
4849                AOP(right)->aopu.aop_dir);
4850       emitcode("setc","");
4851
4852     } else {
4853         tlbl = newiTempLabel(NULL);
4854         toBoolean(left);
4855         emitSKPZ;
4856         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4857         toBoolean(right);
4858         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4859
4860         outBitAcc(result);
4861     }
4862
4863     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865     freeAsmop(result,NULL,ic,TRUE);            
4866 }
4867
4868 /*-----------------------------------------------------------------*/
4869 /* isLiteralBit - test if lit == 2^n                               */
4870 /*-----------------------------------------------------------------*/
4871 static int isLiteralBit(unsigned long lit)
4872 {
4873     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4874     0x100L,0x200L,0x400L,0x800L,
4875     0x1000L,0x2000L,0x4000L,0x8000L,
4876     0x10000L,0x20000L,0x40000L,0x80000L,
4877     0x100000L,0x200000L,0x400000L,0x800000L,
4878     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4879     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4880     int idx;
4881     
4882     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4883     for(idx = 0; idx < 32; idx++)
4884         if(lit == pw[idx])
4885             return idx+1;
4886     return 0;
4887 }
4888
4889 /*-----------------------------------------------------------------*/
4890 /* continueIfTrue -                                                */
4891 /*-----------------------------------------------------------------*/
4892 static void continueIfTrue (iCode *ic)
4893 {
4894     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4895     if(IC_TRUE(ic))
4896         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4897     ic->generated = 1;
4898 }
4899
4900 /*-----------------------------------------------------------------*/
4901 /* jmpIfTrue -                                                     */
4902 /*-----------------------------------------------------------------*/
4903 static void jumpIfTrue (iCode *ic)
4904 {
4905     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4906     if(!IC_TRUE(ic))
4907         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4908     ic->generated = 1;
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* jmpTrueOrFalse -                                                */
4913 /*-----------------------------------------------------------------*/
4914 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4915 {
4916     // ugly but optimized by peephole
4917     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4918     if(IC_TRUE(ic)){
4919         symbol *nlbl = newiTempLabel(NULL);
4920         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4921         emitcode("","%05d_DS_:",tlbl->key+100);
4922         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4923         emitcode("","%05d_DS_:",nlbl->key+100);
4924     }
4925     else{
4926         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4927         emitcode("","%05d_DS_:",tlbl->key+100);
4928     }
4929     ic->generated = 1;
4930 }
4931
4932 /*-----------------------------------------------------------------*/
4933 /* genAnd  - code for and                                          */
4934 /*-----------------------------------------------------------------*/
4935 static void genAnd (iCode *ic, iCode *ifx)
4936 {
4937     operand *left, *right, *result;
4938     int size, offset=0;  
4939     unsigned long lit = 0L;
4940     int bytelit = 0;
4941     char buffer[10];
4942
4943     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4944     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4945     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4946     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4947
4948 #ifdef DEBUG_TYPE
4949     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4950              AOP_TYPE(result),
4951              AOP_TYPE(left), AOP_TYPE(right));
4952     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4953              AOP_SIZE(result),
4954              AOP_SIZE(left), AOP_SIZE(right));
4955 #endif
4956
4957     /* if left is a literal & right is not then exchange them */
4958     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4959         AOP_NEEDSACC(left)) {
4960         operand *tmp = right ;
4961         right = left;
4962         left = tmp;
4963     }
4964
4965     /* if result = right then exchange them */
4966     if(sameRegs(AOP(result),AOP(right))){
4967         operand *tmp = right ;
4968         right = left;
4969         left = tmp;
4970     }
4971
4972     /* if right is bit then exchange them */
4973     if (AOP_TYPE(right) == AOP_CRY &&
4974         AOP_TYPE(left) != AOP_CRY){
4975         operand *tmp = right ;
4976         right = left;
4977         left = tmp;
4978     }
4979     if(AOP_TYPE(right) == AOP_LIT)
4980         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4981
4982     size = AOP_SIZE(result);
4983
4984     // if(bit & yy)
4985     // result = bit & yy;
4986     if (AOP_TYPE(left) == AOP_CRY){
4987         // c = bit & literal;
4988         if(AOP_TYPE(right) == AOP_LIT){
4989             if(lit & 1) {
4990                 if(size && sameRegs(AOP(result),AOP(left)))
4991                     // no change
4992                     goto release;
4993                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4994             } else {
4995                 // bit(result) = 0;
4996                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4997                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4998                     goto release;
4999                 }
5000                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5001                     jumpIfTrue(ifx);
5002                     goto release;
5003                 }
5004                 emitcode("clr","c");
5005             }
5006         } else {
5007             if (AOP_TYPE(right) == AOP_CRY){
5008                 // c = bit & bit;
5009                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5010                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5011             } else {
5012                 // c = bit & val;
5013                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5014                 // c = lsb
5015                 emitcode("rrc","a");
5016                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5017             }
5018         }
5019         // bit = c
5020         // val = c
5021         if(size)
5022             outBitC(result);
5023         // if(bit & ...)
5024         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5025             genIfxJump(ifx, "c");           
5026         goto release ;
5027     }
5028
5029     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5030     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5031     if((AOP_TYPE(right) == AOP_LIT) &&
5032        (AOP_TYPE(result) == AOP_CRY) &&
5033        (AOP_TYPE(left) != AOP_CRY)){
5034         int posbit = isLiteralBit(lit);
5035         /* left &  2^n */
5036         if(posbit){
5037             posbit--;
5038             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5039             // bit = left & 2^n
5040             if(size)
5041                 emitcode("mov","c,acc.%d",posbit&0x07);
5042             // if(left &  2^n)
5043             else{
5044                 if(ifx){
5045                     sprintf(buffer,"acc.%d",posbit&0x07);
5046                     genIfxJump(ifx, buffer);
5047                 }
5048                 goto release;
5049             }
5050         } else {
5051             symbol *tlbl = newiTempLabel(NULL);
5052             int sizel = AOP_SIZE(left);
5053             if(size)
5054                 emitcode("setb","c");
5055             while(sizel--){
5056                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5057                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5058                     // byte ==  2^n ?
5059                     if((posbit = isLiteralBit(bytelit)) != 0)
5060                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5061                     else{
5062                         if(bytelit != 0x0FFL)
5063                             emitcode("anl","a,%s",
5064                                      aopGet(AOP(right),offset,FALSE,TRUE));
5065                         emitcode("jnz","%05d_DS_",tlbl->key+100);
5066                     }
5067                 }
5068                 offset++;
5069             }
5070             // bit = left & literal
5071             if(size){
5072                 emitcode("clr","c");
5073                 emitcode("","%05d_DS_:",tlbl->key+100);
5074             }
5075             // if(left & literal)
5076             else{
5077                 if(ifx)
5078                     jmpTrueOrFalse(ifx, tlbl);
5079                 goto release ;
5080             }
5081         }
5082         outBitC(result);
5083         goto release ;
5084     }
5085
5086     /* if left is same as result */
5087     if(sameRegs(AOP(result),AOP(left))){
5088       for(;size--; offset++,lit>>=8) {
5089         if(AOP_TYPE(right) == AOP_LIT){
5090           switch(lit & 0xff) {
5091           case 0x00:
5092             /*  and'ing with 0 has clears the result */
5093             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5094             break;
5095           case 0xff:
5096             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5097             break;
5098
5099           default:
5100             {
5101               int p = my_powof2( (~lit) & 0xff );
5102               if(p>=0) {
5103                 /* only one bit is set in the literal, so use a bcf instruction */
5104                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5105               } else {
5106                 emitcode("movlw","0x%x", (lit & 0xff));
5107                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5108               }
5109             }    
5110           }
5111         } else {
5112           if (AOP_TYPE(left) == AOP_ACC) 
5113             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5114           else {                    
5115             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5116             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5117
5118           }
5119         }
5120       }
5121
5122     } else {
5123         // left & result in different registers
5124         if(AOP_TYPE(result) == AOP_CRY){
5125             // result = bit
5126             // if(size), result in bit
5127             // if(!size && ifx), conditional oper: if(left & right)
5128             symbol *tlbl = newiTempLabel(NULL);
5129             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5130             if(size)
5131                 emitcode("setb","c");
5132             while(sizer--){
5133                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5134                 emitcode("anl","a,%s",
5135                          aopGet(AOP(left),offset,FALSE,FALSE));
5136                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5137                 offset++;
5138             }
5139             if(size){
5140                 CLRC;
5141                 emitcode("","%05d_DS_:",tlbl->key+100);
5142                 outBitC(result);
5143             } else if(ifx)
5144                 jmpTrueOrFalse(ifx, tlbl);
5145         } else {
5146           for(;(size--);offset++) {
5147             // normal case
5148             // result = left & right
5149             if(AOP_TYPE(right) == AOP_LIT){
5150               int t = (lit >> (offset*8)) & 0x0FFL;
5151               switch(t) { 
5152               case 0x00:
5153                 emitcode("clrf","%s",
5154                          aopGet(AOP(result),offset,FALSE,FALSE));
5155                 break;
5156               case 0xff:
5157                 emitcode("movf","%s,w",
5158                          aopGet(AOP(left),offset,FALSE,FALSE));
5159                 emitcode("movwf","%s",
5160                          aopGet(AOP(result),offset,FALSE,FALSE));
5161                 break;
5162               default:
5163                 emitcode("movlw","0x%x",t);
5164                 emitcode("andwf","%s,w",
5165                          aopGet(AOP(left),offset,FALSE,FALSE));
5166                 emitcode("movwf","%s",
5167                          aopGet(AOP(result),offset,FALSE,FALSE));
5168               
5169               }
5170               continue;
5171             }
5172
5173             if (AOP_TYPE(left) == AOP_ACC) 
5174               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5175             else {
5176               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5177               emitcode("andwf","%s,w",
5178                        aopGet(AOP(left),offset,FALSE,FALSE));
5179             }
5180             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5181           }
5182         }
5183     }
5184
5185 release :
5186     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5187     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5188     freeAsmop(result,NULL,ic,TRUE);     
5189 }
5190
5191 /*-----------------------------------------------------------------*/
5192 /* genOr  - code for or                                            */
5193 /*-----------------------------------------------------------------*/
5194 static void genOr (iCode *ic, iCode *ifx)
5195 {
5196     operand *left, *right, *result;
5197     int size, offset=0;
5198     unsigned long lit = 0L;
5199
5200     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5201
5202     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5203     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5204     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5205
5206
5207     /* if left is a literal & right is not then exchange them */
5208     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5209         AOP_NEEDSACC(left)) {
5210         operand *tmp = right ;
5211         right = left;
5212         left = tmp;
5213     }
5214
5215     /* if result = right then exchange them */
5216     if(sameRegs(AOP(result),AOP(right))){
5217         operand *tmp = right ;
5218         right = left;
5219         left = tmp;
5220     }
5221
5222     /* if right is bit then exchange them */
5223     if (AOP_TYPE(right) == AOP_CRY &&
5224         AOP_TYPE(left) != AOP_CRY){
5225         operand *tmp = right ;
5226         right = left;
5227         left = tmp;
5228     }
5229
5230     if(AOP_TYPE(right) == AOP_LIT)
5231         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5232
5233     size = AOP_SIZE(result);
5234
5235     // if(bit | yy)
5236     // xx = bit | yy;
5237     if (AOP_TYPE(left) == AOP_CRY){
5238         if(AOP_TYPE(right) == AOP_LIT){
5239             // c = bit & literal;
5240             if(lit){
5241                 // lit != 0 => result = 1
5242                 if(AOP_TYPE(result) == AOP_CRY){
5243                   if(size)
5244                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5245                   //emitcode("bsf","(%s >> 3), (%s & 7)",
5246                   //     AOP(result)->aopu.aop_dir,
5247                   //     AOP(result)->aopu.aop_dir);
5248                     else if(ifx)
5249                         continueIfTrue(ifx);
5250                     goto release;
5251                 }
5252             } else {
5253                 // lit == 0 => result = left
5254                 if(size && sameRegs(AOP(result),AOP(left)))
5255                     goto release;
5256                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5257             }
5258         } else {
5259             if (AOP_TYPE(right) == AOP_CRY){
5260               if(sameRegs(AOP(result),AOP(left))){
5261                 // c = bit | bit;
5262                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5263                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5264                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5265
5266                 emitcode("bcf","(%s >> 3), (%s & 7)",
5267                          AOP(result)->aopu.aop_dir,
5268                          AOP(result)->aopu.aop_dir);
5269                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5270                          AOP(right)->aopu.aop_dir,
5271                          AOP(right)->aopu.aop_dir);
5272                 emitcode("bsf","(%s >> 3), (%s & 7)",
5273                          AOP(result)->aopu.aop_dir,
5274                          AOP(result)->aopu.aop_dir);
5275               } else {
5276
5277                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5278                 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5279                 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5280                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5281
5282                 emitcode("bcf","(%s >> 3), (%s & 7)",
5283                          AOP(result)->aopu.aop_dir,
5284                          AOP(result)->aopu.aop_dir);
5285                 emitcode("btfss","(%s >> 3), (%s & 7)",
5286                          AOP(right)->aopu.aop_dir,
5287                          AOP(right)->aopu.aop_dir);
5288                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5289                          AOP(left)->aopu.aop_dir,
5290                          AOP(left)->aopu.aop_dir);
5291                 emitcode("bsf","(%s >> 3), (%s & 7)",
5292                          AOP(result)->aopu.aop_dir,
5293                          AOP(result)->aopu.aop_dir);
5294               }
5295             }
5296             else{
5297                 // c = bit | val;
5298                 symbol *tlbl = newiTempLabel(NULL);
5299                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5300                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5301                     emitcode(";XXX setb","c");
5302                 emitcode(";XXX jb","%s,%05d_DS_",
5303                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5304                 toBoolean(right);
5305                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5306                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5307                     jmpTrueOrFalse(ifx, tlbl);
5308                     goto release;
5309                 } else {
5310                     CLRC;
5311                     emitcode("","%05d_DS_:",tlbl->key+100);
5312                 }
5313             }
5314         }
5315         // bit = c
5316         // val = c
5317         if(size)
5318             outBitC(result);
5319         // if(bit | ...)
5320         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5321             genIfxJump(ifx, "c");           
5322         goto release ;
5323     }
5324
5325     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5326     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5327     if((AOP_TYPE(right) == AOP_LIT) &&
5328        (AOP_TYPE(result) == AOP_CRY) &&
5329        (AOP_TYPE(left) != AOP_CRY)){
5330         if(lit){
5331           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5332             // result = 1
5333             if(size)
5334                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5335             else 
5336                 continueIfTrue(ifx);
5337             goto release;
5338         } else {
5339           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5340             // lit = 0, result = boolean(left)
5341             if(size)
5342                 emitcode(";XXX setb","c");
5343             toBoolean(right);
5344             if(size){
5345                 symbol *tlbl = newiTempLabel(NULL);
5346                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5347                 CLRC;
5348                 emitcode("","%05d_DS_:",tlbl->key+100);
5349             } else {
5350                 genIfxJump (ifx,"a");
5351                 goto release;
5352             }
5353         }
5354         outBitC(result);
5355         goto release ;
5356     }
5357
5358     /* if left is same as result */
5359     if(sameRegs(AOP(result),AOP(left))){
5360       for(;size--; offset++,lit>>=8) {
5361         if(AOP_TYPE(right) == AOP_LIT){
5362           if((lit & 0xff) == 0)
5363             /*  or'ing with 0 has no effect */
5364             continue;
5365           else {
5366             int p = my_powof2(lit & 0xff);
5367             if(p>=0) {
5368               /* only one bit is set in the literal, so use a bsf instruction */
5369               emitpcode(POC_BSF,   popGet(AOP(left),offset,FALSE,FALSE));
5370               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5371             } else {
5372               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5373               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5374
5375               emitcode("movlw","0x%x", (lit & 0xff));
5376               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5377             }
5378                     
5379           }
5380         } else {
5381           if (AOP_TYPE(left) == AOP_ACC) {
5382             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5383             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5384           } else {                  
5385             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5386             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5387
5388             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5389             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5390
5391           }
5392         }
5393       }
5394     } else {
5395         // left & result in different registers
5396         if(AOP_TYPE(result) == AOP_CRY){
5397             // result = bit
5398             // if(size), result in bit
5399             // if(!size && ifx), conditional oper: if(left | right)
5400             symbol *tlbl = newiTempLabel(NULL);
5401             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5402             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5403
5404             if(size)
5405                 emitcode(";XXX setb","c");
5406             while(sizer--){
5407                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5408                 emitcode(";XXX orl","a,%s",
5409                          aopGet(AOP(left),offset,FALSE,FALSE));
5410                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5411                 offset++;
5412             }
5413             if(size){
5414                 CLRC;
5415                 emitcode("","%05d_DS_:",tlbl->key+100);
5416                 outBitC(result);
5417             } else if(ifx)
5418                 jmpTrueOrFalse(ifx, tlbl);
5419         } else for(;(size--);offset++){
5420           // normal case
5421           // result = left & right
5422           if(AOP_TYPE(right) == AOP_LIT){
5423             int t = (lit >> (offset*8)) & 0x0FFL;
5424             switch(t) { 
5425             case 0x00:
5426               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5427               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5428
5429               emitcode("movf","%s,w",
5430                        aopGet(AOP(left),offset,FALSE,FALSE));
5431               emitcode("movwf","%s",
5432                        aopGet(AOP(result),offset,FALSE,FALSE));
5433               break;
5434             default:
5435               emitpcode(POC_MOVLW,  popGetLit(t));
5436               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5437               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5438
5439               emitcode("movlw","0x%x",t);
5440               emitcode("iorwf","%s,w",
5441                        aopGet(AOP(left),offset,FALSE,FALSE));
5442               emitcode("movwf","%s",
5443                        aopGet(AOP(result),offset,FALSE,FALSE));
5444               
5445             }
5446             continue;
5447           }
5448
5449           // faster than result <- left, anl result,right
5450           // and better if result is SFR
5451           if (AOP_TYPE(left) == AOP_ACC) {
5452             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5453             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5454           } else {
5455             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5456             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5457
5458             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5459             emitcode("iorwf","%s,w",
5460                      aopGet(AOP(left),offset,FALSE,FALSE));
5461           }
5462           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5463           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5464         }
5465     }
5466
5467 release :
5468     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5469     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5470     freeAsmop(result,NULL,ic,TRUE);     
5471 }
5472
5473 /*-----------------------------------------------------------------*/
5474 /* genXor - code for xclusive or                                   */
5475 /*-----------------------------------------------------------------*/
5476 static void genXor (iCode *ic, iCode *ifx)
5477 {
5478     operand *left, *right, *result;
5479     int size, offset=0;
5480     unsigned long lit = 0L;
5481
5482     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5483
5484     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5485     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5486     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5487
5488     /* if left is a literal & right is not ||
5489        if left needs acc & right does not */
5490     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5491         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5492         operand *tmp = right ;
5493         right = left;
5494         left = tmp;
5495     }
5496
5497     /* if result = right then exchange them */
5498     if(sameRegs(AOP(result),AOP(right))){
5499         operand *tmp = right ;
5500         right = left;
5501         left = tmp;
5502     }
5503
5504     /* if right is bit then exchange them */
5505     if (AOP_TYPE(right) == AOP_CRY &&
5506         AOP_TYPE(left) != AOP_CRY){
5507         operand *tmp = right ;
5508         right = left;
5509         left = tmp;
5510     }
5511     if(AOP_TYPE(right) == AOP_LIT)
5512         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5513
5514     size = AOP_SIZE(result);
5515
5516     // if(bit ^ yy)
5517     // xx = bit ^ yy;
5518     if (AOP_TYPE(left) == AOP_CRY){
5519         if(AOP_TYPE(right) == AOP_LIT){
5520             // c = bit & literal;
5521             if(lit>>1){
5522                 // lit>>1  != 0 => result = 1
5523                 if(AOP_TYPE(result) == AOP_CRY){
5524                     if(size)
5525                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5526                     else if(ifx)
5527                         continueIfTrue(ifx);
5528                     goto release;
5529                 }
5530                 emitcode("setb","c");
5531             } else{
5532                 // lit == (0 or 1)
5533                 if(lit == 0){
5534                     // lit == 0, result = left
5535                     if(size && sameRegs(AOP(result),AOP(left)))
5536                         goto release;
5537                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5538                 } else{
5539                     // lit == 1, result = not(left)
5540                     if(size && sameRegs(AOP(result),AOP(left))){
5541                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5542                         goto release;
5543                     } else {
5544                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5545                         emitcode("cpl","c");
5546                     }
5547                 }
5548             }
5549
5550         } else {
5551             // right != literal
5552             symbol *tlbl = newiTempLabel(NULL);
5553             if (AOP_TYPE(right) == AOP_CRY){
5554                 // c = bit ^ bit;
5555                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5556             }
5557             else{
5558                 int sizer = AOP_SIZE(right);
5559                 // c = bit ^ val
5560                 // if val>>1 != 0, result = 1
5561                 emitcode("setb","c");
5562                 while(sizer){
5563                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5564                     if(sizer == 1)
5565                         // test the msb of the lsb
5566                         emitcode("anl","a,#0xfe");
5567                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5568                     sizer--;
5569                 }
5570                 // val = (0,1)
5571                 emitcode("rrc","a");
5572             }
5573             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5574             emitcode("cpl","c");
5575             emitcode("","%05d_DS_:",(tlbl->key+100));
5576         }
5577         // bit = c
5578         // val = c
5579         if(size)
5580             outBitC(result);
5581         // if(bit | ...)
5582         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5583             genIfxJump(ifx, "c");           
5584         goto release ;
5585     }
5586
5587     if(sameRegs(AOP(result),AOP(left))){
5588         /* if left is same as result */
5589         for(;size--; offset++) {
5590             if(AOP_TYPE(right) == AOP_LIT){
5591                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5592                     continue;
5593                 else
5594                     if (IS_AOP_PREG(left)) {
5595                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5596                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5597                         aopPut(AOP(result),"a",offset);
5598                     } else 
5599                         emitcode("xrl","%s,%s",
5600                                  aopGet(AOP(left),offset,FALSE,TRUE),
5601                                  aopGet(AOP(right),offset,FALSE,FALSE));
5602             } else {
5603                 if (AOP_TYPE(left) == AOP_ACC)
5604                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5605                 else {
5606                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5607                     if (IS_AOP_PREG(left)) {
5608                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5609                         aopPut(AOP(result),"a",offset);
5610                     } else
5611                         emitcode("xrl","%s,a",
5612                                  aopGet(AOP(left),offset,FALSE,TRUE));
5613                 }
5614             }
5615         }
5616     } else {
5617         // left & result in different registers
5618         if(AOP_TYPE(result) == AOP_CRY){
5619             // result = bit
5620             // if(size), result in bit
5621             // if(!size && ifx), conditional oper: if(left ^ right)
5622             symbol *tlbl = newiTempLabel(NULL);
5623             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5624             if(size)
5625                 emitcode("setb","c");
5626             while(sizer--){
5627                 if((AOP_TYPE(right) == AOP_LIT) &&
5628                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5629                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5630                 } else {
5631                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5632                     emitcode("xrl","a,%s",
5633                              aopGet(AOP(left),offset,FALSE,FALSE));
5634                 }
5635                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5636                 offset++;
5637             }
5638             if(size){
5639                 CLRC;
5640                 emitcode("","%05d_DS_:",tlbl->key+100);
5641                 outBitC(result);
5642             } else if(ifx)
5643                 jmpTrueOrFalse(ifx, tlbl);
5644         } else for(;(size--);offset++){
5645             // normal case
5646             // result = left & right
5647             if(AOP_TYPE(right) == AOP_LIT){
5648               int t = (lit >> (offset*8)) & 0x0FFL;
5649               switch(t) { 
5650               case 0x00:
5651                 emitcode("movf","%s,w",
5652                          aopGet(AOP(left),offset,FALSE,FALSE));
5653                 emitcode("movwf","%s",
5654                          aopGet(AOP(result),offset,FALSE,FALSE));
5655                 break;
5656               case 0xff:
5657                 emitcode("comf","%s,w",
5658                          aopGet(AOP(left),offset,FALSE,FALSE));
5659                 emitcode("movwf","%s",
5660                          aopGet(AOP(result),offset,FALSE,FALSE));
5661                 break;
5662               default:
5663                 emitcode("movlw","0x%x",t);
5664                 emitcode("xorwf","%s,w",
5665                          aopGet(AOP(left),offset,FALSE,FALSE));
5666                 emitcode("movwf","%s",
5667                          aopGet(AOP(result),offset,FALSE,FALSE));
5668
5669               }
5670               continue;
5671             }
5672
5673             // faster than result <- left, anl result,right
5674             // and better if result is SFR
5675             if (AOP_TYPE(left) == AOP_ACC)
5676                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5677             else {
5678                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5679                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5680             }
5681             if ( AOP_TYPE(result) != AOP_ACC)
5682               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5683         }
5684     }
5685
5686 release :
5687     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5688     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5689     freeAsmop(result,NULL,ic,TRUE);     
5690 }
5691
5692 /*-----------------------------------------------------------------*/
5693 /* genInline - write the inline code out                           */
5694 /*-----------------------------------------------------------------*/
5695 static void genInline (iCode *ic)
5696 {
5697     char buffer[MAX_INLINEASM];
5698     char *bp = buffer;
5699     char *bp1= buffer;
5700     
5701     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5702
5703     _G.inLine += (!options.asmpeep);
5704     strcpy(buffer,IC_INLINE(ic));
5705
5706     /* emit each line as a code */
5707     while (*bp) {
5708         if (*bp == '\n') {
5709             *bp++ = '\0';
5710             emitcode(bp1,"");
5711             bp1 = bp;
5712         } else {
5713             if (*bp == ':') {
5714                 bp++;
5715                 *bp = '\0';
5716                 bp++;
5717                 emitcode(bp1,"");
5718                 bp1 = bp;
5719             } else
5720                 bp++;
5721         }
5722     }
5723     if (bp1 != bp)
5724         emitcode(bp1,"");
5725     /*     emitcode("",buffer); */
5726     _G.inLine -= (!options.asmpeep);
5727 }
5728
5729 /*-----------------------------------------------------------------*/
5730 /* genRRC - rotate right with carry                                */
5731 /*-----------------------------------------------------------------*/
5732 static void genRRC (iCode *ic)
5733 {
5734     operand *left , *result ;
5735     int size, offset = 0;
5736     char *l;    
5737
5738     /* rotate right with carry */
5739     left = IC_LEFT(ic);
5740     result=IC_RESULT(ic);
5741     aopOp (left,ic,FALSE);
5742     aopOp (result,ic,FALSE);
5743
5744     /* move it to the result */
5745     size = AOP_SIZE(result);    
5746     offset = size - 1 ;
5747     CLRC;
5748     while (size--) {
5749         l = aopGet(AOP(left),offset,FALSE,FALSE);
5750         MOVA(l);
5751         emitcode("rrc","a");
5752         if (AOP_SIZE(result) > 1)
5753             aopPut(AOP(result),"a",offset--);
5754     }
5755     /* now we need to put the carry into the
5756     highest order byte of the result */
5757     if (AOP_SIZE(result) > 1) {
5758         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5759         MOVA(l);
5760     }
5761     emitcode("mov","acc.7,c");
5762     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5763     freeAsmop(left,NULL,ic,TRUE);
5764     freeAsmop(result,NULL,ic,TRUE);
5765 }
5766
5767 /*-----------------------------------------------------------------*/
5768 /* genRLC - generate code for rotate left with carry               */
5769 /*-----------------------------------------------------------------*/
5770 static void genRLC (iCode *ic)
5771 {    
5772     operand *left , *result ;
5773     int size, offset = 0;
5774     char *l;    
5775
5776     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5777     /* rotate right with carry */
5778     left = IC_LEFT(ic);
5779     result=IC_RESULT(ic);
5780     aopOp (left,ic,FALSE);
5781     aopOp (result,ic,FALSE);
5782
5783     /* move it to the result */
5784     size = AOP_SIZE(result);    
5785     offset = 0 ;
5786     if (size--) {
5787         l = aopGet(AOP(left),offset,FALSE,FALSE);
5788         MOVA(l);
5789         emitcode("add","a,acc");
5790         if (AOP_SIZE(result) > 1)
5791             aopPut(AOP(result),"a",offset++);
5792         while (size--) {
5793             l = aopGet(AOP(left),offset,FALSE,FALSE);
5794             MOVA(l);
5795             emitcode("rlc","a");
5796             if (AOP_SIZE(result) > 1)
5797                 aopPut(AOP(result),"a",offset++);
5798         }
5799     }
5800     /* now we need to put the carry into the
5801     highest order byte of the result */
5802     if (AOP_SIZE(result) > 1) {
5803         l = aopGet(AOP(result),0,FALSE,FALSE);
5804         MOVA(l);
5805     }
5806     emitcode("mov","acc.0,c");
5807     aopPut(AOP(result),"a",0);
5808     freeAsmop(left,NULL,ic,TRUE);
5809     freeAsmop(result,NULL,ic,TRUE);
5810 }
5811
5812 /*-----------------------------------------------------------------*/
5813 /* genGetHbit - generates code get highest order bit               */
5814 /*-----------------------------------------------------------------*/
5815 static void genGetHbit (iCode *ic)
5816 {
5817     operand *left, *result;
5818     left = IC_LEFT(ic);
5819     result=IC_RESULT(ic);
5820     aopOp (left,ic,FALSE);
5821     aopOp (result,ic,FALSE);
5822
5823     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824     /* get the highest order byte into a */
5825     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5826     if(AOP_TYPE(result) == AOP_CRY){
5827         emitcode("rlc","a");
5828         outBitC(result);
5829     }
5830     else{
5831         emitcode("rl","a");
5832         emitcode("anl","a,#0x01");
5833         outAcc(result);
5834     }
5835
5836
5837     freeAsmop(left,NULL,ic,TRUE);
5838     freeAsmop(result,NULL,ic,TRUE);
5839 }
5840
5841 /*-----------------------------------------------------------------*/
5842 /* AccRol - rotate left accumulator by known count                 */
5843 /*-----------------------------------------------------------------*/
5844 static void AccRol (int shCount)
5845 {
5846     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5847     shCount &= 0x0007;              // shCount : 0..7
5848     switch(shCount){
5849         case 0 :
5850             break;
5851         case 1 :
5852             emitcode("rl","a");
5853             break;
5854         case 2 :
5855             emitcode("rl","a");
5856             emitcode("rl","a");
5857             break;
5858         case 3 :
5859             emitcode("swap","a");
5860             emitcode("rr","a");
5861             break;
5862         case 4 :
5863             emitcode("swap","a");
5864             break;
5865         case 5 :
5866             emitcode("swap","a");
5867             emitcode("rl","a");
5868             break;
5869         case 6 :
5870             emitcode("rr","a");
5871             emitcode("rr","a");
5872             break;
5873         case 7 :
5874             emitcode("rr","a");
5875             break;
5876     }
5877 }
5878
5879 /*-----------------------------------------------------------------*/
5880 /* AccLsh - left shift accumulator by known count                  */
5881 /*-----------------------------------------------------------------*/
5882 static void AccLsh (int shCount)
5883 {
5884     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5885     if(shCount != 0){
5886         if(shCount == 1)
5887             emitcode("add","a,acc");
5888         else 
5889             if(shCount == 2) {
5890             emitcode("add","a,acc");
5891             emitcode("add","a,acc");
5892         } else {
5893             /* rotate left accumulator */
5894             AccRol(shCount);
5895             /* and kill the lower order bits */
5896             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5897         }
5898     }
5899 }
5900
5901 /*-----------------------------------------------------------------*/
5902 /* AccRsh - right shift accumulator by known count                 */
5903 /*-----------------------------------------------------------------*/
5904 static void AccRsh (int shCount)
5905 {
5906     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5907     if(shCount != 0){
5908         if(shCount == 1){
5909             CLRC;
5910             emitcode("rrc","a");
5911         } else {
5912             /* rotate right accumulator */
5913             AccRol(8 - shCount);
5914             /* and kill the higher order bits */
5915             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5916         }
5917     }
5918 }
5919
5920 /*-----------------------------------------------------------------*/
5921 /* AccSRsh - signed right shift accumulator by known count                 */
5922 /*-----------------------------------------------------------------*/
5923 static void AccSRsh (int shCount)
5924 {
5925     symbol *tlbl ;
5926     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5927     if(shCount != 0){
5928         if(shCount == 1){
5929             emitcode("mov","c,acc.7");
5930             emitcode("rrc","a");
5931         } else if(shCount == 2){
5932             emitcode("mov","c,acc.7");
5933             emitcode("rrc","a");
5934             emitcode("mov","c,acc.7");
5935             emitcode("rrc","a");
5936         } else {
5937             tlbl = newiTempLabel(NULL);
5938             /* rotate right accumulator */
5939             AccRol(8 - shCount);
5940             /* and kill the higher order bits */
5941             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5942             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5943             emitcode("orl","a,#0x%02x",
5944                      (unsigned char)~SRMask[shCount]);
5945             emitcode("","%05d_DS_:",tlbl->key+100);
5946         }
5947     }
5948 }
5949
5950 /*-----------------------------------------------------------------*/
5951 /* shiftR1Left2Result - shift right one byte from left to result   */
5952 /*-----------------------------------------------------------------*/
5953 static void shiftR1Left2Result (operand *left, int offl,
5954                                 operand *result, int offr,
5955                                 int shCount, int sign)
5956 {
5957     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5958     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5959     /* shift right accumulator */
5960     if(sign)
5961         AccSRsh(shCount);
5962     else
5963         AccRsh(shCount);
5964     aopPut(AOP(result),"a",offr);
5965 }
5966
5967 /*-----------------------------------------------------------------*/
5968 /* shiftL1Left2Result - shift left one byte from left to result    */
5969 /*-----------------------------------------------------------------*/
5970 static void shiftL1Left2Result (operand *left, int offl,
5971                                 operand *result, int offr, int shCount)
5972 {
5973     char *l;
5974     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5975     l = aopGet(AOP(left),offl,FALSE,FALSE);
5976     MOVA(l);
5977     /* shift left accumulator */
5978     AccLsh(shCount);
5979     aopPut(AOP(result),"a",offr);
5980 }
5981
5982 /*-----------------------------------------------------------------*/
5983 /* movLeft2Result - move byte from left to result                  */
5984 /*-----------------------------------------------------------------*/
5985 static void movLeft2Result (operand *left, int offl,
5986                             operand *result, int offr, int sign)
5987 {
5988     char *l;
5989     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5990     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5991         l = aopGet(AOP(left),offl,FALSE,FALSE);
5992
5993         if (*l == '@' && (IS_AOP_PREG(result))) {
5994             emitcode("mov","a,%s",l);
5995             aopPut(AOP(result),"a",offr);
5996         } else {
5997             if(!sign)
5998                 aopPut(AOP(result),l,offr);
5999             else{
6000                 /* MSB sign in acc.7 ! */
6001                 if(getDataSize(left) == offl+1){
6002                     emitcode("mov","a,%s",l);
6003                     aopPut(AOP(result),"a",offr);
6004                 }
6005             }
6006         }
6007     }
6008 }
6009
6010 /*-----------------------------------------------------------------*/
6011 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6012 /*-----------------------------------------------------------------*/
6013 static void AccAXRrl1 (char *x)
6014 {
6015     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6016     emitcode("rrc","a");
6017     emitcode("xch","a,%s", x);
6018     emitcode("rrc","a");
6019     emitcode("xch","a,%s", x);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6024 /*-----------------------------------------------------------------*/
6025 static void AccAXLrl1 (char *x)
6026 {
6027     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6028     emitcode("xch","a,%s",x);
6029     emitcode("rlc","a");
6030     emitcode("xch","a,%s",x);
6031     emitcode("rlc","a");
6032 }
6033
6034 /*-----------------------------------------------------------------*/
6035 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6036 /*-----------------------------------------------------------------*/
6037 static void AccAXLsh1 (char *x)
6038 {
6039     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6040     emitcode("xch","a,%s",x);
6041     emitcode("add","a,acc");
6042     emitcode("xch","a,%s",x);
6043     emitcode("rlc","a");
6044 }
6045
6046 /*-----------------------------------------------------------------*/
6047 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6048 /*-----------------------------------------------------------------*/
6049 static void AccAXLsh (char *x, int shCount)
6050 {
6051     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6052     switch(shCount){
6053         case 0 :
6054             break;
6055         case 1 :
6056             AccAXLsh1(x);
6057             break;
6058         case 2 :
6059             AccAXLsh1(x);
6060             AccAXLsh1(x);
6061             break;
6062         case 3 :
6063         case 4 :
6064         case 5 :                        // AAAAABBB:CCCCCDDD
6065             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
6066             emitcode("anl","a,#0x%02x",
6067                      SLMask[shCount]);  // BBB00000:CCCCCDDD
6068             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
6069             AccRol(shCount);            // DDDCCCCC:BBB00000
6070             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
6071             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
6072             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
6073             emitcode("anl","a,#0x%02x",
6074                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
6075             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
6076             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
6077             break;
6078         case 6 :                        // AAAAAABB:CCCCCCDD
6079             emitcode("anl","a,#0x%02x",
6080                      SRMask[shCount]);  // 000000BB:CCCCCCDD
6081             emitcode("mov","c,acc.0");  // c = B
6082             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
6083             AccAXRrl1(x);               // BCCCCCCD:D000000B
6084             AccAXRrl1(x);               // BBCCCCCC:DD000000
6085             break;
6086         case 7 :                        // a:x <<= 7
6087             emitcode("anl","a,#0x%02x",
6088                      SRMask[shCount]);  // 0000000B:CCCCCCCD
6089             emitcode("mov","c,acc.0");  // c = B
6090             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
6091             AccAXRrl1(x);               // BCCCCCCC:D0000000
6092             break;
6093         default :
6094             break;
6095     }
6096 }
6097
6098 /*-----------------------------------------------------------------*/
6099 /* AccAXRsh - right shift a:x known count (0..7)                   */
6100 /*-----------------------------------------------------------------*/
6101 static void AccAXRsh (char *x, int shCount)
6102 {   
6103     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6104     switch(shCount){
6105         case 0 :
6106             break;
6107         case 1 :
6108             CLRC;
6109             AccAXRrl1(x);               // 0->a:x
6110             break;
6111         case 2 :
6112             CLRC;
6113             AccAXRrl1(x);               // 0->a:x
6114             CLRC;
6115             AccAXRrl1(x);               // 0->a:x
6116             break;
6117         case 3 :
6118         case 4 :
6119         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6120             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
6121             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6122             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6123             emitcode("anl","a,#0x%02x",
6124                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6125             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6126             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6127             emitcode("anl","a,#0x%02x",
6128                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6129             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6130             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6131             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
6132             break;
6133         case 6 :                        // AABBBBBB:CCDDDDDD
6134             emitcode("mov","c,acc.7");
6135             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6136             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6137             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6138             emitcode("anl","a,#0x%02x",
6139                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6140             break;
6141         case 7 :                        // ABBBBBBB:CDDDDDDD
6142             emitcode("mov","c,acc.7");  // c = A
6143             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6144             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6145             emitcode("anl","a,#0x%02x",
6146                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6147             break;
6148         default :
6149             break;
6150     }
6151 }
6152
6153 /*-----------------------------------------------------------------*/
6154 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6155 /*-----------------------------------------------------------------*/
6156 static void AccAXRshS (char *x, int shCount)
6157 {   
6158     symbol *tlbl ;
6159     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6160     switch(shCount){
6161         case 0 :
6162             break;
6163         case 1 :
6164             emitcode("mov","c,acc.7");
6165             AccAXRrl1(x);               // s->a:x
6166             break;
6167         case 2 :
6168             emitcode("mov","c,acc.7");
6169             AccAXRrl1(x);               // s->a:x
6170             emitcode("mov","c,acc.7");
6171             AccAXRrl1(x);               // s->a:x
6172             break;
6173         case 3 :
6174         case 4 :
6175         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6176             tlbl = newiTempLabel(NULL);
6177             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6178             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6179             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6180             emitcode("anl","a,#0x%02x",
6181                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6182             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6183             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6184             emitcode("anl","a,#0x%02x",
6185                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6186             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6187             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6188             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6189             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6190             emitcode("orl","a,#0x%02x",
6191                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6192             emitcode("","%05d_DS_:",tlbl->key+100);
6193             break;                      // SSSSAAAA:BBBCCCCC
6194         case 6 :                        // AABBBBBB:CCDDDDDD
6195             tlbl = newiTempLabel(NULL);
6196             emitcode("mov","c,acc.7");
6197             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6198             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6199             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6200             emitcode("anl","a,#0x%02x",
6201                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6202             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6203             emitcode("orl","a,#0x%02x",
6204                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6205             emitcode("","%05d_DS_:",tlbl->key+100);
6206             break;
6207         case 7 :                        // ABBBBBBB:CDDDDDDD
6208             tlbl = newiTempLabel(NULL);
6209             emitcode("mov","c,acc.7");  // c = A
6210             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6211             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6212             emitcode("anl","a,#0x%02x",
6213                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6214             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6215             emitcode("orl","a,#0x%02x",
6216                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6217             emitcode("","%05d_DS_:",tlbl->key+100);
6218             break;
6219         default :
6220             break;
6221     }
6222 }
6223
6224 /*-----------------------------------------------------------------*/
6225 /* shiftL2Left2Result - shift left two bytes from left to result   */
6226 /*-----------------------------------------------------------------*/
6227 static void shiftL2Left2Result (operand *left, int offl,
6228                                 operand *result, int offr, int shCount)
6229 {
6230     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6231     if(sameRegs(AOP(result), AOP(left)) &&
6232        ((offl + MSB16) == offr)){
6233         /* don't crash result[offr] */
6234         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6235         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6236     } else {
6237         movLeft2Result(left,offl, result, offr, 0);
6238         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6239     }
6240     /* ax << shCount (x = lsb(result))*/
6241     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6242     aopPut(AOP(result),"a",offr+MSB16);
6243 }
6244
6245
6246 /*-----------------------------------------------------------------*/
6247 /* shiftR2Left2Result - shift right two bytes from left to result  */
6248 /*-----------------------------------------------------------------*/
6249 static void shiftR2Left2Result (operand *left, int offl,
6250                                 operand *result, int offr,
6251                                 int shCount, int sign)
6252 {
6253     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6254     if(sameRegs(AOP(result), AOP(left)) &&
6255        ((offl + MSB16) == offr)){
6256         /* don't crash result[offr] */
6257         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6258         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6259     } else {
6260         movLeft2Result(left,offl, result, offr, 0);
6261         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6262     }
6263     /* a:x >> shCount (x = lsb(result))*/
6264     if(sign)
6265         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6266     else
6267         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6268     if(getDataSize(result) > 1)
6269         aopPut(AOP(result),"a",offr+MSB16);
6270 }
6271
6272 /*-----------------------------------------------------------------*/
6273 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6274 /*-----------------------------------------------------------------*/
6275 static void shiftLLeftOrResult (operand *left, int offl,
6276                                 operand *result, int offr, int shCount)
6277 {
6278     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6279     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6280     /* shift left accumulator */
6281     AccLsh(shCount);
6282     /* or with result */
6283     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6284     /* back to result */
6285     aopPut(AOP(result),"a",offr);
6286 }
6287
6288 /*-----------------------------------------------------------------*/
6289 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6290 /*-----------------------------------------------------------------*/
6291 static void shiftRLeftOrResult (operand *left, int offl,
6292                                 operand *result, int offr, int shCount)
6293 {
6294     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6295     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6296     /* shift right accumulator */
6297     AccRsh(shCount);
6298     /* or with result */
6299     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6300     /* back to result */
6301     aopPut(AOP(result),"a",offr);
6302 }
6303
6304 /*-----------------------------------------------------------------*/
6305 /* genlshOne - left shift a one byte quantity by known count       */
6306 /*-----------------------------------------------------------------*/
6307 static void genlshOne (operand *result, operand *left, int shCount)
6308 {       
6309     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6310     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6311 }
6312
6313 /*-----------------------------------------------------------------*/
6314 /* genlshTwo - left shift two bytes by known amount != 0           */
6315 /*-----------------------------------------------------------------*/
6316 static void genlshTwo (operand *result,operand *left, int shCount)
6317 {
6318     int size;
6319     
6320     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6321     size = getDataSize(result);
6322
6323     /* if shCount >= 8 */
6324     if (shCount >= 8) {
6325         shCount -= 8 ;
6326
6327         if (size > 1){
6328             if (shCount)
6329                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6330             else 
6331                 movLeft2Result(left, LSB, result, MSB16, 0);
6332         }
6333         aopPut(AOP(result),zero,LSB);   
6334     }
6335
6336     /*  1 <= shCount <= 7 */
6337     else {  
6338         if(size == 1)
6339             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6340         else 
6341             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6342     }
6343 }
6344
6345 /*-----------------------------------------------------------------*/
6346 /* shiftLLong - shift left one long from left to result            */
6347 /* offl = LSB or MSB16                                             */
6348 /*-----------------------------------------------------------------*/
6349 static void shiftLLong (operand *left, operand *result, int offr )
6350 {
6351     char *l;
6352     int size = AOP_SIZE(result);
6353
6354     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6355     if(size >= LSB+offr){
6356         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6357         MOVA(l);
6358         emitcode("add","a,acc");
6359         if (sameRegs(AOP(left),AOP(result)) && 
6360             size >= MSB16+offr && offr != LSB )
6361             emitcode("xch","a,%s",
6362                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6363         else        
6364             aopPut(AOP(result),"a",LSB+offr);
6365     }
6366
6367     if(size >= MSB16+offr){
6368         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6369             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6370             MOVA(l);
6371         }
6372         emitcode("rlc","a");
6373         if (sameRegs(AOP(left),AOP(result)) && 
6374             size >= MSB24+offr && offr != LSB)
6375             emitcode("xch","a,%s",
6376                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6377         else        
6378             aopPut(AOP(result),"a",MSB16+offr);
6379     }
6380
6381     if(size >= MSB24+offr){
6382         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6383             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6384             MOVA(l);
6385         }
6386         emitcode("rlc","a");
6387         if (sameRegs(AOP(left),AOP(result)) && 
6388             size >= MSB32+offr && offr != LSB )
6389             emitcode("xch","a,%s",
6390                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6391         else        
6392             aopPut(AOP(result),"a",MSB24+offr);
6393     }
6394
6395     if(size > MSB32+offr){
6396         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6397             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6398             MOVA(l);    
6399         }
6400         emitcode("rlc","a");
6401         aopPut(AOP(result),"a",MSB32+offr);
6402     }
6403     if(offr != LSB)
6404         aopPut(AOP(result),zero,LSB);       
6405 }
6406
6407 /*-----------------------------------------------------------------*/
6408 /* genlshFour - shift four byte by a known amount != 0             */
6409 /*-----------------------------------------------------------------*/
6410 static void genlshFour (operand *result, operand *left, int shCount)
6411 {
6412     int size;
6413
6414     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6415     size = AOP_SIZE(result);
6416
6417     /* if shifting more that 3 bytes */
6418     if (shCount >= 24 ) {
6419         shCount -= 24;
6420         if (shCount)
6421             /* lowest order of left goes to the highest
6422             order of the destination */
6423             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6424         else
6425             movLeft2Result(left, LSB, result, MSB32, 0);
6426         aopPut(AOP(result),zero,LSB);
6427         aopPut(AOP(result),zero,MSB16);
6428         aopPut(AOP(result),zero,MSB32);
6429         return;
6430     }
6431
6432     /* more than two bytes */
6433     else if ( shCount >= 16 ) {
6434         /* lower order two bytes goes to higher order two bytes */
6435         shCount -= 16;
6436         /* if some more remaining */
6437         if (shCount)
6438             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6439         else {
6440             movLeft2Result(left, MSB16, result, MSB32, 0);
6441             movLeft2Result(left, LSB, result, MSB24, 0);
6442         }
6443         aopPut(AOP(result),zero,MSB16);
6444         aopPut(AOP(result),zero,LSB);
6445         return;
6446     }    
6447
6448     /* if more than 1 byte */
6449     else if ( shCount >= 8 ) {
6450         /* lower order three bytes goes to higher order  three bytes */
6451         shCount -= 8;
6452         if(size == 2){
6453             if(shCount)
6454                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6455             else
6456                 movLeft2Result(left, LSB, result, MSB16, 0);
6457         }
6458         else{   /* size = 4 */
6459             if(shCount == 0){
6460                 movLeft2Result(left, MSB24, result, MSB32, 0);
6461                 movLeft2Result(left, MSB16, result, MSB24, 0);
6462                 movLeft2Result(left, LSB, result, MSB16, 0);
6463                 aopPut(AOP(result),zero,LSB);
6464             }
6465             else if(shCount == 1)
6466                 shiftLLong(left, result, MSB16);
6467             else{
6468                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6469                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6470                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6471                 aopPut(AOP(result),zero,LSB);
6472             }
6473         }
6474     }
6475
6476     /* 1 <= shCount <= 7 */
6477     else if(shCount <= 2){
6478         shiftLLong(left, result, LSB);
6479         if(shCount == 2)
6480             shiftLLong(result, result, LSB);
6481     }
6482     /* 3 <= shCount <= 7, optimize */
6483     else{
6484         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6485         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6486         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6487     }
6488 }
6489
6490 /*-----------------------------------------------------------------*/
6491 /* genLeftShiftLiteral - left shifting by known count              */
6492 /*-----------------------------------------------------------------*/
6493 static void genLeftShiftLiteral (operand *left,
6494                                  operand *right,
6495                                  operand *result,
6496                                  iCode *ic)
6497 {    
6498     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6499     int size;
6500
6501     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6502     freeAsmop(right,NULL,ic,TRUE);
6503
6504     aopOp(left,ic,FALSE);
6505     aopOp(result,ic,FALSE);
6506
6507     size = getSize(operandType(result));
6508
6509 #if VIEW_SIZE
6510     emitcode("; shift left ","result %d, left %d",size,
6511              AOP_SIZE(left));
6512 #endif
6513
6514     /* I suppose that the left size >= result size */
6515     if(shCount == 0){
6516         while(size--){
6517             movLeft2Result(left, size, result, size, 0);
6518         }
6519     }
6520
6521     else if(shCount >= (size * 8))
6522         while(size--)
6523             aopPut(AOP(result),zero,size);
6524     else{
6525         switch (size) {
6526             case 1:
6527                 genlshOne (result,left,shCount);
6528                 break;
6529
6530             case 2:
6531             case 3:
6532                 genlshTwo (result,left,shCount);
6533                 break;
6534
6535             case 4:
6536                 genlshFour (result,left,shCount);
6537                 break;
6538         }
6539     }
6540     freeAsmop(left,NULL,ic,TRUE);
6541     freeAsmop(result,NULL,ic,TRUE);
6542 }
6543
6544 /*-----------------------------------------------------------------*/
6545 /* genLeftShift - generates code for left shifting                 */
6546 /*-----------------------------------------------------------------*/
6547 static void genLeftShift (iCode *ic)
6548 {
6549     operand *left,*right, *result;
6550     int size, offset;
6551     char *l;
6552     symbol *tlbl , *tlbl1;
6553
6554     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6555
6556     right = IC_RIGHT(ic);
6557     left  = IC_LEFT(ic);
6558     result = IC_RESULT(ic);
6559
6560     aopOp(right,ic,FALSE);
6561
6562     /* if the shift count is known then do it 
6563     as efficiently as possible */
6564     if (AOP_TYPE(right) == AOP_LIT) {
6565         genLeftShiftLiteral (left,right,result,ic);
6566         return ;
6567     }
6568
6569     /* shift count is unknown then we have to form 
6570     a loop get the loop count in B : Note: we take
6571     only the lower order byte since shifting
6572     more that 32 bits make no sense anyway, ( the
6573     largest size of an object can be only 32 bits ) */  
6574
6575     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6576     emitcode("inc","b");
6577     freeAsmop (right,NULL,ic,TRUE);
6578     aopOp(left,ic,FALSE);
6579     aopOp(result,ic,FALSE);
6580
6581     /* now move the left to the result if they are not the
6582     same */
6583     if (!sameRegs(AOP(left),AOP(result)) && 
6584         AOP_SIZE(result) > 1) {
6585
6586         size = AOP_SIZE(result);
6587         offset=0;
6588         while (size--) {
6589             l = aopGet(AOP(left),offset,FALSE,TRUE);
6590             if (*l == '@' && (IS_AOP_PREG(result))) {
6591
6592                 emitcode("mov","a,%s",l);
6593                 aopPut(AOP(result),"a",offset);
6594             } else
6595                 aopPut(AOP(result),l,offset);
6596             offset++;
6597         }
6598     }
6599
6600     tlbl = newiTempLabel(NULL);
6601     size = AOP_SIZE(result);
6602     offset = 0 ;   
6603     tlbl1 = newiTempLabel(NULL);
6604
6605     /* if it is only one byte then */
6606     if (size == 1) {
6607         symbol *tlbl1 = newiTempLabel(NULL);
6608
6609         l = aopGet(AOP(left),0,FALSE,FALSE);
6610         MOVA(l);
6611         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6612         emitcode("","%05d_DS_:",tlbl->key+100);
6613         emitcode("add","a,acc");
6614         emitcode("","%05d_DS_:",tlbl1->key+100);
6615         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6616         aopPut(AOP(result),"a",0);
6617         goto release ;
6618     }
6619     
6620     reAdjustPreg(AOP(result));    
6621     
6622     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6623     emitcode("","%05d_DS_:",tlbl->key+100);    
6624     l = aopGet(AOP(result),offset,FALSE,FALSE);
6625     MOVA(l);
6626     emitcode("add","a,acc");         
6627     aopPut(AOP(result),"a",offset++);
6628     while (--size) {
6629         l = aopGet(AOP(result),offset,FALSE,FALSE);
6630         MOVA(l);
6631         emitcode("rlc","a");         
6632         aopPut(AOP(result),"a",offset++);
6633     }
6634     reAdjustPreg(AOP(result));
6635
6636     emitcode("","%05d_DS_:",tlbl1->key+100);
6637     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6638 release:
6639     freeAsmop(left,NULL,ic,TRUE);
6640     freeAsmop(result,NULL,ic,TRUE);
6641 }
6642
6643 /*-----------------------------------------------------------------*/
6644 /* genrshOne - right shift a one byte quantity by known count      */
6645 /*-----------------------------------------------------------------*/
6646 static void genrshOne (operand *result, operand *left,
6647                        int shCount, int sign)
6648 {
6649     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6650     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6651 }
6652
6653 /*-----------------------------------------------------------------*/
6654 /* genrshTwo - right shift two bytes by known amount != 0          */
6655 /*-----------------------------------------------------------------*/
6656 static void genrshTwo (operand *result,operand *left,
6657                        int shCount, int sign)
6658 {
6659     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6660     /* if shCount >= 8 */
6661     if (shCount >= 8) {
6662         shCount -= 8 ;
6663         if (shCount)
6664             shiftR1Left2Result(left, MSB16, result, LSB,
6665                                shCount, sign);
6666         else 
6667             movLeft2Result(left, MSB16, result, LSB, sign);
6668         addSign(result, MSB16, sign);
6669     }
6670
6671     /*  1 <= shCount <= 7 */
6672     else
6673         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6674 }
6675
6676 /*-----------------------------------------------------------------*/
6677 /* shiftRLong - shift right one long from left to result           */
6678 /* offl = LSB or MSB16                                             */
6679 /*-----------------------------------------------------------------*/
6680 static void shiftRLong (operand *left, int offl,
6681                         operand *result, int sign)
6682 {
6683     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6684     if(!sign)
6685         emitcode("clr","c");
6686     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6687     if(sign)
6688         emitcode("mov","c,acc.7");
6689     emitcode("rrc","a");
6690     aopPut(AOP(result),"a",MSB32-offl);
6691     if(offl == MSB16)
6692         /* add sign of "a" */
6693         addSign(result, MSB32, sign);
6694
6695     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6696     emitcode("rrc","a");
6697     aopPut(AOP(result),"a",MSB24-offl);
6698
6699     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6700     emitcode("rrc","a");
6701     aopPut(AOP(result),"a",MSB16-offl);
6702
6703     if(offl == LSB){
6704         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6705         emitcode("rrc","a");
6706         aopPut(AOP(result),"a",LSB);
6707     }
6708 }
6709
6710 /*-----------------------------------------------------------------*/
6711 /* genrshFour - shift four byte by a known amount != 0             */
6712 /*-----------------------------------------------------------------*/
6713 static void genrshFour (operand *result, operand *left,
6714                         int shCount, int sign)
6715 {
6716     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6717     /* if shifting more that 3 bytes */
6718     if(shCount >= 24 ) {
6719         shCount -= 24;
6720         if(shCount)
6721             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6722         else
6723             movLeft2Result(left, MSB32, result, LSB, sign);
6724         addSign(result, MSB16, sign);
6725     }
6726     else if(shCount >= 16){
6727         shCount -= 16;
6728         if(shCount)
6729             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6730         else{
6731             movLeft2Result(left, MSB24, result, LSB, 0);
6732             movLeft2Result(left, MSB32, result, MSB16, sign);
6733         }
6734         addSign(result, MSB24, sign);
6735     }
6736     else if(shCount >= 8){
6737         shCount -= 8;
6738         if(shCount == 1)
6739             shiftRLong(left, MSB16, result, sign);
6740         else if(shCount == 0){
6741             movLeft2Result(left, MSB16, result, LSB, 0);
6742             movLeft2Result(left, MSB24, result, MSB16, 0);
6743             movLeft2Result(left, MSB32, result, MSB24, sign);
6744             addSign(result, MSB32, sign);
6745         }
6746         else{
6747             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6748             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6749             /* the last shift is signed */
6750             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6751             addSign(result, MSB32, sign);
6752         }
6753     }
6754     else{   /* 1 <= shCount <= 7 */
6755         if(shCount <= 2){
6756             shiftRLong(left, LSB, result, sign);
6757             if(shCount == 2)
6758                 shiftRLong(result, LSB, result, sign);
6759         }
6760         else{
6761             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6762             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6763             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6764         }
6765     }
6766 }
6767
6768 /*-----------------------------------------------------------------*/
6769 /* genRightShiftLiteral - right shifting by known count            */
6770 /*-----------------------------------------------------------------*/
6771 static void genRightShiftLiteral (operand *left,
6772                                   operand *right,
6773                                   operand *result,
6774                                   iCode *ic,
6775                                   int sign)
6776 {    
6777     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6778     int size;
6779
6780     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6781     freeAsmop(right,NULL,ic,TRUE);
6782
6783     aopOp(left,ic,FALSE);
6784     aopOp(result,ic,FALSE);
6785
6786 #if VIEW_SIZE
6787     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6788              AOP_SIZE(left));
6789 #endif
6790
6791     size = getDataSize(left);
6792     /* test the LEFT size !!! */
6793
6794     /* I suppose that the left size >= result size */
6795     if(shCount == 0){
6796         size = getDataSize(result);
6797         while(size--)
6798             movLeft2Result(left, size, result, size, 0);
6799     }
6800
6801     else if(shCount >= (size * 8)){
6802         if(sign)
6803             /* get sign in acc.7 */
6804             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6805         addSign(result, LSB, sign);
6806     } else{
6807         switch (size) {
6808             case 1:
6809                 genrshOne (result,left,shCount,sign);
6810                 break;
6811
6812             case 2:
6813                 genrshTwo (result,left,shCount,sign);
6814                 break;
6815
6816             case 4:
6817                 genrshFour (result,left,shCount,sign);
6818                 break;
6819             default :
6820                 break;
6821         }
6822
6823         freeAsmop(left,NULL,ic,TRUE);
6824         freeAsmop(result,NULL,ic,TRUE);
6825     }
6826 }
6827
6828 /*-----------------------------------------------------------------*/
6829 /* genSignedRightShift - right shift of signed number              */
6830 /*-----------------------------------------------------------------*/
6831 static void genSignedRightShift (iCode *ic)
6832 {
6833     operand *right, *left, *result;
6834     int size, offset;
6835     char *l;
6836     symbol *tlbl, *tlbl1 ;
6837
6838     /* we do it the hard way put the shift count in b
6839     and loop thru preserving the sign */
6840     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6841
6842     right = IC_RIGHT(ic);
6843     left  = IC_LEFT(ic);
6844     result = IC_RESULT(ic);
6845
6846     aopOp(right,ic,FALSE);  
6847
6848
6849     if ( AOP_TYPE(right) == AOP_LIT) {
6850         genRightShiftLiteral (left,right,result,ic,1);
6851         return ;
6852     }
6853         /* shift count is unknown then we have to form 
6854        a loop get the loop count in B : Note: we take
6855        only the lower order byte since shifting
6856        more that 32 bits make no sense anyway, ( the
6857        largest size of an object can be only 32 bits ) */  
6858
6859     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6860     emitcode("inc","b");
6861     freeAsmop (right,NULL,ic,TRUE);
6862     aopOp(left,ic,FALSE);
6863     aopOp(result,ic,FALSE);
6864
6865     /* now move the left to the result if they are not the
6866     same */
6867     if (!sameRegs(AOP(left),AOP(result)) && 
6868         AOP_SIZE(result) > 1) {
6869
6870         size = AOP_SIZE(result);
6871         offset=0;
6872         while (size--) {
6873             l = aopGet(AOP(left),offset,FALSE,TRUE);
6874             if (*l == '@' && IS_AOP_PREG(result)) {
6875
6876                 emitcode("mov","a,%s",l);
6877                 aopPut(AOP(result),"a",offset);
6878             } else
6879                 aopPut(AOP(result),l,offset);
6880             offset++;
6881         }
6882     }
6883
6884     /* mov the highest order bit to OVR */    
6885     tlbl = newiTempLabel(NULL);
6886     tlbl1= newiTempLabel(NULL);
6887
6888     size = AOP_SIZE(result);
6889     offset = size - 1;
6890     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6891     emitcode("rlc","a");
6892     emitcode("mov","ov,c");
6893     /* if it is only one byte then */
6894     if (size == 1) {
6895         l = aopGet(AOP(left),0,FALSE,FALSE);
6896         MOVA(l);
6897         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6898         emitcode("","%05d_DS_:",tlbl->key+100);
6899         emitcode("mov","c,ov");
6900         emitcode("rrc","a");
6901         emitcode("","%05d_DS_:",tlbl1->key+100);
6902         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6903         aopPut(AOP(result),"a",0);
6904         goto release ;
6905     }
6906
6907     reAdjustPreg(AOP(result));
6908     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6909     emitcode("","%05d_DS_:",tlbl->key+100);    
6910     emitcode("mov","c,ov");
6911     while (size--) {
6912         l = aopGet(AOP(result),offset,FALSE,FALSE);
6913         MOVA(l);
6914         emitcode("rrc","a");         
6915         aopPut(AOP(result),"a",offset--);
6916     }
6917     reAdjustPreg(AOP(result));
6918     emitcode("","%05d_DS_:",tlbl1->key+100);
6919     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6920
6921 release:
6922     freeAsmop(left,NULL,ic,TRUE);
6923     freeAsmop(result,NULL,ic,TRUE);
6924 }
6925
6926 /*-----------------------------------------------------------------*/
6927 /* genRightShift - generate code for right shifting                */
6928 /*-----------------------------------------------------------------*/
6929 static void genRightShift (iCode *ic)
6930 {
6931     operand *right, *left, *result;
6932     sym_link *retype ;
6933     int size, offset;
6934     char *l;
6935     symbol *tlbl, *tlbl1 ;
6936
6937     /* if signed then we do it the hard way preserve the
6938     sign bit moving it inwards */
6939     retype = getSpec(operandType(IC_RESULT(ic)));
6940     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6941
6942     if (!SPEC_USIGN(retype)) {
6943         genSignedRightShift (ic);
6944         return ;
6945     }
6946
6947     /* signed & unsigned types are treated the same : i.e. the
6948     signed is NOT propagated inwards : quoting from the
6949     ANSI - standard : "for E1 >> E2, is equivalent to division
6950     by 2**E2 if unsigned or if it has a non-negative value,
6951     otherwise the result is implementation defined ", MY definition
6952     is that the sign does not get propagated */
6953
6954     right = IC_RIGHT(ic);
6955     left  = IC_LEFT(ic);
6956     result = IC_RESULT(ic);
6957
6958     aopOp(right,ic,FALSE);
6959
6960     /* if the shift count is known then do it 
6961     as efficiently as possible */
6962     if (AOP_TYPE(right) == AOP_LIT) {
6963         genRightShiftLiteral (left,right,result,ic, 0);
6964         return ;
6965     }
6966
6967     /* shift count is unknown then we have to form 
6968     a loop get the loop count in B : Note: we take
6969     only the lower order byte since shifting
6970     more that 32 bits make no sense anyway, ( the
6971     largest size of an object can be only 32 bits ) */  
6972
6973     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6974     emitcode("inc","b");
6975     freeAsmop (right,NULL,ic,TRUE);
6976     aopOp(left,ic,FALSE);
6977     aopOp(result,ic,FALSE);
6978
6979     /* now move the left to the result if they are not the
6980     same */
6981     if (!sameRegs(AOP(left),AOP(result)) && 
6982         AOP_SIZE(result) > 1) {
6983
6984         size = AOP_SIZE(result);
6985         offset=0;
6986         while (size--) {
6987             l = aopGet(AOP(left),offset,FALSE,TRUE);
6988             if (*l == '@' && IS_AOP_PREG(result)) {
6989
6990                 emitcode("mov","a,%s",l);
6991                 aopPut(AOP(result),"a",offset);
6992             } else
6993                 aopPut(AOP(result),l,offset);
6994             offset++;
6995         }
6996     }
6997
6998     tlbl = newiTempLabel(NULL);
6999     tlbl1= newiTempLabel(NULL);
7000     size = AOP_SIZE(result);
7001     offset = size - 1;
7002
7003     /* if it is only one byte then */
7004     if (size == 1) {
7005         l = aopGet(AOP(left),0,FALSE,FALSE);
7006         MOVA(l);
7007         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7008         emitcode("","%05d_DS_:",tlbl->key+100);
7009         CLRC;
7010         emitcode("rrc","a");
7011         emitcode("","%05d_DS_:",tlbl1->key+100);
7012         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7013         aopPut(AOP(result),"a",0);
7014         goto release ;
7015     }
7016
7017     reAdjustPreg(AOP(result));
7018     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7019     emitcode("","%05d_DS_:",tlbl->key+100);    
7020     CLRC;
7021     while (size--) {
7022         l = aopGet(AOP(result),offset,FALSE,FALSE);
7023         MOVA(l);
7024         emitcode("rrc","a");         
7025         aopPut(AOP(result),"a",offset--);
7026     }
7027     reAdjustPreg(AOP(result));
7028
7029     emitcode("","%05d_DS_:",tlbl1->key+100);
7030     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7031
7032 release:
7033     freeAsmop(left,NULL,ic,TRUE);
7034     freeAsmop(result,NULL,ic,TRUE);
7035 }
7036
7037 /*-----------------------------------------------------------------*/
7038 /* genUnpackBits - generates code for unpacking bits               */
7039 /*-----------------------------------------------------------------*/
7040 static void genUnpackBits (operand *result, char *rname, int ptype)
7041 {    
7042     int shCnt ;
7043     int rlen = 0 ;
7044     sym_link *etype;
7045     int offset = 0 ;
7046
7047     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7048     etype = getSpec(operandType(result));
7049
7050     /* read the first byte  */
7051     switch (ptype) {
7052
7053     case POINTER:
7054     case IPOINTER:
7055         emitcode("mov","a,@%s",rname);
7056         break;
7057         
7058     case PPOINTER:
7059         emitcode("movx","a,@%s",rname);
7060         break;
7061         
7062     case FPOINTER:
7063         emitcode("movx","a,@dptr");
7064         break;
7065
7066     case CPOINTER:
7067         emitcode("clr","a");
7068         emitcode("movc","a","@a+dptr");
7069         break;
7070
7071     case GPOINTER:
7072         emitcode("lcall","__gptrget");
7073         break;
7074     }
7075
7076     /* if we have bitdisplacement then it fits   */
7077     /* into this byte completely or if length is */
7078     /* less than a byte                          */
7079     if ((shCnt = SPEC_BSTR(etype)) || 
7080         (SPEC_BLEN(etype) <= 8))  {
7081
7082         /* shift right acc */
7083         AccRsh(shCnt);
7084
7085         emitcode("anl","a,#0x%02x",
7086                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7087         aopPut(AOP(result),"a",offset);
7088         return ;
7089     }
7090
7091     /* bit field did not fit in a byte  */
7092     rlen = SPEC_BLEN(etype) - 8;
7093     aopPut(AOP(result),"a",offset++);
7094
7095     while (1)  {
7096
7097         switch (ptype) {
7098         case POINTER:
7099         case IPOINTER:
7100             emitcode("inc","%s",rname);
7101             emitcode("mov","a,@%s",rname);
7102             break;
7103             
7104         case PPOINTER:
7105             emitcode("inc","%s",rname);
7106             emitcode("movx","a,@%s",rname);
7107             break;
7108
7109         case FPOINTER:
7110             emitcode("inc","dptr");
7111             emitcode("movx","a,@dptr");
7112             break;
7113             
7114         case CPOINTER:
7115             emitcode("clr","a");
7116             emitcode("inc","dptr");
7117             emitcode("movc","a","@a+dptr");
7118             break;
7119             
7120         case GPOINTER:
7121             emitcode("inc","dptr");
7122             emitcode("lcall","__gptrget");
7123             break;
7124         }
7125
7126         rlen -= 8;            
7127         /* if we are done */
7128         if ( rlen <= 0 )
7129             break ;
7130         
7131         aopPut(AOP(result),"a",offset++);
7132                               
7133     }
7134     
7135     if (rlen) {
7136         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7137         aopPut(AOP(result),"a",offset);        
7138     }
7139     
7140     return ;
7141 }
7142
7143
7144 /*-----------------------------------------------------------------*/
7145 /* genDataPointerGet - generates code when ptr offset is known     */
7146 /*-----------------------------------------------------------------*/
7147 static void genDataPointerGet (operand *left, 
7148                                operand *result, 
7149                                iCode *ic)
7150 {
7151     char *l;
7152     char buffer[256];
7153     int size , offset = 0;
7154     aopOp(result,ic,TRUE);
7155
7156     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7157
7158     /* get the string representation of the name */
7159     l = aopGet(AOP(left),0,FALSE,TRUE);
7160     size = AOP_SIZE(result);
7161     // tsd, was l+1 - the underline `_' prefix was being stripped
7162     while (size--) {
7163         if (offset)
7164             sprintf(buffer,"(%s + %d)",l,offset);
7165         else
7166             sprintf(buffer,"%s",l);
7167         aopPut(AOP(result),buffer,offset++);
7168     }
7169
7170     freeAsmop(left,NULL,ic,TRUE);
7171     freeAsmop(result,NULL,ic,TRUE);
7172 }
7173
7174 /*-----------------------------------------------------------------*/
7175 /* genNearPointerGet - emitcode for near pointer fetch             */
7176 /*-----------------------------------------------------------------*/
7177 static void genNearPointerGet (operand *left, 
7178                                operand *result, 
7179                                iCode *ic)
7180 {
7181     asmop *aop = NULL;
7182     regs *preg = NULL ;
7183     char *rname ;
7184     sym_link *rtype, *retype;
7185     sym_link *ltype = operandType(left);    
7186     char buffer[80];
7187
7188     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7189
7190     rtype = operandType(result);
7191     retype= getSpec(rtype);
7192     
7193     aopOp(left,ic,FALSE);
7194     
7195     /* if left is rematerialisable and
7196        result is not bit variable type and
7197        the left is pointer to data space i.e
7198        lower 128 bytes of space */
7199     if (AOP_TYPE(left) == AOP_IMMD &&
7200         !IS_BITVAR(retype)         &&
7201         DCL_TYPE(ltype) == POINTER) {
7202         genDataPointerGet (left,result,ic);
7203         return ;
7204     }
7205     
7206         /* if the value is already in a pointer register
7207        then don't need anything more */
7208     if (!AOP_INPREG(AOP(left))) {
7209         /* otherwise get a free pointer register */
7210         aop = newAsmop(0);
7211         preg = getFreePtr(ic,&aop,FALSE);
7212         emitcode("mov","%s,%s",
7213                 preg->name,
7214                 aopGet(AOP(left),0,FALSE,TRUE));
7215         rname = preg->name ;
7216     } else
7217         rname = aopGet(AOP(left),0,FALSE,FALSE);
7218     
7219     freeAsmop(left,NULL,ic,TRUE);
7220     aopOp (result,ic,FALSE);
7221     
7222       /* if bitfield then unpack the bits */
7223     if (IS_BITVAR(retype)) 
7224         genUnpackBits (result,rname,POINTER);
7225     else {
7226         /* we have can just get the values */
7227         int size = AOP_SIZE(result);
7228         int offset = 0 ;        
7229         
7230         while (size--) {
7231             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7232
7233                 emitcode("mov","a,@%s",rname);
7234                 aopPut(AOP(result),"a",offset);
7235             } else {
7236                 sprintf(buffer,"@%s",rname);
7237                 aopPut(AOP(result),buffer,offset);
7238             }
7239             offset++ ;
7240             if (size)
7241                 emitcode("inc","%s",rname);
7242         }
7243     }
7244
7245     /* now some housekeeping stuff */
7246     if (aop) {
7247         /* we had to allocate for this iCode */
7248         freeAsmop(NULL,aop,ic,TRUE);
7249     } else { 
7250         /* we did not allocate which means left
7251            already in a pointer register, then
7252            if size > 0 && this could be used again
7253            we have to point it back to where it 
7254            belongs */
7255         if (AOP_SIZE(result) > 1 &&
7256             !OP_SYMBOL(left)->remat &&
7257             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7258               ic->depth )) {
7259             int size = AOP_SIZE(result) - 1;
7260             while (size--)
7261                 emitcode("dec","%s",rname);
7262         }
7263     }
7264
7265     /* done */
7266     freeAsmop(result,NULL,ic,TRUE);
7267      
7268 }
7269
7270 /*-----------------------------------------------------------------*/
7271 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7272 /*-----------------------------------------------------------------*/
7273 static void genPagedPointerGet (operand *left, 
7274                                operand *result, 
7275                                iCode *ic)
7276 {
7277     asmop *aop = NULL;
7278     regs *preg = NULL ;
7279     char *rname ;
7280     sym_link *rtype, *retype;    
7281
7282     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7283
7284     rtype = operandType(result);
7285     retype= getSpec(rtype);
7286     
7287     aopOp(left,ic,FALSE);
7288
7289   /* if the value is already in a pointer register
7290        then don't need anything more */
7291     if (!AOP_INPREG(AOP(left))) {
7292         /* otherwise get a free pointer register */
7293         aop = newAsmop(0);
7294         preg = getFreePtr(ic,&aop,FALSE);
7295         emitcode("mov","%s,%s",
7296                 preg->name,
7297                 aopGet(AOP(left),0,FALSE,TRUE));
7298         rname = preg->name ;
7299     } else
7300         rname = aopGet(AOP(left),0,FALSE,FALSE);
7301     
7302     freeAsmop(left,NULL,ic,TRUE);
7303     aopOp (result,ic,FALSE);
7304
7305     /* if bitfield then unpack the bits */
7306     if (IS_BITVAR(retype)) 
7307         genUnpackBits (result,rname,PPOINTER);
7308     else {
7309         /* we have can just get the values */
7310         int size = AOP_SIZE(result);
7311         int offset = 0 ;        
7312         
7313         while (size--) {
7314             
7315             emitcode("movx","a,@%s",rname);
7316             aopPut(AOP(result),"a",offset);
7317             
7318             offset++ ;
7319             
7320             if (size)
7321                 emitcode("inc","%s",rname);
7322         }
7323     }
7324
7325     /* now some housekeeping stuff */
7326     if (aop) {
7327         /* we had to allocate for this iCode */
7328         freeAsmop(NULL,aop,ic,TRUE);
7329     } else { 
7330         /* we did not allocate which means left
7331            already in a pointer register, then
7332            if size > 0 && this could be used again
7333            we have to point it back to where it 
7334            belongs */
7335         if (AOP_SIZE(result) > 1 &&
7336             !OP_SYMBOL(left)->remat &&
7337             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7338               ic->depth )) {
7339             int size = AOP_SIZE(result) - 1;
7340             while (size--)
7341                 emitcode("dec","%s",rname);
7342         }
7343     }
7344
7345     /* done */
7346     freeAsmop(result,NULL,ic,TRUE);
7347     
7348         
7349 }
7350
7351 /*-----------------------------------------------------------------*/
7352 /* genFarPointerGet - gget value from far space                    */
7353 /*-----------------------------------------------------------------*/
7354 static void genFarPointerGet (operand *left,
7355                               operand *result, iCode *ic)
7356 {
7357     int size, offset ;
7358     sym_link *retype = getSpec(operandType(result));
7359
7360     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7361
7362     aopOp(left,ic,FALSE);
7363
7364     /* if the operand is already in dptr 
7365     then we do nothing else we move the value to dptr */
7366     if (AOP_TYPE(left) != AOP_STR) {
7367         /* if this is remateriazable */
7368         if (AOP_TYPE(left) == AOP_IMMD)
7369             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7370         else { /* we need to get it byte by byte */
7371             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7372             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7373             if (options.model == MODEL_FLAT24)
7374             {
7375                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7376             }
7377         }
7378     }
7379     /* so dptr know contains the address */
7380     freeAsmop(left,NULL,ic,TRUE);
7381     aopOp(result,ic,FALSE);
7382
7383     /* if bit then unpack */
7384     if (IS_BITVAR(retype)) 
7385         genUnpackBits(result,"dptr",FPOINTER);
7386     else {
7387         size = AOP_SIZE(result);
7388         offset = 0 ;
7389
7390         while (size--) {
7391             emitcode("movx","a,@dptr");
7392             aopPut(AOP(result),"a",offset++);
7393             if (size)
7394                 emitcode("inc","dptr");
7395         }
7396     }
7397
7398     freeAsmop(result,NULL,ic,TRUE);
7399 }
7400
7401 /*-----------------------------------------------------------------*/
7402 /* emitcodePointerGet - gget value from code space                  */
7403 /*-----------------------------------------------------------------*/
7404 static void emitcodePointerGet (operand *left,
7405                                 operand *result, iCode *ic)
7406 {
7407     int size, offset ;
7408     sym_link *retype = getSpec(operandType(result));
7409
7410     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7411
7412     aopOp(left,ic,FALSE);
7413
7414     /* if the operand is already in dptr 
7415     then we do nothing else we move the value to dptr */
7416     if (AOP_TYPE(left) != AOP_STR) {
7417         /* if this is remateriazable */
7418         if (AOP_TYPE(left) == AOP_IMMD)
7419             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7420         else { /* we need to get it byte by byte */
7421             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7422             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7423             if (options.model == MODEL_FLAT24)
7424             {
7425                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7426             }
7427         }
7428     }
7429     /* so dptr know contains the address */
7430     freeAsmop(left,NULL,ic,TRUE);
7431     aopOp(result,ic,FALSE);
7432
7433     /* if bit then unpack */
7434     if (IS_BITVAR(retype)) 
7435         genUnpackBits(result,"dptr",CPOINTER);
7436     else {
7437         size = AOP_SIZE(result);
7438         offset = 0 ;
7439
7440         while (size--) {
7441             emitcode("clr","a");
7442             emitcode("movc","a,@a+dptr");
7443             aopPut(AOP(result),"a",offset++);
7444             if (size)
7445                 emitcode("inc","dptr");
7446         }
7447     }
7448
7449     freeAsmop(result,NULL,ic,TRUE);
7450 }
7451
7452 /*-----------------------------------------------------------------*/
7453 /* genGenPointerGet - gget value from generic pointer space        */
7454 /*-----------------------------------------------------------------*/
7455 static void genGenPointerGet (operand *left,
7456                               operand *result, iCode *ic)
7457 {
7458     int size, offset ;
7459     sym_link *retype = getSpec(operandType(result));
7460
7461     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7462     aopOp(left,ic,FALSE);
7463
7464     /* if the operand is already in dptr 
7465     then we do nothing else we move the value to dptr */
7466     if (AOP_TYPE(left) != AOP_STR) {
7467         /* if this is remateriazable */
7468         if (AOP_TYPE(left) == AOP_IMMD) {
7469             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7470             emitcode("mov","b,#%d",pointerCode(retype));
7471         }
7472         else { /* we need to get it byte by byte */
7473           
7474           emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7475           emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7476           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7477           emitcode("movwf","FSR");
7478           /*
7479             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7480             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7481             if (options.model == MODEL_FLAT24)
7482             {
7483                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7484                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7485             }
7486             else
7487             {
7488                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7489             }
7490           */
7491         }
7492     }
7493     /* so dptr know contains the address */
7494     freeAsmop(left,NULL,ic,TRUE);
7495     aopOp(result,ic,FALSE); 
7496
7497     /* if bit then unpack */
7498     if (IS_BITVAR(retype)) 
7499         genUnpackBits(result,"dptr",GPOINTER);
7500     else {
7501         size = AOP_SIZE(result);
7502         offset = 0 ;
7503
7504         while (size--) {
7505           emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7506           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7507           if(size)
7508             emitpcode(POC_INCF,popCopy(&pc_fsr));
7509 /*
7510           emitcode("movf","indf,w");
7511           emitcode("movwf","%s",
7512                    aopGet(AOP(result),offset++,FALSE,FALSE));
7513           if (size)
7514             emitcode("incf","fsr,f");
7515 */
7516         }
7517     }
7518
7519     freeAsmop(result,NULL,ic,TRUE);
7520 }
7521
7522 /*-----------------------------------------------------------------*/
7523 /* genPointerGet - generate code for pointer get                   */
7524 /*-----------------------------------------------------------------*/
7525 static void genPointerGet (iCode *ic)
7526 {
7527     operand *left, *result ;
7528     sym_link *type, *etype;
7529     int p_type;
7530
7531     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7532
7533     left = IC_LEFT(ic);
7534     result = IC_RESULT(ic) ;
7535
7536     /* depending on the type of pointer we need to
7537     move it to the correct pointer register */
7538     type = operandType(left);
7539     etype = getSpec(type);
7540     /* if left is of type of pointer then it is simple */
7541     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7542         p_type = DCL_TYPE(type);
7543     else {
7544         /* we have to go by the storage class */
7545         p_type = PTR_TYPE(SPEC_OCLS(etype));
7546
7547 /*      if (SPEC_OCLS(etype)->codesp ) { */
7548 /*          p_type = CPOINTER ;  */
7549 /*      } */
7550 /*      else */
7551 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7552 /*              p_type = FPOINTER ; */
7553 /*          else */
7554 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7555 /*                  p_type = PPOINTER; */
7556 /*              else */
7557 /*                  if (SPEC_OCLS(etype) == idata ) */
7558 /*                      p_type = IPOINTER; */
7559 /*                  else */
7560 /*                      p_type = POINTER ; */
7561     }
7562
7563     /* now that we have the pointer type we assign
7564     the pointer values */
7565     switch (p_type) {
7566
7567     case POINTER:       
7568     case IPOINTER:
7569         genNearPointerGet (left,result,ic);
7570         break;
7571
7572     case PPOINTER:
7573         genPagedPointerGet(left,result,ic);
7574         break;
7575
7576     case FPOINTER:
7577         genFarPointerGet (left,result,ic);
7578         break;
7579
7580     case CPOINTER:
7581         emitcodePointerGet (left,result,ic);
7582         break;
7583
7584     case GPOINTER:
7585         genGenPointerGet (left,result,ic);
7586         break;
7587     }
7588
7589 }
7590
7591 /*-----------------------------------------------------------------*/
7592 /* genPackBits - generates code for packed bit storage             */
7593 /*-----------------------------------------------------------------*/
7594 static void genPackBits (sym_link    *etype ,
7595                          operand *right ,
7596                          char *rname, int p_type)
7597 {
7598     int shCount = 0 ;
7599     int offset = 0  ;
7600     int rLen = 0 ;
7601     int blen, bstr ;   
7602     char *l ;
7603
7604     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7605     blen = SPEC_BLEN(etype);
7606     bstr = SPEC_BSTR(etype);
7607
7608     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7609     MOVA(l);   
7610
7611     /* if the bit lenth is less than or    */
7612     /* it exactly fits a byte then         */
7613     if (SPEC_BLEN(etype) <= 8 )  {
7614         shCount = SPEC_BSTR(etype) ;
7615
7616         /* shift left acc */
7617         AccLsh(shCount);
7618
7619         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7620
7621
7622             switch (p_type) {
7623                 case POINTER:
7624                     emitcode ("mov","b,a");
7625                     emitcode("mov","a,@%s",rname);
7626                     break;
7627
7628                 case FPOINTER:
7629                     emitcode ("mov","b,a");
7630                     emitcode("movx","a,@dptr");
7631                     break;
7632
7633                 case GPOINTER:
7634                     emitcode ("push","b");
7635                     emitcode ("push","acc");
7636                     emitcode ("lcall","__gptrget");
7637                     emitcode ("pop","b");
7638                     break;
7639             }
7640
7641             emitcode ("anl","a,#0x%02x",(unsigned char)
7642                       ((unsigned char)(0xFF << (blen+bstr)) | 
7643                        (unsigned char)(0xFF >> (8-bstr)) ) );
7644             emitcode ("orl","a,b");
7645             if (p_type == GPOINTER)
7646                 emitcode("pop","b");
7647         }
7648     }
7649
7650     switch (p_type) {
7651         case POINTER:
7652             emitcode("mov","@%s,a",rname);
7653             break;
7654
7655         case FPOINTER:
7656             emitcode("movx","@dptr,a");
7657             break;
7658
7659         case GPOINTER:
7660             DEBUGemitcode(";lcall","__gptrput");
7661             break;
7662     }
7663
7664     /* if we r done */
7665     if ( SPEC_BLEN(etype) <= 8 )
7666         return ;
7667
7668     emitcode("inc","%s",rname);
7669     rLen = SPEC_BLEN(etype) ;     
7670
7671     /* now generate for lengths greater than one byte */
7672     while (1) {
7673
7674         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7675
7676         rLen -= 8 ;
7677         if (rLen <= 0 )
7678             break ;
7679
7680         switch (p_type) {
7681             case POINTER:
7682                 if (*l == '@') {
7683                     MOVA(l);
7684                     emitcode("mov","@%s,a",rname);
7685                 } else
7686                     emitcode("mov","@%s,%s",rname,l);
7687                 break;
7688
7689             case FPOINTER:
7690                 MOVA(l);
7691                 emitcode("movx","@dptr,a");
7692                 break;
7693
7694             case GPOINTER:
7695                 MOVA(l);
7696                 DEBUGemitcode(";lcall","__gptrput");
7697                 break;  
7698         }   
7699         emitcode ("inc","%s",rname);
7700     }
7701
7702     MOVA(l);
7703
7704     /* last last was not complete */
7705     if (rLen)   {
7706         /* save the byte & read byte */
7707         switch (p_type) {
7708             case POINTER:
7709                 emitcode ("mov","b,a");
7710                 emitcode("mov","a,@%s",rname);
7711                 break;
7712
7713             case FPOINTER:
7714                 emitcode ("mov","b,a");
7715                 emitcode("movx","a,@dptr");
7716                 break;
7717
7718             case GPOINTER:
7719                 emitcode ("push","b");
7720                 emitcode ("push","acc");
7721                 emitcode ("lcall","__gptrget");
7722                 emitcode ("pop","b");
7723                 break;
7724         }
7725
7726         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7727         emitcode ("orl","a,b");
7728     }
7729
7730     if (p_type == GPOINTER)
7731         emitcode("pop","b");
7732
7733     switch (p_type) {
7734
7735     case POINTER:
7736         emitcode("mov","@%s,a",rname);
7737         break;
7738         
7739     case FPOINTER:
7740         emitcode("movx","@dptr,a");
7741         break;
7742         
7743     case GPOINTER:
7744         DEBUGemitcode(";lcall","__gptrput");
7745         break;                  
7746     }
7747 }
7748 /*-----------------------------------------------------------------*/
7749 /* genDataPointerSet - remat pointer to data space                 */
7750 /*-----------------------------------------------------------------*/
7751 static void genDataPointerSet(operand *right,
7752                               operand *result,
7753                               iCode *ic)
7754 {
7755     int size, offset = 0 ;
7756     char *l, buffer[256];
7757
7758     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7759     aopOp(right,ic,FALSE);
7760     
7761     l = aopGet(AOP(result),0,FALSE,TRUE);
7762     size = AOP_SIZE(right);
7763     // tsd, was l+1 - the underline `_' prefix was being stripped
7764     while (size--) {
7765         if (offset)
7766             sprintf(buffer,"(%s + %d)",l,offset);
7767         else
7768             sprintf(buffer,"%s",l);
7769
7770         if (AOP_TYPE(right) == AOP_LIT) {
7771           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7772           lit = lit >> (8*offset);
7773           if(lit) {
7774             emitcode("movlw","%s",lit);
7775             emitcode("movwf","%s",buffer);
7776           } else 
7777             emitcode("clrf","%s",buffer);
7778         }else {
7779           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7780           emitcode("movwf","%s",buffer);
7781         }
7782
7783         offset++;
7784     }
7785
7786     freeAsmop(right,NULL,ic,TRUE);
7787     freeAsmop(result,NULL,ic,TRUE);
7788 }
7789
7790 /*-----------------------------------------------------------------*/
7791 /* genNearPointerSet - emitcode for near pointer put                */
7792 /*-----------------------------------------------------------------*/
7793 static void genNearPointerSet (operand *right,
7794                                operand *result, 
7795                                iCode *ic)
7796 {
7797     asmop *aop = NULL;
7798     char *l;
7799     sym_link *retype;
7800     sym_link *ptype = operandType(result);
7801
7802     
7803     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7804     retype= getSpec(operandType(right));
7805
7806     aopOp(result,ic,FALSE);
7807     
7808     /* if the result is rematerializable &
7809        in data space & not a bit variable */
7810     if (AOP_TYPE(result) == AOP_IMMD &&
7811         DCL_TYPE(ptype) == POINTER   &&
7812         !IS_BITVAR(retype)) {
7813         genDataPointerSet (right,result,ic);
7814         return;
7815     }
7816
7817     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7818
7819     /* if the value is already in a pointer register
7820     then don't need anything more */
7821     if (!AOP_INPREG(AOP(result))) {
7822         /* otherwise get a free pointer register */
7823         //aop = newAsmop(0);
7824         //preg = getFreePtr(ic,&aop,FALSE);
7825         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7826         //emitcode("mov","%s,%s",
7827         //         preg->name,
7828         //         aopGet(AOP(result),0,FALSE,TRUE));
7829         //rname = preg->name ;
7830         emitcode("movwf","fsr");
7831     }// else
7832     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7833
7834     freeAsmop(result,NULL,ic,TRUE);
7835     aopOp (right,ic,FALSE);
7836     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7837
7838     /* if bitfield then unpack the bits */
7839     if (IS_BITVAR(retype)) {
7840       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7841              "The programmer is obviously confused");
7842       //genPackBits (retype,right,rname,POINTER);
7843       exit(1);
7844     }
7845     else {
7846         /* we have can just get the values */
7847         int size = AOP_SIZE(right);
7848         int offset = 0 ;    
7849
7850     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7851         while (size--) {
7852             l = aopGet(AOP(right),offset,FALSE,TRUE);
7853             if (*l == '@' ) {
7854               //MOVA(l);
7855               //emitcode("mov","@%s,a",rname);
7856               emitcode("movf","indf,w ;1");
7857             } else {
7858
7859               if (AOP_TYPE(right) == AOP_LIT) {
7860                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7861                 if(lit) {
7862                   emitcode("movlw","%s",l);
7863                   emitcode("movwf","indf ;2");
7864                 } else 
7865                   emitcode("clrf","indf");
7866               }else {
7867                 emitcode("movf","%s,w",l);
7868                 emitcode("movwf","indf ;2");
7869               }
7870             //emitcode("mov","@%s,%s",rname,l);
7871             }
7872             if (size)
7873               emitcode("incf","fsr,f ;3");
7874             //emitcode("inc","%s",rname);
7875             offset++;
7876         }
7877     }
7878
7879     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7880     /* now some housekeeping stuff */
7881     if (aop) {
7882         /* we had to allocate for this iCode */
7883         freeAsmop(NULL,aop,ic,TRUE);
7884     } else { 
7885         /* we did not allocate which means left
7886         already in a pointer register, then
7887         if size > 0 && this could be used again
7888         we have to point it back to where it 
7889         belongs */
7890     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7891         if (AOP_SIZE(right) > 1 &&
7892             !OP_SYMBOL(result)->remat &&
7893             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7894               ic->depth )) {
7895             int size = AOP_SIZE(right) - 1;
7896             while (size--)
7897               emitcode("decf","fsr,f");
7898               //emitcode("dec","%s",rname);
7899         }
7900     }
7901
7902     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7903     /* done */
7904     freeAsmop(right,NULL,ic,TRUE);
7905
7906
7907 }
7908
7909 /*-----------------------------------------------------------------*/
7910 /* genPagedPointerSet - emitcode for Paged pointer put             */
7911 /*-----------------------------------------------------------------*/
7912 static void genPagedPointerSet (operand *right,
7913                                operand *result, 
7914                                iCode *ic)
7915 {
7916     asmop *aop = NULL;
7917     regs *preg = NULL ;
7918     char *rname , *l;
7919     sym_link *retype;
7920        
7921     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7922
7923     retype= getSpec(operandType(right));
7924     
7925     aopOp(result,ic,FALSE);
7926     
7927     /* if the value is already in a pointer register
7928        then don't need anything more */
7929     if (!AOP_INPREG(AOP(result))) {
7930         /* otherwise get a free pointer register */
7931         aop = newAsmop(0);
7932         preg = getFreePtr(ic,&aop,FALSE);
7933         emitcode("mov","%s,%s",
7934                 preg->name,
7935                 aopGet(AOP(result),0,FALSE,TRUE));
7936         rname = preg->name ;
7937     } else
7938         rname = aopGet(AOP(result),0,FALSE,FALSE);
7939     
7940     freeAsmop(result,NULL,ic,TRUE);
7941     aopOp (right,ic,FALSE);
7942
7943     /* if bitfield then unpack the bits */
7944     if (IS_BITVAR(retype)) 
7945         genPackBits (retype,right,rname,PPOINTER);
7946     else {
7947         /* we have can just get the values */
7948         int size = AOP_SIZE(right);
7949         int offset = 0 ;        
7950         
7951         while (size--) {
7952             l = aopGet(AOP(right),offset,FALSE,TRUE);
7953             
7954             MOVA(l);
7955             emitcode("movx","@%s,a",rname);
7956
7957             if (size)
7958                 emitcode("inc","%s",rname);
7959
7960             offset++;
7961         }
7962     }
7963     
7964     /* now some housekeeping stuff */
7965     if (aop) {
7966         /* we had to allocate for this iCode */
7967         freeAsmop(NULL,aop,ic,TRUE);
7968     } else { 
7969         /* we did not allocate which means left
7970            already in a pointer register, then
7971            if size > 0 && this could be used again
7972            we have to point it back to where it 
7973            belongs */
7974         if (AOP_SIZE(right) > 1 &&
7975             !OP_SYMBOL(result)->remat &&
7976             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7977               ic->depth )) {
7978             int size = AOP_SIZE(right) - 1;
7979             while (size--)
7980                 emitcode("dec","%s",rname);
7981         }
7982     }
7983
7984     /* done */
7985     freeAsmop(right,NULL,ic,TRUE);
7986     
7987         
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* genFarPointerSet - set value from far space                     */
7992 /*-----------------------------------------------------------------*/
7993 static void genFarPointerSet (operand *right,
7994                               operand *result, iCode *ic)
7995 {
7996     int size, offset ;
7997     sym_link *retype = getSpec(operandType(right));
7998
7999     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8000     aopOp(result,ic,FALSE);
8001
8002     /* if the operand is already in dptr 
8003     then we do nothing else we move the value to dptr */
8004     if (AOP_TYPE(result) != AOP_STR) {
8005         /* if this is remateriazable */
8006         if (AOP_TYPE(result) == AOP_IMMD)
8007             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8008         else { /* we need to get it byte by byte */
8009             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8010             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8011             if (options.model == MODEL_FLAT24)
8012             {
8013                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8014             }
8015         }
8016     }
8017     /* so dptr know contains the address */
8018     freeAsmop(result,NULL,ic,TRUE);
8019     aopOp(right,ic,FALSE);
8020
8021     /* if bit then unpack */
8022     if (IS_BITVAR(retype)) 
8023         genPackBits(retype,right,"dptr",FPOINTER);
8024     else {
8025         size = AOP_SIZE(right);
8026         offset = 0 ;
8027
8028         while (size--) {
8029             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8030             MOVA(l);
8031             emitcode("movx","@dptr,a");
8032             if (size)
8033                 emitcode("inc","dptr");
8034         }
8035     }
8036
8037     freeAsmop(right,NULL,ic,TRUE);
8038 }
8039
8040 /*-----------------------------------------------------------------*/
8041 /* genGenPointerSet - set value from generic pointer space         */
8042 /*-----------------------------------------------------------------*/
8043 static void genGenPointerSet (operand *right,
8044                               operand *result, iCode *ic)
8045 {
8046     int size, offset ;
8047     sym_link *retype = getSpec(operandType(right));
8048
8049     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8050
8051     aopOp(result,ic,FALSE);
8052
8053     /* if the operand is already in dptr 
8054     then we do nothing else we move the value to dptr */
8055     if (AOP_TYPE(result) != AOP_STR) {
8056         /* if this is remateriazable */
8057         if (AOP_TYPE(result) == AOP_IMMD) {
8058             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8059             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8060         }
8061         else { /* we need to get it byte by byte */
8062           char *l = aopGet(AOP(result),0,FALSE,FALSE);
8063
8064           if(strcmp("FSR",l))
8065             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8066           emitpcode(POC_MOVWF,popCopy(&pc_indf));
8067
8068           if(strcmp("FSR",l))
8069             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8070
8071           emitcode("movwf","INDF");
8072         }
8073     }
8074     /* so dptr know contains the address */
8075     freeAsmop(result,NULL,ic,TRUE);
8076     aopOp(right,ic,FALSE);
8077
8078     /* if bit then unpack */
8079     if (IS_BITVAR(retype)) 
8080         genPackBits(retype,right,"dptr",GPOINTER);
8081     else {
8082         size = AOP_SIZE(right);
8083         offset = 0 ;
8084
8085         while (--size) {
8086             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8087             if(size)
8088               emitcode("incf","fsr,f");
8089             emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8090             emitcode("movwf","indf");
8091             //MOVA(l);
8092             //DEBUGemitcode(";lcall","__gptrput");
8093             //if (size)
8094             //    emitcode("inc","dptr");
8095         }
8096     }
8097
8098     freeAsmop(right,NULL,ic,TRUE);
8099 }
8100
8101 /*-----------------------------------------------------------------*/
8102 /* genPointerSet - stores the value into a pointer location        */
8103 /*-----------------------------------------------------------------*/
8104 static void genPointerSet (iCode *ic)
8105 {    
8106     operand *right, *result ;
8107     sym_link *type, *etype;
8108     int p_type;
8109
8110     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8111
8112     right = IC_RIGHT(ic);
8113     result = IC_RESULT(ic) ;
8114
8115     /* depending on the type of pointer we need to
8116     move it to the correct pointer register */
8117     type = operandType(result);
8118     etype = getSpec(type);
8119     /* if left is of type of pointer then it is simple */
8120     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8121         p_type = DCL_TYPE(type);
8122     }
8123     else {
8124         /* we have to go by the storage class */
8125         p_type = PTR_TYPE(SPEC_OCLS(etype));
8126
8127 /*      if (SPEC_OCLS(etype)->codesp ) { */
8128 /*          p_type = CPOINTER ;  */
8129 /*      } */
8130 /*      else */
8131 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8132 /*              p_type = FPOINTER ; */
8133 /*          else */
8134 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8135 /*                  p_type = PPOINTER ; */
8136 /*              else */
8137 /*                  if (SPEC_OCLS(etype) == idata ) */
8138 /*                      p_type = IPOINTER ; */
8139 /*                  else */
8140 /*                      p_type = POINTER ; */
8141     }
8142
8143     /* now that we have the pointer type we assign
8144     the pointer values */
8145     switch (p_type) {
8146
8147     case POINTER:
8148     case IPOINTER:
8149         genNearPointerSet (right,result,ic);
8150         break;
8151
8152     case PPOINTER:
8153         genPagedPointerSet (right,result,ic);
8154         break;
8155
8156     case FPOINTER:
8157         genFarPointerSet (right,result,ic);
8158         break;
8159
8160     case GPOINTER:
8161         genGenPointerSet (right,result,ic);
8162         break;
8163     }
8164
8165 }
8166
8167 /*-----------------------------------------------------------------*/
8168 /* genIfx - generate code for Ifx statement                        */
8169 /*-----------------------------------------------------------------*/
8170 static void genIfx (iCode *ic, iCode *popIc)
8171 {
8172     operand *cond = IC_COND(ic);
8173     int isbit =0;
8174
8175     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8176     aopOp(cond,ic,FALSE);
8177
8178     /* get the value into acc */
8179     if (AOP_TYPE(cond) != AOP_CRY)
8180         toBoolean(cond);
8181     else
8182         isbit = 1;
8183     /* the result is now in the accumulator */
8184     freeAsmop(cond,NULL,ic,TRUE);
8185
8186     /* if there was something to be popped then do it */
8187     if (popIc)
8188         genIpop(popIc);
8189
8190     /* if the condition is  a bit variable */
8191     if (isbit && IS_ITEMP(cond) && 
8192         SPIL_LOC(cond)) {
8193       genIfxJump(ic,SPIL_LOC(cond)->rname);
8194       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8195     }
8196     else {
8197       /*
8198         if (isbit && !IS_ITEMP(cond))
8199           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8200         else
8201           DEBUGemitcode ("; isbit","a");
8202       */
8203
8204         if (isbit && !IS_ITEMP(cond))
8205             genIfxJump(ic,OP_SYMBOL(cond)->rname);
8206         else
8207             genIfxJump(ic,"a");
8208     }
8209     ic->generated = 1;
8210 }
8211
8212 /*-----------------------------------------------------------------*/
8213 /* genAddrOf - generates code for address of                       */
8214 /*-----------------------------------------------------------------*/
8215 static void genAddrOf (iCode *ic)
8216 {
8217     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8218     int size, offset ;
8219
8220     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8221
8222     aopOp(IC_RESULT(ic),ic,FALSE);
8223
8224     /* if the operand is on the stack then we 
8225     need to get the stack offset of this
8226     variable */
8227     if (sym->onStack) {
8228         /* if it has an offset then we need to compute
8229         it */
8230         if (sym->stack) {
8231             emitcode("mov","a,_bp");
8232             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8233             aopPut(AOP(IC_RESULT(ic)),"a",0);       
8234         } else {
8235             /* we can just move _bp */
8236             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8237         }
8238         /* fill the result with zero */
8239         size = AOP_SIZE(IC_RESULT(ic)) - 1;
8240         
8241         
8242         if (options.stack10bit && size < (FPTRSIZE - 1))
8243         {
8244             fprintf(stderr, 
8245                     "*** warning: pointer to stack var truncated.\n");
8246         }
8247         
8248         offset = 1;
8249         while (size--)
8250         {
8251             /* Yuck! */
8252             if (options.stack10bit && offset == 2)
8253             {
8254                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8255             }
8256             else
8257             {
8258                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8259             }
8260         }
8261
8262         goto release;
8263     }
8264
8265     /* object not on stack then we need the name */
8266     size = AOP_SIZE(IC_RESULT(ic));
8267     offset = 0;
8268
8269     while (size--) {
8270         char s[SDCC_NAME_MAX];
8271         if (offset) 
8272             sprintf(s,"#(%s >> %d)",
8273                     sym->rname,
8274                     offset*8);
8275         else
8276             sprintf(s,"#%s",sym->rname);
8277         aopPut(AOP(IC_RESULT(ic)),s,offset++);
8278     }
8279
8280 release:
8281     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8282
8283 }
8284
8285 #if 0
8286 /*-----------------------------------------------------------------*/
8287 /* genFarFarAssign - assignment when both are in far space         */
8288 /*-----------------------------------------------------------------*/
8289 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8290 {
8291     int size = AOP_SIZE(right);
8292     int offset = 0;
8293     char *l ;
8294     /* first push the right side on to the stack */
8295     while (size--) {
8296         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8297         MOVA(l);
8298         emitcode ("push","acc");
8299     }
8300     
8301     freeAsmop(right,NULL,ic,FALSE);
8302     /* now assign DPTR to result */
8303     aopOp(result,ic,FALSE);
8304     size = AOP_SIZE(result);
8305     while (size--) {
8306         emitcode ("pop","acc");
8307         aopPut(AOP(result),"a",--offset);
8308     }
8309     freeAsmop(result,NULL,ic,FALSE);
8310         
8311 }
8312 #endif
8313
8314 /*-----------------------------------------------------------------*/
8315 /* genAssign - generate code for assignment                        */
8316 /*-----------------------------------------------------------------*/
8317 static void genAssign (iCode *ic)
8318 {
8319     operand *result, *right;
8320     int size, offset ;
8321         unsigned long lit = 0L;
8322
8323     result = IC_RESULT(ic);
8324     right  = IC_RIGHT(ic) ;
8325
8326     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8327
8328     /* if they are the same */
8329     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8330         return ;
8331
8332     aopOp(right,ic,FALSE);
8333     aopOp(result,ic,TRUE);
8334
8335     /* if they are the same registers */
8336     if (sameRegs(AOP(right),AOP(result)))
8337         goto release;
8338
8339     /* if the result is a bit */
8340     if (AOP_TYPE(result) == AOP_CRY) {
8341
8342         /* if the right size is a literal then
8343         we know what the value is */
8344         if (AOP_TYPE(right) == AOP_LIT) {
8345           
8346           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8347                       popGet(AOP(result),0,FALSE,FALSE));
8348
8349             if (((int) operandLitValue(right))) 
8350               emitcode("bsf","(%s >> 3),(%s & 7)",
8351                        AOP(result)->aopu.aop_dir,
8352                        AOP(result)->aopu.aop_dir);
8353             else
8354               emitcode("bcf","(%s >> 3),(%s & 7)",
8355                  AOP(result)->aopu.aop_dir,
8356                  AOP(result)->aopu.aop_dir);
8357             goto release;
8358         }
8359
8360         /* the right is also a bit variable */
8361         if (AOP_TYPE(right) == AOP_CRY) {
8362           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8363           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8364           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8365
8366           emitcode("bcf","(%s >> 3),(%s & 7)",
8367                    AOP(result)->aopu.aop_dir,
8368                    AOP(result)->aopu.aop_dir);
8369           emitcode("btfsc","(%s >> 3),(%s & 7)",
8370                    AOP(right)->aopu.aop_dir,
8371                    AOP(right)->aopu.aop_dir);
8372           emitcode("bsf","(%s >> 3),(%s & 7)",
8373                    AOP(result)->aopu.aop_dir,
8374                    AOP(result)->aopu.aop_dir);
8375           goto release ;
8376         }
8377
8378         /* we need to or */
8379         toBoolean(right);
8380         aopPut(AOP(result),"a",0);
8381         goto release ;
8382     }
8383
8384     /* bit variables done */
8385     /* general case */
8386     size = AOP_SIZE(result);
8387     offset = 0 ;
8388     if(AOP_TYPE(right) == AOP_LIT)
8389         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8390     if((AOP_TYPE(result) != AOP_REG) &&
8391        (AOP_TYPE(right) == AOP_LIT) &&
8392        !IS_FLOAT(operandType(right)) &&
8393        (lit < 256L)){
8394
8395         while (size--) {
8396           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8397             //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8398               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8399             }else {
8400               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8401               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8402               //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8403               //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8404             }
8405         }
8406     } else {
8407         while (size--) {
8408           if(AOP_TYPE(right) == AOP_LIT)
8409             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8410           //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8411           else
8412             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8413           //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8414             
8415           emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8416           //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8417           offset++;
8418         }
8419     }
8420     
8421 release:
8422     freeAsmop (right,NULL,ic,FALSE);
8423     freeAsmop (result,NULL,ic,TRUE);
8424 }   
8425
8426 /*-----------------------------------------------------------------*/
8427 /* genJumpTab - genrates code for jump table                       */
8428 /*-----------------------------------------------------------------*/
8429 static void genJumpTab (iCode *ic)
8430 {
8431     symbol *jtab;
8432     char *l;
8433
8434     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8435
8436     aopOp(IC_JTCOND(ic),ic,FALSE);
8437     /* get the condition into accumulator */
8438     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8439     MOVA(l);
8440     /* multiply by three */
8441     emitcode("add","a,acc");
8442     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8443     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8444
8445     jtab = newiTempLabel(NULL);
8446     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8447     emitcode("jmp","@a+dptr");
8448     emitcode("","%05d_DS_:",jtab->key+100);
8449     /* now generate the jump labels */
8450     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8451          jtab = setNextItem(IC_JTLABELS(ic)))
8452         emitcode("ljmp","%05d_DS_",jtab->key+100);
8453
8454 }
8455
8456 /*-----------------------------------------------------------------*/
8457 /* genMixedOperation - gen code for operators between mixed types  */
8458 /*-----------------------------------------------------------------*/
8459 /*
8460   TSD - Written for the PIC port - but this unfortunately is buggy.
8461   This routine is good in that it is able to efficiently promote 
8462   types to different (larger) sizes. Unfortunately, the temporary
8463   variables that are optimized out by this routine are sometimes
8464   used in other places. So until I know how to really parse the 
8465   iCode tree, I'm going to not be using this routine :(.
8466 */
8467 static int genMixedOperation (iCode *ic)
8468 {
8469 #if 0
8470   operand *result = IC_RESULT(ic);
8471   sym_link *ctype = operandType(IC_LEFT(ic));
8472   operand *right = IC_RIGHT(ic);
8473   int ret = 0;
8474   int big,small;
8475   int offset;
8476
8477   iCode *nextic;
8478   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8479
8480   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8481
8482   nextic = ic->next;
8483   if(!nextic)
8484     return 0;
8485
8486   nextright = IC_RIGHT(nextic);
8487   nextleft  = IC_LEFT(nextic);
8488   nextresult = IC_RESULT(nextic);
8489
8490   aopOp(right,ic,FALSE);
8491   aopOp(result,ic,FALSE);
8492   aopOp(nextright,  nextic, FALSE);
8493   aopOp(nextleft,   nextic, FALSE);
8494   aopOp(nextresult, nextic, FALSE);
8495
8496   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8497
8498     operand *t = right;
8499     right = nextright;
8500     nextright = t; 
8501
8502     emitcode(";remove right +","");
8503
8504   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8505 /*
8506     operand *t = right;
8507     right = nextleft;
8508     nextleft = t; 
8509 */
8510     emitcode(";remove left +","");
8511   } else
8512     return 0;
8513
8514   big = AOP_SIZE(nextleft);
8515   small = AOP_SIZE(nextright);
8516
8517   switch(nextic->op) {
8518
8519   case '+':
8520     emitcode(";optimize a +","");
8521     /* if unsigned or not an integral type */
8522     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8523       emitcode(";add a bit to something","");
8524     } else {
8525
8526       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8527
8528       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8529         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8530         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8531       } else
8532         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8533
8534       offset = 0;
8535       while(--big) {
8536
8537         offset++;
8538
8539         if(--small) {
8540           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8541             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8542             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8543           }
8544
8545           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8546           emitSKPNC;
8547           emitcode("btfsc","(%s >> 3), (%s & 7)",
8548                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8549                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8550           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8551           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8552
8553         } else {
8554           emitcode("rlf","known_zero,w");
8555
8556           /*
8557             if right is signed
8558               btfsc  right,7
8559                addlw ff
8560           */
8561           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8562             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8563             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8564           } else {
8565             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8566           }
8567         }
8568       }
8569       ret = 1;
8570     }
8571   }
8572   ret = 1;
8573
8574 release:
8575   freeAsmop(right,NULL,ic,TRUE);
8576   freeAsmop(result,NULL,ic,TRUE);
8577   freeAsmop(nextright,NULL,ic,TRUE);
8578   freeAsmop(nextleft,NULL,ic,TRUE);
8579   if(ret)
8580     nextic->generated = 1;
8581
8582   return ret;
8583 #else
8584   return 0;
8585 #endif
8586 }
8587 /*-----------------------------------------------------------------*/
8588 /* genCast - gen code for casting                                  */
8589 /*-----------------------------------------------------------------*/
8590 static void genCast (iCode *ic)
8591 {
8592     operand *result = IC_RESULT(ic);
8593     sym_link *ctype = operandType(IC_LEFT(ic));
8594     operand *right = IC_RIGHT(ic);
8595     int size, offset ;
8596
8597     DEBUGemitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8598     /* if they are equivalent then do nothing */
8599     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8600         return ;
8601
8602     aopOp(right,ic,FALSE) ;
8603     aopOp(result,ic,FALSE);
8604
8605     /* if the result is a bit */
8606     if (AOP_TYPE(result) == AOP_CRY) {
8607         /* if the right size is a literal then
8608         we know what the value is */
8609         if (AOP_TYPE(right) == AOP_LIT) {
8610
8611           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8612                       popGet(AOP(result),0,FALSE,FALSE));
8613
8614             if (((int) operandLitValue(right))) 
8615               emitcode("bsf","(%s >> 3), (%s & 7)",
8616                        AOP(result)->aopu.aop_dir,
8617                        AOP(result)->aopu.aop_dir);
8618             else
8619               emitcode("bcf","(%s >> 3), (%s & 7)",
8620                        AOP(result)->aopu.aop_dir,
8621                        AOP(result)->aopu.aop_dir);
8622
8623             goto release;
8624         }
8625
8626         /* the right is also a bit variable */
8627         if (AOP_TYPE(right) == AOP_CRY) {
8628
8629           emitCLRC;
8630           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8631
8632           emitcode("clrc","");
8633           emitcode("btfsc","(%s >> 3), (%s & 7)",
8634                    AOP(right)->aopu.aop_dir,
8635                    AOP(right)->aopu.aop_dir);
8636             aopPut(AOP(result),"c",0);
8637             goto release ;
8638         }
8639
8640         /* we need to or */
8641         toBoolean(right);
8642         aopPut(AOP(result),"a",0);
8643         goto release ;
8644     }
8645
8646     /* if they are the same size : or less */
8647     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8648
8649         /* if they are in the same place */
8650         if (sameRegs(AOP(right),AOP(result)))
8651             goto release;
8652
8653         /* if they in different places then copy */
8654         size = AOP_SIZE(result);
8655         offset = 0 ;
8656         while (size--) {
8657             aopPut(AOP(result),
8658                    aopGet(AOP(right),offset,FALSE,FALSE),
8659                    offset);
8660             offset++;
8661         }
8662         goto release;
8663     }
8664
8665
8666     /* if the result is of type pointer */
8667     if (IS_PTR(ctype)) {
8668
8669         int p_type;
8670         sym_link *type = operandType(right);
8671         sym_link *etype = getSpec(type);
8672
8673         /* pointer to generic pointer */
8674         if (IS_GENPTR(ctype)) {
8675             char *l = zero;
8676             
8677             if (IS_PTR(type)) 
8678                 p_type = DCL_TYPE(type);
8679             else {
8680                 /* we have to go by the storage class */
8681                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8682
8683 /*              if (SPEC_OCLS(etype)->codesp )  */
8684 /*                  p_type = CPOINTER ;  */
8685 /*              else */
8686 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8687 /*                      p_type = FPOINTER ; */
8688 /*                  else */
8689 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8690 /*                          p_type = PPOINTER; */
8691 /*                      else */
8692 /*                          if (SPEC_OCLS(etype) == idata ) */
8693 /*                              p_type = IPOINTER ; */
8694 /*                          else */
8695 /*                              p_type = POINTER ; */
8696             }
8697                 
8698             /* the first two bytes are known */
8699             size = GPTRSIZE - 1; 
8700             offset = 0 ;
8701             while (size--) {
8702                 aopPut(AOP(result),
8703                        aopGet(AOP(right),offset,FALSE,FALSE),
8704                        offset);
8705                 offset++;
8706             }
8707             /* the last byte depending on type */
8708             switch (p_type) {
8709             case IPOINTER:
8710             case POINTER:
8711                 l = zero;
8712                 break;
8713             case FPOINTER:
8714                 l = one;
8715                 break;
8716             case CPOINTER:
8717                 l = "#0x02";
8718                 break;                          
8719             case PPOINTER:
8720                 l = "#0x03";
8721                 break;
8722                 
8723             default:
8724                 /* this should never happen */
8725                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8726                        "got unknown pointer type");
8727                 exit(1);
8728             }
8729             aopPut(AOP(result),l, GPTRSIZE - 1);            
8730             goto release ;
8731         }
8732         
8733         /* just copy the pointers */
8734         size = AOP_SIZE(result);
8735         offset = 0 ;
8736         while (size--) {
8737             aopPut(AOP(result),
8738                    aopGet(AOP(right),offset,FALSE,FALSE),
8739                    offset);
8740             offset++;
8741         }
8742         goto release ;
8743     }
8744     
8745
8746     if (AOP_TYPE(right) == AOP_CRY) {
8747       int offset = 1;
8748       size = AOP_SIZE(right);
8749
8750       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8751       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8752       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8753
8754       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8755       emitcode("btfsc","(%s >> 3), (%s & 7)",
8756                AOP(right)->aopu.aop_dir,
8757                AOP(right)->aopu.aop_dir);
8758       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8759       while (size--) {
8760         emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8761         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8762       }
8763       goto release;
8764     }
8765
8766     /* so we now know that the size of destination is greater
8767     than the size of the source.
8768     Now, if the next iCode is an operator then we might be
8769     able to optimize the operation without performing a cast.
8770     */
8771     if(genMixedOperation(ic))
8772       goto release;
8773
8774     
8775     /* we move to result for the size of source */
8776     size = AOP_SIZE(right);
8777     offset = 0 ;
8778     while (size--) {
8779       emitcode(";","%d",__LINE__);
8780         aopPut(AOP(result),
8781                aopGet(AOP(right),offset,FALSE,FALSE),
8782                offset);
8783         offset++;
8784     }
8785
8786     /* now depending on the sign of the destination */
8787     size = AOP_SIZE(result) - AOP_SIZE(right);
8788     /* if unsigned or not an integral type */
8789     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8790       while (size--) {
8791           emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8792           emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8793       }
8794     } else {
8795       /* we need to extend the sign :{ */
8796       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8797       //MOVA(l);
8798
8799       emitpcode(POC_CLRW,    NULL);
8800       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8801       emitpcode(POC_MOVLW,   popGetLit(0xff));
8802
8803         emitcode("clrw","");
8804         emitcode("btfsc","(%s >> 3), (%s & 7)",
8805                  AOP(right)->aopu.aop_dir,
8806                  AOP(right)->aopu.aop_dir);
8807         emitcode("movlw","0xff");
8808         while (size--) {
8809           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++,FALSE,FALSE));
8810           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8811           // aopPut(AOP(result),"a",offset++);
8812         }
8813
8814     }
8815
8816     /* we are done hurray !!!! */
8817
8818 release:
8819     freeAsmop(right,NULL,ic,TRUE);
8820     freeAsmop(result,NULL,ic,TRUE);
8821
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* genDjnz - generate decrement & jump if not zero instrucion      */
8826 /*-----------------------------------------------------------------*/
8827 static int genDjnz (iCode *ic, iCode *ifx)
8828 {
8829     symbol *lbl, *lbl1;
8830     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8831
8832     if (!ifx)
8833         return 0;
8834     
8835     /* if the if condition has a false label
8836        then we cannot save */
8837     if (IC_FALSE(ifx))
8838         return 0;
8839
8840     /* if the minus is not of the form 
8841        a = a - 1 */
8842     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8843         !IS_OP_LITERAL(IC_RIGHT(ic)))
8844         return 0;
8845
8846     if (operandLitValue(IC_RIGHT(ic)) != 1)
8847         return 0;
8848
8849     /* if the size of this greater than one then no
8850        saving */
8851     if (getSize(operandType(IC_RESULT(ic))) > 1)
8852         return 0;
8853
8854     /* otherwise we can save BIG */
8855     lbl = newiTempLabel(NULL);
8856     lbl1= newiTempLabel(NULL);
8857
8858     aopOp(IC_RESULT(ic),ic,FALSE);
8859     
8860     if (IS_AOP_PREG(IC_RESULT(ic))) {
8861         emitcode("dec","%s",
8862                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8863         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8864         emitcode("jnz","%05d_DS_",lbl->key+100);
8865     } else {    
8866
8867
8868       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8869       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8870
8871       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8872       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8873
8874     }
8875 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8876 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
8877 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8878 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
8879
8880     
8881     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8882     ifx->generated = 1;
8883     return 1;
8884 }
8885
8886 /*-----------------------------------------------------------------*/
8887 /* genReceive - generate code for a receive iCode                  */
8888 /*-----------------------------------------------------------------*/
8889 static void genReceive (iCode *ic)
8890 {    
8891     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8892
8893     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8894         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8895           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8896
8897         int size = getSize(operandType(IC_RESULT(ic)));
8898         int offset =  fReturnSize - size;
8899         while (size--) {
8900             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8901                                     fReturn[fReturnSize - offset - 1] : "acc"));
8902             offset++;
8903         }
8904         aopOp(IC_RESULT(ic),ic,FALSE);  
8905         size = AOP_SIZE(IC_RESULT(ic));
8906         offset = 0;
8907         while (size--) {
8908             emitcode ("pop","acc");
8909             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8910         }
8911         
8912     } else {
8913         _G.accInUse++;
8914         aopOp(IC_RESULT(ic),ic,FALSE);  
8915         _G.accInUse--;
8916         assignResultValue(IC_RESULT(ic));       
8917     }
8918
8919     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8920 }
8921
8922 /*-----------------------------------------------------------------*/
8923 /* genpic14Code - generate code for pic14 based controllers        */
8924 /*-----------------------------------------------------------------*/
8925 /*
8926  * At this point, ralloc.c has gone through the iCode and attempted
8927  * to optimize in a way suitable for a PIC. Now we've got to generate
8928  * PIC instructions that correspond to the iCode.
8929  *
8930  * Once the instructions are generated, we'll pass through both the
8931  * peep hole optimizer and the pCode optimizer.
8932  *-----------------------------------------------------------------*/
8933
8934 void genpic14Code (iCode *lic)
8935 {
8936     iCode *ic;
8937     int cln = 0;
8938
8939     lineHead = lineCurr = NULL;
8940
8941     pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8942     addpBlock(pb);
8943
8944     /* if debug information required */
8945 /*     if (options.debug && currFunc) { */
8946     if (currFunc) {
8947         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8948         _G.debugLine = 1;
8949         if (IS_STATIC(currFunc->etype)) {
8950             emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8951             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8952         } else {
8953             emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8954             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8955         }
8956         _G.debugLine = 0;
8957     }
8958
8959
8960     for (ic = lic ; ic ; ic = ic->next ) {
8961
8962       DEBUGemitcode(";ic","");
8963         if ( cln != ic->lineno ) {
8964             if ( options.debug ) {
8965                 _G.debugLine = 1;
8966                 emitcode("",";C$%s$%d$%d$%d ==.",
8967                          FileBaseName(ic->filename),ic->lineno,
8968                          ic->level,ic->block);
8969                 _G.debugLine = 0;
8970             }
8971             emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8972             cln = ic->lineno ;
8973         }
8974         /* if the result is marked as
8975            spilt and rematerializable or code for
8976            this has already been generated then
8977            do nothing */
8978         if (resultRemat(ic) || ic->generated ) 
8979             continue ;
8980         
8981         /* depending on the operation */
8982         switch (ic->op) {
8983         case '!' :
8984             genNot(ic);
8985             break;
8986             
8987         case '~' :
8988             genCpl(ic);
8989             break;
8990             
8991         case UNARYMINUS:
8992             genUminus (ic);
8993             break;
8994             
8995         case IPUSH:
8996             genIpush (ic);
8997             break;
8998             
8999         case IPOP:
9000             /* IPOP happens only when trying to restore a 
9001                spilt live range, if there is an ifx statement
9002                following this pop then the if statement might
9003                be using some of the registers being popped which
9004                would destory the contents of the register so
9005                we need to check for this condition and handle it */
9006             if (ic->next            && 
9007                 ic->next->op == IFX &&
9008                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9009                 genIfx (ic->next,ic);
9010             else
9011                 genIpop (ic);
9012             break; 
9013             
9014         case CALL:
9015             genCall (ic);
9016             break;
9017             
9018         case PCALL:
9019             genPcall (ic);
9020             break;
9021             
9022         case FUNCTION:
9023             genFunction (ic);
9024             break;
9025             
9026         case ENDFUNCTION:
9027             genEndFunction (ic);
9028             break;
9029             
9030         case RETURN:
9031             genRet (ic);
9032             break;
9033             
9034         case LABEL:
9035             genLabel (ic);
9036             break;
9037             
9038         case GOTO:
9039             genGoto (ic);
9040             break;
9041             
9042         case '+' :
9043             genPlus (ic) ;
9044             break;
9045             
9046         case '-' :
9047             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9048                 genMinus (ic);
9049             break;
9050             
9051         case '*' :
9052             genMult (ic);
9053             break;
9054             
9055         case '/' :
9056             genDiv (ic) ;
9057             break;
9058             
9059         case '%' :
9060             genMod (ic);
9061             break;
9062             
9063         case '>' :
9064             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9065             break;
9066             
9067         case '<' :
9068             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9069             break;
9070             
9071         case LE_OP:
9072         case GE_OP:
9073         case NE_OP:
9074             
9075             /* note these two are xlated by algebraic equivalence
9076                during parsing SDCC.y */
9077             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9078                    "got '>=' or '<=' shouldn't have come here");
9079             break;      
9080             
9081         case EQ_OP:
9082             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9083             break;          
9084             
9085         case AND_OP:
9086             genAndOp (ic);
9087             break;
9088             
9089         case OR_OP:
9090             genOrOp (ic);
9091             break;
9092             
9093         case '^' :
9094             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9095             break;
9096             
9097         case '|' :
9098                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9099             break;
9100             
9101         case BITWISEAND:
9102             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9103             break;
9104             
9105         case INLINEASM:
9106             genInline (ic);
9107             break;
9108             
9109         case RRC:
9110             genRRC (ic);
9111             break;
9112             
9113         case RLC:
9114             genRLC (ic);
9115             break;
9116             
9117         case GETHBIT:
9118             genGetHbit (ic);
9119             break;
9120             
9121         case LEFT_OP:
9122             genLeftShift (ic);
9123             break;
9124             
9125         case RIGHT_OP:
9126             genRightShift (ic);
9127             break;
9128             
9129         case GET_VALUE_AT_ADDRESS:
9130             genPointerGet(ic);
9131             break;
9132             
9133         case '=' :
9134             if (POINTER_SET(ic))
9135                 genPointerSet(ic);
9136             else
9137                 genAssign(ic);
9138             break;
9139             
9140         case IFX:
9141             genIfx (ic,NULL);
9142             break;
9143             
9144         case ADDRESS_OF:
9145             genAddrOf (ic);
9146             break;
9147             
9148         case JUMPTABLE:
9149             genJumpTab (ic);
9150             break;
9151             
9152         case CAST:
9153             genCast (ic);
9154             break;
9155             
9156         case RECEIVE:
9157             genReceive(ic);
9158             break;
9159             
9160         case SEND:
9161             addSet(&_G.sendSet,ic);
9162             break;
9163
9164         default :
9165             ic = ic;
9166             /*      piCode(ic,stdout); */
9167             
9168         }
9169     }
9170     
9171
9172     /* now we are ready to call the 
9173        peep hole optimizer */
9174     if (!options.nopeep) {
9175       printf("peep hole optimizing\n");
9176         peepHole (&lineHead);
9177     }
9178     /* now do the actual printing */
9179     printLine (lineHead,codeOutFile);
9180
9181     printf("printing pBlock\n\n");
9182     printpBlock(stdout,pb);
9183
9184     return;
9185 }