9bd8650d5eed415e32521c0de7317e4fd28726da
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #if defined(_MSC_VER)
40 #define __FUNCTION__            __FILE__
41 #endif
42
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
45 #else
46 #ifdef HAVE_ENDIAN_H
47 #include <endian.h>
48 #else
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62 //char *aopLiteral (value *val, int offset);
63 unsigned int pic14aopLiteral (value *val, int offset);
64
65 /* this is the down and dirty file with all kinds of 
66    kludgy & hacky stuff. This is what it is all about
67    CODE GENERATION for a specific MCU . some of the
68    routines may be reusable, will have to see */
69
70 static char *zero = "#0x00";
71 static char *one  = "#0x01";
72 static char *spname = "sp";
73
74 char *fReturnpic14[] = {"fsr","dph","b","a" };
75 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
76 static unsigned fReturnSize = 4; /* shared with ralloc.c */
77 static char **fReturn = fReturnpic14;
78
79 static char *accUse[] = {"a","b"};
80
81 //static short rbank = -1;
82
83 static struct {
84     short r0Pushed;
85     short r1Pushed;
86     short accInUse;
87     short inLine;
88     short debugLine;
89     short nRegsSaved;
90     set *sendSet;
91 } _G;
92
93 extern int pic14_ptrRegReq ;
94 extern int pic14_nRegs;
95 extern FILE *codeOutFile;
96 static void saverbank (int, iCode *,bool);
97 #define RESULTONSTACK(x) \
98                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
99                          IC_RESULT(x)->aop->type == AOP_STK )
100
101 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
102 #define CLRC    emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
103
104 #define BIT_NUMBER(x) (x & 7)
105 #define BIT_REGISTER(x) (x>>3)
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
111 0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119
120
121 #define FUNCTION_LABEL_INC  20
122 static int labelOffset=0;
123 static int debug_verbose=1;
124
125 static  pBlock *pb;
126
127 /*-----------------------------------------------------------------*/
128 /* Macros for emitting instructions                                */
129 /*-----------------------------------------------------------------*/
130
131 #define emitSKPC    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPNC   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
133 #define emitSKPZ    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitSKPNZ   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRZ    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
136 #define emitCLRC    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
137 #define emitSETZ    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
138 #define emitSETC    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
139
140 //#define emitSKPC    emitcode("btfss","status,c")
141 //#define emitSKPNC   emitcode("btfsc","status,c")
142 //#define emitSKPZ    emitcode("btfss","status,z")
143 //#define emitSKPNZ   emitcode("btfsc","status,z")
144
145 /*-----------------------------------------------------------------*/
146 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
147 /*                 exponent of 2 is returned, otherwise -1 is      */
148 /*                 returned.                                       */
149 /* note that this is similar to the function `powof2' in SDCCsymt  */
150 /* if(n == 2^y)                                                    */
151 /*   return y;                                                     */
152 /* return -1;                                                      */
153 /*-----------------------------------------------------------------*/
154 static int my_powof2 (unsigned long num)
155 {
156   if(num) {
157     if( (num & (num-1)) == 0) {
158       int nshifts = -1;
159       while(num) {
160         num>>=1;
161         nshifts++;
162       }
163       return nshifts;
164     }
165   }
166
167   return -1;
168 }
169
170 static void emitpLabel(int key)
171 {
172   addpCode2pBlock(pb,newpCodeLabel(key));
173 }
174
175 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
176 {
177
178   addpCode2pBlock(pb,newpCode(poc,pcop));
179
180 }
181 /*-----------------------------------------------------------------*/
182 /* emitcode - writes the code into a file : for now it is simple    */
183 /*-----------------------------------------------------------------*/
184 static void emitcode (char *inst,char *fmt, ...)
185 {
186     va_list ap;
187     char lb[MAX_INLINEASM];  
188     char *lbp = lb;
189
190     va_start(ap,fmt);   
191
192     if (inst && *inst) {
193         if (fmt && *fmt)
194             sprintf(lb,"%s\t",inst);
195         else
196             sprintf(lb,"%s",inst);
197         vsprintf(lb+(strlen(lb)),fmt,ap);
198     }  else
199         vsprintf(lb,fmt,ap);
200
201     while (isspace(*lbp)) lbp++;
202
203     if (lbp && *lbp) 
204         lineCurr = (lineCurr ?
205                     connectLine(lineCurr,newLineNode(lb)) :
206                     (lineHead = newLineNode(lb)));
207     lineCurr->isInline = _G.inLine;
208     lineCurr->isDebug  = _G.debugLine;
209
210     addpCode2pBlock(pb,newpCodeCharP(lb));
211
212     va_end(ap);
213 }
214
215 static void DEBUGemitcode (char *inst,char *fmt, ...)
216 {
217     va_list ap;
218     char lb[MAX_INLINEASM];  
219     char *lbp = lb;
220
221     if(!debug_verbose)
222       return;
223
224     va_start(ap,fmt);   
225
226     if (inst && *inst) {
227         if (fmt && *fmt)
228             sprintf(lb,"%s\t",inst);
229         else
230             sprintf(lb,"%s",inst);
231         vsprintf(lb+(strlen(lb)),fmt,ap);
232     }  else
233         vsprintf(lb,fmt,ap);
234
235     while (isspace(*lbp)) lbp++;
236
237     if (lbp && *lbp) 
238         lineCurr = (lineCurr ?
239                     connectLine(lineCurr,newLineNode(lb)) :
240                     (lineHead = newLineNode(lb)));
241     lineCurr->isInline = _G.inLine;
242     lineCurr->isDebug  = _G.debugLine;
243
244     addpCode2pBlock(pb,newpCodeCharP(lb));
245
246     va_end(ap);
247 }
248
249
250 /*-----------------------------------------------------------------*/
251 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
252 /*-----------------------------------------------------------------*/
253 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
254 {
255     bool r0iu = FALSE , r1iu = FALSE;
256     bool r0ou = FALSE , r1ou = FALSE;
257
258     /* the logic: if r0 & r1 used in the instruction
259     then we are in trouble otherwise */
260
261     /* first check if r0 & r1 are used by this
262     instruction, in which case we are in trouble */
263     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
264         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
265     {
266         goto endOfWorld;      
267     }
268
269     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
270     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
271
272     /* if no usage of r0 then return it */
273     if (!r0iu && !r0ou) {
274         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
275         (*aopp)->type = AOP_R0;
276         
277         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
278     }
279
280     /* if no usage of r1 then return it */
281     if (!r1iu && !r1ou) {
282         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
283         (*aopp)->type = AOP_R1;
284
285         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
286     }    
287
288     /* now we know they both have usage */
289     /* if r0 not used in this instruction */
290     if (!r0iu) {
291         /* push it if not already pushed */
292         if (!_G.r0Pushed) {
293             emitcode ("push","%s",
294                       pic14_regWithIdx(R0_IDX)->dname);
295             _G.r0Pushed++ ;
296         }
297         
298         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
299         (*aopp)->type = AOP_R0;
300
301         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
302     }
303
304     /* if r1 not used then */
305
306     if (!r1iu) {
307         /* push it if not already pushed */
308         if (!_G.r1Pushed) {
309             emitcode ("push","%s",
310                       pic14_regWithIdx(R1_IDX)->dname);
311             _G.r1Pushed++ ;
312         }
313         
314         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
315         (*aopp)->type = AOP_R1;
316         return pic14_regWithIdx(R1_IDX);
317     }
318
319 endOfWorld :
320     /* I said end of world but not quite end of world yet */
321     /* if this is a result then we can push it on the stack*/
322     if (result) {
323         (*aopp)->type = AOP_STK;    
324         return NULL;
325     }
326
327     piCode(ic,stdout);
328     /* other wise this is true end of the world */
329     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
330            "getFreePtr should never reach here");
331     exit(0);
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* newAsmop - creates a new asmOp                                  */
336 /*-----------------------------------------------------------------*/
337 static asmop *newAsmop (short type)
338 {
339     asmop *aop;
340
341     aop = Safe_calloc(1,sizeof(asmop));
342     aop->type = type;
343     return aop;
344 }
345
346 static void genSetDPTR(int n)
347 {
348     if (!n)
349     {
350         emitcode(";", "Select standard DPTR");
351         emitcode("mov", "dps, #0x00");
352     }
353     else
354     {
355         emitcode(";", "Select alternate DPTR");
356         emitcode("mov", "dps, #0x01");
357     }
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* pointerCode - returns the code for a pointer type               */
362 /*-----------------------------------------------------------------*/
363 static int pointerCode (sym_link *etype)
364 {
365
366     return PTR_TYPE(SPEC_OCLS(etype));
367
368 }
369
370 /*-----------------------------------------------------------------*/
371 /* aopForSym - for a true symbol                                   */
372 /*-----------------------------------------------------------------*/
373 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
374 {
375     asmop *aop;
376     memmap *space= SPEC_OCLS(sym->etype);
377
378     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
379     /* if already has one */
380     if (sym->aop)
381         return sym->aop;
382
383     /* assign depending on the storage class */
384     /* if it is on the stack or indirectly addressable */
385     /* space we need to assign either r0 or r1 to it   */    
386     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
387         sym->aop = aop = newAsmop(0);
388         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
389         aop->size = getSize(sym->type);
390
391         /* now assign the address of the variable to 
392         the pointer register */
393         if (aop->type != AOP_STK) {
394
395             if (sym->onStack) {
396                     if ( _G.accInUse )
397                         emitcode("push","acc");
398
399                     emitcode("mov","a,_bp");
400                     emitcode("add","a,#0x%02x",
401                              ((sym->stack < 0) ?
402                               ((char)(sym->stack - _G.nRegsSaved )) :
403                               ((char)sym->stack)) & 0xff);
404                     emitcode("mov","%s,a",
405                              aop->aopu.aop_ptr->name);
406
407                     if ( _G.accInUse )
408                         emitcode("pop","acc");
409             } else
410                 emitcode("mov","%s,#%s",
411                          aop->aopu.aop_ptr->name,
412                          sym->rname);
413             aop->paged = space->paged;
414         } else
415             aop->aopu.aop_stk = sym->stack;
416         return aop;
417     }
418     
419     if (sym->onStack && options.stack10bit)
420     {
421         /* It's on the 10 bit stack, which is located in
422          * far data space.
423          */
424          
425       //DEBUGemitcode(";","%d",__LINE__);
426
427         if ( _G.accInUse )
428                 emitcode("push","acc");
429
430         emitcode("mov","a,_bp");
431         emitcode("add","a,#0x%02x",
432                  ((sym->stack < 0) ?
433                    ((char)(sym->stack - _G.nRegsSaved )) :
434                    ((char)sym->stack)) & 0xff);
435         
436         genSetDPTR(1);
437         emitcode ("mov","dpx1,#0x40");
438         emitcode ("mov","dph1,#0x00");
439         emitcode ("mov","dpl1, a");
440         genSetDPTR(0);
441         
442         if ( _G.accInUse )
443             emitcode("pop","acc");
444             
445         sym->aop = aop = newAsmop(AOP_DPTR2);
446         aop->size = getSize(sym->type); 
447         return aop;
448     }
449
450     //DEBUGemitcode(";","%d",__LINE__);
451     /* if in bit space */
452     if (IN_BITSPACE(space)) {
453         sym->aop = aop = newAsmop (AOP_CRY);
454         aop->aopu.aop_dir = sym->rname ;
455         aop->size = getSize(sym->type);
456         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
457         return aop;
458     }
459     /* if it is in direct space */
460     if (IN_DIRSPACE(space)) {
461         sym->aop = aop = newAsmop (AOP_DIR);
462         aop->aopu.aop_dir = sym->rname ;
463         aop->size = getSize(sym->type);
464         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
465         return aop;
466     }
467
468     /* special case for a function */
469     if (IS_FUNC(sym->type)) {   
470         sym->aop = aop = newAsmop(AOP_IMMD);    
471         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
472         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
473         strcpy(aop->aopu.aop_immd,sym->rname);
474         aop->size = FPTRSIZE; 
475         return aop;
476     }
477
478
479     /* only remaining is far space */
480     /* in which case DPTR gets the address */
481     sym->aop = aop = newAsmop(AOP_DPTR);
482     emitcode ("mov","dptr,#%s", sym->rname);
483     aop->size = getSize(sym->type);
484
485     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
486     /* if it is in code space */
487     if (IN_CODESPACE(space))
488         aop->code = 1;
489
490     return aop;     
491 }
492
493 /*-----------------------------------------------------------------*/
494 /* aopForRemat - rematerialzes an object                           */
495 /*-----------------------------------------------------------------*/
496 static asmop *aopForRemat (symbol *sym)
497 {
498     iCode *ic = sym->rematiCode;
499     asmop *aop = newAsmop(AOP_IMMD);
500     int val = 0;
501     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
502     for (;;) {
503         if (ic->op == '+')
504             val += operandLitValue(IC_RIGHT(ic));
505         else if (ic->op == '-')
506             val -= operandLitValue(IC_RIGHT(ic));
507         else
508             break;
509         
510         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
511     }
512
513     if (val)
514         sprintf(buffer,"(%s %c 0x%04x)",
515                 OP_SYMBOL(IC_LEFT(ic))->rname, 
516                 val >= 0 ? '+' : '-',
517                 abs(val) & 0xffff);
518     else
519         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
520
521     //DEBUGemitcode(";","%s",buffer);
522     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
523     strcpy(aop->aopu.aop_immd,buffer);    
524     return aop;        
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* regsInCommon - two operands have some registers in common       */
529 /*-----------------------------------------------------------------*/
530 static bool regsInCommon (operand *op1, operand *op2)
531 {
532     symbol *sym1, *sym2;
533     int i;
534
535     /* if they have registers in common */
536     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
537         return FALSE ;
538
539     sym1 = OP_SYMBOL(op1);
540     sym2 = OP_SYMBOL(op2);
541
542     if (sym1->nRegs == 0 || sym2->nRegs == 0)
543         return FALSE ;
544
545     for (i = 0 ; i < sym1->nRegs ; i++) {
546         int j;
547         if (!sym1->regs[i])
548             continue ;
549
550         for (j = 0 ; j < sym2->nRegs ;j++ ) {
551             if (!sym2->regs[j])
552                 continue ;
553
554             if (sym2->regs[j] == sym1->regs[i])
555                 return TRUE ;
556         }
557     }
558
559     return FALSE ;
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* operandsEqu - equivalent                                        */
564 /*-----------------------------------------------------------------*/
565 static bool operandsEqu ( operand *op1, operand *op2)
566 {
567     symbol *sym1, *sym2;
568
569     /* if they not symbols */
570     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
571         return FALSE;
572
573     sym1 = OP_SYMBOL(op1);
574     sym2 = OP_SYMBOL(op2);
575
576     /* if both are itemps & one is spilt
577        and the other is not then false */
578     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
579         sym1->isspilt != sym2->isspilt )
580         return FALSE ;
581
582     /* if they are the same */
583     if (sym1 == sym2)
584         return TRUE ;
585
586     if (strcmp(sym1->rname,sym2->rname) == 0)
587         return TRUE;
588
589
590     /* if left is a tmp & right is not */
591     if (IS_ITEMP(op1)  && 
592         !IS_ITEMP(op2) &&
593         sym1->isspilt  &&
594         (sym1->usl.spillLoc == sym2))
595         return TRUE;
596
597     if (IS_ITEMP(op2)  && 
598         !IS_ITEMP(op1) &&
599         sym2->isspilt  &&
600         sym1->level > 0 &&
601         (sym2->usl.spillLoc == sym1))
602         return TRUE ;
603
604     return FALSE ;
605 }
606
607 /*-----------------------------------------------------------------*/
608 /* sameRegs - two asmops have the same registers                   */
609 /*-----------------------------------------------------------------*/
610 static bool sameRegs (asmop *aop1, asmop *aop2 )
611 {
612     int i;
613
614     if (aop1 == aop2)
615         return TRUE ;
616
617     if (aop1->type != AOP_REG ||
618         aop2->type != AOP_REG )
619         return FALSE ;
620
621     if (aop1->size != aop2->size )
622         return FALSE ;
623
624     for (i = 0 ; i < aop1->size ; i++ )
625         if (aop1->aopu.aop_reg[i] !=
626             aop2->aopu.aop_reg[i] )
627             return FALSE ;
628
629     return TRUE ;
630 }
631
632 /*-----------------------------------------------------------------*/
633 /* aopOp - allocates an asmop for an operand  :                    */
634 /*-----------------------------------------------------------------*/
635 static void aopOp (operand *op, iCode *ic, bool result)
636 {
637     asmop *aop;
638     symbol *sym;
639     int i;
640
641     if (!op)
642         return ;
643
644     DEBUGemitcode(";","%d",__LINE__);
645     /* if this a literal */
646     if (IS_OP_LITERAL(op)) {
647       DEBUGemitcode(";","%d",__LINE__);
648         op->aop = aop = newAsmop(AOP_LIT);
649         aop->aopu.aop_lit = op->operand.valOperand;
650         aop->size = getSize(operandType(op));
651         return;
652     }
653
654     /* if already has a asmop then continue */
655     if (op->aop)
656         return ;
657
658     /* if the underlying symbol has a aop */
659     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
660       DEBUGemitcode(";","%d",__LINE__);
661         op->aop = OP_SYMBOL(op)->aop;
662         return;
663     }
664
665     /* if this is a true symbol */
666     if (IS_TRUE_SYMOP(op)) {    
667       DEBUGemitcode(";","%d",__LINE__);
668         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
669         return ;
670     }
671
672     /* this is a temporary : this has
673     only four choices :
674     a) register
675     b) spillocation
676     c) rematerialize 
677     d) conditional   
678     e) can be a return use only */
679
680     sym = OP_SYMBOL(op);
681
682
683     /* if the type is a conditional */
684     if (sym->regType == REG_CND) {
685       DEBUGemitcode(";","%d",__LINE__);
686         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
687         aop->size = 0;
688         return;
689     }
690
691     /* if it is spilt then two situations
692     a) is rematerialize 
693     b) has a spill location */
694     if (sym->isspilt || sym->nRegs == 0) {
695
696       DEBUGemitcode(";","%d",__LINE__);
697         /* rematerialize it NOW */
698         if (sym->remat) {
699             sym->aop = op->aop = aop =
700                                       aopForRemat (sym);
701             aop->size = getSize(sym->type);
702             DEBUGemitcode(";","%d",__LINE__);
703             return;
704         }
705
706         if (sym->accuse) {
707             int i;
708             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
709             aop->size = getSize(sym->type);
710             for ( i = 0 ; i < 2 ; i++ )
711                 aop->aopu.aop_str[i] = accUse[i];
712             DEBUGemitcode(";","%d",__LINE__);
713             return;  
714         }
715
716         if (sym->ruonly ) {
717             int i;
718             aop = op->aop = sym->aop = newAsmop(AOP_STR);
719             aop->size = getSize(sym->type);
720             for ( i = 0 ; i < fReturnSize ; i++ )
721               aop->aopu.aop_str[i] = fReturn[i];
722             DEBUGemitcode(";","%d",__LINE__);
723             return;
724         }
725
726         /* else spill location  */
727         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
728         sym->aop = op->aop = aop = 
729                                   aopForSym(ic,sym->usl.spillLoc,result);
730         aop->size = getSize(sym->type);
731         return;
732     }
733
734     /* must be in a register */
735     sym->aop = op->aop = aop = newAsmop(AOP_REG);
736     aop->size = sym->nRegs;
737     for ( i = 0 ; i < sym->nRegs ;i++)
738         aop->aopu.aop_reg[i] = sym->regs[i];
739 }
740
741 /*-----------------------------------------------------------------*/
742 /* freeAsmop - free up the asmop given to an operand               */
743 /*----------------------------------------------------------------*/
744 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
745 {   
746     asmop *aop ;
747
748     if (!op)
749         aop = aaop;
750     else 
751         aop = op->aop;
752
753     if (!aop)
754         return ;
755
756     if (aop->freed)
757         goto dealloc; 
758
759     aop->freed = 1;
760
761     /* depending on the asmop type only three cases need work AOP_RO
762        , AOP_R1 && AOP_STK */
763     switch (aop->type) {
764         case AOP_R0 :
765             if (_G.r0Pushed ) {
766                 if (pop) {
767                     emitcode ("pop","ar0");     
768                     _G.r0Pushed--;
769                 }
770             }
771             bitVectUnSetBit(ic->rUsed,R0_IDX);
772             break;
773
774         case AOP_R1 :
775             if (_G.r1Pushed ) {
776                 if (pop) {
777                     emitcode ("pop","ar1");
778                     _G.r1Pushed--;
779                 }
780             }
781             bitVectUnSetBit(ic->rUsed,R1_IDX);          
782             break;
783
784         case AOP_STK :
785         {
786             int sz = aop->size;    
787             int stk = aop->aopu.aop_stk + aop->size;
788             bitVectUnSetBit(ic->rUsed,R0_IDX);
789             bitVectUnSetBit(ic->rUsed,R1_IDX);          
790
791             getFreePtr(ic,&aop,FALSE);
792             
793             if (options.stack10bit)
794             {
795                 /* I'm not sure what to do here yet... */
796                 /* #STUB */
797                 fprintf(stderr, 
798                         "*** Warning: probably generating bad code for "
799                         "10 bit stack mode.\n");
800             }
801             
802             if (stk) {
803                 emitcode ("mov","a,_bp");
804                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
805                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
806             } else {
807                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
808             }
809
810             while (sz--) {
811                 emitcode("pop","acc");
812                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
813                 if (!sz) break;
814                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
815             }
816             op->aop = aop;
817             freeAsmop(op,NULL,ic,TRUE);
818             if (_G.r0Pushed) {
819                 emitcode("pop","ar0");
820                 _G.r0Pushed--;
821             }
822
823             if (_G.r1Pushed) {
824                 emitcode("pop","ar1");
825                 _G.r1Pushed--;
826             }       
827         }
828     }
829
830 dealloc:
831     /* all other cases just dealloc */
832     if (op ) {
833         op->aop = NULL;
834         if (IS_SYMOP(op)) {
835             OP_SYMBOL(op)->aop = NULL;    
836             /* if the symbol has a spill */
837             if (SPIL_LOC(op))
838                 SPIL_LOC(op)->aop = NULL;
839         }
840     }
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* aopGet - for fetching value of the aop                          */
845 /*-----------------------------------------------------------------*/
846 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
847 {
848     char *s = buffer ;
849     char *rs;
850
851     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
852     /* offset is greater than
853     size then zero */
854     if (offset > (aop->size - 1) &&
855         aop->type != AOP_LIT)
856         return zero;
857
858     /* depending on type */
859     switch (aop->type) {
860         
861     case AOP_R0:
862     case AOP_R1:
863         DEBUGemitcode(";","%d",__LINE__);
864         /* if we need to increment it */       
865         while (offset > aop->coff) {        
866             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
867             aop->coff++;
868         }
869         
870         while (offset < aop->coff) {
871             emitcode("dec","%s",aop->aopu.aop_ptr->name);
872             aop->coff--;
873         }
874         
875         aop->coff = offset ;
876         if (aop->paged) {
877             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
878             return (dname ? "acc" : "a");
879         }       
880         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
881         rs = Safe_calloc(1,strlen(s)+1);
882         strcpy(rs,s);   
883         return rs;
884         
885     case AOP_DPTR:
886     case AOP_DPTR2:
887         DEBUGemitcode(";","%d",__LINE__);
888     if (aop->type == AOP_DPTR2)
889     {
890         genSetDPTR(1);
891     }
892     
893         while (offset > aop->coff) {
894             emitcode ("inc","dptr");
895             aop->coff++;
896         }
897         
898         while (offset < aop->coff) {        
899             emitcode("lcall","__decdptr");
900             aop->coff--;
901         }
902         
903         aop->coff = offset;
904         if (aop->code) {
905             emitcode("clr","a");
906             emitcode("movc","a,@a+dptr");
907         }
908     else {
909             emitcode("movx","a,@dptr");
910     }
911             
912     if (aop->type == AOP_DPTR2)
913     {
914         genSetDPTR(0);
915     }
916             
917     return (dname ? "acc" : "a");
918         
919         
920     case AOP_IMMD:
921       DEBUGemitcode(";","%d",__LINE__);
922         if (bit16) 
923             sprintf (s,"%s",aop->aopu.aop_immd);
924         else
925             if (offset) 
926                 sprintf(s,"(%s >> %d)",
927                         aop->aopu.aop_immd,
928                         offset*8);
929             else
930                 sprintf(s,"%s",
931                         aop->aopu.aop_immd);
932         rs = Safe_calloc(1,strlen(s)+1);
933         strcpy(rs,s);   
934         return rs;
935         
936     case AOP_DIR:
937         if (offset)
938             sprintf(s,"(%s + %d)",
939                     aop->aopu.aop_dir,
940                     offset);
941         else
942             sprintf(s,"%s",aop->aopu.aop_dir);
943         rs = Safe_calloc(1,strlen(s)+1);
944         strcpy(rs,s);   
945         return rs;
946         
947     case AOP_REG:
948       DEBUGemitcode(";","%d",__LINE__);
949         if (dname) 
950             return aop->aopu.aop_reg[offset]->dname;
951         else
952             return aop->aopu.aop_reg[offset]->name;
953         
954     case AOP_CRY:
955       emitcode(";","%d",__LINE__);
956       //emitcode("clr","a");
957       //emitcode("mov","c,%s",aop->aopu.aop_dir);
958       //emitcode("rlc","a") ;
959       //return (dname ? "acc" : "a");
960       return aop->aopu.aop_dir;
961         
962     case AOP_ACC:
963         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
964         //if (!offset && dname)
965         //    return "acc";
966         //return aop->aopu.aop_str[offset];
967         return "AOP_accumulator_bug";
968
969     case AOP_LIT:
970         DEBUGemitcode(";","%d",__LINE__);
971         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
972         rs = Safe_calloc(1,strlen(s)+1);
973         strcpy(rs,s);   
974         return rs;
975         
976     case AOP_STR:
977         DEBUGemitcode(";","%d",__LINE__);
978         aop->coff = offset ;
979         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
980             dname)
981             return "acc";
982         
983         return aop->aopu.aop_str[offset];
984         
985     }
986
987     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
988            "aopget got unsupported aop->type");
989     exit(0);
990 }
991
992 /*-----------------------------------------------------------------*/
993 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
994 /*-----------------------------------------------------------------*/
995 static pCodeOp *popGetLabel(unsigned int key)
996 {
997   return newpCodeOpLabel(key+100+labelOffset);
998 }
999
1000 /*-----------------------------------------------------------------*/
1001 /* popCopy - copy a pcode operator                                 */
1002 /*-----------------------------------------------------------------*/
1003 static pCodeOp *popCopy(pCodeOp *pc)
1004 {
1005   pCodeOp *pcop;
1006
1007   pcop = Safe_calloc(1,sizeof(pCodeOp) );
1008   pcop->type = pc->type;
1009   if(!(pcop->name = strdup(pc->name)))
1010     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1011
1012   return pcop;
1013 }
1014
1015 /*-----------------------------------------------------------------*/
1016 /* popCopy - copy a pcode operator                                 */
1017 /*-----------------------------------------------------------------*/
1018 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1019 {
1020   pCodeOp *pcop;
1021
1022   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1023   pcop->type = PO_BIT;
1024   if(!(pcop->name = strdup(pc->name)))
1025     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1026   ((pCodeOpBit *)pcop)->bit = bitval;
1027
1028   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1029
1030   return pcop;
1031 }
1032
1033 /*-----------------------------------------------------------------*/
1034 /* popGet - asm operator to pcode operator conversion              */
1035 /*-----------------------------------------------------------------*/
1036 static pCodeOp *popGetLit(unsigned int lit)
1037 {
1038
1039   return newpCodeOpLit(lit);
1040 }
1041
1042
1043 /*-----------------------------------------------------------------*/
1044 /* popGet - asm operator to pcode operator conversion              */
1045 /*-----------------------------------------------------------------*/
1046 static pCodeOp *popGetWithString(char *str)
1047 {
1048   pCodeOp *pcop;
1049
1050
1051   if(!str) {
1052     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1053     exit (1);
1054   }
1055
1056   pcop = newpCodeOp(str);
1057   pcop->type = PO_STR;
1058
1059 /*
1060   _ALLOC(pcop,sizeof(pCodeOp) );
1061     _ALLOC_ATOMIC(pcop->name,strlen(str)+1);
1062     strcpy(pcop->name,str);   
1063   } else {
1064   }
1065 */
1066   return pcop;
1067 }
1068 /*-----------------------------------------------------------------*/
1069 /* popGet - asm operator to pcode operator conversion              */
1070 /*-----------------------------------------------------------------*/
1071 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1072 {
1073     char *s = buffer ;
1074     char *rs;
1075
1076     pCodeOp *pcop;
1077
1078     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1079     /* offset is greater than
1080     size then zero */
1081
1082     if (offset > (aop->size - 1) &&
1083         aop->type != AOP_LIT)
1084       return NULL;  //zero;
1085
1086     /* depending on type */
1087     switch (aop->type) {
1088         
1089     case AOP_R0:
1090     case AOP_R1:
1091     case AOP_DPTR:
1092     case AOP_DPTR2:
1093     case AOP_ACC:
1094         DEBUGemitcode(";8051 legacy","%d",__LINE__);
1095         return NULL;
1096         
1097     case AOP_IMMD:
1098       DEBUGemitcode(";","%d",__LINE__);
1099         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1100         pcop->type = PO_IMMEDIATE;
1101         if (bit16) 
1102             sprintf (s,"%s",aop->aopu.aop_immd);
1103         else
1104             if (offset) 
1105                 sprintf(s,"(%s >> %d)",
1106                         aop->aopu.aop_immd,
1107                         offset*8);
1108             else
1109                 sprintf(s,"%s",
1110                         aop->aopu.aop_immd);
1111         pcop->name = Safe_calloc(1,strlen(s)+1);
1112         strcpy(pcop->name,s);   
1113         return pcop;
1114         
1115     case AOP_DIR:
1116         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1117         pcop->type = PO_DIR;
1118         if (offset)
1119             sprintf(s,"(%s + %d)",
1120                     aop->aopu.aop_dir,
1121                     offset);
1122         else
1123             sprintf(s,"%s",aop->aopu.aop_dir);
1124         pcop->name = Safe_calloc(1,strlen(s)+1);
1125         strcpy(pcop->name,s);   
1126         return pcop;
1127         
1128     case AOP_REG:
1129       DEBUGemitcode(";","%d",__LINE__);
1130       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1131       pcop->type = PO_GPR_REGISTER;
1132       if (dname)
1133         rs = aop->aopu.aop_reg[offset]->dname;
1134       else 
1135         rs = aop->aopu.aop_reg[offset]->name;
1136
1137       DEBUGemitcode(";","%d  %s",__LINE__,rs);
1138       pcop->name = Safe_calloc(1,(strlen(rs)+1));
1139       strcpy(pcop->name,rs);   
1140       return pcop;
1141
1142     case AOP_CRY:
1143       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1144       return pcop;
1145         
1146     case AOP_LIT:
1147       DEBUGemitcode(";","%d",__LINE__);
1148       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1149
1150     case AOP_STR:
1151       DEBUGemitcode(";","%d",__LINE__);
1152
1153       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1154       pcop->type = PO_STR;
1155
1156       //aop->coff = offset ;
1157         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1158           sprintf(s,"%s","acc");
1159         else
1160           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1161         pcop->name = Safe_calloc(1,strlen(s)+1);
1162         strcpy(pcop->name,s);   
1163         return pcop;
1164         
1165     }
1166
1167     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1168            "popGet got unsupported aop->type");
1169     exit(0);
1170 }
1171 /*-----------------------------------------------------------------*/
1172 /* aopPut - puts a string for a aop                                */
1173 /*-----------------------------------------------------------------*/
1174 static void aopPut (asmop *aop, char *s, int offset)
1175 {
1176     char *d = buffer ;
1177     symbol *lbl ;
1178
1179     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1180
1181     if (aop->size && offset > ( aop->size - 1)) {
1182         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1183                "aopPut got offset > aop->size");
1184         exit(0);
1185     }
1186
1187     /* will assign value to value */
1188     /* depending on where it is ofcourse */
1189     switch (aop->type) {
1190     case AOP_DIR:
1191         if (offset)
1192             sprintf(d,"(%s + %d)",
1193                     aop->aopu.aop_dir,offset);
1194         else
1195             sprintf(d,"%s",aop->aopu.aop_dir);
1196         
1197         if (strcmp(d,s)) {
1198           DEBUGemitcode(";","%d",__LINE__);
1199           if(strcmp(s,"W"))
1200             emitcode("movf","%s,w",s);
1201           emitcode("movwf","%s",d);
1202
1203           if(strcmp(s,"W"))
1204             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1205           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1206
1207
1208         }
1209         break;
1210         
1211     case AOP_REG:
1212         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1213             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1214           /*
1215             if (*s == '@'           ||
1216                 strcmp(s,"r0") == 0 ||
1217                 strcmp(s,"r1") == 0 ||
1218                 strcmp(s,"r2") == 0 ||
1219                 strcmp(s,"r3") == 0 ||
1220                 strcmp(s,"r4") == 0 ||
1221                 strcmp(s,"r5") == 0 ||
1222                 strcmp(s,"r6") == 0 || 
1223                 strcmp(s,"r7") == 0 )
1224                 emitcode("mov","%s,%s  ; %d",
1225                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1226             else
1227           */
1228
1229           if(strcmp(s,"W"))
1230             emitcode("movf","%s,w  ; %d",s,__LINE__);
1231
1232           emitcode("movwf","%s",
1233                    aop->aopu.aop_reg[offset]->name);
1234
1235           if(strcmp(s,"W"))
1236             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1237           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1238
1239         }
1240         break;
1241         
1242     case AOP_DPTR:
1243     case AOP_DPTR2:
1244     
1245     if (aop->type == AOP_DPTR2)
1246     {
1247         genSetDPTR(1);
1248     }
1249     
1250         if (aop->code) {
1251             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1252                    "aopPut writting to code space");
1253             exit(0);
1254         }
1255         
1256         while (offset > aop->coff) {
1257             aop->coff++;
1258             emitcode ("inc","dptr");
1259         }
1260         
1261         while (offset < aop->coff) {
1262             aop->coff-- ;
1263             emitcode("lcall","__decdptr");
1264         }
1265         
1266         aop->coff = offset;
1267         
1268         /* if not in accumulater */
1269         MOVA(s);        
1270         
1271         emitcode ("movx","@dptr,a");
1272         
1273     if (aop->type == AOP_DPTR2)
1274     {
1275         genSetDPTR(0);
1276     }
1277         break;
1278         
1279     case AOP_R0:
1280     case AOP_R1:
1281         while (offset > aop->coff) {
1282             aop->coff++;
1283             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1284         }
1285         while (offset < aop->coff) {
1286             aop->coff-- ;
1287             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1288         }
1289         aop->coff = offset;
1290         
1291         if (aop->paged) {
1292             MOVA(s);           
1293             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1294             
1295         } else
1296             if (*s == '@') {
1297                 MOVA(s);
1298                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1299             } else
1300                 if (strcmp(s,"r0") == 0 ||
1301                     strcmp(s,"r1") == 0 ||
1302                     strcmp(s,"r2") == 0 ||
1303                     strcmp(s,"r3") == 0 ||
1304                     strcmp(s,"r4") == 0 ||
1305                     strcmp(s,"r5") == 0 ||
1306                     strcmp(s,"r6") == 0 || 
1307                     strcmp(s,"r7") == 0 ) {
1308                     char buffer[10];
1309                     sprintf(buffer,"a%s",s);
1310                     emitcode("mov","@%s,%s",
1311                              aop->aopu.aop_ptr->name,buffer);
1312                 } else
1313                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1314         
1315         break;
1316         
1317     case AOP_STK:
1318         if (strcmp(s,"a") == 0)
1319             emitcode("push","acc");
1320         else
1321             emitcode("push","%s",s);
1322         
1323         break;
1324         
1325     case AOP_CRY:
1326         /* if bit variable */
1327         if (!aop->aopu.aop_dir) {
1328             emitcode("clr","a");
1329             emitcode("rlc","a");
1330         } else {
1331             if (s == zero) 
1332                 emitcode("clr","%s",aop->aopu.aop_dir);
1333             else
1334                 if (s == one)
1335                     emitcode("setb","%s",aop->aopu.aop_dir);
1336                 else
1337                     if (!strcmp(s,"c"))
1338                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1339                     else {
1340                         lbl = newiTempLabel(NULL);
1341                         
1342                         if (strcmp(s,"a")) {
1343                             MOVA(s);
1344                         }
1345                         emitcode("clr","c");
1346                         emitcode("jz","%05d_DS_",lbl->key+100);
1347                         emitcode("cpl","c");
1348                         emitcode("","%05d_DS_:",lbl->key+100);
1349                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1350                     }
1351         }
1352         break;
1353         
1354     case AOP_STR:
1355         aop->coff = offset;
1356         if (strcmp(aop->aopu.aop_str[offset],s))
1357             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1358         break;
1359         
1360     case AOP_ACC:
1361         aop->coff = offset;
1362         if (!offset && (strcmp(s,"acc") == 0))
1363             break;
1364         
1365         if (strcmp(aop->aopu.aop_str[offset],s))
1366             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1367         break;
1368
1369     default :
1370         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1371                "aopPut got unsupported aop->type");
1372         exit(0);    
1373     }    
1374
1375 }
1376
1377 /*-----------------------------------------------------------------*/
1378 /* reAdjustPreg - points a register back to where it should        */
1379 /*-----------------------------------------------------------------*/
1380 static void reAdjustPreg (asmop *aop)
1381 {
1382     int size ;
1383
1384     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1385     aop->coff = 0;
1386     if ((size = aop->size) <= 1)
1387         return ;
1388     size-- ;
1389     switch (aop->type) {
1390         case AOP_R0 :
1391         case AOP_R1 :
1392             while (size--)
1393                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1394             break;          
1395         case AOP_DPTR :
1396         case AOP_DPTR2:
1397             if (aop->type == AOP_DPTR2)
1398             {
1399                 genSetDPTR(1);
1400             } 
1401             while (size--)
1402             {
1403                 emitcode("lcall","__decdptr");
1404             }
1405                 
1406             if (aop->type == AOP_DPTR2)
1407             {
1408                 genSetDPTR(0);
1409             }                
1410             break;  
1411
1412     }   
1413
1414 }
1415
1416 #define AOP(op) op->aop
1417 #define AOP_TYPE(op) AOP(op)->type
1418 #define AOP_SIZE(op) AOP(op)->size
1419 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1420                        AOP_TYPE(x) == AOP_R0))
1421
1422 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1423                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1424                          AOP(x)->paged)) 
1425
1426 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1427                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1428                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1429
1430 /*-----------------------------------------------------------------*/
1431 /* genNotFloat - generates not for float operations              */
1432 /*-----------------------------------------------------------------*/
1433 static void genNotFloat (operand *op, operand *res)
1434 {
1435     int size, offset;
1436     char *l;
1437     symbol *tlbl ;
1438
1439     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1440     /* we will put 127 in the first byte of 
1441     the result */
1442     aopPut(AOP(res),"#127",0);
1443     size = AOP_SIZE(op) - 1;
1444     offset = 1;
1445
1446     l = aopGet(op->aop,offset++,FALSE,FALSE);
1447     MOVA(l);    
1448
1449     while(size--) {
1450         emitcode("orl","a,%s",
1451                  aopGet(op->aop,
1452                         offset++,FALSE,FALSE));
1453     }
1454     tlbl = newiTempLabel(NULL);
1455
1456     tlbl = newiTempLabel(NULL);
1457     aopPut(res->aop,one,1);
1458     emitcode("jz","%05d_DS_",(tlbl->key+100));
1459     aopPut(res->aop,zero,1);
1460     emitcode("","%05d_DS_:",(tlbl->key+100));
1461
1462     size = res->aop->size - 2;
1463     offset = 2;    
1464     /* put zeros in the rest */
1465     while (size--) 
1466         aopPut(res->aop,zero,offset++);
1467 }
1468
1469 #if 0
1470 /*-----------------------------------------------------------------*/
1471 /* opIsGptr: returns non-zero if the passed operand is             */   
1472 /* a generic pointer type.                                         */
1473 /*-----------------------------------------------------------------*/ 
1474 static int opIsGptr(operand *op)
1475 {
1476     sym_link *type = operandType(op);
1477     
1478     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1479     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1480     {
1481         return 1;
1482     }
1483     return 0;        
1484 }
1485 #endif
1486
1487 /*-----------------------------------------------------------------*/
1488 /* getDataSize - get the operand data size                         */
1489 /*-----------------------------------------------------------------*/
1490 static int getDataSize(operand *op)
1491 {
1492     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1493
1494
1495     return AOP_SIZE(op);
1496
1497     // tsd- in the pic port, the genptr size is 1, so this code here
1498     // fails. ( in the 8051 port, the size was 4).
1499 #if 0
1500     int size;
1501     size = AOP_SIZE(op);
1502     if (size == GPTRSIZE)
1503     {
1504         sym_link *type = operandType(op);
1505         if (IS_GENPTR(type))
1506         {
1507             /* generic pointer; arithmetic operations
1508              * should ignore the high byte (pointer type).
1509              */
1510             size--;
1511     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1512         }
1513     }
1514     return size;
1515 #endif
1516 }
1517
1518 /*-----------------------------------------------------------------*/
1519 /* outAcc - output Acc                                             */
1520 /*-----------------------------------------------------------------*/
1521 static void outAcc(operand *result)
1522 {
1523     int size, offset;
1524     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1525     size = getDataSize(result);
1526     if(size){
1527         aopPut(AOP(result),"a",0);
1528         size--;
1529         offset = 1;
1530         /* unsigned or positive */
1531         while(size--){
1532             aopPut(AOP(result),zero,offset++);
1533         }
1534     }
1535 }
1536
1537 /*-----------------------------------------------------------------*/
1538 /* outBitC - output a bit C                                        */
1539 /*-----------------------------------------------------------------*/
1540 static void outBitC(operand *result)
1541 {
1542
1543     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1544     /* if the result is bit */
1545     if (AOP_TYPE(result) == AOP_CRY) 
1546         aopPut(AOP(result),"c",0);
1547     else {
1548         emitcode("clr","a  ; %d", __LINE__);
1549         emitcode("rlc","a");
1550         outAcc(result);
1551     }
1552 }
1553
1554 /*-----------------------------------------------------------------*/
1555 /* toBoolean - emit code for orl a,operator(sizeop)                */
1556 /*-----------------------------------------------------------------*/
1557 static void toBoolean(operand *oper)
1558 {
1559     int size = AOP_SIZE(oper) - 1;
1560     int offset = 1;
1561
1562     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1563
1564     if ( AOP_TYPE(oper) != AOP_ACC) {
1565       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1566       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1567     }
1568     while (size--) {
1569       emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1570       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1571     }
1572 }
1573
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation                          */
1577 /*-----------------------------------------------------------------*/
1578 static void genNot (iCode *ic)
1579 {
1580     symbol *tlbl;
1581     sym_link *optype = operandType(IC_LEFT(ic));
1582
1583     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1584     /* assign asmOps to operand & result */
1585     aopOp (IC_LEFT(ic),ic,FALSE);
1586     aopOp (IC_RESULT(ic),ic,TRUE);
1587
1588     /* if in bit space then a special case */
1589     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1590       emitcode("movlw","1<<%s");
1591       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1592       //emitcode("cpl","c"); 
1593       //outBitC(IC_RESULT(ic));
1594       goto release;
1595     }
1596
1597     /* if type float then do float */
1598     if (IS_FLOAT(optype)) {
1599         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1600         goto release;
1601     }
1602
1603     toBoolean(IC_LEFT(ic));
1604
1605     tlbl = newiTempLabel(NULL);
1606     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1607     emitcode("","%05d_DS_:",tlbl->key+100);
1608     outBitC(IC_RESULT(ic));
1609
1610 release:    
1611     /* release the aops */
1612     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1613     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1614 }
1615
1616
1617 /*-----------------------------------------------------------------*/
1618 /* genCpl - generate code for complement                           */
1619 /*-----------------------------------------------------------------*/
1620 static void genCpl (iCode *ic)
1621 {
1622     int offset = 0;
1623     int size ;
1624
1625
1626     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1627     /* assign asmOps to operand & result */
1628     aopOp (IC_LEFT(ic),ic,FALSE);
1629     aopOp (IC_RESULT(ic),ic,TRUE);
1630
1631     /* if both are in bit space then 
1632     a special case */
1633     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1634         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1635
1636         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1637         emitcode("cpl","c"); 
1638         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1639         goto release; 
1640     } 
1641
1642     size = AOP_SIZE(IC_RESULT(ic));
1643     while (size--) {
1644         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1645         MOVA(l);       
1646         emitcode("cpl","a");
1647         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1648     }
1649
1650
1651 release:
1652     /* release the aops */
1653     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1654     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* genUminusFloat - unary minus for floating points                */
1659 /*-----------------------------------------------------------------*/
1660 static void genUminusFloat(operand *op,operand *result)
1661 {
1662     int size ,offset =0 ;
1663     char *l;
1664
1665     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1666     /* for this we just need to flip the 
1667     first it then copy the rest in place */
1668     size = AOP_SIZE(op) - 1;
1669     l = aopGet(AOP(op),3,FALSE,FALSE);
1670
1671     MOVA(l);    
1672
1673     emitcode("cpl","acc.7");
1674     aopPut(AOP(result),"a",3);    
1675
1676     while(size--) {
1677         aopPut(AOP(result),
1678                aopGet(AOP(op),offset,FALSE,FALSE),
1679                offset);
1680         offset++;
1681     }          
1682 }
1683
1684 /*-----------------------------------------------------------------*/
1685 /* genUminus - unary minus code generation                         */
1686 /*-----------------------------------------------------------------*/
1687 static void genUminus (iCode *ic)
1688 {
1689     int offset ,size ;
1690     sym_link *optype, *rtype;
1691
1692
1693     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1694     /* assign asmops */
1695     aopOp(IC_LEFT(ic),ic,FALSE);
1696     aopOp(IC_RESULT(ic),ic,TRUE);
1697
1698     /* if both in bit space then special
1699     case */
1700     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1701         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1702
1703         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1704         emitcode("cpl","c"); 
1705         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1706         goto release; 
1707     } 
1708
1709     optype = operandType(IC_LEFT(ic));
1710     rtype = operandType(IC_RESULT(ic));
1711
1712     /* if float then do float stuff */
1713     if (IS_FLOAT(optype)) {
1714         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1715         goto release;
1716     }
1717
1718     /* otherwise subtract from zero */
1719     size = AOP_SIZE(IC_LEFT(ic));
1720     offset = 0 ;
1721     CLRC ;
1722     while(size--) {
1723         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1724         if (!strcmp(l,"a")) {
1725             emitcode("cpl","a");
1726             emitcode("inc","a");
1727         } else {
1728             emitcode("clr","a");
1729             emitcode("subb","a,%s",l);
1730         }       
1731         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1732     }
1733
1734     /* if any remaining bytes in the result */
1735     /* we just need to propagate the sign   */
1736     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1737         emitcode("rlc","a");
1738         emitcode("subb","a,acc");
1739         while (size--) 
1740             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1741     }       
1742
1743 release:
1744     /* release the aops */
1745     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1746     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1747 }
1748
1749 /*-----------------------------------------------------------------*/
1750 /* saveRegisters - will look for a call and save the registers     */
1751 /*-----------------------------------------------------------------*/
1752 static void saveRegisters(iCode *lic) 
1753 {
1754     int i;
1755     iCode *ic;
1756     bitVect *rsave;
1757     sym_link *detype;
1758
1759     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1760     /* look for call */
1761     for (ic = lic ; ic ; ic = ic->next) 
1762         if (ic->op == CALL || ic->op == PCALL)
1763             break;
1764
1765     if (!ic) {
1766         fprintf(stderr,"found parameter push with no function call\n");
1767         return ;
1768     }
1769
1770     /* if the registers have been saved already then
1771     do nothing */
1772     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1773         return ;
1774
1775     /* find the registers in use at this time 
1776     and push them away to safety */
1777     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1778                           ic->rUsed);
1779
1780     ic->regsSaved = 1;
1781     if (options.useXstack) {
1782         if (bitVectBitValue(rsave,R0_IDX))
1783             emitcode("mov","b,r0");
1784         emitcode("mov","r0,%s",spname);
1785         for (i = 0 ; i < pic14_nRegs ; i++) {
1786             if (bitVectBitValue(rsave,i)) {
1787                 if (i == R0_IDX)
1788                     emitcode("mov","a,b");
1789                 else
1790                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1791                 emitcode("movx","@r0,a");
1792                 emitcode("inc","r0");
1793             }
1794         }
1795         emitcode("mov","%s,r0",spname);
1796         if (bitVectBitValue(rsave,R0_IDX))
1797             emitcode("mov","r0,b");         
1798     } else
1799         for (i = 0 ; i < pic14_nRegs ; i++) {
1800             if (bitVectBitValue(rsave,i))
1801                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1802         }
1803
1804     detype = getSpec(operandType(IC_LEFT(ic)));
1805     if (detype        && 
1806         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1807         IS_ISR(currFunc->etype) &&
1808         !ic->bankSaved) 
1809
1810         saverbank(SPEC_BANK(detype),ic,TRUE);
1811
1812 }
1813 /*-----------------------------------------------------------------*/
1814 /* unsaveRegisters - pop the pushed registers                      */
1815 /*-----------------------------------------------------------------*/
1816 static void unsaveRegisters (iCode *ic)
1817 {
1818     int i;
1819     bitVect *rsave;
1820
1821     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1822     /* find the registers in use at this time 
1823     and push them away to safety */
1824     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1825                           ic->rUsed);
1826     
1827     if (options.useXstack) {
1828         emitcode("mov","r0,%s",spname); 
1829         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1830             if (bitVectBitValue(rsave,i)) {
1831                 emitcode("dec","r0");
1832                 emitcode("movx","a,@r0");
1833                 if (i == R0_IDX)
1834                     emitcode("mov","b,a");
1835                 else
1836                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1837             }       
1838
1839         }
1840         emitcode("mov","%s,r0",spname);
1841         if (bitVectBitValue(rsave,R0_IDX))
1842             emitcode("mov","r0,b");
1843     } else
1844         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1845             if (bitVectBitValue(rsave,i))
1846                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1847         }
1848
1849 }  
1850
1851
1852 /*-----------------------------------------------------------------*/
1853 /* pushSide -                                                      */
1854 /*-----------------------------------------------------------------*/
1855 static void pushSide(operand * oper, int size)
1856 {
1857         int offset = 0;
1858     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1859         while (size--) {
1860                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1861                 if (AOP_TYPE(oper) != AOP_REG &&
1862                     AOP_TYPE(oper) != AOP_DIR &&
1863                     strcmp(l,"a") ) {
1864                         emitcode("mov","a,%s",l);
1865                         emitcode("push","acc");
1866                 } else
1867                         emitcode("push","%s",l);
1868         }
1869 }
1870
1871 /*-----------------------------------------------------------------*/
1872 /* assignResultValue -                                             */
1873 /*-----------------------------------------------------------------*/
1874 static void assignResultValue(operand * oper)
1875 {
1876         int offset = 0;
1877         int size = AOP_SIZE(oper);
1878
1879     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1880
1881     // The last byte in the assignment is in W
1882     aopPut(AOP(oper),"W",size-1);
1883
1884     if(size>1) {
1885       while (--size) {
1886         aopPut(AOP(oper),fReturn[offset],offset);
1887         offset++;
1888
1889       }
1890     }
1891 }
1892
1893
1894 /*-----------------------------------------------------------------*/
1895 /* genXpush - pushes onto the external stack                       */
1896 /*-----------------------------------------------------------------*/
1897 static void genXpush (iCode *ic)
1898 {
1899     asmop *aop = newAsmop(0);
1900     regs *r ;
1901     int size,offset = 0;
1902
1903     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1904     aopOp(IC_LEFT(ic),ic,FALSE);
1905     r = getFreePtr(ic,&aop,FALSE);
1906
1907     
1908     emitcode("mov","%s,_spx",r->name);
1909
1910     size = AOP_SIZE(IC_LEFT(ic));
1911     while(size--) {
1912
1913         char *l = aopGet(AOP(IC_LEFT(ic)),
1914                          offset++,FALSE,FALSE); 
1915         MOVA(l);            
1916         emitcode("movx","@%s,a",r->name);       
1917         emitcode("inc","%s",r->name);
1918
1919     }
1920
1921         
1922     emitcode("mov","_spx,%s",r->name);
1923
1924     freeAsmop(NULL,aop,ic,TRUE);
1925     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1926 }
1927
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex  */
1930 /*-----------------------------------------------------------------*/
1931 static void genIpush (iCode *ic)
1932 {
1933     int size, offset = 0 ;
1934     char *l;
1935
1936
1937     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1938     /* if this is not a parm push : ie. it is spill push 
1939     and spill push is always done on the local stack */
1940     if (!ic->parmPush) {
1941
1942         /* and the item is spilt then do nothing */
1943         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1944             return ;
1945
1946         aopOp(IC_LEFT(ic),ic,FALSE);
1947         size = AOP_SIZE(IC_LEFT(ic));
1948         /* push it on the stack */
1949         while(size--) {
1950             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1951             if (*l == '#') {
1952                 MOVA(l);
1953                 l = "acc";
1954             }
1955             emitcode("push","%s",l);
1956         }
1957         return ;        
1958     }
1959
1960     /* this is a paramter push: in this case we call
1961     the routine to find the call and save those
1962     registers that need to be saved */   
1963     saveRegisters(ic);
1964
1965     /* if use external stack then call the external
1966     stack pushing routine */
1967     if (options.useXstack) {
1968         genXpush(ic);
1969         return ;
1970     }
1971
1972     /* then do the push */
1973     aopOp(IC_LEFT(ic),ic,FALSE);
1974
1975
1976         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1977     size = AOP_SIZE(IC_LEFT(ic));
1978
1979     while (size--) {
1980         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1981         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1982             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1983             strcmp(l,"a") ) {
1984             emitcode("mov","a,%s",l);
1985             emitcode("push","acc");
1986         } else
1987             emitcode("push","%s",l);
1988     }       
1989
1990     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1991 }
1992
1993 /*-----------------------------------------------------------------*/
1994 /* genIpop - recover the registers: can happen only for spilling   */
1995 /*-----------------------------------------------------------------*/
1996 static void genIpop (iCode *ic)
1997 {
1998     int size,offset ;
1999
2000
2001     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2002     /* if the temp was not pushed then */
2003     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2004         return ;
2005
2006     aopOp(IC_LEFT(ic),ic,FALSE);
2007     size = AOP_SIZE(IC_LEFT(ic));
2008     offset = (size-1);
2009     while (size--) 
2010         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2011                                    FALSE,TRUE));
2012
2013     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2014 }
2015
2016 /*-----------------------------------------------------------------*/
2017 /* unsaverbank - restores the resgister bank from stack            */
2018 /*-----------------------------------------------------------------*/
2019 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2020 {
2021     int i;
2022     asmop *aop ;
2023     regs *r = NULL;
2024
2025     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2026     if (popPsw) {
2027         if (options.useXstack) {
2028             aop = newAsmop(0);
2029             r = getFreePtr(ic,&aop,FALSE);
2030             
2031             
2032             emitcode("mov","%s,_spx",r->name);
2033             emitcode("movx","a,@%s",r->name);
2034             emitcode("mov","psw,a");
2035             emitcode("dec","%s",r->name);
2036             
2037         }else
2038             emitcode ("pop","psw");
2039     }
2040
2041     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2042         if (options.useXstack) {       
2043             emitcode("movx","a,@%s",r->name);
2044             //emitcode("mov","(%s+%d),a",
2045             //       regspic14[i].base,8*bank+regspic14[i].offset);
2046             emitcode("dec","%s",r->name);
2047
2048         } else 
2049           emitcode("pop",""); //"(%s+%d)",
2050         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2051     }
2052
2053     if (options.useXstack) {
2054
2055         emitcode("mov","_spx,%s",r->name);
2056         freeAsmop(NULL,aop,ic,TRUE);
2057
2058     } 
2059 }
2060
2061 /*-----------------------------------------------------------------*/
2062 /* saverbank - saves an entire register bank on the stack          */
2063 /*-----------------------------------------------------------------*/
2064 static void saverbank (int bank, iCode *ic, bool pushPsw)
2065 {
2066     int i;
2067     asmop *aop ;
2068     regs *r = NULL;
2069
2070     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071     if (options.useXstack) {
2072
2073         aop = newAsmop(0);
2074         r = getFreePtr(ic,&aop,FALSE);  
2075         emitcode("mov","%s,_spx",r->name);
2076
2077     }
2078
2079     for (i = 0 ; i < pic14_nRegs ;i++) {
2080         if (options.useXstack) {
2081             emitcode("inc","%s",r->name);
2082             //emitcode("mov","a,(%s+%d)",
2083             //         regspic14[i].base,8*bank+regspic14[i].offset);
2084             emitcode("movx","@%s,a",r->name);           
2085         } else 
2086           emitcode("push","");// "(%s+%d)",
2087                      //regspic14[i].base,8*bank+regspic14[i].offset);
2088     }
2089     
2090     if (pushPsw) {
2091         if (options.useXstack) {
2092             emitcode("mov","a,psw");
2093             emitcode("movx","@%s,a",r->name);   
2094             emitcode("inc","%s",r->name);
2095             emitcode("mov","_spx,%s",r->name);       
2096             freeAsmop (NULL,aop,ic,TRUE);
2097             
2098         } else
2099             emitcode("push","psw");
2100         
2101         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2102     }
2103     ic->bankSaved = 1;
2104
2105 }
2106
2107 /*-----------------------------------------------------------------*/
2108 /* genCall - generates a call statement                            */
2109 /*-----------------------------------------------------------------*/
2110 static void genCall (iCode *ic)
2111 {
2112     sym_link *detype;   
2113
2114     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2115
2116     /* if caller saves & we have not saved then */
2117     if (!ic->regsSaved)
2118         saveRegisters(ic);
2119
2120     /* if we are calling a function that is not using
2121     the same register bank then we need to save the
2122     destination registers on the stack */
2123     detype = getSpec(operandType(IC_LEFT(ic)));
2124     if (detype        && 
2125         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2126         IS_ISR(currFunc->etype) &&
2127         !ic->bankSaved) 
2128
2129         saverbank(SPEC_BANK(detype),ic,TRUE);
2130
2131     /* if send set is not empty the assign */
2132     if (_G.sendSet) {
2133         iCode *sic ;
2134
2135         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2136              sic = setNextItem(_G.sendSet)) {
2137             int size, offset = 0;
2138
2139             aopOp(IC_LEFT(sic),sic,FALSE);
2140             size = AOP_SIZE(IC_LEFT(sic));
2141             while (size--) {
2142                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2143                                 FALSE,FALSE);
2144                 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2145
2146                 if (strcmp(l,fReturn[offset])) {
2147
2148                   if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2149                        ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2150                     emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2151                   //emitcode("movlw","%s",l);
2152                   else
2153                     emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2154                   //emitcode("movf","%s,w",l);
2155
2156                   // The last one is passed in W
2157                   if(size)
2158                     emitcode("movwf","%s",fReturn[offset]);
2159                 }
2160                 offset++;
2161             }
2162             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2163         }
2164         _G.sendSet = NULL;
2165     }
2166     /* make the call */
2167     emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2168                                         OP_SYMBOL(IC_LEFT(ic))->rname :
2169                                         OP_SYMBOL(IC_LEFT(ic))->name));
2170
2171     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2172                            OP_SYMBOL(IC_LEFT(ic))->rname :
2173                            OP_SYMBOL(IC_LEFT(ic))->name));
2174
2175     /* if we need assign a result value */
2176     if ((IS_ITEMP(IC_RESULT(ic)) && 
2177          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2178           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2179         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2180
2181         _G.accInUse++;
2182         aopOp(IC_RESULT(ic),ic,FALSE);
2183         _G.accInUse--;
2184
2185         assignResultValue(IC_RESULT(ic));
2186                 
2187         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2188     }
2189
2190     /* adjust the stack for parameters if 
2191     required */
2192     if (IC_LEFT(ic)->parmBytes) {
2193         int i;
2194         if (IC_LEFT(ic)->parmBytes > 3) {
2195             emitcode("mov","a,%s",spname);
2196             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2197             emitcode("mov","%s,a",spname);
2198         } else 
2199             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2200                 emitcode("dec","%s",spname);
2201
2202     }
2203
2204     /* if register bank was saved then pop them */
2205     if (ic->bankSaved)
2206         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2207
2208     /* if we hade saved some registers then unsave them */
2209     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2210         unsaveRegisters (ic);
2211
2212
2213 }
2214
2215 /*-----------------------------------------------------------------*/
2216 /* genPcall - generates a call by pointer statement                */
2217 /*-----------------------------------------------------------------*/
2218 static void genPcall (iCode *ic)
2219 {
2220     sym_link *detype;
2221     symbol *rlbl = newiTempLabel(NULL);
2222
2223
2224     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2225     /* if caller saves & we have not saved then */
2226     if (!ic->regsSaved)
2227         saveRegisters(ic);
2228
2229     /* if we are calling a function that is not using
2230     the same register bank then we need to save the
2231     destination registers on the stack */
2232     detype = getSpec(operandType(IC_LEFT(ic)));
2233     if (detype        && 
2234         IS_ISR(currFunc->etype) &&
2235         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2236         saverbank(SPEC_BANK(detype),ic,TRUE);
2237
2238
2239     /* push the return address on to the stack */
2240     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2241     emitcode("push","acc");    
2242     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2243     emitcode("push","acc");
2244     
2245     if (options.model == MODEL_FLAT24)
2246     {
2247         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2248         emitcode("push","acc");    
2249     }
2250
2251     /* now push the calling address */
2252     aopOp(IC_LEFT(ic),ic,FALSE);
2253
2254     pushSide(IC_LEFT(ic), FPTRSIZE);
2255
2256     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2257
2258     /* if send set is not empty the assign */
2259     if (_G.sendSet) {
2260         iCode *sic ;
2261
2262         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2263              sic = setNextItem(_G.sendSet)) {
2264             int size, offset = 0;
2265             aopOp(IC_LEFT(sic),sic,FALSE);
2266             size = AOP_SIZE(IC_LEFT(sic));
2267             while (size--) {
2268                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2269                                 FALSE,FALSE);
2270                 if (strcmp(l,fReturn[offset]))
2271                     emitcode("mov","%s,%s",
2272                              fReturn[offset],
2273                              l);
2274                 offset++;
2275             }
2276             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2277         }
2278         _G.sendSet = NULL;
2279     }
2280
2281     emitcode("ret","");
2282     emitcode("","%05d_DS_:",(rlbl->key+100));
2283
2284
2285     /* if we need assign a result value */
2286     if ((IS_ITEMP(IC_RESULT(ic)) &&
2287          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2288           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2289         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2290
2291         _G.accInUse++;
2292         aopOp(IC_RESULT(ic),ic,FALSE);
2293         _G.accInUse--;
2294         
2295         assignResultValue(IC_RESULT(ic));
2296
2297         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2298     }
2299
2300     /* adjust the stack for parameters if 
2301     required */
2302     if (IC_LEFT(ic)->parmBytes) {
2303         int i;
2304         if (IC_LEFT(ic)->parmBytes > 3) {
2305             emitcode("mov","a,%s",spname);
2306             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2307             emitcode("mov","%s,a",spname);
2308         } else 
2309             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2310                 emitcode("dec","%s",spname);
2311
2312     }
2313
2314     /* if register bank was saved then unsave them */
2315     if (detype        && 
2316         (SPEC_BANK(currFunc->etype) != 
2317          SPEC_BANK(detype)))
2318         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2319
2320     /* if we hade saved some registers then
2321     unsave them */
2322     if (ic->regsSaved)
2323         unsaveRegisters (ic);
2324
2325 }
2326
2327 /*-----------------------------------------------------------------*/
2328 /* resultRemat - result  is rematerializable                       */
2329 /*-----------------------------------------------------------------*/
2330 static int resultRemat (iCode *ic)
2331 {
2332     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2333     if (SKIP_IC(ic) || ic->op == IFX)
2334         return 0;
2335
2336     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2337         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2338         if (sym->remat && !POINTER_SET(ic)) 
2339             return 1;
2340     }
2341
2342     return 0;
2343 }
2344
2345 #if defined(__BORLANDC__) || defined(_MSC_VER)
2346 #define STRCASECMP stricmp
2347 #else
2348 #define STRCASECMP strcasecmp
2349 #endif
2350
2351 /*-----------------------------------------------------------------*/
2352 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2353 /*-----------------------------------------------------------------*/
2354 static bool inExcludeList(char *s)
2355 {
2356     int i =0;
2357     
2358     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2359     if (options.excludeRegs[i] &&
2360     STRCASECMP(options.excludeRegs[i],"none") == 0)
2361         return FALSE ;
2362
2363     for ( i = 0 ; options.excludeRegs[i]; i++) {
2364         if (options.excludeRegs[i] &&
2365         STRCASECMP(s,options.excludeRegs[i]) == 0)
2366             return TRUE;
2367     }
2368     return FALSE ;
2369 }
2370
2371 /*-----------------------------------------------------------------*/
2372 /* genFunction - generated code for function entry                 */
2373 /*-----------------------------------------------------------------*/
2374 static void genFunction (iCode *ic)
2375 {
2376     symbol *sym;
2377     sym_link *fetype;
2378
2379     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2380     labelOffset += FUNCTION_LABEL_INC;
2381
2382     _G.nRegsSaved = 0;
2383     /* create the function header */
2384     emitcode(";","-----------------------------------------");
2385     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2386     emitcode(";","-----------------------------------------");
2387
2388     emitcode("","%s:",sym->rname);
2389     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2390
2391     fetype = getSpec(operandType(IC_LEFT(ic)));
2392
2393     /* if critical function then turn interrupts off */
2394     if (SPEC_CRTCL(fetype))
2395         emitcode("clr","ea");
2396
2397     /* here we need to generate the equates for the
2398        register bank if required */
2399 #if 0
2400     if (SPEC_BANK(fetype) != rbank) {
2401         int i ;
2402
2403         rbank = SPEC_BANK(fetype);
2404         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2405             if (strcmp(regspic14[i].base,"0") == 0)
2406                 emitcode("","%s = 0x%02x",
2407                          regspic14[i].dname,
2408                          8*rbank+regspic14[i].offset);
2409             else
2410                 emitcode ("","%s = %s + 0x%02x",
2411                           regspic14[i].dname,
2412                           regspic14[i].base,
2413                           8*rbank+regspic14[i].offset);
2414         }
2415     }
2416 #endif
2417
2418     /* if this is an interrupt service routine then
2419     save acc, b, dpl, dph  */
2420     if (IS_ISR(sym->etype)) {
2421         
2422         if (!inExcludeList("acc"))          
2423             emitcode ("push","acc");    
2424         if (!inExcludeList("b"))
2425             emitcode ("push","b");
2426         if (!inExcludeList("dpl"))
2427             emitcode ("push","dpl");
2428         if (!inExcludeList("dph"))
2429             emitcode ("push","dph");
2430         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2431         {
2432             emitcode ("push", "dpx");
2433             /* Make sure we're using standard DPTR */
2434             emitcode ("push", "dps");
2435             emitcode ("mov", "dps, #0x00");
2436             if (options.stack10bit)
2437             {   
2438                 /* This ISR could conceivably use DPTR2. Better save it. */
2439                 emitcode ("push", "dpl1");
2440                 emitcode ("push", "dph1");
2441                 emitcode ("push", "dpx1");
2442             }
2443         }
2444         /* if this isr has no bank i.e. is going to
2445            run with bank 0 , then we need to save more
2446            registers :-) */
2447         if (!SPEC_BANK(sym->etype)) {
2448
2449             /* if this function does not call any other
2450                function then we can be economical and
2451                save only those registers that are used */
2452             if (! sym->hasFcall) {
2453                 int i;
2454
2455                 /* if any registers used */
2456                 if (sym->regsUsed) {
2457                     /* save the registers used */
2458                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2459                         if (bitVectBitValue(sym->regsUsed,i) ||
2460                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2461                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2462                     }
2463                 }
2464                 
2465             } else {
2466                 /* this function has  a function call cannot
2467                    determines register usage so we will have the
2468                    entire bank */
2469                 saverbank(0,ic,FALSE);
2470             }       
2471         }
2472     } else {
2473         /* if callee-save to be used for this function
2474            then save the registers being used in this function */
2475         if (sym->calleeSave) {
2476             int i;
2477             
2478             /* if any registers used */
2479             if (sym->regsUsed) {
2480                 /* save the registers used */
2481                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2482                     if (bitVectBitValue(sym->regsUsed,i) ||
2483                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2484                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2485                         _G.nRegsSaved++;
2486                     }
2487                 }
2488             }
2489         }
2490     }
2491
2492     /* set the register bank to the desired value */
2493     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2494         emitcode("push","psw");
2495         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2496     }
2497
2498     if (IS_RENT(sym->etype) || options.stackAuto) {
2499
2500         if (options.useXstack) {
2501             emitcode("mov","r0,%s",spname);
2502             emitcode("mov","a,_bp");
2503             emitcode("movx","@r0,a");
2504             emitcode("inc","%s",spname);
2505         }
2506         else
2507         {
2508             /* set up the stack */
2509             emitcode ("push","_bp");     /* save the callers stack  */
2510         }
2511         emitcode ("mov","_bp,%s",spname);
2512     }
2513
2514     /* adjust the stack for the function */
2515     if (sym->stack) {
2516
2517         int i = sym->stack;
2518         if (i > 256 ) 
2519             werror(W_STACK_OVERFLOW,sym->name);
2520
2521         if (i > 3 && sym->recvSize < 4) {              
2522
2523             emitcode ("mov","a,sp");
2524             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2525             emitcode ("mov","sp,a");
2526            
2527         }
2528         else
2529             while(i--)
2530                 emitcode("inc","sp");
2531     }
2532
2533      if (sym->xstack) {
2534
2535         emitcode ("mov","a,_spx");
2536         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2537         emitcode ("mov","_spx,a");
2538     }    
2539
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* genEndFunction - generates epilogue for functions               */
2544 /*-----------------------------------------------------------------*/
2545 static void genEndFunction (iCode *ic)
2546 {
2547     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2548
2549     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2550
2551     if (IS_RENT(sym->etype) || options.stackAuto)
2552     {
2553         emitcode ("mov","%s,_bp",spname);
2554     }
2555
2556     /* if use external stack but some variables were
2557     added to the local stack then decrement the
2558     local stack */
2559     if (options.useXstack && sym->stack) {      
2560         emitcode("mov","a,sp");
2561         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2562         emitcode("mov","sp,a");
2563     }
2564
2565
2566     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2567         if (options.useXstack) {
2568             emitcode("mov","r0,%s",spname);
2569             emitcode("movx","a,@r0");
2570             emitcode("mov","_bp,a");
2571             emitcode("dec","%s",spname);
2572         }
2573         else
2574         {
2575             emitcode ("pop","_bp");
2576         }
2577     }
2578
2579     /* restore the register bank  */    
2580     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2581         emitcode ("pop","psw");
2582
2583     if (IS_ISR(sym->etype)) {
2584
2585         /* now we need to restore the registers */
2586         /* if this isr has no bank i.e. is going to
2587            run with bank 0 , then we need to save more
2588            registers :-) */
2589         if (!SPEC_BANK(sym->etype)) {
2590             
2591             /* if this function does not call any other
2592                function then we can be economical and
2593                save only those registers that are used */
2594             if (! sym->hasFcall) {
2595                 int i;
2596                 
2597                 /* if any registers used */
2598                 if (sym->regsUsed) {
2599                     /* save the registers used */
2600                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2601                         if (bitVectBitValue(sym->regsUsed,i) ||
2602                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2603                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2604                     }
2605                 }
2606                 
2607             } else {
2608                 /* this function has  a function call cannot
2609                    determines register usage so we will have the
2610                    entire bank */
2611                 unsaverbank(0,ic,FALSE);
2612             }       
2613         }
2614
2615         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2616         {
2617             if (options.stack10bit)
2618             {
2619                 emitcode ("pop", "dpx1");
2620                 emitcode ("pop", "dph1");
2621                 emitcode ("pop", "dpl1");
2622             }   
2623             emitcode ("pop", "dps");
2624             emitcode ("pop", "dpx");
2625         }
2626         if (!inExcludeList("dph"))
2627             emitcode ("pop","dph");
2628         if (!inExcludeList("dpl"))
2629             emitcode ("pop","dpl");
2630         if (!inExcludeList("b"))
2631             emitcode ("pop","b");
2632         if (!inExcludeList("acc"))
2633             emitcode ("pop","acc");
2634
2635         if (SPEC_CRTCL(sym->etype))
2636             emitcode("setb","ea");
2637
2638         /* if debug then send end of function */
2639 /*      if (options.debug && currFunc) { */
2640         if (currFunc) {
2641             _G.debugLine = 1;
2642             emitcode(";","C$%s$%d$%d$%d ==.",
2643                      FileBaseName(ic->filename),currFunc->lastLine,
2644                      ic->level,ic->block); 
2645             if (IS_STATIC(currFunc->etype))         
2646                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2647             else
2648                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2649             _G.debugLine = 0;
2650         }
2651         
2652         emitcode ("reti","");
2653     }
2654     else {
2655         if (SPEC_CRTCL(sym->etype))
2656             emitcode("setb","ea");
2657         
2658         if (sym->calleeSave) {
2659             int i;
2660             
2661             /* if any registers used */
2662             if (sym->regsUsed) {
2663                 /* save the registers used */
2664                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2665                     if (bitVectBitValue(sym->regsUsed,i) ||
2666                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2667                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2668                 }
2669             }
2670             
2671         }
2672
2673         /* if debug then send end of function */
2674         if (currFunc) {
2675             _G.debugLine = 1;
2676             emitcode(";","C$%s$%d$%d$%d ==.",
2677                      FileBaseName(ic->filename),currFunc->lastLine,
2678                      ic->level,ic->block); 
2679             if (IS_STATIC(currFunc->etype))         
2680                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2681             else
2682                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2683             _G.debugLine = 0;
2684         }
2685
2686         emitcode ("return","");
2687         emitpcode(POC_RETURN,NULL);
2688
2689         /* Mark the end of a function */
2690         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2691     }
2692
2693 }
2694
2695 /*-----------------------------------------------------------------*/
2696 /* genRet - generate code for return statement                     */
2697 /*-----------------------------------------------------------------*/
2698 static void genRet (iCode *ic)
2699 {
2700     int size,offset = 0 , pushed = 0;
2701     
2702     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2703     /* if we have no return value then
2704        just generate the "ret" */
2705     if (!IC_LEFT(ic)) 
2706         goto jumpret;       
2707     
2708     /* we have something to return then
2709        move the return value into place */
2710     aopOp(IC_LEFT(ic),ic,FALSE);
2711     size = AOP_SIZE(IC_LEFT(ic));
2712     
2713     while (size--) {
2714             char *l ;
2715             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2716                     /* #NOCHANGE */
2717                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2718                            FALSE,TRUE);
2719                     emitcode("push","%s",l);
2720                     pushed++;
2721             } else {
2722                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2723                                FALSE,FALSE);
2724                     if (strcmp(fReturn[offset],l)) {
2725                       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2726                           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2727                         emitcode("movlw","%s",l);
2728                       else
2729                         emitcode("movf","%s,w",l);
2730                       if(size)
2731                         emitcode("movwf","%s",fReturn[offset]);
2732                       offset++;
2733                     }
2734             }
2735     }    
2736
2737     if (pushed) {
2738         while(pushed) {
2739             pushed--;
2740             if (strcmp(fReturn[pushed],"a"))
2741                 emitcode("pop",fReturn[pushed]);
2742             else
2743                 emitcode("pop","acc");
2744         }
2745     }
2746     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2747     
2748  jumpret:
2749         /* generate a jump to the return label
2750            if the next is not the return statement */
2751     if (!(ic->next && ic->next->op == LABEL &&
2752           IC_LABEL(ic->next) == returnLabel))
2753         
2754         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2755     
2756 }
2757
2758 /*-----------------------------------------------------------------*/
2759 /* genLabel - generates a label                                    */
2760 /*-----------------------------------------------------------------*/
2761 static void genLabel (iCode *ic)
2762 {
2763     /* special case never generate */
2764     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2765     if (IC_LABEL(ic) == entryLabel)
2766         return ;
2767
2768     emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2769     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* genGoto - generates a goto                                      */
2774 /*-----------------------------------------------------------------*/
2775 //tsd
2776 static void genGoto (iCode *ic)
2777 {
2778     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2779 }
2780
2781 /*-----------------------------------------------------------------*/
2782 /* findLabelBackwards: walks back through the iCode chain looking  */
2783 /* for the given label. Returns number of iCode instructions       */
2784 /* between that label and given ic.                                */
2785 /* Returns zero if label not found.                                */
2786 /*-----------------------------------------------------------------*/
2787 #if 0
2788 static int findLabelBackwards(iCode *ic, int key)
2789 {
2790     int count = 0;
2791     
2792     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2793     while (ic->prev)
2794     {
2795         ic = ic->prev;
2796         count++;
2797         
2798         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2799         {
2800             /* printf("findLabelBackwards = %d\n", count); */
2801             return count;
2802         }
2803     }
2804     
2805     return 0;
2806 }
2807 #endif
2808 /*-----------------------------------------------------------------*/
2809 /* genPlusIncr :- does addition with increment if possible         */
2810 /*-----------------------------------------------------------------*/
2811 static bool genPlusIncr (iCode *ic)
2812 {
2813     unsigned int icount ;
2814     unsigned int size = getDataSize(IC_RESULT(ic));
2815
2816     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2817     DEBUGemitcode ("; ","result %d, left %d, right %d",
2818                    AOP_TYPE(IC_RESULT(ic)),
2819                    AOP_TYPE(IC_LEFT(ic)),
2820                    AOP_TYPE(IC_RIGHT(ic)));
2821
2822     /* will try to generate an increment */
2823     /* if the right side is not a literal 
2824        we cannot */
2825     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2826         return FALSE ;
2827     
2828     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2829     /* if the literal value of the right hand side
2830        is greater than 1 then it is faster to add */
2831     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2832         return FALSE ;
2833     
2834     /* if increment 16 bits in register */
2835     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2836         (icount == 1)) {
2837
2838       int offset = MSB16;
2839
2840       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2841       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2842
2843       while(--size) {
2844         emitSKPNZ;
2845         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2846         //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2847       }
2848
2849       return TRUE;
2850     }
2851     
2852     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2853     /* if left is in accumulator  - probably a bit operation*/
2854     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2855         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2856       
2857       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2858       emitcode("bcf","(%s >> 3), (%s & 7)",
2859                AOP(IC_RESULT(ic))->aopu.aop_dir,
2860                AOP(IC_RESULT(ic))->aopu.aop_dir);
2861       if(icount)
2862         emitpcode(POC_XORLW,popGetLit(1));
2863       //emitcode("xorlw","1");
2864       else
2865         emitpcode(POC_ANDLW,popGetLit(1));
2866       //emitcode("andlw","1");
2867
2868       emitSKPZ;
2869       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2870       emitcode("bsf","(%s >> 3), (%s & 7)",
2871                AOP(IC_RESULT(ic))->aopu.aop_dir,
2872                AOP(IC_RESULT(ic))->aopu.aop_dir);
2873
2874       return TRUE;
2875     }
2876
2877
2878
2879     /* if the sizes are greater than 1 then we cannot */
2880     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2881         AOP_SIZE(IC_LEFT(ic)) > 1   )
2882         return FALSE ;
2883     
2884     /* If we are incrementing the same register by two: */
2885
2886     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2887         
2888       while (icount--) 
2889         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2890       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2891         
2892       return TRUE ;
2893     }
2894     
2895     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2896                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2897                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2898     return FALSE ;
2899 }
2900
2901 /*-----------------------------------------------------------------*/
2902 /* outBitAcc - output a bit in acc                                 */
2903 /*-----------------------------------------------------------------*/
2904 static void outBitAcc(operand *result)
2905 {
2906     symbol *tlbl = newiTempLabel(NULL);
2907     /* if the result is a bit */
2908     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2909
2910     if (AOP_TYPE(result) == AOP_CRY){
2911         aopPut(AOP(result),"a",0);
2912     }
2913     else {
2914         emitcode("jz","%05d_DS_",tlbl->key+100);
2915         emitcode("mov","a,%s",one);
2916         emitcode("","%05d_DS_:",tlbl->key+100);
2917         outAcc(result);
2918     }
2919 }
2920
2921 /*-----------------------------------------------------------------*/
2922 /* genPlusBits - generates code for addition of two bits           */
2923 /*-----------------------------------------------------------------*/
2924 static void genPlusBits (iCode *ic)
2925 {
2926
2927     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2928     /*
2929       The following block of code will add two bits. 
2930       Note that it'll even work if the destination is
2931       the carry (C in the status register).
2932       It won't work if the 'Z' bit is a source or destination.
2933     */
2934
2935     /* If the result is stored in the accumulator (w) */
2936     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2937       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2938       //              popGet(AOP(result),0,FALSE,FALSE));
2939
2940       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2941       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2942       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2943       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2944       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2945       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2946
2947         emitcode("movlw","(1 << (%s & 7))",
2948                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2949                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2950         emitcode("bcf","(%s >> 3), (%s & 7)",
2951                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2952                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2953         emitcode("btfsc","(%s >> 3), (%s & 7)",
2954                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2955                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2956         emitcode("xorwf","(%s >>3),f",
2957                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2958         emitcode("btfsc","(%s >> 3), (%s & 7)",
2959                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2960                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2961         emitcode("xorwf","(%s>>3),f",
2962                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2963     } else { 
2964
2965       emitpcode(POC_CLRW, NULL);
2966       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2967       emitpcode(POC_XORLW, popGetLit(1));
2968       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2969       emitpcode(POC_XORLW, popGetLit(1));
2970
2971       emitcode("clrw","");
2972       emitcode("btfsc","(%s >> 3), (%s & 7)",
2973                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2974                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2975       emitcode("xorlw","1");
2976       emitcode("btfsc","(%s >> 3), (%s & 7)",
2977                AOP(IC_LEFT(ic))->aopu.aop_dir,
2978                AOP(IC_LEFT(ic))->aopu.aop_dir);
2979       emitcode("xorlw","1");
2980     }
2981
2982 }
2983
2984 #if 0
2985 /* This is the original version of this code.
2986  *
2987  * This is being kept around for reference, 
2988  * because I am not entirely sure I got it right...
2989  */
2990 static void adjustArithmeticResult(iCode *ic)
2991 {
2992     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2993         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2994         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2995         aopPut(AOP(IC_RESULT(ic)),
2996                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2997                2);
2998
2999     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
3000         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
3001         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3002         aopPut(AOP(IC_RESULT(ic)),
3003                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3004                2);
3005     
3006     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3007         AOP_SIZE(IC_LEFT(ic)) < 3    &&
3008         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
3009         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3010         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3011         char buffer[5];
3012         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3013         aopPut(AOP(IC_RESULT(ic)),buffer,2);
3014     }
3015 }
3016 //#else
3017 /* This is the pure and virtuous version of this code.
3018  * I'm pretty certain it's right, but not enough to toss the old 
3019  * code just yet...
3020  */
3021 static void adjustArithmeticResult(iCode *ic)
3022 {
3023     if (opIsGptr(IC_RESULT(ic)) &&
3024         opIsGptr(IC_LEFT(ic))   &&
3025         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3026     {
3027         aopPut(AOP(IC_RESULT(ic)),
3028                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3029                GPTRSIZE - 1);
3030     }
3031
3032     if (opIsGptr(IC_RESULT(ic)) &&
3033         opIsGptr(IC_RIGHT(ic))   &&
3034         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3035     {
3036         aopPut(AOP(IC_RESULT(ic)),
3037                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3038                GPTRSIZE - 1);
3039     }
3040
3041     if (opIsGptr(IC_RESULT(ic))            &&
3042         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
3043         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
3044          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3045          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3046          char buffer[5];
3047          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3048          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3049      }
3050 }
3051 #endif
3052
3053 /*-----------------------------------------------------------------*/
3054 /* genPlus - generates code for addition                           */
3055 /*-----------------------------------------------------------------*/
3056 static void genPlus (iCode *ic)
3057 {
3058     int size, offset = 0;
3059
3060     /* special cases :- */
3061     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3062
3063     aopOp (IC_LEFT(ic),ic,FALSE);
3064     aopOp (IC_RIGHT(ic),ic,FALSE);
3065     aopOp (IC_RESULT(ic),ic,TRUE);
3066
3067     /* if literal, literal on the right or
3068        if left requires ACC or right is already
3069        in ACC */
3070
3071     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3072         operand *t = IC_RIGHT(ic);
3073         IC_RIGHT(ic) = IC_LEFT(ic);
3074         IC_LEFT(ic) = t;
3075     }
3076
3077     /* if both left & right are in bit space */
3078     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3079         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3080         genPlusBits (ic);
3081         goto release ;
3082     }
3083
3084     /* if left in bit space & right literal */
3085     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3086         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3087         /* if result in bit space */
3088         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3089           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3090             emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3091             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3092               emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3093             emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3094           }
3095         } else {
3096             size = getDataSize(IC_RESULT(ic));
3097             while (size--) {
3098                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
3099                 emitcode("addc","a,#00  ;%d",__LINE__);
3100                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3101             }
3102         }
3103         goto release ;
3104     }
3105
3106     /* if I can do an increment instead
3107     of add then GOOD for ME */
3108     if (genPlusIncr (ic) == TRUE)
3109         goto release;   
3110
3111     size = getDataSize(IC_RESULT(ic));
3112
3113     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3114       /* Add a literal to something else */
3115       bool know_W=0;
3116       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3117       unsigned l1=0;
3118
3119       offset = 0;
3120       DEBUGemitcode(";","adding lit to something. size %d",size);
3121       while(size--){
3122
3123       DEBUGemitcode(";","size %d",size);
3124
3125         switch (lit & 0xff) {
3126         case 0:
3127           break;
3128         case 1:
3129           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3130             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3131           else {
3132             know_W = 0;
3133             emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3134             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3135               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3136           }
3137           break;
3138         case 0xff:
3139           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3140             emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3141           else {
3142             know_W = 0;
3143             emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3144             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3145               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3146           }
3147           break;
3148         default:
3149           if( !know_W || ( (lit&0xff) != l1)  ) {
3150             know_W = 1;
3151             emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3152           }
3153           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3154             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3155           else {
3156             know_W = 0;
3157             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3158             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3159             if(size) {
3160               emitSKPNC;
3161               emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3162             }
3163           }
3164         }
3165
3166         l1 = lit & 0xff;
3167         lit >>= 8;
3168         offset++;
3169       }
3170
3171     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3172
3173       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3174       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3175       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3176
3177       /* here we are adding a bit to a char or int */
3178       if(size == 1) {
3179         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3180
3181           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3182           emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3183
3184           emitcode("btfsc","(%s >> 3), (%s & 7)",
3185                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3186                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3187           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3188         } else {
3189
3190           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3191             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3192             emitpcode(POC_XORLW , popGetLit(1));
3193
3194             emitcode("btfsc","(%s >> 3), (%s & 7)",
3195                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3196                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3197             emitcode(" xorlw","1");
3198           } else {
3199             emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3200             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3201             emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3202
3203             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3204             emitcode("btfsc","(%s >> 3), (%s & 7)",
3205                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3206                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3207             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3208           }
3209           
3210           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3211             
3212             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3213               emitpcode(POC_ANDLW , popGetLit(1));
3214               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3215               emitSKPZ;
3216               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3217 /*
3218               emitcode("andlw","1");
3219               emitcode("bcf","(%s >> 3), (%s & 7)",
3220                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3221                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3222               emitSKPZ;
3223               emitcode("bsf","(%s >> 3), (%s & 7)",
3224                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3225                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3226 */
3227
3228             } else {
3229               emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3230               emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3231             }
3232           }
3233         }
3234
3235       } else {
3236         int offset = 1;
3237
3238         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3239           emitCLRZ;
3240           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3241           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3242
3243           emitcode("clrz","");
3244
3245           emitcode("btfsc","(%s >> 3), (%s & 7)",
3246                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3247                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3248           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3249
3250         } else {
3251
3252           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3253           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3254           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3255           emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3256
3257
3258           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3259           emitcode("btfsc","(%s >> 3), (%s & 7)",
3260                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3261                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3262           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3263           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3264
3265         }
3266
3267         while(--size){
3268           emitSKPZ;
3269           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3270       //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3271         }
3272
3273       }
3274       
3275     } else {
3276     
3277       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3278         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3279         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3280       } else {
3281
3282         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3283           emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3284           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3285             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3286         } else {
3287
3288           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3289
3290           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3291             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3292           else {
3293             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3294                 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3295               emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3296             } else {
3297               emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3298               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3299                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3300             }
3301           }
3302         }
3303       }
3304
3305       offset = 1;
3306       size--;
3307
3308       while(size--){
3309         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3310           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3311           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3312
3313           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3314           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3315         }
3316
3317         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3318         emitSKPNC;
3319         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3320         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3321
3322         /*
3323         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3324         emitSKPNC;
3325         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3326         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3327         */
3328
3329         offset++;
3330       }
3331
3332     }
3333
3334     //adjustArithmeticResult(ic);
3335
3336  release:
3337       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3339       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3340 }
3341
3342 /*-----------------------------------------------------------------*/
3343 /* genMinusDec :- does subtraction with decrement if possible     */
3344 /*-----------------------------------------------------------------*/
3345 static bool genMinusDec (iCode *ic)
3346 {
3347     unsigned int icount ;
3348     unsigned int size = getDataSize(IC_RESULT(ic));
3349
3350     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3351     /* will try to generate an increment */
3352     /* if the right side is not a literal 
3353     we cannot */
3354     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3355         return FALSE ;
3356
3357     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3358
3359     /* if the literal value of the right hand side
3360     is greater than 4 then it is not worth it */
3361     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3362         return FALSE ;
3363
3364     /* if decrement 16 bits in register */
3365     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3366         (size > 1) &&
3367         (icount == 1)) {
3368
3369       if(size == 2) { 
3370         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3371         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3372         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3373       } else {
3374         /* size is 3 or 4 */
3375         emitcode("movlw","0xff");
3376         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3377
3378         emitSKPNC;
3379         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3380         emitSKPNC;
3381         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3382
3383         if(size > 3) {
3384           emitcode("skpnc","");
3385           emitSKPNC;
3386           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3387         }
3388
3389       }
3390
3391       return TRUE;
3392
3393     }
3394
3395     /* if the sizes are greater than 1 then we cannot */
3396     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3397         AOP_SIZE(IC_LEFT(ic)) > 1   )
3398         return FALSE ;
3399
3400     /* we can if the aops of the left & result match or
3401     if they are in registers and the registers are the
3402     same */
3403     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3404
3405       while (icount--) 
3406         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3407
3408         //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3409
3410         return TRUE ;
3411     }
3412
3413     DEBUGemitcode ("; returning"," result=%s, left=%s",
3414                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3415                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3416     if(size==1) {
3417       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3418       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3419       return TRUE;
3420     }
3421
3422     return FALSE ;
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* addSign - complete with sign                                    */
3427 /*-----------------------------------------------------------------*/
3428 static void addSign(operand *result, int offset, int sign)
3429 {
3430     int size = (getDataSize(result) - offset);
3431     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3432     if(size > 0){
3433         if(sign){
3434             emitcode("rlc","a");
3435             emitcode("subb","a,acc");
3436             while(size--)
3437                 aopPut(AOP(result),"a",offset++); 
3438         } else
3439             while(size--)
3440                 aopPut(AOP(result),zero,offset++);
3441     }
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* genMinusBits - generates code for subtraction  of two bits      */
3446 /*-----------------------------------------------------------------*/
3447 static void genMinusBits (iCode *ic)
3448 {
3449     symbol *lbl = newiTempLabel(NULL);
3450     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3451     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3452         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3453         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3454         emitcode("cpl","c");
3455         emitcode("","%05d_DS_:",(lbl->key+100));
3456         outBitC(IC_RESULT(ic));
3457     }
3458     else{
3459         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3460         emitcode("subb","a,acc");
3461         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3462         emitcode("inc","a");
3463         emitcode("","%05d_DS_:",(lbl->key+100));
3464         aopPut(AOP(IC_RESULT(ic)),"a",0);
3465         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3466     }
3467 }
3468
3469 /*-----------------------------------------------------------------*/
3470 /* genMinus - generates code for subtraction                       */
3471 /*-----------------------------------------------------------------*/
3472 static void genMinus (iCode *ic)
3473 {
3474     int size, offset = 0;
3475     unsigned long lit = 0L;
3476
3477     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3478     aopOp (IC_LEFT(ic),ic,FALSE);
3479     aopOp (IC_RIGHT(ic),ic,FALSE);
3480     aopOp (IC_RESULT(ic),ic,TRUE);
3481
3482     /* special cases :- */
3483     /* if both left & right are in bit space */
3484     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3485         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3486         genMinusBits (ic);
3487         goto release ;
3488     }
3489
3490     /* if I can do an decrement instead
3491     of subtract then GOOD for ME */
3492     if (genMinusDec (ic) == TRUE)
3493         goto release;   
3494
3495     size = getDataSize(IC_RESULT(ic));   
3496
3497     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3498       /* Add a literal to something else */
3499
3500       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3501       lit = - (long)lit;
3502
3503       /* add the first byte: */
3504       emitcode("movlw","0x%x", lit & 0xff);
3505       emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3506
3507       offset = 1;
3508       size--;
3509
3510       while(size--){
3511
3512         emitcode("rlf","_known_zero,w");
3513         emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3514
3515         lit >>= 8;
3516         if(lit & 0xff) {
3517           emitcode("movlw","0x%x", lit & 0xff);
3518           emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3519           
3520         }
3521         offset++;
3522       }
3523
3524     } else {
3525
3526       emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3527       emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3528
3529       offset = 1;
3530       size--;
3531
3532       while(size--){
3533         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3534         emitSKPNC;
3535         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3536         emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3537         
3538       }
3539
3540     }
3541
3542
3543     //    adjustArithmeticResult(ic);
3544         
3545 release:
3546     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3549 }
3550
3551
3552 /*-----------------------------------------------------------------*/
3553 /* genMultbits :- multiplication of bits                           */
3554 /*-----------------------------------------------------------------*/
3555 static void genMultbits (operand *left, 
3556                          operand *right, 
3557                          operand *result)
3558 {
3559     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3560
3561     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3562     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3563     outBitC(result);
3564 }
3565
3566
3567 /*-----------------------------------------------------------------*/
3568 /* genMultOneByte : 8 bit multiplication & division                */
3569 /*-----------------------------------------------------------------*/
3570 static void genMultOneByte (operand *left,
3571                             operand *right,
3572                             operand *result)
3573 {
3574     sym_link *opetype = operandType(result);
3575     char *l ;
3576     symbol *lbl ;
3577     int size,offset;
3578
3579     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3580     /* (if two literals, the value is computed before) */
3581     /* if one literal, literal on the right */
3582     if (AOP_TYPE(left) == AOP_LIT){
3583         operand *t = right;
3584         right = left;
3585         left = t;
3586     }
3587
3588     size = AOP_SIZE(result);
3589     /* signed or unsigned */
3590     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3591     l = aopGet(AOP(left),0,FALSE,FALSE);
3592     MOVA(l);       
3593     emitcode("mul","ab");
3594     /* if result size = 1, mul signed = mul unsigned */
3595     aopPut(AOP(result),"a",0);
3596     if (size > 1){
3597         if (SPEC_USIGN(opetype)){
3598             aopPut(AOP(result),"b",1);
3599             if (size > 2)
3600                 /* for filling the MSBs */
3601                 emitcode("clr","a");
3602         }
3603         else{
3604             emitcode("mov","a,b");
3605
3606             /* adjust the MSB if left or right neg */
3607
3608             /* if one literal */
3609             if (AOP_TYPE(right) == AOP_LIT){
3610                 /* AND literal negative */
3611                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3612                     /* adjust MSB (c==0 after mul) */
3613                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3614                 }
3615             }
3616             else{
3617                 lbl = newiTempLabel(NULL);
3618                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3619                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3620                 emitcode("","%05d_DS_:",(lbl->key+100));
3621                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3622                 lbl = newiTempLabel(NULL);      
3623                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3624                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3625                 emitcode("","%05d_DS_:",(lbl->key+100));
3626             }
3627
3628             lbl = newiTempLabel(NULL);
3629             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3630             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3631             emitcode("","%05d_DS_:",(lbl->key+100));
3632             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3633             lbl = newiTempLabel(NULL);      
3634             emitcode("jc","%05d_DS_",(lbl->key+100));          
3635             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3636             emitcode("","%05d_DS_:",(lbl->key+100));
3637
3638             aopPut(AOP(result),"a",1);
3639             if(size > 2){
3640                 /* get the sign */
3641                 emitcode("rlc","a");
3642                 emitcode("subb","a,acc");
3643             }
3644         }
3645         size -= 2;   
3646         offset = 2;
3647         if (size > 0)
3648             while (size--)
3649                 aopPut(AOP(result),"a",offset++);
3650     }
3651 }
3652
3653 /*-----------------------------------------------------------------*/
3654 /* genMult - generates code for multiplication                     */
3655 /*-----------------------------------------------------------------*/
3656 static void genMult (iCode *ic)
3657 {
3658     operand *left = IC_LEFT(ic);
3659     operand *right = IC_RIGHT(ic);
3660     operand *result= IC_RESULT(ic);   
3661
3662     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3663     /* assign the amsops */
3664     aopOp (left,ic,FALSE);
3665     aopOp (right,ic,FALSE);
3666     aopOp (result,ic,TRUE);
3667
3668     /* special cases first */
3669     /* both are bits */
3670     if (AOP_TYPE(left) == AOP_CRY &&
3671         AOP_TYPE(right)== AOP_CRY) {
3672         genMultbits(left,right,result);
3673         goto release ;
3674     }
3675
3676     /* if both are of size == 1 */
3677     if (AOP_SIZE(left) == 1 &&
3678         AOP_SIZE(right) == 1 ) {
3679         genMultOneByte(left,right,result);
3680         goto release ;
3681     }
3682
3683     /* should have been converted to function call */       
3684     assert(1) ;
3685
3686 release :
3687     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3689     freeAsmop(result,NULL,ic,TRUE); 
3690 }
3691
3692 /*-----------------------------------------------------------------*/
3693 /* genDivbits :- division of bits                                  */
3694 /*-----------------------------------------------------------------*/
3695 static void genDivbits (operand *left, 
3696                         operand *right, 
3697                         operand *result)
3698 {
3699
3700     char *l;
3701
3702     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3703     /* the result must be bit */    
3704     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3705     l = aopGet(AOP(left),0,FALSE,FALSE);
3706
3707     MOVA(l);    
3708
3709     emitcode("div","ab");
3710     emitcode("rrc","a");
3711     aopPut(AOP(result),"c",0);
3712 }
3713
3714 /*-----------------------------------------------------------------*/
3715 /* genDivOneByte : 8 bit division                                  */
3716 /*-----------------------------------------------------------------*/
3717 static void genDivOneByte (operand *left,
3718                            operand *right,
3719                            operand *result)
3720 {
3721     sym_link *opetype = operandType(result);
3722     char *l ;
3723     symbol *lbl ;
3724     int size,offset;
3725
3726     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3727     size = AOP_SIZE(result) - 1;
3728     offset = 1;
3729     /* signed or unsigned */
3730     if (SPEC_USIGN(opetype)) {
3731         /* unsigned is easy */
3732         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3733         l = aopGet(AOP(left),0,FALSE,FALSE);
3734         MOVA(l);        
3735         emitcode("div","ab");
3736         aopPut(AOP(result),"a",0);
3737         while (size--)
3738             aopPut(AOP(result),zero,offset++);
3739         return ;
3740     }
3741
3742     /* signed is a little bit more difficult */
3743
3744     /* save the signs of the operands */
3745     l = aopGet(AOP(left),0,FALSE,FALSE);    
3746     MOVA(l);    
3747     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3748     emitcode("push","acc"); /* save it on the stack */
3749
3750     /* now sign adjust for both left & right */
3751     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3752     MOVA(l);       
3753     lbl = newiTempLabel(NULL);
3754     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3755     emitcode("cpl","a");   
3756     emitcode("inc","a");
3757     emitcode("","%05d_DS_:",(lbl->key+100));
3758     emitcode("mov","b,a");
3759
3760     /* sign adjust left side */
3761     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3762     MOVA(l);
3763
3764     lbl = newiTempLabel(NULL);
3765     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3766     emitcode("cpl","a");
3767     emitcode("inc","a");
3768     emitcode("","%05d_DS_:",(lbl->key+100));
3769
3770     /* now the division */
3771     emitcode("div","ab");
3772     /* we are interested in the lower order
3773     only */
3774     emitcode("mov","b,a");
3775     lbl = newiTempLabel(NULL);
3776     emitcode("pop","acc");   
3777     /* if there was an over flow we don't 
3778     adjust the sign of the result */
3779     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3780     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3781     CLRC;
3782     emitcode("clr","a");
3783     emitcode("subb","a,b");
3784     emitcode("mov","b,a");
3785     emitcode("","%05d_DS_:",(lbl->key+100));
3786
3787     /* now we are done */
3788     aopPut(AOP(result),"b",0);
3789     if(size > 0){
3790         emitcode("mov","c,b.7");
3791         emitcode("subb","a,acc");   
3792     }
3793     while (size--)
3794         aopPut(AOP(result),"a",offset++);
3795
3796 }
3797
3798 /*-----------------------------------------------------------------*/
3799 /* genDiv - generates code for division                            */
3800 /*-----------------------------------------------------------------*/
3801 static void genDiv (iCode *ic)
3802 {
3803     operand *left = IC_LEFT(ic);
3804     operand *right = IC_RIGHT(ic);
3805     operand *result= IC_RESULT(ic);   
3806
3807     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3808     /* assign the amsops */
3809     aopOp (left,ic,FALSE);
3810     aopOp (right,ic,FALSE);
3811     aopOp (result,ic,TRUE);
3812
3813     /* special cases first */
3814     /* both are bits */
3815     if (AOP_TYPE(left) == AOP_CRY &&
3816         AOP_TYPE(right)== AOP_CRY) {
3817         genDivbits(left,right,result);
3818         goto release ;
3819     }
3820
3821     /* if both are of size == 1 */
3822     if (AOP_SIZE(left) == 1 &&
3823         AOP_SIZE(right) == 1 ) {
3824         genDivOneByte(left,right,result);
3825         goto release ;
3826     }
3827
3828     /* should have been converted to function call */
3829     assert(1);
3830 release :
3831     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3832     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3833     freeAsmop(result,NULL,ic,TRUE); 
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genModbits :- modulus of bits                                   */
3838 /*-----------------------------------------------------------------*/
3839 static void genModbits (operand *left, 
3840                         operand *right, 
3841                         operand *result)
3842 {
3843
3844     char *l;
3845
3846     /* the result must be bit */    
3847     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3848     l = aopGet(AOP(left),0,FALSE,FALSE);
3849
3850     MOVA(l);       
3851
3852     emitcode("div","ab");
3853     emitcode("mov","a,b");
3854     emitcode("rrc","a");
3855     aopPut(AOP(result),"c",0);
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genModOneByte : 8 bit modulus                                   */
3860 /*-----------------------------------------------------------------*/
3861 static void genModOneByte (operand *left,
3862                            operand *right,
3863                            operand *result)
3864 {
3865     sym_link *opetype = operandType(result);
3866     char *l ;
3867     symbol *lbl ;
3868
3869     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3870     /* signed or unsigned */
3871     if (SPEC_USIGN(opetype)) {
3872         /* unsigned is easy */
3873         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3874         l = aopGet(AOP(left),0,FALSE,FALSE);
3875         MOVA(l);    
3876         emitcode("div","ab");
3877         aopPut(AOP(result),"b",0);
3878         return ;
3879     }
3880
3881     /* signed is a little bit more difficult */
3882
3883     /* save the signs of the operands */
3884     l = aopGet(AOP(left),0,FALSE,FALSE);    
3885     MOVA(l);
3886
3887     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3888     emitcode("push","acc"); /* save it on the stack */
3889
3890     /* now sign adjust for both left & right */
3891     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3892     MOVA(l);
3893
3894     lbl = newiTempLabel(NULL);
3895     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3896     emitcode("cpl","a");   
3897     emitcode("inc","a");
3898     emitcode("","%05d_DS_:",(lbl->key+100));
3899     emitcode("mov","b,a"); 
3900
3901     /* sign adjust left side */
3902     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3903     MOVA(l);
3904
3905     lbl = newiTempLabel(NULL);
3906     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3907     emitcode("cpl","a");   
3908     emitcode("inc","a");
3909     emitcode("","%05d_DS_:",(lbl->key+100));
3910
3911     /* now the multiplication */
3912     emitcode("div","ab");
3913     /* we are interested in the lower order
3914     only */
3915     lbl = newiTempLabel(NULL);
3916     emitcode("pop","acc");   
3917     /* if there was an over flow we don't 
3918     adjust the sign of the result */
3919     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3920     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3921     CLRC ;
3922     emitcode("clr","a");
3923     emitcode("subb","a,b");
3924     emitcode("mov","b,a");
3925     emitcode("","%05d_DS_:",(lbl->key+100));
3926
3927     /* now we are done */
3928     aopPut(AOP(result),"b",0);
3929
3930 }
3931
3932 /*-----------------------------------------------------------------*/
3933 /* genMod - generates code for division                            */
3934 /*-----------------------------------------------------------------*/
3935 static void genMod (iCode *ic)
3936 {
3937     operand *left = IC_LEFT(ic);
3938     operand *right = IC_RIGHT(ic);
3939     operand *result= IC_RESULT(ic);  
3940
3941     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3942     /* assign the amsops */
3943     aopOp (left,ic,FALSE);
3944     aopOp (right,ic,FALSE);
3945     aopOp (result,ic,TRUE);
3946
3947     /* special cases first */
3948     /* both are bits */
3949     if (AOP_TYPE(left) == AOP_CRY &&
3950         AOP_TYPE(right)== AOP_CRY) {
3951         genModbits(left,right,result);
3952         goto release ;
3953     }
3954
3955     /* if both are of size == 1 */
3956     if (AOP_SIZE(left) == 1 &&
3957         AOP_SIZE(right) == 1 ) {
3958         genModOneByte(left,right,result);
3959         goto release ;
3960     }
3961
3962     /* should have been converted to function call */
3963     assert(1);
3964
3965 release :
3966     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3967     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3968     freeAsmop(result,NULL,ic,TRUE); 
3969 }
3970
3971 /*-----------------------------------------------------------------*/
3972 /* genIfxJump :- will create a jump depending on the ifx           */
3973 /*-----------------------------------------------------------------*/
3974 static void genIfxJump (iCode *ic, char *jval)
3975 {
3976
3977     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3978     /* if true label then we jump if condition
3979     supplied is true */
3980     if ( IC_TRUE(ic) ) {
3981
3982         if(strcmp(jval,"a") == 0)
3983           emitSKPZ;
3984         else if (strcmp(jval,"c") == 0)
3985           emitSKPC;
3986         else {
3987           //pCodeOp *p = popGetWithString(jval);
3988           //p->type = PO_BIT;
3989           //emitpcode(POC_BTFSC,  p);
3990           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,0));
3991         //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3992         }
3993
3994         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3995         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3996
3997     }
3998     else {
3999         /* false label is present */
4000         if(strcmp(jval,"a") == 0)
4001           emitSKPNZ;
4002         else if (strcmp(jval,"c") == 0)
4003           emitSKPNC;
4004         else {
4005           //pCodeOp *p = popGetWithString(jval);
4006           //p->type = PO_BIT;
4007           //emitpcode(POC_BTFSS,  p);
4008           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,0));
4009
4010         //        emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4011         }
4012
4013         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4014         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4015
4016     }
4017
4018
4019     /* mark the icode as generated */
4020     ic->generated = 1;
4021 }
4022
4023 /*-----------------------------------------------------------------*/
4024 /* genSkip                                                         */
4025 /*-----------------------------------------------------------------*/
4026 static void genSkip(iCode *ifx,int status_bit)
4027 {
4028   if(!ifx)
4029     return;
4030
4031   if ( IC_TRUE(ifx) ) {
4032     switch(status_bit) {
4033     case 'z':
4034       emitSKPNZ;
4035       break;
4036
4037     case 'c':
4038       emitSKPNC;
4039       break;
4040
4041     case 'd':
4042       emitcode("skpndc","");
4043       break;
4044
4045     }
4046
4047     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4048     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4049
4050   } else {
4051
4052     switch(status_bit) {
4053
4054     case 'z':
4055       emitSKPZ;
4056       break;
4057
4058     case 'c':
4059       emitSKPC;
4060       break;
4061
4062     case 'd':
4063       emitcode("skpdc","");
4064       break;
4065     }
4066     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4067     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4068
4069   }
4070
4071 }
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genSkipc                                                        */
4075 /*-----------------------------------------------------------------*/
4076 static void genSkipc(iCode *ifx, int condition)
4077 {
4078   if(!ifx)
4079     return;
4080
4081   if(condition)
4082     emitSKPNC;
4083   else
4084     emitSKPC;
4085
4086   if ( IC_TRUE(ifx) )
4087     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4088   else
4089     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4090
4091   if ( IC_TRUE(ifx) )
4092     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4093   else
4094     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4095
4096 }
4097
4098 /*-----------------------------------------------------------------*/
4099 /* genSkipz                                                        */
4100 /*-----------------------------------------------------------------*/
4101 static void genSkipz(iCode *ifx, int condition)
4102 {
4103   if(!ifx)
4104     return;
4105
4106   if(condition)
4107     emitSKPNZ;
4108   else
4109     emitSKPZ;
4110
4111   if ( IC_TRUE(ifx) )
4112     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4113   else
4114     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4115
4116   if ( IC_TRUE(ifx) )
4117     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4118   else
4119     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4120
4121 }
4122 /*-----------------------------------------------------------------*/
4123 /* genCmp :- greater or less than comparison                       */
4124 /*-----------------------------------------------------------------*/
4125 static void genCmp (operand *left,operand *right,
4126                     operand *result, iCode *ifx, int sign)
4127 {
4128   int size, offset = 0 ;
4129   unsigned long lit = 0L,i = 0;
4130
4131   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4132   /* if left & right are bit variables */
4133   if (AOP_TYPE(left) == AOP_CRY &&
4134       AOP_TYPE(right) == AOP_CRY ) {
4135     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4136     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4137   } else {
4138     /* subtract right from left if at the
4139        end the carry flag is set then we know that
4140        left is greater than right */
4141     size = max(AOP_SIZE(left),AOP_SIZE(right));
4142
4143     /* if unsigned char cmp with lit, do cjne left,#right,zz */
4144     if((size == 1) && !sign &&
4145        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4146       symbol *lbl  = newiTempLabel(NULL);
4147       emitcode("cjne","%s,%s,%05d_DS_",
4148                aopGet(AOP(left),offset,FALSE,FALSE),
4149                aopGet(AOP(right),offset,FALSE,FALSE),
4150                lbl->key+100);
4151       emitcode("","%05d_DS_:",lbl->key+100);
4152     } else {
4153
4154       if(AOP_TYPE(right) == AOP_LIT) {
4155
4156         DEBUGemitcode(";right lit","%d",sign);
4157
4158         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4159         //default:
4160         while(size--) {
4161           i = (lit >> (size*8)) & 0xff;
4162           if(i == 0) {
4163             emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4164             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4165             genSkipz(ifx,IC_TRUE(ifx) == NULL);
4166           } else {
4167             emitpcode(POC_MOVLW, popGetLit(i));
4168             emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4169
4170             emitcode("movlw","0x%x",i);
4171             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4172             genSkipc(ifx,IC_TRUE(ifx) == NULL);
4173           }
4174
4175         }
4176         ifx->generated = 1;
4177         return;
4178       }
4179       if(AOP_TYPE(left) == AOP_LIT) {
4180
4181         DEBUGemitcode(";left lit","%d",sign);
4182
4183         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4184
4185         //default:
4186         while(size--) {
4187           i = (lit >> (size*8)) & 0xff;
4188           if(i == 0) {
4189             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4190             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4191             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4192           } else if( i == 1 ) {
4193             emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4194             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4195             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4196
4197           } else {
4198             emitpcode(POC_MOVLW, popGetLit(i));
4199             emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4200
4201             emitcode("movlw","0x%x",i);
4202             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4203             genSkipc(ifx,IC_TRUE(ifx) != NULL);
4204           }
4205         }
4206         ifx->generated = 1;
4207         return;
4208       }
4209
4210
4211       // CLRC;
4212       DEBUGemitcode(";sign","%d",sign);
4213
4214       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4215       emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4216
4217       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4218       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4219
4220       size--;
4221       while (size--) {
4222
4223         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
4224         emitSKPC;
4225         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4226         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
4227
4228 /*
4229         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4230         emitSKPC;
4231         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4232         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4233 */
4234         offset++;
4235       }
4236     }
4237   }
4238
4239   //release:
4240   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4241     outBitC(result);
4242   } else {
4243     /* if the result is used in the next
4244        ifx conditional branch then generate
4245        code a little differently */
4246     if (ifx )
4247       genIfxJump (ifx,"c");
4248     else
4249       outBitC(result);
4250     /* leave the result in acc */
4251   }
4252
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genCmpGt :- greater than comparison                             */
4257 /*-----------------------------------------------------------------*/
4258 static void genCmpGt (iCode *ic, iCode *ifx)
4259 {
4260     operand *left, *right, *result;
4261     sym_link *letype , *retype;
4262     int sign ;
4263
4264     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4265     left = IC_LEFT(ic);
4266     right= IC_RIGHT(ic);
4267     result = IC_RESULT(ic);
4268
4269     letype = getSpec(operandType(left));
4270     retype =getSpec(operandType(right));
4271     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4272     /* assign the amsops */
4273     aopOp (left,ic,FALSE);
4274     aopOp (right,ic,FALSE);
4275     aopOp (result,ic,TRUE);
4276
4277     genCmp(right, left, result, ifx, sign);
4278
4279     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4280     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4281     freeAsmop(result,NULL,ic,TRUE); 
4282 }
4283
4284 /*-----------------------------------------------------------------*/
4285 /* genCmpLt - less than comparisons                                */
4286 /*-----------------------------------------------------------------*/
4287 static void genCmpLt (iCode *ic, iCode *ifx)
4288 {
4289     operand *left, *right, *result;
4290     sym_link *letype , *retype;
4291     int sign ;
4292
4293     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4294     left = IC_LEFT(ic);
4295     right= IC_RIGHT(ic);
4296     result = IC_RESULT(ic);
4297
4298     letype = getSpec(operandType(left));
4299     retype =getSpec(operandType(right));
4300     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4301
4302     /* assign the amsops */
4303     aopOp (left,ic,FALSE);
4304     aopOp (right,ic,FALSE);
4305     aopOp (result,ic,TRUE);
4306
4307     genCmp(left, right, result, ifx, sign);
4308
4309     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4310     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4311     freeAsmop(result,NULL,ic,TRUE); 
4312 }
4313
4314 /*-----------------------------------------------------------------*/
4315 /* gencjneshort - compare and jump if not equal                    */
4316 /*-----------------------------------------------------------------*/
4317 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4318 {
4319     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4320     int offset = 0;
4321     unsigned long lit = 0L;
4322
4323     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4324     /* if the left side is a literal or 
4325     if the right is in a pointer register and left 
4326     is not */
4327     if ((AOP_TYPE(left) == AOP_LIT) || 
4328         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4329         operand *t = right;
4330         right = left;
4331         left = t;
4332     }
4333     if(AOP_TYPE(right) == AOP_LIT)
4334         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4335
4336     /* if the right side is a literal then anything goes */
4337     if (AOP_TYPE(right) == AOP_LIT &&
4338         AOP_TYPE(left) != AOP_DIR ) {
4339         while (size--) {
4340           if(lit & 0xff) {
4341             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4342             emitcode("xorlw","0x%x",lit & 0xff);
4343           } else
4344             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4345
4346           emitSKPNZ;
4347           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4348           offset++;
4349           lit >>= 8;
4350         }
4351     }
4352
4353     /* if the right side is in a register or in direct space or
4354     if the left is a pointer register & right is not */    
4355     else if (AOP_TYPE(right) == AOP_REG ||
4356              AOP_TYPE(right) == AOP_DIR || 
4357              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4358              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4359         while (size--) {
4360           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4361              ( (lit & 0xff) != 0)) {
4362             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4363             emitcode("xorlw","0x%x",lit & 0xff);
4364             lit >>= 8;
4365           } else
4366             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4367
4368           emitSKPZ;
4369           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4370           offset++;
4371 /*
4372             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4373             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4374                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4375                 emitcode("jnz","%05d_DS_",lbl->key+100);
4376             else
4377                 emitcode("cjne","a,%s,%05d_DS_",
4378                          aopGet(AOP(right),offset,FALSE,TRUE),
4379                          lbl->key+100);
4380             offset++;
4381 */
4382         }
4383     } else {
4384         /* right is a pointer reg need both a & b */
4385         while(size--) {
4386             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4387             if(strcmp(l,"b"))
4388                 emitcode("mov","b,%s",l);
4389             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4390             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4391             offset++;
4392         }
4393     }
4394 }
4395
4396 /*-----------------------------------------------------------------*/
4397 /* gencjne - compare and jump if not equal                         */
4398 /*-----------------------------------------------------------------*/
4399 static void gencjne(operand *left, operand *right, symbol *lbl)
4400 {
4401     symbol *tlbl  = newiTempLabel(NULL);
4402
4403     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4404     gencjneshort(left, right, lbl);
4405
4406     emitcode("mov","a,%s",one);
4407     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4408     emitcode("","%05d_DS_:",lbl->key+100);
4409     emitcode("clr","a");
4410     emitcode("","%05d_DS_:",tlbl->key+100);
4411 }
4412
4413
4414 /*-----------------------------------------------------------------*/
4415 /* genCmpEq - generates code for equal to                          */
4416 /*-----------------------------------------------------------------*/
4417 static void genCmpEq (iCode *ic, iCode *ifx)
4418 {
4419     operand *left, *right, *result;
4420     unsigned long lit = 0L;
4421     int size,offset=0;
4422
4423     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4424     if(ifx)
4425       DEBUGemitcode ("; ifx is non-null","");
4426     else
4427       DEBUGemitcode ("; ifx is null","");
4428
4429     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4430     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4431     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4432
4433     size = max(AOP_SIZE(left),AOP_SIZE(right));
4434
4435     /* if literal, literal on the right or 
4436     if the right is in a pointer register and left 
4437     is not */
4438     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4439         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4440         operand *t = IC_RIGHT(ic);
4441         IC_RIGHT(ic) = IC_LEFT(ic);
4442         IC_LEFT(ic) = t;
4443     }
4444
4445     if(ifx && !AOP_SIZE(result)){
4446         symbol *tlbl;
4447         /* if they are both bit variables */
4448         if (AOP_TYPE(left) == AOP_CRY &&
4449             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4450             if(AOP_TYPE(right) == AOP_LIT){
4451                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4452                 if(lit == 0L){
4453                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4454                     emitcode("cpl","c");
4455                 } else if(lit == 1L) {
4456                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4457                 } else {
4458                     emitcode("clr","c");
4459                 }
4460                 /* AOP_TYPE(right) == AOP_CRY */
4461             } else {
4462                 symbol *lbl = newiTempLabel(NULL);
4463                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4464                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4465                 emitcode("cpl","c");
4466                 emitcode("","%05d_DS_:",(lbl->key+100));
4467             }
4468             /* if true label then we jump if condition
4469             supplied is true */
4470             tlbl = newiTempLabel(NULL);
4471             if ( IC_TRUE(ifx) ) {
4472                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4473                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4474             } else {
4475                 emitcode("jc","%05d_DS_",tlbl->key+100);
4476                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4477             }
4478             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4479         } else {
4480
4481           /* They're not both bit variables. Is the right a literal? */
4482           if(AOP_TYPE(right) == AOP_LIT) {
4483
4484             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4485             while (size--) {
4486
4487               if(size >= 1) {
4488                 int l = lit & 0xff;
4489                 int h = (lit>>8) & 0xff;
4490                 int optimized=0;
4491
4492                 /* Check special cases for integers */
4493                 switch(lit & 0xffff) {
4494                 case 0x0000:
4495                   emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4496                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4497                   //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4498                   //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4499                   genSkip(ifx,'z');
4500                   optimized++;
4501                   break;
4502                 case 0x0001:
4503                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4504                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4505                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4506                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4507                   genSkip(ifx,'z');
4508                   optimized++;
4509                   break;
4510                 case 0x0100:
4511                   emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4512                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4513                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4514                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4515                   genSkip(ifx,'z');
4516                   optimized++;
4517                   break;
4518                 case 0x00ff:
4519                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4520                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4521                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4522                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4523                   genSkip(ifx,'z');
4524                   optimized++;
4525                   break;
4526                 case 0xff00:
4527                   emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4528                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4529                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4530                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4531                   genSkip(ifx,'z');
4532                   optimized++;
4533                   break;
4534                 default:
4535                   if(h == 0) {
4536                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4537                     emitpcode(POC_XORLW,popGetLit(l));
4538                     emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4539
4540                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4541                     emitcode("xorlw","0x%x",l);
4542                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4543                     optimized++;
4544                     genSkip(ifx,'z');
4545                   } else if (l == 0) {
4546                     emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4547                     emitpcode(POC_XORLW,popGetLit(h));
4548                     emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4549
4550                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4551                     emitcode("xorlw","0x%x",h);
4552                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4553                     optimized++;
4554                     genSkip(ifx,'z');
4555                   } else {
4556                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4557                     emitpcode(POC_XORLW,popGetLit(l));
4558                     emitpcode(POC_MOVLW,popGetLit(h));
4559                     emitSKPZ;
4560                     emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4561 /*
4562                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4563                     emitcode("xorlw","0x%x",l);
4564                     emitcode("movlw","0x%x",h);
4565                     emitSKPZ;
4566                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4567 */
4568                     optimized++;
4569                     genSkip(ifx,'z');
4570                   }
4571
4572                 }
4573                 if(optimized) {
4574                   size--;
4575                   offset+=2;
4576                   lit>>=16;
4577
4578                   continue;
4579                 }
4580                   
4581               }
4582                 
4583               switch(lit & 0xff) {
4584               case 1:
4585                 if ( IC_TRUE(ifx) ) {
4586
4587                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4588
4589                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4590                   emitSKPNZ;
4591                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4592
4593                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4594                 } else {
4595                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4596                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4597
4598                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4599                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4600                 }
4601                 break;
4602               case 0xff:
4603                 if ( IC_TRUE(ifx) ) {
4604                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4605
4606                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4607                   emitSKPNZ;
4608                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4609
4610                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4611                 } else {
4612                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4613                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4614
4615                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4616                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4617                 }
4618                 break;
4619               default:
4620                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4621                 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4622                 if(lit)
4623                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4624                 //emitcode("xorlw","0x%x",lit & 0xff);
4625                 genSkip(ifx,'z');
4626               }
4627
4628
4629               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4630               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4631               offset++;
4632               lit >>= 8;
4633             }
4634
4635           } else if(AOP_TYPE(right) == AOP_CRY ) {
4636             /* we know the left is not a bit, but that the right is */
4637             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4638             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4639                       popGet(AOP(right),offset,FALSE,FALSE));
4640             emitpcode(POC_XORLW,popGetLit(1));
4641
4642             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4643             if ( IC_TRUE(ifx) )
4644               emitcode("btfsc","(%s >> 3), (%s & 7)",
4645                        AOP(right)->aopu.aop_dir,
4646                        AOP(right)->aopu.aop_dir);
4647             else
4648               emitcode("btfss","(%s >> 3), (%s & 7)",
4649                        AOP(right)->aopu.aop_dir,
4650                        AOP(right)->aopu.aop_dir);
4651
4652             emitcode("xorlw","1");
4653
4654             /* if the two are equal, then W will be 0 and the Z bit is set
4655              * we could test Z now, or go ahead and check the high order bytes if
4656              * the variable we're comparing is larger than a byte. */
4657
4658             while(--size)
4659               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4660             //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4661
4662             if ( IC_TRUE(ifx) ) {
4663               emitSKPNZ;
4664               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4665               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4666             } else {
4667               emitSKPZ;
4668               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4669               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4670             }
4671
4672           } else {
4673             /* They're both variables that are larger than bits */
4674             int s = size;
4675
4676             tlbl = newiTempLabel(NULL);
4677
4678             while(size--) {
4679               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4680               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4681
4682               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4683               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4684
4685               if ( IC_TRUE(ifx) ) {
4686                 if(size) {
4687                   emitSKPZ;
4688                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4689                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4690                 } else {
4691                   emitSKPNZ;
4692                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4693                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4694                 }
4695               } else {
4696                 emitSKPZ;
4697                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4698                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4699               }
4700               offset++;
4701             }
4702             if(s>1 && IC_TRUE(ifx)) {
4703               emitpLabel(tlbl->key+100+labelOffset);
4704               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4705             }
4706           }
4707         }
4708         /* mark the icode as generated */
4709         ifx->generated = 1;
4710         goto release ;
4711     }
4712
4713     /* if they are both bit variables */
4714     if (AOP_TYPE(left) == AOP_CRY &&
4715         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4716         if(AOP_TYPE(right) == AOP_LIT){
4717             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4718             if(lit == 0L){
4719                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4720                 emitcode("cpl","c");
4721             } else if(lit == 1L) {
4722                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4723             } else {
4724                 emitcode("clr","c");
4725             }
4726             /* AOP_TYPE(right) == AOP_CRY */
4727         } else {
4728             symbol *lbl = newiTempLabel(NULL);
4729             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4730             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4731             emitcode("cpl","c");
4732             emitcode("","%05d_DS_:",(lbl->key+100));
4733         }
4734         /* c = 1 if egal */
4735         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4736             outBitC(result);
4737             goto release ;
4738         }
4739         if (ifx) {
4740             genIfxJump (ifx,"c");
4741             goto release ;
4742         }
4743         /* if the result is used in an arithmetic operation
4744         then put the result in place */
4745         outBitC(result);
4746     } else {
4747         gencjne(left,right,newiTempLabel(NULL));    
4748         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4749             aopPut(AOP(result),"a",0);
4750             goto release ;
4751         }
4752         if (ifx) {
4753             genIfxJump (ifx,"a");
4754             goto release ;
4755         }
4756         /* if the result is used in an arithmetic operation
4757         then put the result in place */
4758         if (AOP_TYPE(result) != AOP_CRY) 
4759             outAcc(result);
4760         /* leave the result in acc */
4761     }
4762
4763 release:
4764     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4765     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4766     freeAsmop(result,NULL,ic,TRUE);
4767 }
4768
4769 /*-----------------------------------------------------------------*/
4770 /* ifxForOp - returns the icode containing the ifx for operand     */
4771 /*-----------------------------------------------------------------*/
4772 static iCode *ifxForOp ( operand *op, iCode *ic )
4773 {
4774     /* if true symbol then needs to be assigned */
4775     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4776     if (IS_TRUE_SYMOP(op))
4777         return NULL ;
4778
4779     /* if this has register type condition and
4780     the next instruction is ifx with the same operand
4781     and live to of the operand is upto the ifx only then */
4782     if (ic->next &&
4783         ic->next->op == IFX &&
4784         IC_COND(ic->next)->key == op->key &&
4785         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4786         return ic->next;
4787
4788     return NULL;
4789 }
4790 /*-----------------------------------------------------------------*/
4791 /* genAndOp - for && operation                                     */
4792 /*-----------------------------------------------------------------*/
4793 static void genAndOp (iCode *ic)
4794 {
4795     operand *left,*right, *result;
4796     symbol *tlbl;
4797
4798     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4799     /* note here that && operations that are in an
4800     if statement are taken away by backPatchLabels
4801     only those used in arthmetic operations remain */
4802     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4803     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4804     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4805
4806     /* if both are bit variables */
4807     if (AOP_TYPE(left) == AOP_CRY &&
4808         AOP_TYPE(right) == AOP_CRY ) {
4809         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4810         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4811         outBitC(result);
4812     } else {
4813         tlbl = newiTempLabel(NULL);
4814         toBoolean(left);    
4815         emitcode("jz","%05d_DS_",tlbl->key+100);
4816         toBoolean(right);
4817         emitcode("","%05d_DS_:",tlbl->key+100);
4818         outBitAcc(result);
4819     }
4820
4821     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4822     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4823     freeAsmop(result,NULL,ic,TRUE);
4824 }
4825
4826
4827 /*-----------------------------------------------------------------*/
4828 /* genOrOp - for || operation                                      */
4829 /*-----------------------------------------------------------------*/
4830 /*
4831   tsd pic port -
4832   modified this code, but it doesn't appear to ever get called
4833 */
4834
4835 static void genOrOp (iCode *ic)
4836 {
4837     operand *left,*right, *result;
4838     symbol *tlbl;
4839
4840     /* note here that || operations that are in an
4841     if statement are taken away by backPatchLabels
4842     only those used in arthmetic operations remain */
4843     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4844     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4845     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4846     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4847
4848     /* if both are bit variables */
4849     if (AOP_TYPE(left) == AOP_CRY &&
4850         AOP_TYPE(right) == AOP_CRY ) {
4851       emitcode("clrc","");
4852       emitcode("btfss","(%s >> 3), (%s & 7)",
4853                AOP(left)->aopu.aop_dir,
4854                AOP(left)->aopu.aop_dir);
4855       emitcode("btfsc","(%s >> 3), (%s & 7)",
4856                AOP(right)->aopu.aop_dir,
4857                AOP(right)->aopu.aop_dir);
4858       emitcode("setc","");
4859
4860     } else {
4861         tlbl = newiTempLabel(NULL);
4862         toBoolean(left);
4863         emitSKPZ;
4864         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4865         toBoolean(right);
4866         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4867
4868         outBitAcc(result);
4869     }
4870
4871     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4872     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873     freeAsmop(result,NULL,ic,TRUE);            
4874 }
4875
4876 /*-----------------------------------------------------------------*/
4877 /* isLiteralBit - test if lit == 2^n                               */
4878 /*-----------------------------------------------------------------*/
4879 static int isLiteralBit(unsigned long lit)
4880 {
4881     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4882     0x100L,0x200L,0x400L,0x800L,
4883     0x1000L,0x2000L,0x4000L,0x8000L,
4884     0x10000L,0x20000L,0x40000L,0x80000L,
4885     0x100000L,0x200000L,0x400000L,0x800000L,
4886     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4887     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4888     int idx;
4889     
4890     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4891     for(idx = 0; idx < 32; idx++)
4892         if(lit == pw[idx])
4893             return idx+1;
4894     return 0;
4895 }
4896
4897 /*-----------------------------------------------------------------*/
4898 /* continueIfTrue -                                                */
4899 /*-----------------------------------------------------------------*/
4900 static void continueIfTrue (iCode *ic)
4901 {
4902     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4903     if(IC_TRUE(ic))
4904         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4905     ic->generated = 1;
4906 }
4907
4908 /*-----------------------------------------------------------------*/
4909 /* jmpIfTrue -                                                     */
4910 /*-----------------------------------------------------------------*/
4911 static void jumpIfTrue (iCode *ic)
4912 {
4913     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4914     if(!IC_TRUE(ic))
4915         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4916     ic->generated = 1;
4917 }
4918
4919 /*-----------------------------------------------------------------*/
4920 /* jmpTrueOrFalse -                                                */
4921 /*-----------------------------------------------------------------*/
4922 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4923 {
4924     // ugly but optimized by peephole
4925     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4926     if(IC_TRUE(ic)){
4927         symbol *nlbl = newiTempLabel(NULL);
4928         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4929         emitcode("","%05d_DS_:",tlbl->key+100);
4930         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4931         emitcode("","%05d_DS_:",nlbl->key+100);
4932     }
4933     else{
4934         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4935         emitcode("","%05d_DS_:",tlbl->key+100);
4936     }
4937     ic->generated = 1;
4938 }
4939
4940 /*-----------------------------------------------------------------*/
4941 /* genAnd  - code for and                                          */
4942 /*-----------------------------------------------------------------*/
4943 static void genAnd (iCode *ic, iCode *ifx)
4944 {
4945     operand *left, *right, *result;
4946     int size, offset=0;  
4947     unsigned long lit = 0L;
4948     int bytelit = 0;
4949     char buffer[10];
4950
4951     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4952     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4953     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4954     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4955
4956 #ifdef DEBUG_TYPE
4957     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4958              AOP_TYPE(result),
4959              AOP_TYPE(left), AOP_TYPE(right));
4960     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4961              AOP_SIZE(result),
4962              AOP_SIZE(left), AOP_SIZE(right));
4963 #endif
4964
4965     /* if left is a literal & right is not then exchange them */
4966     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4967         AOP_NEEDSACC(left)) {
4968         operand *tmp = right ;
4969         right = left;
4970         left = tmp;
4971     }
4972
4973     /* if result = right then exchange them */
4974     if(sameRegs(AOP(result),AOP(right))){
4975         operand *tmp = right ;
4976         right = left;
4977         left = tmp;
4978     }
4979
4980     /* if right is bit then exchange them */
4981     if (AOP_TYPE(right) == AOP_CRY &&
4982         AOP_TYPE(left) != AOP_CRY){
4983         operand *tmp = right ;
4984         right = left;
4985         left = tmp;
4986     }
4987     if(AOP_TYPE(right) == AOP_LIT)
4988         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4989
4990     size = AOP_SIZE(result);
4991
4992     // if(bit & yy)
4993     // result = bit & yy;
4994     if (AOP_TYPE(left) == AOP_CRY){
4995         // c = bit & literal;
4996         if(AOP_TYPE(right) == AOP_LIT){
4997             if(lit & 1) {
4998                 if(size && sameRegs(AOP(result),AOP(left)))
4999                     // no change
5000                     goto release;
5001                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5002             } else {
5003                 // bit(result) = 0;
5004                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5005                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5006                     goto release;
5007                 }
5008                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5009                     jumpIfTrue(ifx);
5010                     goto release;
5011                 }
5012                 emitcode("clr","c");
5013             }
5014         } else {
5015             if (AOP_TYPE(right) == AOP_CRY){
5016                 // c = bit & bit;
5017                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5018                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5019             } else {
5020                 // c = bit & val;
5021                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5022                 // c = lsb
5023                 emitcode("rrc","a");
5024                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5025             }
5026         }
5027         // bit = c
5028         // val = c
5029         if(size)
5030             outBitC(result);
5031         // if(bit & ...)
5032         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5033             genIfxJump(ifx, "c");           
5034         goto release ;
5035     }
5036
5037     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5038     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5039     if((AOP_TYPE(right) == AOP_LIT) &&
5040        (AOP_TYPE(result) == AOP_CRY) &&
5041        (AOP_TYPE(left) != AOP_CRY)){
5042         int posbit = isLiteralBit(lit);
5043         /* left &  2^n */
5044         if(posbit){
5045             posbit--;
5046             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5047             // bit = left & 2^n
5048             if(size)
5049                 emitcode("mov","c,acc.%d",posbit&0x07);
5050             // if(left &  2^n)
5051             else{
5052                 if(ifx){
5053                     sprintf(buffer,"acc.%d",posbit&0x07);
5054                     genIfxJump(ifx, buffer);
5055                 }
5056                 goto release;
5057             }
5058         } else {
5059             symbol *tlbl = newiTempLabel(NULL);
5060             int sizel = AOP_SIZE(left);
5061             if(size)
5062                 emitcode("setb","c");
5063             while(sizel--){
5064                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5065                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5066                     // byte ==  2^n ?
5067                     if((posbit = isLiteralBit(bytelit)) != 0)
5068                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5069                     else{
5070                         if(bytelit != 0x0FFL)
5071                             emitcode("anl","a,%s",
5072                                      aopGet(AOP(right),offset,FALSE,TRUE));
5073                         emitcode("jnz","%05d_DS_",tlbl->key+100);
5074                     }
5075                 }
5076                 offset++;
5077             }
5078             // bit = left & literal
5079             if(size){
5080                 emitcode("clr","c");
5081                 emitcode("","%05d_DS_:",tlbl->key+100);
5082             }
5083             // if(left & literal)
5084             else{
5085                 if(ifx)
5086                     jmpTrueOrFalse(ifx, tlbl);
5087                 goto release ;
5088             }
5089         }
5090         outBitC(result);
5091         goto release ;
5092     }
5093
5094     /* if left is same as result */
5095     if(sameRegs(AOP(result),AOP(left))){
5096       for(;size--; offset++,lit>>=8) {
5097         if(AOP_TYPE(right) == AOP_LIT){
5098           switch(lit & 0xff) {
5099           case 0x00:
5100             /*  and'ing with 0 has clears the result */
5101             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5102             break;
5103           case 0xff:
5104             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5105             break;
5106
5107           default:
5108             {
5109               int p = my_powof2( (~lit) & 0xff );
5110               if(p>=0) {
5111                 /* only one bit is set in the literal, so use a bcf instruction */
5112                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5113               } else {
5114                 emitcode("movlw","0x%x", (lit & 0xff));
5115                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5116               }
5117             }    
5118           }
5119         } else {
5120           if (AOP_TYPE(left) == AOP_ACC) 
5121             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5122           else {                    
5123             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5124             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5125
5126           }
5127         }
5128       }
5129
5130     } else {
5131         // left & result in different registers
5132         if(AOP_TYPE(result) == AOP_CRY){
5133             // result = bit
5134             // if(size), result in bit
5135             // if(!size && ifx), conditional oper: if(left & right)
5136             symbol *tlbl = newiTempLabel(NULL);
5137             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5138             if(size)
5139                 emitcode("setb","c");
5140             while(sizer--){
5141                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5142                 emitcode("anl","a,%s",
5143                          aopGet(AOP(left),offset,FALSE,FALSE));
5144                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5145                 offset++;
5146             }
5147             if(size){
5148                 CLRC;
5149                 emitcode("","%05d_DS_:",tlbl->key+100);
5150                 outBitC(result);
5151             } else if(ifx)
5152                 jmpTrueOrFalse(ifx, tlbl);
5153         } else {
5154           for(;(size--);offset++) {
5155             // normal case
5156             // result = left & right
5157             if(AOP_TYPE(right) == AOP_LIT){
5158               int t = (lit >> (offset*8)) & 0x0FFL;
5159               switch(t) { 
5160               case 0x00:
5161                 emitcode("clrf","%s",
5162                          aopGet(AOP(result),offset,FALSE,FALSE));
5163                 break;
5164               case 0xff:
5165                 emitcode("movf","%s,w",
5166                          aopGet(AOP(left),offset,FALSE,FALSE));
5167                 emitcode("movwf","%s",
5168                          aopGet(AOP(result),offset,FALSE,FALSE));
5169                 break;
5170               default:
5171                 emitcode("movlw","0x%x",t);
5172                 emitcode("andwf","%s,w",
5173                          aopGet(AOP(left),offset,FALSE,FALSE));
5174                 emitcode("movwf","%s",
5175                          aopGet(AOP(result),offset,FALSE,FALSE));
5176               
5177               }
5178               continue;
5179             }
5180
5181             if (AOP_TYPE(left) == AOP_ACC) 
5182               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5183             else {
5184               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5185               emitcode("andwf","%s,w",
5186                        aopGet(AOP(left),offset,FALSE,FALSE));
5187             }
5188             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5189           }
5190         }
5191     }
5192
5193 release :
5194     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5195     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5196     freeAsmop(result,NULL,ic,TRUE);     
5197 }
5198
5199 /*-----------------------------------------------------------------*/
5200 /* genOr  - code for or                                            */
5201 /*-----------------------------------------------------------------*/
5202 static void genOr (iCode *ic, iCode *ifx)
5203 {
5204     operand *left, *right, *result;
5205     int size, offset=0;
5206     unsigned long lit = 0L;
5207
5208     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5209
5210     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5211     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5212     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5213
5214
5215     /* if left is a literal & right is not then exchange them */
5216     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5217         AOP_NEEDSACC(left)) {
5218         operand *tmp = right ;
5219         right = left;
5220         left = tmp;
5221     }
5222
5223     /* if result = right then exchange them */
5224     if(sameRegs(AOP(result),AOP(right))){
5225         operand *tmp = right ;
5226         right = left;
5227         left = tmp;
5228     }
5229
5230     /* if right is bit then exchange them */
5231     if (AOP_TYPE(right) == AOP_CRY &&
5232         AOP_TYPE(left) != AOP_CRY){
5233         operand *tmp = right ;
5234         right = left;
5235         left = tmp;
5236     }
5237
5238     if(AOP_TYPE(right) == AOP_LIT)
5239         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5240
5241     size = AOP_SIZE(result);
5242
5243     // if(bit | yy)
5244     // xx = bit | yy;
5245     if (AOP_TYPE(left) == AOP_CRY){
5246         if(AOP_TYPE(right) == AOP_LIT){
5247             // c = bit & literal;
5248             if(lit){
5249                 // lit != 0 => result = 1
5250                 if(AOP_TYPE(result) == AOP_CRY){
5251                   if(size)
5252                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5253                   //emitcode("bsf","(%s >> 3), (%s & 7)",
5254                   //     AOP(result)->aopu.aop_dir,
5255                   //     AOP(result)->aopu.aop_dir);
5256                     else if(ifx)
5257                         continueIfTrue(ifx);
5258                     goto release;
5259                 }
5260             } else {
5261                 // lit == 0 => result = left
5262                 if(size && sameRegs(AOP(result),AOP(left)))
5263                     goto release;
5264                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5265             }
5266         } else {
5267             if (AOP_TYPE(right) == AOP_CRY){
5268               if(sameRegs(AOP(result),AOP(left))){
5269                 // c = bit | bit;
5270                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5271                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5272                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5273
5274                 emitcode("bcf","(%s >> 3), (%s & 7)",
5275                          AOP(result)->aopu.aop_dir,
5276                          AOP(result)->aopu.aop_dir);
5277                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5278                          AOP(right)->aopu.aop_dir,
5279                          AOP(right)->aopu.aop_dir);
5280                 emitcode("bsf","(%s >> 3), (%s & 7)",
5281                          AOP(result)->aopu.aop_dir,
5282                          AOP(result)->aopu.aop_dir);
5283               } else {
5284
5285                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5286                 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5287                 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5288                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5289
5290                 emitcode("bcf","(%s >> 3), (%s & 7)",
5291                          AOP(result)->aopu.aop_dir,
5292                          AOP(result)->aopu.aop_dir);
5293                 emitcode("btfss","(%s >> 3), (%s & 7)",
5294                          AOP(right)->aopu.aop_dir,
5295                          AOP(right)->aopu.aop_dir);
5296                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5297                          AOP(left)->aopu.aop_dir,
5298                          AOP(left)->aopu.aop_dir);
5299                 emitcode("bsf","(%s >> 3), (%s & 7)",
5300                          AOP(result)->aopu.aop_dir,
5301                          AOP(result)->aopu.aop_dir);
5302               }
5303             }
5304             else{
5305                 // c = bit | val;
5306                 symbol *tlbl = newiTempLabel(NULL);
5307                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5308                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5309                     emitcode(";XXX setb","c");
5310                 emitcode(";XXX jb","%s,%05d_DS_",
5311                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5312                 toBoolean(right);
5313                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5314                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5315                     jmpTrueOrFalse(ifx, tlbl);
5316                     goto release;
5317                 } else {
5318                     CLRC;
5319                     emitcode("","%05d_DS_:",tlbl->key+100);
5320                 }
5321             }
5322         }
5323         // bit = c
5324         // val = c
5325         if(size)
5326             outBitC(result);
5327         // if(bit | ...)
5328         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5329             genIfxJump(ifx, "c");           
5330         goto release ;
5331     }
5332
5333     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5334     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5335     if((AOP_TYPE(right) == AOP_LIT) &&
5336        (AOP_TYPE(result) == AOP_CRY) &&
5337        (AOP_TYPE(left) != AOP_CRY)){
5338         if(lit){
5339           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5340             // result = 1
5341             if(size)
5342                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5343             else 
5344                 continueIfTrue(ifx);
5345             goto release;
5346         } else {
5347           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5348             // lit = 0, result = boolean(left)
5349             if(size)
5350                 emitcode(";XXX setb","c");
5351             toBoolean(right);
5352             if(size){
5353                 symbol *tlbl = newiTempLabel(NULL);
5354                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5355                 CLRC;
5356                 emitcode("","%05d_DS_:",tlbl->key+100);
5357             } else {
5358                 genIfxJump (ifx,"a");
5359                 goto release;
5360             }
5361         }
5362         outBitC(result);
5363         goto release ;
5364     }
5365
5366     /* if left is same as result */
5367     if(sameRegs(AOP(result),AOP(left))){
5368       for(;size--; offset++,lit>>=8) {
5369         if(AOP_TYPE(right) == AOP_LIT){
5370           if((lit & 0xff) == 0)
5371             /*  or'ing with 0 has no effect */
5372             continue;
5373           else {
5374             int p = my_powof2(lit & 0xff);
5375             if(p>=0) {
5376               /* only one bit is set in the literal, so use a bsf instruction */
5377               emitpcode(POC_BSF,   popGet(AOP(left),offset,FALSE,FALSE));
5378               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5379             } else {
5380               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5381               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5382
5383               emitcode("movlw","0x%x", (lit & 0xff));
5384               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5385             }
5386                     
5387           }
5388         } else {
5389           if (AOP_TYPE(left) == AOP_ACC) {
5390             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5391             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5392           } else {                  
5393             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5394             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5395
5396             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5397             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5398
5399           }
5400         }
5401       }
5402     } else {
5403         // left & result in different registers
5404         if(AOP_TYPE(result) == AOP_CRY){
5405             // result = bit
5406             // if(size), result in bit
5407             // if(!size && ifx), conditional oper: if(left | right)
5408             symbol *tlbl = newiTempLabel(NULL);
5409             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5410             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5411
5412             if(size)
5413                 emitcode(";XXX setb","c");
5414             while(sizer--){
5415                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5416                 emitcode(";XXX orl","a,%s",
5417                          aopGet(AOP(left),offset,FALSE,FALSE));
5418                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5419                 offset++;
5420             }
5421             if(size){
5422                 CLRC;
5423                 emitcode("","%05d_DS_:",tlbl->key+100);
5424                 outBitC(result);
5425             } else if(ifx)
5426                 jmpTrueOrFalse(ifx, tlbl);
5427         } else for(;(size--);offset++){
5428           // normal case
5429           // result = left & right
5430           if(AOP_TYPE(right) == AOP_LIT){
5431             int t = (lit >> (offset*8)) & 0x0FFL;
5432             switch(t) { 
5433             case 0x00:
5434               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5435               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5436
5437               emitcode("movf","%s,w",
5438                        aopGet(AOP(left),offset,FALSE,FALSE));
5439               emitcode("movwf","%s",
5440                        aopGet(AOP(result),offset,FALSE,FALSE));
5441               break;
5442             default:
5443               emitpcode(POC_MOVLW,  popGetLit(t));
5444               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5445               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5446
5447               emitcode("movlw","0x%x",t);
5448               emitcode("iorwf","%s,w",
5449                        aopGet(AOP(left),offset,FALSE,FALSE));
5450               emitcode("movwf","%s",
5451                        aopGet(AOP(result),offset,FALSE,FALSE));
5452               
5453             }
5454             continue;
5455           }
5456
5457           // faster than result <- left, anl result,right
5458           // and better if result is SFR
5459           if (AOP_TYPE(left) == AOP_ACC) {
5460             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5461             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5462           } else {
5463             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5464             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5465
5466             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5467             emitcode("iorwf","%s,w",
5468                      aopGet(AOP(left),offset,FALSE,FALSE));
5469           }
5470           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5471           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5472         }
5473     }
5474
5475 release :
5476     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5477     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5478     freeAsmop(result,NULL,ic,TRUE);     
5479 }
5480
5481 /*-----------------------------------------------------------------*/
5482 /* genXor - code for xclusive or                                   */
5483 /*-----------------------------------------------------------------*/
5484 static void genXor (iCode *ic, iCode *ifx)
5485 {
5486     operand *left, *right, *result;
5487     int size, offset=0;
5488     unsigned long lit = 0L;
5489
5490     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5491
5492     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5493     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5494     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5495
5496     /* if left is a literal & right is not ||
5497        if left needs acc & right does not */
5498     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5499         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5500         operand *tmp = right ;
5501         right = left;
5502         left = tmp;
5503     }
5504
5505     /* if result = right then exchange them */
5506     if(sameRegs(AOP(result),AOP(right))){
5507         operand *tmp = right ;
5508         right = left;
5509         left = tmp;
5510     }
5511
5512     /* if right is bit then exchange them */
5513     if (AOP_TYPE(right) == AOP_CRY &&
5514         AOP_TYPE(left) != AOP_CRY){
5515         operand *tmp = right ;
5516         right = left;
5517         left = tmp;
5518     }
5519     if(AOP_TYPE(right) == AOP_LIT)
5520         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5521
5522     size = AOP_SIZE(result);
5523
5524     // if(bit ^ yy)
5525     // xx = bit ^ yy;
5526     if (AOP_TYPE(left) == AOP_CRY){
5527         if(AOP_TYPE(right) == AOP_LIT){
5528             // c = bit & literal;
5529             if(lit>>1){
5530                 // lit>>1  != 0 => result = 1
5531                 if(AOP_TYPE(result) == AOP_CRY){
5532                     if(size)
5533                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5534                     else if(ifx)
5535                         continueIfTrue(ifx);
5536                     goto release;
5537                 }
5538                 emitcode("setb","c");
5539             } else{
5540                 // lit == (0 or 1)
5541                 if(lit == 0){
5542                     // lit == 0, result = left
5543                     if(size && sameRegs(AOP(result),AOP(left)))
5544                         goto release;
5545                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5546                 } else{
5547                     // lit == 1, result = not(left)
5548                     if(size && sameRegs(AOP(result),AOP(left))){
5549                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5550                         goto release;
5551                     } else {
5552                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5553                         emitcode("cpl","c");
5554                     }
5555                 }
5556             }
5557
5558         } else {
5559             // right != literal
5560             symbol *tlbl = newiTempLabel(NULL);
5561             if (AOP_TYPE(right) == AOP_CRY){
5562                 // c = bit ^ bit;
5563                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5564             }
5565             else{
5566                 int sizer = AOP_SIZE(right);
5567                 // c = bit ^ val
5568                 // if val>>1 != 0, result = 1
5569                 emitcode("setb","c");
5570                 while(sizer){
5571                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5572                     if(sizer == 1)
5573                         // test the msb of the lsb
5574                         emitcode("anl","a,#0xfe");
5575                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5576                     sizer--;
5577                 }
5578                 // val = (0,1)
5579                 emitcode("rrc","a");
5580             }
5581             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5582             emitcode("cpl","c");
5583             emitcode("","%05d_DS_:",(tlbl->key+100));
5584         }
5585         // bit = c
5586         // val = c
5587         if(size)
5588             outBitC(result);
5589         // if(bit | ...)
5590         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5591             genIfxJump(ifx, "c");           
5592         goto release ;
5593     }
5594
5595     if(sameRegs(AOP(result),AOP(left))){
5596         /* if left is same as result */
5597         for(;size--; offset++) {
5598             if(AOP_TYPE(right) == AOP_LIT){
5599                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5600                     continue;
5601                 else
5602                     if (IS_AOP_PREG(left)) {
5603                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5604                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5605                         aopPut(AOP(result),"a",offset);
5606                     } else 
5607                         emitcode("xrl","%s,%s",
5608                                  aopGet(AOP(left),offset,FALSE,TRUE),
5609                                  aopGet(AOP(right),offset,FALSE,FALSE));
5610             } else {
5611                 if (AOP_TYPE(left) == AOP_ACC)
5612                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5613                 else {
5614                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5615                     if (IS_AOP_PREG(left)) {
5616                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5617                         aopPut(AOP(result),"a",offset);
5618                     } else
5619                         emitcode("xrl","%s,a",
5620                                  aopGet(AOP(left),offset,FALSE,TRUE));
5621                 }
5622             }
5623         }
5624     } else {
5625         // left & result in different registers
5626         if(AOP_TYPE(result) == AOP_CRY){
5627             // result = bit
5628             // if(size), result in bit
5629             // if(!size && ifx), conditional oper: if(left ^ right)
5630             symbol *tlbl = newiTempLabel(NULL);
5631             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5632             if(size)
5633                 emitcode("setb","c");
5634             while(sizer--){
5635                 if((AOP_TYPE(right) == AOP_LIT) &&
5636                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5637                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5638                 } else {
5639                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5640                     emitcode("xrl","a,%s",
5641                              aopGet(AOP(left),offset,FALSE,FALSE));
5642                 }
5643                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5644                 offset++;
5645             }
5646             if(size){
5647                 CLRC;
5648                 emitcode("","%05d_DS_:",tlbl->key+100);
5649                 outBitC(result);
5650             } else if(ifx)
5651                 jmpTrueOrFalse(ifx, tlbl);
5652         } else for(;(size--);offset++){
5653             // normal case
5654             // result = left & right
5655             if(AOP_TYPE(right) == AOP_LIT){
5656               int t = (lit >> (offset*8)) & 0x0FFL;
5657               switch(t) { 
5658               case 0x00:
5659                 emitcode("movf","%s,w",
5660                          aopGet(AOP(left),offset,FALSE,FALSE));
5661                 emitcode("movwf","%s",
5662                          aopGet(AOP(result),offset,FALSE,FALSE));
5663                 break;
5664               case 0xff:
5665                 emitcode("comf","%s,w",
5666                          aopGet(AOP(left),offset,FALSE,FALSE));
5667                 emitcode("movwf","%s",
5668                          aopGet(AOP(result),offset,FALSE,FALSE));
5669                 break;
5670               default:
5671                 emitcode("movlw","0x%x",t);
5672                 emitcode("xorwf","%s,w",
5673                          aopGet(AOP(left),offset,FALSE,FALSE));
5674                 emitcode("movwf","%s",
5675                          aopGet(AOP(result),offset,FALSE,FALSE));
5676
5677               }
5678               continue;
5679             }
5680
5681             // faster than result <- left, anl result,right
5682             // and better if result is SFR
5683             if (AOP_TYPE(left) == AOP_ACC)
5684                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5685             else {
5686                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5687                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5688             }
5689             if ( AOP_TYPE(result) != AOP_ACC)
5690               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5691         }
5692     }
5693
5694 release :
5695     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5696     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5697     freeAsmop(result,NULL,ic,TRUE);     
5698 }
5699
5700 /*-----------------------------------------------------------------*/
5701 /* genInline - write the inline code out                           */
5702 /*-----------------------------------------------------------------*/
5703 static void genInline (iCode *ic)
5704 {
5705     char buffer[MAX_INLINEASM];
5706     char *bp = buffer;
5707     char *bp1= buffer;
5708     
5709     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5710
5711     _G.inLine += (!options.asmpeep);
5712     strcpy(buffer,IC_INLINE(ic));
5713
5714     /* emit each line as a code */
5715     while (*bp) {
5716         if (*bp == '\n') {
5717             *bp++ = '\0';
5718             emitcode(bp1,"");
5719             bp1 = bp;
5720         } else {
5721             if (*bp == ':') {
5722                 bp++;
5723                 *bp = '\0';
5724                 bp++;
5725                 emitcode(bp1,"");
5726                 bp1 = bp;
5727             } else
5728                 bp++;
5729         }
5730     }
5731     if (bp1 != bp)
5732         emitcode(bp1,"");
5733     /*     emitcode("",buffer); */
5734     _G.inLine -= (!options.asmpeep);
5735 }
5736
5737 /*-----------------------------------------------------------------*/
5738 /* genRRC - rotate right with carry                                */
5739 /*-----------------------------------------------------------------*/
5740 static void genRRC (iCode *ic)
5741 {
5742     operand *left , *result ;
5743     int size, offset = 0;
5744     char *l;    
5745
5746     /* rotate right with carry */
5747     left = IC_LEFT(ic);
5748     result=IC_RESULT(ic);
5749     aopOp (left,ic,FALSE);
5750     aopOp (result,ic,FALSE);
5751
5752     /* move it to the result */
5753     size = AOP_SIZE(result);    
5754     offset = size - 1 ;
5755     CLRC;
5756     while (size--) {
5757         l = aopGet(AOP(left),offset,FALSE,FALSE);
5758         MOVA(l);
5759         emitcode("rrc","a");
5760         if (AOP_SIZE(result) > 1)
5761             aopPut(AOP(result),"a",offset--);
5762     }
5763     /* now we need to put the carry into the
5764     highest order byte of the result */
5765     if (AOP_SIZE(result) > 1) {
5766         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5767         MOVA(l);
5768     }
5769     emitcode("mov","acc.7,c");
5770     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5771     freeAsmop(left,NULL,ic,TRUE);
5772     freeAsmop(result,NULL,ic,TRUE);
5773 }
5774
5775 /*-----------------------------------------------------------------*/
5776 /* genRLC - generate code for rotate left with carry               */
5777 /*-----------------------------------------------------------------*/
5778 static void genRLC (iCode *ic)
5779 {    
5780     operand *left , *result ;
5781     int size, offset = 0;
5782     char *l;    
5783
5784     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5785     /* rotate right with carry */
5786     left = IC_LEFT(ic);
5787     result=IC_RESULT(ic);
5788     aopOp (left,ic,FALSE);
5789     aopOp (result,ic,FALSE);
5790
5791     /* move it to the result */
5792     size = AOP_SIZE(result);    
5793     offset = 0 ;
5794     if (size--) {
5795         l = aopGet(AOP(left),offset,FALSE,FALSE);
5796         MOVA(l);
5797         emitcode("add","a,acc");
5798         if (AOP_SIZE(result) > 1)
5799             aopPut(AOP(result),"a",offset++);
5800         while (size--) {
5801             l = aopGet(AOP(left),offset,FALSE,FALSE);
5802             MOVA(l);
5803             emitcode("rlc","a");
5804             if (AOP_SIZE(result) > 1)
5805                 aopPut(AOP(result),"a",offset++);
5806         }
5807     }
5808     /* now we need to put the carry into the
5809     highest order byte of the result */
5810     if (AOP_SIZE(result) > 1) {
5811         l = aopGet(AOP(result),0,FALSE,FALSE);
5812         MOVA(l);
5813     }
5814     emitcode("mov","acc.0,c");
5815     aopPut(AOP(result),"a",0);
5816     freeAsmop(left,NULL,ic,TRUE);
5817     freeAsmop(result,NULL,ic,TRUE);
5818 }
5819
5820 /*-----------------------------------------------------------------*/
5821 /* genGetHbit - generates code get highest order bit               */
5822 /*-----------------------------------------------------------------*/
5823 static void genGetHbit (iCode *ic)
5824 {
5825     operand *left, *result;
5826     left = IC_LEFT(ic);
5827     result=IC_RESULT(ic);
5828     aopOp (left,ic,FALSE);
5829     aopOp (result,ic,FALSE);
5830
5831     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832     /* get the highest order byte into a */
5833     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5834     if(AOP_TYPE(result) == AOP_CRY){
5835         emitcode("rlc","a");
5836         outBitC(result);
5837     }
5838     else{
5839         emitcode("rl","a");
5840         emitcode("anl","a,#0x01");
5841         outAcc(result);
5842     }
5843
5844
5845     freeAsmop(left,NULL,ic,TRUE);
5846     freeAsmop(result,NULL,ic,TRUE);
5847 }
5848
5849 /*-----------------------------------------------------------------*/
5850 /* AccRol - rotate left accumulator by known count                 */
5851 /*-----------------------------------------------------------------*/
5852 static void AccRol (int shCount)
5853 {
5854     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5855     shCount &= 0x0007;              // shCount : 0..7
5856     switch(shCount){
5857         case 0 :
5858             break;
5859         case 1 :
5860             emitcode("rl","a");
5861             break;
5862         case 2 :
5863             emitcode("rl","a");
5864             emitcode("rl","a");
5865             break;
5866         case 3 :
5867             emitcode("swap","a");
5868             emitcode("rr","a");
5869             break;
5870         case 4 :
5871             emitcode("swap","a");
5872             break;
5873         case 5 :
5874             emitcode("swap","a");
5875             emitcode("rl","a");
5876             break;
5877         case 6 :
5878             emitcode("rr","a");
5879             emitcode("rr","a");
5880             break;
5881         case 7 :
5882             emitcode("rr","a");
5883             break;
5884     }
5885 }
5886
5887 /*-----------------------------------------------------------------*/
5888 /* AccLsh - left shift accumulator by known count                  */
5889 /*-----------------------------------------------------------------*/
5890 static void AccLsh (int shCount)
5891 {
5892     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5893     if(shCount != 0){
5894         if(shCount == 1)
5895             emitcode("add","a,acc");
5896         else 
5897             if(shCount == 2) {
5898             emitcode("add","a,acc");
5899             emitcode("add","a,acc");
5900         } else {
5901             /* rotate left accumulator */
5902             AccRol(shCount);
5903             /* and kill the lower order bits */
5904             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5905         }
5906     }
5907 }
5908
5909 /*-----------------------------------------------------------------*/
5910 /* AccRsh - right shift accumulator by known count                 */
5911 /*-----------------------------------------------------------------*/
5912 static void AccRsh (int shCount)
5913 {
5914     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5915     if(shCount != 0){
5916         if(shCount == 1){
5917             CLRC;
5918             emitcode("rrc","a");
5919         } else {
5920             /* rotate right accumulator */
5921             AccRol(8 - shCount);
5922             /* and kill the higher order bits */
5923             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5924         }
5925     }
5926 }
5927
5928 /*-----------------------------------------------------------------*/
5929 /* AccSRsh - signed right shift accumulator by known count                 */
5930 /*-----------------------------------------------------------------*/
5931 static void AccSRsh (int shCount)
5932 {
5933     symbol *tlbl ;
5934     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5935     if(shCount != 0){
5936         if(shCount == 1){
5937             emitcode("mov","c,acc.7");
5938             emitcode("rrc","a");
5939         } else if(shCount == 2){
5940             emitcode("mov","c,acc.7");
5941             emitcode("rrc","a");
5942             emitcode("mov","c,acc.7");
5943             emitcode("rrc","a");
5944         } else {
5945             tlbl = newiTempLabel(NULL);
5946             /* rotate right accumulator */
5947             AccRol(8 - shCount);
5948             /* and kill the higher order bits */
5949             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5950             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5951             emitcode("orl","a,#0x%02x",
5952                      (unsigned char)~SRMask[shCount]);
5953             emitcode("","%05d_DS_:",tlbl->key+100);
5954         }
5955     }
5956 }
5957
5958 /*-----------------------------------------------------------------*/
5959 /* shiftR1Left2Result - shift right one byte from left to result   */
5960 /*-----------------------------------------------------------------*/
5961 static void shiftR1Left2Result (operand *left, int offl,
5962                                 operand *result, int offr,
5963                                 int shCount, int sign)
5964 {
5965     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5966     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5967     /* shift right accumulator */
5968     if(sign)
5969         AccSRsh(shCount);
5970     else
5971         AccRsh(shCount);
5972     aopPut(AOP(result),"a",offr);
5973 }
5974
5975 /*-----------------------------------------------------------------*/
5976 /* shiftL1Left2Result - shift left one byte from left to result    */
5977 /*-----------------------------------------------------------------*/
5978 static void shiftL1Left2Result (operand *left, int offl,
5979                                 operand *result, int offr, int shCount)
5980 {
5981     char *l;
5982     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5983     l = aopGet(AOP(left),offl,FALSE,FALSE);
5984     MOVA(l);
5985     /* shift left accumulator */
5986     AccLsh(shCount);
5987     aopPut(AOP(result),"a",offr);
5988 }
5989
5990 /*-----------------------------------------------------------------*/
5991 /* movLeft2Result - move byte from left to result                  */
5992 /*-----------------------------------------------------------------*/
5993 static void movLeft2Result (operand *left, int offl,
5994                             operand *result, int offr, int sign)
5995 {
5996     char *l;
5997     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5998     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5999         l = aopGet(AOP(left),offl,FALSE,FALSE);
6000
6001         if (*l == '@' && (IS_AOP_PREG(result))) {
6002             emitcode("mov","a,%s",l);
6003             aopPut(AOP(result),"a",offr);
6004         } else {
6005             if(!sign)
6006                 aopPut(AOP(result),l,offr);
6007             else{
6008                 /* MSB sign in acc.7 ! */
6009                 if(getDataSize(left) == offl+1){
6010                     emitcode("mov","a,%s",l);
6011                     aopPut(AOP(result),"a",offr);
6012                 }
6013             }
6014         }
6015     }
6016 }
6017
6018 /*-----------------------------------------------------------------*/
6019 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6020 /*-----------------------------------------------------------------*/
6021 static void AccAXRrl1 (char *x)
6022 {
6023     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6024     emitcode("rrc","a");
6025     emitcode("xch","a,%s", x);
6026     emitcode("rrc","a");
6027     emitcode("xch","a,%s", x);
6028 }
6029
6030 /*-----------------------------------------------------------------*/
6031 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6032 /*-----------------------------------------------------------------*/
6033 static void AccAXLrl1 (char *x)
6034 {
6035     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6036     emitcode("xch","a,%s",x);
6037     emitcode("rlc","a");
6038     emitcode("xch","a,%s",x);
6039     emitcode("rlc","a");
6040 }
6041
6042 /*-----------------------------------------------------------------*/
6043 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6044 /*-----------------------------------------------------------------*/
6045 static void AccAXLsh1 (char *x)
6046 {
6047     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6048     emitcode("xch","a,%s",x);
6049     emitcode("add","a,acc");
6050     emitcode("xch","a,%s",x);
6051     emitcode("rlc","a");
6052 }
6053
6054 /*-----------------------------------------------------------------*/
6055 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6056 /*-----------------------------------------------------------------*/
6057 static void AccAXLsh (char *x, int shCount)
6058 {
6059     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6060     switch(shCount){
6061         case 0 :
6062             break;
6063         case 1 :
6064             AccAXLsh1(x);
6065             break;
6066         case 2 :
6067             AccAXLsh1(x);
6068             AccAXLsh1(x);
6069             break;
6070         case 3 :
6071         case 4 :
6072         case 5 :                        // AAAAABBB:CCCCCDDD
6073             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
6074             emitcode("anl","a,#0x%02x",
6075                      SLMask[shCount]);  // BBB00000:CCCCCDDD
6076             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
6077             AccRol(shCount);            // DDDCCCCC:BBB00000
6078             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
6079             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
6080             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
6081             emitcode("anl","a,#0x%02x",
6082                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
6083             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
6084             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
6085             break;
6086         case 6 :                        // AAAAAABB:CCCCCCDD
6087             emitcode("anl","a,#0x%02x",
6088                      SRMask[shCount]);  // 000000BB:CCCCCCDD
6089             emitcode("mov","c,acc.0");  // c = B
6090             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
6091             AccAXRrl1(x);               // BCCCCCCD:D000000B
6092             AccAXRrl1(x);               // BBCCCCCC:DD000000
6093             break;
6094         case 7 :                        // a:x <<= 7
6095             emitcode("anl","a,#0x%02x",
6096                      SRMask[shCount]);  // 0000000B:CCCCCCCD
6097             emitcode("mov","c,acc.0");  // c = B
6098             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
6099             AccAXRrl1(x);               // BCCCCCCC:D0000000
6100             break;
6101         default :
6102             break;
6103     }
6104 }
6105
6106 /*-----------------------------------------------------------------*/
6107 /* AccAXRsh - right shift a:x known count (0..7)                   */
6108 /*-----------------------------------------------------------------*/
6109 static void AccAXRsh (char *x, int shCount)
6110 {   
6111     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6112     switch(shCount){
6113         case 0 :
6114             break;
6115         case 1 :
6116             CLRC;
6117             AccAXRrl1(x);               // 0->a:x
6118             break;
6119         case 2 :
6120             CLRC;
6121             AccAXRrl1(x);               // 0->a:x
6122             CLRC;
6123             AccAXRrl1(x);               // 0->a:x
6124             break;
6125         case 3 :
6126         case 4 :
6127         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6128             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
6129             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6130             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6131             emitcode("anl","a,#0x%02x",
6132                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6133             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6134             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6135             emitcode("anl","a,#0x%02x",
6136                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6137             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6138             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6139             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
6140             break;
6141         case 6 :                        // AABBBBBB:CCDDDDDD
6142             emitcode("mov","c,acc.7");
6143             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6144             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6145             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6146             emitcode("anl","a,#0x%02x",
6147                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6148             break;
6149         case 7 :                        // ABBBBBBB:CDDDDDDD
6150             emitcode("mov","c,acc.7");  // c = A
6151             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6152             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6153             emitcode("anl","a,#0x%02x",
6154                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6155             break;
6156         default :
6157             break;
6158     }
6159 }
6160
6161 /*-----------------------------------------------------------------*/
6162 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6163 /*-----------------------------------------------------------------*/
6164 static void AccAXRshS (char *x, int shCount)
6165 {   
6166     symbol *tlbl ;
6167     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6168     switch(shCount){
6169         case 0 :
6170             break;
6171         case 1 :
6172             emitcode("mov","c,acc.7");
6173             AccAXRrl1(x);               // s->a:x
6174             break;
6175         case 2 :
6176             emitcode("mov","c,acc.7");
6177             AccAXRrl1(x);               // s->a:x
6178             emitcode("mov","c,acc.7");
6179             AccAXRrl1(x);               // s->a:x
6180             break;
6181         case 3 :
6182         case 4 :
6183         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6184             tlbl = newiTempLabel(NULL);
6185             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6186             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6187             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6188             emitcode("anl","a,#0x%02x",
6189                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6190             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6191             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6192             emitcode("anl","a,#0x%02x",
6193                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6194             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6195             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6196             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6197             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6198             emitcode("orl","a,#0x%02x",
6199                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6200             emitcode("","%05d_DS_:",tlbl->key+100);
6201             break;                      // SSSSAAAA:BBBCCCCC
6202         case 6 :                        // AABBBBBB:CCDDDDDD
6203             tlbl = newiTempLabel(NULL);
6204             emitcode("mov","c,acc.7");
6205             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6206             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6207             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6208             emitcode("anl","a,#0x%02x",
6209                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6210             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6211             emitcode("orl","a,#0x%02x",
6212                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6213             emitcode("","%05d_DS_:",tlbl->key+100);
6214             break;
6215         case 7 :                        // ABBBBBBB:CDDDDDDD
6216             tlbl = newiTempLabel(NULL);
6217             emitcode("mov","c,acc.7");  // c = A
6218             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6219             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6220             emitcode("anl","a,#0x%02x",
6221                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6222             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6223             emitcode("orl","a,#0x%02x",
6224                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6225             emitcode("","%05d_DS_:",tlbl->key+100);
6226             break;
6227         default :
6228             break;
6229     }
6230 }
6231
6232 /*-----------------------------------------------------------------*/
6233 /* shiftL2Left2Result - shift left two bytes from left to result   */
6234 /*-----------------------------------------------------------------*/
6235 static void shiftL2Left2Result (operand *left, int offl,
6236                                 operand *result, int offr, int shCount)
6237 {
6238     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6239     if(sameRegs(AOP(result), AOP(left)) &&
6240        ((offl + MSB16) == offr)){
6241         /* don't crash result[offr] */
6242         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6243         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6244     } else {
6245         movLeft2Result(left,offl, result, offr, 0);
6246         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6247     }
6248     /* ax << shCount (x = lsb(result))*/
6249     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6250     aopPut(AOP(result),"a",offr+MSB16);
6251 }
6252
6253
6254 /*-----------------------------------------------------------------*/
6255 /* shiftR2Left2Result - shift right two bytes from left to result  */
6256 /*-----------------------------------------------------------------*/
6257 static void shiftR2Left2Result (operand *left, int offl,
6258                                 operand *result, int offr,
6259                                 int shCount, int sign)
6260 {
6261     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6262     if(sameRegs(AOP(result), AOP(left)) &&
6263        ((offl + MSB16) == offr)){
6264         /* don't crash result[offr] */
6265         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6266         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6267     } else {
6268         movLeft2Result(left,offl, result, offr, 0);
6269         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6270     }
6271     /* a:x >> shCount (x = lsb(result))*/
6272     if(sign)
6273         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6274     else
6275         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6276     if(getDataSize(result) > 1)
6277         aopPut(AOP(result),"a",offr+MSB16);
6278 }
6279
6280 /*-----------------------------------------------------------------*/
6281 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6282 /*-----------------------------------------------------------------*/
6283 static void shiftLLeftOrResult (operand *left, int offl,
6284                                 operand *result, int offr, int shCount)
6285 {
6286     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6287     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6288     /* shift left accumulator */
6289     AccLsh(shCount);
6290     /* or with result */
6291     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6292     /* back to result */
6293     aopPut(AOP(result),"a",offr);
6294 }
6295
6296 /*-----------------------------------------------------------------*/
6297 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6298 /*-----------------------------------------------------------------*/
6299 static void shiftRLeftOrResult (operand *left, int offl,
6300                                 operand *result, int offr, int shCount)
6301 {
6302     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6303     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6304     /* shift right accumulator */
6305     AccRsh(shCount);
6306     /* or with result */
6307     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6308     /* back to result */
6309     aopPut(AOP(result),"a",offr);
6310 }
6311
6312 /*-----------------------------------------------------------------*/
6313 /* genlshOne - left shift a one byte quantity by known count       */
6314 /*-----------------------------------------------------------------*/
6315 static void genlshOne (operand *result, operand *left, int shCount)
6316 {       
6317     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6318     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6319 }
6320
6321 /*-----------------------------------------------------------------*/
6322 /* genlshTwo - left shift two bytes by known amount != 0           */
6323 /*-----------------------------------------------------------------*/
6324 static void genlshTwo (operand *result,operand *left, int shCount)
6325 {
6326     int size;
6327     
6328     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6329     size = getDataSize(result);
6330
6331     /* if shCount >= 8 */
6332     if (shCount >= 8) {
6333         shCount -= 8 ;
6334
6335         if (size > 1){
6336             if (shCount)
6337                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6338             else 
6339                 movLeft2Result(left, LSB, result, MSB16, 0);
6340         }
6341         aopPut(AOP(result),zero,LSB);   
6342     }
6343
6344     /*  1 <= shCount <= 7 */
6345     else {  
6346         if(size == 1)
6347             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6348         else 
6349             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6350     }
6351 }
6352
6353 /*-----------------------------------------------------------------*/
6354 /* shiftLLong - shift left one long from left to result            */
6355 /* offl = LSB or MSB16                                             */
6356 /*-----------------------------------------------------------------*/
6357 static void shiftLLong (operand *left, operand *result, int offr )
6358 {
6359     char *l;
6360     int size = AOP_SIZE(result);
6361
6362     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363     if(size >= LSB+offr){
6364         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6365         MOVA(l);
6366         emitcode("add","a,acc");
6367         if (sameRegs(AOP(left),AOP(result)) && 
6368             size >= MSB16+offr && offr != LSB )
6369             emitcode("xch","a,%s",
6370                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6371         else        
6372             aopPut(AOP(result),"a",LSB+offr);
6373     }
6374
6375     if(size >= MSB16+offr){
6376         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6377             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6378             MOVA(l);
6379         }
6380         emitcode("rlc","a");
6381         if (sameRegs(AOP(left),AOP(result)) && 
6382             size >= MSB24+offr && offr != LSB)
6383             emitcode("xch","a,%s",
6384                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6385         else        
6386             aopPut(AOP(result),"a",MSB16+offr);
6387     }
6388
6389     if(size >= MSB24+offr){
6390         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6391             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6392             MOVA(l);
6393         }
6394         emitcode("rlc","a");
6395         if (sameRegs(AOP(left),AOP(result)) && 
6396             size >= MSB32+offr && offr != LSB )
6397             emitcode("xch","a,%s",
6398                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6399         else        
6400             aopPut(AOP(result),"a",MSB24+offr);
6401     }
6402
6403     if(size > MSB32+offr){
6404         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6405             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6406             MOVA(l);    
6407         }
6408         emitcode("rlc","a");
6409         aopPut(AOP(result),"a",MSB32+offr);
6410     }
6411     if(offr != LSB)
6412         aopPut(AOP(result),zero,LSB);       
6413 }
6414
6415 /*-----------------------------------------------------------------*/
6416 /* genlshFour - shift four byte by a known amount != 0             */
6417 /*-----------------------------------------------------------------*/
6418 static void genlshFour (operand *result, operand *left, int shCount)
6419 {
6420     int size;
6421
6422     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6423     size = AOP_SIZE(result);
6424
6425     /* if shifting more that 3 bytes */
6426     if (shCount >= 24 ) {
6427         shCount -= 24;
6428         if (shCount)
6429             /* lowest order of left goes to the highest
6430             order of the destination */
6431             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6432         else
6433             movLeft2Result(left, LSB, result, MSB32, 0);
6434         aopPut(AOP(result),zero,LSB);
6435         aopPut(AOP(result),zero,MSB16);
6436         aopPut(AOP(result),zero,MSB32);
6437         return;
6438     }
6439
6440     /* more than two bytes */
6441     else if ( shCount >= 16 ) {
6442         /* lower order two bytes goes to higher order two bytes */
6443         shCount -= 16;
6444         /* if some more remaining */
6445         if (shCount)
6446             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6447         else {
6448             movLeft2Result(left, MSB16, result, MSB32, 0);
6449             movLeft2Result(left, LSB, result, MSB24, 0);
6450         }
6451         aopPut(AOP(result),zero,MSB16);
6452         aopPut(AOP(result),zero,LSB);
6453         return;
6454     }    
6455
6456     /* if more than 1 byte */
6457     else if ( shCount >= 8 ) {
6458         /* lower order three bytes goes to higher order  three bytes */
6459         shCount -= 8;
6460         if(size == 2){
6461             if(shCount)
6462                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6463             else
6464                 movLeft2Result(left, LSB, result, MSB16, 0);
6465         }
6466         else{   /* size = 4 */
6467             if(shCount == 0){
6468                 movLeft2Result(left, MSB24, result, MSB32, 0);
6469                 movLeft2Result(left, MSB16, result, MSB24, 0);
6470                 movLeft2Result(left, LSB, result, MSB16, 0);
6471                 aopPut(AOP(result),zero,LSB);
6472             }
6473             else if(shCount == 1)
6474                 shiftLLong(left, result, MSB16);
6475             else{
6476                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6477                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6478                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6479                 aopPut(AOP(result),zero,LSB);
6480             }
6481         }
6482     }
6483
6484     /* 1 <= shCount <= 7 */
6485     else if(shCount <= 2){
6486         shiftLLong(left, result, LSB);
6487         if(shCount == 2)
6488             shiftLLong(result, result, LSB);
6489     }
6490     /* 3 <= shCount <= 7, optimize */
6491     else{
6492         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6493         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6494         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6495     }
6496 }
6497
6498 /*-----------------------------------------------------------------*/
6499 /* genLeftShiftLiteral - left shifting by known count              */
6500 /*-----------------------------------------------------------------*/
6501 static void genLeftShiftLiteral (operand *left,
6502                                  operand *right,
6503                                  operand *result,
6504                                  iCode *ic)
6505 {    
6506     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6507     int size;
6508
6509     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6510     freeAsmop(right,NULL,ic,TRUE);
6511
6512     aopOp(left,ic,FALSE);
6513     aopOp(result,ic,FALSE);
6514
6515     size = getSize(operandType(result));
6516
6517 #if VIEW_SIZE
6518     emitcode("; shift left ","result %d, left %d",size,
6519              AOP_SIZE(left));
6520 #endif
6521
6522     /* I suppose that the left size >= result size */
6523     if(shCount == 0){
6524         while(size--){
6525             movLeft2Result(left, size, result, size, 0);
6526         }
6527     }
6528
6529     else if(shCount >= (size * 8))
6530         while(size--)
6531             aopPut(AOP(result),zero,size);
6532     else{
6533         switch (size) {
6534             case 1:
6535                 genlshOne (result,left,shCount);
6536                 break;
6537
6538             case 2:
6539             case 3:
6540                 genlshTwo (result,left,shCount);
6541                 break;
6542
6543             case 4:
6544                 genlshFour (result,left,shCount);
6545                 break;
6546         }
6547     }
6548     freeAsmop(left,NULL,ic,TRUE);
6549     freeAsmop(result,NULL,ic,TRUE);
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* genLeftShift - generates code for left shifting                 */
6554 /*-----------------------------------------------------------------*/
6555 static void genLeftShift (iCode *ic)
6556 {
6557     operand *left,*right, *result;
6558     int size, offset;
6559     char *l;
6560     symbol *tlbl , *tlbl1;
6561
6562     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6563
6564     right = IC_RIGHT(ic);
6565     left  = IC_LEFT(ic);
6566     result = IC_RESULT(ic);
6567
6568     aopOp(right,ic,FALSE);
6569
6570     /* if the shift count is known then do it 
6571     as efficiently as possible */
6572     if (AOP_TYPE(right) == AOP_LIT) {
6573         genLeftShiftLiteral (left,right,result,ic);
6574         return ;
6575     }
6576
6577     /* shift count is unknown then we have to form 
6578     a loop get the loop count in B : Note: we take
6579     only the lower order byte since shifting
6580     more that 32 bits make no sense anyway, ( the
6581     largest size of an object can be only 32 bits ) */  
6582
6583     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6584     emitcode("inc","b");
6585     freeAsmop (right,NULL,ic,TRUE);
6586     aopOp(left,ic,FALSE);
6587     aopOp(result,ic,FALSE);
6588
6589     /* now move the left to the result if they are not the
6590     same */
6591     if (!sameRegs(AOP(left),AOP(result)) && 
6592         AOP_SIZE(result) > 1) {
6593
6594         size = AOP_SIZE(result);
6595         offset=0;
6596         while (size--) {
6597             l = aopGet(AOP(left),offset,FALSE,TRUE);
6598             if (*l == '@' && (IS_AOP_PREG(result))) {
6599
6600                 emitcode("mov","a,%s",l);
6601                 aopPut(AOP(result),"a",offset);
6602             } else
6603                 aopPut(AOP(result),l,offset);
6604             offset++;
6605         }
6606     }
6607
6608     tlbl = newiTempLabel(NULL);
6609     size = AOP_SIZE(result);
6610     offset = 0 ;   
6611     tlbl1 = newiTempLabel(NULL);
6612
6613     /* if it is only one byte then */
6614     if (size == 1) {
6615         symbol *tlbl1 = newiTempLabel(NULL);
6616
6617         l = aopGet(AOP(left),0,FALSE,FALSE);
6618         MOVA(l);
6619         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6620         emitcode("","%05d_DS_:",tlbl->key+100);
6621         emitcode("add","a,acc");
6622         emitcode("","%05d_DS_:",tlbl1->key+100);
6623         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6624         aopPut(AOP(result),"a",0);
6625         goto release ;
6626     }
6627     
6628     reAdjustPreg(AOP(result));    
6629     
6630     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6631     emitcode("","%05d_DS_:",tlbl->key+100);    
6632     l = aopGet(AOP(result),offset,FALSE,FALSE);
6633     MOVA(l);
6634     emitcode("add","a,acc");         
6635     aopPut(AOP(result),"a",offset++);
6636     while (--size) {
6637         l = aopGet(AOP(result),offset,FALSE,FALSE);
6638         MOVA(l);
6639         emitcode("rlc","a");         
6640         aopPut(AOP(result),"a",offset++);
6641     }
6642     reAdjustPreg(AOP(result));
6643
6644     emitcode("","%05d_DS_:",tlbl1->key+100);
6645     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6646 release:
6647     freeAsmop(left,NULL,ic,TRUE);
6648     freeAsmop(result,NULL,ic,TRUE);
6649 }
6650
6651 /*-----------------------------------------------------------------*/
6652 /* genrshOne - right shift a one byte quantity by known count      */
6653 /*-----------------------------------------------------------------*/
6654 static void genrshOne (operand *result, operand *left,
6655                        int shCount, int sign)
6656 {
6657     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6659 }
6660
6661 /*-----------------------------------------------------------------*/
6662 /* genrshTwo - right shift two bytes by known amount != 0          */
6663 /*-----------------------------------------------------------------*/
6664 static void genrshTwo (operand *result,operand *left,
6665                        int shCount, int sign)
6666 {
6667     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6668     /* if shCount >= 8 */
6669     if (shCount >= 8) {
6670         shCount -= 8 ;
6671         if (shCount)
6672             shiftR1Left2Result(left, MSB16, result, LSB,
6673                                shCount, sign);
6674         else 
6675             movLeft2Result(left, MSB16, result, LSB, sign);
6676         addSign(result, MSB16, sign);
6677     }
6678
6679     /*  1 <= shCount <= 7 */
6680     else
6681         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6682 }
6683
6684 /*-----------------------------------------------------------------*/
6685 /* shiftRLong - shift right one long from left to result           */
6686 /* offl = LSB or MSB16                                             */
6687 /*-----------------------------------------------------------------*/
6688 static void shiftRLong (operand *left, int offl,
6689                         operand *result, int sign)
6690 {
6691     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6692     if(!sign)
6693         emitcode("clr","c");
6694     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6695     if(sign)
6696         emitcode("mov","c,acc.7");
6697     emitcode("rrc","a");
6698     aopPut(AOP(result),"a",MSB32-offl);
6699     if(offl == MSB16)
6700         /* add sign of "a" */
6701         addSign(result, MSB32, sign);
6702
6703     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6704     emitcode("rrc","a");
6705     aopPut(AOP(result),"a",MSB24-offl);
6706
6707     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6708     emitcode("rrc","a");
6709     aopPut(AOP(result),"a",MSB16-offl);
6710
6711     if(offl == LSB){
6712         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6713         emitcode("rrc","a");
6714         aopPut(AOP(result),"a",LSB);
6715     }
6716 }
6717
6718 /*-----------------------------------------------------------------*/
6719 /* genrshFour - shift four byte by a known amount != 0             */
6720 /*-----------------------------------------------------------------*/
6721 static void genrshFour (operand *result, operand *left,
6722                         int shCount, int sign)
6723 {
6724     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6725     /* if shifting more that 3 bytes */
6726     if(shCount >= 24 ) {
6727         shCount -= 24;
6728         if(shCount)
6729             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6730         else
6731             movLeft2Result(left, MSB32, result, LSB, sign);
6732         addSign(result, MSB16, sign);
6733     }
6734     else if(shCount >= 16){
6735         shCount -= 16;
6736         if(shCount)
6737             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6738         else{
6739             movLeft2Result(left, MSB24, result, LSB, 0);
6740             movLeft2Result(left, MSB32, result, MSB16, sign);
6741         }
6742         addSign(result, MSB24, sign);
6743     }
6744     else if(shCount >= 8){
6745         shCount -= 8;
6746         if(shCount == 1)
6747             shiftRLong(left, MSB16, result, sign);
6748         else if(shCount == 0){
6749             movLeft2Result(left, MSB16, result, LSB, 0);
6750             movLeft2Result(left, MSB24, result, MSB16, 0);
6751             movLeft2Result(left, MSB32, result, MSB24, sign);
6752             addSign(result, MSB32, sign);
6753         }
6754         else{
6755             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6756             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6757             /* the last shift is signed */
6758             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6759             addSign(result, MSB32, sign);
6760         }
6761     }
6762     else{   /* 1 <= shCount <= 7 */
6763         if(shCount <= 2){
6764             shiftRLong(left, LSB, result, sign);
6765             if(shCount == 2)
6766                 shiftRLong(result, LSB, result, sign);
6767         }
6768         else{
6769             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6770             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6771             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6772         }
6773     }
6774 }
6775
6776 /*-----------------------------------------------------------------*/
6777 /* genRightShiftLiteral - right shifting by known count            */
6778 /*-----------------------------------------------------------------*/
6779 static void genRightShiftLiteral (operand *left,
6780                                   operand *right,
6781                                   operand *result,
6782                                   iCode *ic,
6783                                   int sign)
6784 {    
6785     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6786     int size;
6787
6788     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6789     freeAsmop(right,NULL,ic,TRUE);
6790
6791     aopOp(left,ic,FALSE);
6792     aopOp(result,ic,FALSE);
6793
6794 #if VIEW_SIZE
6795     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6796              AOP_SIZE(left));
6797 #endif
6798
6799     size = getDataSize(left);
6800     /* test the LEFT size !!! */
6801
6802     /* I suppose that the left size >= result size */
6803     if(shCount == 0){
6804         size = getDataSize(result);
6805         while(size--)
6806             movLeft2Result(left, size, result, size, 0);
6807     }
6808
6809     else if(shCount >= (size * 8)){
6810         if(sign)
6811             /* get sign in acc.7 */
6812             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6813         addSign(result, LSB, sign);
6814     } else{
6815         switch (size) {
6816             case 1:
6817                 genrshOne (result,left,shCount,sign);
6818                 break;
6819
6820             case 2:
6821                 genrshTwo (result,left,shCount,sign);
6822                 break;
6823
6824             case 4:
6825                 genrshFour (result,left,shCount,sign);
6826                 break;
6827             default :
6828                 break;
6829         }
6830
6831         freeAsmop(left,NULL,ic,TRUE);
6832         freeAsmop(result,NULL,ic,TRUE);
6833     }
6834 }
6835
6836 /*-----------------------------------------------------------------*/
6837 /* genSignedRightShift - right shift of signed number              */
6838 /*-----------------------------------------------------------------*/
6839 static void genSignedRightShift (iCode *ic)
6840 {
6841     operand *right, *left, *result;
6842     int size, offset;
6843     char *l;
6844     symbol *tlbl, *tlbl1 ;
6845
6846     /* we do it the hard way put the shift count in b
6847     and loop thru preserving the sign */
6848     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6849
6850     right = IC_RIGHT(ic);
6851     left  = IC_LEFT(ic);
6852     result = IC_RESULT(ic);
6853
6854     aopOp(right,ic,FALSE);  
6855
6856
6857     if ( AOP_TYPE(right) == AOP_LIT) {
6858         genRightShiftLiteral (left,right,result,ic,1);
6859         return ;
6860     }
6861         /* shift count is unknown then we have to form 
6862        a loop get the loop count in B : Note: we take
6863        only the lower order byte since shifting
6864        more that 32 bits make no sense anyway, ( the
6865        largest size of an object can be only 32 bits ) */  
6866
6867     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6868     emitcode("inc","b");
6869     freeAsmop (right,NULL,ic,TRUE);
6870     aopOp(left,ic,FALSE);
6871     aopOp(result,ic,FALSE);
6872
6873     /* now move the left to the result if they are not the
6874     same */
6875     if (!sameRegs(AOP(left),AOP(result)) && 
6876         AOP_SIZE(result) > 1) {
6877
6878         size = AOP_SIZE(result);
6879         offset=0;
6880         while (size--) {
6881             l = aopGet(AOP(left),offset,FALSE,TRUE);
6882             if (*l == '@' && IS_AOP_PREG(result)) {
6883
6884                 emitcode("mov","a,%s",l);
6885                 aopPut(AOP(result),"a",offset);
6886             } else
6887                 aopPut(AOP(result),l,offset);
6888             offset++;
6889         }
6890     }
6891
6892     /* mov the highest order bit to OVR */    
6893     tlbl = newiTempLabel(NULL);
6894     tlbl1= newiTempLabel(NULL);
6895
6896     size = AOP_SIZE(result);
6897     offset = size - 1;
6898     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6899     emitcode("rlc","a");
6900     emitcode("mov","ov,c");
6901     /* if it is only one byte then */
6902     if (size == 1) {
6903         l = aopGet(AOP(left),0,FALSE,FALSE);
6904         MOVA(l);
6905         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6906         emitcode("","%05d_DS_:",tlbl->key+100);
6907         emitcode("mov","c,ov");
6908         emitcode("rrc","a");
6909         emitcode("","%05d_DS_:",tlbl1->key+100);
6910         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6911         aopPut(AOP(result),"a",0);
6912         goto release ;
6913     }
6914
6915     reAdjustPreg(AOP(result));
6916     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6917     emitcode("","%05d_DS_:",tlbl->key+100);    
6918     emitcode("mov","c,ov");
6919     while (size--) {
6920         l = aopGet(AOP(result),offset,FALSE,FALSE);
6921         MOVA(l);
6922         emitcode("rrc","a");         
6923         aopPut(AOP(result),"a",offset--);
6924     }
6925     reAdjustPreg(AOP(result));
6926     emitcode("","%05d_DS_:",tlbl1->key+100);
6927     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6928
6929 release:
6930     freeAsmop(left,NULL,ic,TRUE);
6931     freeAsmop(result,NULL,ic,TRUE);
6932 }
6933
6934 /*-----------------------------------------------------------------*/
6935 /* genRightShift - generate code for right shifting                */
6936 /*-----------------------------------------------------------------*/
6937 static void genRightShift (iCode *ic)
6938 {
6939     operand *right, *left, *result;
6940     sym_link *retype ;
6941     int size, offset;
6942     char *l;
6943     symbol *tlbl, *tlbl1 ;
6944
6945     /* if signed then we do it the hard way preserve the
6946     sign bit moving it inwards */
6947     retype = getSpec(operandType(IC_RESULT(ic)));
6948     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6949
6950     if (!SPEC_USIGN(retype)) {
6951         genSignedRightShift (ic);
6952         return ;
6953     }
6954
6955     /* signed & unsigned types are treated the same : i.e. the
6956     signed is NOT propagated inwards : quoting from the
6957     ANSI - standard : "for E1 >> E2, is equivalent to division
6958     by 2**E2 if unsigned or if it has a non-negative value,
6959     otherwise the result is implementation defined ", MY definition
6960     is that the sign does not get propagated */
6961
6962     right = IC_RIGHT(ic);
6963     left  = IC_LEFT(ic);
6964     result = IC_RESULT(ic);
6965
6966     aopOp(right,ic,FALSE);
6967
6968     /* if the shift count is known then do it 
6969     as efficiently as possible */
6970     if (AOP_TYPE(right) == AOP_LIT) {
6971         genRightShiftLiteral (left,right,result,ic, 0);
6972         return ;
6973     }
6974
6975     /* shift count is unknown then we have to form 
6976     a loop get the loop count in B : Note: we take
6977     only the lower order byte since shifting
6978     more that 32 bits make no sense anyway, ( the
6979     largest size of an object can be only 32 bits ) */  
6980
6981     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6982     emitcode("inc","b");
6983     freeAsmop (right,NULL,ic,TRUE);
6984     aopOp(left,ic,FALSE);
6985     aopOp(result,ic,FALSE);
6986
6987     /* now move the left to the result if they are not the
6988     same */
6989     if (!sameRegs(AOP(left),AOP(result)) && 
6990         AOP_SIZE(result) > 1) {
6991
6992         size = AOP_SIZE(result);
6993         offset=0;
6994         while (size--) {
6995             l = aopGet(AOP(left),offset,FALSE,TRUE);
6996             if (*l == '@' && IS_AOP_PREG(result)) {
6997
6998                 emitcode("mov","a,%s",l);
6999                 aopPut(AOP(result),"a",offset);
7000             } else
7001                 aopPut(AOP(result),l,offset);
7002             offset++;
7003         }
7004     }
7005
7006     tlbl = newiTempLabel(NULL);
7007     tlbl1= newiTempLabel(NULL);
7008     size = AOP_SIZE(result);
7009     offset = size - 1;
7010
7011     /* if it is only one byte then */
7012     if (size == 1) {
7013         l = aopGet(AOP(left),0,FALSE,FALSE);
7014         MOVA(l);
7015         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7016         emitcode("","%05d_DS_:",tlbl->key+100);
7017         CLRC;
7018         emitcode("rrc","a");
7019         emitcode("","%05d_DS_:",tlbl1->key+100);
7020         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7021         aopPut(AOP(result),"a",0);
7022         goto release ;
7023     }
7024
7025     reAdjustPreg(AOP(result));
7026     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7027     emitcode("","%05d_DS_:",tlbl->key+100);    
7028     CLRC;
7029     while (size--) {
7030         l = aopGet(AOP(result),offset,FALSE,FALSE);
7031         MOVA(l);
7032         emitcode("rrc","a");         
7033         aopPut(AOP(result),"a",offset--);
7034     }
7035     reAdjustPreg(AOP(result));
7036
7037     emitcode("","%05d_DS_:",tlbl1->key+100);
7038     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7039
7040 release:
7041     freeAsmop(left,NULL,ic,TRUE);
7042     freeAsmop(result,NULL,ic,TRUE);
7043 }
7044
7045 /*-----------------------------------------------------------------*/
7046 /* genUnpackBits - generates code for unpacking bits               */
7047 /*-----------------------------------------------------------------*/
7048 static void genUnpackBits (operand *result, char *rname, int ptype)
7049 {    
7050     int shCnt ;
7051     int rlen = 0 ;
7052     sym_link *etype;
7053     int offset = 0 ;
7054
7055     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7056     etype = getSpec(operandType(result));
7057
7058     /* read the first byte  */
7059     switch (ptype) {
7060
7061     case POINTER:
7062     case IPOINTER:
7063         emitcode("mov","a,@%s",rname);
7064         break;
7065         
7066     case PPOINTER:
7067         emitcode("movx","a,@%s",rname);
7068         break;
7069         
7070     case FPOINTER:
7071         emitcode("movx","a,@dptr");
7072         break;
7073
7074     case CPOINTER:
7075         emitcode("clr","a");
7076         emitcode("movc","a","@a+dptr");
7077         break;
7078
7079     case GPOINTER:
7080         emitcode("lcall","__gptrget");
7081         break;
7082     }
7083
7084     /* if we have bitdisplacement then it fits   */
7085     /* into this byte completely or if length is */
7086     /* less than a byte                          */
7087     if ((shCnt = SPEC_BSTR(etype)) || 
7088         (SPEC_BLEN(etype) <= 8))  {
7089
7090         /* shift right acc */
7091         AccRsh(shCnt);
7092
7093         emitcode("anl","a,#0x%02x",
7094                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7095         aopPut(AOP(result),"a",offset);
7096         return ;
7097     }
7098
7099     /* bit field did not fit in a byte  */
7100     rlen = SPEC_BLEN(etype) - 8;
7101     aopPut(AOP(result),"a",offset++);
7102
7103     while (1)  {
7104
7105         switch (ptype) {
7106         case POINTER:
7107         case IPOINTER:
7108             emitcode("inc","%s",rname);
7109             emitcode("mov","a,@%s",rname);
7110             break;
7111             
7112         case PPOINTER:
7113             emitcode("inc","%s",rname);
7114             emitcode("movx","a,@%s",rname);
7115             break;
7116
7117         case FPOINTER:
7118             emitcode("inc","dptr");
7119             emitcode("movx","a,@dptr");
7120             break;
7121             
7122         case CPOINTER:
7123             emitcode("clr","a");
7124             emitcode("inc","dptr");
7125             emitcode("movc","a","@a+dptr");
7126             break;
7127             
7128         case GPOINTER:
7129             emitcode("inc","dptr");
7130             emitcode("lcall","__gptrget");
7131             break;
7132         }
7133
7134         rlen -= 8;            
7135         /* if we are done */
7136         if ( rlen <= 0 )
7137             break ;
7138         
7139         aopPut(AOP(result),"a",offset++);
7140                               
7141     }
7142     
7143     if (rlen) {
7144         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7145         aopPut(AOP(result),"a",offset);        
7146     }
7147     
7148     return ;
7149 }
7150
7151
7152 /*-----------------------------------------------------------------*/
7153 /* genDataPointerGet - generates code when ptr offset is known     */
7154 /*-----------------------------------------------------------------*/
7155 static void genDataPointerGet (operand *left, 
7156                                operand *result, 
7157                                iCode *ic)
7158 {
7159     char *l;
7160     char buffer[256];
7161     int size , offset = 0;
7162     aopOp(result,ic,TRUE);
7163
7164     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7165
7166     /* get the string representation of the name */
7167     l = aopGet(AOP(left),0,FALSE,TRUE);
7168     size = AOP_SIZE(result);
7169     // tsd, was l+1 - the underline `_' prefix was being stripped
7170     while (size--) {
7171         if (offset)
7172             sprintf(buffer,"(%s + %d)",l,offset);
7173         else
7174             sprintf(buffer,"%s",l);
7175         aopPut(AOP(result),buffer,offset++);
7176     }
7177
7178     freeAsmop(left,NULL,ic,TRUE);
7179     freeAsmop(result,NULL,ic,TRUE);
7180 }
7181
7182 /*-----------------------------------------------------------------*/
7183 /* genNearPointerGet - emitcode for near pointer fetch             */
7184 /*-----------------------------------------------------------------*/
7185 static void genNearPointerGet (operand *left, 
7186                                operand *result, 
7187                                iCode *ic)
7188 {
7189     asmop *aop = NULL;
7190     regs *preg = NULL ;
7191     char *rname ;
7192     sym_link *rtype, *retype;
7193     sym_link *ltype = operandType(left);    
7194     char buffer[80];
7195
7196     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7197
7198     rtype = operandType(result);
7199     retype= getSpec(rtype);
7200     
7201     aopOp(left,ic,FALSE);
7202     
7203     /* if left is rematerialisable and
7204        result is not bit variable type and
7205        the left is pointer to data space i.e
7206        lower 128 bytes of space */
7207     if (AOP_TYPE(left) == AOP_IMMD &&
7208         !IS_BITVAR(retype)         &&
7209         DCL_TYPE(ltype) == POINTER) {
7210         genDataPointerGet (left,result,ic);
7211         return ;
7212     }
7213     
7214         /* if the value is already in a pointer register
7215        then don't need anything more */
7216     if (!AOP_INPREG(AOP(left))) {
7217         /* otherwise get a free pointer register */
7218         aop = newAsmop(0);
7219         preg = getFreePtr(ic,&aop,FALSE);
7220         emitcode("mov","%s,%s",
7221                 preg->name,
7222                 aopGet(AOP(left),0,FALSE,TRUE));
7223         rname = preg->name ;
7224     } else
7225         rname = aopGet(AOP(left),0,FALSE,FALSE);
7226     
7227     freeAsmop(left,NULL,ic,TRUE);
7228     aopOp (result,ic,FALSE);
7229     
7230       /* if bitfield then unpack the bits */
7231     if (IS_BITVAR(retype)) 
7232         genUnpackBits (result,rname,POINTER);
7233     else {
7234         /* we have can just get the values */
7235         int size = AOP_SIZE(result);
7236         int offset = 0 ;        
7237         
7238         while (size--) {
7239             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7240
7241                 emitcode("mov","a,@%s",rname);
7242                 aopPut(AOP(result),"a",offset);
7243             } else {
7244                 sprintf(buffer,"@%s",rname);
7245                 aopPut(AOP(result),buffer,offset);
7246             }
7247             offset++ ;
7248             if (size)
7249                 emitcode("inc","%s",rname);
7250         }
7251     }
7252
7253     /* now some housekeeping stuff */
7254     if (aop) {
7255         /* we had to allocate for this iCode */
7256         freeAsmop(NULL,aop,ic,TRUE);
7257     } else { 
7258         /* we did not allocate which means left
7259            already in a pointer register, then
7260            if size > 0 && this could be used again
7261            we have to point it back to where it 
7262            belongs */
7263         if (AOP_SIZE(result) > 1 &&
7264             !OP_SYMBOL(left)->remat &&
7265             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7266               ic->depth )) {
7267             int size = AOP_SIZE(result) - 1;
7268             while (size--)
7269                 emitcode("dec","%s",rname);
7270         }
7271     }
7272
7273     /* done */
7274     freeAsmop(result,NULL,ic,TRUE);
7275      
7276 }
7277
7278 /*-----------------------------------------------------------------*/
7279 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7280 /*-----------------------------------------------------------------*/
7281 static void genPagedPointerGet (operand *left, 
7282                                operand *result, 
7283                                iCode *ic)
7284 {
7285     asmop *aop = NULL;
7286     regs *preg = NULL ;
7287     char *rname ;
7288     sym_link *rtype, *retype;    
7289
7290     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7291
7292     rtype = operandType(result);
7293     retype= getSpec(rtype);
7294     
7295     aopOp(left,ic,FALSE);
7296
7297   /* if the value is already in a pointer register
7298        then don't need anything more */
7299     if (!AOP_INPREG(AOP(left))) {
7300         /* otherwise get a free pointer register */
7301         aop = newAsmop(0);
7302         preg = getFreePtr(ic,&aop,FALSE);
7303         emitcode("mov","%s,%s",
7304                 preg->name,
7305                 aopGet(AOP(left),0,FALSE,TRUE));
7306         rname = preg->name ;
7307     } else
7308         rname = aopGet(AOP(left),0,FALSE,FALSE);
7309     
7310     freeAsmop(left,NULL,ic,TRUE);
7311     aopOp (result,ic,FALSE);
7312
7313     /* if bitfield then unpack the bits */
7314     if (IS_BITVAR(retype)) 
7315         genUnpackBits (result,rname,PPOINTER);
7316     else {
7317         /* we have can just get the values */
7318         int size = AOP_SIZE(result);
7319         int offset = 0 ;        
7320         
7321         while (size--) {
7322             
7323             emitcode("movx","a,@%s",rname);
7324             aopPut(AOP(result),"a",offset);
7325             
7326             offset++ ;
7327             
7328             if (size)
7329                 emitcode("inc","%s",rname);
7330         }
7331     }
7332
7333     /* now some housekeeping stuff */
7334     if (aop) {
7335         /* we had to allocate for this iCode */
7336         freeAsmop(NULL,aop,ic,TRUE);
7337     } else { 
7338         /* we did not allocate which means left
7339            already in a pointer register, then
7340            if size > 0 && this could be used again
7341            we have to point it back to where it 
7342            belongs */
7343         if (AOP_SIZE(result) > 1 &&
7344             !OP_SYMBOL(left)->remat &&
7345             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7346               ic->depth )) {
7347             int size = AOP_SIZE(result) - 1;
7348             while (size--)
7349                 emitcode("dec","%s",rname);
7350         }
7351     }
7352
7353     /* done */
7354     freeAsmop(result,NULL,ic,TRUE);
7355     
7356         
7357 }
7358
7359 /*-----------------------------------------------------------------*/
7360 /* genFarPointerGet - gget value from far space                    */
7361 /*-----------------------------------------------------------------*/
7362 static void genFarPointerGet (operand *left,
7363                               operand *result, iCode *ic)
7364 {
7365     int size, offset ;
7366     sym_link *retype = getSpec(operandType(result));
7367
7368     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7369
7370     aopOp(left,ic,FALSE);
7371
7372     /* if the operand is already in dptr 
7373     then we do nothing else we move the value to dptr */
7374     if (AOP_TYPE(left) != AOP_STR) {
7375         /* if this is remateriazable */
7376         if (AOP_TYPE(left) == AOP_IMMD)
7377             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7378         else { /* we need to get it byte by byte */
7379             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7380             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7381             if (options.model == MODEL_FLAT24)
7382             {
7383                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7384             }
7385         }
7386     }
7387     /* so dptr know contains the address */
7388     freeAsmop(left,NULL,ic,TRUE);
7389     aopOp(result,ic,FALSE);
7390
7391     /* if bit then unpack */
7392     if (IS_BITVAR(retype)) 
7393         genUnpackBits(result,"dptr",FPOINTER);
7394     else {
7395         size = AOP_SIZE(result);
7396         offset = 0 ;
7397
7398         while (size--) {
7399             emitcode("movx","a,@dptr");
7400             aopPut(AOP(result),"a",offset++);
7401             if (size)
7402                 emitcode("inc","dptr");
7403         }
7404     }
7405
7406     freeAsmop(result,NULL,ic,TRUE);
7407 }
7408
7409 /*-----------------------------------------------------------------*/
7410 /* emitcodePointerGet - gget value from code space                  */
7411 /*-----------------------------------------------------------------*/
7412 static void emitcodePointerGet (operand *left,
7413                                 operand *result, iCode *ic)
7414 {
7415     int size, offset ;
7416     sym_link *retype = getSpec(operandType(result));
7417
7418     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7419
7420     aopOp(left,ic,FALSE);
7421
7422     /* if the operand is already in dptr 
7423     then we do nothing else we move the value to dptr */
7424     if (AOP_TYPE(left) != AOP_STR) {
7425         /* if this is remateriazable */
7426         if (AOP_TYPE(left) == AOP_IMMD)
7427             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7428         else { /* we need to get it byte by byte */
7429             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7430             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7431             if (options.model == MODEL_FLAT24)
7432             {
7433                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7434             }
7435         }
7436     }
7437     /* so dptr know contains the address */
7438     freeAsmop(left,NULL,ic,TRUE);
7439     aopOp(result,ic,FALSE);
7440
7441     /* if bit then unpack */
7442     if (IS_BITVAR(retype)) 
7443         genUnpackBits(result,"dptr",CPOINTER);
7444     else {
7445         size = AOP_SIZE(result);
7446         offset = 0 ;
7447
7448         while (size--) {
7449             emitcode("clr","a");
7450             emitcode("movc","a,@a+dptr");
7451             aopPut(AOP(result),"a",offset++);
7452             if (size)
7453                 emitcode("inc","dptr");
7454         }
7455     }
7456
7457     freeAsmop(result,NULL,ic,TRUE);
7458 }
7459
7460 /*-----------------------------------------------------------------*/
7461 /* genGenPointerGet - gget value from generic pointer space        */
7462 /*-----------------------------------------------------------------*/
7463 static void genGenPointerGet (operand *left,
7464                               operand *result, iCode *ic)
7465 {
7466     int size, offset ;
7467     sym_link *retype = getSpec(operandType(result));
7468
7469     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7470     aopOp(left,ic,FALSE);
7471
7472     /* if the operand is already in dptr 
7473     then we do nothing else we move the value to dptr */
7474     if (AOP_TYPE(left) != AOP_STR) {
7475         /* if this is remateriazable */
7476         if (AOP_TYPE(left) == AOP_IMMD) {
7477             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7478             emitcode("mov","b,#%d",pointerCode(retype));
7479         }
7480         else { /* we need to get it byte by byte */
7481           
7482           emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7483           emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7484           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7485           emitcode("movwf","FSR");
7486           /*
7487             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7488             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7489             if (options.model == MODEL_FLAT24)
7490             {
7491                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7492                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7493             }
7494             else
7495             {
7496                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7497             }
7498           */
7499         }
7500     }
7501     /* so dptr know contains the address */
7502     freeAsmop(left,NULL,ic,TRUE);
7503     aopOp(result,ic,FALSE); 
7504
7505     /* if bit then unpack */
7506     if (IS_BITVAR(retype)) 
7507         genUnpackBits(result,"dptr",GPOINTER);
7508     else {
7509         size = AOP_SIZE(result);
7510         offset = 0 ;
7511
7512         while (size--) {
7513           emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7514           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7515           if(size)
7516             emitpcode(POC_INCF,popCopy(&pc_fsr));
7517 /*
7518           emitcode("movf","indf,w");
7519           emitcode("movwf","%s",
7520                    aopGet(AOP(result),offset++,FALSE,FALSE));
7521           if (size)
7522             emitcode("incf","fsr,f");
7523 */
7524         }
7525     }
7526
7527     freeAsmop(result,NULL,ic,TRUE);
7528 }
7529
7530 /*-----------------------------------------------------------------*/
7531 /* genPointerGet - generate code for pointer get                   */
7532 /*-----------------------------------------------------------------*/
7533 static void genPointerGet (iCode *ic)
7534 {
7535     operand *left, *result ;
7536     sym_link *type, *etype;
7537     int p_type;
7538
7539     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7540
7541     left = IC_LEFT(ic);
7542     result = IC_RESULT(ic) ;
7543
7544     /* depending on the type of pointer we need to
7545     move it to the correct pointer register */
7546     type = operandType(left);
7547     etype = getSpec(type);
7548     /* if left is of type of pointer then it is simple */
7549     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7550         p_type = DCL_TYPE(type);
7551     else {
7552         /* we have to go by the storage class */
7553         p_type = PTR_TYPE(SPEC_OCLS(etype));
7554
7555 /*      if (SPEC_OCLS(etype)->codesp ) { */
7556 /*          p_type = CPOINTER ;  */
7557 /*      } */
7558 /*      else */
7559 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7560 /*              p_type = FPOINTER ; */
7561 /*          else */
7562 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7563 /*                  p_type = PPOINTER; */
7564 /*              else */
7565 /*                  if (SPEC_OCLS(etype) == idata ) */
7566 /*                      p_type = IPOINTER; */
7567 /*                  else */
7568 /*                      p_type = POINTER ; */
7569     }
7570
7571     /* now that we have the pointer type we assign
7572     the pointer values */
7573     switch (p_type) {
7574
7575     case POINTER:       
7576     case IPOINTER:
7577         genNearPointerGet (left,result,ic);
7578         break;
7579
7580     case PPOINTER:
7581         genPagedPointerGet(left,result,ic);
7582         break;
7583
7584     case FPOINTER:
7585         genFarPointerGet (left,result,ic);
7586         break;
7587
7588     case CPOINTER:
7589         emitcodePointerGet (left,result,ic);
7590         break;
7591
7592     case GPOINTER:
7593         genGenPointerGet (left,result,ic);
7594         break;
7595     }
7596
7597 }
7598
7599 /*-----------------------------------------------------------------*/
7600 /* genPackBits - generates code for packed bit storage             */
7601 /*-----------------------------------------------------------------*/
7602 static void genPackBits (sym_link    *etype ,
7603                          operand *right ,
7604                          char *rname, int p_type)
7605 {
7606     int shCount = 0 ;
7607     int offset = 0  ;
7608     int rLen = 0 ;
7609     int blen, bstr ;   
7610     char *l ;
7611
7612     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7613     blen = SPEC_BLEN(etype);
7614     bstr = SPEC_BSTR(etype);
7615
7616     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7617     MOVA(l);   
7618
7619     /* if the bit lenth is less than or    */
7620     /* it exactly fits a byte then         */
7621     if (SPEC_BLEN(etype) <= 8 )  {
7622         shCount = SPEC_BSTR(etype) ;
7623
7624         /* shift left acc */
7625         AccLsh(shCount);
7626
7627         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7628
7629
7630             switch (p_type) {
7631                 case POINTER:
7632                     emitcode ("mov","b,a");
7633                     emitcode("mov","a,@%s",rname);
7634                     break;
7635
7636                 case FPOINTER:
7637                     emitcode ("mov","b,a");
7638                     emitcode("movx","a,@dptr");
7639                     break;
7640
7641                 case GPOINTER:
7642                     emitcode ("push","b");
7643                     emitcode ("push","acc");
7644                     emitcode ("lcall","__gptrget");
7645                     emitcode ("pop","b");
7646                     break;
7647             }
7648
7649             emitcode ("anl","a,#0x%02x",(unsigned char)
7650                       ((unsigned char)(0xFF << (blen+bstr)) | 
7651                        (unsigned char)(0xFF >> (8-bstr)) ) );
7652             emitcode ("orl","a,b");
7653             if (p_type == GPOINTER)
7654                 emitcode("pop","b");
7655         }
7656     }
7657
7658     switch (p_type) {
7659         case POINTER:
7660             emitcode("mov","@%s,a",rname);
7661             break;
7662
7663         case FPOINTER:
7664             emitcode("movx","@dptr,a");
7665             break;
7666
7667         case GPOINTER:
7668             DEBUGemitcode(";lcall","__gptrput");
7669             break;
7670     }
7671
7672     /* if we r done */
7673     if ( SPEC_BLEN(etype) <= 8 )
7674         return ;
7675
7676     emitcode("inc","%s",rname);
7677     rLen = SPEC_BLEN(etype) ;     
7678
7679     /* now generate for lengths greater than one byte */
7680     while (1) {
7681
7682         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7683
7684         rLen -= 8 ;
7685         if (rLen <= 0 )
7686             break ;
7687
7688         switch (p_type) {
7689             case POINTER:
7690                 if (*l == '@') {
7691                     MOVA(l);
7692                     emitcode("mov","@%s,a",rname);
7693                 } else
7694                     emitcode("mov","@%s,%s",rname,l);
7695                 break;
7696
7697             case FPOINTER:
7698                 MOVA(l);
7699                 emitcode("movx","@dptr,a");
7700                 break;
7701
7702             case GPOINTER:
7703                 MOVA(l);
7704                 DEBUGemitcode(";lcall","__gptrput");
7705                 break;  
7706         }   
7707         emitcode ("inc","%s",rname);
7708     }
7709
7710     MOVA(l);
7711
7712     /* last last was not complete */
7713     if (rLen)   {
7714         /* save the byte & read byte */
7715         switch (p_type) {
7716             case POINTER:
7717                 emitcode ("mov","b,a");
7718                 emitcode("mov","a,@%s",rname);
7719                 break;
7720
7721             case FPOINTER:
7722                 emitcode ("mov","b,a");
7723                 emitcode("movx","a,@dptr");
7724                 break;
7725
7726             case GPOINTER:
7727                 emitcode ("push","b");
7728                 emitcode ("push","acc");
7729                 emitcode ("lcall","__gptrget");
7730                 emitcode ("pop","b");
7731                 break;
7732         }
7733
7734         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7735         emitcode ("orl","a,b");
7736     }
7737
7738     if (p_type == GPOINTER)
7739         emitcode("pop","b");
7740
7741     switch (p_type) {
7742
7743     case POINTER:
7744         emitcode("mov","@%s,a",rname);
7745         break;
7746         
7747     case FPOINTER:
7748         emitcode("movx","@dptr,a");
7749         break;
7750         
7751     case GPOINTER:
7752         DEBUGemitcode(";lcall","__gptrput");
7753         break;                  
7754     }
7755 }
7756 /*-----------------------------------------------------------------*/
7757 /* genDataPointerSet - remat pointer to data space                 */
7758 /*-----------------------------------------------------------------*/
7759 static void genDataPointerSet(operand *right,
7760                               operand *result,
7761                               iCode *ic)
7762 {
7763     int size, offset = 0 ;
7764     char *l, buffer[256];
7765
7766     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7767     aopOp(right,ic,FALSE);
7768     
7769     l = aopGet(AOP(result),0,FALSE,TRUE);
7770     size = AOP_SIZE(right);
7771     // tsd, was l+1 - the underline `_' prefix was being stripped
7772     while (size--) {
7773         if (offset)
7774             sprintf(buffer,"(%s + %d)",l,offset);
7775         else
7776             sprintf(buffer,"%s",l);
7777
7778         if (AOP_TYPE(right) == AOP_LIT) {
7779           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7780           lit = lit >> (8*offset);
7781           if(lit) {
7782             emitcode("movlw","%s",lit);
7783             emitcode("movwf","%s",buffer);
7784           } else 
7785             emitcode("clrf","%s",buffer);
7786         }else {
7787           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7788           emitcode("movwf","%s",buffer);
7789         }
7790
7791         offset++;
7792     }
7793
7794     freeAsmop(right,NULL,ic,TRUE);
7795     freeAsmop(result,NULL,ic,TRUE);
7796 }
7797
7798 /*-----------------------------------------------------------------*/
7799 /* genNearPointerSet - emitcode for near pointer put                */
7800 /*-----------------------------------------------------------------*/
7801 static void genNearPointerSet (operand *right,
7802                                operand *result, 
7803                                iCode *ic)
7804 {
7805     asmop *aop = NULL;
7806     char *l;
7807     sym_link *retype;
7808     sym_link *ptype = operandType(result);
7809
7810     
7811     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7812     retype= getSpec(operandType(right));
7813
7814     aopOp(result,ic,FALSE);
7815     
7816     /* if the result is rematerializable &
7817        in data space & not a bit variable */
7818     if (AOP_TYPE(result) == AOP_IMMD &&
7819         DCL_TYPE(ptype) == POINTER   &&
7820         !IS_BITVAR(retype)) {
7821         genDataPointerSet (right,result,ic);
7822         return;
7823     }
7824
7825     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7826
7827     /* if the value is already in a pointer register
7828     then don't need anything more */
7829     if (!AOP_INPREG(AOP(result))) {
7830         /* otherwise get a free pointer register */
7831         //aop = newAsmop(0);
7832         //preg = getFreePtr(ic,&aop,FALSE);
7833         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7834         //emitcode("mov","%s,%s",
7835         //         preg->name,
7836         //         aopGet(AOP(result),0,FALSE,TRUE));
7837         //rname = preg->name ;
7838         emitcode("movwf","fsr");
7839     }// else
7840     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7841
7842     freeAsmop(result,NULL,ic,TRUE);
7843     aopOp (right,ic,FALSE);
7844     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7845
7846     /* if bitfield then unpack the bits */
7847     if (IS_BITVAR(retype)) {
7848       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7849              "The programmer is obviously confused");
7850       //genPackBits (retype,right,rname,POINTER);
7851       exit(1);
7852     }
7853     else {
7854         /* we have can just get the values */
7855         int size = AOP_SIZE(right);
7856         int offset = 0 ;    
7857
7858     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7859         while (size--) {
7860             l = aopGet(AOP(right),offset,FALSE,TRUE);
7861             if (*l == '@' ) {
7862               //MOVA(l);
7863               //emitcode("mov","@%s,a",rname);
7864               emitcode("movf","indf,w ;1");
7865             } else {
7866
7867               if (AOP_TYPE(right) == AOP_LIT) {
7868                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7869                 if(lit) {
7870                   emitcode("movlw","%s",l);
7871                   emitcode("movwf","indf ;2");
7872                 } else 
7873                   emitcode("clrf","indf");
7874               }else {
7875                 emitcode("movf","%s,w",l);
7876                 emitcode("movwf","indf ;2");
7877               }
7878             //emitcode("mov","@%s,%s",rname,l);
7879             }
7880             if (size)
7881               emitcode("incf","fsr,f ;3");
7882             //emitcode("inc","%s",rname);
7883             offset++;
7884         }
7885     }
7886
7887     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7888     /* now some housekeeping stuff */
7889     if (aop) {
7890         /* we had to allocate for this iCode */
7891         freeAsmop(NULL,aop,ic,TRUE);
7892     } else { 
7893         /* we did not allocate which means left
7894         already in a pointer register, then
7895         if size > 0 && this could be used again
7896         we have to point it back to where it 
7897         belongs */
7898     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7899         if (AOP_SIZE(right) > 1 &&
7900             !OP_SYMBOL(result)->remat &&
7901             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7902               ic->depth )) {
7903             int size = AOP_SIZE(right) - 1;
7904             while (size--)
7905               emitcode("decf","fsr,f");
7906               //emitcode("dec","%s",rname);
7907         }
7908     }
7909
7910     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7911     /* done */
7912     freeAsmop(right,NULL,ic,TRUE);
7913
7914
7915 }
7916
7917 /*-----------------------------------------------------------------*/
7918 /* genPagedPointerSet - emitcode for Paged pointer put             */
7919 /*-----------------------------------------------------------------*/
7920 static void genPagedPointerSet (operand *right,
7921                                operand *result, 
7922                                iCode *ic)
7923 {
7924     asmop *aop = NULL;
7925     regs *preg = NULL ;
7926     char *rname , *l;
7927     sym_link *retype;
7928        
7929     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7930
7931     retype= getSpec(operandType(right));
7932     
7933     aopOp(result,ic,FALSE);
7934     
7935     /* if the value is already in a pointer register
7936        then don't need anything more */
7937     if (!AOP_INPREG(AOP(result))) {
7938         /* otherwise get a free pointer register */
7939         aop = newAsmop(0);
7940         preg = getFreePtr(ic,&aop,FALSE);
7941         emitcode("mov","%s,%s",
7942                 preg->name,
7943                 aopGet(AOP(result),0,FALSE,TRUE));
7944         rname = preg->name ;
7945     } else
7946         rname = aopGet(AOP(result),0,FALSE,FALSE);
7947     
7948     freeAsmop(result,NULL,ic,TRUE);
7949     aopOp (right,ic,FALSE);
7950
7951     /* if bitfield then unpack the bits */
7952     if (IS_BITVAR(retype)) 
7953         genPackBits (retype,right,rname,PPOINTER);
7954     else {
7955         /* we have can just get the values */
7956         int size = AOP_SIZE(right);
7957         int offset = 0 ;        
7958         
7959         while (size--) {
7960             l = aopGet(AOP(right),offset,FALSE,TRUE);
7961             
7962             MOVA(l);
7963             emitcode("movx","@%s,a",rname);
7964
7965             if (size)
7966                 emitcode("inc","%s",rname);
7967
7968             offset++;
7969         }
7970     }
7971     
7972     /* now some housekeeping stuff */
7973     if (aop) {
7974         /* we had to allocate for this iCode */
7975         freeAsmop(NULL,aop,ic,TRUE);
7976     } else { 
7977         /* we did not allocate which means left
7978            already in a pointer register, then
7979            if size > 0 && this could be used again
7980            we have to point it back to where it 
7981            belongs */
7982         if (AOP_SIZE(right) > 1 &&
7983             !OP_SYMBOL(result)->remat &&
7984             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7985               ic->depth )) {
7986             int size = AOP_SIZE(right) - 1;
7987             while (size--)
7988                 emitcode("dec","%s",rname);
7989         }
7990     }
7991
7992     /* done */
7993     freeAsmop(right,NULL,ic,TRUE);
7994     
7995         
7996 }
7997
7998 /*-----------------------------------------------------------------*/
7999 /* genFarPointerSet - set value from far space                     */
8000 /*-----------------------------------------------------------------*/
8001 static void genFarPointerSet (operand *right,
8002                               operand *result, iCode *ic)
8003 {
8004     int size, offset ;
8005     sym_link *retype = getSpec(operandType(right));
8006
8007     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8008     aopOp(result,ic,FALSE);
8009
8010     /* if the operand is already in dptr 
8011     then we do nothing else we move the value to dptr */
8012     if (AOP_TYPE(result) != AOP_STR) {
8013         /* if this is remateriazable */
8014         if (AOP_TYPE(result) == AOP_IMMD)
8015             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8016         else { /* we need to get it byte by byte */
8017             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8018             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8019             if (options.model == MODEL_FLAT24)
8020             {
8021                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8022             }
8023         }
8024     }
8025     /* so dptr know contains the address */
8026     freeAsmop(result,NULL,ic,TRUE);
8027     aopOp(right,ic,FALSE);
8028
8029     /* if bit then unpack */
8030     if (IS_BITVAR(retype)) 
8031         genPackBits(retype,right,"dptr",FPOINTER);
8032     else {
8033         size = AOP_SIZE(right);
8034         offset = 0 ;
8035
8036         while (size--) {
8037             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8038             MOVA(l);
8039             emitcode("movx","@dptr,a");
8040             if (size)
8041                 emitcode("inc","dptr");
8042         }
8043     }
8044
8045     freeAsmop(right,NULL,ic,TRUE);
8046 }
8047
8048 /*-----------------------------------------------------------------*/
8049 /* genGenPointerSet - set value from generic pointer space         */
8050 /*-----------------------------------------------------------------*/
8051 static void genGenPointerSet (operand *right,
8052                               operand *result, iCode *ic)
8053 {
8054     int size, offset ;
8055     sym_link *retype = getSpec(operandType(right));
8056
8057     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8058
8059     aopOp(result,ic,FALSE);
8060
8061     /* if the operand is already in dptr 
8062     then we do nothing else we move the value to dptr */
8063     if (AOP_TYPE(result) != AOP_STR) {
8064         /* if this is remateriazable */
8065         if (AOP_TYPE(result) == AOP_IMMD) {
8066             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8067             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8068         }
8069         else { /* we need to get it byte by byte */
8070           char *l = aopGet(AOP(result),0,FALSE,FALSE);
8071
8072           if(strcmp("FSR",l))
8073             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8074           emitpcode(POC_MOVWF,popCopy(&pc_indf));
8075
8076           if(strcmp("FSR",l))
8077             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8078
8079           emitcode("movwf","INDF");
8080         }
8081     }
8082     /* so dptr know contains the address */
8083     freeAsmop(result,NULL,ic,TRUE);
8084     aopOp(right,ic,FALSE);
8085
8086     /* if bit then unpack */
8087     if (IS_BITVAR(retype)) 
8088         genPackBits(retype,right,"dptr",GPOINTER);
8089     else {
8090         size = AOP_SIZE(right);
8091         offset = 0 ;
8092
8093         while (--size) {
8094             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8095             if(size)
8096               emitcode("incf","fsr,f");
8097             emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8098             emitcode("movwf","indf");
8099             //MOVA(l);
8100             //DEBUGemitcode(";lcall","__gptrput");
8101             //if (size)
8102             //    emitcode("inc","dptr");
8103         }
8104     }
8105
8106     freeAsmop(right,NULL,ic,TRUE);
8107 }
8108
8109 /*-----------------------------------------------------------------*/
8110 /* genPointerSet - stores the value into a pointer location        */
8111 /*-----------------------------------------------------------------*/
8112 static void genPointerSet (iCode *ic)
8113 {    
8114     operand *right, *result ;
8115     sym_link *type, *etype;
8116     int p_type;
8117
8118     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8119
8120     right = IC_RIGHT(ic);
8121     result = IC_RESULT(ic) ;
8122
8123     /* depending on the type of pointer we need to
8124     move it to the correct pointer register */
8125     type = operandType(result);
8126     etype = getSpec(type);
8127     /* if left is of type of pointer then it is simple */
8128     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8129         p_type = DCL_TYPE(type);
8130     }
8131     else {
8132         /* we have to go by the storage class */
8133         p_type = PTR_TYPE(SPEC_OCLS(etype));
8134
8135 /*      if (SPEC_OCLS(etype)->codesp ) { */
8136 /*          p_type = CPOINTER ;  */
8137 /*      } */
8138 /*      else */
8139 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8140 /*              p_type = FPOINTER ; */
8141 /*          else */
8142 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8143 /*                  p_type = PPOINTER ; */
8144 /*              else */
8145 /*                  if (SPEC_OCLS(etype) == idata ) */
8146 /*                      p_type = IPOINTER ; */
8147 /*                  else */
8148 /*                      p_type = POINTER ; */
8149     }
8150
8151     /* now that we have the pointer type we assign
8152     the pointer values */
8153     switch (p_type) {
8154
8155     case POINTER:
8156     case IPOINTER:
8157         genNearPointerSet (right,result,ic);
8158         break;
8159
8160     case PPOINTER:
8161         genPagedPointerSet (right,result,ic);
8162         break;
8163
8164     case FPOINTER:
8165         genFarPointerSet (right,result,ic);
8166         break;
8167
8168     case GPOINTER:
8169         genGenPointerSet (right,result,ic);
8170         break;
8171     }
8172
8173 }
8174
8175 /*-----------------------------------------------------------------*/
8176 /* genIfx - generate code for Ifx statement                        */
8177 /*-----------------------------------------------------------------*/
8178 static void genIfx (iCode *ic, iCode *popIc)
8179 {
8180     operand *cond = IC_COND(ic);
8181     int isbit =0;
8182
8183     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8184     aopOp(cond,ic,FALSE);
8185
8186     /* get the value into acc */
8187     if (AOP_TYPE(cond) != AOP_CRY)
8188         toBoolean(cond);
8189     else
8190         isbit = 1;
8191     /* the result is now in the accumulator */
8192     freeAsmop(cond,NULL,ic,TRUE);
8193
8194     /* if there was something to be popped then do it */
8195     if (popIc)
8196         genIpop(popIc);
8197
8198     /* if the condition is  a bit variable */
8199     if (isbit && IS_ITEMP(cond) && 
8200         SPIL_LOC(cond)) {
8201       genIfxJump(ic,SPIL_LOC(cond)->rname);
8202       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8203     }
8204     else {
8205       /*
8206         if (isbit && !IS_ITEMP(cond))
8207           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8208         else
8209           DEBUGemitcode ("; isbit","a");
8210       */
8211
8212         if (isbit && !IS_ITEMP(cond))
8213             genIfxJump(ic,OP_SYMBOL(cond)->rname);
8214         else
8215             genIfxJump(ic,"a");
8216     }
8217     ic->generated = 1;
8218 }
8219
8220 /*-----------------------------------------------------------------*/
8221 /* genAddrOf - generates code for address of                       */
8222 /*-----------------------------------------------------------------*/
8223 static void genAddrOf (iCode *ic)
8224 {
8225     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8226     int size, offset ;
8227
8228     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8229
8230     aopOp(IC_RESULT(ic),ic,FALSE);
8231
8232     /* if the operand is on the stack then we 
8233     need to get the stack offset of this
8234     variable */
8235     if (sym->onStack) {
8236         /* if it has an offset then we need to compute
8237         it */
8238         if (sym->stack) {
8239             emitcode("mov","a,_bp");
8240             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8241             aopPut(AOP(IC_RESULT(ic)),"a",0);       
8242         } else {
8243             /* we can just move _bp */
8244             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8245         }
8246         /* fill the result with zero */
8247         size = AOP_SIZE(IC_RESULT(ic)) - 1;
8248         
8249         
8250         if (options.stack10bit && size < (FPTRSIZE - 1))
8251         {
8252             fprintf(stderr, 
8253                     "*** warning: pointer to stack var truncated.\n");
8254         }
8255         
8256         offset = 1;
8257         while (size--)
8258         {
8259             /* Yuck! */
8260             if (options.stack10bit && offset == 2)
8261             {
8262                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8263             }
8264             else
8265             {
8266                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8267             }
8268         }
8269
8270         goto release;
8271     }
8272
8273     /* object not on stack then we need the name */
8274     size = AOP_SIZE(IC_RESULT(ic));
8275     offset = 0;
8276
8277     while (size--) {
8278         char s[SDCC_NAME_MAX];
8279         if (offset) 
8280             sprintf(s,"#(%s >> %d)",
8281                     sym->rname,
8282                     offset*8);
8283         else
8284             sprintf(s,"#%s",sym->rname);
8285         aopPut(AOP(IC_RESULT(ic)),s,offset++);
8286     }
8287
8288 release:
8289     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8290
8291 }
8292
8293 #if 0
8294 /*-----------------------------------------------------------------*/
8295 /* genFarFarAssign - assignment when both are in far space         */
8296 /*-----------------------------------------------------------------*/
8297 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8298 {
8299     int size = AOP_SIZE(right);
8300     int offset = 0;
8301     char *l ;
8302     /* first push the right side on to the stack */
8303     while (size--) {
8304         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8305         MOVA(l);
8306         emitcode ("push","acc");
8307     }
8308     
8309     freeAsmop(right,NULL,ic,FALSE);
8310     /* now assign DPTR to result */
8311     aopOp(result,ic,FALSE);
8312     size = AOP_SIZE(result);
8313     while (size--) {
8314         emitcode ("pop","acc");
8315         aopPut(AOP(result),"a",--offset);
8316     }
8317     freeAsmop(result,NULL,ic,FALSE);
8318         
8319 }
8320 #endif
8321
8322 /*-----------------------------------------------------------------*/
8323 /* genAssign - generate code for assignment                        */
8324 /*-----------------------------------------------------------------*/
8325 static void genAssign (iCode *ic)
8326 {
8327     operand *result, *right;
8328     int size, offset ;
8329         unsigned long lit = 0L;
8330
8331     result = IC_RESULT(ic);
8332     right  = IC_RIGHT(ic) ;
8333
8334     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8335
8336     /* if they are the same */
8337     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8338         return ;
8339
8340     aopOp(right,ic,FALSE);
8341     aopOp(result,ic,TRUE);
8342
8343     /* if they are the same registers */
8344     if (sameRegs(AOP(right),AOP(result)))
8345         goto release;
8346
8347     /* if the result is a bit */
8348     if (AOP_TYPE(result) == AOP_CRY) {
8349
8350         /* if the right size is a literal then
8351         we know what the value is */
8352         if (AOP_TYPE(right) == AOP_LIT) {
8353           
8354           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8355                       popGet(AOP(result),0,FALSE,FALSE));
8356
8357             if (((int) operandLitValue(right))) 
8358               emitcode("bsf","(%s >> 3),(%s & 7)",
8359                        AOP(result)->aopu.aop_dir,
8360                        AOP(result)->aopu.aop_dir);
8361             else
8362               emitcode("bcf","(%s >> 3),(%s & 7)",
8363                  AOP(result)->aopu.aop_dir,
8364                  AOP(result)->aopu.aop_dir);
8365             goto release;
8366         }
8367
8368         /* the right is also a bit variable */
8369         if (AOP_TYPE(right) == AOP_CRY) {
8370           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8371           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8372           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8373
8374           emitcode("bcf","(%s >> 3),(%s & 7)",
8375                    AOP(result)->aopu.aop_dir,
8376                    AOP(result)->aopu.aop_dir);
8377           emitcode("btfsc","(%s >> 3),(%s & 7)",
8378                    AOP(right)->aopu.aop_dir,
8379                    AOP(right)->aopu.aop_dir);
8380           emitcode("bsf","(%s >> 3),(%s & 7)",
8381                    AOP(result)->aopu.aop_dir,
8382                    AOP(result)->aopu.aop_dir);
8383           goto release ;
8384         }
8385
8386         /* we need to or */
8387         toBoolean(right);
8388         aopPut(AOP(result),"a",0);
8389         goto release ;
8390     }
8391
8392     /* bit variables done */
8393     /* general case */
8394     size = AOP_SIZE(result);
8395     offset = 0 ;
8396     if(AOP_TYPE(right) == AOP_LIT)
8397         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8398     if((AOP_TYPE(result) != AOP_REG) &&
8399        (AOP_TYPE(right) == AOP_LIT) &&
8400        !IS_FLOAT(operandType(right)) &&
8401        (lit < 256L)){
8402
8403         while (size--) {
8404           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8405             //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8406               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8407             }else {
8408               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8409               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8410               //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8411               //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8412             }
8413         }
8414     } else {
8415         while (size--) {
8416           if(AOP_TYPE(right) == AOP_LIT)
8417             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8418           //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8419           else
8420             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8421           //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8422             
8423           emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8424           //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8425           offset++;
8426         }
8427     }
8428     
8429 release:
8430     freeAsmop (right,NULL,ic,FALSE);
8431     freeAsmop (result,NULL,ic,TRUE);
8432 }   
8433
8434 /*-----------------------------------------------------------------*/
8435 /* genJumpTab - genrates code for jump table                       */
8436 /*-----------------------------------------------------------------*/
8437 static void genJumpTab (iCode *ic)
8438 {
8439     symbol *jtab;
8440     char *l;
8441
8442     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8443
8444     aopOp(IC_JTCOND(ic),ic,FALSE);
8445     /* get the condition into accumulator */
8446     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8447     MOVA(l);
8448     /* multiply by three */
8449     emitcode("add","a,acc");
8450     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8451     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8452
8453     jtab = newiTempLabel(NULL);
8454     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8455     emitcode("jmp","@a+dptr");
8456     emitcode("","%05d_DS_:",jtab->key+100);
8457     /* now generate the jump labels */
8458     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8459          jtab = setNextItem(IC_JTLABELS(ic)))
8460         emitcode("ljmp","%05d_DS_",jtab->key+100);
8461
8462 }
8463
8464 /*-----------------------------------------------------------------*/
8465 /* genMixedOperation - gen code for operators between mixed types  */
8466 /*-----------------------------------------------------------------*/
8467 /*
8468   TSD - Written for the PIC port - but this unfortunately is buggy.
8469   This routine is good in that it is able to efficiently promote 
8470   types to different (larger) sizes. Unfortunately, the temporary
8471   variables that are optimized out by this routine are sometimes
8472   used in other places. So until I know how to really parse the 
8473   iCode tree, I'm going to not be using this routine :(.
8474 */
8475 static int genMixedOperation (iCode *ic)
8476 {
8477 #if 0
8478   operand *result = IC_RESULT(ic);
8479   sym_link *ctype = operandType(IC_LEFT(ic));
8480   operand *right = IC_RIGHT(ic);
8481   int ret = 0;
8482   int big,small;
8483   int offset;
8484
8485   iCode *nextic;
8486   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8487
8488   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8489
8490   nextic = ic->next;
8491   if(!nextic)
8492     return 0;
8493
8494   nextright = IC_RIGHT(nextic);
8495   nextleft  = IC_LEFT(nextic);
8496   nextresult = IC_RESULT(nextic);
8497
8498   aopOp(right,ic,FALSE);
8499   aopOp(result,ic,FALSE);
8500   aopOp(nextright,  nextic, FALSE);
8501   aopOp(nextleft,   nextic, FALSE);
8502   aopOp(nextresult, nextic, FALSE);
8503
8504   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8505
8506     operand *t = right;
8507     right = nextright;
8508     nextright = t; 
8509
8510     emitcode(";remove right +","");
8511
8512   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8513 /*
8514     operand *t = right;
8515     right = nextleft;
8516     nextleft = t; 
8517 */
8518     emitcode(";remove left +","");
8519   } else
8520     return 0;
8521
8522   big = AOP_SIZE(nextleft);
8523   small = AOP_SIZE(nextright);
8524
8525   switch(nextic->op) {
8526
8527   case '+':
8528     emitcode(";optimize a +","");
8529     /* if unsigned or not an integral type */
8530     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8531       emitcode(";add a bit to something","");
8532     } else {
8533
8534       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8535
8536       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8537         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8538         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8539       } else
8540         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8541
8542       offset = 0;
8543       while(--big) {
8544
8545         offset++;
8546
8547         if(--small) {
8548           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8549             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8550             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8551           }
8552
8553           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8554           emitSKPNC;
8555           emitcode("btfsc","(%s >> 3), (%s & 7)",
8556                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8557                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8558           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8559           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8560
8561         } else {
8562           emitcode("rlf","known_zero,w");
8563
8564           /*
8565             if right is signed
8566               btfsc  right,7
8567                addlw ff
8568           */
8569           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8570             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8571             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8572           } else {
8573             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8574           }
8575         }
8576       }
8577       ret = 1;
8578     }
8579   }
8580   ret = 1;
8581
8582 release:
8583   freeAsmop(right,NULL,ic,TRUE);
8584   freeAsmop(result,NULL,ic,TRUE);
8585   freeAsmop(nextright,NULL,ic,TRUE);
8586   freeAsmop(nextleft,NULL,ic,TRUE);
8587   if(ret)
8588     nextic->generated = 1;
8589
8590   return ret;
8591 #else
8592   return 0;
8593 #endif
8594 }
8595 /*-----------------------------------------------------------------*/
8596 /* genCast - gen code for casting                                  */
8597 /*-----------------------------------------------------------------*/
8598 static void genCast (iCode *ic)
8599 {
8600     operand *result = IC_RESULT(ic);
8601     sym_link *ctype = operandType(IC_LEFT(ic));
8602     operand *right = IC_RIGHT(ic);
8603     int size, offset ;
8604
8605     DEBUGemitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8606     /* if they are equivalent then do nothing */
8607     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8608         return ;
8609
8610     aopOp(right,ic,FALSE) ;
8611     aopOp(result,ic,FALSE);
8612
8613     /* if the result is a bit */
8614     if (AOP_TYPE(result) == AOP_CRY) {
8615         /* if the right size is a literal then
8616         we know what the value is */
8617         if (AOP_TYPE(right) == AOP_LIT) {
8618
8619           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8620                       popGet(AOP(result),0,FALSE,FALSE));
8621
8622             if (((int) operandLitValue(right))) 
8623               emitcode("bsf","(%s >> 3), (%s & 7)",
8624                        AOP(result)->aopu.aop_dir,
8625                        AOP(result)->aopu.aop_dir);
8626             else
8627               emitcode("bcf","(%s >> 3), (%s & 7)",
8628                        AOP(result)->aopu.aop_dir,
8629                        AOP(result)->aopu.aop_dir);
8630
8631             goto release;
8632         }
8633
8634         /* the right is also a bit variable */
8635         if (AOP_TYPE(right) == AOP_CRY) {
8636
8637           emitCLRC;
8638           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8639
8640           emitcode("clrc","");
8641           emitcode("btfsc","(%s >> 3), (%s & 7)",
8642                    AOP(right)->aopu.aop_dir,
8643                    AOP(right)->aopu.aop_dir);
8644             aopPut(AOP(result),"c",0);
8645             goto release ;
8646         }
8647
8648         /* we need to or */
8649         toBoolean(right);
8650         aopPut(AOP(result),"a",0);
8651         goto release ;
8652     }
8653
8654     /* if they are the same size : or less */
8655     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8656
8657         /* if they are in the same place */
8658         if (sameRegs(AOP(right),AOP(result)))
8659             goto release;
8660
8661         /* if they in different places then copy */
8662         size = AOP_SIZE(result);
8663         offset = 0 ;
8664         while (size--) {
8665             aopPut(AOP(result),
8666                    aopGet(AOP(right),offset,FALSE,FALSE),
8667                    offset);
8668             offset++;
8669         }
8670         goto release;
8671     }
8672
8673
8674     /* if the result is of type pointer */
8675     if (IS_PTR(ctype)) {
8676
8677         int p_type;
8678         sym_link *type = operandType(right);
8679         sym_link *etype = getSpec(type);
8680
8681         /* pointer to generic pointer */
8682         if (IS_GENPTR(ctype)) {
8683             char *l = zero;
8684             
8685             if (IS_PTR(type)) 
8686                 p_type = DCL_TYPE(type);
8687             else {
8688                 /* we have to go by the storage class */
8689                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8690
8691 /*              if (SPEC_OCLS(etype)->codesp )  */
8692 /*                  p_type = CPOINTER ;  */
8693 /*              else */
8694 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8695 /*                      p_type = FPOINTER ; */
8696 /*                  else */
8697 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8698 /*                          p_type = PPOINTER; */
8699 /*                      else */
8700 /*                          if (SPEC_OCLS(etype) == idata ) */
8701 /*                              p_type = IPOINTER ; */
8702 /*                          else */
8703 /*                              p_type = POINTER ; */
8704             }
8705                 
8706             /* the first two bytes are known */
8707             size = GPTRSIZE - 1; 
8708             offset = 0 ;
8709             while (size--) {
8710                 aopPut(AOP(result),
8711                        aopGet(AOP(right),offset,FALSE,FALSE),
8712                        offset);
8713                 offset++;
8714             }
8715             /* the last byte depending on type */
8716             switch (p_type) {
8717             case IPOINTER:
8718             case POINTER:
8719                 l = zero;
8720                 break;
8721             case FPOINTER:
8722                 l = one;
8723                 break;
8724             case CPOINTER:
8725                 l = "#0x02";
8726                 break;                          
8727             case PPOINTER:
8728                 l = "#0x03";
8729                 break;
8730                 
8731             default:
8732                 /* this should never happen */
8733                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8734                        "got unknown pointer type");
8735                 exit(1);
8736             }
8737             aopPut(AOP(result),l, GPTRSIZE - 1);            
8738             goto release ;
8739         }
8740         
8741         /* just copy the pointers */
8742         size = AOP_SIZE(result);
8743         offset = 0 ;
8744         while (size--) {
8745             aopPut(AOP(result),
8746                    aopGet(AOP(right),offset,FALSE,FALSE),
8747                    offset);
8748             offset++;
8749         }
8750         goto release ;
8751     }
8752     
8753
8754     if (AOP_TYPE(right) == AOP_CRY) {
8755       int offset = 1;
8756       size = AOP_SIZE(right);
8757
8758       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8759       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8760       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8761
8762       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8763       emitcode("btfsc","(%s >> 3), (%s & 7)",
8764                AOP(right)->aopu.aop_dir,
8765                AOP(right)->aopu.aop_dir);
8766       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8767       while (size--) {
8768         emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8769         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8770       }
8771       goto release;
8772     }
8773
8774     /* so we now know that the size of destination is greater
8775     than the size of the source.
8776     Now, if the next iCode is an operator then we might be
8777     able to optimize the operation without performing a cast.
8778     */
8779     if(genMixedOperation(ic))
8780       goto release;
8781
8782     
8783     /* we move to result for the size of source */
8784     size = AOP_SIZE(right);
8785     offset = 0 ;
8786     while (size--) {
8787       emitcode(";","%d",__LINE__);
8788         aopPut(AOP(result),
8789                aopGet(AOP(right),offset,FALSE,FALSE),
8790                offset);
8791         offset++;
8792     }
8793
8794     /* now depending on the sign of the destination */
8795     size = AOP_SIZE(result) - AOP_SIZE(right);
8796     /* if unsigned or not an integral type */
8797     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8798       while (size--) {
8799           emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8800           emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8801       }
8802     } else {
8803       /* we need to extend the sign :{ */
8804       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8805       //MOVA(l);
8806
8807       emitpcode(POC_CLRW,    NULL);
8808       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8809       emitpcode(POC_MOVLW,   popGetLit(0xff));
8810
8811         emitcode("clrw","");
8812         emitcode("btfsc","(%s >> 3), (%s & 7)",
8813                  AOP(right)->aopu.aop_dir,
8814                  AOP(right)->aopu.aop_dir);
8815         emitcode("movlw","0xff");
8816         while (size--) {
8817           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++,FALSE,FALSE));
8818           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8819           // aopPut(AOP(result),"a",offset++);
8820         }
8821
8822     }
8823
8824     /* we are done hurray !!!! */
8825
8826 release:
8827     freeAsmop(right,NULL,ic,TRUE);
8828     freeAsmop(result,NULL,ic,TRUE);
8829
8830 }
8831
8832 /*-----------------------------------------------------------------*/
8833 /* genDjnz - generate decrement & jump if not zero instrucion      */
8834 /*-----------------------------------------------------------------*/
8835 static int genDjnz (iCode *ic, iCode *ifx)
8836 {
8837     symbol *lbl, *lbl1;
8838     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839
8840     if (!ifx)
8841         return 0;
8842     
8843     /* if the if condition has a false label
8844        then we cannot save */
8845     if (IC_FALSE(ifx))
8846         return 0;
8847
8848     /* if the minus is not of the form 
8849        a = a - 1 */
8850     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8851         !IS_OP_LITERAL(IC_RIGHT(ic)))
8852         return 0;
8853
8854     if (operandLitValue(IC_RIGHT(ic)) != 1)
8855         return 0;
8856
8857     /* if the size of this greater than one then no
8858        saving */
8859     if (getSize(operandType(IC_RESULT(ic))) > 1)
8860         return 0;
8861
8862     /* otherwise we can save BIG */
8863     lbl = newiTempLabel(NULL);
8864     lbl1= newiTempLabel(NULL);
8865
8866     aopOp(IC_RESULT(ic),ic,FALSE);
8867     
8868     if (IS_AOP_PREG(IC_RESULT(ic))) {
8869         emitcode("dec","%s",
8870                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8871         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8872         emitcode("jnz","%05d_DS_",lbl->key+100);
8873     } else {    
8874
8875
8876       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8877       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8878
8879       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8880       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8881
8882     }
8883 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8884 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
8885 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8886 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
8887
8888     
8889     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8890     ifx->generated = 1;
8891     return 1;
8892 }
8893
8894 /*-----------------------------------------------------------------*/
8895 /* genReceive - generate code for a receive iCode                  */
8896 /*-----------------------------------------------------------------*/
8897 static void genReceive (iCode *ic)
8898 {    
8899     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8900
8901     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8902         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8903           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8904
8905         int size = getSize(operandType(IC_RESULT(ic)));
8906         int offset =  fReturnSize - size;
8907         while (size--) {
8908             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8909                                     fReturn[fReturnSize - offset - 1] : "acc"));
8910             offset++;
8911         }
8912         aopOp(IC_RESULT(ic),ic,FALSE);  
8913         size = AOP_SIZE(IC_RESULT(ic));
8914         offset = 0;
8915         while (size--) {
8916             emitcode ("pop","acc");
8917             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8918         }
8919         
8920     } else {
8921         _G.accInUse++;
8922         aopOp(IC_RESULT(ic),ic,FALSE);  
8923         _G.accInUse--;
8924         assignResultValue(IC_RESULT(ic));       
8925     }
8926
8927     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8928 }
8929
8930 /*-----------------------------------------------------------------*/
8931 /* genpic14Code - generate code for pic14 based controllers        */
8932 /*-----------------------------------------------------------------*/
8933 /*
8934  * At this point, ralloc.c has gone through the iCode and attempted
8935  * to optimize in a way suitable for a PIC. Now we've got to generate
8936  * PIC instructions that correspond to the iCode.
8937  *
8938  * Once the instructions are generated, we'll pass through both the
8939  * peep hole optimizer and the pCode optimizer.
8940  *-----------------------------------------------------------------*/
8941
8942 void genpic14Code (iCode *lic)
8943 {
8944     iCode *ic;
8945     int cln = 0;
8946
8947     lineHead = lineCurr = NULL;
8948
8949     pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8950     addpBlock(pb);
8951
8952     /* if debug information required */
8953 /*     if (options.debug && currFunc) { */
8954     if (currFunc) {
8955         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8956         _G.debugLine = 1;
8957         if (IS_STATIC(currFunc->etype)) {
8958             emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8959             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8960         } else {
8961             emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8962             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8963         }
8964         _G.debugLine = 0;
8965     }
8966
8967
8968     for (ic = lic ; ic ; ic = ic->next ) {
8969
8970       DEBUGemitcode(";ic","");
8971         if ( cln != ic->lineno ) {
8972             if ( options.debug ) {
8973                 _G.debugLine = 1;
8974                 emitcode("",";C$%s$%d$%d$%d ==.",
8975                          FileBaseName(ic->filename),ic->lineno,
8976                          ic->level,ic->block);
8977                 _G.debugLine = 0;
8978             }
8979             emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8980             cln = ic->lineno ;
8981         }
8982         /* if the result is marked as
8983            spilt and rematerializable or code for
8984            this has already been generated then
8985            do nothing */
8986         if (resultRemat(ic) || ic->generated ) 
8987             continue ;
8988         
8989         /* depending on the operation */
8990         switch (ic->op) {
8991         case '!' :
8992             genNot(ic);
8993             break;
8994             
8995         case '~' :
8996             genCpl(ic);
8997             break;
8998             
8999         case UNARYMINUS:
9000             genUminus (ic);
9001             break;
9002             
9003         case IPUSH:
9004             genIpush (ic);
9005             break;
9006             
9007         case IPOP:
9008             /* IPOP happens only when trying to restore a 
9009                spilt live range, if there is an ifx statement
9010                following this pop then the if statement might
9011                be using some of the registers being popped which
9012                would destory the contents of the register so
9013                we need to check for this condition and handle it */
9014             if (ic->next            && 
9015                 ic->next->op == IFX &&
9016                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9017                 genIfx (ic->next,ic);
9018             else
9019                 genIpop (ic);
9020             break; 
9021             
9022         case CALL:
9023             genCall (ic);
9024             break;
9025             
9026         case PCALL:
9027             genPcall (ic);
9028             break;
9029             
9030         case FUNCTION:
9031             genFunction (ic);
9032             break;
9033             
9034         case ENDFUNCTION:
9035             genEndFunction (ic);
9036             break;
9037             
9038         case RETURN:
9039             genRet (ic);
9040             break;
9041             
9042         case LABEL:
9043             genLabel (ic);
9044             break;
9045             
9046         case GOTO:
9047             genGoto (ic);
9048             break;
9049             
9050         case '+' :
9051             genPlus (ic) ;
9052             break;
9053             
9054         case '-' :
9055             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9056                 genMinus (ic);
9057             break;
9058             
9059         case '*' :
9060             genMult (ic);
9061             break;
9062             
9063         case '/' :
9064             genDiv (ic) ;
9065             break;
9066             
9067         case '%' :
9068             genMod (ic);
9069             break;
9070             
9071         case '>' :
9072             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9073             break;
9074             
9075         case '<' :
9076             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9077             break;
9078             
9079         case LE_OP:
9080         case GE_OP:
9081         case NE_OP:
9082             
9083             /* note these two are xlated by algebraic equivalence
9084                during parsing SDCC.y */
9085             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9086                    "got '>=' or '<=' shouldn't have come here");
9087             break;      
9088             
9089         case EQ_OP:
9090             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9091             break;          
9092             
9093         case AND_OP:
9094             genAndOp (ic);
9095             break;
9096             
9097         case OR_OP:
9098             genOrOp (ic);
9099             break;
9100             
9101         case '^' :
9102             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9103             break;
9104             
9105         case '|' :
9106                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9107             break;
9108             
9109         case BITWISEAND:
9110             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9111             break;
9112             
9113         case INLINEASM:
9114             genInline (ic);
9115             break;
9116             
9117         case RRC:
9118             genRRC (ic);
9119             break;
9120             
9121         case RLC:
9122             genRLC (ic);
9123             break;
9124             
9125         case GETHBIT:
9126             genGetHbit (ic);
9127             break;
9128             
9129         case LEFT_OP:
9130             genLeftShift (ic);
9131             break;
9132             
9133         case RIGHT_OP:
9134             genRightShift (ic);
9135             break;
9136             
9137         case GET_VALUE_AT_ADDRESS:
9138             genPointerGet(ic);
9139             break;
9140             
9141         case '=' :
9142             if (POINTER_SET(ic))
9143                 genPointerSet(ic);
9144             else
9145                 genAssign(ic);
9146             break;
9147             
9148         case IFX:
9149             genIfx (ic,NULL);
9150             break;
9151             
9152         case ADDRESS_OF:
9153             genAddrOf (ic);
9154             break;
9155             
9156         case JUMPTABLE:
9157             genJumpTab (ic);
9158             break;
9159             
9160         case CAST:
9161             genCast (ic);
9162             break;
9163             
9164         case RECEIVE:
9165             genReceive(ic);
9166             break;
9167             
9168         case SEND:
9169             addSet(&_G.sendSet,ic);
9170             break;
9171
9172         default :
9173             ic = ic;
9174             /*      piCode(ic,stdout); */
9175             
9176         }
9177     }
9178     
9179
9180     /* now we are ready to call the 
9181        peep hole optimizer */
9182     if (!options.nopeep) {
9183       printf("peep hole optimizing\n");
9184         peepHole (&lineHead);
9185     }
9186     /* now do the actual printing */
9187     printLine (lineHead,codeOutFile);
9188
9189     printf("printing pBlock\n\n");
9190     printpBlock(stdout,pb);
9191
9192     return;
9193 }