pcode generation added
[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
38 #if defined(_MSC_VER)
39 #define __FUNCTION__            __FILE__
40 #endif
41
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54
55 #include "common.h"
56 #include "SDCCpeeph.h"
57 #include "ralloc.h"
58 #include "pcode.h"
59 #include "gen.h"
60
61 //char *aopLiteral (value *val, int offset);
62 unsigned int pic14aopLiteral (value *val, int offset);
63
64 /* this is the down and dirty file with all kinds of 
65    kludgy & hacky stuff. This is what it is all about
66    CODE GENERATION for a specific MCU . some of the
67    routines may be reusable, will have to see */
68
69 static char *zero = "#0x00";
70 static char *one  = "#0x01";
71 static char *spname = "sp";
72
73 char *fReturnpic14[] = {"fsr","dph","b","a" };
74 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
75 static unsigned fReturnSize = 4; /* shared with ralloc.c */
76 static char **fReturn = fReturnpic14;
77
78 static char *accUse[] = {"a","b"};
79
80 //static short rbank = -1;
81
82 static struct {
83     short r0Pushed;
84     short r1Pushed;
85     short accInUse;
86     short inLine;
87     short debugLine;
88     short nRegsSaved;
89     set *sendSet;
90 } _G;
91
92 extern int pic14_ptrRegReq ;
93 extern int pic14_nRegs;
94 extern FILE *codeOutFile;
95 static void saverbank (int, iCode *,bool);
96 #define RESULTONSTACK(x) \
97                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
98                          IC_RESULT(x)->aop->type == AOP_STK )
99
100 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
101 #define CLRC    emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
102
103 #define BIT_NUMBER(x) (x & 7)
104 #define BIT_REGISTER(x) (x>>3)
105
106 static lineNode *lineHead = NULL;
107 static lineNode *lineCurr = NULL;
108
109 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
112 0x07, 0x03, 0x01, 0x00};
113
114 #define LSB     0
115 #define MSB16   1
116 #define MSB24   2
117 #define MSB32   3
118
119
120 #define FUNCTION_LABEL_INC  20
121 static int labelOffset=0;
122 static int debug_verbose=1;
123
124 static  pBlock *pb;
125
126 /*-----------------------------------------------------------------*/
127 /* Macros for emitting instructions                                */
128 /*-----------------------------------------------------------------*/
129
130 #define emitSKPC    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
131 #define emitSKPNC   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPZ    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
133 #define emitSKPNZ   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitCLRZ    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRC    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
136 #define emitSETZ    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
137 #define emitSETC    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
138
139 //#define emitSKPC    emitcode("btfss","status,c")
140 //#define emitSKPNC   emitcode("btfsc","status,c")
141 //#define emitSKPZ    emitcode("btfss","status,z")
142 //#define emitSKPNZ   emitcode("btfsc","status,z")
143
144 /*-----------------------------------------------------------------*/
145 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
146 /*                 exponent of 2 is returned, otherwise -1 is      */
147 /*                 returned.                                       */
148 /* note that this is similar to the function `powof2' in SDCCsymt  */
149 /* if(n == 2^y)                                                    */
150 /*   return y;                                                     */
151 /* return -1;                                                      */
152 /*-----------------------------------------------------------------*/
153 static int my_powof2 (unsigned long num)
154 {
155   if(num) {
156     if( (num & (num-1)) == 0) {
157       int nshifts = -1;
158       while(num) {
159         num>>=1;
160         nshifts++;
161       }
162       return nshifts;
163     }
164   }
165
166   return -1;
167 }
168
169 static void emitpLabel(int key)
170 {
171   addpCode2pBlock(pb,newpCodeLabel(key));
172 }
173
174 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
175 {
176
177   addpCode2pBlock(pb,newpCode(poc,pcop));
178
179 }
180 /*-----------------------------------------------------------------*/
181 /* emitcode - writes the code into a file : for now it is simple    */
182 /*-----------------------------------------------------------------*/
183 static void emitcode (char *inst,char *fmt, ...)
184 {
185     va_list ap;
186     char lb[MAX_INLINEASM];  
187     char *lbp = lb;
188
189     va_start(ap,fmt);   
190
191     if (inst && *inst) {
192         if (fmt && *fmt)
193             sprintf(lb,"%s\t",inst);
194         else
195             sprintf(lb,"%s",inst);
196         vsprintf(lb+(strlen(lb)),fmt,ap);
197     }  else
198         vsprintf(lb,fmt,ap);
199
200     while (isspace(*lbp)) lbp++;
201
202     if (lbp && *lbp) 
203         lineCurr = (lineCurr ?
204                     connectLine(lineCurr,newLineNode(lb)) :
205                     (lineHead = newLineNode(lb)));
206     lineCurr->isInline = _G.inLine;
207     lineCurr->isDebug  = _G.debugLine;
208
209     addpCode2pBlock(pb,newpCodeCharP(lb));
210
211     va_end(ap);
212 }
213
214 static void DEBUGemitcode (char *inst,char *fmt, ...)
215 {
216     va_list ap;
217     char lb[MAX_INLINEASM];  
218     char *lbp = lb;
219
220     if(!debug_verbose)
221       return;
222
223     va_start(ap,fmt);   
224
225     if (inst && *inst) {
226         if (fmt && *fmt)
227             sprintf(lb,"%s\t",inst);
228         else
229             sprintf(lb,"%s",inst);
230         vsprintf(lb+(strlen(lb)),fmt,ap);
231     }  else
232         vsprintf(lb,fmt,ap);
233
234     while (isspace(*lbp)) lbp++;
235
236     if (lbp && *lbp) 
237         lineCurr = (lineCurr ?
238                     connectLine(lineCurr,newLineNode(lb)) :
239                     (lineHead = newLineNode(lb)));
240     lineCurr->isInline = _G.inLine;
241     lineCurr->isDebug  = _G.debugLine;
242
243     addpCode2pBlock(pb,newpCodeCharP(lb));
244
245     va_end(ap);
246 }
247
248
249 /*-----------------------------------------------------------------*/
250 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
251 /*-----------------------------------------------------------------*/
252 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
253 {
254     bool r0iu = FALSE , r1iu = FALSE;
255     bool r0ou = FALSE , r1ou = FALSE;
256
257     /* the logic: if r0 & r1 used in the instruction
258     then we are in trouble otherwise */
259
260     /* first check if r0 & r1 are used by this
261     instruction, in which case we are in trouble */
262     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
263         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
264     {
265         goto endOfWorld;      
266     }
267
268     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
269     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
270
271     /* if no usage of r0 then return it */
272     if (!r0iu && !r0ou) {
273         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
274         (*aopp)->type = AOP_R0;
275         
276         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
277     }
278
279     /* if no usage of r1 then return it */
280     if (!r1iu && !r1ou) {
281         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
282         (*aopp)->type = AOP_R1;
283
284         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
285     }    
286
287     /* now we know they both have usage */
288     /* if r0 not used in this instruction */
289     if (!r0iu) {
290         /* push it if not already pushed */
291         if (!_G.r0Pushed) {
292             emitcode ("push","%s",
293                       pic14_regWithIdx(R0_IDX)->dname);
294             _G.r0Pushed++ ;
295         }
296         
297         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
298         (*aopp)->type = AOP_R0;
299
300         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
301     }
302
303     /* if r1 not used then */
304
305     if (!r1iu) {
306         /* push it if not already pushed */
307         if (!_G.r1Pushed) {
308             emitcode ("push","%s",
309                       pic14_regWithIdx(R1_IDX)->dname);
310             _G.r1Pushed++ ;
311         }
312         
313         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
314         (*aopp)->type = AOP_R1;
315         return pic14_regWithIdx(R1_IDX);
316     }
317
318 endOfWorld :
319     /* I said end of world but not quite end of world yet */
320     /* if this is a result then we can push it on the stack*/
321     if (result) {
322         (*aopp)->type = AOP_STK;    
323         return NULL;
324     }
325
326     piCode(ic,stdout);
327     /* other wise this is true end of the world */
328     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
329            "getFreePtr should never reach here");
330     exit(0);
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* newAsmop - creates a new asmOp                                  */
335 /*-----------------------------------------------------------------*/
336 static asmop *newAsmop (short type)
337 {
338     asmop *aop;
339
340     _ALLOC(aop,sizeof(asmop));
341     aop->type = type;
342     return aop;
343 }
344
345 static void genSetDPTR(int n)
346 {
347     if (!n)
348     {
349         emitcode(";", "Select standard DPTR");
350         emitcode("mov", "dps, #0x00");
351     }
352     else
353     {
354         emitcode(";", "Select alternate DPTR");
355         emitcode("mov", "dps, #0x01");
356     }
357 }
358
359 /*-----------------------------------------------------------------*/
360 /* pointerCode - returns the code for a pointer type               */
361 /*-----------------------------------------------------------------*/
362 static int pointerCode (sym_link *etype)
363 {
364
365     return PTR_TYPE(SPEC_OCLS(etype));
366
367 }
368
369 /*-----------------------------------------------------------------*/
370 /* aopForSym - for a true symbol                                   */
371 /*-----------------------------------------------------------------*/
372 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
373 {
374     asmop *aop;
375     memmap *space= SPEC_OCLS(sym->etype);
376
377     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
378     /* if already has one */
379     if (sym->aop)
380         return sym->aop;
381
382     /* assign depending on the storage class */
383     /* if it is on the stack or indirectly addressable */
384     /* space we need to assign either r0 or r1 to it   */    
385     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
386         sym->aop = aop = newAsmop(0);
387         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
388         aop->size = getSize(sym->type);
389
390         /* now assign the address of the variable to 
391         the pointer register */
392         if (aop->type != AOP_STK) {
393
394             if (sym->onStack) {
395                     if ( _G.accInUse )
396                         emitcode("push","acc");
397
398                     emitcode("mov","a,_bp");
399                     emitcode("add","a,#0x%02x",
400                              ((sym->stack < 0) ?
401                               ((char)(sym->stack - _G.nRegsSaved )) :
402                               ((char)sym->stack)) & 0xff);
403                     emitcode("mov","%s,a",
404                              aop->aopu.aop_ptr->name);
405
406                     if ( _G.accInUse )
407                         emitcode("pop","acc");
408             } else
409                 emitcode("mov","%s,#%s",
410                          aop->aopu.aop_ptr->name,
411                          sym->rname);
412             aop->paged = space->paged;
413         } else
414             aop->aopu.aop_stk = sym->stack;
415         return aop;
416     }
417     
418     if (sym->onStack && options.stack10bit)
419     {
420         /* It's on the 10 bit stack, which is located in
421          * far data space.
422          */
423          
424       //DEBUGemitcode(";","%d",__LINE__);
425
426         if ( _G.accInUse )
427                 emitcode("push","acc");
428
429         emitcode("mov","a,_bp");
430         emitcode("add","a,#0x%02x",
431                  ((sym->stack < 0) ?
432                    ((char)(sym->stack - _G.nRegsSaved )) :
433                    ((char)sym->stack)) & 0xff);
434         
435         genSetDPTR(1);
436         emitcode ("mov","dpx1,#0x40");
437         emitcode ("mov","dph1,#0x00");
438         emitcode ("mov","dpl1, a");
439         genSetDPTR(0);
440         
441         if ( _G.accInUse )
442             emitcode("pop","acc");
443             
444         sym->aop = aop = newAsmop(AOP_DPTR2);
445         aop->size = getSize(sym->type); 
446         return aop;
447     }
448
449     //DEBUGemitcode(";","%d",__LINE__);
450     /* if in bit space */
451     if (IN_BITSPACE(space)) {
452         sym->aop = aop = newAsmop (AOP_CRY);
453         aop->aopu.aop_dir = sym->rname ;
454         aop->size = getSize(sym->type);
455         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
456         return aop;
457     }
458     /* if it is in direct space */
459     if (IN_DIRSPACE(space)) {
460         sym->aop = aop = newAsmop (AOP_DIR);
461         aop->aopu.aop_dir = sym->rname ;
462         aop->size = getSize(sym->type);
463         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
464         return aop;
465     }
466
467     /* special case for a function */
468     if (IS_FUNC(sym->type)) {   
469         sym->aop = aop = newAsmop(AOP_IMMD);    
470         _ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
471         strcpy(aop->aopu.aop_immd,sym->rname);
472         aop->size = FPTRSIZE; 
473         return aop;
474     }
475
476
477     /* only remaining is far space */
478     /* in which case DPTR gets the address */
479     sym->aop = aop = newAsmop(AOP_DPTR);
480     emitcode ("mov","dptr,#%s", sym->rname);
481     aop->size = getSize(sym->type);
482
483     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
484     /* if it is in code space */
485     if (IN_CODESPACE(space))
486         aop->code = 1;
487
488     return aop;     
489 }
490
491 /*-----------------------------------------------------------------*/
492 /* aopForRemat - rematerialzes an object                           */
493 /*-----------------------------------------------------------------*/
494 static asmop *aopForRemat (symbol *sym)
495 {
496     iCode *ic = sym->rematiCode;
497     asmop *aop = newAsmop(AOP_IMMD);
498     int val = 0;
499     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
500     for (;;) {
501         if (ic->op == '+')
502             val += operandLitValue(IC_RIGHT(ic));
503         else if (ic->op == '-')
504             val -= operandLitValue(IC_RIGHT(ic));
505         else
506             break;
507         
508         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
509     }
510
511     if (val)
512         sprintf(buffer,"(%s %c 0x%04x)",
513                 OP_SYMBOL(IC_LEFT(ic))->rname, 
514                 val >= 0 ? '+' : '-',
515                 abs(val) & 0xffff);
516     else
517         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
518
519     //DEBUGemitcode(";","%s",buffer);
520     _ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
521     strcpy(aop->aopu.aop_immd,buffer);    
522     return aop;        
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* regsInCommon - two operands have some registers in common       */
527 /*-----------------------------------------------------------------*/
528 static bool regsInCommon (operand *op1, operand *op2)
529 {
530     symbol *sym1, *sym2;
531     int i;
532
533     /* if they have registers in common */
534     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
535         return FALSE ;
536
537     sym1 = OP_SYMBOL(op1);
538     sym2 = OP_SYMBOL(op2);
539
540     if (sym1->nRegs == 0 || sym2->nRegs == 0)
541         return FALSE ;
542
543     for (i = 0 ; i < sym1->nRegs ; i++) {
544         int j;
545         if (!sym1->regs[i])
546             continue ;
547
548         for (j = 0 ; j < sym2->nRegs ;j++ ) {
549             if (!sym2->regs[j])
550                 continue ;
551
552             if (sym2->regs[j] == sym1->regs[i])
553                 return TRUE ;
554         }
555     }
556
557     return FALSE ;
558 }
559
560 /*-----------------------------------------------------------------*/
561 /* operandsEqu - equivalent                                        */
562 /*-----------------------------------------------------------------*/
563 static bool operandsEqu ( operand *op1, operand *op2)
564 {
565     symbol *sym1, *sym2;
566
567     /* if they not symbols */
568     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
569         return FALSE;
570
571     sym1 = OP_SYMBOL(op1);
572     sym2 = OP_SYMBOL(op2);
573
574     /* if both are itemps & one is spilt
575        and the other is not then false */
576     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
577         sym1->isspilt != sym2->isspilt )
578         return FALSE ;
579
580     /* if they are the same */
581     if (sym1 == sym2)
582         return TRUE ;
583
584     if (strcmp(sym1->rname,sym2->rname) == 0)
585         return TRUE;
586
587
588     /* if left is a tmp & right is not */
589     if (IS_ITEMP(op1)  && 
590         !IS_ITEMP(op2) &&
591         sym1->isspilt  &&
592         (sym1->usl.spillLoc == sym2))
593         return TRUE;
594
595     if (IS_ITEMP(op2)  && 
596         !IS_ITEMP(op1) &&
597         sym2->isspilt  &&
598         sym1->level > 0 &&
599         (sym2->usl.spillLoc == sym1))
600         return TRUE ;
601
602     return FALSE ;
603 }
604
605 /*-----------------------------------------------------------------*/
606 /* sameRegs - two asmops have the same registers                   */
607 /*-----------------------------------------------------------------*/
608 static bool sameRegs (asmop *aop1, asmop *aop2 )
609 {
610     int i;
611
612     if (aop1 == aop2)
613         return TRUE ;
614
615     if (aop1->type != AOP_REG ||
616         aop2->type != AOP_REG )
617         return FALSE ;
618
619     if (aop1->size != aop2->size )
620         return FALSE ;
621
622     for (i = 0 ; i < aop1->size ; i++ )
623         if (aop1->aopu.aop_reg[i] !=
624             aop2->aopu.aop_reg[i] )
625             return FALSE ;
626
627     return TRUE ;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* aopOp - allocates an asmop for an operand  :                    */
632 /*-----------------------------------------------------------------*/
633 static void aopOp (operand *op, iCode *ic, bool result)
634 {
635     asmop *aop;
636     symbol *sym;
637     int i;
638
639     if (!op)
640         return ;
641
642     DEBUGemitcode(";","%d",__LINE__);
643     /* if this a literal */
644     if (IS_OP_LITERAL(op)) {
645       DEBUGemitcode(";","%d",__LINE__);
646         op->aop = aop = newAsmop(AOP_LIT);
647         aop->aopu.aop_lit = op->operand.valOperand;
648         aop->size = getSize(operandType(op));
649         return;
650     }
651
652     /* if already has a asmop then continue */
653     if (op->aop)
654         return ;
655
656     /* if the underlying symbol has a aop */
657     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
658       DEBUGemitcode(";","%d",__LINE__);
659         op->aop = OP_SYMBOL(op)->aop;
660         return;
661     }
662
663     /* if this is a true symbol */
664     if (IS_TRUE_SYMOP(op)) {    
665       DEBUGemitcode(";","%d",__LINE__);
666         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
667         return ;
668     }
669
670     /* this is a temporary : this has
671     only four choices :
672     a) register
673     b) spillocation
674     c) rematerialize 
675     d) conditional   
676     e) can be a return use only */
677
678     sym = OP_SYMBOL(op);
679
680
681     /* if the type is a conditional */
682     if (sym->regType == REG_CND) {
683       DEBUGemitcode(";","%d",__LINE__);
684         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
685         aop->size = 0;
686         return;
687     }
688
689     /* if it is spilt then two situations
690     a) is rematerialize 
691     b) has a spill location */
692     if (sym->isspilt || sym->nRegs == 0) {
693
694       DEBUGemitcode(";","%d",__LINE__);
695         /* rematerialize it NOW */
696         if (sym->remat) {
697             sym->aop = op->aop = aop =
698                                       aopForRemat (sym);
699             aop->size = getSize(sym->type);
700             DEBUGemitcode(";","%d",__LINE__);
701             return;
702         }
703
704         if (sym->accuse) {
705             int i;
706             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
707             aop->size = getSize(sym->type);
708             for ( i = 0 ; i < 2 ; i++ )
709                 aop->aopu.aop_str[i] = accUse[i];
710             DEBUGemitcode(";","%d",__LINE__);
711             return;  
712         }
713
714         if (sym->ruonly ) {
715             int i;
716             aop = op->aop = sym->aop = newAsmop(AOP_STR);
717             aop->size = getSize(sym->type);
718             for ( i = 0 ; i < fReturnSize ; i++ )
719               aop->aopu.aop_str[i] = fReturn[i];
720             DEBUGemitcode(";","%d",__LINE__);
721             return;
722         }
723
724         /* else spill location  */
725         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
726         sym->aop = op->aop = aop = 
727                                   aopForSym(ic,sym->usl.spillLoc,result);
728         aop->size = getSize(sym->type);
729         return;
730     }
731
732     /* must be in a register */
733     sym->aop = op->aop = aop = newAsmop(AOP_REG);
734     aop->size = sym->nRegs;
735     for ( i = 0 ; i < sym->nRegs ;i++)
736         aop->aopu.aop_reg[i] = sym->regs[i];
737 }
738
739 /*-----------------------------------------------------------------*/
740 /* freeAsmop - free up the asmop given to an operand               */
741 /*----------------------------------------------------------------*/
742 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
743 {   
744     asmop *aop ;
745
746     if (!op)
747         aop = aaop;
748     else 
749         aop = op->aop;
750
751     if (!aop)
752         return ;
753
754     if (aop->freed)
755         goto dealloc; 
756
757     aop->freed = 1;
758
759     /* depending on the asmop type only three cases need work AOP_RO
760        , AOP_R1 && AOP_STK */
761     switch (aop->type) {
762         case AOP_R0 :
763             if (_G.r0Pushed ) {
764                 if (pop) {
765                     emitcode ("pop","ar0");     
766                     _G.r0Pushed--;
767                 }
768             }
769             bitVectUnSetBit(ic->rUsed,R0_IDX);
770             break;
771
772         case AOP_R1 :
773             if (_G.r1Pushed ) {
774                 if (pop) {
775                     emitcode ("pop","ar1");
776                     _G.r1Pushed--;
777                 }
778             }
779             bitVectUnSetBit(ic->rUsed,R1_IDX);          
780             break;
781
782         case AOP_STK :
783         {
784             int sz = aop->size;    
785             int stk = aop->aopu.aop_stk + aop->size;
786             bitVectUnSetBit(ic->rUsed,R0_IDX);
787             bitVectUnSetBit(ic->rUsed,R1_IDX);          
788
789             getFreePtr(ic,&aop,FALSE);
790             
791             if (options.stack10bit)
792             {
793                 /* I'm not sure what to do here yet... */
794                 /* #STUB */
795                 fprintf(stderr, 
796                         "*** Warning: probably generating bad code for "
797                         "10 bit stack mode.\n");
798             }
799             
800             if (stk) {
801                 emitcode ("mov","a,_bp");
802                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
803                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
804             } else {
805                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
806             }
807
808             while (sz--) {
809                 emitcode("pop","acc");
810                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
811                 if (!sz) break;
812                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
813             }
814             op->aop = aop;
815             freeAsmop(op,NULL,ic,TRUE);
816             if (_G.r0Pushed) {
817                 emitcode("pop","ar0");
818                 _G.r0Pushed--;
819             }
820
821             if (_G.r1Pushed) {
822                 emitcode("pop","ar1");
823                 _G.r1Pushed--;
824             }       
825         }
826     }
827
828 dealloc:
829     /* all other cases just dealloc */
830     if (op ) {
831         op->aop = NULL;
832         if (IS_SYMOP(op)) {
833             OP_SYMBOL(op)->aop = NULL;    
834             /* if the symbol has a spill */
835             if (SPIL_LOC(op))
836                 SPIL_LOC(op)->aop = NULL;
837         }
838     }
839 }
840
841 /*-----------------------------------------------------------------*/
842 /* aopGet - for fetching value of the aop                          */
843 /*-----------------------------------------------------------------*/
844 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
845 {
846     char *s = buffer ;
847     char *rs;
848
849     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
850     /* offset is greater than
851     size then zero */
852     if (offset > (aop->size - 1) &&
853         aop->type != AOP_LIT)
854         return zero;
855
856     /* depending on type */
857     switch (aop->type) {
858         
859     case AOP_R0:
860     case AOP_R1:
861         DEBUGemitcode(";","%d",__LINE__);
862         /* if we need to increment it */       
863         while (offset > aop->coff) {        
864             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
865             aop->coff++;
866         }
867         
868         while (offset < aop->coff) {
869             emitcode("dec","%s",aop->aopu.aop_ptr->name);
870             aop->coff--;
871         }
872         
873         aop->coff = offset ;
874         if (aop->paged) {
875             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
876             return (dname ? "acc" : "a");
877         }       
878         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
879         _ALLOC_ATOMIC(rs,strlen(s)+1);
880         strcpy(rs,s);   
881         return rs;
882         
883     case AOP_DPTR:
884     case AOP_DPTR2:
885         DEBUGemitcode(";","%d",__LINE__);
886     if (aop->type == AOP_DPTR2)
887     {
888         genSetDPTR(1);
889     }
890     
891         while (offset > aop->coff) {
892             emitcode ("inc","dptr");
893             aop->coff++;
894         }
895         
896         while (offset < aop->coff) {        
897             emitcode("lcall","__decdptr");
898             aop->coff--;
899         }
900         
901         aop->coff = offset;
902         if (aop->code) {
903             emitcode("clr","a");
904             emitcode("movc","a,@a+dptr");
905         }
906     else {
907             emitcode("movx","a,@dptr");
908     }
909             
910     if (aop->type == AOP_DPTR2)
911     {
912         genSetDPTR(0);
913     }
914             
915     return (dname ? "acc" : "a");
916         
917         
918     case AOP_IMMD:
919       DEBUGemitcode(";","%d",__LINE__);
920         if (bit16) 
921             sprintf (s,"%s",aop->aopu.aop_immd);
922         else
923             if (offset) 
924                 sprintf(s,"(%s >> %d)",
925                         aop->aopu.aop_immd,
926                         offset*8);
927             else
928                 sprintf(s,"%s",
929                         aop->aopu.aop_immd);
930         _ALLOC_ATOMIC(rs,strlen(s)+1);
931         strcpy(rs,s);   
932         return rs;
933         
934     case AOP_DIR:
935         if (offset)
936             sprintf(s,"(%s + %d)",
937                     aop->aopu.aop_dir,
938                     offset);
939         else
940             sprintf(s,"%s",aop->aopu.aop_dir);
941         _ALLOC_ATOMIC(rs,strlen(s)+1);
942         strcpy(rs,s);   
943         return rs;
944         
945     case AOP_REG:
946       DEBUGemitcode(";","%d",__LINE__);
947         if (dname) 
948             return aop->aopu.aop_reg[offset]->dname;
949         else
950             return aop->aopu.aop_reg[offset]->name;
951         
952     case AOP_CRY:
953       emitcode(";","%d",__LINE__);
954       //emitcode("clr","a");
955       //emitcode("mov","c,%s",aop->aopu.aop_dir);
956       //emitcode("rlc","a") ;
957       //return (dname ? "acc" : "a");
958       return aop->aopu.aop_dir;
959         
960     case AOP_ACC:
961         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
962         //if (!offset && dname)
963         //    return "acc";
964         //return aop->aopu.aop_str[offset];
965         return "AOP_accumulator_bug";
966
967     case AOP_LIT:
968         DEBUGemitcode(";","%d",__LINE__);
969         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
970         _ALLOC_ATOMIC(rs,strlen(s)+1);
971         strcpy(rs,s);   
972         return rs;
973         
974     case AOP_STR:
975         DEBUGemitcode(";","%d",__LINE__);
976         aop->coff = offset ;
977         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
978             dname)
979             return "acc";
980         
981         return aop->aopu.aop_str[offset];
982         
983     }
984
985     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
986            "aopget got unsupported aop->type");
987     exit(0);
988 }
989
990 /*-----------------------------------------------------------------*/
991 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
992 /*-----------------------------------------------------------------*/
993 static pCodeOp *popGetLabel(unsigned int key)
994 {
995   return newpCodeOpLabel(key+100+labelOffset);
996 }
997
998 /*-----------------------------------------------------------------*/
999 /* popCopy - copy a pcode operator                                 */
1000 /*-----------------------------------------------------------------*/
1001 static pCodeOp *popCopy(pCodeOp *pc)
1002 {
1003   pCodeOp *pcop;
1004
1005   _ALLOC(pcop,sizeof(pCodeOp) );
1006   pcop->type = pc->type;
1007   if(!(pcop->name = strdup(pc->name)))
1008     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1009
1010   return pcop;
1011 }
1012
1013 /*-----------------------------------------------------------------*/
1014 /* popCopy - copy a pcode operator                                 */
1015 /*-----------------------------------------------------------------*/
1016 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1017 {
1018   pCodeOp *pcop;
1019
1020   _ALLOC(pcop,sizeof(pCodeOpBit) );
1021   pcop->type = PO_BIT;
1022   if(!(pcop->name = strdup(pc->name)))
1023     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1024   ((pCodeOpBit *)pcop)->bit = bitval;
1025
1026   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1027
1028   return pcop;
1029 }
1030
1031 /*-----------------------------------------------------------------*/
1032 /* popGet - asm operator to pcode operator conversion              */
1033 /*-----------------------------------------------------------------*/
1034 static pCodeOp *popGetLit(unsigned int lit)
1035 {
1036
1037   return newpCodeOpLit(lit);
1038 }
1039
1040
1041 /*-----------------------------------------------------------------*/
1042 /* popGet - asm operator to pcode operator conversion              */
1043 /*-----------------------------------------------------------------*/
1044 static pCodeOp *popGetWithString(char *str)
1045 {
1046   pCodeOp *pcop;
1047
1048
1049   if(!str) {
1050     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1051     exit (1);
1052   }
1053
1054   pcop = newpCodeOp(str);
1055   pcop->type = PO_STR;
1056
1057 /*
1058   _ALLOC(pcop,sizeof(pCodeOp) );
1059     _ALLOC_ATOMIC(pcop->name,strlen(str)+1);
1060     strcpy(pcop->name,str);   
1061   } else {
1062   }
1063 */
1064   return pcop;
1065 }
1066 /*-----------------------------------------------------------------*/
1067 /* popGet - asm operator to pcode operator conversion              */
1068 /*-----------------------------------------------------------------*/
1069 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1070 {
1071     char *s = buffer ;
1072     char *rs;
1073
1074     pCodeOp *pcop;
1075
1076     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1077     /* offset is greater than
1078     size then zero */
1079
1080     if (offset > (aop->size - 1) &&
1081         aop->type != AOP_LIT)
1082       return NULL;  //zero;
1083
1084     /* depending on type */
1085     switch (aop->type) {
1086         
1087     case AOP_R0:
1088     case AOP_R1:
1089     case AOP_DPTR:
1090     case AOP_DPTR2:
1091     case AOP_ACC:
1092         DEBUGemitcode(";8051 legacy","%d",__LINE__);
1093         return NULL;
1094         
1095     case AOP_IMMD:
1096       DEBUGemitcode(";","%d",__LINE__);
1097         _ALLOC(pcop,sizeof(pCodeOp) );
1098         pcop->type = PO_IMMEDIATE;
1099         if (bit16) 
1100             sprintf (s,"%s",aop->aopu.aop_immd);
1101         else
1102             if (offset) 
1103                 sprintf(s,"(%s >> %d)",
1104                         aop->aopu.aop_immd,
1105                         offset*8);
1106             else
1107                 sprintf(s,"%s",
1108                         aop->aopu.aop_immd);
1109         _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1110         strcpy(pcop->name,s);   
1111         return pcop;
1112         
1113     case AOP_DIR:
1114         _ALLOC(pcop,sizeof(pCodeOp) );
1115         pcop->type = PO_DIR;
1116         if (offset)
1117             sprintf(s,"(%s + %d)",
1118                     aop->aopu.aop_dir,
1119                     offset);
1120         else
1121             sprintf(s,"%s",aop->aopu.aop_dir);
1122         _ALLOC(pcop->name,strlen(s)+1);
1123         strcpy(pcop->name,s);   
1124         return pcop;
1125         
1126     case AOP_REG:
1127       DEBUGemitcode(";","%d",__LINE__);
1128       _ALLOC(pcop,sizeof(pCodeOp) );
1129       pcop->type = PO_GPR_REGISTER;
1130       if (dname)
1131         rs = aop->aopu.aop_reg[offset]->dname;
1132       else 
1133         rs = aop->aopu.aop_reg[offset]->name;
1134
1135       DEBUGemitcode(";","%d  %s",__LINE__,rs);
1136       _ALLOC_ATOMIC((pcop->name),(strlen(rs)+1));
1137       strcpy(pcop->name,rs);   
1138       return pcop;
1139
1140     case AOP_CRY:
1141       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1142       return pcop;
1143         
1144     case AOP_LIT:
1145       DEBUGemitcode(";","%d",__LINE__);
1146       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1147
1148     case AOP_STR:
1149       DEBUGemitcode(";","%d",__LINE__);
1150
1151       _ALLOC(pcop,sizeof(pCodeOp) );
1152       pcop->type = PO_STR;
1153
1154       //aop->coff = offset ;
1155         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1156           sprintf(s,"%s","acc");
1157         else
1158           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1159         _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1160         strcpy(pcop->name,s);   
1161         return pcop;
1162         
1163     }
1164
1165     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1166            "popGet got unsupported aop->type");
1167     exit(0);
1168 }
1169 /*-----------------------------------------------------------------*/
1170 /* aopPut - puts a string for a aop                                */
1171 /*-----------------------------------------------------------------*/
1172 static void aopPut (asmop *aop, char *s, int offset)
1173 {
1174     char *d = buffer ;
1175     symbol *lbl ;
1176
1177     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1178
1179     if (aop->size && offset > ( aop->size - 1)) {
1180         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1181                "aopPut got offset > aop->size");
1182         exit(0);
1183     }
1184
1185     /* will assign value to value */
1186     /* depending on where it is ofcourse */
1187     switch (aop->type) {
1188     case AOP_DIR:
1189         if (offset)
1190             sprintf(d,"(%s + %d)",
1191                     aop->aopu.aop_dir,offset);
1192         else
1193             sprintf(d,"%s",aop->aopu.aop_dir);
1194         
1195         if (strcmp(d,s)) {
1196           DEBUGemitcode(";","%d",__LINE__);
1197           if(strcmp(s,"W"))
1198             emitcode("movf","%s,w",s);
1199           emitcode("movwf","%s",d);
1200
1201           if(strcmp(s,"W"))
1202             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1203           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1204
1205
1206         }
1207         break;
1208         
1209     case AOP_REG:
1210         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1211             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1212           /*
1213             if (*s == '@'           ||
1214                 strcmp(s,"r0") == 0 ||
1215                 strcmp(s,"r1") == 0 ||
1216                 strcmp(s,"r2") == 0 ||
1217                 strcmp(s,"r3") == 0 ||
1218                 strcmp(s,"r4") == 0 ||
1219                 strcmp(s,"r5") == 0 ||
1220                 strcmp(s,"r6") == 0 || 
1221                 strcmp(s,"r7") == 0 )
1222                 emitcode("mov","%s,%s  ; %d",
1223                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1224             else
1225           */
1226
1227           if(strcmp(s,"W"))
1228             emitcode("movf","%s,w  ; %d",s,__LINE__);
1229
1230           emitcode("movwf","%s",
1231                    aop->aopu.aop_reg[offset]->name);
1232
1233           if(strcmp(s,"W"))
1234             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1235           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1236
1237         }
1238         break;
1239         
1240     case AOP_DPTR:
1241     case AOP_DPTR2:
1242     
1243     if (aop->type == AOP_DPTR2)
1244     {
1245         genSetDPTR(1);
1246     }
1247     
1248         if (aop->code) {
1249             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1250                    "aopPut writting to code space");
1251             exit(0);
1252         }
1253         
1254         while (offset > aop->coff) {
1255             aop->coff++;
1256             emitcode ("inc","dptr");
1257         }
1258         
1259         while (offset < aop->coff) {
1260             aop->coff-- ;
1261             emitcode("lcall","__decdptr");
1262         }
1263         
1264         aop->coff = offset;
1265         
1266         /* if not in accumulater */
1267         MOVA(s);        
1268         
1269         emitcode ("movx","@dptr,a");
1270         
1271     if (aop->type == AOP_DPTR2)
1272     {
1273         genSetDPTR(0);
1274     }
1275         break;
1276         
1277     case AOP_R0:
1278     case AOP_R1:
1279         while (offset > aop->coff) {
1280             aop->coff++;
1281             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1282         }
1283         while (offset < aop->coff) {
1284             aop->coff-- ;
1285             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1286         }
1287         aop->coff = offset;
1288         
1289         if (aop->paged) {
1290             MOVA(s);           
1291             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1292             
1293         } else
1294             if (*s == '@') {
1295                 MOVA(s);
1296                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1297             } else
1298                 if (strcmp(s,"r0") == 0 ||
1299                     strcmp(s,"r1") == 0 ||
1300                     strcmp(s,"r2") == 0 ||
1301                     strcmp(s,"r3") == 0 ||
1302                     strcmp(s,"r4") == 0 ||
1303                     strcmp(s,"r5") == 0 ||
1304                     strcmp(s,"r6") == 0 || 
1305                     strcmp(s,"r7") == 0 ) {
1306                     char buffer[10];
1307                     sprintf(buffer,"a%s",s);
1308                     emitcode("mov","@%s,%s",
1309                              aop->aopu.aop_ptr->name,buffer);
1310                 } else
1311                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1312         
1313         break;
1314         
1315     case AOP_STK:
1316         if (strcmp(s,"a") == 0)
1317             emitcode("push","acc");
1318         else
1319             emitcode("push","%s",s);
1320         
1321         break;
1322         
1323     case AOP_CRY:
1324         /* if bit variable */
1325         if (!aop->aopu.aop_dir) {
1326             emitcode("clr","a");
1327             emitcode("rlc","a");
1328         } else {
1329             if (s == zero) 
1330                 emitcode("clr","%s",aop->aopu.aop_dir);
1331             else
1332                 if (s == one)
1333                     emitcode("setb","%s",aop->aopu.aop_dir);
1334                 else
1335                     if (!strcmp(s,"c"))
1336                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1337                     else {
1338                         lbl = newiTempLabel(NULL);
1339                         
1340                         if (strcmp(s,"a")) {
1341                             MOVA(s);
1342                         }
1343                         emitcode("clr","c");
1344                         emitcode("jz","%05d_DS_",lbl->key+100);
1345                         emitcode("cpl","c");
1346                         emitcode("","%05d_DS_:",lbl->key+100);
1347                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1348                     }
1349         }
1350         break;
1351         
1352     case AOP_STR:
1353         aop->coff = offset;
1354         if (strcmp(aop->aopu.aop_str[offset],s))
1355             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1356         break;
1357         
1358     case AOP_ACC:
1359         aop->coff = offset;
1360         if (!offset && (strcmp(s,"acc") == 0))
1361             break;
1362         
1363         if (strcmp(aop->aopu.aop_str[offset],s))
1364             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1365         break;
1366
1367     default :
1368         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1369                "aopPut got unsupported aop->type");
1370         exit(0);    
1371     }    
1372
1373 }
1374
1375 /*-----------------------------------------------------------------*/
1376 /* reAdjustPreg - points a register back to where it should        */
1377 /*-----------------------------------------------------------------*/
1378 static void reAdjustPreg (asmop *aop)
1379 {
1380     int size ;
1381
1382     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1383     aop->coff = 0;
1384     if ((size = aop->size) <= 1)
1385         return ;
1386     size-- ;
1387     switch (aop->type) {
1388         case AOP_R0 :
1389         case AOP_R1 :
1390             while (size--)
1391                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1392             break;          
1393         case AOP_DPTR :
1394         case AOP_DPTR2:
1395             if (aop->type == AOP_DPTR2)
1396             {
1397                 genSetDPTR(1);
1398             } 
1399             while (size--)
1400             {
1401                 emitcode("lcall","__decdptr");
1402             }
1403                 
1404             if (aop->type == AOP_DPTR2)
1405             {
1406                 genSetDPTR(0);
1407             }                
1408             break;  
1409
1410     }   
1411
1412 }
1413
1414 #define AOP(op) op->aop
1415 #define AOP_TYPE(op) AOP(op)->type
1416 #define AOP_SIZE(op) AOP(op)->size
1417 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1418                        AOP_TYPE(x) == AOP_R0))
1419
1420 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1421                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1422                          AOP(x)->paged)) 
1423
1424 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1425                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1426                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1427
1428 /*-----------------------------------------------------------------*/
1429 /* genNotFloat - generates not for float operations              */
1430 /*-----------------------------------------------------------------*/
1431 static void genNotFloat (operand *op, operand *res)
1432 {
1433     int size, offset;
1434     char *l;
1435     symbol *tlbl ;
1436
1437     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1438     /* we will put 127 in the first byte of 
1439     the result */
1440     aopPut(AOP(res),"#127",0);
1441     size = AOP_SIZE(op) - 1;
1442     offset = 1;
1443
1444     l = aopGet(op->aop,offset++,FALSE,FALSE);
1445     MOVA(l);    
1446
1447     while(size--) {
1448         emitcode("orl","a,%s",
1449                  aopGet(op->aop,
1450                         offset++,FALSE,FALSE));
1451     }
1452     tlbl = newiTempLabel(NULL);
1453
1454     tlbl = newiTempLabel(NULL);
1455     aopPut(res->aop,one,1);
1456     emitcode("jz","%05d_DS_",(tlbl->key+100));
1457     aopPut(res->aop,zero,1);
1458     emitcode("","%05d_DS_:",(tlbl->key+100));
1459
1460     size = res->aop->size - 2;
1461     offset = 2;    
1462     /* put zeros in the rest */
1463     while (size--) 
1464         aopPut(res->aop,zero,offset++);
1465 }
1466
1467 #if 0
1468 /*-----------------------------------------------------------------*/
1469 /* opIsGptr: returns non-zero if the passed operand is             */   
1470 /* a generic pointer type.                                         */
1471 /*-----------------------------------------------------------------*/ 
1472 static int opIsGptr(operand *op)
1473 {
1474     sym_link *type = operandType(op);
1475     
1476     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1477     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1478     {
1479         return 1;
1480     }
1481     return 0;        
1482 }
1483 #endif
1484
1485 /*-----------------------------------------------------------------*/
1486 /* getDataSize - get the operand data size                         */
1487 /*-----------------------------------------------------------------*/
1488 static int getDataSize(operand *op)
1489 {
1490     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1491
1492
1493     return AOP_SIZE(op);
1494
1495     // tsd- in the pic port, the genptr size is 1, so this code here
1496     // fails. ( in the 8051 port, the size was 4).
1497 #if 0
1498     int size;
1499     size = AOP_SIZE(op);
1500     if (size == GPTRSIZE)
1501     {
1502         sym_link *type = operandType(op);
1503         if (IS_GENPTR(type))
1504         {
1505             /* generic pointer; arithmetic operations
1506              * should ignore the high byte (pointer type).
1507              */
1508             size--;
1509     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1510         }
1511     }
1512     return size;
1513 #endif
1514 }
1515
1516 /*-----------------------------------------------------------------*/
1517 /* outAcc - output Acc                                             */
1518 /*-----------------------------------------------------------------*/
1519 static void outAcc(operand *result)
1520 {
1521     int size, offset;
1522     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1523     size = getDataSize(result);
1524     if(size){
1525         aopPut(AOP(result),"a",0);
1526         size--;
1527         offset = 1;
1528         /* unsigned or positive */
1529         while(size--){
1530             aopPut(AOP(result),zero,offset++);
1531         }
1532     }
1533 }
1534
1535 /*-----------------------------------------------------------------*/
1536 /* outBitC - output a bit C                                        */
1537 /*-----------------------------------------------------------------*/
1538 static void outBitC(operand *result)
1539 {
1540
1541     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1542     /* if the result is bit */
1543     if (AOP_TYPE(result) == AOP_CRY) 
1544         aopPut(AOP(result),"c",0);
1545     else {
1546         emitcode("clr","a  ; %d", __LINE__);
1547         emitcode("rlc","a");
1548         outAcc(result);
1549     }
1550 }
1551
1552 /*-----------------------------------------------------------------*/
1553 /* toBoolean - emit code for orl a,operator(sizeop)                */
1554 /*-----------------------------------------------------------------*/
1555 static void toBoolean(operand *oper)
1556 {
1557     int size = AOP_SIZE(oper) - 1;
1558     int offset = 1;
1559
1560     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1561
1562     if ( AOP_TYPE(oper) != AOP_ACC) {
1563       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1564       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1565     }
1566     while (size--) {
1567       emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1568       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1569     }
1570 }
1571
1572
1573 /*-----------------------------------------------------------------*/
1574 /* genNot - generate code for ! operation                          */
1575 /*-----------------------------------------------------------------*/
1576 static void genNot (iCode *ic)
1577 {
1578     symbol *tlbl;
1579     sym_link *optype = operandType(IC_LEFT(ic));
1580
1581     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1582     /* assign asmOps to operand & result */
1583     aopOp (IC_LEFT(ic),ic,FALSE);
1584     aopOp (IC_RESULT(ic),ic,TRUE);
1585
1586     /* if in bit space then a special case */
1587     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1588       emitcode("movlw","1<<%s");
1589       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1590       //emitcode("cpl","c"); 
1591       //outBitC(IC_RESULT(ic));
1592       goto release;
1593     }
1594
1595     /* if type float then do float */
1596     if (IS_FLOAT(optype)) {
1597         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1598         goto release;
1599     }
1600
1601     toBoolean(IC_LEFT(ic));
1602
1603     tlbl = newiTempLabel(NULL);
1604     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1605     emitcode("","%05d_DS_:",tlbl->key+100);
1606     outBitC(IC_RESULT(ic));
1607
1608 release:    
1609     /* release the aops */
1610     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1611     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1612 }
1613
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement                           */
1617 /*-----------------------------------------------------------------*/
1618 static void genCpl (iCode *ic)
1619 {
1620     int offset = 0;
1621     int size ;
1622
1623
1624     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1625     /* assign asmOps to operand & result */
1626     aopOp (IC_LEFT(ic),ic,FALSE);
1627     aopOp (IC_RESULT(ic),ic,TRUE);
1628
1629     /* if both are in bit space then 
1630     a special case */
1631     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1632         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1633
1634         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1635         emitcode("cpl","c"); 
1636         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1637         goto release; 
1638     } 
1639
1640     size = AOP_SIZE(IC_RESULT(ic));
1641     while (size--) {
1642         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1643         MOVA(l);       
1644         emitcode("cpl","a");
1645         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1646     }
1647
1648
1649 release:
1650     /* release the aops */
1651     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1652     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* genUminusFloat - unary minus for floating points                */
1657 /*-----------------------------------------------------------------*/
1658 static void genUminusFloat(operand *op,operand *result)
1659 {
1660     int size ,offset =0 ;
1661     char *l;
1662
1663     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1664     /* for this we just need to flip the 
1665     first it then copy the rest in place */
1666     size = AOP_SIZE(op) - 1;
1667     l = aopGet(AOP(op),3,FALSE,FALSE);
1668
1669     MOVA(l);    
1670
1671     emitcode("cpl","acc.7");
1672     aopPut(AOP(result),"a",3);    
1673
1674     while(size--) {
1675         aopPut(AOP(result),
1676                aopGet(AOP(op),offset,FALSE,FALSE),
1677                offset);
1678         offset++;
1679     }          
1680 }
1681
1682 /*-----------------------------------------------------------------*/
1683 /* genUminus - unary minus code generation                         */
1684 /*-----------------------------------------------------------------*/
1685 static void genUminus (iCode *ic)
1686 {
1687     int offset ,size ;
1688     sym_link *optype, *rtype;
1689
1690
1691     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1692     /* assign asmops */
1693     aopOp(IC_LEFT(ic),ic,FALSE);
1694     aopOp(IC_RESULT(ic),ic,TRUE);
1695
1696     /* if both in bit space then special
1697     case */
1698     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1699         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1700
1701         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1702         emitcode("cpl","c"); 
1703         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1704         goto release; 
1705     } 
1706
1707     optype = operandType(IC_LEFT(ic));
1708     rtype = operandType(IC_RESULT(ic));
1709
1710     /* if float then do float stuff */
1711     if (IS_FLOAT(optype)) {
1712         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1713         goto release;
1714     }
1715
1716     /* otherwise subtract from zero */
1717     size = AOP_SIZE(IC_LEFT(ic));
1718     offset = 0 ;
1719     CLRC ;
1720     while(size--) {
1721         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1722         if (!strcmp(l,"a")) {
1723             emitcode("cpl","a");
1724             emitcode("inc","a");
1725         } else {
1726             emitcode("clr","a");
1727             emitcode("subb","a,%s",l);
1728         }       
1729         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1730     }
1731
1732     /* if any remaining bytes in the result */
1733     /* we just need to propagate the sign   */
1734     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1735         emitcode("rlc","a");
1736         emitcode("subb","a,acc");
1737         while (size--) 
1738             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1739     }       
1740
1741 release:
1742     /* release the aops */
1743     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1744     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* saveRegisters - will look for a call and save the registers     */
1749 /*-----------------------------------------------------------------*/
1750 static void saveRegisters(iCode *lic) 
1751 {
1752     int i;
1753     iCode *ic;
1754     bitVect *rsave;
1755     sym_link *detype;
1756
1757     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1758     /* look for call */
1759     for (ic = lic ; ic ; ic = ic->next) 
1760         if (ic->op == CALL || ic->op == PCALL)
1761             break;
1762
1763     if (!ic) {
1764         fprintf(stderr,"found parameter push with no function call\n");
1765         return ;
1766     }
1767
1768     /* if the registers have been saved already then
1769     do nothing */
1770     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1771         return ;
1772
1773     /* find the registers in use at this time 
1774     and push them away to safety */
1775     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1776                           ic->rUsed);
1777
1778     ic->regsSaved = 1;
1779     if (options.useXstack) {
1780         if (bitVectBitValue(rsave,R0_IDX))
1781             emitcode("mov","b,r0");
1782         emitcode("mov","r0,%s",spname);
1783         for (i = 0 ; i < pic14_nRegs ; i++) {
1784             if (bitVectBitValue(rsave,i)) {
1785                 if (i == R0_IDX)
1786                     emitcode("mov","a,b");
1787                 else
1788                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1789                 emitcode("movx","@r0,a");
1790                 emitcode("inc","r0");
1791             }
1792         }
1793         emitcode("mov","%s,r0",spname);
1794         if (bitVectBitValue(rsave,R0_IDX))
1795             emitcode("mov","r0,b");         
1796     } else
1797         for (i = 0 ; i < pic14_nRegs ; i++) {
1798             if (bitVectBitValue(rsave,i))
1799                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1800         }
1801
1802     detype = getSpec(operandType(IC_LEFT(ic)));
1803     if (detype        && 
1804         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1805         IS_ISR(currFunc->etype) &&
1806         !ic->bankSaved) 
1807
1808         saverbank(SPEC_BANK(detype),ic,TRUE);
1809
1810 }
1811 /*-----------------------------------------------------------------*/
1812 /* unsaveRegisters - pop the pushed registers                      */
1813 /*-----------------------------------------------------------------*/
1814 static void unsaveRegisters (iCode *ic)
1815 {
1816     int i;
1817     bitVect *rsave;
1818
1819     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1820     /* find the registers in use at this time 
1821     and push them away to safety */
1822     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1823                           ic->rUsed);
1824     
1825     if (options.useXstack) {
1826         emitcode("mov","r0,%s",spname); 
1827         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1828             if (bitVectBitValue(rsave,i)) {
1829                 emitcode("dec","r0");
1830                 emitcode("movx","a,@r0");
1831                 if (i == R0_IDX)
1832                     emitcode("mov","b,a");
1833                 else
1834                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1835             }       
1836
1837         }
1838         emitcode("mov","%s,r0",spname);
1839         if (bitVectBitValue(rsave,R0_IDX))
1840             emitcode("mov","r0,b");
1841     } else
1842         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1843             if (bitVectBitValue(rsave,i))
1844                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1845         }
1846
1847 }  
1848
1849
1850 /*-----------------------------------------------------------------*/
1851 /* pushSide -                                                      */
1852 /*-----------------------------------------------------------------*/
1853 static void pushSide(operand * oper, int size)
1854 {
1855         int offset = 0;
1856     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1857         while (size--) {
1858                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1859                 if (AOP_TYPE(oper) != AOP_REG &&
1860                     AOP_TYPE(oper) != AOP_DIR &&
1861                     strcmp(l,"a") ) {
1862                         emitcode("mov","a,%s",l);
1863                         emitcode("push","acc");
1864                 } else
1865                         emitcode("push","%s",l);
1866         }
1867 }
1868
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue -                                             */
1871 /*-----------------------------------------------------------------*/
1872 static void assignResultValue(operand * oper)
1873 {
1874         int offset = 0;
1875         int size = AOP_SIZE(oper);
1876
1877     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1878
1879     // The last byte in the assignment is in W
1880     aopPut(AOP(oper),"W",size-1);
1881
1882     if(size>1) {
1883       while (--size) {
1884         aopPut(AOP(oper),fReturn[offset],offset);
1885         offset++;
1886
1887       }
1888     }
1889 }
1890
1891
1892 /*-----------------------------------------------------------------*/
1893 /* genXpush - pushes onto the external stack                       */
1894 /*-----------------------------------------------------------------*/
1895 static void genXpush (iCode *ic)
1896 {
1897     asmop *aop = newAsmop(0);
1898     regs *r ;
1899     int size,offset = 0;
1900
1901     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1902     aopOp(IC_LEFT(ic),ic,FALSE);
1903     r = getFreePtr(ic,&aop,FALSE);
1904
1905     
1906     emitcode("mov","%s,_spx",r->name);
1907
1908     size = AOP_SIZE(IC_LEFT(ic));
1909     while(size--) {
1910
1911         char *l = aopGet(AOP(IC_LEFT(ic)),
1912                          offset++,FALSE,FALSE); 
1913         MOVA(l);            
1914         emitcode("movx","@%s,a",r->name);       
1915         emitcode("inc","%s",r->name);
1916
1917     }
1918
1919         
1920     emitcode("mov","_spx,%s",r->name);
1921
1922     freeAsmop(NULL,aop,ic,TRUE);
1923     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1924 }
1925
1926 /*-----------------------------------------------------------------*/
1927 /* genIpush - genrate code for pushing this gets a little complex  */
1928 /*-----------------------------------------------------------------*/
1929 static void genIpush (iCode *ic)
1930 {
1931     int size, offset = 0 ;
1932     char *l;
1933
1934
1935     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1936     /* if this is not a parm push : ie. it is spill push 
1937     and spill push is always done on the local stack */
1938     if (!ic->parmPush) {
1939
1940         /* and the item is spilt then do nothing */
1941         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1942             return ;
1943
1944         aopOp(IC_LEFT(ic),ic,FALSE);
1945         size = AOP_SIZE(IC_LEFT(ic));
1946         /* push it on the stack */
1947         while(size--) {
1948             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1949             if (*l == '#') {
1950                 MOVA(l);
1951                 l = "acc";
1952             }
1953             emitcode("push","%s",l);
1954         }
1955         return ;        
1956     }
1957
1958     /* this is a paramter push: in this case we call
1959     the routine to find the call and save those
1960     registers that need to be saved */   
1961     saveRegisters(ic);
1962
1963     /* if use external stack then call the external
1964     stack pushing routine */
1965     if (options.useXstack) {
1966         genXpush(ic);
1967         return ;
1968     }
1969
1970     /* then do the push */
1971     aopOp(IC_LEFT(ic),ic,FALSE);
1972
1973
1974         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1975     size = AOP_SIZE(IC_LEFT(ic));
1976
1977     while (size--) {
1978         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1979         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1980             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1981             strcmp(l,"a") ) {
1982             emitcode("mov","a,%s",l);
1983             emitcode("push","acc");
1984         } else
1985             emitcode("push","%s",l);
1986     }       
1987
1988     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* genIpop - recover the registers: can happen only for spilling   */
1993 /*-----------------------------------------------------------------*/
1994 static void genIpop (iCode *ic)
1995 {
1996     int size,offset ;
1997
1998
1999     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2000     /* if the temp was not pushed then */
2001     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2002         return ;
2003
2004     aopOp(IC_LEFT(ic),ic,FALSE);
2005     size = AOP_SIZE(IC_LEFT(ic));
2006     offset = (size-1);
2007     while (size--) 
2008         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2009                                    FALSE,TRUE));
2010
2011     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2012 }
2013
2014 /*-----------------------------------------------------------------*/
2015 /* unsaverbank - restores the resgister bank from stack            */
2016 /*-----------------------------------------------------------------*/
2017 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2018 {
2019     int i;
2020     asmop *aop ;
2021     regs *r = NULL;
2022
2023     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2024     if (popPsw) {
2025         if (options.useXstack) {
2026             aop = newAsmop(0);
2027             r = getFreePtr(ic,&aop,FALSE);
2028             
2029             
2030             emitcode("mov","%s,_spx",r->name);
2031             emitcode("movx","a,@%s",r->name);
2032             emitcode("mov","psw,a");
2033             emitcode("dec","%s",r->name);
2034             
2035         }else
2036             emitcode ("pop","psw");
2037     }
2038
2039     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2040         if (options.useXstack) {       
2041             emitcode("movx","a,@%s",r->name);
2042             //emitcode("mov","(%s+%d),a",
2043             //       regspic14[i].base,8*bank+regspic14[i].offset);
2044             emitcode("dec","%s",r->name);
2045
2046         } else 
2047           emitcode("pop",""); //"(%s+%d)",
2048         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2049     }
2050
2051     if (options.useXstack) {
2052
2053         emitcode("mov","_spx,%s",r->name);
2054         freeAsmop(NULL,aop,ic,TRUE);
2055
2056     } 
2057 }
2058
2059 /*-----------------------------------------------------------------*/
2060 /* saverbank - saves an entire register bank on the stack          */
2061 /*-----------------------------------------------------------------*/
2062 static void saverbank (int bank, iCode *ic, bool pushPsw)
2063 {
2064     int i;
2065     asmop *aop ;
2066     regs *r = NULL;
2067
2068     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2069     if (options.useXstack) {
2070
2071         aop = newAsmop(0);
2072         r = getFreePtr(ic,&aop,FALSE);  
2073         emitcode("mov","%s,_spx",r->name);
2074
2075     }
2076
2077     for (i = 0 ; i < pic14_nRegs ;i++) {
2078         if (options.useXstack) {
2079             emitcode("inc","%s",r->name);
2080             //emitcode("mov","a,(%s+%d)",
2081             //         regspic14[i].base,8*bank+regspic14[i].offset);
2082             emitcode("movx","@%s,a",r->name);           
2083         } else 
2084           emitcode("push","");// "(%s+%d)",
2085                      //regspic14[i].base,8*bank+regspic14[i].offset);
2086     }
2087     
2088     if (pushPsw) {
2089         if (options.useXstack) {
2090             emitcode("mov","a,psw");
2091             emitcode("movx","@%s,a",r->name);   
2092             emitcode("inc","%s",r->name);
2093             emitcode("mov","_spx,%s",r->name);       
2094             freeAsmop (NULL,aop,ic,TRUE);
2095             
2096         } else
2097             emitcode("push","psw");
2098         
2099         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2100     }
2101     ic->bankSaved = 1;
2102
2103 }
2104
2105 /*-----------------------------------------------------------------*/
2106 /* genCall - generates a call statement                            */
2107 /*-----------------------------------------------------------------*/
2108 static void genCall (iCode *ic)
2109 {
2110     sym_link *detype;   
2111
2112     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2113
2114     /* if caller saves & we have not saved then */
2115     if (!ic->regsSaved)
2116         saveRegisters(ic);
2117
2118     /* if we are calling a function that is not using
2119     the same register bank then we need to save the
2120     destination registers on the stack */
2121     detype = getSpec(operandType(IC_LEFT(ic)));
2122     if (detype        && 
2123         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2124         IS_ISR(currFunc->etype) &&
2125         !ic->bankSaved) 
2126
2127         saverbank(SPEC_BANK(detype),ic,TRUE);
2128
2129     /* if send set is not empty the assign */
2130     if (_G.sendSet) {
2131         iCode *sic ;
2132
2133         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2134              sic = setNextItem(_G.sendSet)) {
2135             int size, offset = 0;
2136
2137             aopOp(IC_LEFT(sic),sic,FALSE);
2138             size = AOP_SIZE(IC_LEFT(sic));
2139             while (size--) {
2140                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2141                                 FALSE,FALSE);
2142                 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2143
2144                 if (strcmp(l,fReturn[offset])) {
2145
2146                   if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2147                        ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2148                     emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2149                   //emitcode("movlw","%s",l);
2150                   else
2151                     emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2152                   //emitcode("movf","%s,w",l);
2153
2154                   // The last one is passed in W
2155                   if(size)
2156                     emitcode("movwf","%s",fReturn[offset]);
2157                 }
2158                 offset++;
2159             }
2160             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2161         }
2162         _G.sendSet = NULL;
2163     }
2164     /* make the call */
2165     emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2166                                         OP_SYMBOL(IC_LEFT(ic))->rname :
2167                                         OP_SYMBOL(IC_LEFT(ic))->name));
2168
2169     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2170                            OP_SYMBOL(IC_LEFT(ic))->rname :
2171                            OP_SYMBOL(IC_LEFT(ic))->name));
2172
2173     /* if we need assign a result value */
2174     if ((IS_ITEMP(IC_RESULT(ic)) && 
2175          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2176           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2177         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2178
2179         _G.accInUse++;
2180         aopOp(IC_RESULT(ic),ic,FALSE);
2181         _G.accInUse--;
2182
2183         assignResultValue(IC_RESULT(ic));
2184                 
2185         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2186     }
2187
2188     /* adjust the stack for parameters if 
2189     required */
2190     if (IC_LEFT(ic)->parmBytes) {
2191         int i;
2192         if (IC_LEFT(ic)->parmBytes > 3) {
2193             emitcode("mov","a,%s",spname);
2194             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2195             emitcode("mov","%s,a",spname);
2196         } else 
2197             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2198                 emitcode("dec","%s",spname);
2199
2200     }
2201
2202     /* if register bank was saved then pop them */
2203     if (ic->bankSaved)
2204         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2205
2206     /* if we hade saved some registers then unsave them */
2207     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2208         unsaveRegisters (ic);
2209
2210
2211 }
2212
2213 /*-----------------------------------------------------------------*/
2214 /* genPcall - generates a call by pointer statement                */
2215 /*-----------------------------------------------------------------*/
2216 static void genPcall (iCode *ic)
2217 {
2218     sym_link *detype;
2219     symbol *rlbl = newiTempLabel(NULL);
2220
2221
2222     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2223     /* if caller saves & we have not saved then */
2224     if (!ic->regsSaved)
2225         saveRegisters(ic);
2226
2227     /* if we are calling a function that is not using
2228     the same register bank then we need to save the
2229     destination registers on the stack */
2230     detype = getSpec(operandType(IC_LEFT(ic)));
2231     if (detype        && 
2232         IS_ISR(currFunc->etype) &&
2233         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2234         saverbank(SPEC_BANK(detype),ic,TRUE);
2235
2236
2237     /* push the return address on to the stack */
2238     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2239     emitcode("push","acc");    
2240     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2241     emitcode("push","acc");
2242     
2243     if (options.model == MODEL_FLAT24)
2244     {
2245         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2246         emitcode("push","acc");    
2247     }
2248
2249     /* now push the calling address */
2250     aopOp(IC_LEFT(ic),ic,FALSE);
2251
2252     pushSide(IC_LEFT(ic), FPTRSIZE);
2253
2254     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2255
2256     /* if send set is not empty the assign */
2257     if (_G.sendSet) {
2258         iCode *sic ;
2259
2260         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2261              sic = setNextItem(_G.sendSet)) {
2262             int size, offset = 0;
2263             aopOp(IC_LEFT(sic),sic,FALSE);
2264             size = AOP_SIZE(IC_LEFT(sic));
2265             while (size--) {
2266                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2267                                 FALSE,FALSE);
2268                 if (strcmp(l,fReturn[offset]))
2269                     emitcode("mov","%s,%s",
2270                              fReturn[offset],
2271                              l);
2272                 offset++;
2273             }
2274             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2275         }
2276         _G.sendSet = NULL;
2277     }
2278
2279     emitcode("ret","");
2280     emitcode("","%05d_DS_:",(rlbl->key+100));
2281
2282
2283     /* if we need assign a result value */
2284     if ((IS_ITEMP(IC_RESULT(ic)) &&
2285          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2286           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2287         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2288
2289         _G.accInUse++;
2290         aopOp(IC_RESULT(ic),ic,FALSE);
2291         _G.accInUse--;
2292         
2293         assignResultValue(IC_RESULT(ic));
2294
2295         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2296     }
2297
2298     /* adjust the stack for parameters if 
2299     required */
2300     if (IC_LEFT(ic)->parmBytes) {
2301         int i;
2302         if (IC_LEFT(ic)->parmBytes > 3) {
2303             emitcode("mov","a,%s",spname);
2304             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2305             emitcode("mov","%s,a",spname);
2306         } else 
2307             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2308                 emitcode("dec","%s",spname);
2309
2310     }
2311
2312     /* if register bank was saved then unsave them */
2313     if (detype        && 
2314         (SPEC_BANK(currFunc->etype) != 
2315          SPEC_BANK(detype)))
2316         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2317
2318     /* if we hade saved some registers then
2319     unsave them */
2320     if (ic->regsSaved)
2321         unsaveRegisters (ic);
2322
2323 }
2324
2325 /*-----------------------------------------------------------------*/
2326 /* resultRemat - result  is rematerializable                       */
2327 /*-----------------------------------------------------------------*/
2328 static int resultRemat (iCode *ic)
2329 {
2330     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2331     if (SKIP_IC(ic) || ic->op == IFX)
2332         return 0;
2333
2334     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2335         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2336         if (sym->remat && !POINTER_SET(ic)) 
2337             return 1;
2338     }
2339
2340     return 0;
2341 }
2342
2343 #if defined(__BORLANDC__) || defined(_MSC_VER)
2344 #define STRCASECMP stricmp
2345 #else
2346 #define STRCASECMP strcasecmp
2347 #endif
2348
2349 /*-----------------------------------------------------------------*/
2350 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2351 /*-----------------------------------------------------------------*/
2352 static bool inExcludeList(char *s)
2353 {
2354     int i =0;
2355     
2356     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2357     if (options.excludeRegs[i] &&
2358     STRCASECMP(options.excludeRegs[i],"none") == 0)
2359         return FALSE ;
2360
2361     for ( i = 0 ; options.excludeRegs[i]; i++) {
2362         if (options.excludeRegs[i] &&
2363         STRCASECMP(s,options.excludeRegs[i]) == 0)
2364             return TRUE;
2365     }
2366     return FALSE ;
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genFunction - generated code for function entry                 */
2371 /*-----------------------------------------------------------------*/
2372 static void genFunction (iCode *ic)
2373 {
2374     symbol *sym;
2375     sym_link *fetype;
2376
2377     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378     labelOffset += FUNCTION_LABEL_INC;
2379
2380     _G.nRegsSaved = 0;
2381     /* create the function header */
2382     emitcode(";","-----------------------------------------");
2383     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2384     emitcode(";","-----------------------------------------");
2385
2386     emitcode("","%s:",sym->rname);
2387     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2388
2389     fetype = getSpec(operandType(IC_LEFT(ic)));
2390
2391     /* if critical function then turn interrupts off */
2392     if (SPEC_CRTCL(fetype))
2393         emitcode("clr","ea");
2394
2395     /* here we need to generate the equates for the
2396        register bank if required */
2397 #if 0
2398     if (SPEC_BANK(fetype) != rbank) {
2399         int i ;
2400
2401         rbank = SPEC_BANK(fetype);
2402         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2403             if (strcmp(regspic14[i].base,"0") == 0)
2404                 emitcode("","%s = 0x%02x",
2405                          regspic14[i].dname,
2406                          8*rbank+regspic14[i].offset);
2407             else
2408                 emitcode ("","%s = %s + 0x%02x",
2409                           regspic14[i].dname,
2410                           regspic14[i].base,
2411                           8*rbank+regspic14[i].offset);
2412         }
2413     }
2414 #endif
2415
2416     /* if this is an interrupt service routine then
2417     save acc, b, dpl, dph  */
2418     if (IS_ISR(sym->etype)) {
2419         
2420         if (!inExcludeList("acc"))          
2421             emitcode ("push","acc");    
2422         if (!inExcludeList("b"))
2423             emitcode ("push","b");
2424         if (!inExcludeList("dpl"))
2425             emitcode ("push","dpl");
2426         if (!inExcludeList("dph"))
2427             emitcode ("push","dph");
2428         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2429         {
2430             emitcode ("push", "dpx");
2431             /* Make sure we're using standard DPTR */
2432             emitcode ("push", "dps");
2433             emitcode ("mov", "dps, #0x00");
2434             if (options.stack10bit)
2435             {   
2436                 /* This ISR could conceivably use DPTR2. Better save it. */
2437                 emitcode ("push", "dpl1");
2438                 emitcode ("push", "dph1");
2439                 emitcode ("push", "dpx1");
2440             }
2441         }
2442         /* if this isr has no bank i.e. is going to
2443            run with bank 0 , then we need to save more
2444            registers :-) */
2445         if (!SPEC_BANK(sym->etype)) {
2446
2447             /* if this function does not call any other
2448                function then we can be economical and
2449                save only those registers that are used */
2450             if (! sym->hasFcall) {
2451                 int i;
2452
2453                 /* if any registers used */
2454                 if (sym->regsUsed) {
2455                     /* save the registers used */
2456                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2457                         if (bitVectBitValue(sym->regsUsed,i) ||
2458                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2459                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2460                     }
2461                 }
2462                 
2463             } else {
2464                 /* this function has  a function call cannot
2465                    determines register usage so we will have the
2466                    entire bank */
2467                 saverbank(0,ic,FALSE);
2468             }       
2469         }
2470     } else {
2471         /* if callee-save to be used for this function
2472            then save the registers being used in this function */
2473         if (sym->calleeSave) {
2474             int i;
2475             
2476             /* if any registers used */
2477             if (sym->regsUsed) {
2478                 /* save the registers used */
2479                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2480                     if (bitVectBitValue(sym->regsUsed,i) ||
2481                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2482                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2483                         _G.nRegsSaved++;
2484                     }
2485                 }
2486             }
2487         }
2488     }
2489
2490     /* set the register bank to the desired value */
2491     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2492         emitcode("push","psw");
2493         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2494     }
2495
2496     if (IS_RENT(sym->etype) || options.stackAuto) {
2497
2498         if (options.useXstack) {
2499             emitcode("mov","r0,%s",spname);
2500             emitcode("mov","a,_bp");
2501             emitcode("movx","@r0,a");
2502             emitcode("inc","%s",spname);
2503         }
2504         else
2505         {
2506             /* set up the stack */
2507             emitcode ("push","_bp");     /* save the callers stack  */
2508         }
2509         emitcode ("mov","_bp,%s",spname);
2510     }
2511
2512     /* adjust the stack for the function */
2513     if (sym->stack) {
2514
2515         int i = sym->stack;
2516         if (i > 256 ) 
2517             werror(W_STACK_OVERFLOW,sym->name);
2518
2519         if (i > 3 && sym->recvSize < 4) {              
2520
2521             emitcode ("mov","a,sp");
2522             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2523             emitcode ("mov","sp,a");
2524            
2525         }
2526         else
2527             while(i--)
2528                 emitcode("inc","sp");
2529     }
2530
2531      if (sym->xstack) {
2532
2533         emitcode ("mov","a,_spx");
2534         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2535         emitcode ("mov","_spx,a");
2536     }    
2537
2538 }
2539
2540 /*-----------------------------------------------------------------*/
2541 /* genEndFunction - generates epilogue for functions               */
2542 /*-----------------------------------------------------------------*/
2543 static void genEndFunction (iCode *ic)
2544 {
2545     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2546
2547     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548
2549     if (IS_RENT(sym->etype) || options.stackAuto)
2550     {
2551         emitcode ("mov","%s,_bp",spname);
2552     }
2553
2554     /* if use external stack but some variables were
2555     added to the local stack then decrement the
2556     local stack */
2557     if (options.useXstack && sym->stack) {      
2558         emitcode("mov","a,sp");
2559         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2560         emitcode("mov","sp,a");
2561     }
2562
2563
2564     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2565         if (options.useXstack) {
2566             emitcode("mov","r0,%s",spname);
2567             emitcode("movx","a,@r0");
2568             emitcode("mov","_bp,a");
2569             emitcode("dec","%s",spname);
2570         }
2571         else
2572         {
2573             emitcode ("pop","_bp");
2574         }
2575     }
2576
2577     /* restore the register bank  */    
2578     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2579         emitcode ("pop","psw");
2580
2581     if (IS_ISR(sym->etype)) {
2582
2583         /* now we need to restore the registers */
2584         /* if this isr has no bank i.e. is going to
2585            run with bank 0 , then we need to save more
2586            registers :-) */
2587         if (!SPEC_BANK(sym->etype)) {
2588             
2589             /* if this function does not call any other
2590                function then we can be economical and
2591                save only those registers that are used */
2592             if (! sym->hasFcall) {
2593                 int i;
2594                 
2595                 /* if any registers used */
2596                 if (sym->regsUsed) {
2597                     /* save the registers used */
2598                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2599                         if (bitVectBitValue(sym->regsUsed,i) ||
2600                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2601                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2602                     }
2603                 }
2604                 
2605             } else {
2606                 /* this function has  a function call cannot
2607                    determines register usage so we will have the
2608                    entire bank */
2609                 unsaverbank(0,ic,FALSE);
2610             }       
2611         }
2612
2613         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2614         {
2615             if (options.stack10bit)
2616             {
2617                 emitcode ("pop", "dpx1");
2618                 emitcode ("pop", "dph1");
2619                 emitcode ("pop", "dpl1");
2620             }   
2621             emitcode ("pop", "dps");
2622             emitcode ("pop", "dpx");
2623         }
2624         if (!inExcludeList("dph"))
2625             emitcode ("pop","dph");
2626         if (!inExcludeList("dpl"))
2627             emitcode ("pop","dpl");
2628         if (!inExcludeList("b"))
2629             emitcode ("pop","b");
2630         if (!inExcludeList("acc"))
2631             emitcode ("pop","acc");
2632
2633         if (SPEC_CRTCL(sym->etype))
2634             emitcode("setb","ea");
2635
2636         /* if debug then send end of function */
2637 /*      if (options.debug && currFunc) { */
2638         if (currFunc) {
2639             _G.debugLine = 1;
2640             emitcode(";","C$%s$%d$%d$%d ==.",
2641                      ic->filename,currFunc->lastLine,
2642                      ic->level,ic->block); 
2643             if (IS_STATIC(currFunc->etype))         
2644                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2645             else
2646                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2647             _G.debugLine = 0;
2648         }
2649         
2650         emitcode ("reti","");
2651     }
2652     else {
2653         if (SPEC_CRTCL(sym->etype))
2654             emitcode("setb","ea");
2655         
2656         if (sym->calleeSave) {
2657             int i;
2658             
2659             /* if any registers used */
2660             if (sym->regsUsed) {
2661                 /* save the registers used */
2662                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2663                     if (bitVectBitValue(sym->regsUsed,i) ||
2664                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2665                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2666                 }
2667             }
2668             
2669         }
2670
2671         /* if debug then send end of function */
2672         if (currFunc) {
2673             _G.debugLine = 1;
2674             emitcode(";","C$%s$%d$%d$%d ==.",
2675                      ic->filename,currFunc->lastLine,
2676                      ic->level,ic->block); 
2677             if (IS_STATIC(currFunc->etype))         
2678                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2679             else
2680                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2681             _G.debugLine = 0;
2682         }
2683
2684         emitcode ("return","");
2685         emitpcode(POC_RETURN,NULL);
2686
2687         /* Mark the end of a function */
2688         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2689     }
2690
2691 }
2692
2693 /*-----------------------------------------------------------------*/
2694 /* genRet - generate code for return statement                     */
2695 /*-----------------------------------------------------------------*/
2696 static void genRet (iCode *ic)
2697 {
2698     int size,offset = 0 , pushed = 0;
2699     
2700     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2701     /* if we have no return value then
2702        just generate the "ret" */
2703     if (!IC_LEFT(ic)) 
2704         goto jumpret;       
2705     
2706     /* we have something to return then
2707        move the return value into place */
2708     aopOp(IC_LEFT(ic),ic,FALSE);
2709     size = AOP_SIZE(IC_LEFT(ic));
2710     
2711     while (size--) {
2712             char *l ;
2713             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2714                     /* #NOCHANGE */
2715                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2716                            FALSE,TRUE);
2717                     emitcode("push","%s",l);
2718                     pushed++;
2719             } else {
2720                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2721                                FALSE,FALSE);
2722                     if (strcmp(fReturn[offset],l)) {
2723                       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2724                           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2725                         emitcode("movlw","%s",l);
2726                       else
2727                         emitcode("movf","%s,w",l);
2728                       if(size)
2729                         emitcode("movwf","%s",fReturn[offset]);
2730                       offset++;
2731                     }
2732             }
2733     }    
2734
2735     if (pushed) {
2736         while(pushed) {
2737             pushed--;
2738             if (strcmp(fReturn[pushed],"a"))
2739                 emitcode("pop",fReturn[pushed]);
2740             else
2741                 emitcode("pop","acc");
2742         }
2743     }
2744     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2745     
2746  jumpret:
2747         /* generate a jump to the return label
2748            if the next is not the return statement */
2749     if (!(ic->next && ic->next->op == LABEL &&
2750           IC_LABEL(ic->next) == returnLabel))
2751         
2752         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2753     
2754 }
2755
2756 /*-----------------------------------------------------------------*/
2757 /* genLabel - generates a label                                    */
2758 /*-----------------------------------------------------------------*/
2759 static void genLabel (iCode *ic)
2760 {
2761     /* special case never generate */
2762     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2763     if (IC_LABEL(ic) == entryLabel)
2764         return ;
2765
2766     emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2767     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2768 }
2769
2770 /*-----------------------------------------------------------------*/
2771 /* genGoto - generates a goto                                      */
2772 /*-----------------------------------------------------------------*/
2773 //tsd
2774 static void genGoto (iCode *ic)
2775 {
2776     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2777 }
2778
2779 /*-----------------------------------------------------------------*/
2780 /* findLabelBackwards: walks back through the iCode chain looking  */
2781 /* for the given label. Returns number of iCode instructions       */
2782 /* between that label and given ic.                                */
2783 /* Returns zero if label not found.                                */
2784 /*-----------------------------------------------------------------*/
2785 #if 0
2786 static int findLabelBackwards(iCode *ic, int key)
2787 {
2788     int count = 0;
2789     
2790     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2791     while (ic->prev)
2792     {
2793         ic = ic->prev;
2794         count++;
2795         
2796         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2797         {
2798             /* printf("findLabelBackwards = %d\n", count); */
2799             return count;
2800         }
2801     }
2802     
2803     return 0;
2804 }
2805 #endif
2806 /*-----------------------------------------------------------------*/
2807 /* genPlusIncr :- does addition with increment if possible         */
2808 /*-----------------------------------------------------------------*/
2809 static bool genPlusIncr (iCode *ic)
2810 {
2811     unsigned int icount ;
2812     unsigned int size = getDataSize(IC_RESULT(ic));
2813
2814     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2815     DEBUGemitcode ("; ","result %d, left %d, right %d",
2816                    AOP_TYPE(IC_RESULT(ic)),
2817                    AOP_TYPE(IC_LEFT(ic)),
2818                    AOP_TYPE(IC_RIGHT(ic)));
2819
2820     /* will try to generate an increment */
2821     /* if the right side is not a literal 
2822        we cannot */
2823     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2824         return FALSE ;
2825     
2826     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2827     /* if the literal value of the right hand side
2828        is greater than 1 then it is faster to add */
2829     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2830         return FALSE ;
2831     
2832     /* if increment 16 bits in register */
2833     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2834         (icount == 1)) {
2835
2836       int offset = MSB16;
2837
2838       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2839       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2840
2841       while(--size) {
2842         emitSKPNZ;
2843         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2844         //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2845       }
2846
2847       return TRUE;
2848     }
2849     
2850     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2851     /* if left is in accumulator  - probably a bit operation*/
2852     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2853         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2854       
2855       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2856       emitcode("bcf","(%s >> 3), (%s & 7)",
2857                AOP(IC_RESULT(ic))->aopu.aop_dir,
2858                AOP(IC_RESULT(ic))->aopu.aop_dir);
2859       if(icount)
2860         emitpcode(POC_XORLW,popGetLit(1));
2861       //emitcode("xorlw","1");
2862       else
2863         emitpcode(POC_ANDLW,popGetLit(1));
2864       //emitcode("andlw","1");
2865
2866       emitSKPZ;
2867       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2868       emitcode("bsf","(%s >> 3), (%s & 7)",
2869                AOP(IC_RESULT(ic))->aopu.aop_dir,
2870                AOP(IC_RESULT(ic))->aopu.aop_dir);
2871
2872       return TRUE;
2873     }
2874
2875
2876
2877     /* if the sizes are greater than 1 then we cannot */
2878     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2879         AOP_SIZE(IC_LEFT(ic)) > 1   )
2880         return FALSE ;
2881     
2882     /* If we are incrementing the same register by two: */
2883
2884     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2885         
2886       while (icount--) 
2887         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2888       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2889         
2890       return TRUE ;
2891     }
2892     
2893     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2894                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2895                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2896     return FALSE ;
2897 }
2898
2899 /*-----------------------------------------------------------------*/
2900 /* outBitAcc - output a bit in acc                                 */
2901 /*-----------------------------------------------------------------*/
2902 static void outBitAcc(operand *result)
2903 {
2904     symbol *tlbl = newiTempLabel(NULL);
2905     /* if the result is a bit */
2906     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2907
2908     if (AOP_TYPE(result) == AOP_CRY){
2909         aopPut(AOP(result),"a",0);
2910     }
2911     else {
2912         emitcode("jz","%05d_DS_",tlbl->key+100);
2913         emitcode("mov","a,%s",one);
2914         emitcode("","%05d_DS_:",tlbl->key+100);
2915         outAcc(result);
2916     }
2917 }
2918
2919 /*-----------------------------------------------------------------*/
2920 /* genPlusBits - generates code for addition of two bits           */
2921 /*-----------------------------------------------------------------*/
2922 static void genPlusBits (iCode *ic)
2923 {
2924
2925     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2926     /*
2927       The following block of code will add two bits. 
2928       Note that it'll even work if the destination is
2929       the carry (C in the status register).
2930       It won't work if the 'Z' bit is a source or destination.
2931     */
2932
2933     /* If the result is stored in the accumulator (w) */
2934     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2935       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2936       //              popGet(AOP(result),0,FALSE,FALSE));
2937
2938       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2939       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2940       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2941       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2942       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2943       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2944
2945         emitcode("movlw","(1 << (%s & 7))",
2946                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2947                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2948         emitcode("bcf","(%s >> 3), (%s & 7)",
2949                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2950                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2951         emitcode("btfsc","(%s >> 3), (%s & 7)",
2952                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2953                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2954         emitcode("xorwf","(%s >>3),f",
2955                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2956         emitcode("btfsc","(%s >> 3), (%s & 7)",
2957                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2958                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2959         emitcode("xorwf","(%s>>3),f",
2960                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2961     } else { 
2962
2963       emitpcode(POC_CLRW, NULL);
2964       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2965       emitpcode(POC_XORLW, popGetLit(1));
2966       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2967       emitpcode(POC_XORLW, popGetLit(1));
2968
2969       emitcode("clrw","");
2970       emitcode("btfsc","(%s >> 3), (%s & 7)",
2971                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2972                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2973       emitcode("xorlw","1");
2974       emitcode("btfsc","(%s >> 3), (%s & 7)",
2975                AOP(IC_LEFT(ic))->aopu.aop_dir,
2976                AOP(IC_LEFT(ic))->aopu.aop_dir);
2977       emitcode("xorlw","1");
2978     }
2979
2980 }
2981
2982 #if 0
2983 /* This is the original version of this code.
2984  *
2985  * This is being kept around for reference, 
2986  * because I am not entirely sure I got it right...
2987  */
2988 static void adjustArithmeticResult(iCode *ic)
2989 {
2990     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2991         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2992         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2993         aopPut(AOP(IC_RESULT(ic)),
2994                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2995                2);
2996
2997     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2998         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2999         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3000         aopPut(AOP(IC_RESULT(ic)),
3001                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3002                2);
3003     
3004     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3005         AOP_SIZE(IC_LEFT(ic)) < 3    &&
3006         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
3007         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3008         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3009         char buffer[5];
3010         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3011         aopPut(AOP(IC_RESULT(ic)),buffer,2);
3012     }
3013 }
3014 //#else
3015 /* This is the pure and virtuous version of this code.
3016  * I'm pretty certain it's right, but not enough to toss the old 
3017  * code just yet...
3018  */
3019 static void adjustArithmeticResult(iCode *ic)
3020 {
3021     if (opIsGptr(IC_RESULT(ic)) &&
3022         opIsGptr(IC_LEFT(ic))   &&
3023         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3024     {
3025         aopPut(AOP(IC_RESULT(ic)),
3026                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3027                GPTRSIZE - 1);
3028     }
3029
3030     if (opIsGptr(IC_RESULT(ic)) &&
3031         opIsGptr(IC_RIGHT(ic))   &&
3032         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3033     {
3034         aopPut(AOP(IC_RESULT(ic)),
3035                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3036                GPTRSIZE - 1);
3037     }
3038
3039     if (opIsGptr(IC_RESULT(ic))            &&
3040         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
3041         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
3042          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3043          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3044          char buffer[5];
3045          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3046          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3047      }
3048 }
3049 #endif
3050
3051 /*-----------------------------------------------------------------*/
3052 /* genPlus - generates code for addition                           */
3053 /*-----------------------------------------------------------------*/
3054 static void genPlus (iCode *ic)
3055 {
3056     int size, offset = 0;
3057
3058     /* special cases :- */
3059     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3060
3061     aopOp (IC_LEFT(ic),ic,FALSE);
3062     aopOp (IC_RIGHT(ic),ic,FALSE);
3063     aopOp (IC_RESULT(ic),ic,TRUE);
3064
3065     /* if literal, literal on the right or
3066        if left requires ACC or right is already
3067        in ACC */
3068
3069     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3070         operand *t = IC_RIGHT(ic);
3071         IC_RIGHT(ic) = IC_LEFT(ic);
3072         IC_LEFT(ic) = t;
3073     }
3074
3075     /* if both left & right are in bit space */
3076     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3077         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3078         genPlusBits (ic);
3079         goto release ;
3080     }
3081
3082     /* if left in bit space & right literal */
3083     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3084         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3085         /* if result in bit space */
3086         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3087           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3088             emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3089             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3090               emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3091             emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3092           }
3093         } else {
3094             size = getDataSize(IC_RESULT(ic));
3095             while (size--) {
3096                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
3097                 emitcode("addc","a,#00  ;%d",__LINE__);
3098                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3099             }
3100         }
3101         goto release ;
3102     }
3103
3104     /* if I can do an increment instead
3105     of add then GOOD for ME */
3106     if (genPlusIncr (ic) == TRUE)
3107         goto release;   
3108
3109     size = getDataSize(IC_RESULT(ic));
3110
3111     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3112       /* Add a literal to something else */
3113       bool know_W=0;
3114       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3115       unsigned l1=0;
3116
3117       offset = 0;
3118       DEBUGemitcode(";","adding lit to something. size %d",size);
3119       while(size--){
3120
3121       DEBUGemitcode(";","size %d",size);
3122
3123         switch (lit & 0xff) {
3124         case 0:
3125           break;
3126         case 1:
3127           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3128             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3129           else {
3130             know_W = 0;
3131             emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3132             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3133               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3134           }
3135           break;
3136         case 0xff:
3137           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3138             emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3139           else {
3140             know_W = 0;
3141             emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3142             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3143               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3144           }
3145           break;
3146         default:
3147           if( !know_W || ( (lit&0xff) != l1)  ) {
3148             know_W = 1;
3149             emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3150           }
3151           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3152             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3153           else {
3154             know_W = 0;
3155             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3156             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3157             if(size) {
3158               emitSKPNC;
3159               emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3160             }
3161           }
3162         }
3163
3164         l1 = lit & 0xff;
3165         lit >>= 8;
3166         offset++;
3167       }
3168
3169     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3170
3171       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3172       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3173       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3174
3175       /* here we are adding a bit to a char or int */
3176       if(size == 1) {
3177         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3178
3179           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3180           emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3181
3182           emitcode("btfsc","(%s >> 3), (%s & 7)",
3183                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3184                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3185           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3186         } else {
3187
3188           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3189             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3190             emitpcode(POC_XORLW , popGetLit(1));
3191
3192             emitcode("btfsc","(%s >> 3), (%s & 7)",
3193                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3194                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3195             emitcode(" xorlw","1");
3196           } else {
3197             emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3198             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3199             emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3200
3201             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3202             emitcode("btfsc","(%s >> 3), (%s & 7)",
3203                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3204                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3205             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3206           }
3207           
3208           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3209             
3210             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3211               emitpcode(POC_ANDLW , popGetLit(1));
3212               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3213               emitSKPZ;
3214               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3215 /*
3216               emitcode("andlw","1");
3217               emitcode("bcf","(%s >> 3), (%s & 7)",
3218                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3219                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3220               emitSKPZ;
3221               emitcode("bsf","(%s >> 3), (%s & 7)",
3222                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3223                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3224 */
3225
3226             } else {
3227               emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3228               emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3229             }
3230           }
3231         }
3232
3233       } else {
3234         int offset = 1;
3235
3236         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3237           emitCLRZ;
3238           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3239           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3240
3241           emitcode("clrz","");
3242
3243           emitcode("btfsc","(%s >> 3), (%s & 7)",
3244                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3245                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3246           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3247
3248         } else {
3249
3250           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3251           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3252           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3253           emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3254
3255
3256           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3257           emitcode("btfsc","(%s >> 3), (%s & 7)",
3258                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3259                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3260           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3261           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3262
3263         }
3264
3265         while(--size){
3266           emitSKPZ;
3267           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3268       //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3269         }
3270
3271       }
3272       
3273     } else {
3274     
3275       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3276         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3277         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3278       } else {
3279
3280         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3281           emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3282           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3283             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3284         } else {
3285
3286           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3287
3288           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3289             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3290           else {
3291             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3292                 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3293               emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3294             } else {
3295               emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3296               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3297                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3298             }
3299           }
3300         }
3301       }
3302
3303       offset = 1;
3304       size--;
3305
3306       while(size--){
3307         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3308           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3309           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3310
3311           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3312           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3313         }
3314
3315         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3316         emitSKPNC;
3317         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3318         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3319
3320         /*
3321         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3322         emitSKPNC;
3323         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3324         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3325         */
3326
3327         offset++;
3328       }
3329
3330     }
3331
3332     //adjustArithmeticResult(ic);
3333
3334  release:
3335       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3336       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3338 }
3339
3340 /*-----------------------------------------------------------------*/
3341 /* genMinusDec :- does subtraction with decrement if possible     */
3342 /*-----------------------------------------------------------------*/
3343 static bool genMinusDec (iCode *ic)
3344 {
3345     unsigned int icount ;
3346     unsigned int size = getDataSize(IC_RESULT(ic));
3347
3348     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3349     /* will try to generate an increment */
3350     /* if the right side is not a literal 
3351     we cannot */
3352     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3353         return FALSE ;
3354
3355     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3356
3357     /* if the literal value of the right hand side
3358     is greater than 4 then it is not worth it */
3359     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3360         return FALSE ;
3361
3362     /* if decrement 16 bits in register */
3363     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3364         (size > 1) &&
3365         (icount == 1)) {
3366
3367       if(size == 2) { 
3368         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3369         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3370         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3371       } else {
3372         /* size is 3 or 4 */
3373         emitcode("movlw","0xff");
3374         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3375
3376         emitSKPNC;
3377         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3378         emitSKPNC;
3379         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3380
3381         if(size > 3) {
3382           emitcode("skpnc","");
3383           emitSKPNC;
3384           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3385         }
3386
3387       }
3388
3389       return TRUE;
3390
3391     }
3392
3393     /* if the sizes are greater than 1 then we cannot */
3394     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3395         AOP_SIZE(IC_LEFT(ic)) > 1   )
3396         return FALSE ;
3397
3398     /* we can if the aops of the left & result match or
3399     if they are in registers and the registers are the
3400     same */
3401     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3402
3403       while (icount--) 
3404         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3405
3406         //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3407
3408         return TRUE ;
3409     }
3410
3411     DEBUGemitcode ("; returning"," result=%s, left=%s",
3412                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3413                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3414     if(size==1) {
3415       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3416       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3417       return TRUE;
3418     }
3419
3420     return FALSE ;
3421 }
3422
3423 /*-----------------------------------------------------------------*/
3424 /* addSign - complete with sign                                    */
3425 /*-----------------------------------------------------------------*/
3426 static void addSign(operand *result, int offset, int sign)
3427 {
3428     int size = (getDataSize(result) - offset);
3429     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3430     if(size > 0){
3431         if(sign){
3432             emitcode("rlc","a");
3433             emitcode("subb","a,acc");
3434             while(size--)
3435                 aopPut(AOP(result),"a",offset++); 
3436         } else
3437             while(size--)
3438                 aopPut(AOP(result),zero,offset++);
3439     }
3440 }
3441
3442 /*-----------------------------------------------------------------*/
3443 /* genMinusBits - generates code for subtraction  of two bits      */
3444 /*-----------------------------------------------------------------*/
3445 static void genMinusBits (iCode *ic)
3446 {
3447     symbol *lbl = newiTempLabel(NULL);
3448     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3449     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3450         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3451         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3452         emitcode("cpl","c");
3453         emitcode("","%05d_DS_:",(lbl->key+100));
3454         outBitC(IC_RESULT(ic));
3455     }
3456     else{
3457         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3458         emitcode("subb","a,acc");
3459         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3460         emitcode("inc","a");
3461         emitcode("","%05d_DS_:",(lbl->key+100));
3462         aopPut(AOP(IC_RESULT(ic)),"a",0);
3463         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3464     }
3465 }
3466
3467 /*-----------------------------------------------------------------*/
3468 /* genMinus - generates code for subtraction                       */
3469 /*-----------------------------------------------------------------*/
3470 static void genMinus (iCode *ic)
3471 {
3472     int size, offset = 0;
3473     unsigned long lit = 0L;
3474
3475     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3476     aopOp (IC_LEFT(ic),ic,FALSE);
3477     aopOp (IC_RIGHT(ic),ic,FALSE);
3478     aopOp (IC_RESULT(ic),ic,TRUE);
3479
3480     /* special cases :- */
3481     /* if both left & right are in bit space */
3482     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3483         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3484         genMinusBits (ic);
3485         goto release ;
3486     }
3487
3488     /* if I can do an decrement instead
3489     of subtract then GOOD for ME */
3490     if (genMinusDec (ic) == TRUE)
3491         goto release;   
3492
3493     size = getDataSize(IC_RESULT(ic));   
3494
3495     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3496       /* Add a literal to something else */
3497
3498       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3499       lit = - (long)lit;
3500
3501       /* add the first byte: */
3502       emitcode("movlw","0x%x", lit & 0xff);
3503       emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3504
3505       offset = 1;
3506       size--;
3507
3508       while(size--){
3509
3510         emitcode("rlf","_known_zero,w");
3511         emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3512
3513         lit >>= 8;
3514         if(lit & 0xff) {
3515           emitcode("movlw","0x%x", lit & 0xff);
3516           emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3517           
3518         }
3519         offset++;
3520       }
3521
3522     } else {
3523
3524       emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3525       emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3526
3527       offset = 1;
3528       size--;
3529
3530       while(size--){
3531         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3532         emitSKPNC;
3533         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3534         emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3535         
3536       }
3537
3538     }
3539
3540
3541     //    adjustArithmeticResult(ic);
3542         
3543 release:
3544     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3545     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3547 }
3548
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genMultbits :- multiplication of bits                           */
3552 /*-----------------------------------------------------------------*/
3553 static void genMultbits (operand *left, 
3554                          operand *right, 
3555                          operand *result)
3556 {
3557     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3558
3559     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3560     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3561     outBitC(result);
3562 }
3563
3564
3565 /*-----------------------------------------------------------------*/
3566 /* genMultOneByte : 8 bit multiplication & division                */
3567 /*-----------------------------------------------------------------*/
3568 static void genMultOneByte (operand *left,
3569                             operand *right,
3570                             operand *result)
3571 {
3572     sym_link *opetype = operandType(result);
3573     char *l ;
3574     symbol *lbl ;
3575     int size,offset;
3576
3577     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3578     /* (if two literals, the value is computed before) */
3579     /* if one literal, literal on the right */
3580     if (AOP_TYPE(left) == AOP_LIT){
3581         operand *t = right;
3582         right = left;
3583         left = t;
3584     }
3585
3586     size = AOP_SIZE(result);
3587     /* signed or unsigned */
3588     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3589     l = aopGet(AOP(left),0,FALSE,FALSE);
3590     MOVA(l);       
3591     emitcode("mul","ab");
3592     /* if result size = 1, mul signed = mul unsigned */
3593     aopPut(AOP(result),"a",0);
3594     if (size > 1){
3595         if (SPEC_USIGN(opetype)){
3596             aopPut(AOP(result),"b",1);
3597             if (size > 2)
3598                 /* for filling the MSBs */
3599                 emitcode("clr","a");
3600         }
3601         else{
3602             emitcode("mov","a,b");
3603
3604             /* adjust the MSB if left or right neg */
3605
3606             /* if one literal */
3607             if (AOP_TYPE(right) == AOP_LIT){
3608                 /* AND literal negative */
3609                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3610                     /* adjust MSB (c==0 after mul) */
3611                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3612                 }
3613             }
3614             else{
3615                 lbl = newiTempLabel(NULL);
3616                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3617                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3618                 emitcode("","%05d_DS_:",(lbl->key+100));
3619                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3620                 lbl = newiTempLabel(NULL);      
3621                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3622                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3623                 emitcode("","%05d_DS_:",(lbl->key+100));
3624             }
3625
3626             lbl = newiTempLabel(NULL);
3627             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3628             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3629             emitcode("","%05d_DS_:",(lbl->key+100));
3630             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3631             lbl = newiTempLabel(NULL);      
3632             emitcode("jc","%05d_DS_",(lbl->key+100));          
3633             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3634             emitcode("","%05d_DS_:",(lbl->key+100));
3635
3636             aopPut(AOP(result),"a",1);
3637             if(size > 2){
3638                 /* get the sign */
3639                 emitcode("rlc","a");
3640                 emitcode("subb","a,acc");
3641             }
3642         }
3643         size -= 2;   
3644         offset = 2;
3645         if (size > 0)
3646             while (size--)
3647                 aopPut(AOP(result),"a",offset++);
3648     }
3649 }
3650
3651 /*-----------------------------------------------------------------*/
3652 /* genMult - generates code for multiplication                     */
3653 /*-----------------------------------------------------------------*/
3654 static void genMult (iCode *ic)
3655 {
3656     operand *left = IC_LEFT(ic);
3657     operand *right = IC_RIGHT(ic);
3658     operand *result= IC_RESULT(ic);   
3659
3660     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3661     /* assign the amsops */
3662     aopOp (left,ic,FALSE);
3663     aopOp (right,ic,FALSE);
3664     aopOp (result,ic,TRUE);
3665
3666     /* special cases first */
3667     /* both are bits */
3668     if (AOP_TYPE(left) == AOP_CRY &&
3669         AOP_TYPE(right)== AOP_CRY) {
3670         genMultbits(left,right,result);
3671         goto release ;
3672     }
3673
3674     /* if both are of size == 1 */
3675     if (AOP_SIZE(left) == 1 &&
3676         AOP_SIZE(right) == 1 ) {
3677         genMultOneByte(left,right,result);
3678         goto release ;
3679     }
3680
3681     /* should have been converted to function call */       
3682     assert(1) ;
3683
3684 release :
3685     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687     freeAsmop(result,NULL,ic,TRUE); 
3688 }
3689
3690 /*-----------------------------------------------------------------*/
3691 /* genDivbits :- division of bits                                  */
3692 /*-----------------------------------------------------------------*/
3693 static void genDivbits (operand *left, 
3694                         operand *right, 
3695                         operand *result)
3696 {
3697
3698     char *l;
3699
3700     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3701     /* the result must be bit */    
3702     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3703     l = aopGet(AOP(left),0,FALSE,FALSE);
3704
3705     MOVA(l);    
3706
3707     emitcode("div","ab");
3708     emitcode("rrc","a");
3709     aopPut(AOP(result),"c",0);
3710 }
3711
3712 /*-----------------------------------------------------------------*/
3713 /* genDivOneByte : 8 bit division                                  */
3714 /*-----------------------------------------------------------------*/
3715 static void genDivOneByte (operand *left,
3716                            operand *right,
3717                            operand *result)
3718 {
3719     sym_link *opetype = operandType(result);
3720     char *l ;
3721     symbol *lbl ;
3722     int size,offset;
3723
3724     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3725     size = AOP_SIZE(result) - 1;
3726     offset = 1;
3727     /* signed or unsigned */
3728     if (SPEC_USIGN(opetype)) {
3729         /* unsigned is easy */
3730         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3731         l = aopGet(AOP(left),0,FALSE,FALSE);
3732         MOVA(l);        
3733         emitcode("div","ab");
3734         aopPut(AOP(result),"a",0);
3735         while (size--)
3736             aopPut(AOP(result),zero,offset++);
3737         return ;
3738     }
3739
3740     /* signed is a little bit more difficult */
3741
3742     /* save the signs of the operands */
3743     l = aopGet(AOP(left),0,FALSE,FALSE);    
3744     MOVA(l);    
3745     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3746     emitcode("push","acc"); /* save it on the stack */
3747
3748     /* now sign adjust for both left & right */
3749     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3750     MOVA(l);       
3751     lbl = newiTempLabel(NULL);
3752     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3753     emitcode("cpl","a");   
3754     emitcode("inc","a");
3755     emitcode("","%05d_DS_:",(lbl->key+100));
3756     emitcode("mov","b,a");
3757
3758     /* sign adjust left side */
3759     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3760     MOVA(l);
3761
3762     lbl = newiTempLabel(NULL);
3763     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3764     emitcode("cpl","a");
3765     emitcode("inc","a");
3766     emitcode("","%05d_DS_:",(lbl->key+100));
3767
3768     /* now the division */
3769     emitcode("div","ab");
3770     /* we are interested in the lower order
3771     only */
3772     emitcode("mov","b,a");
3773     lbl = newiTempLabel(NULL);
3774     emitcode("pop","acc");   
3775     /* if there was an over flow we don't 
3776     adjust the sign of the result */
3777     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3778     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3779     CLRC;
3780     emitcode("clr","a");
3781     emitcode("subb","a,b");
3782     emitcode("mov","b,a");
3783     emitcode("","%05d_DS_:",(lbl->key+100));
3784
3785     /* now we are done */
3786     aopPut(AOP(result),"b",0);
3787     if(size > 0){
3788         emitcode("mov","c,b.7");
3789         emitcode("subb","a,acc");   
3790     }
3791     while (size--)
3792         aopPut(AOP(result),"a",offset++);
3793
3794 }
3795
3796 /*-----------------------------------------------------------------*/
3797 /* genDiv - generates code for division                            */
3798 /*-----------------------------------------------------------------*/
3799 static void genDiv (iCode *ic)
3800 {
3801     operand *left = IC_LEFT(ic);
3802     operand *right = IC_RIGHT(ic);
3803     operand *result= IC_RESULT(ic);   
3804
3805     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3806     /* assign the amsops */
3807     aopOp (left,ic,FALSE);
3808     aopOp (right,ic,FALSE);
3809     aopOp (result,ic,TRUE);
3810
3811     /* special cases first */
3812     /* both are bits */
3813     if (AOP_TYPE(left) == AOP_CRY &&
3814         AOP_TYPE(right)== AOP_CRY) {
3815         genDivbits(left,right,result);
3816         goto release ;
3817     }
3818
3819     /* if both are of size == 1 */
3820     if (AOP_SIZE(left) == 1 &&
3821         AOP_SIZE(right) == 1 ) {
3822         genDivOneByte(left,right,result);
3823         goto release ;
3824     }
3825
3826     /* should have been converted to function call */
3827     assert(1);
3828 release :
3829     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3830     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3831     freeAsmop(result,NULL,ic,TRUE); 
3832 }
3833
3834 /*-----------------------------------------------------------------*/
3835 /* genModbits :- modulus of bits                                   */
3836 /*-----------------------------------------------------------------*/
3837 static void genModbits (operand *left, 
3838                         operand *right, 
3839                         operand *result)
3840 {
3841
3842     char *l;
3843
3844     /* the result must be bit */    
3845     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3846     l = aopGet(AOP(left),0,FALSE,FALSE);
3847
3848     MOVA(l);       
3849
3850     emitcode("div","ab");
3851     emitcode("mov","a,b");
3852     emitcode("rrc","a");
3853     aopPut(AOP(result),"c",0);
3854 }
3855
3856 /*-----------------------------------------------------------------*/
3857 /* genModOneByte : 8 bit modulus                                   */
3858 /*-----------------------------------------------------------------*/
3859 static void genModOneByte (operand *left,
3860                            operand *right,
3861                            operand *result)
3862 {
3863     sym_link *opetype = operandType(result);
3864     char *l ;
3865     symbol *lbl ;
3866
3867     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3868     /* signed or unsigned */
3869     if (SPEC_USIGN(opetype)) {
3870         /* unsigned is easy */
3871         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3872         l = aopGet(AOP(left),0,FALSE,FALSE);
3873         MOVA(l);    
3874         emitcode("div","ab");
3875         aopPut(AOP(result),"b",0);
3876         return ;
3877     }
3878
3879     /* signed is a little bit more difficult */
3880
3881     /* save the signs of the operands */
3882     l = aopGet(AOP(left),0,FALSE,FALSE);    
3883     MOVA(l);
3884
3885     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3886     emitcode("push","acc"); /* save it on the stack */
3887
3888     /* now sign adjust for both left & right */
3889     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3890     MOVA(l);
3891
3892     lbl = newiTempLabel(NULL);
3893     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3894     emitcode("cpl","a");   
3895     emitcode("inc","a");
3896     emitcode("","%05d_DS_:",(lbl->key+100));
3897     emitcode("mov","b,a"); 
3898
3899     /* sign adjust left side */
3900     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3901     MOVA(l);
3902
3903     lbl = newiTempLabel(NULL);
3904     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3905     emitcode("cpl","a");   
3906     emitcode("inc","a");
3907     emitcode("","%05d_DS_:",(lbl->key+100));
3908
3909     /* now the multiplication */
3910     emitcode("div","ab");
3911     /* we are interested in the lower order
3912     only */
3913     lbl = newiTempLabel(NULL);
3914     emitcode("pop","acc");   
3915     /* if there was an over flow we don't 
3916     adjust the sign of the result */
3917     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3918     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3919     CLRC ;
3920     emitcode("clr","a");
3921     emitcode("subb","a,b");
3922     emitcode("mov","b,a");
3923     emitcode("","%05d_DS_:",(lbl->key+100));
3924
3925     /* now we are done */
3926     aopPut(AOP(result),"b",0);
3927
3928 }
3929
3930 /*-----------------------------------------------------------------*/
3931 /* genMod - generates code for division                            */
3932 /*-----------------------------------------------------------------*/
3933 static void genMod (iCode *ic)
3934 {
3935     operand *left = IC_LEFT(ic);
3936     operand *right = IC_RIGHT(ic);
3937     operand *result= IC_RESULT(ic);  
3938
3939     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3940     /* assign the amsops */
3941     aopOp (left,ic,FALSE);
3942     aopOp (right,ic,FALSE);
3943     aopOp (result,ic,TRUE);
3944
3945     /* special cases first */
3946     /* both are bits */
3947     if (AOP_TYPE(left) == AOP_CRY &&
3948         AOP_TYPE(right)== AOP_CRY) {
3949         genModbits(left,right,result);
3950         goto release ;
3951     }
3952
3953     /* if both are of size == 1 */
3954     if (AOP_SIZE(left) == 1 &&
3955         AOP_SIZE(right) == 1 ) {
3956         genModOneByte(left,right,result);
3957         goto release ;
3958     }
3959
3960     /* should have been converted to function call */
3961     assert(1);
3962
3963 release :
3964     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3965     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966     freeAsmop(result,NULL,ic,TRUE); 
3967 }
3968
3969 /*-----------------------------------------------------------------*/
3970 /* genIfxJump :- will create a jump depending on the ifx           */
3971 /*-----------------------------------------------------------------*/
3972 static void genIfxJump (iCode *ic, char *jval)
3973 {
3974
3975     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3976     /* if true label then we jump if condition
3977     supplied is true */
3978     if ( IC_TRUE(ic) ) {
3979
3980         if(strcmp(jval,"a") == 0)
3981           emitSKPZ;
3982         else if (strcmp(jval,"c") == 0)
3983           emitSKPC;
3984         else {
3985           //pCodeOp *p = popGetWithString(jval);
3986           //p->type = PO_BIT;
3987           //emitpcode(POC_BTFSC,  p);
3988           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,0));
3989         //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3990         }
3991
3992         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3993         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3994
3995     }
3996     else {
3997         /* false label is present */
3998         if(strcmp(jval,"a") == 0)
3999           emitSKPNZ;
4000         else if (strcmp(jval,"c") == 0)
4001           emitSKPNC;
4002         else {
4003           //pCodeOp *p = popGetWithString(jval);
4004           //p->type = PO_BIT;
4005           //emitpcode(POC_BTFSS,  p);
4006           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,0));
4007
4008         //        emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4009         }
4010
4011         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4012         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4013
4014     }
4015
4016
4017     /* mark the icode as generated */
4018     ic->generated = 1;
4019 }
4020
4021 /*-----------------------------------------------------------------*/
4022 /* genSkip                                                         */
4023 /*-----------------------------------------------------------------*/
4024 static void genSkip(iCode *ifx,int status_bit)
4025 {
4026   if(!ifx)
4027     return;
4028
4029   if ( IC_TRUE(ifx) ) {
4030     switch(status_bit) {
4031     case 'z':
4032       emitSKPNZ;
4033       break;
4034
4035     case 'c':
4036       emitSKPNC;
4037       break;
4038
4039     case 'd':
4040       emitcode("skpndc","");
4041       break;
4042
4043     }
4044
4045     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4046     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4047
4048   } else {
4049
4050     switch(status_bit) {
4051
4052     case 'z':
4053       emitSKPZ;
4054       break;
4055
4056     case 'c':
4057       emitSKPC;
4058       break;
4059
4060     case 'd':
4061       emitcode("skpdc","");
4062       break;
4063     }
4064     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4065     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4066
4067   }
4068
4069 }
4070
4071 /*-----------------------------------------------------------------*/
4072 /* genSkipc                                                        */
4073 /*-----------------------------------------------------------------*/
4074 static void genSkipc(iCode *ifx, int condition)
4075 {
4076   if(!ifx)
4077     return;
4078
4079   if(condition)
4080     emitSKPNC;
4081   else
4082     emitSKPC;
4083
4084   if ( IC_TRUE(ifx) )
4085     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4086   else
4087     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4088
4089   if ( IC_TRUE(ifx) )
4090     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4091   else
4092     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4093
4094 }
4095
4096 /*-----------------------------------------------------------------*/
4097 /* genSkipz                                                        */
4098 /*-----------------------------------------------------------------*/
4099 static void genSkipz(iCode *ifx, int condition)
4100 {
4101   if(!ifx)
4102     return;
4103
4104   if(condition)
4105     emitSKPNZ;
4106   else
4107     emitSKPZ;
4108
4109   if ( IC_TRUE(ifx) )
4110     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4111   else
4112     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4113
4114   if ( IC_TRUE(ifx) )
4115     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4116   else
4117     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4118
4119 }
4120 /*-----------------------------------------------------------------*/
4121 /* genCmp :- greater or less than comparison                       */
4122 /*-----------------------------------------------------------------*/
4123 static void genCmp (operand *left,operand *right,
4124                     operand *result, iCode *ifx, int sign)
4125 {
4126   int size, offset = 0 ;
4127   unsigned long lit = 0L,i = 0;
4128
4129   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4130   /* if left & right are bit variables */
4131   if (AOP_TYPE(left) == AOP_CRY &&
4132       AOP_TYPE(right) == AOP_CRY ) {
4133     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4134     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4135   } else {
4136     /* subtract right from left if at the
4137        end the carry flag is set then we know that
4138        left is greater than right */
4139     size = max(AOP_SIZE(left),AOP_SIZE(right));
4140
4141     /* if unsigned char cmp with lit, do cjne left,#right,zz */
4142     if((size == 1) && !sign &&
4143        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4144       symbol *lbl  = newiTempLabel(NULL);
4145       emitcode("cjne","%s,%s,%05d_DS_",
4146                aopGet(AOP(left),offset,FALSE,FALSE),
4147                aopGet(AOP(right),offset,FALSE,FALSE),
4148                lbl->key+100);
4149       emitcode("","%05d_DS_:",lbl->key+100);
4150     } else {
4151
4152       if(AOP_TYPE(right) == AOP_LIT) {
4153
4154         DEBUGemitcode(";right lit","%d",sign);
4155
4156         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4157         //default:
4158         while(size--) {
4159           i = (lit >> (size*8)) & 0xff;
4160           if(i == 0) {
4161             emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4162             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4163             genSkipz(ifx,IC_TRUE(ifx) == NULL);
4164           } else {
4165             emitpcode(POC_MOVLW, popGetLit(i));
4166             emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4167
4168             emitcode("movlw","0x%x",i);
4169             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4170             genSkipc(ifx,IC_TRUE(ifx) == NULL);
4171           }
4172
4173         }
4174         ifx->generated = 1;
4175         return;
4176       }
4177       if(AOP_TYPE(left) == AOP_LIT) {
4178
4179         DEBUGemitcode(";left lit","%d",sign);
4180
4181         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4182
4183         //default:
4184         while(size--) {
4185           i = (lit >> (size*8)) & 0xff;
4186           if(i == 0) {
4187             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4188             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4189             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4190           } else if( i == 1 ) {
4191             emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4192             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4193             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4194
4195           } else {
4196             emitpcode(POC_MOVLW, popGetLit(i));
4197             emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4198
4199             emitcode("movlw","0x%x",i);
4200             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4201             genSkipc(ifx,IC_TRUE(ifx) != NULL);
4202           }
4203         }
4204         ifx->generated = 1;
4205         return;
4206       }
4207
4208
4209       // CLRC;
4210       DEBUGemitcode(";sign","%d",sign);
4211
4212       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4213       emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4214
4215       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4216       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4217
4218       size--;
4219       while (size--) {
4220
4221         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
4222         emitSKPC;
4223         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4224         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
4225
4226 /*
4227         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4228         emitSKPC;
4229         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4230         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4231 */
4232         offset++;
4233       }
4234     }
4235   }
4236
4237   //release:
4238   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4239     outBitC(result);
4240   } else {
4241     /* if the result is used in the next
4242        ifx conditional branch then generate
4243        code a little differently */
4244     if (ifx )
4245       genIfxJump (ifx,"c");
4246     else
4247       outBitC(result);
4248     /* leave the result in acc */
4249   }
4250
4251 }
4252
4253 /*-----------------------------------------------------------------*/
4254 /* genCmpGt :- greater than comparison                             */
4255 /*-----------------------------------------------------------------*/
4256 static void genCmpGt (iCode *ic, iCode *ifx)
4257 {
4258     operand *left, *right, *result;
4259     sym_link *letype , *retype;
4260     int sign ;
4261
4262     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4263     left = IC_LEFT(ic);
4264     right= IC_RIGHT(ic);
4265     result = IC_RESULT(ic);
4266
4267     letype = getSpec(operandType(left));
4268     retype =getSpec(operandType(right));
4269     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4270     /* assign the amsops */
4271     aopOp (left,ic,FALSE);
4272     aopOp (right,ic,FALSE);
4273     aopOp (result,ic,TRUE);
4274
4275     genCmp(right, left, result, ifx, sign);
4276
4277     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4279     freeAsmop(result,NULL,ic,TRUE); 
4280 }
4281
4282 /*-----------------------------------------------------------------*/
4283 /* genCmpLt - less than comparisons                                */
4284 /*-----------------------------------------------------------------*/
4285 static void genCmpLt (iCode *ic, iCode *ifx)
4286 {
4287     operand *left, *right, *result;
4288     sym_link *letype , *retype;
4289     int sign ;
4290
4291     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4292     left = IC_LEFT(ic);
4293     right= IC_RIGHT(ic);
4294     result = IC_RESULT(ic);
4295
4296     letype = getSpec(operandType(left));
4297     retype =getSpec(operandType(right));
4298     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4299
4300     /* assign the amsops */
4301     aopOp (left,ic,FALSE);
4302     aopOp (right,ic,FALSE);
4303     aopOp (result,ic,TRUE);
4304
4305     genCmp(left, right, result, ifx, sign);
4306
4307     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4308     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4309     freeAsmop(result,NULL,ic,TRUE); 
4310 }
4311
4312 /*-----------------------------------------------------------------*/
4313 /* gencjneshort - compare and jump if not equal                    */
4314 /*-----------------------------------------------------------------*/
4315 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4316 {
4317     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4318     int offset = 0;
4319     unsigned long lit = 0L;
4320
4321     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4322     /* if the left side is a literal or 
4323     if the right is in a pointer register and left 
4324     is not */
4325     if ((AOP_TYPE(left) == AOP_LIT) || 
4326         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4327         operand *t = right;
4328         right = left;
4329         left = t;
4330     }
4331     if(AOP_TYPE(right) == AOP_LIT)
4332         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4333
4334     /* if the right side is a literal then anything goes */
4335     if (AOP_TYPE(right) == AOP_LIT &&
4336         AOP_TYPE(left) != AOP_DIR ) {
4337         while (size--) {
4338           if(lit & 0xff) {
4339             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4340             emitcode("xorlw","0x%x",lit & 0xff);
4341           } else
4342             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4343
4344           emitSKPNZ;
4345           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4346           offset++;
4347           lit >>= 8;
4348         }
4349     }
4350
4351     /* if the right side is in a register or in direct space or
4352     if the left is a pointer register & right is not */    
4353     else if (AOP_TYPE(right) == AOP_REG ||
4354              AOP_TYPE(right) == AOP_DIR || 
4355              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4356              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4357         while (size--) {
4358           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4359              ( (lit & 0xff) != 0)) {
4360             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4361             emitcode("xorlw","0x%x",lit & 0xff);
4362             lit >>= 8;
4363           } else
4364             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4365
4366           emitSKPZ;
4367           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4368           offset++;
4369 /*
4370             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4371             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4372                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4373                 emitcode("jnz","%05d_DS_",lbl->key+100);
4374             else
4375                 emitcode("cjne","a,%s,%05d_DS_",
4376                          aopGet(AOP(right),offset,FALSE,TRUE),
4377                          lbl->key+100);
4378             offset++;
4379 */
4380         }
4381     } else {
4382         /* right is a pointer reg need both a & b */
4383         while(size--) {
4384             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4385             if(strcmp(l,"b"))
4386                 emitcode("mov","b,%s",l);
4387             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4388             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4389             offset++;
4390         }
4391     }
4392 }
4393
4394 /*-----------------------------------------------------------------*/
4395 /* gencjne - compare and jump if not equal                         */
4396 /*-----------------------------------------------------------------*/
4397 static void gencjne(operand *left, operand *right, symbol *lbl)
4398 {
4399     symbol *tlbl  = newiTempLabel(NULL);
4400
4401     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4402     gencjneshort(left, right, lbl);
4403
4404     emitcode("mov","a,%s",one);
4405     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4406     emitcode("","%05d_DS_:",lbl->key+100);
4407     emitcode("clr","a");
4408     emitcode("","%05d_DS_:",tlbl->key+100);
4409 }
4410
4411
4412 /*-----------------------------------------------------------------*/
4413 /* genCmpEq - generates code for equal to                          */
4414 /*-----------------------------------------------------------------*/
4415 static void genCmpEq (iCode *ic, iCode *ifx)
4416 {
4417     operand *left, *right, *result;
4418     unsigned long lit = 0L;
4419     int size,offset=0;
4420
4421     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4422     if(ifx)
4423       DEBUGemitcode ("; ifx is non-null","");
4424     else
4425       DEBUGemitcode ("; ifx is null","");
4426
4427     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4428     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4429     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4430
4431     size = max(AOP_SIZE(left),AOP_SIZE(right));
4432
4433     /* if literal, literal on the right or 
4434     if the right is in a pointer register and left 
4435     is not */
4436     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4437         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4438         operand *t = IC_RIGHT(ic);
4439         IC_RIGHT(ic) = IC_LEFT(ic);
4440         IC_LEFT(ic) = t;
4441     }
4442
4443     if(ifx && !AOP_SIZE(result)){
4444         symbol *tlbl;
4445         /* if they are both bit variables */
4446         if (AOP_TYPE(left) == AOP_CRY &&
4447             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4448             if(AOP_TYPE(right) == AOP_LIT){
4449                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4450                 if(lit == 0L){
4451                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4452                     emitcode("cpl","c");
4453                 } else if(lit == 1L) {
4454                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4455                 } else {
4456                     emitcode("clr","c");
4457                 }
4458                 /* AOP_TYPE(right) == AOP_CRY */
4459             } else {
4460                 symbol *lbl = newiTempLabel(NULL);
4461                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4462                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4463                 emitcode("cpl","c");
4464                 emitcode("","%05d_DS_:",(lbl->key+100));
4465             }
4466             /* if true label then we jump if condition
4467             supplied is true */
4468             tlbl = newiTempLabel(NULL);
4469             if ( IC_TRUE(ifx) ) {
4470                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4471                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4472             } else {
4473                 emitcode("jc","%05d_DS_",tlbl->key+100);
4474                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4475             }
4476             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4477         } else {
4478
4479           /* They're not both bit variables. Is the right a literal? */
4480           if(AOP_TYPE(right) == AOP_LIT) {
4481
4482             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4483             while (size--) {
4484
4485               if(size >= 1) {
4486                 int l = lit & 0xff;
4487                 int h = (lit>>8) & 0xff;
4488                 int optimized=0;
4489
4490                 /* Check special cases for integers */
4491                 switch(lit & 0xffff) {
4492                 case 0x0000:
4493                   emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4494                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4495                   //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4496                   //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4497                   genSkip(ifx,'z');
4498                   optimized++;
4499                   break;
4500                 case 0x0001:
4501                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4502                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4503                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4504                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4505                   genSkip(ifx,'z');
4506                   optimized++;
4507                   break;
4508                 case 0x0100:
4509                   emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4510                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4511                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4512                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4513                   genSkip(ifx,'z');
4514                   optimized++;
4515                   break;
4516                 case 0x00ff:
4517                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4518                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4519                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4520                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4521                   genSkip(ifx,'z');
4522                   optimized++;
4523                   break;
4524                 case 0xff00:
4525                   emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4526                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4527                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4528                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4529                   genSkip(ifx,'z');
4530                   optimized++;
4531                   break;
4532                 default:
4533                   if(h == 0) {
4534                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4535                     emitpcode(POC_XORLW,popGetLit(l));
4536                     emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4537
4538                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4539                     emitcode("xorlw","0x%x",l);
4540                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4541                     optimized++;
4542                     genSkip(ifx,'z');
4543                   } else if (l == 0) {
4544                     emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4545                     emitpcode(POC_XORLW,popGetLit(h));
4546                     emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4547
4548                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4549                     emitcode("xorlw","0x%x",h);
4550                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4551                     optimized++;
4552                     genSkip(ifx,'z');
4553                   } else {
4554                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4555                     emitpcode(POC_XORLW,popGetLit(l));
4556                     emitpcode(POC_MOVLW,popGetLit(h));
4557                     emitSKPZ;
4558                     emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4559 /*
4560                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4561                     emitcode("xorlw","0x%x",l);
4562                     emitcode("movlw","0x%x",h);
4563                     emitSKPZ;
4564                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4565 */
4566                     optimized++;
4567                     genSkip(ifx,'z');
4568                   }
4569
4570                 }
4571                 if(optimized) {
4572                   size--;
4573                   offset+=2;
4574                   lit>>=16;
4575
4576                   continue;
4577                 }
4578                   
4579               }
4580                 
4581               switch(lit & 0xff) {
4582               case 1:
4583                 if ( IC_TRUE(ifx) ) {
4584
4585                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4586
4587                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4588                   emitSKPNZ;
4589                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4590
4591                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4592                 } else {
4593                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4594                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4595
4596                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4597                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4598                 }
4599                 break;
4600               case 0xff:
4601                 if ( IC_TRUE(ifx) ) {
4602                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4603
4604                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4605                   emitSKPNZ;
4606                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4607
4608                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4609                 } else {
4610                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4611                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4612
4613                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4614                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4615                 }
4616                 break;
4617               default:
4618                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4619                 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4620                 if(lit)
4621                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4622                 //emitcode("xorlw","0x%x",lit & 0xff);
4623                 genSkip(ifx,'z');
4624               }
4625
4626
4627               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4628               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4629               offset++;
4630               lit >>= 8;
4631             }
4632
4633           } else if(AOP_TYPE(right) == AOP_CRY ) {
4634             /* we know the left is not a bit, but that the right is */
4635             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4636             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4637                       popGet(AOP(right),offset,FALSE,FALSE));
4638             emitpcode(POC_XORLW,popGetLit(1));
4639
4640             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4641             if ( IC_TRUE(ifx) )
4642               emitcode("btfsc","(%s >> 3), (%s & 7)",
4643                        AOP(right)->aopu.aop_dir,
4644                        AOP(right)->aopu.aop_dir);
4645             else
4646               emitcode("btfss","(%s >> 3), (%s & 7)",
4647                        AOP(right)->aopu.aop_dir,
4648                        AOP(right)->aopu.aop_dir);
4649
4650             emitcode("xorlw","1");
4651
4652             /* if the two are equal, then W will be 0 and the Z bit is set
4653              * we could test Z now, or go ahead and check the high order bytes if
4654              * the variable we're comparing is larger than a byte. */
4655
4656             while(--size)
4657               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4658             //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4659
4660             if ( IC_TRUE(ifx) ) {
4661               emitSKPNZ;
4662               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4663               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4664             } else {
4665               emitSKPZ;
4666               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4667               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4668             }
4669
4670           } else {
4671             /* They're both variables that are larger than bits */
4672             int s = size;
4673
4674             tlbl = newiTempLabel(NULL);
4675
4676             while(size--) {
4677               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4678               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4679
4680               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4681               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4682
4683               if ( IC_TRUE(ifx) ) {
4684                 if(size) {
4685                   emitSKPZ;
4686                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4687                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4688                 } else {
4689                   emitSKPNZ;
4690                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4691                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4692                 }
4693               } else {
4694                 emitSKPZ;
4695                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4696                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4697               }
4698               offset++;
4699             }
4700             if(s>1 && IC_TRUE(ifx)) {
4701               emitpLabel(tlbl->key+100+labelOffset);
4702               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4703             }
4704           }
4705         }
4706         /* mark the icode as generated */
4707         ifx->generated = 1;
4708         goto release ;
4709     }
4710
4711     /* if they are both bit variables */
4712     if (AOP_TYPE(left) == AOP_CRY &&
4713         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4714         if(AOP_TYPE(right) == AOP_LIT){
4715             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4716             if(lit == 0L){
4717                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4718                 emitcode("cpl","c");
4719             } else if(lit == 1L) {
4720                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4721             } else {
4722                 emitcode("clr","c");
4723             }
4724             /* AOP_TYPE(right) == AOP_CRY */
4725         } else {
4726             symbol *lbl = newiTempLabel(NULL);
4727             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4728             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4729             emitcode("cpl","c");
4730             emitcode("","%05d_DS_:",(lbl->key+100));
4731         }
4732         /* c = 1 if egal */
4733         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4734             outBitC(result);
4735             goto release ;
4736         }
4737         if (ifx) {
4738             genIfxJump (ifx,"c");
4739             goto release ;
4740         }
4741         /* if the result is used in an arithmetic operation
4742         then put the result in place */
4743         outBitC(result);
4744     } else {
4745         gencjne(left,right,newiTempLabel(NULL));    
4746         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4747             aopPut(AOP(result),"a",0);
4748             goto release ;
4749         }
4750         if (ifx) {
4751             genIfxJump (ifx,"a");
4752             goto release ;
4753         }
4754         /* if the result is used in an arithmetic operation
4755         then put the result in place */
4756         if (AOP_TYPE(result) != AOP_CRY) 
4757             outAcc(result);
4758         /* leave the result in acc */
4759     }
4760
4761 release:
4762     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4763     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4764     freeAsmop(result,NULL,ic,TRUE);
4765 }
4766
4767 /*-----------------------------------------------------------------*/
4768 /* ifxForOp - returns the icode containing the ifx for operand     */
4769 /*-----------------------------------------------------------------*/
4770 static iCode *ifxForOp ( operand *op, iCode *ic )
4771 {
4772     /* if true symbol then needs to be assigned */
4773     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4774     if (IS_TRUE_SYMOP(op))
4775         return NULL ;
4776
4777     /* if this has register type condition and
4778     the next instruction is ifx with the same operand
4779     and live to of the operand is upto the ifx only then */
4780     if (ic->next &&
4781         ic->next->op == IFX &&
4782         IC_COND(ic->next)->key == op->key &&
4783         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4784         return ic->next;
4785
4786     return NULL;
4787 }
4788 /*-----------------------------------------------------------------*/
4789 /* genAndOp - for && operation                                     */
4790 /*-----------------------------------------------------------------*/
4791 static void genAndOp (iCode *ic)
4792 {
4793     operand *left,*right, *result;
4794     symbol *tlbl;
4795
4796     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4797     /* note here that && operations that are in an
4798     if statement are taken away by backPatchLabels
4799     only those used in arthmetic operations remain */
4800     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4801     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4802     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4803
4804     /* if both are bit variables */
4805     if (AOP_TYPE(left) == AOP_CRY &&
4806         AOP_TYPE(right) == AOP_CRY ) {
4807         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4808         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4809         outBitC(result);
4810     } else {
4811         tlbl = newiTempLabel(NULL);
4812         toBoolean(left);    
4813         emitcode("jz","%05d_DS_",tlbl->key+100);
4814         toBoolean(right);
4815         emitcode("","%05d_DS_:",tlbl->key+100);
4816         outBitAcc(result);
4817     }
4818
4819     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4820     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4821     freeAsmop(result,NULL,ic,TRUE);
4822 }
4823
4824
4825 /*-----------------------------------------------------------------*/
4826 /* genOrOp - for || operation                                      */
4827 /*-----------------------------------------------------------------*/
4828 /*
4829   tsd pic port -
4830   modified this code, but it doesn't appear to ever get called
4831 */
4832
4833 static void genOrOp (iCode *ic)
4834 {
4835     operand *left,*right, *result;
4836     symbol *tlbl;
4837
4838     /* note here that || operations that are in an
4839     if statement are taken away by backPatchLabels
4840     only those used in arthmetic operations remain */
4841     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4842     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4843     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4844     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4845
4846     /* if both are bit variables */
4847     if (AOP_TYPE(left) == AOP_CRY &&
4848         AOP_TYPE(right) == AOP_CRY ) {
4849       emitcode("clrc","");
4850       emitcode("btfss","(%s >> 3), (%s & 7)",
4851                AOP(left)->aopu.aop_dir,
4852                AOP(left)->aopu.aop_dir);
4853       emitcode("btfsc","(%s >> 3), (%s & 7)",
4854                AOP(right)->aopu.aop_dir,
4855                AOP(right)->aopu.aop_dir);
4856       emitcode("setc","");
4857
4858     } else {
4859         tlbl = newiTempLabel(NULL);
4860         toBoolean(left);
4861         emitSKPZ;
4862         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4863         toBoolean(right);
4864         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4865
4866         outBitAcc(result);
4867     }
4868
4869     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4870     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4871     freeAsmop(result,NULL,ic,TRUE);            
4872 }
4873
4874 /*-----------------------------------------------------------------*/
4875 /* isLiteralBit - test if lit == 2^n                               */
4876 /*-----------------------------------------------------------------*/
4877 static int isLiteralBit(unsigned long lit)
4878 {
4879     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4880     0x100L,0x200L,0x400L,0x800L,
4881     0x1000L,0x2000L,0x4000L,0x8000L,
4882     0x10000L,0x20000L,0x40000L,0x80000L,
4883     0x100000L,0x200000L,0x400000L,0x800000L,
4884     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4885     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4886     int idx;
4887     
4888     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4889     for(idx = 0; idx < 32; idx++)
4890         if(lit == pw[idx])
4891             return idx+1;
4892     return 0;
4893 }
4894
4895 /*-----------------------------------------------------------------*/
4896 /* continueIfTrue -                                                */
4897 /*-----------------------------------------------------------------*/
4898 static void continueIfTrue (iCode *ic)
4899 {
4900     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4901     if(IC_TRUE(ic))
4902         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4903     ic->generated = 1;
4904 }
4905
4906 /*-----------------------------------------------------------------*/
4907 /* jmpIfTrue -                                                     */
4908 /*-----------------------------------------------------------------*/
4909 static void jumpIfTrue (iCode *ic)
4910 {
4911     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4912     if(!IC_TRUE(ic))
4913         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4914     ic->generated = 1;
4915 }
4916
4917 /*-----------------------------------------------------------------*/
4918 /* jmpTrueOrFalse -                                                */
4919 /*-----------------------------------------------------------------*/
4920 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4921 {
4922     // ugly but optimized by peephole
4923     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4924     if(IC_TRUE(ic)){
4925         symbol *nlbl = newiTempLabel(NULL);
4926         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4927         emitcode("","%05d_DS_:",tlbl->key+100);
4928         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4929         emitcode("","%05d_DS_:",nlbl->key+100);
4930     }
4931     else{
4932         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4933         emitcode("","%05d_DS_:",tlbl->key+100);
4934     }
4935     ic->generated = 1;
4936 }
4937
4938 /*-----------------------------------------------------------------*/
4939 /* genAnd  - code for and                                          */
4940 /*-----------------------------------------------------------------*/
4941 static void genAnd (iCode *ic, iCode *ifx)
4942 {
4943     operand *left, *right, *result;
4944     int size, offset=0;  
4945     unsigned long lit = 0L;
4946     int bytelit = 0;
4947     char buffer[10];
4948
4949     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4950     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4951     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4952     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4953
4954 #ifdef DEBUG_TYPE
4955     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4956              AOP_TYPE(result),
4957              AOP_TYPE(left), AOP_TYPE(right));
4958     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4959              AOP_SIZE(result),
4960              AOP_SIZE(left), AOP_SIZE(right));
4961 #endif
4962
4963     /* if left is a literal & right is not then exchange them */
4964     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4965         AOP_NEEDSACC(left)) {
4966         operand *tmp = right ;
4967         right = left;
4968         left = tmp;
4969     }
4970
4971     /* if result = right then exchange them */
4972     if(sameRegs(AOP(result),AOP(right))){
4973         operand *tmp = right ;
4974         right = left;
4975         left = tmp;
4976     }
4977
4978     /* if right is bit then exchange them */
4979     if (AOP_TYPE(right) == AOP_CRY &&
4980         AOP_TYPE(left) != AOP_CRY){
4981         operand *tmp = right ;
4982         right = left;
4983         left = tmp;
4984     }
4985     if(AOP_TYPE(right) == AOP_LIT)
4986         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4987
4988     size = AOP_SIZE(result);
4989
4990     // if(bit & yy)
4991     // result = bit & yy;
4992     if (AOP_TYPE(left) == AOP_CRY){
4993         // c = bit & literal;
4994         if(AOP_TYPE(right) == AOP_LIT){
4995             if(lit & 1) {
4996                 if(size && sameRegs(AOP(result),AOP(left)))
4997                     // no change
4998                     goto release;
4999                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5000             } else {
5001                 // bit(result) = 0;
5002                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5003                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5004                     goto release;
5005                 }
5006                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5007                     jumpIfTrue(ifx);
5008                     goto release;
5009                 }
5010                 emitcode("clr","c");
5011             }
5012         } else {
5013             if (AOP_TYPE(right) == AOP_CRY){
5014                 // c = bit & bit;
5015                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5016                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5017             } else {
5018                 // c = bit & val;
5019                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5020                 // c = lsb
5021                 emitcode("rrc","a");
5022                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5023             }
5024         }
5025         // bit = c
5026         // val = c
5027         if(size)
5028             outBitC(result);
5029         // if(bit & ...)
5030         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5031             genIfxJump(ifx, "c");           
5032         goto release ;
5033     }
5034
5035     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5036     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5037     if((AOP_TYPE(right) == AOP_LIT) &&
5038        (AOP_TYPE(result) == AOP_CRY) &&
5039        (AOP_TYPE(left) != AOP_CRY)){
5040         int posbit = isLiteralBit(lit);
5041         /* left &  2^n */
5042         if(posbit){
5043             posbit--;
5044             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5045             // bit = left & 2^n
5046             if(size)
5047                 emitcode("mov","c,acc.%d",posbit&0x07);
5048             // if(left &  2^n)
5049             else{
5050                 if(ifx){
5051                     sprintf(buffer,"acc.%d",posbit&0x07);
5052                     genIfxJump(ifx, buffer);
5053                 }
5054                 goto release;
5055             }
5056         } else {
5057             symbol *tlbl = newiTempLabel(NULL);
5058             int sizel = AOP_SIZE(left);
5059             if(size)
5060                 emitcode("setb","c");
5061             while(sizel--){
5062                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5063                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5064                     // byte ==  2^n ?
5065                     if((posbit = isLiteralBit(bytelit)) != 0)
5066                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5067                     else{
5068                         if(bytelit != 0x0FFL)
5069                             emitcode("anl","a,%s",
5070                                      aopGet(AOP(right),offset,FALSE,TRUE));
5071                         emitcode("jnz","%05d_DS_",tlbl->key+100);
5072                     }
5073                 }
5074                 offset++;
5075             }
5076             // bit = left & literal
5077             if(size){
5078                 emitcode("clr","c");
5079                 emitcode("","%05d_DS_:",tlbl->key+100);
5080             }
5081             // if(left & literal)
5082             else{
5083                 if(ifx)
5084                     jmpTrueOrFalse(ifx, tlbl);
5085                 goto release ;
5086             }
5087         }
5088         outBitC(result);
5089         goto release ;
5090     }
5091
5092     /* if left is same as result */
5093     if(sameRegs(AOP(result),AOP(left))){
5094       for(;size--; offset++,lit>>=8) {
5095         if(AOP_TYPE(right) == AOP_LIT){
5096           switch(lit & 0xff) {
5097           case 0x00:
5098             /*  and'ing with 0 has clears the result */
5099             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5100             break;
5101           case 0xff:
5102             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5103             break;
5104
5105           default:
5106             {
5107               int p = my_powof2( (~lit) & 0xff );
5108               if(p>=0) {
5109                 /* only one bit is set in the literal, so use a bcf instruction */
5110                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5111               } else {
5112                 emitcode("movlw","0x%x", (lit & 0xff));
5113                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5114               }
5115             }    
5116           }
5117         } else {
5118           if (AOP_TYPE(left) == AOP_ACC) 
5119             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5120           else {                    
5121             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5122             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5123
5124           }
5125         }
5126       }
5127
5128     } else {
5129         // left & result in different registers
5130         if(AOP_TYPE(result) == AOP_CRY){
5131             // result = bit
5132             // if(size), result in bit
5133             // if(!size && ifx), conditional oper: if(left & right)
5134             symbol *tlbl = newiTempLabel(NULL);
5135             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5136             if(size)
5137                 emitcode("setb","c");
5138             while(sizer--){
5139                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5140                 emitcode("anl","a,%s",
5141                          aopGet(AOP(left),offset,FALSE,FALSE));
5142                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5143                 offset++;
5144             }
5145             if(size){
5146                 CLRC;
5147                 emitcode("","%05d_DS_:",tlbl->key+100);
5148                 outBitC(result);
5149             } else if(ifx)
5150                 jmpTrueOrFalse(ifx, tlbl);
5151         } else {
5152           for(;(size--);offset++) {
5153             // normal case
5154             // result = left & right
5155             if(AOP_TYPE(right) == AOP_LIT){
5156               int t = (lit >> (offset*8)) & 0x0FFL;
5157               switch(t) { 
5158               case 0x00:
5159                 emitcode("clrf","%s",
5160                          aopGet(AOP(result),offset,FALSE,FALSE));
5161                 break;
5162               case 0xff:
5163                 emitcode("movf","%s,w",
5164                          aopGet(AOP(left),offset,FALSE,FALSE));
5165                 emitcode("movwf","%s",
5166                          aopGet(AOP(result),offset,FALSE,FALSE));
5167                 break;
5168               default:
5169                 emitcode("movlw","0x%x",t);
5170                 emitcode("andwf","%s,w",
5171                          aopGet(AOP(left),offset,FALSE,FALSE));
5172                 emitcode("movwf","%s",
5173                          aopGet(AOP(result),offset,FALSE,FALSE));
5174               
5175               }
5176               continue;
5177             }
5178
5179             if (AOP_TYPE(left) == AOP_ACC) 
5180               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5181             else {
5182               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5183               emitcode("andwf","%s,w",
5184                        aopGet(AOP(left),offset,FALSE,FALSE));
5185             }
5186             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5187           }
5188         }
5189     }
5190
5191 release :
5192     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5193     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5194     freeAsmop(result,NULL,ic,TRUE);     
5195 }
5196
5197 /*-----------------------------------------------------------------*/
5198 /* genOr  - code for or                                            */
5199 /*-----------------------------------------------------------------*/
5200 static void genOr (iCode *ic, iCode *ifx)
5201 {
5202     operand *left, *right, *result;
5203     int size, offset=0;
5204     unsigned long lit = 0L;
5205
5206     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5207
5208     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5209     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5210     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5211
5212
5213     /* if left is a literal & right is not then exchange them */
5214     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5215         AOP_NEEDSACC(left)) {
5216         operand *tmp = right ;
5217         right = left;
5218         left = tmp;
5219     }
5220
5221     /* if result = right then exchange them */
5222     if(sameRegs(AOP(result),AOP(right))){
5223         operand *tmp = right ;
5224         right = left;
5225         left = tmp;
5226     }
5227
5228     /* if right is bit then exchange them */
5229     if (AOP_TYPE(right) == AOP_CRY &&
5230         AOP_TYPE(left) != AOP_CRY){
5231         operand *tmp = right ;
5232         right = left;
5233         left = tmp;
5234     }
5235
5236     if(AOP_TYPE(right) == AOP_LIT)
5237         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5238
5239     size = AOP_SIZE(result);
5240
5241     // if(bit | yy)
5242     // xx = bit | yy;
5243     if (AOP_TYPE(left) == AOP_CRY){
5244         if(AOP_TYPE(right) == AOP_LIT){
5245             // c = bit & literal;
5246             if(lit){
5247                 // lit != 0 => result = 1
5248                 if(AOP_TYPE(result) == AOP_CRY){
5249                   if(size)
5250                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5251                   //emitcode("bsf","(%s >> 3), (%s & 7)",
5252                   //     AOP(result)->aopu.aop_dir,
5253                   //     AOP(result)->aopu.aop_dir);
5254                     else if(ifx)
5255                         continueIfTrue(ifx);
5256                     goto release;
5257                 }
5258             } else {
5259                 // lit == 0 => result = left
5260                 if(size && sameRegs(AOP(result),AOP(left)))
5261                     goto release;
5262                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5263             }
5264         } else {
5265             if (AOP_TYPE(right) == AOP_CRY){
5266               if(sameRegs(AOP(result),AOP(left))){
5267                 // c = bit | bit;
5268                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5269                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5270                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5271
5272                 emitcode("bcf","(%s >> 3), (%s & 7)",
5273                          AOP(result)->aopu.aop_dir,
5274                          AOP(result)->aopu.aop_dir);
5275                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5276                          AOP(right)->aopu.aop_dir,
5277                          AOP(right)->aopu.aop_dir);
5278                 emitcode("bsf","(%s >> 3), (%s & 7)",
5279                          AOP(result)->aopu.aop_dir,
5280                          AOP(result)->aopu.aop_dir);
5281               } else {
5282
5283                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5284                 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5285                 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5286                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5287
5288                 emitcode("bcf","(%s >> 3), (%s & 7)",
5289                          AOP(result)->aopu.aop_dir,
5290                          AOP(result)->aopu.aop_dir);
5291                 emitcode("btfss","(%s >> 3), (%s & 7)",
5292                          AOP(right)->aopu.aop_dir,
5293                          AOP(right)->aopu.aop_dir);
5294                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5295                          AOP(left)->aopu.aop_dir,
5296                          AOP(left)->aopu.aop_dir);
5297                 emitcode("bsf","(%s >> 3), (%s & 7)",
5298                          AOP(result)->aopu.aop_dir,
5299                          AOP(result)->aopu.aop_dir);
5300               }
5301             }
5302             else{
5303                 // c = bit | val;
5304                 symbol *tlbl = newiTempLabel(NULL);
5305                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5306                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5307                     emitcode(";XXX setb","c");
5308                 emitcode(";XXX jb","%s,%05d_DS_",
5309                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5310                 toBoolean(right);
5311                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5312                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5313                     jmpTrueOrFalse(ifx, tlbl);
5314                     goto release;
5315                 } else {
5316                     CLRC;
5317                     emitcode("","%05d_DS_:",tlbl->key+100);
5318                 }
5319             }
5320         }
5321         // bit = c
5322         // val = c
5323         if(size)
5324             outBitC(result);
5325         // if(bit | ...)
5326         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5327             genIfxJump(ifx, "c");           
5328         goto release ;
5329     }
5330
5331     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5332     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5333     if((AOP_TYPE(right) == AOP_LIT) &&
5334        (AOP_TYPE(result) == AOP_CRY) &&
5335        (AOP_TYPE(left) != AOP_CRY)){
5336         if(lit){
5337           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5338             // result = 1
5339             if(size)
5340                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5341             else 
5342                 continueIfTrue(ifx);
5343             goto release;
5344         } else {
5345           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5346             // lit = 0, result = boolean(left)
5347             if(size)
5348                 emitcode(";XXX setb","c");
5349             toBoolean(right);
5350             if(size){
5351                 symbol *tlbl = newiTempLabel(NULL);
5352                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5353                 CLRC;
5354                 emitcode("","%05d_DS_:",tlbl->key+100);
5355             } else {
5356                 genIfxJump (ifx,"a");
5357                 goto release;
5358             }
5359         }
5360         outBitC(result);
5361         goto release ;
5362     }
5363
5364     /* if left is same as result */
5365     if(sameRegs(AOP(result),AOP(left))){
5366       for(;size--; offset++,lit>>=8) {
5367         if(AOP_TYPE(right) == AOP_LIT){
5368           if((lit & 0xff) == 0)
5369             /*  or'ing with 0 has no effect */
5370             continue;
5371           else {
5372             int p = my_powof2(lit & 0xff);
5373             if(p>=0) {
5374               /* only one bit is set in the literal, so use a bsf instruction */
5375               emitpcode(POC_BSF,   popGet(AOP(left),offset,FALSE,FALSE));
5376               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5377             } else {
5378               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5379               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5380
5381               emitcode("movlw","0x%x", (lit & 0xff));
5382               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5383             }
5384                     
5385           }
5386         } else {
5387           if (AOP_TYPE(left) == AOP_ACC) {
5388             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5389             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5390           } else {                  
5391             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5392             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5393
5394             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5395             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5396
5397           }
5398         }
5399       }
5400     } else {
5401         // left & result in different registers
5402         if(AOP_TYPE(result) == AOP_CRY){
5403             // result = bit
5404             // if(size), result in bit
5405             // if(!size && ifx), conditional oper: if(left | right)
5406             symbol *tlbl = newiTempLabel(NULL);
5407             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5408             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5409
5410             if(size)
5411                 emitcode(";XXX setb","c");
5412             while(sizer--){
5413                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5414                 emitcode(";XXX orl","a,%s",
5415                          aopGet(AOP(left),offset,FALSE,FALSE));
5416                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5417                 offset++;
5418             }
5419             if(size){
5420                 CLRC;
5421                 emitcode("","%05d_DS_:",tlbl->key+100);
5422                 outBitC(result);
5423             } else if(ifx)
5424                 jmpTrueOrFalse(ifx, tlbl);
5425         } else for(;(size--);offset++){
5426           // normal case
5427           // result = left & right
5428           if(AOP_TYPE(right) == AOP_LIT){
5429             int t = (lit >> (offset*8)) & 0x0FFL;
5430             switch(t) { 
5431             case 0x00:
5432               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5433               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5434
5435               emitcode("movf","%s,w",
5436                        aopGet(AOP(left),offset,FALSE,FALSE));
5437               emitcode("movwf","%s",
5438                        aopGet(AOP(result),offset,FALSE,FALSE));
5439               break;
5440             default:
5441               emitpcode(POC_MOVLW,  popGetLit(t));
5442               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5443               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5444
5445               emitcode("movlw","0x%x",t);
5446               emitcode("iorwf","%s,w",
5447                        aopGet(AOP(left),offset,FALSE,FALSE));
5448               emitcode("movwf","%s",
5449                        aopGet(AOP(result),offset,FALSE,FALSE));
5450               
5451             }
5452             continue;
5453           }
5454
5455           // faster than result <- left, anl result,right
5456           // and better if result is SFR
5457           if (AOP_TYPE(left) == AOP_ACC) {
5458             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5459             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5460           } else {
5461             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5462             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5463
5464             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5465             emitcode("iorwf","%s,w",
5466                      aopGet(AOP(left),offset,FALSE,FALSE));
5467           }
5468           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5469           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5470         }
5471     }
5472
5473 release :
5474     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5475     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5476     freeAsmop(result,NULL,ic,TRUE);     
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* genXor - code for xclusive or                                   */
5481 /*-----------------------------------------------------------------*/
5482 static void genXor (iCode *ic, iCode *ifx)
5483 {
5484     operand *left, *right, *result;
5485     int size, offset=0;
5486     unsigned long lit = 0L;
5487
5488     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5489
5490     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5491     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5492     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5493
5494     /* if left is a literal & right is not ||
5495        if left needs acc & right does not */
5496     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5497         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5498         operand *tmp = right ;
5499         right = left;
5500         left = tmp;
5501     }
5502
5503     /* if result = right then exchange them */
5504     if(sameRegs(AOP(result),AOP(right))){
5505         operand *tmp = right ;
5506         right = left;
5507         left = tmp;
5508     }
5509
5510     /* if right is bit then exchange them */
5511     if (AOP_TYPE(right) == AOP_CRY &&
5512         AOP_TYPE(left) != AOP_CRY){
5513         operand *tmp = right ;
5514         right = left;
5515         left = tmp;
5516     }
5517     if(AOP_TYPE(right) == AOP_LIT)
5518         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5519
5520     size = AOP_SIZE(result);
5521
5522     // if(bit ^ yy)
5523     // xx = bit ^ yy;
5524     if (AOP_TYPE(left) == AOP_CRY){
5525         if(AOP_TYPE(right) == AOP_LIT){
5526             // c = bit & literal;
5527             if(lit>>1){
5528                 // lit>>1  != 0 => result = 1
5529                 if(AOP_TYPE(result) == AOP_CRY){
5530                     if(size)
5531                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5532                     else if(ifx)
5533                         continueIfTrue(ifx);
5534                     goto release;
5535                 }
5536                 emitcode("setb","c");
5537             } else{
5538                 // lit == (0 or 1)
5539                 if(lit == 0){
5540                     // lit == 0, result = left
5541                     if(size && sameRegs(AOP(result),AOP(left)))
5542                         goto release;
5543                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5544                 } else{
5545                     // lit == 1, result = not(left)
5546                     if(size && sameRegs(AOP(result),AOP(left))){
5547                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5548                         goto release;
5549                     } else {
5550                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5551                         emitcode("cpl","c");
5552                     }
5553                 }
5554             }
5555
5556         } else {
5557             // right != literal
5558             symbol *tlbl = newiTempLabel(NULL);
5559             if (AOP_TYPE(right) == AOP_CRY){
5560                 // c = bit ^ bit;
5561                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5562             }
5563             else{
5564                 int sizer = AOP_SIZE(right);
5565                 // c = bit ^ val
5566                 // if val>>1 != 0, result = 1
5567                 emitcode("setb","c");
5568                 while(sizer){
5569                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5570                     if(sizer == 1)
5571                         // test the msb of the lsb
5572                         emitcode("anl","a,#0xfe");
5573                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5574                     sizer--;
5575                 }
5576                 // val = (0,1)
5577                 emitcode("rrc","a");
5578             }
5579             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5580             emitcode("cpl","c");
5581             emitcode("","%05d_DS_:",(tlbl->key+100));
5582         }
5583         // bit = c
5584         // val = c
5585         if(size)
5586             outBitC(result);
5587         // if(bit | ...)
5588         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5589             genIfxJump(ifx, "c");           
5590         goto release ;
5591     }
5592
5593     if(sameRegs(AOP(result),AOP(left))){
5594         /* if left is same as result */
5595         for(;size--; offset++) {
5596             if(AOP_TYPE(right) == AOP_LIT){
5597                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5598                     continue;
5599                 else
5600                     if (IS_AOP_PREG(left)) {
5601                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5602                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5603                         aopPut(AOP(result),"a",offset);
5604                     } else 
5605                         emitcode("xrl","%s,%s",
5606                                  aopGet(AOP(left),offset,FALSE,TRUE),
5607                                  aopGet(AOP(right),offset,FALSE,FALSE));
5608             } else {
5609                 if (AOP_TYPE(left) == AOP_ACC)
5610                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5611                 else {
5612                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5613                     if (IS_AOP_PREG(left)) {
5614                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5615                         aopPut(AOP(result),"a",offset);
5616                     } else
5617                         emitcode("xrl","%s,a",
5618                                  aopGet(AOP(left),offset,FALSE,TRUE));
5619                 }
5620             }
5621         }
5622     } else {
5623         // left & result in different registers
5624         if(AOP_TYPE(result) == AOP_CRY){
5625             // result = bit
5626             // if(size), result in bit
5627             // if(!size && ifx), conditional oper: if(left ^ right)
5628             symbol *tlbl = newiTempLabel(NULL);
5629             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5630             if(size)
5631                 emitcode("setb","c");
5632             while(sizer--){
5633                 if((AOP_TYPE(right) == AOP_LIT) &&
5634                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5635                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5636                 } else {
5637                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5638                     emitcode("xrl","a,%s",
5639                              aopGet(AOP(left),offset,FALSE,FALSE));
5640                 }
5641                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5642                 offset++;
5643             }
5644             if(size){
5645                 CLRC;
5646                 emitcode("","%05d_DS_:",tlbl->key+100);
5647                 outBitC(result);
5648             } else if(ifx)
5649                 jmpTrueOrFalse(ifx, tlbl);
5650         } else for(;(size--);offset++){
5651             // normal case
5652             // result = left & right
5653             if(AOP_TYPE(right) == AOP_LIT){
5654               int t = (lit >> (offset*8)) & 0x0FFL;
5655               switch(t) { 
5656               case 0x00:
5657                 emitcode("movf","%s,w",
5658                          aopGet(AOP(left),offset,FALSE,FALSE));
5659                 emitcode("movwf","%s",
5660                          aopGet(AOP(result),offset,FALSE,FALSE));
5661                 break;
5662               case 0xff:
5663                 emitcode("comf","%s,w",
5664                          aopGet(AOP(left),offset,FALSE,FALSE));
5665                 emitcode("movwf","%s",
5666                          aopGet(AOP(result),offset,FALSE,FALSE));
5667                 break;
5668               default:
5669                 emitcode("movlw","0x%x",t);
5670                 emitcode("xorwf","%s,w",
5671                          aopGet(AOP(left),offset,FALSE,FALSE));
5672                 emitcode("movwf","%s",
5673                          aopGet(AOP(result),offset,FALSE,FALSE));
5674
5675               }
5676               continue;
5677             }
5678
5679             // faster than result <- left, anl result,right
5680             // and better if result is SFR
5681             if (AOP_TYPE(left) == AOP_ACC)
5682                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5683             else {
5684                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5685                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5686             }
5687             if ( AOP_TYPE(result) != AOP_ACC)
5688               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5689         }
5690     }
5691
5692 release :
5693     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5694     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5695     freeAsmop(result,NULL,ic,TRUE);     
5696 }
5697
5698 /*-----------------------------------------------------------------*/
5699 /* genInline - write the inline code out                           */
5700 /*-----------------------------------------------------------------*/
5701 static void genInline (iCode *ic)
5702 {
5703     char buffer[MAX_INLINEASM];
5704     char *bp = buffer;
5705     char *bp1= buffer;
5706     
5707     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5708
5709     _G.inLine += (!options.asmpeep);
5710     strcpy(buffer,IC_INLINE(ic));
5711
5712     /* emit each line as a code */
5713     while (*bp) {
5714         if (*bp == '\n') {
5715             *bp++ = '\0';
5716             emitcode(bp1,"");
5717             bp1 = bp;
5718         } else {
5719             if (*bp == ':') {
5720                 bp++;
5721                 *bp = '\0';
5722                 bp++;
5723                 emitcode(bp1,"");
5724                 bp1 = bp;
5725             } else
5726                 bp++;
5727         }
5728     }
5729     if (bp1 != bp)
5730         emitcode(bp1,"");
5731     /*     emitcode("",buffer); */
5732     _G.inLine -= (!options.asmpeep);
5733 }
5734
5735 /*-----------------------------------------------------------------*/
5736 /* genRRC - rotate right with carry                                */
5737 /*-----------------------------------------------------------------*/
5738 static void genRRC (iCode *ic)
5739 {
5740     operand *left , *result ;
5741     int size, offset = 0;
5742     char *l;    
5743
5744     /* rotate right with carry */
5745     left = IC_LEFT(ic);
5746     result=IC_RESULT(ic);
5747     aopOp (left,ic,FALSE);
5748     aopOp (result,ic,FALSE);
5749
5750     /* move it to the result */
5751     size = AOP_SIZE(result);    
5752     offset = size - 1 ;
5753     CLRC;
5754     while (size--) {
5755         l = aopGet(AOP(left),offset,FALSE,FALSE);
5756         MOVA(l);
5757         emitcode("rrc","a");
5758         if (AOP_SIZE(result) > 1)
5759             aopPut(AOP(result),"a",offset--);
5760     }
5761     /* now we need to put the carry into the
5762     highest order byte of the result */
5763     if (AOP_SIZE(result) > 1) {
5764         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5765         MOVA(l);
5766     }
5767     emitcode("mov","acc.7,c");
5768     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5769     freeAsmop(left,NULL,ic,TRUE);
5770     freeAsmop(result,NULL,ic,TRUE);
5771 }
5772
5773 /*-----------------------------------------------------------------*/
5774 /* genRLC - generate code for rotate left with carry               */
5775 /*-----------------------------------------------------------------*/
5776 static void genRLC (iCode *ic)
5777 {    
5778     operand *left , *result ;
5779     int size, offset = 0;
5780     char *l;    
5781
5782     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5783     /* rotate right with carry */
5784     left = IC_LEFT(ic);
5785     result=IC_RESULT(ic);
5786     aopOp (left,ic,FALSE);
5787     aopOp (result,ic,FALSE);
5788
5789     /* move it to the result */
5790     size = AOP_SIZE(result);    
5791     offset = 0 ;
5792     if (size--) {
5793         l = aopGet(AOP(left),offset,FALSE,FALSE);
5794         MOVA(l);
5795         emitcode("add","a,acc");
5796         if (AOP_SIZE(result) > 1)
5797             aopPut(AOP(result),"a",offset++);
5798         while (size--) {
5799             l = aopGet(AOP(left),offset,FALSE,FALSE);
5800             MOVA(l);
5801             emitcode("rlc","a");
5802             if (AOP_SIZE(result) > 1)
5803                 aopPut(AOP(result),"a",offset++);
5804         }
5805     }
5806     /* now we need to put the carry into the
5807     highest order byte of the result */
5808     if (AOP_SIZE(result) > 1) {
5809         l = aopGet(AOP(result),0,FALSE,FALSE);
5810         MOVA(l);
5811     }
5812     emitcode("mov","acc.0,c");
5813     aopPut(AOP(result),"a",0);
5814     freeAsmop(left,NULL,ic,TRUE);
5815     freeAsmop(result,NULL,ic,TRUE);
5816 }
5817
5818 /*-----------------------------------------------------------------*/
5819 /* genGetHbit - generates code get highest order bit               */
5820 /*-----------------------------------------------------------------*/
5821 static void genGetHbit (iCode *ic)
5822 {
5823     operand *left, *result;
5824     left = IC_LEFT(ic);
5825     result=IC_RESULT(ic);
5826     aopOp (left,ic,FALSE);
5827     aopOp (result,ic,FALSE);
5828
5829     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5830     /* get the highest order byte into a */
5831     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5832     if(AOP_TYPE(result) == AOP_CRY){
5833         emitcode("rlc","a");
5834         outBitC(result);
5835     }
5836     else{
5837         emitcode("rl","a");
5838         emitcode("anl","a,#0x01");
5839         outAcc(result);
5840     }
5841
5842
5843     freeAsmop(left,NULL,ic,TRUE);
5844     freeAsmop(result,NULL,ic,TRUE);
5845 }
5846
5847 /*-----------------------------------------------------------------*/
5848 /* AccRol - rotate left accumulator by known count                 */
5849 /*-----------------------------------------------------------------*/
5850 static void AccRol (int shCount)
5851 {
5852     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5853     shCount &= 0x0007;              // shCount : 0..7
5854     switch(shCount){
5855         case 0 :
5856             break;
5857         case 1 :
5858             emitcode("rl","a");
5859             break;
5860         case 2 :
5861             emitcode("rl","a");
5862             emitcode("rl","a");
5863             break;
5864         case 3 :
5865             emitcode("swap","a");
5866             emitcode("rr","a");
5867             break;
5868         case 4 :
5869             emitcode("swap","a");
5870             break;
5871         case 5 :
5872             emitcode("swap","a");
5873             emitcode("rl","a");
5874             break;
5875         case 6 :
5876             emitcode("rr","a");
5877             emitcode("rr","a");
5878             break;
5879         case 7 :
5880             emitcode("rr","a");
5881             break;
5882     }
5883 }
5884
5885 /*-----------------------------------------------------------------*/
5886 /* AccLsh - left shift accumulator by known count                  */
5887 /*-----------------------------------------------------------------*/
5888 static void AccLsh (int shCount)
5889 {
5890     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5891     if(shCount != 0){
5892         if(shCount == 1)
5893             emitcode("add","a,acc");
5894         else 
5895             if(shCount == 2) {
5896             emitcode("add","a,acc");
5897             emitcode("add","a,acc");
5898         } else {
5899             /* rotate left accumulator */
5900             AccRol(shCount);
5901             /* and kill the lower order bits */
5902             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5903         }
5904     }
5905 }
5906
5907 /*-----------------------------------------------------------------*/
5908 /* AccRsh - right shift accumulator by known count                 */
5909 /*-----------------------------------------------------------------*/
5910 static void AccRsh (int shCount)
5911 {
5912     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5913     if(shCount != 0){
5914         if(shCount == 1){
5915             CLRC;
5916             emitcode("rrc","a");
5917         } else {
5918             /* rotate right accumulator */
5919             AccRol(8 - shCount);
5920             /* and kill the higher order bits */
5921             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5922         }
5923     }
5924 }
5925
5926 /*-----------------------------------------------------------------*/
5927 /* AccSRsh - signed right shift accumulator by known count                 */
5928 /*-----------------------------------------------------------------*/
5929 static void AccSRsh (int shCount)
5930 {
5931     symbol *tlbl ;
5932     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5933     if(shCount != 0){
5934         if(shCount == 1){
5935             emitcode("mov","c,acc.7");
5936             emitcode("rrc","a");
5937         } else if(shCount == 2){
5938             emitcode("mov","c,acc.7");
5939             emitcode("rrc","a");
5940             emitcode("mov","c,acc.7");
5941             emitcode("rrc","a");
5942         } else {
5943             tlbl = newiTempLabel(NULL);
5944             /* rotate right accumulator */
5945             AccRol(8 - shCount);
5946             /* and kill the higher order bits */
5947             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5948             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5949             emitcode("orl","a,#0x%02x",
5950                      (unsigned char)~SRMask[shCount]);
5951             emitcode("","%05d_DS_:",tlbl->key+100);
5952         }
5953     }
5954 }
5955
5956 /*-----------------------------------------------------------------*/
5957 /* shiftR1Left2Result - shift right one byte from left to result   */
5958 /*-----------------------------------------------------------------*/
5959 static void shiftR1Left2Result (operand *left, int offl,
5960                                 operand *result, int offr,
5961                                 int shCount, int sign)
5962 {
5963     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5964     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5965     /* shift right accumulator */
5966     if(sign)
5967         AccSRsh(shCount);
5968     else
5969         AccRsh(shCount);
5970     aopPut(AOP(result),"a",offr);
5971 }
5972
5973 /*-----------------------------------------------------------------*/
5974 /* shiftL1Left2Result - shift left one byte from left to result    */
5975 /*-----------------------------------------------------------------*/
5976 static void shiftL1Left2Result (operand *left, int offl,
5977                                 operand *result, int offr, int shCount)
5978 {
5979     char *l;
5980     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5981     l = aopGet(AOP(left),offl,FALSE,FALSE);
5982     MOVA(l);
5983     /* shift left accumulator */
5984     AccLsh(shCount);
5985     aopPut(AOP(result),"a",offr);
5986 }
5987
5988 /*-----------------------------------------------------------------*/
5989 /* movLeft2Result - move byte from left to result                  */
5990 /*-----------------------------------------------------------------*/
5991 static void movLeft2Result (operand *left, int offl,
5992                             operand *result, int offr, int sign)
5993 {
5994     char *l;
5995     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5996     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5997         l = aopGet(AOP(left),offl,FALSE,FALSE);
5998
5999         if (*l == '@' && (IS_AOP_PREG(result))) {
6000             emitcode("mov","a,%s",l);
6001             aopPut(AOP(result),"a",offr);
6002         } else {
6003             if(!sign)
6004                 aopPut(AOP(result),l,offr);
6005             else{
6006                 /* MSB sign in acc.7 ! */
6007                 if(getDataSize(left) == offl+1){
6008                     emitcode("mov","a,%s",l);
6009                     aopPut(AOP(result),"a",offr);
6010                 }
6011             }
6012         }
6013     }
6014 }
6015
6016 /*-----------------------------------------------------------------*/
6017 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6018 /*-----------------------------------------------------------------*/
6019 static void AccAXRrl1 (char *x)
6020 {
6021     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6022     emitcode("rrc","a");
6023     emitcode("xch","a,%s", x);
6024     emitcode("rrc","a");
6025     emitcode("xch","a,%s", x);
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6030 /*-----------------------------------------------------------------*/
6031 static void AccAXLrl1 (char *x)
6032 {
6033     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6034     emitcode("xch","a,%s",x);
6035     emitcode("rlc","a");
6036     emitcode("xch","a,%s",x);
6037     emitcode("rlc","a");
6038 }
6039
6040 /*-----------------------------------------------------------------*/
6041 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6042 /*-----------------------------------------------------------------*/
6043 static void AccAXLsh1 (char *x)
6044 {
6045     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6046     emitcode("xch","a,%s",x);
6047     emitcode("add","a,acc");
6048     emitcode("xch","a,%s",x);
6049     emitcode("rlc","a");
6050 }
6051
6052 /*-----------------------------------------------------------------*/
6053 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6054 /*-----------------------------------------------------------------*/
6055 static void AccAXLsh (char *x, int shCount)
6056 {
6057     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6058     switch(shCount){
6059         case 0 :
6060             break;
6061         case 1 :
6062             AccAXLsh1(x);
6063             break;
6064         case 2 :
6065             AccAXLsh1(x);
6066             AccAXLsh1(x);
6067             break;
6068         case 3 :
6069         case 4 :
6070         case 5 :                        // AAAAABBB:CCCCCDDD
6071             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
6072             emitcode("anl","a,#0x%02x",
6073                      SLMask[shCount]);  // BBB00000:CCCCCDDD
6074             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
6075             AccRol(shCount);            // DDDCCCCC:BBB00000
6076             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
6077             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
6078             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
6079             emitcode("anl","a,#0x%02x",
6080                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
6081             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
6082             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
6083             break;
6084         case 6 :                        // AAAAAABB:CCCCCCDD
6085             emitcode("anl","a,#0x%02x",
6086                      SRMask[shCount]);  // 000000BB:CCCCCCDD
6087             emitcode("mov","c,acc.0");  // c = B
6088             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
6089             AccAXRrl1(x);               // BCCCCCCD:D000000B
6090             AccAXRrl1(x);               // BBCCCCCC:DD000000
6091             break;
6092         case 7 :                        // a:x <<= 7
6093             emitcode("anl","a,#0x%02x",
6094                      SRMask[shCount]);  // 0000000B:CCCCCCCD
6095             emitcode("mov","c,acc.0");  // c = B
6096             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
6097             AccAXRrl1(x);               // BCCCCCCC:D0000000
6098             break;
6099         default :
6100             break;
6101     }
6102 }
6103
6104 /*-----------------------------------------------------------------*/
6105 /* AccAXRsh - right shift a:x known count (0..7)                   */
6106 /*-----------------------------------------------------------------*/
6107 static void AccAXRsh (char *x, int shCount)
6108 {   
6109     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6110     switch(shCount){
6111         case 0 :
6112             break;
6113         case 1 :
6114             CLRC;
6115             AccAXRrl1(x);               // 0->a:x
6116             break;
6117         case 2 :
6118             CLRC;
6119             AccAXRrl1(x);               // 0->a:x
6120             CLRC;
6121             AccAXRrl1(x);               // 0->a:x
6122             break;
6123         case 3 :
6124         case 4 :
6125         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6126             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
6127             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6128             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6129             emitcode("anl","a,#0x%02x",
6130                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6131             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6132             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6133             emitcode("anl","a,#0x%02x",
6134                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6135             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6136             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6137             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
6138             break;
6139         case 6 :                        // AABBBBBB:CCDDDDDD
6140             emitcode("mov","c,acc.7");
6141             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6142             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6143             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6144             emitcode("anl","a,#0x%02x",
6145                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6146             break;
6147         case 7 :                        // ABBBBBBB:CDDDDDDD
6148             emitcode("mov","c,acc.7");  // c = A
6149             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6150             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6151             emitcode("anl","a,#0x%02x",
6152                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6153             break;
6154         default :
6155             break;
6156     }
6157 }
6158
6159 /*-----------------------------------------------------------------*/
6160 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6161 /*-----------------------------------------------------------------*/
6162 static void AccAXRshS (char *x, int shCount)
6163 {   
6164     symbol *tlbl ;
6165     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6166     switch(shCount){
6167         case 0 :
6168             break;
6169         case 1 :
6170             emitcode("mov","c,acc.7");
6171             AccAXRrl1(x);               // s->a:x
6172             break;
6173         case 2 :
6174             emitcode("mov","c,acc.7");
6175             AccAXRrl1(x);               // s->a:x
6176             emitcode("mov","c,acc.7");
6177             AccAXRrl1(x);               // s->a:x
6178             break;
6179         case 3 :
6180         case 4 :
6181         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6182             tlbl = newiTempLabel(NULL);
6183             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6184             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6185             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6186             emitcode("anl","a,#0x%02x",
6187                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6188             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6189             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6190             emitcode("anl","a,#0x%02x",
6191                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6192             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6193             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6194             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6195             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6196             emitcode("orl","a,#0x%02x",
6197                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6198             emitcode("","%05d_DS_:",tlbl->key+100);
6199             break;                      // SSSSAAAA:BBBCCCCC
6200         case 6 :                        // AABBBBBB:CCDDDDDD
6201             tlbl = newiTempLabel(NULL);
6202             emitcode("mov","c,acc.7");
6203             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6204             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6205             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6206             emitcode("anl","a,#0x%02x",
6207                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6208             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6209             emitcode("orl","a,#0x%02x",
6210                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6211             emitcode("","%05d_DS_:",tlbl->key+100);
6212             break;
6213         case 7 :                        // ABBBBBBB:CDDDDDDD
6214             tlbl = newiTempLabel(NULL);
6215             emitcode("mov","c,acc.7");  // c = A
6216             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6217             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6218             emitcode("anl","a,#0x%02x",
6219                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6220             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6221             emitcode("orl","a,#0x%02x",
6222                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6223             emitcode("","%05d_DS_:",tlbl->key+100);
6224             break;
6225         default :
6226             break;
6227     }
6228 }
6229
6230 /*-----------------------------------------------------------------*/
6231 /* shiftL2Left2Result - shift left two bytes from left to result   */
6232 /*-----------------------------------------------------------------*/
6233 static void shiftL2Left2Result (operand *left, int offl,
6234                                 operand *result, int offr, int shCount)
6235 {
6236     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6237     if(sameRegs(AOP(result), AOP(left)) &&
6238        ((offl + MSB16) == offr)){
6239         /* don't crash result[offr] */
6240         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6241         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6242     } else {
6243         movLeft2Result(left,offl, result, offr, 0);
6244         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6245     }
6246     /* ax << shCount (x = lsb(result))*/
6247     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6248     aopPut(AOP(result),"a",offr+MSB16);
6249 }
6250
6251
6252 /*-----------------------------------------------------------------*/
6253 /* shiftR2Left2Result - shift right two bytes from left to result  */
6254 /*-----------------------------------------------------------------*/
6255 static void shiftR2Left2Result (operand *left, int offl,
6256                                 operand *result, int offr,
6257                                 int shCount, int sign)
6258 {
6259     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6260     if(sameRegs(AOP(result), AOP(left)) &&
6261        ((offl + MSB16) == offr)){
6262         /* don't crash result[offr] */
6263         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6264         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6265     } else {
6266         movLeft2Result(left,offl, result, offr, 0);
6267         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6268     }
6269     /* a:x >> shCount (x = lsb(result))*/
6270     if(sign)
6271         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6272     else
6273         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6274     if(getDataSize(result) > 1)
6275         aopPut(AOP(result),"a",offr+MSB16);
6276 }
6277
6278 /*-----------------------------------------------------------------*/
6279 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6280 /*-----------------------------------------------------------------*/
6281 static void shiftLLeftOrResult (operand *left, int offl,
6282                                 operand *result, int offr, int shCount)
6283 {
6284     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6285     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6286     /* shift left accumulator */
6287     AccLsh(shCount);
6288     /* or with result */
6289     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6290     /* back to result */
6291     aopPut(AOP(result),"a",offr);
6292 }
6293
6294 /*-----------------------------------------------------------------*/
6295 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6296 /*-----------------------------------------------------------------*/
6297 static void shiftRLeftOrResult (operand *left, int offl,
6298                                 operand *result, int offr, int shCount)
6299 {
6300     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6301     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6302     /* shift right accumulator */
6303     AccRsh(shCount);
6304     /* or with result */
6305     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6306     /* back to result */
6307     aopPut(AOP(result),"a",offr);
6308 }
6309
6310 /*-----------------------------------------------------------------*/
6311 /* genlshOne - left shift a one byte quantity by known count       */
6312 /*-----------------------------------------------------------------*/
6313 static void genlshOne (operand *result, operand *left, int shCount)
6314 {       
6315     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6316     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6317 }
6318
6319 /*-----------------------------------------------------------------*/
6320 /* genlshTwo - left shift two bytes by known amount != 0           */
6321 /*-----------------------------------------------------------------*/
6322 static void genlshTwo (operand *result,operand *left, int shCount)
6323 {
6324     int size;
6325     
6326     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6327     size = getDataSize(result);
6328
6329     /* if shCount >= 8 */
6330     if (shCount >= 8) {
6331         shCount -= 8 ;
6332
6333         if (size > 1){
6334             if (shCount)
6335                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6336             else 
6337                 movLeft2Result(left, LSB, result, MSB16, 0);
6338         }
6339         aopPut(AOP(result),zero,LSB);   
6340     }
6341
6342     /*  1 <= shCount <= 7 */
6343     else {  
6344         if(size == 1)
6345             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6346         else 
6347             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6348     }
6349 }
6350
6351 /*-----------------------------------------------------------------*/
6352 /* shiftLLong - shift left one long from left to result            */
6353 /* offl = LSB or MSB16                                             */
6354 /*-----------------------------------------------------------------*/
6355 static void shiftLLong (operand *left, operand *result, int offr )
6356 {
6357     char *l;
6358     int size = AOP_SIZE(result);
6359
6360     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6361     if(size >= LSB+offr){
6362         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6363         MOVA(l);
6364         emitcode("add","a,acc");
6365         if (sameRegs(AOP(left),AOP(result)) && 
6366             size >= MSB16+offr && offr != LSB )
6367             emitcode("xch","a,%s",
6368                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6369         else        
6370             aopPut(AOP(result),"a",LSB+offr);
6371     }
6372
6373     if(size >= MSB16+offr){
6374         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6375             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6376             MOVA(l);
6377         }
6378         emitcode("rlc","a");
6379         if (sameRegs(AOP(left),AOP(result)) && 
6380             size >= MSB24+offr && offr != LSB)
6381             emitcode("xch","a,%s",
6382                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6383         else        
6384             aopPut(AOP(result),"a",MSB16+offr);
6385     }
6386
6387     if(size >= MSB24+offr){
6388         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6389             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6390             MOVA(l);
6391         }
6392         emitcode("rlc","a");
6393         if (sameRegs(AOP(left),AOP(result)) && 
6394             size >= MSB32+offr && offr != LSB )
6395             emitcode("xch","a,%s",
6396                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6397         else        
6398             aopPut(AOP(result),"a",MSB24+offr);
6399     }
6400
6401     if(size > MSB32+offr){
6402         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6403             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6404             MOVA(l);    
6405         }
6406         emitcode("rlc","a");
6407         aopPut(AOP(result),"a",MSB32+offr);
6408     }
6409     if(offr != LSB)
6410         aopPut(AOP(result),zero,LSB);       
6411 }
6412
6413 /*-----------------------------------------------------------------*/
6414 /* genlshFour - shift four byte by a known amount != 0             */
6415 /*-----------------------------------------------------------------*/
6416 static void genlshFour (operand *result, operand *left, int shCount)
6417 {
6418     int size;
6419
6420     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6421     size = AOP_SIZE(result);
6422
6423     /* if shifting more that 3 bytes */
6424     if (shCount >= 24 ) {
6425         shCount -= 24;
6426         if (shCount)
6427             /* lowest order of left goes to the highest
6428             order of the destination */
6429             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6430         else
6431             movLeft2Result(left, LSB, result, MSB32, 0);
6432         aopPut(AOP(result),zero,LSB);
6433         aopPut(AOP(result),zero,MSB16);
6434         aopPut(AOP(result),zero,MSB32);
6435         return;
6436     }
6437
6438     /* more than two bytes */
6439     else if ( shCount >= 16 ) {
6440         /* lower order two bytes goes to higher order two bytes */
6441         shCount -= 16;
6442         /* if some more remaining */
6443         if (shCount)
6444             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6445         else {
6446             movLeft2Result(left, MSB16, result, MSB32, 0);
6447             movLeft2Result(left, LSB, result, MSB24, 0);
6448         }
6449         aopPut(AOP(result),zero,MSB16);
6450         aopPut(AOP(result),zero,LSB);
6451         return;
6452     }    
6453
6454     /* if more than 1 byte */
6455     else if ( shCount >= 8 ) {
6456         /* lower order three bytes goes to higher order  three bytes */
6457         shCount -= 8;
6458         if(size == 2){
6459             if(shCount)
6460                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6461             else
6462                 movLeft2Result(left, LSB, result, MSB16, 0);
6463         }
6464         else{   /* size = 4 */
6465             if(shCount == 0){
6466                 movLeft2Result(left, MSB24, result, MSB32, 0);
6467                 movLeft2Result(left, MSB16, result, MSB24, 0);
6468                 movLeft2Result(left, LSB, result, MSB16, 0);
6469                 aopPut(AOP(result),zero,LSB);
6470             }
6471             else if(shCount == 1)
6472                 shiftLLong(left, result, MSB16);
6473             else{
6474                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6475                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6476                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6477                 aopPut(AOP(result),zero,LSB);
6478             }
6479         }
6480     }
6481
6482     /* 1 <= shCount <= 7 */
6483     else if(shCount <= 2){
6484         shiftLLong(left, result, LSB);
6485         if(shCount == 2)
6486             shiftLLong(result, result, LSB);
6487     }
6488     /* 3 <= shCount <= 7, optimize */
6489     else{
6490         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6491         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6492         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6493     }
6494 }
6495
6496 /*-----------------------------------------------------------------*/
6497 /* genLeftShiftLiteral - left shifting by known count              */
6498 /*-----------------------------------------------------------------*/
6499 static void genLeftShiftLiteral (operand *left,
6500                                  operand *right,
6501                                  operand *result,
6502                                  iCode *ic)
6503 {    
6504     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6505     int size;
6506
6507     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6508     freeAsmop(right,NULL,ic,TRUE);
6509
6510     aopOp(left,ic,FALSE);
6511     aopOp(result,ic,FALSE);
6512
6513     size = getSize(operandType(result));
6514
6515 #if VIEW_SIZE
6516     emitcode("; shift left ","result %d, left %d",size,
6517              AOP_SIZE(left));
6518 #endif
6519
6520     /* I suppose that the left size >= result size */
6521     if(shCount == 0){
6522         while(size--){
6523             movLeft2Result(left, size, result, size, 0);
6524         }
6525     }
6526
6527     else if(shCount >= (size * 8))
6528         while(size--)
6529             aopPut(AOP(result),zero,size);
6530     else{
6531         switch (size) {
6532             case 1:
6533                 genlshOne (result,left,shCount);
6534                 break;
6535
6536             case 2:
6537             case 3:
6538                 genlshTwo (result,left,shCount);
6539                 break;
6540
6541             case 4:
6542                 genlshFour (result,left,shCount);
6543                 break;
6544         }
6545     }
6546     freeAsmop(left,NULL,ic,TRUE);
6547     freeAsmop(result,NULL,ic,TRUE);
6548 }
6549
6550 /*-----------------------------------------------------------------*/
6551 /* genLeftShift - generates code for left shifting                 */
6552 /*-----------------------------------------------------------------*/
6553 static void genLeftShift (iCode *ic)
6554 {
6555     operand *left,*right, *result;
6556     int size, offset;
6557     char *l;
6558     symbol *tlbl , *tlbl1;
6559
6560     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6561
6562     right = IC_RIGHT(ic);
6563     left  = IC_LEFT(ic);
6564     result = IC_RESULT(ic);
6565
6566     aopOp(right,ic,FALSE);
6567
6568     /* if the shift count is known then do it 
6569     as efficiently as possible */
6570     if (AOP_TYPE(right) == AOP_LIT) {
6571         genLeftShiftLiteral (left,right,result,ic);
6572         return ;
6573     }
6574
6575     /* shift count is unknown then we have to form 
6576     a loop get the loop count in B : Note: we take
6577     only the lower order byte since shifting
6578     more that 32 bits make no sense anyway, ( the
6579     largest size of an object can be only 32 bits ) */  
6580
6581     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6582     emitcode("inc","b");
6583     freeAsmop (right,NULL,ic,TRUE);
6584     aopOp(left,ic,FALSE);
6585     aopOp(result,ic,FALSE);
6586
6587     /* now move the left to the result if they are not the
6588     same */
6589     if (!sameRegs(AOP(left),AOP(result)) && 
6590         AOP_SIZE(result) > 1) {
6591
6592         size = AOP_SIZE(result);
6593         offset=0;
6594         while (size--) {
6595             l = aopGet(AOP(left),offset,FALSE,TRUE);
6596             if (*l == '@' && (IS_AOP_PREG(result))) {
6597
6598                 emitcode("mov","a,%s",l);
6599                 aopPut(AOP(result),"a",offset);
6600             } else
6601                 aopPut(AOP(result),l,offset);
6602             offset++;
6603         }
6604     }
6605
6606     tlbl = newiTempLabel(NULL);
6607     size = AOP_SIZE(result);
6608     offset = 0 ;   
6609     tlbl1 = newiTempLabel(NULL);
6610
6611     /* if it is only one byte then */
6612     if (size == 1) {
6613         symbol *tlbl1 = newiTempLabel(NULL);
6614
6615         l = aopGet(AOP(left),0,FALSE,FALSE);
6616         MOVA(l);
6617         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6618         emitcode("","%05d_DS_:",tlbl->key+100);
6619         emitcode("add","a,acc");
6620         emitcode("","%05d_DS_:",tlbl1->key+100);
6621         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6622         aopPut(AOP(result),"a",0);
6623         goto release ;
6624     }
6625     
6626     reAdjustPreg(AOP(result));    
6627     
6628     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6629     emitcode("","%05d_DS_:",tlbl->key+100);    
6630     l = aopGet(AOP(result),offset,FALSE,FALSE);
6631     MOVA(l);
6632     emitcode("add","a,acc");         
6633     aopPut(AOP(result),"a",offset++);
6634     while (--size) {
6635         l = aopGet(AOP(result),offset,FALSE,FALSE);
6636         MOVA(l);
6637         emitcode("rlc","a");         
6638         aopPut(AOP(result),"a",offset++);
6639     }
6640     reAdjustPreg(AOP(result));
6641
6642     emitcode("","%05d_DS_:",tlbl1->key+100);
6643     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6644 release:
6645     freeAsmop(left,NULL,ic,TRUE);
6646     freeAsmop(result,NULL,ic,TRUE);
6647 }
6648
6649 /*-----------------------------------------------------------------*/
6650 /* genrshOne - right shift a one byte quantity by known count      */
6651 /*-----------------------------------------------------------------*/
6652 static void genrshOne (operand *result, operand *left,
6653                        int shCount, int sign)
6654 {
6655     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6656     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6657 }
6658
6659 /*-----------------------------------------------------------------*/
6660 /* genrshTwo - right shift two bytes by known amount != 0          */
6661 /*-----------------------------------------------------------------*/
6662 static void genrshTwo (operand *result,operand *left,
6663                        int shCount, int sign)
6664 {
6665     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6666     /* if shCount >= 8 */
6667     if (shCount >= 8) {
6668         shCount -= 8 ;
6669         if (shCount)
6670             shiftR1Left2Result(left, MSB16, result, LSB,
6671                                shCount, sign);
6672         else 
6673             movLeft2Result(left, MSB16, result, LSB, sign);
6674         addSign(result, MSB16, sign);
6675     }
6676
6677     /*  1 <= shCount <= 7 */
6678     else
6679         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6680 }
6681
6682 /*-----------------------------------------------------------------*/
6683 /* shiftRLong - shift right one long from left to result           */
6684 /* offl = LSB or MSB16                                             */
6685 /*-----------------------------------------------------------------*/
6686 static void shiftRLong (operand *left, int offl,
6687                         operand *result, int sign)
6688 {
6689     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6690     if(!sign)
6691         emitcode("clr","c");
6692     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6693     if(sign)
6694         emitcode("mov","c,acc.7");
6695     emitcode("rrc","a");
6696     aopPut(AOP(result),"a",MSB32-offl);
6697     if(offl == MSB16)
6698         /* add sign of "a" */
6699         addSign(result, MSB32, sign);
6700
6701     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6702     emitcode("rrc","a");
6703     aopPut(AOP(result),"a",MSB24-offl);
6704
6705     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6706     emitcode("rrc","a");
6707     aopPut(AOP(result),"a",MSB16-offl);
6708
6709     if(offl == LSB){
6710         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6711         emitcode("rrc","a");
6712         aopPut(AOP(result),"a",LSB);
6713     }
6714 }
6715
6716 /*-----------------------------------------------------------------*/
6717 /* genrshFour - shift four byte by a known amount != 0             */
6718 /*-----------------------------------------------------------------*/
6719 static void genrshFour (operand *result, operand *left,
6720                         int shCount, int sign)
6721 {
6722     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6723     /* if shifting more that 3 bytes */
6724     if(shCount >= 24 ) {
6725         shCount -= 24;
6726         if(shCount)
6727             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6728         else
6729             movLeft2Result(left, MSB32, result, LSB, sign);
6730         addSign(result, MSB16, sign);
6731     }
6732     else if(shCount >= 16){
6733         shCount -= 16;
6734         if(shCount)
6735             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6736         else{
6737             movLeft2Result(left, MSB24, result, LSB, 0);
6738             movLeft2Result(left, MSB32, result, MSB16, sign);
6739         }
6740         addSign(result, MSB24, sign);
6741     }
6742     else if(shCount >= 8){
6743         shCount -= 8;
6744         if(shCount == 1)
6745             shiftRLong(left, MSB16, result, sign);
6746         else if(shCount == 0){
6747             movLeft2Result(left, MSB16, result, LSB, 0);
6748             movLeft2Result(left, MSB24, result, MSB16, 0);
6749             movLeft2Result(left, MSB32, result, MSB24, sign);
6750             addSign(result, MSB32, sign);
6751         }
6752         else{
6753             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6754             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6755             /* the last shift is signed */
6756             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6757             addSign(result, MSB32, sign);
6758         }
6759     }
6760     else{   /* 1 <= shCount <= 7 */
6761         if(shCount <= 2){
6762             shiftRLong(left, LSB, result, sign);
6763             if(shCount == 2)
6764                 shiftRLong(result, LSB, result, sign);
6765         }
6766         else{
6767             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6768             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6769             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6770         }
6771     }
6772 }
6773
6774 /*-----------------------------------------------------------------*/
6775 /* genRightShiftLiteral - right shifting by known count            */
6776 /*-----------------------------------------------------------------*/
6777 static void genRightShiftLiteral (operand *left,
6778                                   operand *right,
6779                                   operand *result,
6780                                   iCode *ic,
6781                                   int sign)
6782 {    
6783     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6784     int size;
6785
6786     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6787     freeAsmop(right,NULL,ic,TRUE);
6788
6789     aopOp(left,ic,FALSE);
6790     aopOp(result,ic,FALSE);
6791
6792 #if VIEW_SIZE
6793     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6794              AOP_SIZE(left));
6795 #endif
6796
6797     size = getDataSize(left);
6798     /* test the LEFT size !!! */
6799
6800     /* I suppose that the left size >= result size */
6801     if(shCount == 0){
6802         size = getDataSize(result);
6803         while(size--)
6804             movLeft2Result(left, size, result, size, 0);
6805     }
6806
6807     else if(shCount >= (size * 8)){
6808         if(sign)
6809             /* get sign in acc.7 */
6810             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6811         addSign(result, LSB, sign);
6812     } else{
6813         switch (size) {
6814             case 1:
6815                 genrshOne (result,left,shCount,sign);
6816                 break;
6817
6818             case 2:
6819                 genrshTwo (result,left,shCount,sign);
6820                 break;
6821
6822             case 4:
6823                 genrshFour (result,left,shCount,sign);
6824                 break;
6825             default :
6826                 break;
6827         }
6828
6829         freeAsmop(left,NULL,ic,TRUE);
6830         freeAsmop(result,NULL,ic,TRUE);
6831     }
6832 }
6833
6834 /*-----------------------------------------------------------------*/
6835 /* genSignedRightShift - right shift of signed number              */
6836 /*-----------------------------------------------------------------*/
6837 static void genSignedRightShift (iCode *ic)
6838 {
6839     operand *right, *left, *result;
6840     int size, offset;
6841     char *l;
6842     symbol *tlbl, *tlbl1 ;
6843
6844     /* we do it the hard way put the shift count in b
6845     and loop thru preserving the sign */
6846     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6847
6848     right = IC_RIGHT(ic);
6849     left  = IC_LEFT(ic);
6850     result = IC_RESULT(ic);
6851
6852     aopOp(right,ic,FALSE);  
6853
6854
6855     if ( AOP_TYPE(right) == AOP_LIT) {
6856         genRightShiftLiteral (left,right,result,ic,1);
6857         return ;
6858     }
6859         /* shift count is unknown then we have to form 
6860        a loop get the loop count in B : Note: we take
6861        only the lower order byte since shifting
6862        more that 32 bits make no sense anyway, ( the
6863        largest size of an object can be only 32 bits ) */  
6864
6865     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6866     emitcode("inc","b");
6867     freeAsmop (right,NULL,ic,TRUE);
6868     aopOp(left,ic,FALSE);
6869     aopOp(result,ic,FALSE);
6870
6871     /* now move the left to the result if they are not the
6872     same */
6873     if (!sameRegs(AOP(left),AOP(result)) && 
6874         AOP_SIZE(result) > 1) {
6875
6876         size = AOP_SIZE(result);
6877         offset=0;
6878         while (size--) {
6879             l = aopGet(AOP(left),offset,FALSE,TRUE);
6880             if (*l == '@' && IS_AOP_PREG(result)) {
6881
6882                 emitcode("mov","a,%s",l);
6883                 aopPut(AOP(result),"a",offset);
6884             } else
6885                 aopPut(AOP(result),l,offset);
6886             offset++;
6887         }
6888     }
6889
6890     /* mov the highest order bit to OVR */    
6891     tlbl = newiTempLabel(NULL);
6892     tlbl1= newiTempLabel(NULL);
6893
6894     size = AOP_SIZE(result);
6895     offset = size - 1;
6896     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6897     emitcode("rlc","a");
6898     emitcode("mov","ov,c");
6899     /* if it is only one byte then */
6900     if (size == 1) {
6901         l = aopGet(AOP(left),0,FALSE,FALSE);
6902         MOVA(l);
6903         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6904         emitcode("","%05d_DS_:",tlbl->key+100);
6905         emitcode("mov","c,ov");
6906         emitcode("rrc","a");
6907         emitcode("","%05d_DS_:",tlbl1->key+100);
6908         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6909         aopPut(AOP(result),"a",0);
6910         goto release ;
6911     }
6912
6913     reAdjustPreg(AOP(result));
6914     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6915     emitcode("","%05d_DS_:",tlbl->key+100);    
6916     emitcode("mov","c,ov");
6917     while (size--) {
6918         l = aopGet(AOP(result),offset,FALSE,FALSE);
6919         MOVA(l);
6920         emitcode("rrc","a");         
6921         aopPut(AOP(result),"a",offset--);
6922     }
6923     reAdjustPreg(AOP(result));
6924     emitcode("","%05d_DS_:",tlbl1->key+100);
6925     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6926
6927 release:
6928     freeAsmop(left,NULL,ic,TRUE);
6929     freeAsmop(result,NULL,ic,TRUE);
6930 }
6931
6932 /*-----------------------------------------------------------------*/
6933 /* genRightShift - generate code for right shifting                */
6934 /*-----------------------------------------------------------------*/
6935 static void genRightShift (iCode *ic)
6936 {
6937     operand *right, *left, *result;
6938     sym_link *retype ;
6939     int size, offset;
6940     char *l;
6941     symbol *tlbl, *tlbl1 ;
6942
6943     /* if signed then we do it the hard way preserve the
6944     sign bit moving it inwards */
6945     retype = getSpec(operandType(IC_RESULT(ic)));
6946     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6947
6948     if (!SPEC_USIGN(retype)) {
6949         genSignedRightShift (ic);
6950         return ;
6951     }
6952
6953     /* signed & unsigned types are treated the same : i.e. the
6954     signed is NOT propagated inwards : quoting from the
6955     ANSI - standard : "for E1 >> E2, is equivalent to division
6956     by 2**E2 if unsigned or if it has a non-negative value,
6957     otherwise the result is implementation defined ", MY definition
6958     is that the sign does not get propagated */
6959
6960     right = IC_RIGHT(ic);
6961     left  = IC_LEFT(ic);
6962     result = IC_RESULT(ic);
6963
6964     aopOp(right,ic,FALSE);
6965
6966     /* if the shift count is known then do it 
6967     as efficiently as possible */
6968     if (AOP_TYPE(right) == AOP_LIT) {
6969         genRightShiftLiteral (left,right,result,ic, 0);
6970         return ;
6971     }
6972
6973     /* shift count is unknown then we have to form 
6974     a loop get the loop count in B : Note: we take
6975     only the lower order byte since shifting
6976     more that 32 bits make no sense anyway, ( the
6977     largest size of an object can be only 32 bits ) */  
6978
6979     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6980     emitcode("inc","b");
6981     freeAsmop (right,NULL,ic,TRUE);
6982     aopOp(left,ic,FALSE);
6983     aopOp(result,ic,FALSE);
6984
6985     /* now move the left to the result if they are not the
6986     same */
6987     if (!sameRegs(AOP(left),AOP(result)) && 
6988         AOP_SIZE(result) > 1) {
6989
6990         size = AOP_SIZE(result);
6991         offset=0;
6992         while (size--) {
6993             l = aopGet(AOP(left),offset,FALSE,TRUE);
6994             if (*l == '@' && IS_AOP_PREG(result)) {
6995
6996                 emitcode("mov","a,%s",l);
6997                 aopPut(AOP(result),"a",offset);
6998             } else
6999                 aopPut(AOP(result),l,offset);
7000             offset++;
7001         }
7002     }
7003
7004     tlbl = newiTempLabel(NULL);
7005     tlbl1= newiTempLabel(NULL);
7006     size = AOP_SIZE(result);
7007     offset = size - 1;
7008
7009     /* if it is only one byte then */
7010     if (size == 1) {
7011         l = aopGet(AOP(left),0,FALSE,FALSE);
7012         MOVA(l);
7013         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7014         emitcode("","%05d_DS_:",tlbl->key+100);
7015         CLRC;
7016         emitcode("rrc","a");
7017         emitcode("","%05d_DS_:",tlbl1->key+100);
7018         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7019         aopPut(AOP(result),"a",0);
7020         goto release ;
7021     }
7022
7023     reAdjustPreg(AOP(result));
7024     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7025     emitcode("","%05d_DS_:",tlbl->key+100);    
7026     CLRC;
7027     while (size--) {
7028         l = aopGet(AOP(result),offset,FALSE,FALSE);
7029         MOVA(l);
7030         emitcode("rrc","a");         
7031         aopPut(AOP(result),"a",offset--);
7032     }
7033     reAdjustPreg(AOP(result));
7034
7035     emitcode("","%05d_DS_:",tlbl1->key+100);
7036     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7037
7038 release:
7039     freeAsmop(left,NULL,ic,TRUE);
7040     freeAsmop(result,NULL,ic,TRUE);
7041 }
7042
7043 /*-----------------------------------------------------------------*/
7044 /* genUnpackBits - generates code for unpacking bits               */
7045 /*-----------------------------------------------------------------*/
7046 static void genUnpackBits (operand *result, char *rname, int ptype)
7047 {    
7048     int shCnt ;
7049     int rlen = 0 ;
7050     sym_link *etype;
7051     int offset = 0 ;
7052
7053     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7054     etype = getSpec(operandType(result));
7055
7056     /* read the first byte  */
7057     switch (ptype) {
7058
7059     case POINTER:
7060     case IPOINTER:
7061         emitcode("mov","a,@%s",rname);
7062         break;
7063         
7064     case PPOINTER:
7065         emitcode("movx","a,@%s",rname);
7066         break;
7067         
7068     case FPOINTER:
7069         emitcode("movx","a,@dptr");
7070         break;
7071
7072     case CPOINTER:
7073         emitcode("clr","a");
7074         emitcode("movc","a","@a+dptr");
7075         break;
7076
7077     case GPOINTER:
7078         emitcode("lcall","__gptrget");
7079         break;
7080     }
7081
7082     /* if we have bitdisplacement then it fits   */
7083     /* into this byte completely or if length is */
7084     /* less than a byte                          */
7085     if ((shCnt = SPEC_BSTR(etype)) || 
7086         (SPEC_BLEN(etype) <= 8))  {
7087
7088         /* shift right acc */
7089         AccRsh(shCnt);
7090
7091         emitcode("anl","a,#0x%02x",
7092                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7093         aopPut(AOP(result),"a",offset);
7094         return ;
7095     }
7096
7097     /* bit field did not fit in a byte  */
7098     rlen = SPEC_BLEN(etype) - 8;
7099     aopPut(AOP(result),"a",offset++);
7100
7101     while (1)  {
7102
7103         switch (ptype) {
7104         case POINTER:
7105         case IPOINTER:
7106             emitcode("inc","%s",rname);
7107             emitcode("mov","a,@%s",rname);
7108             break;
7109             
7110         case PPOINTER:
7111             emitcode("inc","%s",rname);
7112             emitcode("movx","a,@%s",rname);
7113             break;
7114
7115         case FPOINTER:
7116             emitcode("inc","dptr");
7117             emitcode("movx","a,@dptr");
7118             break;
7119             
7120         case CPOINTER:
7121             emitcode("clr","a");
7122             emitcode("inc","dptr");
7123             emitcode("movc","a","@a+dptr");
7124             break;
7125             
7126         case GPOINTER:
7127             emitcode("inc","dptr");
7128             emitcode("lcall","__gptrget");
7129             break;
7130         }
7131
7132         rlen -= 8;            
7133         /* if we are done */
7134         if ( rlen <= 0 )
7135             break ;
7136         
7137         aopPut(AOP(result),"a",offset++);
7138                               
7139     }
7140     
7141     if (rlen) {
7142         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7143         aopPut(AOP(result),"a",offset);        
7144     }
7145     
7146     return ;
7147 }
7148
7149
7150 /*-----------------------------------------------------------------*/
7151 /* genDataPointerGet - generates code when ptr offset is known     */
7152 /*-----------------------------------------------------------------*/
7153 static void genDataPointerGet (operand *left, 
7154                                operand *result, 
7155                                iCode *ic)
7156 {
7157     char *l;
7158     char buffer[256];
7159     int size , offset = 0;
7160     aopOp(result,ic,TRUE);
7161
7162     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7163
7164     /* get the string representation of the name */
7165     l = aopGet(AOP(left),0,FALSE,TRUE);
7166     size = AOP_SIZE(result);
7167     // tsd, was l+1 - the underline `_' prefix was being stripped
7168     while (size--) {
7169         if (offset)
7170             sprintf(buffer,"(%s + %d)",l,offset);
7171         else
7172             sprintf(buffer,"%s",l);
7173         aopPut(AOP(result),buffer,offset++);
7174     }
7175
7176     freeAsmop(left,NULL,ic,TRUE);
7177     freeAsmop(result,NULL,ic,TRUE);
7178 }
7179
7180 /*-----------------------------------------------------------------*/
7181 /* genNearPointerGet - emitcode for near pointer fetch             */
7182 /*-----------------------------------------------------------------*/
7183 static void genNearPointerGet (operand *left, 
7184                                operand *result, 
7185                                iCode *ic)
7186 {
7187     asmop *aop = NULL;
7188     regs *preg = NULL ;
7189     char *rname ;
7190     sym_link *rtype, *retype;
7191     sym_link *ltype = operandType(left);    
7192     char buffer[80];
7193
7194     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7195
7196     rtype = operandType(result);
7197     retype= getSpec(rtype);
7198     
7199     aopOp(left,ic,FALSE);
7200     
7201     /* if left is rematerialisable and
7202        result is not bit variable type and
7203        the left is pointer to data space i.e
7204        lower 128 bytes of space */
7205     if (AOP_TYPE(left) == AOP_IMMD &&
7206         !IS_BITVAR(retype)         &&
7207         DCL_TYPE(ltype) == POINTER) {
7208         genDataPointerGet (left,result,ic);
7209         return ;
7210     }
7211     
7212         /* if the value is already in a pointer register
7213        then don't need anything more */
7214     if (!AOP_INPREG(AOP(left))) {
7215         /* otherwise get a free pointer register */
7216         aop = newAsmop(0);
7217         preg = getFreePtr(ic,&aop,FALSE);
7218         emitcode("mov","%s,%s",
7219                 preg->name,
7220                 aopGet(AOP(left),0,FALSE,TRUE));
7221         rname = preg->name ;
7222     } else
7223         rname = aopGet(AOP(left),0,FALSE,FALSE);
7224     
7225     freeAsmop(left,NULL,ic,TRUE);
7226     aopOp (result,ic,FALSE);
7227     
7228       /* if bitfield then unpack the bits */
7229     if (IS_BITVAR(retype)) 
7230         genUnpackBits (result,rname,POINTER);
7231     else {
7232         /* we have can just get the values */
7233         int size = AOP_SIZE(result);
7234         int offset = 0 ;        
7235         
7236         while (size--) {
7237             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7238
7239                 emitcode("mov","a,@%s",rname);
7240                 aopPut(AOP(result),"a",offset);
7241             } else {
7242                 sprintf(buffer,"@%s",rname);
7243                 aopPut(AOP(result),buffer,offset);
7244             }
7245             offset++ ;
7246             if (size)
7247                 emitcode("inc","%s",rname);
7248         }
7249     }
7250
7251     /* now some housekeeping stuff */
7252     if (aop) {
7253         /* we had to allocate for this iCode */
7254         freeAsmop(NULL,aop,ic,TRUE);
7255     } else { 
7256         /* we did not allocate which means left
7257            already in a pointer register, then
7258            if size > 0 && this could be used again
7259            we have to point it back to where it 
7260            belongs */
7261         if (AOP_SIZE(result) > 1 &&
7262             !OP_SYMBOL(left)->remat &&
7263             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7264               ic->depth )) {
7265             int size = AOP_SIZE(result) - 1;
7266             while (size--)
7267                 emitcode("dec","%s",rname);
7268         }
7269     }
7270
7271     /* done */
7272     freeAsmop(result,NULL,ic,TRUE);
7273      
7274 }
7275
7276 /*-----------------------------------------------------------------*/
7277 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7278 /*-----------------------------------------------------------------*/
7279 static void genPagedPointerGet (operand *left, 
7280                                operand *result, 
7281                                iCode *ic)
7282 {
7283     asmop *aop = NULL;
7284     regs *preg = NULL ;
7285     char *rname ;
7286     sym_link *rtype, *retype;    
7287
7288     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7289
7290     rtype = operandType(result);
7291     retype= getSpec(rtype);
7292     
7293     aopOp(left,ic,FALSE);
7294
7295   /* if the value is already in a pointer register
7296        then don't need anything more */
7297     if (!AOP_INPREG(AOP(left))) {
7298         /* otherwise get a free pointer register */
7299         aop = newAsmop(0);
7300         preg = getFreePtr(ic,&aop,FALSE);
7301         emitcode("mov","%s,%s",
7302                 preg->name,
7303                 aopGet(AOP(left),0,FALSE,TRUE));
7304         rname = preg->name ;
7305     } else
7306         rname = aopGet(AOP(left),0,FALSE,FALSE);
7307     
7308     freeAsmop(left,NULL,ic,TRUE);
7309     aopOp (result,ic,FALSE);
7310
7311     /* if bitfield then unpack the bits */
7312     if (IS_BITVAR(retype)) 
7313         genUnpackBits (result,rname,PPOINTER);
7314     else {
7315         /* we have can just get the values */
7316         int size = AOP_SIZE(result);
7317         int offset = 0 ;        
7318         
7319         while (size--) {
7320             
7321             emitcode("movx","a,@%s",rname);
7322             aopPut(AOP(result),"a",offset);
7323             
7324             offset++ ;
7325             
7326             if (size)
7327                 emitcode("inc","%s",rname);
7328         }
7329     }
7330
7331     /* now some housekeeping stuff */
7332     if (aop) {
7333         /* we had to allocate for this iCode */
7334         freeAsmop(NULL,aop,ic,TRUE);
7335     } else { 
7336         /* we did not allocate which means left
7337            already in a pointer register, then
7338            if size > 0 && this could be used again
7339            we have to point it back to where it 
7340            belongs */
7341         if (AOP_SIZE(result) > 1 &&
7342             !OP_SYMBOL(left)->remat &&
7343             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7344               ic->depth )) {
7345             int size = AOP_SIZE(result) - 1;
7346             while (size--)
7347                 emitcode("dec","%s",rname);
7348         }
7349     }
7350
7351     /* done */
7352     freeAsmop(result,NULL,ic,TRUE);
7353     
7354         
7355 }
7356
7357 /*-----------------------------------------------------------------*/
7358 /* genFarPointerGet - gget value from far space                    */
7359 /*-----------------------------------------------------------------*/
7360 static void genFarPointerGet (operand *left,
7361                               operand *result, iCode *ic)
7362 {
7363     int size, offset ;
7364     sym_link *retype = getSpec(operandType(result));
7365
7366     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7367
7368     aopOp(left,ic,FALSE);
7369
7370     /* if the operand is already in dptr 
7371     then we do nothing else we move the value to dptr */
7372     if (AOP_TYPE(left) != AOP_STR) {
7373         /* if this is remateriazable */
7374         if (AOP_TYPE(left) == AOP_IMMD)
7375             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7376         else { /* we need to get it byte by byte */
7377             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7378             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7379             if (options.model == MODEL_FLAT24)
7380             {
7381                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7382             }
7383         }
7384     }
7385     /* so dptr know contains the address */
7386     freeAsmop(left,NULL,ic,TRUE);
7387     aopOp(result,ic,FALSE);
7388
7389     /* if bit then unpack */
7390     if (IS_BITVAR(retype)) 
7391         genUnpackBits(result,"dptr",FPOINTER);
7392     else {
7393         size = AOP_SIZE(result);
7394         offset = 0 ;
7395
7396         while (size--) {
7397             emitcode("movx","a,@dptr");
7398             aopPut(AOP(result),"a",offset++);
7399             if (size)
7400                 emitcode("inc","dptr");
7401         }
7402     }
7403
7404     freeAsmop(result,NULL,ic,TRUE);
7405 }
7406
7407 /*-----------------------------------------------------------------*/
7408 /* emitcodePointerGet - gget value from code space                  */
7409 /*-----------------------------------------------------------------*/
7410 static void emitcodePointerGet (operand *left,
7411                                 operand *result, iCode *ic)
7412 {
7413     int size, offset ;
7414     sym_link *retype = getSpec(operandType(result));
7415
7416     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7417
7418     aopOp(left,ic,FALSE);
7419
7420     /* if the operand is already in dptr 
7421     then we do nothing else we move the value to dptr */
7422     if (AOP_TYPE(left) != AOP_STR) {
7423         /* if this is remateriazable */
7424         if (AOP_TYPE(left) == AOP_IMMD)
7425             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7426         else { /* we need to get it byte by byte */
7427             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7428             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7429             if (options.model == MODEL_FLAT24)
7430             {
7431                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7432             }
7433         }
7434     }
7435     /* so dptr know contains the address */
7436     freeAsmop(left,NULL,ic,TRUE);
7437     aopOp(result,ic,FALSE);
7438
7439     /* if bit then unpack */
7440     if (IS_BITVAR(retype)) 
7441         genUnpackBits(result,"dptr",CPOINTER);
7442     else {
7443         size = AOP_SIZE(result);
7444         offset = 0 ;
7445
7446         while (size--) {
7447             emitcode("clr","a");
7448             emitcode("movc","a,@a+dptr");
7449             aopPut(AOP(result),"a",offset++);
7450             if (size)
7451                 emitcode("inc","dptr");
7452         }
7453     }
7454
7455     freeAsmop(result,NULL,ic,TRUE);
7456 }
7457
7458 /*-----------------------------------------------------------------*/
7459 /* genGenPointerGet - gget value from generic pointer space        */
7460 /*-----------------------------------------------------------------*/
7461 static void genGenPointerGet (operand *left,
7462                               operand *result, iCode *ic)
7463 {
7464     int size, offset ;
7465     sym_link *retype = getSpec(operandType(result));
7466
7467     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7468     aopOp(left,ic,FALSE);
7469
7470     /* if the operand is already in dptr 
7471     then we do nothing else we move the value to dptr */
7472     if (AOP_TYPE(left) != AOP_STR) {
7473         /* if this is remateriazable */
7474         if (AOP_TYPE(left) == AOP_IMMD) {
7475             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7476             emitcode("mov","b,#%d",pointerCode(retype));
7477         }
7478         else { /* we need to get it byte by byte */
7479           
7480           emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7481           emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7482           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7483           emitcode("movwf","FSR");
7484           /*
7485             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7486             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7487             if (options.model == MODEL_FLAT24)
7488             {
7489                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7490                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7491             }
7492             else
7493             {
7494                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7495             }
7496           */
7497         }
7498     }
7499     /* so dptr know contains the address */
7500     freeAsmop(left,NULL,ic,TRUE);
7501     aopOp(result,ic,FALSE); 
7502
7503     /* if bit then unpack */
7504     if (IS_BITVAR(retype)) 
7505         genUnpackBits(result,"dptr",GPOINTER);
7506     else {
7507         size = AOP_SIZE(result);
7508         offset = 0 ;
7509
7510         while (size--) {
7511           emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7512           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7513           if(size)
7514             emitpcode(POC_INCF,popCopy(&pc_fsr));
7515 /*
7516           emitcode("movf","indf,w");
7517           emitcode("movwf","%s",
7518                    aopGet(AOP(result),offset++,FALSE,FALSE));
7519           if (size)
7520             emitcode("incf","fsr,f");
7521 */
7522         }
7523     }
7524
7525     freeAsmop(result,NULL,ic,TRUE);
7526 }
7527
7528 /*-----------------------------------------------------------------*/
7529 /* genPointerGet - generate code for pointer get                   */
7530 /*-----------------------------------------------------------------*/
7531 static void genPointerGet (iCode *ic)
7532 {
7533     operand *left, *result ;
7534     sym_link *type, *etype;
7535     int p_type;
7536
7537     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7538
7539     left = IC_LEFT(ic);
7540     result = IC_RESULT(ic) ;
7541
7542     /* depending on the type of pointer we need to
7543     move it to the correct pointer register */
7544     type = operandType(left);
7545     etype = getSpec(type);
7546     /* if left is of type of pointer then it is simple */
7547     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7548         p_type = DCL_TYPE(type);
7549     else {
7550         /* we have to go by the storage class */
7551         p_type = PTR_TYPE(SPEC_OCLS(etype));
7552
7553 /*      if (SPEC_OCLS(etype)->codesp ) { */
7554 /*          p_type = CPOINTER ;  */
7555 /*      } */
7556 /*      else */
7557 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7558 /*              p_type = FPOINTER ; */
7559 /*          else */
7560 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7561 /*                  p_type = PPOINTER; */
7562 /*              else */
7563 /*                  if (SPEC_OCLS(etype) == idata ) */
7564 /*                      p_type = IPOINTER; */
7565 /*                  else */
7566 /*                      p_type = POINTER ; */
7567     }
7568
7569     /* now that we have the pointer type we assign
7570     the pointer values */
7571     switch (p_type) {
7572
7573     case POINTER:       
7574     case IPOINTER:
7575         genNearPointerGet (left,result,ic);
7576         break;
7577
7578     case PPOINTER:
7579         genPagedPointerGet(left,result,ic);
7580         break;
7581
7582     case FPOINTER:
7583         genFarPointerGet (left,result,ic);
7584         break;
7585
7586     case CPOINTER:
7587         emitcodePointerGet (left,result,ic);
7588         break;
7589
7590     case GPOINTER:
7591         genGenPointerGet (left,result,ic);
7592         break;
7593     }
7594
7595 }
7596
7597 /*-----------------------------------------------------------------*/
7598 /* genPackBits - generates code for packed bit storage             */
7599 /*-----------------------------------------------------------------*/
7600 static void genPackBits (sym_link    *etype ,
7601                          operand *right ,
7602                          char *rname, int p_type)
7603 {
7604     int shCount = 0 ;
7605     int offset = 0  ;
7606     int rLen = 0 ;
7607     int blen, bstr ;   
7608     char *l ;
7609
7610     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7611     blen = SPEC_BLEN(etype);
7612     bstr = SPEC_BSTR(etype);
7613
7614     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7615     MOVA(l);   
7616
7617     /* if the bit lenth is less than or    */
7618     /* it exactly fits a byte then         */
7619     if (SPEC_BLEN(etype) <= 8 )  {
7620         shCount = SPEC_BSTR(etype) ;
7621
7622         /* shift left acc */
7623         AccLsh(shCount);
7624
7625         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7626
7627
7628             switch (p_type) {
7629                 case POINTER:
7630                     emitcode ("mov","b,a");
7631                     emitcode("mov","a,@%s",rname);
7632                     break;
7633
7634                 case FPOINTER:
7635                     emitcode ("mov","b,a");
7636                     emitcode("movx","a,@dptr");
7637                     break;
7638
7639                 case GPOINTER:
7640                     emitcode ("push","b");
7641                     emitcode ("push","acc");
7642                     emitcode ("lcall","__gptrget");
7643                     emitcode ("pop","b");
7644                     break;
7645             }
7646
7647             emitcode ("anl","a,#0x%02x",(unsigned char)
7648                       ((unsigned char)(0xFF << (blen+bstr)) | 
7649                        (unsigned char)(0xFF >> (8-bstr)) ) );
7650             emitcode ("orl","a,b");
7651             if (p_type == GPOINTER)
7652                 emitcode("pop","b");
7653         }
7654     }
7655
7656     switch (p_type) {
7657         case POINTER:
7658             emitcode("mov","@%s,a",rname);
7659             break;
7660
7661         case FPOINTER:
7662             emitcode("movx","@dptr,a");
7663             break;
7664
7665         case GPOINTER:
7666             DEBUGemitcode(";lcall","__gptrput");
7667             break;
7668     }
7669
7670     /* if we r done */
7671     if ( SPEC_BLEN(etype) <= 8 )
7672         return ;
7673
7674     emitcode("inc","%s",rname);
7675     rLen = SPEC_BLEN(etype) ;     
7676
7677     /* now generate for lengths greater than one byte */
7678     while (1) {
7679
7680         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7681
7682         rLen -= 8 ;
7683         if (rLen <= 0 )
7684             break ;
7685
7686         switch (p_type) {
7687             case POINTER:
7688                 if (*l == '@') {
7689                     MOVA(l);
7690                     emitcode("mov","@%s,a",rname);
7691                 } else
7692                     emitcode("mov","@%s,%s",rname,l);
7693                 break;
7694
7695             case FPOINTER:
7696                 MOVA(l);
7697                 emitcode("movx","@dptr,a");
7698                 break;
7699
7700             case GPOINTER:
7701                 MOVA(l);
7702                 DEBUGemitcode(";lcall","__gptrput");
7703                 break;  
7704         }   
7705         emitcode ("inc","%s",rname);
7706     }
7707
7708     MOVA(l);
7709
7710     /* last last was not complete */
7711     if (rLen)   {
7712         /* save the byte & read byte */
7713         switch (p_type) {
7714             case POINTER:
7715                 emitcode ("mov","b,a");
7716                 emitcode("mov","a,@%s",rname);
7717                 break;
7718
7719             case FPOINTER:
7720                 emitcode ("mov","b,a");
7721                 emitcode("movx","a,@dptr");
7722                 break;
7723
7724             case GPOINTER:
7725                 emitcode ("push","b");
7726                 emitcode ("push","acc");
7727                 emitcode ("lcall","__gptrget");
7728                 emitcode ("pop","b");
7729                 break;
7730         }
7731
7732         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7733         emitcode ("orl","a,b");
7734     }
7735
7736     if (p_type == GPOINTER)
7737         emitcode("pop","b");
7738
7739     switch (p_type) {
7740
7741     case POINTER:
7742         emitcode("mov","@%s,a",rname);
7743         break;
7744         
7745     case FPOINTER:
7746         emitcode("movx","@dptr,a");
7747         break;
7748         
7749     case GPOINTER:
7750         DEBUGemitcode(";lcall","__gptrput");
7751         break;                  
7752     }
7753 }
7754 /*-----------------------------------------------------------------*/
7755 /* genDataPointerSet - remat pointer to data space                 */
7756 /*-----------------------------------------------------------------*/
7757 static void genDataPointerSet(operand *right,
7758                               operand *result,
7759                               iCode *ic)
7760 {
7761     int size, offset = 0 ;
7762     char *l, buffer[256];
7763
7764     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7765     aopOp(right,ic,FALSE);
7766     
7767     l = aopGet(AOP(result),0,FALSE,TRUE);
7768     size = AOP_SIZE(right);
7769     // tsd, was l+1 - the underline `_' prefix was being stripped
7770     while (size--) {
7771         if (offset)
7772             sprintf(buffer,"(%s + %d)",l,offset);
7773         else
7774             sprintf(buffer,"%s",l);
7775
7776         if (AOP_TYPE(right) == AOP_LIT) {
7777           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7778           lit = lit >> (8*offset);
7779           if(lit) {
7780             emitcode("movlw","%s",lit);
7781             emitcode("movwf","%s",buffer);
7782           } else 
7783             emitcode("clrf","%s",buffer);
7784         }else {
7785           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7786           emitcode("movwf","%s",buffer);
7787         }
7788
7789         offset++;
7790     }
7791
7792     freeAsmop(right,NULL,ic,TRUE);
7793     freeAsmop(result,NULL,ic,TRUE);
7794 }
7795
7796 /*-----------------------------------------------------------------*/
7797 /* genNearPointerSet - emitcode for near pointer put                */
7798 /*-----------------------------------------------------------------*/
7799 static void genNearPointerSet (operand *right,
7800                                operand *result, 
7801                                iCode *ic)
7802 {
7803     asmop *aop = NULL;
7804     char *l;
7805     sym_link *retype;
7806     sym_link *ptype = operandType(result);
7807
7808     
7809     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7810     retype= getSpec(operandType(right));
7811
7812     aopOp(result,ic,FALSE);
7813     
7814     /* if the result is rematerializable &
7815        in data space & not a bit variable */
7816     if (AOP_TYPE(result) == AOP_IMMD &&
7817         DCL_TYPE(ptype) == POINTER   &&
7818         !IS_BITVAR(retype)) {
7819         genDataPointerSet (right,result,ic);
7820         return;
7821     }
7822
7823     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7824
7825     /* if the value is already in a pointer register
7826     then don't need anything more */
7827     if (!AOP_INPREG(AOP(result))) {
7828         /* otherwise get a free pointer register */
7829         //aop = newAsmop(0);
7830         //preg = getFreePtr(ic,&aop,FALSE);
7831         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7832         //emitcode("mov","%s,%s",
7833         //         preg->name,
7834         //         aopGet(AOP(result),0,FALSE,TRUE));
7835         //rname = preg->name ;
7836         emitcode("movwf","fsr");
7837     }// else
7838     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7839
7840     freeAsmop(result,NULL,ic,TRUE);
7841     aopOp (right,ic,FALSE);
7842     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7843
7844     /* if bitfield then unpack the bits */
7845     if (IS_BITVAR(retype)) {
7846       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7847              "The programmer is obviously confused");
7848       //genPackBits (retype,right,rname,POINTER);
7849       exit(1);
7850     }
7851     else {
7852         /* we have can just get the values */
7853         int size = AOP_SIZE(right);
7854         int offset = 0 ;    
7855
7856     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7857         while (size--) {
7858             l = aopGet(AOP(right),offset,FALSE,TRUE);
7859             if (*l == '@' ) {
7860               //MOVA(l);
7861               //emitcode("mov","@%s,a",rname);
7862               emitcode("movf","indf,w ;1");
7863             } else {
7864
7865               if (AOP_TYPE(right) == AOP_LIT) {
7866                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7867                 if(lit) {
7868                   emitcode("movlw","%s",l);
7869                   emitcode("movwf","indf ;2");
7870                 } else 
7871                   emitcode("clrf","indf");
7872               }else {
7873                 emitcode("movf","%s,w",l);
7874                 emitcode("movwf","indf ;2");
7875               }
7876             //emitcode("mov","@%s,%s",rname,l);
7877             }
7878             if (size)
7879               emitcode("incf","fsr,f ;3");
7880             //emitcode("inc","%s",rname);
7881             offset++;
7882         }
7883     }
7884
7885     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7886     /* now some housekeeping stuff */
7887     if (aop) {
7888         /* we had to allocate for this iCode */
7889         freeAsmop(NULL,aop,ic,TRUE);
7890     } else { 
7891         /* we did not allocate which means left
7892         already in a pointer register, then
7893         if size > 0 && this could be used again
7894         we have to point it back to where it 
7895         belongs */
7896     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7897         if (AOP_SIZE(right) > 1 &&
7898             !OP_SYMBOL(result)->remat &&
7899             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7900               ic->depth )) {
7901             int size = AOP_SIZE(right) - 1;
7902             while (size--)
7903               emitcode("decf","fsr,f");
7904               //emitcode("dec","%s",rname);
7905         }
7906     }
7907
7908     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7909     /* done */
7910     freeAsmop(right,NULL,ic,TRUE);
7911
7912
7913 }
7914
7915 /*-----------------------------------------------------------------*/
7916 /* genPagedPointerSet - emitcode for Paged pointer put             */
7917 /*-----------------------------------------------------------------*/
7918 static void genPagedPointerSet (operand *right,
7919                                operand *result, 
7920                                iCode *ic)
7921 {
7922     asmop *aop = NULL;
7923     regs *preg = NULL ;
7924     char *rname , *l;
7925     sym_link *retype;
7926        
7927     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7928
7929     retype= getSpec(operandType(right));
7930     
7931     aopOp(result,ic,FALSE);
7932     
7933     /* if the value is already in a pointer register
7934        then don't need anything more */
7935     if (!AOP_INPREG(AOP(result))) {
7936         /* otherwise get a free pointer register */
7937         aop = newAsmop(0);
7938         preg = getFreePtr(ic,&aop,FALSE);
7939         emitcode("mov","%s,%s",
7940                 preg->name,
7941                 aopGet(AOP(result),0,FALSE,TRUE));
7942         rname = preg->name ;
7943     } else
7944         rname = aopGet(AOP(result),0,FALSE,FALSE);
7945     
7946     freeAsmop(result,NULL,ic,TRUE);
7947     aopOp (right,ic,FALSE);
7948
7949     /* if bitfield then unpack the bits */
7950     if (IS_BITVAR(retype)) 
7951         genPackBits (retype,right,rname,PPOINTER);
7952     else {
7953         /* we have can just get the values */
7954         int size = AOP_SIZE(right);
7955         int offset = 0 ;        
7956         
7957         while (size--) {
7958             l = aopGet(AOP(right),offset,FALSE,TRUE);
7959             
7960             MOVA(l);
7961             emitcode("movx","@%s,a",rname);
7962
7963             if (size)
7964                 emitcode("inc","%s",rname);
7965
7966             offset++;
7967         }
7968     }
7969     
7970     /* now some housekeeping stuff */
7971     if (aop) {
7972         /* we had to allocate for this iCode */
7973         freeAsmop(NULL,aop,ic,TRUE);
7974     } else { 
7975         /* we did not allocate which means left
7976            already in a pointer register, then
7977            if size > 0 && this could be used again
7978            we have to point it back to where it 
7979            belongs */
7980         if (AOP_SIZE(right) > 1 &&
7981             !OP_SYMBOL(result)->remat &&
7982             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7983               ic->depth )) {
7984             int size = AOP_SIZE(right) - 1;
7985             while (size--)
7986                 emitcode("dec","%s",rname);
7987         }
7988     }
7989
7990     /* done */
7991     freeAsmop(right,NULL,ic,TRUE);
7992     
7993         
7994 }
7995
7996 /*-----------------------------------------------------------------*/
7997 /* genFarPointerSet - set value from far space                     */
7998 /*-----------------------------------------------------------------*/
7999 static void genFarPointerSet (operand *right,
8000                               operand *result, iCode *ic)
8001 {
8002     int size, offset ;
8003     sym_link *retype = getSpec(operandType(right));
8004
8005     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8006     aopOp(result,ic,FALSE);
8007
8008     /* if the operand is already in dptr 
8009     then we do nothing else we move the value to dptr */
8010     if (AOP_TYPE(result) != AOP_STR) {
8011         /* if this is remateriazable */
8012         if (AOP_TYPE(result) == AOP_IMMD)
8013             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8014         else { /* we need to get it byte by byte */
8015             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8016             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8017             if (options.model == MODEL_FLAT24)
8018             {
8019                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8020             }
8021         }
8022     }
8023     /* so dptr know contains the address */
8024     freeAsmop(result,NULL,ic,TRUE);
8025     aopOp(right,ic,FALSE);
8026
8027     /* if bit then unpack */
8028     if (IS_BITVAR(retype)) 
8029         genPackBits(retype,right,"dptr",FPOINTER);
8030     else {
8031         size = AOP_SIZE(right);
8032         offset = 0 ;
8033
8034         while (size--) {
8035             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8036             MOVA(l);
8037             emitcode("movx","@dptr,a");
8038             if (size)
8039                 emitcode("inc","dptr");
8040         }
8041     }
8042
8043     freeAsmop(right,NULL,ic,TRUE);
8044 }
8045
8046 /*-----------------------------------------------------------------*/
8047 /* genGenPointerSet - set value from generic pointer space         */
8048 /*-----------------------------------------------------------------*/
8049 static void genGenPointerSet (operand *right,
8050                               operand *result, iCode *ic)
8051 {
8052     int size, offset ;
8053     sym_link *retype = getSpec(operandType(right));
8054
8055     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8056
8057     aopOp(result,ic,FALSE);
8058
8059     /* if the operand is already in dptr 
8060     then we do nothing else we move the value to dptr */
8061     if (AOP_TYPE(result) != AOP_STR) {
8062         /* if this is remateriazable */
8063         if (AOP_TYPE(result) == AOP_IMMD) {
8064             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8065             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8066         }
8067         else { /* we need to get it byte by byte */
8068           char *l = aopGet(AOP(result),0,FALSE,FALSE);
8069
8070           if(strcmp("FSR",l))
8071             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8072           emitpcode(POC_MOVWF,popCopy(&pc_indf));
8073
8074           if(strcmp("FSR",l))
8075             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8076
8077           emitcode("movwf","INDF");
8078         }
8079     }
8080     /* so dptr know contains the address */
8081     freeAsmop(result,NULL,ic,TRUE);
8082     aopOp(right,ic,FALSE);
8083
8084     /* if bit then unpack */
8085     if (IS_BITVAR(retype)) 
8086         genPackBits(retype,right,"dptr",GPOINTER);
8087     else {
8088         size = AOP_SIZE(right);
8089         offset = 0 ;
8090
8091         while (--size) {
8092             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8093             if(size)
8094               emitcode("incf","fsr,f");
8095             emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8096             emitcode("movwf","indf");
8097             //MOVA(l);
8098             //DEBUGemitcode(";lcall","__gptrput");
8099             //if (size)
8100             //    emitcode("inc","dptr");
8101         }
8102     }
8103
8104     freeAsmop(right,NULL,ic,TRUE);
8105 }
8106
8107 /*-----------------------------------------------------------------*/
8108 /* genPointerSet - stores the value into a pointer location        */
8109 /*-----------------------------------------------------------------*/
8110 static void genPointerSet (iCode *ic)
8111 {    
8112     operand *right, *result ;
8113     sym_link *type, *etype;
8114     int p_type;
8115
8116     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8117
8118     right = IC_RIGHT(ic);
8119     result = IC_RESULT(ic) ;
8120
8121     /* depending on the type of pointer we need to
8122     move it to the correct pointer register */
8123     type = operandType(result);
8124     etype = getSpec(type);
8125     /* if left is of type of pointer then it is simple */
8126     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8127         p_type = DCL_TYPE(type);
8128     }
8129     else {
8130         /* we have to go by the storage class */
8131         p_type = PTR_TYPE(SPEC_OCLS(etype));
8132
8133 /*      if (SPEC_OCLS(etype)->codesp ) { */
8134 /*          p_type = CPOINTER ;  */
8135 /*      } */
8136 /*      else */
8137 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8138 /*              p_type = FPOINTER ; */
8139 /*          else */
8140 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8141 /*                  p_type = PPOINTER ; */
8142 /*              else */
8143 /*                  if (SPEC_OCLS(etype) == idata ) */
8144 /*                      p_type = IPOINTER ; */
8145 /*                  else */
8146 /*                      p_type = POINTER ; */
8147     }
8148
8149     /* now that we have the pointer type we assign
8150     the pointer values */
8151     switch (p_type) {
8152
8153     case POINTER:
8154     case IPOINTER:
8155         genNearPointerSet (right,result,ic);
8156         break;
8157
8158     case PPOINTER:
8159         genPagedPointerSet (right,result,ic);
8160         break;
8161
8162     case FPOINTER:
8163         genFarPointerSet (right,result,ic);
8164         break;
8165
8166     case GPOINTER:
8167         genGenPointerSet (right,result,ic);
8168         break;
8169     }
8170
8171 }
8172
8173 /*-----------------------------------------------------------------*/
8174 /* genIfx - generate code for Ifx statement                        */
8175 /*-----------------------------------------------------------------*/
8176 static void genIfx (iCode *ic, iCode *popIc)
8177 {
8178     operand *cond = IC_COND(ic);
8179     int isbit =0;
8180
8181     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8182     aopOp(cond,ic,FALSE);
8183
8184     /* get the value into acc */
8185     if (AOP_TYPE(cond) != AOP_CRY)
8186         toBoolean(cond);
8187     else
8188         isbit = 1;
8189     /* the result is now in the accumulator */
8190     freeAsmop(cond,NULL,ic,TRUE);
8191
8192     /* if there was something to be popped then do it */
8193     if (popIc)
8194         genIpop(popIc);
8195
8196     /* if the condition is  a bit variable */
8197     if (isbit && IS_ITEMP(cond) && 
8198         SPIL_LOC(cond)) {
8199       genIfxJump(ic,SPIL_LOC(cond)->rname);
8200       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8201     }
8202     else {
8203       /*
8204         if (isbit && !IS_ITEMP(cond))
8205           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8206         else
8207           DEBUGemitcode ("; isbit","a");
8208       */
8209
8210         if (isbit && !IS_ITEMP(cond))
8211             genIfxJump(ic,OP_SYMBOL(cond)->rname);
8212         else
8213             genIfxJump(ic,"a");
8214     }
8215     ic->generated = 1;
8216 }
8217
8218 /*-----------------------------------------------------------------*/
8219 /* genAddrOf - generates code for address of                       */
8220 /*-----------------------------------------------------------------*/
8221 static void genAddrOf (iCode *ic)
8222 {
8223     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8224     int size, offset ;
8225
8226     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8227
8228     aopOp(IC_RESULT(ic),ic,FALSE);
8229
8230     /* if the operand is on the stack then we 
8231     need to get the stack offset of this
8232     variable */
8233     if (sym->onStack) {
8234         /* if it has an offset then we need to compute
8235         it */
8236         if (sym->stack) {
8237             emitcode("mov","a,_bp");
8238             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8239             aopPut(AOP(IC_RESULT(ic)),"a",0);       
8240         } else {
8241             /* we can just move _bp */
8242             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8243         }
8244         /* fill the result with zero */
8245         size = AOP_SIZE(IC_RESULT(ic)) - 1;
8246         
8247         
8248         if (options.stack10bit && size < (FPTRSIZE - 1))
8249         {
8250             fprintf(stderr, 
8251                     "*** warning: pointer to stack var truncated.\n");
8252         }
8253         
8254         offset = 1;
8255         while (size--)
8256         {
8257             /* Yuck! */
8258             if (options.stack10bit && offset == 2)
8259             {
8260                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8261             }
8262             else
8263             {
8264                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8265             }
8266         }
8267
8268         goto release;
8269     }
8270
8271     /* object not on stack then we need the name */
8272     size = AOP_SIZE(IC_RESULT(ic));
8273     offset = 0;
8274
8275     while (size--) {
8276         char s[SDCC_NAME_MAX];
8277         if (offset) 
8278             sprintf(s,"#(%s >> %d)",
8279                     sym->rname,
8280                     offset*8);
8281         else
8282             sprintf(s,"#%s",sym->rname);
8283         aopPut(AOP(IC_RESULT(ic)),s,offset++);
8284     }
8285
8286 release:
8287     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8288
8289 }
8290
8291 #if 0
8292 /*-----------------------------------------------------------------*/
8293 /* genFarFarAssign - assignment when both are in far space         */
8294 /*-----------------------------------------------------------------*/
8295 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8296 {
8297     int size = AOP_SIZE(right);
8298     int offset = 0;
8299     char *l ;
8300     /* first push the right side on to the stack */
8301     while (size--) {
8302         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8303         MOVA(l);
8304         emitcode ("push","acc");
8305     }
8306     
8307     freeAsmop(right,NULL,ic,FALSE);
8308     /* now assign DPTR to result */
8309     aopOp(result,ic,FALSE);
8310     size = AOP_SIZE(result);
8311     while (size--) {
8312         emitcode ("pop","acc");
8313         aopPut(AOP(result),"a",--offset);
8314     }
8315     freeAsmop(result,NULL,ic,FALSE);
8316         
8317 }
8318 #endif
8319
8320 /*-----------------------------------------------------------------*/
8321 /* genAssign - generate code for assignment                        */
8322 /*-----------------------------------------------------------------*/
8323 static void genAssign (iCode *ic)
8324 {
8325     operand *result, *right;
8326     int size, offset ;
8327         unsigned long lit = 0L;
8328
8329     result = IC_RESULT(ic);
8330     right  = IC_RIGHT(ic) ;
8331
8332     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8333
8334     /* if they are the same */
8335     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8336         return ;
8337
8338     aopOp(right,ic,FALSE);
8339     aopOp(result,ic,TRUE);
8340
8341     /* if they are the same registers */
8342     if (sameRegs(AOP(right),AOP(result)))
8343         goto release;
8344
8345     /* if the result is a bit */
8346     if (AOP_TYPE(result) == AOP_CRY) {
8347
8348         /* if the right size is a literal then
8349         we know what the value is */
8350         if (AOP_TYPE(right) == AOP_LIT) {
8351           
8352           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8353                       popGet(AOP(result),0,FALSE,FALSE));
8354
8355             if (((int) operandLitValue(right))) 
8356               emitcode("bsf","(%s >> 3),(%s & 7)",
8357                        AOP(result)->aopu.aop_dir,
8358                        AOP(result)->aopu.aop_dir);
8359             else
8360               emitcode("bcf","(%s >> 3),(%s & 7)",
8361                  AOP(result)->aopu.aop_dir,
8362                  AOP(result)->aopu.aop_dir);
8363             goto release;
8364         }
8365
8366         /* the right is also a bit variable */
8367         if (AOP_TYPE(right) == AOP_CRY) {
8368           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8369           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8370           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8371
8372           emitcode("bcf","(%s >> 3),(%s & 7)",
8373                    AOP(result)->aopu.aop_dir,
8374                    AOP(result)->aopu.aop_dir);
8375           emitcode("btfsc","(%s >> 3),(%s & 7)",
8376                    AOP(right)->aopu.aop_dir,
8377                    AOP(right)->aopu.aop_dir);
8378           emitcode("bsf","(%s >> 3),(%s & 7)",
8379                    AOP(result)->aopu.aop_dir,
8380                    AOP(result)->aopu.aop_dir);
8381           goto release ;
8382         }
8383
8384         /* we need to or */
8385         toBoolean(right);
8386         aopPut(AOP(result),"a",0);
8387         goto release ;
8388     }
8389
8390     /* bit variables done */
8391     /* general case */
8392     size = AOP_SIZE(result);
8393     offset = 0 ;
8394     if(AOP_TYPE(right) == AOP_LIT)
8395         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8396     if((AOP_TYPE(result) != AOP_REG) &&
8397        (AOP_TYPE(right) == AOP_LIT) &&
8398        !IS_FLOAT(operandType(right)) &&
8399        (lit < 256L)){
8400
8401         while (size--) {
8402           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8403             //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8404               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8405             }else {
8406               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8407               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8408               //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8409               //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8410             }
8411         }
8412     } else {
8413         while (size--) {
8414           if(AOP_TYPE(right) == AOP_LIT)
8415             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8416           //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8417           else
8418             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8419           //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8420             
8421           emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8422           //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8423           offset++;
8424         }
8425     }
8426     
8427 release:
8428     freeAsmop (right,NULL,ic,FALSE);
8429     freeAsmop (result,NULL,ic,TRUE);
8430 }   
8431
8432 /*-----------------------------------------------------------------*/
8433 /* genJumpTab - genrates code for jump table                       */
8434 /*-----------------------------------------------------------------*/
8435 static void genJumpTab (iCode *ic)
8436 {
8437     symbol *jtab;
8438     char *l;
8439
8440     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441
8442     aopOp(IC_JTCOND(ic),ic,FALSE);
8443     /* get the condition into accumulator */
8444     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8445     MOVA(l);
8446     /* multiply by three */
8447     emitcode("add","a,acc");
8448     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8449     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8450
8451     jtab = newiTempLabel(NULL);
8452     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8453     emitcode("jmp","@a+dptr");
8454     emitcode("","%05d_DS_:",jtab->key+100);
8455     /* now generate the jump labels */
8456     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8457          jtab = setNextItem(IC_JTLABELS(ic)))
8458         emitcode("ljmp","%05d_DS_",jtab->key+100);
8459
8460 }
8461
8462 /*-----------------------------------------------------------------*/
8463 /* genMixedOperation - gen code for operators between mixed types  */
8464 /*-----------------------------------------------------------------*/
8465 /*
8466   TSD - Written for the PIC port - but this unfortunately is buggy.
8467   This routine is good in that it is able to efficiently promote 
8468   types to different (larger) sizes. Unfortunately, the temporary
8469   variables that are optimized out by this routine are sometimes
8470   used in other places. So until I know how to really parse the 
8471   iCode tree, I'm going to not be using this routine :(.
8472 */
8473 static int genMixedOperation (iCode *ic)
8474 {
8475 #if 0
8476   operand *result = IC_RESULT(ic);
8477   sym_link *ctype = operandType(IC_LEFT(ic));
8478   operand *right = IC_RIGHT(ic);
8479   int ret = 0;
8480   int big,small;
8481   int offset;
8482
8483   iCode *nextic;
8484   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8485
8486   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8487
8488   nextic = ic->next;
8489   if(!nextic)
8490     return 0;
8491
8492   nextright = IC_RIGHT(nextic);
8493   nextleft  = IC_LEFT(nextic);
8494   nextresult = IC_RESULT(nextic);
8495
8496   aopOp(right,ic,FALSE);
8497   aopOp(result,ic,FALSE);
8498   aopOp(nextright,  nextic, FALSE);
8499   aopOp(nextleft,   nextic, FALSE);
8500   aopOp(nextresult, nextic, FALSE);
8501
8502   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8503
8504     operand *t = right;
8505     right = nextright;
8506     nextright = t; 
8507
8508     emitcode(";remove right +","");
8509
8510   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8511 /*
8512     operand *t = right;
8513     right = nextleft;
8514     nextleft = t; 
8515 */
8516     emitcode(";remove left +","");
8517   } else
8518     return 0;
8519
8520   big = AOP_SIZE(nextleft);
8521   small = AOP_SIZE(nextright);
8522
8523   switch(nextic->op) {
8524
8525   case '+':
8526     emitcode(";optimize a +","");
8527     /* if unsigned or not an integral type */
8528     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8529       emitcode(";add a bit to something","");
8530     } else {
8531
8532       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8533
8534       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8535         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8536         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8537       } else
8538         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8539
8540       offset = 0;
8541       while(--big) {
8542
8543         offset++;
8544
8545         if(--small) {
8546           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8547             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8548             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8549           }
8550
8551           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8552           emitSKPNC;
8553           emitcode("btfsc","(%s >> 3), (%s & 7)",
8554                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8555                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8556           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8557           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8558
8559         } else {
8560           emitcode("rlf","known_zero,w");
8561
8562           /*
8563             if right is signed
8564               btfsc  right,7
8565                addlw ff
8566           */
8567           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8568             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8569             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8570           } else {
8571             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8572           }
8573         }
8574       }
8575       ret = 1;
8576     }
8577   }
8578   ret = 1;
8579
8580 release:
8581   freeAsmop(right,NULL,ic,TRUE);
8582   freeAsmop(result,NULL,ic,TRUE);
8583   freeAsmop(nextright,NULL,ic,TRUE);
8584   freeAsmop(nextleft,NULL,ic,TRUE);
8585   if(ret)
8586     nextic->generated = 1;
8587
8588   return ret;
8589 #else
8590   return 0;
8591 #endif
8592 }
8593 /*-----------------------------------------------------------------*/
8594 /* genCast - gen code for casting                                  */
8595 /*-----------------------------------------------------------------*/
8596 static void genCast (iCode *ic)
8597 {
8598     operand *result = IC_RESULT(ic);
8599     sym_link *ctype = operandType(IC_LEFT(ic));
8600     operand *right = IC_RIGHT(ic);
8601     int size, offset ;
8602
8603     DEBUGemitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8604     /* if they are equivalent then do nothing */
8605     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8606         return ;
8607
8608     aopOp(right,ic,FALSE) ;
8609     aopOp(result,ic,FALSE);
8610
8611     /* if the result is a bit */
8612     if (AOP_TYPE(result) == AOP_CRY) {
8613         /* if the right size is a literal then
8614         we know what the value is */
8615         if (AOP_TYPE(right) == AOP_LIT) {
8616
8617           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8618                       popGet(AOP(result),0,FALSE,FALSE));
8619
8620             if (((int) operandLitValue(right))) 
8621               emitcode("bsf","(%s >> 3), (%s & 7)",
8622                        AOP(result)->aopu.aop_dir,
8623                        AOP(result)->aopu.aop_dir);
8624             else
8625               emitcode("bcf","(%s >> 3), (%s & 7)",
8626                        AOP(result)->aopu.aop_dir,
8627                        AOP(result)->aopu.aop_dir);
8628
8629             goto release;
8630         }
8631
8632         /* the right is also a bit variable */
8633         if (AOP_TYPE(right) == AOP_CRY) {
8634
8635           emitCLRC;
8636           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8637
8638           emitcode("clrc","");
8639           emitcode("btfsc","(%s >> 3), (%s & 7)",
8640                    AOP(right)->aopu.aop_dir,
8641                    AOP(right)->aopu.aop_dir);
8642             aopPut(AOP(result),"c",0);
8643             goto release ;
8644         }
8645
8646         /* we need to or */
8647         toBoolean(right);
8648         aopPut(AOP(result),"a",0);
8649         goto release ;
8650     }
8651
8652     /* if they are the same size : or less */
8653     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8654
8655         /* if they are in the same place */
8656         if (sameRegs(AOP(right),AOP(result)))
8657             goto release;
8658
8659         /* if they in different places then copy */
8660         size = AOP_SIZE(result);
8661         offset = 0 ;
8662         while (size--) {
8663             aopPut(AOP(result),
8664                    aopGet(AOP(right),offset,FALSE,FALSE),
8665                    offset);
8666             offset++;
8667         }
8668         goto release;
8669     }
8670
8671
8672     /* if the result is of type pointer */
8673     if (IS_PTR(ctype)) {
8674
8675         int p_type;
8676         sym_link *type = operandType(right);
8677         sym_link *etype = getSpec(type);
8678
8679         /* pointer to generic pointer */
8680         if (IS_GENPTR(ctype)) {
8681             char *l = zero;
8682             
8683             if (IS_PTR(type)) 
8684                 p_type = DCL_TYPE(type);
8685             else {
8686                 /* we have to go by the storage class */
8687                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8688
8689 /*              if (SPEC_OCLS(etype)->codesp )  */
8690 /*                  p_type = CPOINTER ;  */
8691 /*              else */
8692 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8693 /*                      p_type = FPOINTER ; */
8694 /*                  else */
8695 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8696 /*                          p_type = PPOINTER; */
8697 /*                      else */
8698 /*                          if (SPEC_OCLS(etype) == idata ) */
8699 /*                              p_type = IPOINTER ; */
8700 /*                          else */
8701 /*                              p_type = POINTER ; */
8702             }
8703                 
8704             /* the first two bytes are known */
8705             size = GPTRSIZE - 1; 
8706             offset = 0 ;
8707             while (size--) {
8708                 aopPut(AOP(result),
8709                        aopGet(AOP(right),offset,FALSE,FALSE),
8710                        offset);
8711                 offset++;
8712             }
8713             /* the last byte depending on type */
8714             switch (p_type) {
8715             case IPOINTER:
8716             case POINTER:
8717                 l = zero;
8718                 break;
8719             case FPOINTER:
8720                 l = one;
8721                 break;
8722             case CPOINTER:
8723                 l = "#0x02";
8724                 break;                          
8725             case PPOINTER:
8726                 l = "#0x03";
8727                 break;
8728                 
8729             default:
8730                 /* this should never happen */
8731                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8732                        "got unknown pointer type");
8733                 exit(1);
8734             }
8735             aopPut(AOP(result),l, GPTRSIZE - 1);            
8736             goto release ;
8737         }
8738         
8739         /* just copy the pointers */
8740         size = AOP_SIZE(result);
8741         offset = 0 ;
8742         while (size--) {
8743             aopPut(AOP(result),
8744                    aopGet(AOP(right),offset,FALSE,FALSE),
8745                    offset);
8746             offset++;
8747         }
8748         goto release ;
8749     }
8750     
8751
8752     if (AOP_TYPE(right) == AOP_CRY) {
8753       int offset = 1;
8754       size = AOP_SIZE(right);
8755
8756       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8757       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8758       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8759
8760       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8761       emitcode("btfsc","(%s >> 3), (%s & 7)",
8762                AOP(right)->aopu.aop_dir,
8763                AOP(right)->aopu.aop_dir);
8764       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8765       while (size--) {
8766         emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8767         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8768       }
8769       goto release;
8770     }
8771
8772     /* so we now know that the size of destination is greater
8773     than the size of the source.
8774     Now, if the next iCode is an operator then we might be
8775     able to optimize the operation without performing a cast.
8776     */
8777     if(genMixedOperation(ic))
8778       goto release;
8779
8780     
8781     /* we move to result for the size of source */
8782     size = AOP_SIZE(right);
8783     offset = 0 ;
8784     while (size--) {
8785       emitcode(";","%d",__LINE__);
8786         aopPut(AOP(result),
8787                aopGet(AOP(right),offset,FALSE,FALSE),
8788                offset);
8789         offset++;
8790     }
8791
8792     /* now depending on the sign of the destination */
8793     size = AOP_SIZE(result) - AOP_SIZE(right);
8794     /* if unsigned or not an integral type */
8795     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8796       while (size--) {
8797           emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8798           emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8799       }
8800     } else {
8801       /* we need to extend the sign :{ */
8802       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8803       //MOVA(l);
8804
8805       emitpcode(POC_CLRW,    NULL);
8806       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8807       emitpcode(POC_MOVLW,   popGetLit(0xff));
8808
8809         emitcode("clrw","");
8810         emitcode("btfsc","(%s >> 3), (%s & 7)",
8811                  AOP(right)->aopu.aop_dir,
8812                  AOP(right)->aopu.aop_dir);
8813         emitcode("movlw","0xff");
8814         while (size--) {
8815           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++,FALSE,FALSE));
8816           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8817           // aopPut(AOP(result),"a",offset++);
8818         }
8819
8820     }
8821
8822     /* we are done hurray !!!! */
8823
8824 release:
8825     freeAsmop(right,NULL,ic,TRUE);
8826     freeAsmop(result,NULL,ic,TRUE);
8827
8828 }
8829
8830 /*-----------------------------------------------------------------*/
8831 /* genDjnz - generate decrement & jump if not zero instrucion      */
8832 /*-----------------------------------------------------------------*/
8833 static int genDjnz (iCode *ic, iCode *ifx)
8834 {
8835     symbol *lbl, *lbl1;
8836     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8837
8838     if (!ifx)
8839         return 0;
8840     
8841     /* if the if condition has a false label
8842        then we cannot save */
8843     if (IC_FALSE(ifx))
8844         return 0;
8845
8846     /* if the minus is not of the form 
8847        a = a - 1 */
8848     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8849         !IS_OP_LITERAL(IC_RIGHT(ic)))
8850         return 0;
8851
8852     if (operandLitValue(IC_RIGHT(ic)) != 1)
8853         return 0;
8854
8855     /* if the size of this greater than one then no
8856        saving */
8857     if (getSize(operandType(IC_RESULT(ic))) > 1)
8858         return 0;
8859
8860     /* otherwise we can save BIG */
8861     lbl = newiTempLabel(NULL);
8862     lbl1= newiTempLabel(NULL);
8863
8864     aopOp(IC_RESULT(ic),ic,FALSE);
8865     
8866     if (IS_AOP_PREG(IC_RESULT(ic))) {
8867         emitcode("dec","%s",
8868                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8869         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8870         emitcode("jnz","%05d_DS_",lbl->key+100);
8871     } else {    
8872
8873
8874       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8875       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8876
8877       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8878       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8879
8880     }
8881 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8882 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
8883 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8884 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
8885
8886     
8887     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8888     ifx->generated = 1;
8889     return 1;
8890 }
8891
8892 /*-----------------------------------------------------------------*/
8893 /* genReceive - generate code for a receive iCode                  */
8894 /*-----------------------------------------------------------------*/
8895 static void genReceive (iCode *ic)
8896 {    
8897     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8898
8899     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8900         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8901           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8902
8903         int size = getSize(operandType(IC_RESULT(ic)));
8904         int offset =  fReturnSize - size;
8905         while (size--) {
8906             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8907                                     fReturn[fReturnSize - offset - 1] : "acc"));
8908             offset++;
8909         }
8910         aopOp(IC_RESULT(ic),ic,FALSE);  
8911         size = AOP_SIZE(IC_RESULT(ic));
8912         offset = 0;
8913         while (size--) {
8914             emitcode ("pop","acc");
8915             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8916         }
8917         
8918     } else {
8919         _G.accInUse++;
8920         aopOp(IC_RESULT(ic),ic,FALSE);  
8921         _G.accInUse--;
8922         assignResultValue(IC_RESULT(ic));       
8923     }
8924
8925     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8926 }
8927
8928 /*-----------------------------------------------------------------*/
8929 /* genpic14Code - generate code for pic14 based controllers        */
8930 /*-----------------------------------------------------------------*/
8931 /*
8932  * At this point, ralloc.c has gone through the iCode and attempted
8933  * to optimize in a way suitable for a PIC. Now we've got to generate
8934  * PIC instructions that correspond to the iCode.
8935  *
8936  * Once the instructions are generated, we'll pass through both the
8937  * peep hole optimizer and the pCode optimizer.
8938  *-----------------------------------------------------------------*/
8939
8940 void genpic14Code (iCode *lic)
8941 {
8942     iCode *ic;
8943     int cln = 0;
8944
8945     lineHead = lineCurr = NULL;
8946
8947     pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8948     addpBlock(pb);
8949
8950     /* if debug information required */
8951 /*     if (options.debug && currFunc) { */
8952     if (currFunc) {
8953         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8954         _G.debugLine = 1;
8955         if (IS_STATIC(currFunc->etype)) {
8956             emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8957             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8958         } else {
8959             emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8960             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8961         }
8962         _G.debugLine = 0;
8963     }
8964
8965
8966     for (ic = lic ; ic ; ic = ic->next ) {
8967
8968       DEBUGemitcode(";ic","");
8969         if ( cln != ic->lineno ) {
8970             if ( options.debug ) {
8971                 _G.debugLine = 1;
8972                 emitcode("",";C$%s$%d$%d$%d ==.",
8973                          ic->filename,ic->lineno,
8974                          ic->level,ic->block);
8975                 _G.debugLine = 0;
8976             }
8977             emitcode(";","%s %d",ic->filename,ic->lineno);
8978             cln = ic->lineno ;
8979         }
8980         /* if the result is marked as
8981            spilt and rematerializable or code for
8982            this has already been generated then
8983            do nothing */
8984         if (resultRemat(ic) || ic->generated ) 
8985             continue ;
8986         
8987         /* depending on the operation */
8988         switch (ic->op) {
8989         case '!' :
8990             genNot(ic);
8991             break;
8992             
8993         case '~' :
8994             genCpl(ic);
8995             break;
8996             
8997         case UNARYMINUS:
8998             genUminus (ic);
8999             break;
9000             
9001         case IPUSH:
9002             genIpush (ic);
9003             break;
9004             
9005         case IPOP:
9006             /* IPOP happens only when trying to restore a 
9007                spilt live range, if there is an ifx statement
9008                following this pop then the if statement might
9009                be using some of the registers being popped which
9010                would destory the contents of the register so
9011                we need to check for this condition and handle it */
9012             if (ic->next            && 
9013                 ic->next->op == IFX &&
9014                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9015                 genIfx (ic->next,ic);
9016             else
9017                 genIpop (ic);
9018             break; 
9019             
9020         case CALL:
9021             genCall (ic);
9022             break;
9023             
9024         case PCALL:
9025             genPcall (ic);
9026             break;
9027             
9028         case FUNCTION:
9029             genFunction (ic);
9030             break;
9031             
9032         case ENDFUNCTION:
9033             genEndFunction (ic);
9034             break;
9035             
9036         case RETURN:
9037             genRet (ic);
9038             break;
9039             
9040         case LABEL:
9041             genLabel (ic);
9042             break;
9043             
9044         case GOTO:
9045             genGoto (ic);
9046             break;
9047             
9048         case '+' :
9049             genPlus (ic) ;
9050             break;
9051             
9052         case '-' :
9053             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9054                 genMinus (ic);
9055             break;
9056             
9057         case '*' :
9058             genMult (ic);
9059             break;
9060             
9061         case '/' :
9062             genDiv (ic) ;
9063             break;
9064             
9065         case '%' :
9066             genMod (ic);
9067             break;
9068             
9069         case '>' :
9070             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9071             break;
9072             
9073         case '<' :
9074             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9075             break;
9076             
9077         case LE_OP:
9078         case GE_OP:
9079         case NE_OP:
9080             
9081             /* note these two are xlated by algebraic equivalence
9082                during parsing SDCC.y */
9083             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9084                    "got '>=' or '<=' shouldn't have come here");
9085             break;      
9086             
9087         case EQ_OP:
9088             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9089             break;          
9090             
9091         case AND_OP:
9092             genAndOp (ic);
9093             break;
9094             
9095         case OR_OP:
9096             genOrOp (ic);
9097             break;
9098             
9099         case '^' :
9100             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9101             break;
9102             
9103         case '|' :
9104                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9105             break;
9106             
9107         case BITWISEAND:
9108             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9109             break;
9110             
9111         case INLINEASM:
9112             genInline (ic);
9113             break;
9114             
9115         case RRC:
9116             genRRC (ic);
9117             break;
9118             
9119         case RLC:
9120             genRLC (ic);
9121             break;
9122             
9123         case GETHBIT:
9124             genGetHbit (ic);
9125             break;
9126             
9127         case LEFT_OP:
9128             genLeftShift (ic);
9129             break;
9130             
9131         case RIGHT_OP:
9132             genRightShift (ic);
9133             break;
9134             
9135         case GET_VALUE_AT_ADDRESS:
9136             genPointerGet(ic);
9137             break;
9138             
9139         case '=' :
9140             if (POINTER_SET(ic))
9141                 genPointerSet(ic);
9142             else
9143                 genAssign(ic);
9144             break;
9145             
9146         case IFX:
9147             genIfx (ic,NULL);
9148             break;
9149             
9150         case ADDRESS_OF:
9151             genAddrOf (ic);
9152             break;
9153             
9154         case JUMPTABLE:
9155             genJumpTab (ic);
9156             break;
9157             
9158         case CAST:
9159             genCast (ic);
9160             break;
9161             
9162         case RECEIVE:
9163             genReceive(ic);
9164             break;
9165             
9166         case SEND:
9167             addSet(&_G.sendSet,ic);
9168             break;
9169
9170         default :
9171             ic = ic;
9172             /*      piCode(ic,stdout); */
9173             
9174         }
9175     }
9176     
9177
9178     /* now we are ready to call the 
9179        peep hole optimizer */
9180     if (!options.nopeep) {
9181       printf("peep hole optimizing\n");
9182         peepHole (&lineHead);
9183     }
9184     /* now do the actual printing */
9185     printLine (lineHead,codeOutFile);
9186
9187     printf("printing pBlock\n\n");
9188     printpBlock(stdout,pb);
9189
9190     return;
9191 }