pCode - register allocation, flow analysis, and peephole.
[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 unsigned fReturnSizePic = 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=0;
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     if(debug_verbose)
211       addpCode2pBlock(pb,newpCodeCharP(lb));
212
213     va_end(ap);
214 }
215
216 static void DEBUGemitcode (char *inst,char *fmt, ...)
217 {
218     va_list ap;
219     char lb[MAX_INLINEASM];  
220     char *lbp = lb;
221
222     if(!debug_verbose)
223       return;
224
225     va_start(ap,fmt);   
226
227     if (inst && *inst) {
228         if (fmt && *fmt)
229             sprintf(lb,"%s\t",inst);
230         else
231             sprintf(lb,"%s",inst);
232         vsprintf(lb+(strlen(lb)),fmt,ap);
233     }  else
234         vsprintf(lb,fmt,ap);
235
236     while (isspace(*lbp)) lbp++;
237
238     if (lbp && *lbp) 
239         lineCurr = (lineCurr ?
240                     connectLine(lineCurr,newLineNode(lb)) :
241                     (lineHead = newLineNode(lb)));
242     lineCurr->isInline = _G.inLine;
243     lineCurr->isDebug  = _G.debugLine;
244
245     addpCode2pBlock(pb,newpCodeCharP(lb));
246
247     va_end(ap);
248 }
249
250
251 /*-----------------------------------------------------------------*/
252 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
253 /*-----------------------------------------------------------------*/
254 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
255 {
256     bool r0iu = FALSE , r1iu = FALSE;
257     bool r0ou = FALSE , r1ou = FALSE;
258
259     /* the logic: if r0 & r1 used in the instruction
260     then we are in trouble otherwise */
261
262     /* first check if r0 & r1 are used by this
263     instruction, in which case we are in trouble */
264     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
265         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
266     {
267         goto endOfWorld;      
268     }
269
270     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
271     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
272
273     /* if no usage of r0 then return it */
274     if (!r0iu && !r0ou) {
275         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
276         (*aopp)->type = AOP_R0;
277         
278         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
279     }
280
281     /* if no usage of r1 then return it */
282     if (!r1iu && !r1ou) {
283         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
284         (*aopp)->type = AOP_R1;
285
286         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
287     }    
288
289     /* now we know they both have usage */
290     /* if r0 not used in this instruction */
291     if (!r0iu) {
292         /* push it if not already pushed */
293         if (!_G.r0Pushed) {
294             emitcode ("push","%s",
295                       pic14_regWithIdx(R0_IDX)->dname);
296             _G.r0Pushed++ ;
297         }
298         
299         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
300         (*aopp)->type = AOP_R0;
301
302         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
303     }
304
305     /* if r1 not used then */
306
307     if (!r1iu) {
308         /* push it if not already pushed */
309         if (!_G.r1Pushed) {
310             emitcode ("push","%s",
311                       pic14_regWithIdx(R1_IDX)->dname);
312             _G.r1Pushed++ ;
313         }
314         
315         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
316         (*aopp)->type = AOP_R1;
317         return pic14_regWithIdx(R1_IDX);
318     }
319
320 endOfWorld :
321     /* I said end of world but not quite end of world yet */
322     /* if this is a result then we can push it on the stack*/
323     if (result) {
324         (*aopp)->type = AOP_STK;    
325         return NULL;
326     }
327
328     piCode(ic,stdout);
329     /* other wise this is true end of the world */
330     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
331            "getFreePtr should never reach here");
332     exit(0);
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* newAsmop - creates a new asmOp                                  */
337 /*-----------------------------------------------------------------*/
338 static asmop *newAsmop (short type)
339 {
340     asmop *aop;
341
342     aop = Safe_calloc(1,sizeof(asmop));
343     aop->type = type;
344     return aop;
345 }
346
347 static void genSetDPTR(int n)
348 {
349     if (!n)
350     {
351         emitcode(";", "Select standard DPTR");
352         emitcode("mov", "dps, #0x00");
353     }
354     else
355     {
356         emitcode(";", "Select alternate DPTR");
357         emitcode("mov", "dps, #0x01");
358     }
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* pointerCode - returns the code for a pointer type               */
363 /*-----------------------------------------------------------------*/
364 static int pointerCode (sym_link *etype)
365 {
366
367     return PTR_TYPE(SPEC_OCLS(etype));
368
369 }
370
371 /*-----------------------------------------------------------------*/
372 /* aopForSym - for a true symbol                                   */
373 /*-----------------------------------------------------------------*/
374 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
375 {
376     asmop *aop;
377     memmap *space= SPEC_OCLS(sym->etype);
378
379     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
380     /* if already has one */
381     if (sym->aop)
382         return sym->aop;
383
384     /* assign depending on the storage class */
385     /* if it is on the stack or indirectly addressable */
386     /* space we need to assign either r0 or r1 to it   */    
387     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
388         sym->aop = aop = newAsmop(0);
389         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
390         aop->size = getSize(sym->type);
391
392         /* now assign the address of the variable to 
393         the pointer register */
394         if (aop->type != AOP_STK) {
395
396             if (sym->onStack) {
397                     if ( _G.accInUse )
398                         emitcode("push","acc");
399
400                     emitcode("mov","a,_bp");
401                     emitcode("add","a,#0x%02x",
402                              ((sym->stack < 0) ?
403                               ((char)(sym->stack - _G.nRegsSaved )) :
404                               ((char)sym->stack)) & 0xff);
405                     emitcode("mov","%s,a",
406                              aop->aopu.aop_ptr->name);
407
408                     if ( _G.accInUse )
409                         emitcode("pop","acc");
410             } else
411                 emitcode("mov","%s,#%s",
412                          aop->aopu.aop_ptr->name,
413                          sym->rname);
414             aop->paged = space->paged;
415         } else
416             aop->aopu.aop_stk = sym->stack;
417         return aop;
418     }
419     
420     if (sym->onStack && options.stack10bit)
421     {
422         /* It's on the 10 bit stack, which is located in
423          * far data space.
424          */
425          
426       //DEBUGemitcode(";","%d",__LINE__);
427
428         if ( _G.accInUse )
429                 emitcode("push","acc");
430
431         emitcode("mov","a,_bp");
432         emitcode("add","a,#0x%02x",
433                  ((sym->stack < 0) ?
434                    ((char)(sym->stack - _G.nRegsSaved )) :
435                    ((char)sym->stack)) & 0xff);
436         
437         genSetDPTR(1);
438         emitcode ("mov","dpx1,#0x40");
439         emitcode ("mov","dph1,#0x00");
440         emitcode ("mov","dpl1, a");
441         genSetDPTR(0);
442         
443         if ( _G.accInUse )
444             emitcode("pop","acc");
445             
446         sym->aop = aop = newAsmop(AOP_DPTR2);
447         aop->size = getSize(sym->type); 
448         return aop;
449     }
450
451     //DEBUGemitcode(";","%d",__LINE__);
452     /* if in bit space */
453     if (IN_BITSPACE(space)) {
454         sym->aop = aop = newAsmop (AOP_CRY);
455         aop->aopu.aop_dir = sym->rname ;
456         aop->size = getSize(sym->type);
457         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
458         return aop;
459     }
460     /* if it is in direct space */
461     if (IN_DIRSPACE(space)) {
462         sym->aop = aop = newAsmop (AOP_DIR);
463         aop->aopu.aop_dir = sym->rname ;
464         aop->size = getSize(sym->type);
465         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
466         return aop;
467     }
468
469     /* special case for a function */
470     if (IS_FUNC(sym->type)) {   
471         sym->aop = aop = newAsmop(AOP_IMMD);    
472         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
473         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
474         strcpy(aop->aopu.aop_immd,sym->rname);
475         aop->size = FPTRSIZE; 
476         return aop;
477     }
478
479
480     /* only remaining is far space */
481     /* in which case DPTR gets the address */
482     sym->aop = aop = newAsmop(AOP_DPTR);
483     emitcode ("mov","dptr,#%s", sym->rname);
484     aop->size = getSize(sym->type);
485
486     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
487     /* if it is in code space */
488     if (IN_CODESPACE(space))
489         aop->code = 1;
490
491     return aop;     
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* aopForRemat - rematerialzes an object                           */
496 /*-----------------------------------------------------------------*/
497 static asmop *aopForRemat (symbol *sym)
498 {
499     iCode *ic = sym->rematiCode;
500     asmop *aop = newAsmop(AOP_IMMD);
501     int val = 0;
502     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
503     for (;;) {
504         if (ic->op == '+')
505             val += operandLitValue(IC_RIGHT(ic));
506         else if (ic->op == '-')
507             val -= operandLitValue(IC_RIGHT(ic));
508         else
509             break;
510         
511         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
512     }
513
514     if (val)
515         sprintf(buffer,"(%s %c 0x%04x)",
516                 OP_SYMBOL(IC_LEFT(ic))->rname, 
517                 val >= 0 ? '+' : '-',
518                 abs(val) & 0xffff);
519     else
520         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
521
522     //DEBUGemitcode(";","%s",buffer);
523     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
524     strcpy(aop->aopu.aop_immd,buffer);    
525     return aop;        
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* regsInCommon - two operands have some registers in common       */
530 /*-----------------------------------------------------------------*/
531 static bool regsInCommon (operand *op1, operand *op2)
532 {
533     symbol *sym1, *sym2;
534     int i;
535
536     /* if they have registers in common */
537     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
538         return FALSE ;
539
540     sym1 = OP_SYMBOL(op1);
541     sym2 = OP_SYMBOL(op2);
542
543     if (sym1->nRegs == 0 || sym2->nRegs == 0)
544         return FALSE ;
545
546     for (i = 0 ; i < sym1->nRegs ; i++) {
547         int j;
548         if (!sym1->regs[i])
549             continue ;
550
551         for (j = 0 ; j < sym2->nRegs ;j++ ) {
552             if (!sym2->regs[j])
553                 continue ;
554
555             if (sym2->regs[j] == sym1->regs[i])
556                 return TRUE ;
557         }
558     }
559
560     return FALSE ;
561 }
562
563 /*-----------------------------------------------------------------*/
564 /* operandsEqu - equivalent                                        */
565 /*-----------------------------------------------------------------*/
566 static bool operandsEqu ( operand *op1, operand *op2)
567 {
568     symbol *sym1, *sym2;
569
570     /* if they not symbols */
571     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
572         return FALSE;
573
574     sym1 = OP_SYMBOL(op1);
575     sym2 = OP_SYMBOL(op2);
576
577     /* if both are itemps & one is spilt
578        and the other is not then false */
579     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
580         sym1->isspilt != sym2->isspilt )
581         return FALSE ;
582
583     /* if they are the same */
584     if (sym1 == sym2)
585         return TRUE ;
586
587     if (strcmp(sym1->rname,sym2->rname) == 0)
588         return TRUE;
589
590
591     /* if left is a tmp & right is not */
592     if (IS_ITEMP(op1)  && 
593         !IS_ITEMP(op2) &&
594         sym1->isspilt  &&
595         (sym1->usl.spillLoc == sym2))
596         return TRUE;
597
598     if (IS_ITEMP(op2)  && 
599         !IS_ITEMP(op1) &&
600         sym2->isspilt  &&
601         sym1->level > 0 &&
602         (sym2->usl.spillLoc == sym1))
603         return TRUE ;
604
605     return FALSE ;
606 }
607
608 /*-----------------------------------------------------------------*/
609 /* sameRegs - two asmops have the same registers                   */
610 /*-----------------------------------------------------------------*/
611 static bool sameRegs (asmop *aop1, asmop *aop2 )
612 {
613     int i;
614
615     if (aop1 == aop2)
616         return TRUE ;
617
618     if (aop1->type != AOP_REG ||
619         aop2->type != AOP_REG )
620         return FALSE ;
621
622     if (aop1->size != aop2->size )
623         return FALSE ;
624
625     for (i = 0 ; i < aop1->size ; i++ )
626         if (aop1->aopu.aop_reg[i] !=
627             aop2->aopu.aop_reg[i] )
628             return FALSE ;
629
630     return TRUE ;
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* aopOp - allocates an asmop for an operand  :                    */
635 /*-----------------------------------------------------------------*/
636 static void aopOp (operand *op, iCode *ic, bool result)
637 {
638     asmop *aop;
639     symbol *sym;
640     int i;
641
642     if (!op)
643         return ;
644
645     DEBUGemitcode(";","%d",__LINE__);
646     /* if this a literal */
647     if (IS_OP_LITERAL(op)) {
648       DEBUGemitcode(";","%d",__LINE__);
649         op->aop = aop = newAsmop(AOP_LIT);
650         aop->aopu.aop_lit = op->operand.valOperand;
651         aop->size = getSize(operandType(op));
652         return;
653     }
654
655     /* if already has a asmop then continue */
656     if (op->aop)
657         return ;
658
659     /* if the underlying symbol has a aop */
660     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
661       DEBUGemitcode(";","%d",__LINE__);
662         op->aop = OP_SYMBOL(op)->aop;
663         return;
664     }
665
666     /* if this is a true symbol */
667     if (IS_TRUE_SYMOP(op)) {    
668       DEBUGemitcode(";","%d",__LINE__);
669         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
670         return ;
671     }
672
673     /* this is a temporary : this has
674     only four choices :
675     a) register
676     b) spillocation
677     c) rematerialize 
678     d) conditional   
679     e) can be a return use only */
680
681     sym = OP_SYMBOL(op);
682
683
684     /* if the type is a conditional */
685     if (sym->regType == REG_CND) {
686       DEBUGemitcode(";","%d",__LINE__);
687         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
688         aop->size = 0;
689         return;
690     }
691
692     /* if it is spilt then two situations
693     a) is rematerialize 
694     b) has a spill location */
695     if (sym->isspilt || sym->nRegs == 0) {
696
697       DEBUGemitcode(";","%d",__LINE__);
698         /* rematerialize it NOW */
699         if (sym->remat) {
700             sym->aop = op->aop = aop =
701                                       aopForRemat (sym);
702             aop->size = getSize(sym->type);
703             DEBUGemitcode(";","%d",__LINE__);
704             return;
705         }
706
707         if (sym->accuse) {
708             int i;
709             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
710             aop->size = getSize(sym->type);
711             for ( i = 0 ; i < 2 ; i++ )
712                 aop->aopu.aop_str[i] = accUse[i];
713             DEBUGemitcode(";","%d",__LINE__);
714             return;  
715         }
716
717         if (sym->ruonly ) {
718             int i;
719             aop = op->aop = sym->aop = newAsmop(AOP_STR);
720             aop->size = getSize(sym->type);
721             for ( i = 0 ; i < fReturnSizePic ; i++ )
722               aop->aopu.aop_str[i] = fReturn[i];
723             DEBUGemitcode(";","%d",__LINE__);
724             return;
725         }
726
727         /* else spill location  */
728         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
729         sym->aop = op->aop = aop = 
730                                   aopForSym(ic,sym->usl.spillLoc,result);
731         aop->size = getSize(sym->type);
732         return;
733     }
734
735     /* must be in a register */
736     sym->aop = op->aop = aop = newAsmop(AOP_REG);
737     aop->size = sym->nRegs;
738     for ( i = 0 ; i < sym->nRegs ;i++)
739         aop->aopu.aop_reg[i] = sym->regs[i];
740 }
741
742 /*-----------------------------------------------------------------*/
743 /* freeAsmop - free up the asmop given to an operand               */
744 /*----------------------------------------------------------------*/
745 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
746 {   
747     asmop *aop ;
748
749     if (!op)
750         aop = aaop;
751     else 
752         aop = op->aop;
753
754     if (!aop)
755         return ;
756
757     if (aop->freed)
758         goto dealloc; 
759
760     aop->freed = 1;
761
762     /* depending on the asmop type only three cases need work AOP_RO
763        , AOP_R1 && AOP_STK */
764     switch (aop->type) {
765         case AOP_R0 :
766             if (_G.r0Pushed ) {
767                 if (pop) {
768                     emitcode ("pop","ar0");     
769                     _G.r0Pushed--;
770                 }
771             }
772             bitVectUnSetBit(ic->rUsed,R0_IDX);
773             break;
774
775         case AOP_R1 :
776             if (_G.r1Pushed ) {
777                 if (pop) {
778                     emitcode ("pop","ar1");
779                     _G.r1Pushed--;
780                 }
781             }
782             bitVectUnSetBit(ic->rUsed,R1_IDX);          
783             break;
784
785         case AOP_STK :
786         {
787             int sz = aop->size;    
788             int stk = aop->aopu.aop_stk + aop->size;
789             bitVectUnSetBit(ic->rUsed,R0_IDX);
790             bitVectUnSetBit(ic->rUsed,R1_IDX);          
791
792             getFreePtr(ic,&aop,FALSE);
793             
794             if (options.stack10bit)
795             {
796                 /* I'm not sure what to do here yet... */
797                 /* #STUB */
798                 fprintf(stderr, 
799                         "*** Warning: probably generating bad code for "
800                         "10 bit stack mode.\n");
801             }
802             
803             if (stk) {
804                 emitcode ("mov","a,_bp");
805                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
806                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
807             } else {
808                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
809             }
810
811             while (sz--) {
812                 emitcode("pop","acc");
813                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
814                 if (!sz) break;
815                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
816             }
817             op->aop = aop;
818             freeAsmop(op,NULL,ic,TRUE);
819             if (_G.r0Pushed) {
820                 emitcode("pop","ar0");
821                 _G.r0Pushed--;
822             }
823
824             if (_G.r1Pushed) {
825                 emitcode("pop","ar1");
826                 _G.r1Pushed--;
827             }       
828         }
829     }
830
831 dealloc:
832     /* all other cases just dealloc */
833     if (op ) {
834         op->aop = NULL;
835         if (IS_SYMOP(op)) {
836             OP_SYMBOL(op)->aop = NULL;    
837             /* if the symbol has a spill */
838             if (SPIL_LOC(op))
839                 SPIL_LOC(op)->aop = NULL;
840         }
841     }
842 }
843
844 /*-----------------------------------------------------------------*/
845 /* aopGet - for fetching value of the aop                          */
846 /*-----------------------------------------------------------------*/
847 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
848 {
849     char *s = buffer ;
850     char *rs;
851
852     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
853     /* offset is greater than
854     size then zero */
855     if (offset > (aop->size - 1) &&
856         aop->type != AOP_LIT)
857         return zero;
858
859     /* depending on type */
860     switch (aop->type) {
861         
862     case AOP_R0:
863     case AOP_R1:
864         DEBUGemitcode(";","%d",__LINE__);
865         /* if we need to increment it */       
866         while (offset > aop->coff) {        
867             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
868             aop->coff++;
869         }
870         
871         while (offset < aop->coff) {
872             emitcode("dec","%s",aop->aopu.aop_ptr->name);
873             aop->coff--;
874         }
875         
876         aop->coff = offset ;
877         if (aop->paged) {
878             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
879             return (dname ? "acc" : "a");
880         }       
881         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
882         rs = Safe_calloc(1,strlen(s)+1);
883         strcpy(rs,s);   
884         return rs;
885         
886     case AOP_DPTR:
887     case AOP_DPTR2:
888         DEBUGemitcode(";","%d",__LINE__);
889     if (aop->type == AOP_DPTR2)
890     {
891         genSetDPTR(1);
892     }
893     
894         while (offset > aop->coff) {
895             emitcode ("inc","dptr");
896             aop->coff++;
897         }
898         
899         while (offset < aop->coff) {        
900             emitcode("lcall","__decdptr");
901             aop->coff--;
902         }
903         
904         aop->coff = offset;
905         if (aop->code) {
906             emitcode("clr","a");
907             emitcode("movc","a,@a+dptr");
908         }
909     else {
910             emitcode("movx","a,@dptr");
911     }
912             
913     if (aop->type == AOP_DPTR2)
914     {
915         genSetDPTR(0);
916     }
917             
918     return (dname ? "acc" : "a");
919         
920         
921     case AOP_IMMD:
922       DEBUGemitcode(";","%d",__LINE__);
923         if (bit16) 
924             sprintf (s,"%s",aop->aopu.aop_immd);
925         else
926             if (offset) 
927                 sprintf(s,"(%s >> %d)",
928                         aop->aopu.aop_immd,
929                         offset*8);
930             else
931                 sprintf(s,"%s",
932                         aop->aopu.aop_immd);
933         rs = Safe_calloc(1,strlen(s)+1);
934         strcpy(rs,s);   
935         return rs;
936         
937     case AOP_DIR:
938         if (offset)
939             sprintf(s,"(%s + %d)",
940                     aop->aopu.aop_dir,
941                     offset);
942         else
943             sprintf(s,"%s",aop->aopu.aop_dir);
944         rs = Safe_calloc(1,strlen(s)+1);
945         strcpy(rs,s);   
946         return rs;
947         
948     case AOP_REG:
949       DEBUGemitcode(";","%d",__LINE__);
950         if (dname) 
951             return aop->aopu.aop_reg[offset]->dname;
952         else
953             return aop->aopu.aop_reg[offset]->name;
954         
955     case AOP_CRY:
956       emitcode(";","%d",__LINE__);
957       //emitcode("clr","a");
958       //emitcode("mov","c,%s",aop->aopu.aop_dir);
959       //emitcode("rlc","a") ;
960       //return (dname ? "acc" : "a");
961       return aop->aopu.aop_dir;
962         
963     case AOP_ACC:
964         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
965         //if (!offset && dname)
966         //    return "acc";
967         //return aop->aopu.aop_str[offset];
968         return "AOP_accumulator_bug";
969
970     case AOP_LIT:
971         DEBUGemitcode(";","%d",__LINE__);
972         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
973         rs = Safe_calloc(1,strlen(s)+1);
974         strcpy(rs,s);   
975         return rs;
976         
977     case AOP_STR:
978         DEBUGemitcode(";","%d",__LINE__);
979         aop->coff = offset ;
980         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
981             dname)
982             return "acc";
983         
984         return aop->aopu.aop_str[offset];
985         
986     }
987
988     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
989            "aopget got unsupported aop->type");
990     exit(0);
991 }
992
993 /*-----------------------------------------------------------------*/
994 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
995 /*-----------------------------------------------------------------*/
996 static pCodeOp *popGetLabel(unsigned int key)
997 {
998   return newpCodeOpLabel(key+100+labelOffset);
999 }
1000
1001 /*-----------------------------------------------------------------*/
1002 /* popCopy - copy a pcode operator                                 */
1003 /*-----------------------------------------------------------------*/
1004 static pCodeOp *popCopy(pCodeOp *pc)
1005 {
1006   pCodeOp *pcop;
1007
1008   pcop = Safe_calloc(1,sizeof(pCodeOp) );
1009   pcop->type = pc->type;
1010   if(!(pcop->name = strdup(pc->name)))
1011     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1012
1013   return pcop;
1014 }
1015
1016 /*-----------------------------------------------------------------*/
1017 /* popCopy - copy a pcode operator                                 */
1018 /*-----------------------------------------------------------------*/
1019 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1020 {
1021   pCodeOp *pcop;
1022
1023   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1024   pcop->type = PO_BIT;
1025   if(!(pcop->name = strdup(pc->name)))
1026     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1027   ((pCodeOpBit *)pcop)->bit = bitval;
1028
1029   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1030
1031   return pcop;
1032 }
1033
1034 /*-----------------------------------------------------------------*/
1035 /* popGet - asm operator to pcode operator conversion              */
1036 /*-----------------------------------------------------------------*/
1037 static pCodeOp *popGetLit(unsigned int lit)
1038 {
1039
1040   return newpCodeOpLit(lit);
1041 }
1042
1043
1044 /*-----------------------------------------------------------------*/
1045 /* popGet - asm operator to pcode operator conversion              */
1046 /*-----------------------------------------------------------------*/
1047 static pCodeOp *popGetWithString(char *str)
1048 {
1049   pCodeOp *pcop;
1050
1051
1052   if(!str) {
1053     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1054     exit (1);
1055   }
1056
1057   pcop = newpCodeOp(str,PO_STR);
1058
1059   return pcop;
1060 }
1061 /*-----------------------------------------------------------------*/
1062 /* popGet - asm operator to pcode operator conversion              */
1063 /*-----------------------------------------------------------------*/
1064 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1065 {
1066     char *s = buffer ;
1067     char *rs;
1068
1069     pCodeOp *pcop;
1070
1071     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1072     /* offset is greater than
1073     size then zero */
1074
1075     if (offset > (aop->size - 1) &&
1076         aop->type != AOP_LIT)
1077       return NULL;  //zero;
1078
1079     /* depending on type */
1080     switch (aop->type) {
1081         
1082     case AOP_R0:
1083     case AOP_R1:
1084     case AOP_DPTR:
1085     case AOP_DPTR2:
1086     case AOP_ACC:
1087         DEBUGemitcode(";8051 legacy","%d",__LINE__);
1088         return NULL;
1089         
1090     case AOP_IMMD:
1091       DEBUGemitcode(";","%d",__LINE__);
1092         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1093         pcop->type = PO_IMMEDIATE;
1094         if (bit16) 
1095             sprintf (s,"%s",aop->aopu.aop_immd);
1096         else
1097             if (offset) 
1098                 sprintf(s,"(%s >> %d)",
1099                         aop->aopu.aop_immd,
1100                         offset*8);
1101             else
1102                 sprintf(s,"%s",
1103                         aop->aopu.aop_immd);
1104         pcop->name = Safe_calloc(1,strlen(s)+1);
1105         strcpy(pcop->name,s);   
1106         return pcop;
1107         
1108     case AOP_DIR:
1109         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1110         pcop->type = PO_DIR;
1111         if (offset)
1112             sprintf(s,"(%s + %d)",
1113                     aop->aopu.aop_dir,
1114                     offset);
1115         else
1116             sprintf(s,"%s",aop->aopu.aop_dir);
1117         pcop->name = Safe_calloc(1,strlen(s)+1);
1118         strcpy(pcop->name,s);   
1119         return pcop;
1120         
1121     case AOP_REG:
1122       {
1123         int len;
1124
1125         DEBUGemitcode(";","%d",__LINE__);
1126         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1127         pcop->type = PO_GPR_REGISTER;
1128         if (dname)
1129           rs = aop->aopu.aop_reg[offset]->dname;
1130         else 
1131           rs = aop->aopu.aop_reg[offset]->name;
1132
1133         PCOR(pcop)->rIdx = aop->aopu.aop_reg[offset]->rIdx;
1134         PCOR(pcop)->r = pic14_regWithIdx(aop->aopu.aop_reg[offset]->rIdx);
1135         // Really nasty hack to check for temporary registers
1136         len = strlen(rs);
1137         if(len >=3 && rs[0]=='r' && rs[1]=='0' && rs[2]=='x')
1138           pcop->type = PO_GPR_TEMP;
1139         else
1140           fprintf(stderr,"popGet - AOP_REG is not a temp: %s\n",rs);
1141
1142         DEBUGemitcode(";","%d  %s",__LINE__,rs);
1143         pcop->name = NULL;// Safe_calloc(1,(strlen(rs)+1));
1144         //strcpy(pcop->name,rs);   
1145         return pcop;
1146       }
1147
1148     case AOP_CRY:
1149       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1150       return pcop;
1151         
1152     case AOP_LIT:
1153       DEBUGemitcode(";","%d",__LINE__);
1154       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1155
1156     case AOP_STR:
1157       DEBUGemitcode(";","%d",__LINE__);
1158
1159       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1160       pcop->type = PO_STR;
1161
1162       //aop->coff = offset ;
1163         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1164           sprintf(s,"%s","acc");
1165         else
1166           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1167         pcop->name = Safe_calloc(1,strlen(s)+1);
1168         strcpy(pcop->name,s);   
1169         return pcop;
1170         
1171     }
1172
1173     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1174            "popGet got unsupported aop->type");
1175     exit(0);
1176 }
1177 /*-----------------------------------------------------------------*/
1178 /* aopPut - puts a string for a aop                                */
1179 /*-----------------------------------------------------------------*/
1180 static void aopPut (asmop *aop, char *s, int offset)
1181 {
1182     char *d = buffer ;
1183     symbol *lbl ;
1184
1185     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1186
1187     if (aop->size && offset > ( aop->size - 1)) {
1188         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1189                "aopPut got offset > aop->size");
1190         exit(0);
1191     }
1192
1193     /* will assign value to value */
1194     /* depending on where it is ofcourse */
1195     switch (aop->type) {
1196     case AOP_DIR:
1197         if (offset)
1198             sprintf(d,"(%s + %d)",
1199                     aop->aopu.aop_dir,offset);
1200         else
1201             sprintf(d,"%s",aop->aopu.aop_dir);
1202         
1203         if (strcmp(d,s)) {
1204           DEBUGemitcode(";","%d",__LINE__);
1205           if(strcmp(s,"W"))
1206             emitcode("movf","%s,w",s);
1207           emitcode("movwf","%s",d);
1208
1209           if(strcmp(s,"W"))
1210             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1211           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1212
1213
1214         }
1215         break;
1216         
1217     case AOP_REG:
1218         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1219             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1220           /*
1221             if (*s == '@'           ||
1222                 strcmp(s,"r0") == 0 ||
1223                 strcmp(s,"r1") == 0 ||
1224                 strcmp(s,"r2") == 0 ||
1225                 strcmp(s,"r3") == 0 ||
1226                 strcmp(s,"r4") == 0 ||
1227                 strcmp(s,"r5") == 0 ||
1228                 strcmp(s,"r6") == 0 || 
1229                 strcmp(s,"r7") == 0 )
1230                 emitcode("mov","%s,%s  ; %d",
1231                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1232             else
1233           */
1234
1235           if(strcmp(s,"W"))
1236             emitcode("movf","%s,w  ; %d",s,__LINE__);
1237
1238           emitcode("movwf","%s",
1239                    aop->aopu.aop_reg[offset]->name);
1240
1241           if(strcmp(s,"W"))
1242             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1243           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1244
1245         }
1246         break;
1247         
1248     case AOP_DPTR:
1249     case AOP_DPTR2:
1250     
1251     if (aop->type == AOP_DPTR2)
1252     {
1253         genSetDPTR(1);
1254     }
1255     
1256         if (aop->code) {
1257             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1258                    "aopPut writting to code space");
1259             exit(0);
1260         }
1261         
1262         while (offset > aop->coff) {
1263             aop->coff++;
1264             emitcode ("inc","dptr");
1265         }
1266         
1267         while (offset < aop->coff) {
1268             aop->coff-- ;
1269             emitcode("lcall","__decdptr");
1270         }
1271         
1272         aop->coff = offset;
1273         
1274         /* if not in accumulater */
1275         MOVA(s);        
1276         
1277         emitcode ("movx","@dptr,a");
1278         
1279     if (aop->type == AOP_DPTR2)
1280     {
1281         genSetDPTR(0);
1282     }
1283         break;
1284         
1285     case AOP_R0:
1286     case AOP_R1:
1287         while (offset > aop->coff) {
1288             aop->coff++;
1289             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1290         }
1291         while (offset < aop->coff) {
1292             aop->coff-- ;
1293             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1294         }
1295         aop->coff = offset;
1296         
1297         if (aop->paged) {
1298             MOVA(s);           
1299             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1300             
1301         } else
1302             if (*s == '@') {
1303                 MOVA(s);
1304                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1305             } else
1306                 if (strcmp(s,"r0") == 0 ||
1307                     strcmp(s,"r1") == 0 ||
1308                     strcmp(s,"r2") == 0 ||
1309                     strcmp(s,"r3") == 0 ||
1310                     strcmp(s,"r4") == 0 ||
1311                     strcmp(s,"r5") == 0 ||
1312                     strcmp(s,"r6") == 0 || 
1313                     strcmp(s,"r7") == 0 ) {
1314                     char buffer[10];
1315                     sprintf(buffer,"a%s",s);
1316                     emitcode("mov","@%s,%s",
1317                              aop->aopu.aop_ptr->name,buffer);
1318                 } else
1319                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1320         
1321         break;
1322         
1323     case AOP_STK:
1324         if (strcmp(s,"a") == 0)
1325             emitcode("push","acc");
1326         else
1327             emitcode("push","%s",s);
1328         
1329         break;
1330         
1331     case AOP_CRY:
1332         /* if bit variable */
1333         if (!aop->aopu.aop_dir) {
1334             emitcode("clr","a");
1335             emitcode("rlc","a");
1336         } else {
1337             if (s == zero) 
1338                 emitcode("clr","%s",aop->aopu.aop_dir);
1339             else
1340                 if (s == one)
1341                     emitcode("setb","%s",aop->aopu.aop_dir);
1342                 else
1343                     if (!strcmp(s,"c"))
1344                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1345                     else {
1346                         lbl = newiTempLabel(NULL);
1347                         
1348                         if (strcmp(s,"a")) {
1349                             MOVA(s);
1350                         }
1351                         emitcode("clr","c");
1352                         emitcode("jz","%05d_DS_",lbl->key+100);
1353                         emitcode("cpl","c");
1354                         emitcode("","%05d_DS_:",lbl->key+100);
1355                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1356                     }
1357         }
1358         break;
1359         
1360     case AOP_STR:
1361         aop->coff = offset;
1362         if (strcmp(aop->aopu.aop_str[offset],s))
1363             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1364         break;
1365         
1366     case AOP_ACC:
1367         aop->coff = offset;
1368         if (!offset && (strcmp(s,"acc") == 0))
1369             break;
1370         
1371         if (strcmp(aop->aopu.aop_str[offset],s))
1372             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1373         break;
1374
1375     default :
1376         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1377                "aopPut got unsupported aop->type");
1378         exit(0);    
1379     }    
1380
1381 }
1382
1383 /*-----------------------------------------------------------------*/
1384 /* reAdjustPreg - points a register back to where it should        */
1385 /*-----------------------------------------------------------------*/
1386 static void reAdjustPreg (asmop *aop)
1387 {
1388     int size ;
1389
1390     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1391     aop->coff = 0;
1392     if ((size = aop->size) <= 1)
1393         return ;
1394     size-- ;
1395     switch (aop->type) {
1396         case AOP_R0 :
1397         case AOP_R1 :
1398             while (size--)
1399                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1400             break;          
1401         case AOP_DPTR :
1402         case AOP_DPTR2:
1403             if (aop->type == AOP_DPTR2)
1404             {
1405                 genSetDPTR(1);
1406             } 
1407             while (size--)
1408             {
1409                 emitcode("lcall","__decdptr");
1410             }
1411                 
1412             if (aop->type == AOP_DPTR2)
1413             {
1414                 genSetDPTR(0);
1415             }                
1416             break;  
1417
1418     }   
1419
1420 }
1421
1422 #define AOP(op) op->aop
1423 #define AOP_TYPE(op) AOP(op)->type
1424 #define AOP_SIZE(op) AOP(op)->size
1425 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1426                        AOP_TYPE(x) == AOP_R0))
1427
1428 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1429                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1430                          AOP(x)->paged)) 
1431
1432 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1433                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1434                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1435
1436 /*-----------------------------------------------------------------*/
1437 /* genNotFloat - generates not for float operations              */
1438 /*-----------------------------------------------------------------*/
1439 static void genNotFloat (operand *op, operand *res)
1440 {
1441     int size, offset;
1442     char *l;
1443     symbol *tlbl ;
1444
1445     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1446     /* we will put 127 in the first byte of 
1447     the result */
1448     aopPut(AOP(res),"#127",0);
1449     size = AOP_SIZE(op) - 1;
1450     offset = 1;
1451
1452     l = aopGet(op->aop,offset++,FALSE,FALSE);
1453     MOVA(l);    
1454
1455     while(size--) {
1456         emitcode("orl","a,%s",
1457                  aopGet(op->aop,
1458                         offset++,FALSE,FALSE));
1459     }
1460     tlbl = newiTempLabel(NULL);
1461
1462     tlbl = newiTempLabel(NULL);
1463     aopPut(res->aop,one,1);
1464     emitcode("jz","%05d_DS_",(tlbl->key+100));
1465     aopPut(res->aop,zero,1);
1466     emitcode("","%05d_DS_:",(tlbl->key+100));
1467
1468     size = res->aop->size - 2;
1469     offset = 2;    
1470     /* put zeros in the rest */
1471     while (size--) 
1472         aopPut(res->aop,zero,offset++);
1473 }
1474
1475 #if 0
1476 /*-----------------------------------------------------------------*/
1477 /* opIsGptr: returns non-zero if the passed operand is             */   
1478 /* a generic pointer type.                                         */
1479 /*-----------------------------------------------------------------*/ 
1480 static int opIsGptr(operand *op)
1481 {
1482     sym_link *type = operandType(op);
1483     
1484     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1485     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1486     {
1487         return 1;
1488     }
1489     return 0;        
1490 }
1491 #endif
1492
1493 /*-----------------------------------------------------------------*/
1494 /* getDataSize - get the operand data size                         */
1495 /*-----------------------------------------------------------------*/
1496 static int getDataSize(operand *op)
1497 {
1498     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1499
1500
1501     return AOP_SIZE(op);
1502
1503     // tsd- in the pic port, the genptr size is 1, so this code here
1504     // fails. ( in the 8051 port, the size was 4).
1505 #if 0
1506     int size;
1507     size = AOP_SIZE(op);
1508     if (size == GPTRSIZE)
1509     {
1510         sym_link *type = operandType(op);
1511         if (IS_GENPTR(type))
1512         {
1513             /* generic pointer; arithmetic operations
1514              * should ignore the high byte (pointer type).
1515              */
1516             size--;
1517     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1518         }
1519     }
1520     return size;
1521 #endif
1522 }
1523
1524 /*-----------------------------------------------------------------*/
1525 /* outAcc - output Acc                                             */
1526 /*-----------------------------------------------------------------*/
1527 static void outAcc(operand *result)
1528 {
1529     int size, offset;
1530     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1531     size = getDataSize(result);
1532     if(size){
1533         aopPut(AOP(result),"a",0);
1534         size--;
1535         offset = 1;
1536         /* unsigned or positive */
1537         while(size--){
1538             aopPut(AOP(result),zero,offset++);
1539         }
1540     }
1541 }
1542
1543 /*-----------------------------------------------------------------*/
1544 /* outBitC - output a bit C                                        */
1545 /*-----------------------------------------------------------------*/
1546 static void outBitC(operand *result)
1547 {
1548
1549     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1550     /* if the result is bit */
1551     if (AOP_TYPE(result) == AOP_CRY) 
1552         aopPut(AOP(result),"c",0);
1553     else {
1554         emitcode("clr","a  ; %d", __LINE__);
1555         emitcode("rlc","a");
1556         outAcc(result);
1557     }
1558 }
1559
1560 /*-----------------------------------------------------------------*/
1561 /* toBoolean - emit code for orl a,operator(sizeop)                */
1562 /*-----------------------------------------------------------------*/
1563 static void toBoolean(operand *oper)
1564 {
1565     int size = AOP_SIZE(oper) - 1;
1566     int offset = 1;
1567
1568     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1569
1570     if ( AOP_TYPE(oper) != AOP_ACC) {
1571       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1572       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1573     }
1574     while (size--) {
1575       emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1576       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1577     }
1578 }
1579
1580
1581 /*-----------------------------------------------------------------*/
1582 /* genNot - generate code for ! operation                          */
1583 /*-----------------------------------------------------------------*/
1584 static void genNot (iCode *ic)
1585 {
1586     symbol *tlbl;
1587     sym_link *optype = operandType(IC_LEFT(ic));
1588
1589     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1590     /* assign asmOps to operand & result */
1591     aopOp (IC_LEFT(ic),ic,FALSE);
1592     aopOp (IC_RESULT(ic),ic,TRUE);
1593
1594     /* if in bit space then a special case */
1595     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1596       emitcode("movlw","1<<%s");
1597       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1598       //emitcode("cpl","c"); 
1599       //outBitC(IC_RESULT(ic));
1600       goto release;
1601     }
1602
1603     /* if type float then do float */
1604     if (IS_FLOAT(optype)) {
1605         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1606         goto release;
1607     }
1608
1609     toBoolean(IC_LEFT(ic));
1610
1611     tlbl = newiTempLabel(NULL);
1612     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1613     emitcode("","%05d_DS_:",tlbl->key+100);
1614     outBitC(IC_RESULT(ic));
1615
1616 release:    
1617     /* release the aops */
1618     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1619     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1620 }
1621
1622
1623 /*-----------------------------------------------------------------*/
1624 /* genCpl - generate code for complement                           */
1625 /*-----------------------------------------------------------------*/
1626 static void genCpl (iCode *ic)
1627 {
1628     int offset = 0;
1629     int size ;
1630
1631
1632     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1633     /* assign asmOps to operand & result */
1634     aopOp (IC_LEFT(ic),ic,FALSE);
1635     aopOp (IC_RESULT(ic),ic,TRUE);
1636
1637     /* if both are in bit space then 
1638     a special case */
1639     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1640         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1641
1642         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1643         emitcode("cpl","c"); 
1644         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1645         goto release; 
1646     } 
1647
1648     size = AOP_SIZE(IC_RESULT(ic));
1649     while (size--) {
1650         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1651         MOVA(l);       
1652         emitcode("cpl","a");
1653         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1654     }
1655
1656
1657 release:
1658     /* release the aops */
1659     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1660     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1661 }
1662
1663 /*-----------------------------------------------------------------*/
1664 /* genUminusFloat - unary minus for floating points                */
1665 /*-----------------------------------------------------------------*/
1666 static void genUminusFloat(operand *op,operand *result)
1667 {
1668     int size ,offset =0 ;
1669     char *l;
1670
1671     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1672     /* for this we just need to flip the 
1673     first it then copy the rest in place */
1674     size = AOP_SIZE(op) - 1;
1675     l = aopGet(AOP(op),3,FALSE,FALSE);
1676
1677     MOVA(l);    
1678
1679     emitcode("cpl","acc.7");
1680     aopPut(AOP(result),"a",3);    
1681
1682     while(size--) {
1683         aopPut(AOP(result),
1684                aopGet(AOP(op),offset,FALSE,FALSE),
1685                offset);
1686         offset++;
1687     }          
1688 }
1689
1690 /*-----------------------------------------------------------------*/
1691 /* genUminus - unary minus code generation                         */
1692 /*-----------------------------------------------------------------*/
1693 static void genUminus (iCode *ic)
1694 {
1695     int offset ,size ;
1696     sym_link *optype, *rtype;
1697
1698
1699     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1700     /* assign asmops */
1701     aopOp(IC_LEFT(ic),ic,FALSE);
1702     aopOp(IC_RESULT(ic),ic,TRUE);
1703
1704     /* if both in bit space then special
1705     case */
1706     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1707         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1708
1709         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1710         emitcode("cpl","c"); 
1711         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1712         goto release; 
1713     } 
1714
1715     optype = operandType(IC_LEFT(ic));
1716     rtype = operandType(IC_RESULT(ic));
1717
1718     /* if float then do float stuff */
1719     if (IS_FLOAT(optype)) {
1720         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1721         goto release;
1722     }
1723
1724     /* otherwise subtract from zero */
1725     size = AOP_SIZE(IC_LEFT(ic));
1726     offset = 0 ;
1727     CLRC ;
1728     while(size--) {
1729         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1730         if (!strcmp(l,"a")) {
1731             emitcode("cpl","a");
1732             emitcode("inc","a");
1733         } else {
1734             emitcode("clr","a");
1735             emitcode("subb","a,%s",l);
1736         }       
1737         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1738     }
1739
1740     /* if any remaining bytes in the result */
1741     /* we just need to propagate the sign   */
1742     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1743         emitcode("rlc","a");
1744         emitcode("subb","a,acc");
1745         while (size--) 
1746             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1747     }       
1748
1749 release:
1750     /* release the aops */
1751     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1752     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* saveRegisters - will look for a call and save the registers     */
1757 /*-----------------------------------------------------------------*/
1758 static void saveRegisters(iCode *lic) 
1759 {
1760     int i;
1761     iCode *ic;
1762     bitVect *rsave;
1763     sym_link *detype;
1764
1765     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1766     /* look for call */
1767     for (ic = lic ; ic ; ic = ic->next) 
1768         if (ic->op == CALL || ic->op == PCALL)
1769             break;
1770
1771     if (!ic) {
1772         fprintf(stderr,"found parameter push with no function call\n");
1773         return ;
1774     }
1775
1776     /* if the registers have been saved already then
1777     do nothing */
1778     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1779         return ;
1780
1781     /* find the registers in use at this time 
1782     and push them away to safety */
1783     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1784                           ic->rUsed);
1785
1786     ic->regsSaved = 1;
1787     if (options.useXstack) {
1788         if (bitVectBitValue(rsave,R0_IDX))
1789             emitcode("mov","b,r0");
1790         emitcode("mov","r0,%s",spname);
1791         for (i = 0 ; i < pic14_nRegs ; i++) {
1792             if (bitVectBitValue(rsave,i)) {
1793                 if (i == R0_IDX)
1794                     emitcode("mov","a,b");
1795                 else
1796                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1797                 emitcode("movx","@r0,a");
1798                 emitcode("inc","r0");
1799             }
1800         }
1801         emitcode("mov","%s,r0",spname);
1802         if (bitVectBitValue(rsave,R0_IDX))
1803             emitcode("mov","r0,b");         
1804     } else
1805         for (i = 0 ; i < pic14_nRegs ; i++) {
1806             if (bitVectBitValue(rsave,i))
1807                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1808         }
1809
1810     detype = getSpec(operandType(IC_LEFT(ic)));
1811     if (detype        && 
1812         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1813         IS_ISR(currFunc->etype) &&
1814         !ic->bankSaved) 
1815
1816         saverbank(SPEC_BANK(detype),ic,TRUE);
1817
1818 }
1819 /*-----------------------------------------------------------------*/
1820 /* unsaveRegisters - pop the pushed registers                      */
1821 /*-----------------------------------------------------------------*/
1822 static void unsaveRegisters (iCode *ic)
1823 {
1824     int i;
1825     bitVect *rsave;
1826
1827     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1828     /* find the registers in use at this time 
1829     and push them away to safety */
1830     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1831                           ic->rUsed);
1832     
1833     if (options.useXstack) {
1834         emitcode("mov","r0,%s",spname); 
1835         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1836             if (bitVectBitValue(rsave,i)) {
1837                 emitcode("dec","r0");
1838                 emitcode("movx","a,@r0");
1839                 if (i == R0_IDX)
1840                     emitcode("mov","b,a");
1841                 else
1842                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1843             }       
1844
1845         }
1846         emitcode("mov","%s,r0",spname);
1847         if (bitVectBitValue(rsave,R0_IDX))
1848             emitcode("mov","r0,b");
1849     } else
1850         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1851             if (bitVectBitValue(rsave,i))
1852                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1853         }
1854
1855 }  
1856
1857
1858 /*-----------------------------------------------------------------*/
1859 /* pushSide -                                                      */
1860 /*-----------------------------------------------------------------*/
1861 static void pushSide(operand * oper, int size)
1862 {
1863         int offset = 0;
1864     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1865         while (size--) {
1866                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1867                 if (AOP_TYPE(oper) != AOP_REG &&
1868                     AOP_TYPE(oper) != AOP_DIR &&
1869                     strcmp(l,"a") ) {
1870                         emitcode("mov","a,%s",l);
1871                         emitcode("push","acc");
1872                 } else
1873                         emitcode("push","%s",l);
1874         }
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* assignResultValue -                                             */
1879 /*-----------------------------------------------------------------*/
1880 static void assignResultValue(operand * oper)
1881 {
1882         int offset = 0;
1883         int size = AOP_SIZE(oper);
1884
1885     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1886
1887     // The last byte in the assignment is in W
1888     aopPut(AOP(oper),"W",size-1);
1889
1890     if(size>1) {
1891       while (--size) {
1892         aopPut(AOP(oper),fReturn[offset],offset);
1893         offset++;
1894
1895       }
1896     }
1897 }
1898
1899
1900 /*-----------------------------------------------------------------*/
1901 /* genXpush - pushes onto the external stack                       */
1902 /*-----------------------------------------------------------------*/
1903 static void genXpush (iCode *ic)
1904 {
1905     asmop *aop = newAsmop(0);
1906     regs *r ;
1907     int size,offset = 0;
1908
1909     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1910     aopOp(IC_LEFT(ic),ic,FALSE);
1911     r = getFreePtr(ic,&aop,FALSE);
1912
1913     
1914     emitcode("mov","%s,_spx",r->name);
1915
1916     size = AOP_SIZE(IC_LEFT(ic));
1917     while(size--) {
1918
1919         char *l = aopGet(AOP(IC_LEFT(ic)),
1920                          offset++,FALSE,FALSE); 
1921         MOVA(l);            
1922         emitcode("movx","@%s,a",r->name);       
1923         emitcode("inc","%s",r->name);
1924
1925     }
1926
1927         
1928     emitcode("mov","_spx,%s",r->name);
1929
1930     freeAsmop(NULL,aop,ic,TRUE);
1931     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* genIpush - genrate code for pushing this gets a little complex  */
1936 /*-----------------------------------------------------------------*/
1937 static void genIpush (iCode *ic)
1938 {
1939     int size, offset = 0 ;
1940     char *l;
1941
1942
1943     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1944     /* if this is not a parm push : ie. it is spill push 
1945     and spill push is always done on the local stack */
1946     if (!ic->parmPush) {
1947
1948         /* and the item is spilt then do nothing */
1949         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1950             return ;
1951
1952         aopOp(IC_LEFT(ic),ic,FALSE);
1953         size = AOP_SIZE(IC_LEFT(ic));
1954         /* push it on the stack */
1955         while(size--) {
1956             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1957             if (*l == '#') {
1958                 MOVA(l);
1959                 l = "acc";
1960             }
1961             emitcode("push","%s",l);
1962         }
1963         return ;        
1964     }
1965
1966     /* this is a paramter push: in this case we call
1967     the routine to find the call and save those
1968     registers that need to be saved */   
1969     saveRegisters(ic);
1970
1971     /* if use external stack then call the external
1972     stack pushing routine */
1973     if (options.useXstack) {
1974         genXpush(ic);
1975         return ;
1976     }
1977
1978     /* then do the push */
1979     aopOp(IC_LEFT(ic),ic,FALSE);
1980
1981
1982         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1983     size = AOP_SIZE(IC_LEFT(ic));
1984
1985     while (size--) {
1986         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1987         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1988             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1989             strcmp(l,"a") ) {
1990             emitcode("mov","a,%s",l);
1991             emitcode("push","acc");
1992         } else
1993             emitcode("push","%s",l);
1994     }       
1995
1996     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* genIpop - recover the registers: can happen only for spilling   */
2001 /*-----------------------------------------------------------------*/
2002 static void genIpop (iCode *ic)
2003 {
2004     int size,offset ;
2005
2006
2007     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2008     /* if the temp was not pushed then */
2009     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2010         return ;
2011
2012     aopOp(IC_LEFT(ic),ic,FALSE);
2013     size = AOP_SIZE(IC_LEFT(ic));
2014     offset = (size-1);
2015     while (size--) 
2016         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2017                                    FALSE,TRUE));
2018
2019     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* unsaverbank - restores the resgister bank from stack            */
2024 /*-----------------------------------------------------------------*/
2025 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2026 {
2027     int i;
2028     asmop *aop ;
2029     regs *r = NULL;
2030
2031     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2032     if (popPsw) {
2033         if (options.useXstack) {
2034             aop = newAsmop(0);
2035             r = getFreePtr(ic,&aop,FALSE);
2036             
2037             
2038             emitcode("mov","%s,_spx",r->name);
2039             emitcode("movx","a,@%s",r->name);
2040             emitcode("mov","psw,a");
2041             emitcode("dec","%s",r->name);
2042             
2043         }else
2044             emitcode ("pop","psw");
2045     }
2046
2047     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2048         if (options.useXstack) {       
2049             emitcode("movx","a,@%s",r->name);
2050             //emitcode("mov","(%s+%d),a",
2051             //       regspic14[i].base,8*bank+regspic14[i].offset);
2052             emitcode("dec","%s",r->name);
2053
2054         } else 
2055           emitcode("pop",""); //"(%s+%d)",
2056         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2057     }
2058
2059     if (options.useXstack) {
2060
2061         emitcode("mov","_spx,%s",r->name);
2062         freeAsmop(NULL,aop,ic,TRUE);
2063
2064     } 
2065 }
2066
2067 /*-----------------------------------------------------------------*/
2068 /* saverbank - saves an entire register bank on the stack          */
2069 /*-----------------------------------------------------------------*/
2070 static void saverbank (int bank, iCode *ic, bool pushPsw)
2071 {
2072     int i;
2073     asmop *aop ;
2074     regs *r = NULL;
2075
2076     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2077     if (options.useXstack) {
2078
2079         aop = newAsmop(0);
2080         r = getFreePtr(ic,&aop,FALSE);  
2081         emitcode("mov","%s,_spx",r->name);
2082
2083     }
2084
2085     for (i = 0 ; i < pic14_nRegs ;i++) {
2086         if (options.useXstack) {
2087             emitcode("inc","%s",r->name);
2088             //emitcode("mov","a,(%s+%d)",
2089             //         regspic14[i].base,8*bank+regspic14[i].offset);
2090             emitcode("movx","@%s,a",r->name);           
2091         } else 
2092           emitcode("push","");// "(%s+%d)",
2093                      //regspic14[i].base,8*bank+regspic14[i].offset);
2094     }
2095     
2096     if (pushPsw) {
2097         if (options.useXstack) {
2098             emitcode("mov","a,psw");
2099             emitcode("movx","@%s,a",r->name);   
2100             emitcode("inc","%s",r->name);
2101             emitcode("mov","_spx,%s",r->name);       
2102             freeAsmop (NULL,aop,ic,TRUE);
2103             
2104         } else
2105             emitcode("push","psw");
2106         
2107         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2108     }
2109     ic->bankSaved = 1;
2110
2111 }
2112
2113 /*-----------------------------------------------------------------*/
2114 /* genCall - generates a call statement                            */
2115 /*-----------------------------------------------------------------*/
2116 static void genCall (iCode *ic)
2117 {
2118     sym_link *detype;   
2119
2120     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2121
2122     /* if caller saves & we have not saved then */
2123     if (!ic->regsSaved)
2124         saveRegisters(ic);
2125
2126     /* if we are calling a function that is not using
2127     the same register bank then we need to save the
2128     destination registers on the stack */
2129     detype = getSpec(operandType(IC_LEFT(ic)));
2130     if (detype        && 
2131         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2132         IS_ISR(currFunc->etype) &&
2133         !ic->bankSaved) 
2134
2135         saverbank(SPEC_BANK(detype),ic,TRUE);
2136
2137     /* if send set is not empty the assign */
2138     if (_G.sendSet) {
2139         iCode *sic ;
2140
2141         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2142              sic = setNextItem(_G.sendSet)) {
2143             int size, offset = 0;
2144
2145             aopOp(IC_LEFT(sic),sic,FALSE);
2146             size = AOP_SIZE(IC_LEFT(sic));
2147             while (size--) {
2148                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2149                                 FALSE,FALSE);
2150                 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2151
2152                 if (strcmp(l,fReturn[offset])) {
2153
2154                   if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2155                        ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2156                     emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2157                   //emitcode("movlw","%s",l);
2158                   else
2159                     emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2160                   //emitcode("movf","%s,w",l);
2161
2162                   // The last one is passed in W
2163                   if(size)
2164                     emitcode("movwf","%s",fReturn[offset]);
2165                 }
2166                 offset++;
2167             }
2168             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2169         }
2170         _G.sendSet = NULL;
2171     }
2172     /* make the call */
2173     emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2174                                         OP_SYMBOL(IC_LEFT(ic))->rname :
2175                                         OP_SYMBOL(IC_LEFT(ic))->name));
2176
2177     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2178                            OP_SYMBOL(IC_LEFT(ic))->rname :
2179                            OP_SYMBOL(IC_LEFT(ic))->name));
2180
2181     /* if we need assign a result value */
2182     if ((IS_ITEMP(IC_RESULT(ic)) && 
2183          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2184           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2185         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2186
2187         _G.accInUse++;
2188         aopOp(IC_RESULT(ic),ic,FALSE);
2189         _G.accInUse--;
2190
2191         assignResultValue(IC_RESULT(ic));
2192                 
2193         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2194     }
2195
2196     /* adjust the stack for parameters if 
2197     required */
2198     if (ic->parmBytes) {
2199         int i;
2200         if (ic->parmBytes > 3) {
2201             emitcode("mov","a,%s",spname);
2202             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2203             emitcode("mov","%s,a",spname);
2204         } else 
2205             for ( i = 0 ; i <  ic->parmBytes ;i++)
2206                 emitcode("dec","%s",spname);
2207
2208     }
2209
2210     /* if register bank was saved then pop them */
2211     if (ic->bankSaved)
2212         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2213
2214     /* if we hade saved some registers then unsave them */
2215     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2216         unsaveRegisters (ic);
2217
2218
2219 }
2220
2221 /*-----------------------------------------------------------------*/
2222 /* genPcall - generates a call by pointer statement                */
2223 /*-----------------------------------------------------------------*/
2224 static void genPcall (iCode *ic)
2225 {
2226     sym_link *detype;
2227     symbol *rlbl = newiTempLabel(NULL);
2228
2229
2230     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231     /* if caller saves & we have not saved then */
2232     if (!ic->regsSaved)
2233         saveRegisters(ic);
2234
2235     /* if we are calling a function that is not using
2236     the same register bank then we need to save the
2237     destination registers on the stack */
2238     detype = getSpec(operandType(IC_LEFT(ic)));
2239     if (detype        && 
2240         IS_ISR(currFunc->etype) &&
2241         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2242         saverbank(SPEC_BANK(detype),ic,TRUE);
2243
2244
2245     /* push the return address on to the stack */
2246     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2247     emitcode("push","acc");    
2248     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2249     emitcode("push","acc");
2250     
2251     if (options.model == MODEL_FLAT24)
2252     {
2253         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2254         emitcode("push","acc");    
2255     }
2256
2257     /* now push the calling address */
2258     aopOp(IC_LEFT(ic),ic,FALSE);
2259
2260     pushSide(IC_LEFT(ic), FPTRSIZE);
2261
2262     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2263
2264     /* if send set is not empty the assign */
2265     if (_G.sendSet) {
2266         iCode *sic ;
2267
2268         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2269              sic = setNextItem(_G.sendSet)) {
2270             int size, offset = 0;
2271             aopOp(IC_LEFT(sic),sic,FALSE);
2272             size = AOP_SIZE(IC_LEFT(sic));
2273             while (size--) {
2274                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2275                                 FALSE,FALSE);
2276                 if (strcmp(l,fReturn[offset]))
2277                     emitcode("mov","%s,%s",
2278                              fReturn[offset],
2279                              l);
2280                 offset++;
2281             }
2282             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2283         }
2284         _G.sendSet = NULL;
2285     }
2286
2287     emitcode("ret","");
2288     emitcode("","%05d_DS_:",(rlbl->key+100));
2289
2290
2291     /* if we need assign a result value */
2292     if ((IS_ITEMP(IC_RESULT(ic)) &&
2293          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2294           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2295         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2296
2297         _G.accInUse++;
2298         aopOp(IC_RESULT(ic),ic,FALSE);
2299         _G.accInUse--;
2300         
2301         assignResultValue(IC_RESULT(ic));
2302
2303         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2304     }
2305
2306     /* adjust the stack for parameters if 
2307     required */
2308     if (ic->parmBytes) {
2309         int i;
2310         if (ic->parmBytes > 3) {
2311             emitcode("mov","a,%s",spname);
2312             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2313             emitcode("mov","%s,a",spname);
2314         } else 
2315             for ( i = 0 ; i <  ic->parmBytes ;i++)
2316                 emitcode("dec","%s",spname);
2317
2318     }
2319
2320     /* if register bank was saved then unsave them */
2321     if (detype        && 
2322         (SPEC_BANK(currFunc->etype) != 
2323          SPEC_BANK(detype)))
2324         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2325
2326     /* if we hade saved some registers then
2327     unsave them */
2328     if (ic->regsSaved)
2329         unsaveRegisters (ic);
2330
2331 }
2332
2333 /*-----------------------------------------------------------------*/
2334 /* resultRemat - result  is rematerializable                       */
2335 /*-----------------------------------------------------------------*/
2336 static int resultRemat (iCode *ic)
2337 {
2338     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2339     if (SKIP_IC(ic) || ic->op == IFX)
2340         return 0;
2341
2342     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2343         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2344         if (sym->remat && !POINTER_SET(ic)) 
2345             return 1;
2346     }
2347
2348     return 0;
2349 }
2350
2351 #if defined(__BORLANDC__) || defined(_MSC_VER)
2352 #define STRCASECMP stricmp
2353 #else
2354 #define STRCASECMP strcasecmp
2355 #endif
2356
2357 /*-----------------------------------------------------------------*/
2358 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2359 /*-----------------------------------------------------------------*/
2360 static bool inExcludeList(char *s)
2361 {
2362     int i =0;
2363     
2364     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2365     if (options.excludeRegs[i] &&
2366     STRCASECMP(options.excludeRegs[i],"none") == 0)
2367         return FALSE ;
2368
2369     for ( i = 0 ; options.excludeRegs[i]; i++) {
2370         if (options.excludeRegs[i] &&
2371         STRCASECMP(s,options.excludeRegs[i]) == 0)
2372             return TRUE;
2373     }
2374     return FALSE ;
2375 }
2376
2377 /*-----------------------------------------------------------------*/
2378 /* genFunction - generated code for function entry                 */
2379 /*-----------------------------------------------------------------*/
2380 static void genFunction (iCode *ic)
2381 {
2382     symbol *sym;
2383     sym_link *fetype;
2384
2385     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2386     labelOffset += FUNCTION_LABEL_INC;
2387
2388     _G.nRegsSaved = 0;
2389     /* create the function header */
2390     emitcode(";","-----------------------------------------");
2391     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2392     emitcode(";","-----------------------------------------");
2393
2394     emitcode("","%s:",sym->rname);
2395     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2396
2397     fetype = getSpec(operandType(IC_LEFT(ic)));
2398
2399     /* if critical function then turn interrupts off */
2400     if (SPEC_CRTCL(fetype))
2401         emitcode("clr","ea");
2402
2403     /* here we need to generate the equates for the
2404        register bank if required */
2405 #if 0
2406     if (SPEC_BANK(fetype) != rbank) {
2407         int i ;
2408
2409         rbank = SPEC_BANK(fetype);
2410         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2411             if (strcmp(regspic14[i].base,"0") == 0)
2412                 emitcode("","%s = 0x%02x",
2413                          regspic14[i].dname,
2414                          8*rbank+regspic14[i].offset);
2415             else
2416                 emitcode ("","%s = %s + 0x%02x",
2417                           regspic14[i].dname,
2418                           regspic14[i].base,
2419                           8*rbank+regspic14[i].offset);
2420         }
2421     }
2422 #endif
2423
2424     /* if this is an interrupt service routine then
2425     save acc, b, dpl, dph  */
2426     if (IS_ISR(sym->etype)) {
2427         
2428         if (!inExcludeList("acc"))          
2429             emitcode ("push","acc");    
2430         if (!inExcludeList("b"))
2431             emitcode ("push","b");
2432         if (!inExcludeList("dpl"))
2433             emitcode ("push","dpl");
2434         if (!inExcludeList("dph"))
2435             emitcode ("push","dph");
2436         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2437         {
2438             emitcode ("push", "dpx");
2439             /* Make sure we're using standard DPTR */
2440             emitcode ("push", "dps");
2441             emitcode ("mov", "dps, #0x00");
2442             if (options.stack10bit)
2443             {   
2444                 /* This ISR could conceivably use DPTR2. Better save it. */
2445                 emitcode ("push", "dpl1");
2446                 emitcode ("push", "dph1");
2447                 emitcode ("push", "dpx1");
2448             }
2449         }
2450         /* if this isr has no bank i.e. is going to
2451            run with bank 0 , then we need to save more
2452            registers :-) */
2453         if (!SPEC_BANK(sym->etype)) {
2454
2455             /* if this function does not call any other
2456                function then we can be economical and
2457                save only those registers that are used */
2458             if (! sym->hasFcall) {
2459                 int i;
2460
2461                 /* if any registers used */
2462                 if (sym->regsUsed) {
2463                     /* save the registers used */
2464                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2465                         if (bitVectBitValue(sym->regsUsed,i) ||
2466                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2467                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2468                     }
2469                 }
2470                 
2471             } else {
2472                 /* this function has  a function call cannot
2473                    determines register usage so we will have the
2474                    entire bank */
2475                 saverbank(0,ic,FALSE);
2476             }       
2477         }
2478     } else {
2479         /* if callee-save to be used for this function
2480            then save the registers being used in this function */
2481         if (sym->calleeSave) {
2482             int i;
2483             
2484             /* if any registers used */
2485             if (sym->regsUsed) {
2486                 /* save the registers used */
2487                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2488                     if (bitVectBitValue(sym->regsUsed,i) ||
2489                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2490                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2491                         _G.nRegsSaved++;
2492                     }
2493                 }
2494             }
2495         }
2496     }
2497
2498     /* set the register bank to the desired value */
2499     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2500         emitcode("push","psw");
2501         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2502     }
2503
2504     if (IS_RENT(sym->etype) || options.stackAuto) {
2505
2506         if (options.useXstack) {
2507             emitcode("mov","r0,%s",spname);
2508             emitcode("mov","a,_bp");
2509             emitcode("movx","@r0,a");
2510             emitcode("inc","%s",spname);
2511         }
2512         else
2513         {
2514             /* set up the stack */
2515             emitcode ("push","_bp");     /* save the callers stack  */
2516         }
2517         emitcode ("mov","_bp,%s",spname);
2518     }
2519
2520     /* adjust the stack for the function */
2521     if (sym->stack) {
2522
2523         int i = sym->stack;
2524         if (i > 256 ) 
2525             werror(W_STACK_OVERFLOW,sym->name);
2526
2527         if (i > 3 && sym->recvSize < 4) {              
2528
2529             emitcode ("mov","a,sp");
2530             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2531             emitcode ("mov","sp,a");
2532            
2533         }
2534         else
2535             while(i--)
2536                 emitcode("inc","sp");
2537     }
2538
2539      if (sym->xstack) {
2540
2541         emitcode ("mov","a,_spx");
2542         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2543         emitcode ("mov","_spx,a");
2544     }    
2545
2546 }
2547
2548 /*-----------------------------------------------------------------*/
2549 /* genEndFunction - generates epilogue for functions               */
2550 /*-----------------------------------------------------------------*/
2551 static void genEndFunction (iCode *ic)
2552 {
2553     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2554
2555     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2556
2557     if (IS_RENT(sym->etype) || options.stackAuto)
2558     {
2559         emitcode ("mov","%s,_bp",spname);
2560     }
2561
2562     /* if use external stack but some variables were
2563     added to the local stack then decrement the
2564     local stack */
2565     if (options.useXstack && sym->stack) {      
2566         emitcode("mov","a,sp");
2567         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2568         emitcode("mov","sp,a");
2569     }
2570
2571
2572     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2573         if (options.useXstack) {
2574             emitcode("mov","r0,%s",spname);
2575             emitcode("movx","a,@r0");
2576             emitcode("mov","_bp,a");
2577             emitcode("dec","%s",spname);
2578         }
2579         else
2580         {
2581             emitcode ("pop","_bp");
2582         }
2583     }
2584
2585     /* restore the register bank  */    
2586     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2587         emitcode ("pop","psw");
2588
2589     if (IS_ISR(sym->etype)) {
2590
2591         /* now we need to restore the registers */
2592         /* if this isr has no bank i.e. is going to
2593            run with bank 0 , then we need to save more
2594            registers :-) */
2595         if (!SPEC_BANK(sym->etype)) {
2596             
2597             /* if this function does not call any other
2598                function then we can be economical and
2599                save only those registers that are used */
2600             if (! sym->hasFcall) {
2601                 int i;
2602                 
2603                 /* if any registers used */
2604                 if (sym->regsUsed) {
2605                     /* save the registers used */
2606                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2607                         if (bitVectBitValue(sym->regsUsed,i) ||
2608                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2609                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2610                     }
2611                 }
2612                 
2613             } else {
2614                 /* this function has  a function call cannot
2615                    determines register usage so we will have the
2616                    entire bank */
2617                 unsaverbank(0,ic,FALSE);
2618             }       
2619         }
2620
2621         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2622         {
2623             if (options.stack10bit)
2624             {
2625                 emitcode ("pop", "dpx1");
2626                 emitcode ("pop", "dph1");
2627                 emitcode ("pop", "dpl1");
2628             }   
2629             emitcode ("pop", "dps");
2630             emitcode ("pop", "dpx");
2631         }
2632         if (!inExcludeList("dph"))
2633             emitcode ("pop","dph");
2634         if (!inExcludeList("dpl"))
2635             emitcode ("pop","dpl");
2636         if (!inExcludeList("b"))
2637             emitcode ("pop","b");
2638         if (!inExcludeList("acc"))
2639             emitcode ("pop","acc");
2640
2641         if (SPEC_CRTCL(sym->etype))
2642             emitcode("setb","ea");
2643
2644         /* if debug then send end of function */
2645 /*      if (options.debug && currFunc) { */
2646         if (currFunc) {
2647             _G.debugLine = 1;
2648             emitcode(";","C$%s$%d$%d$%d ==.",
2649                      FileBaseName(ic->filename),currFunc->lastLine,
2650                      ic->level,ic->block); 
2651             if (IS_STATIC(currFunc->etype))         
2652                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2653             else
2654                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2655             _G.debugLine = 0;
2656         }
2657         
2658         emitcode ("reti","");
2659     }
2660     else {
2661         if (SPEC_CRTCL(sym->etype))
2662             emitcode("setb","ea");
2663         
2664         if (sym->calleeSave) {
2665             int i;
2666             
2667             /* if any registers used */
2668             if (sym->regsUsed) {
2669                 /* save the registers used */
2670                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2671                     if (bitVectBitValue(sym->regsUsed,i) ||
2672                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2673                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2674                 }
2675             }
2676             
2677         }
2678
2679         /* if debug then send end of function */
2680         if (currFunc) {
2681             _G.debugLine = 1;
2682             emitcode(";","C$%s$%d$%d$%d ==.",
2683                      FileBaseName(ic->filename),currFunc->lastLine,
2684                      ic->level,ic->block); 
2685             if (IS_STATIC(currFunc->etype))         
2686                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2687             else
2688                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2689             _G.debugLine = 0;
2690         }
2691
2692         emitcode ("return","");
2693         emitpcode(POC_RETURN,NULL);
2694
2695         /* Mark the end of a function */
2696         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2697     }
2698
2699 }
2700
2701 /*-----------------------------------------------------------------*/
2702 /* genRet - generate code for return statement                     */
2703 /*-----------------------------------------------------------------*/
2704 static void genRet (iCode *ic)
2705 {
2706     int size,offset = 0 , pushed = 0;
2707     
2708     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2709     /* if we have no return value then
2710        just generate the "ret" */
2711     if (!IC_LEFT(ic)) 
2712         goto jumpret;       
2713     
2714     /* we have something to return then
2715        move the return value into place */
2716     aopOp(IC_LEFT(ic),ic,FALSE);
2717     size = AOP_SIZE(IC_LEFT(ic));
2718     
2719     while (size--) {
2720             char *l ;
2721             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2722                     /* #NOCHANGE */
2723                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2724                            FALSE,TRUE);
2725                     emitcode("push","%s",l);
2726                     pushed++;
2727             } else {
2728                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2729                                FALSE,FALSE);
2730                     if (strcmp(fReturn[offset],l)) {
2731                       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2732                           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2733                         emitcode("movlw","%s",l);
2734                       else
2735                         emitcode("movf","%s,w",l);
2736                       if(size)
2737                         emitcode("movwf","%s",fReturn[offset]);
2738                       offset++;
2739                     }
2740             }
2741     }    
2742
2743     if (pushed) {
2744         while(pushed) {
2745             pushed--;
2746             if (strcmp(fReturn[pushed],"a"))
2747                 emitcode("pop",fReturn[pushed]);
2748             else
2749                 emitcode("pop","acc");
2750         }
2751     }
2752     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2753     
2754  jumpret:
2755         /* generate a jump to the return label
2756            if the next is not the return statement */
2757     if (!(ic->next && ic->next->op == LABEL &&
2758           IC_LABEL(ic->next) == returnLabel))
2759         
2760         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2761     
2762 }
2763
2764 /*-----------------------------------------------------------------*/
2765 /* genLabel - generates a label                                    */
2766 /*-----------------------------------------------------------------*/
2767 static void genLabel (iCode *ic)
2768 {
2769     /* special case never generate */
2770     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2771     if (IC_LABEL(ic) == entryLabel)
2772         return ;
2773
2774     emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2775     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2776 }
2777
2778 /*-----------------------------------------------------------------*/
2779 /* genGoto - generates a goto                                      */
2780 /*-----------------------------------------------------------------*/
2781 //tsd
2782 static void genGoto (iCode *ic)
2783 {
2784     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2785 }
2786
2787 /*-----------------------------------------------------------------*/
2788 /* findLabelBackwards: walks back through the iCode chain looking  */
2789 /* for the given label. Returns number of iCode instructions       */
2790 /* between that label and given ic.                                */
2791 /* Returns zero if label not found.                                */
2792 /*-----------------------------------------------------------------*/
2793 #if 0
2794 static int findLabelBackwards(iCode *ic, int key)
2795 {
2796     int count = 0;
2797     
2798     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2799     while (ic->prev)
2800     {
2801         ic = ic->prev;
2802         count++;
2803         
2804         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2805         {
2806             /* printf("findLabelBackwards = %d\n", count); */
2807             return count;
2808         }
2809     }
2810     
2811     return 0;
2812 }
2813 #endif
2814 /*-----------------------------------------------------------------*/
2815 /* genPlusIncr :- does addition with increment if possible         */
2816 /*-----------------------------------------------------------------*/
2817 static bool genPlusIncr (iCode *ic)
2818 {
2819     unsigned int icount ;
2820     unsigned int size = getDataSize(IC_RESULT(ic));
2821
2822     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2823     DEBUGemitcode ("; ","result %d, left %d, right %d",
2824                    AOP_TYPE(IC_RESULT(ic)),
2825                    AOP_TYPE(IC_LEFT(ic)),
2826                    AOP_TYPE(IC_RIGHT(ic)));
2827
2828     /* will try to generate an increment */
2829     /* if the right side is not a literal 
2830        we cannot */
2831     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2832         return FALSE ;
2833     
2834     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2835     /* if the literal value of the right hand side
2836        is greater than 1 then it is faster to add */
2837     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2838         return FALSE ;
2839     
2840     /* if increment 16 bits in register */
2841     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2842         (icount == 1)) {
2843
2844       int offset = MSB16;
2845
2846       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2847       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2848
2849       while(--size) {
2850         emitSKPNZ;
2851         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2852         //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2853       }
2854
2855       return TRUE;
2856     }
2857     
2858     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2859     /* if left is in accumulator  - probably a bit operation*/
2860     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2861         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2862       
2863       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2864       emitcode("bcf","(%s >> 3), (%s & 7)",
2865                AOP(IC_RESULT(ic))->aopu.aop_dir,
2866                AOP(IC_RESULT(ic))->aopu.aop_dir);
2867       if(icount)
2868         emitpcode(POC_XORLW,popGetLit(1));
2869       //emitcode("xorlw","1");
2870       else
2871         emitpcode(POC_ANDLW,popGetLit(1));
2872       //emitcode("andlw","1");
2873
2874       emitSKPZ;
2875       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2876       emitcode("bsf","(%s >> 3), (%s & 7)",
2877                AOP(IC_RESULT(ic))->aopu.aop_dir,
2878                AOP(IC_RESULT(ic))->aopu.aop_dir);
2879
2880       return TRUE;
2881     }
2882
2883
2884
2885     /* if the sizes are greater than 1 then we cannot */
2886     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2887         AOP_SIZE(IC_LEFT(ic)) > 1   )
2888         return FALSE ;
2889     
2890     /* If we are incrementing the same register by two: */
2891
2892     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2893         
2894       while (icount--) 
2895         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2896       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2897         
2898       return TRUE ;
2899     }
2900     
2901     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2902                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2903                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2904     return FALSE ;
2905 }
2906
2907 /*-----------------------------------------------------------------*/
2908 /* outBitAcc - output a bit in acc                                 */
2909 /*-----------------------------------------------------------------*/
2910 static void outBitAcc(operand *result)
2911 {
2912     symbol *tlbl = newiTempLabel(NULL);
2913     /* if the result is a bit */
2914     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2915
2916     if (AOP_TYPE(result) == AOP_CRY){
2917         aopPut(AOP(result),"a",0);
2918     }
2919     else {
2920         emitcode("jz","%05d_DS_",tlbl->key+100);
2921         emitcode("mov","a,%s",one);
2922         emitcode("","%05d_DS_:",tlbl->key+100);
2923         outAcc(result);
2924     }
2925 }
2926
2927 /*-----------------------------------------------------------------*/
2928 /* genPlusBits - generates code for addition of two bits           */
2929 /*-----------------------------------------------------------------*/
2930 static void genPlusBits (iCode *ic)
2931 {
2932
2933     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2934     /*
2935       The following block of code will add two bits. 
2936       Note that it'll even work if the destination is
2937       the carry (C in the status register).
2938       It won't work if the 'Z' bit is a source or destination.
2939     */
2940
2941     /* If the result is stored in the accumulator (w) */
2942     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2943       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2944       //              popGet(AOP(result),0,FALSE,FALSE));
2945
2946       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2947       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2948       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2949       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2950       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2951       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2952
2953         emitcode("movlw","(1 << (%s & 7))",
2954                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2955                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2956         emitcode("bcf","(%s >> 3), (%s & 7)",
2957                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2958                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2959         emitcode("btfsc","(%s >> 3), (%s & 7)",
2960                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2961                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2962         emitcode("xorwf","(%s >>3),f",
2963                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2964         emitcode("btfsc","(%s >> 3), (%s & 7)",
2965                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2966                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2967         emitcode("xorwf","(%s>>3),f",
2968                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2969     } else { 
2970
2971       emitpcode(POC_CLRW, NULL);
2972       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2973       emitpcode(POC_XORLW, popGetLit(1));
2974       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2975       emitpcode(POC_XORLW, popGetLit(1));
2976
2977       emitcode("clrw","");
2978       emitcode("btfsc","(%s >> 3), (%s & 7)",
2979                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2980                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2981       emitcode("xorlw","1");
2982       emitcode("btfsc","(%s >> 3), (%s & 7)",
2983                AOP(IC_LEFT(ic))->aopu.aop_dir,
2984                AOP(IC_LEFT(ic))->aopu.aop_dir);
2985       emitcode("xorlw","1");
2986     }
2987
2988 }
2989
2990 #if 0
2991 /* This is the original version of this code.
2992  *
2993  * This is being kept around for reference, 
2994  * because I am not entirely sure I got it right...
2995  */
2996 static void adjustArithmeticResult(iCode *ic)
2997 {
2998     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2999         AOP_SIZE(IC_LEFT(ic)) == 3   &&
3000         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3001         aopPut(AOP(IC_RESULT(ic)),
3002                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
3003                2);
3004
3005     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
3006         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
3007         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3008         aopPut(AOP(IC_RESULT(ic)),
3009                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3010                2);
3011     
3012     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3013         AOP_SIZE(IC_LEFT(ic)) < 3    &&
3014         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
3015         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3016         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3017         char buffer[5];
3018         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3019         aopPut(AOP(IC_RESULT(ic)),buffer,2);
3020     }
3021 }
3022 //#else
3023 /* This is the pure and virtuous version of this code.
3024  * I'm pretty certain it's right, but not enough to toss the old 
3025  * code just yet...
3026  */
3027 static void adjustArithmeticResult(iCode *ic)
3028 {
3029     if (opIsGptr(IC_RESULT(ic)) &&
3030         opIsGptr(IC_LEFT(ic))   &&
3031         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3032     {
3033         aopPut(AOP(IC_RESULT(ic)),
3034                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3035                GPTRSIZE - 1);
3036     }
3037
3038     if (opIsGptr(IC_RESULT(ic)) &&
3039         opIsGptr(IC_RIGHT(ic))   &&
3040         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3041     {
3042         aopPut(AOP(IC_RESULT(ic)),
3043                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3044                GPTRSIZE - 1);
3045     }
3046
3047     if (opIsGptr(IC_RESULT(ic))            &&
3048         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
3049         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
3050          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3051          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3052          char buffer[5];
3053          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3054          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3055      }
3056 }
3057 #endif
3058
3059 /*-----------------------------------------------------------------*/
3060 /* genPlus - generates code for addition                           */
3061 /*-----------------------------------------------------------------*/
3062 static void genPlus (iCode *ic)
3063 {
3064     int size, offset = 0;
3065
3066     /* special cases :- */
3067     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3068
3069     aopOp (IC_LEFT(ic),ic,FALSE);
3070     aopOp (IC_RIGHT(ic),ic,FALSE);
3071     aopOp (IC_RESULT(ic),ic,TRUE);
3072
3073     /* if literal, literal on the right or
3074        if left requires ACC or right is already
3075        in ACC */
3076
3077     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3078         operand *t = IC_RIGHT(ic);
3079         IC_RIGHT(ic) = IC_LEFT(ic);
3080         IC_LEFT(ic) = t;
3081     }
3082
3083     /* if both left & right are in bit space */
3084     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3085         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3086         genPlusBits (ic);
3087         goto release ;
3088     }
3089
3090     /* if left in bit space & right literal */
3091     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3092         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3093         /* if result in bit space */
3094         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3095           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3096             emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3097             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3098               emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3099             emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3100           }
3101         } else {
3102             size = getDataSize(IC_RESULT(ic));
3103             while (size--) {
3104                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
3105                 emitcode("addc","a,#00  ;%d",__LINE__);
3106                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3107             }
3108         }
3109         goto release ;
3110     }
3111
3112     /* if I can do an increment instead
3113     of add then GOOD for ME */
3114     if (genPlusIncr (ic) == TRUE)
3115         goto release;   
3116
3117     size = getDataSize(IC_RESULT(ic));
3118
3119     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3120       /* Add a literal to something else */
3121       bool know_W=0;
3122       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3123       unsigned l1=0;
3124
3125       offset = 0;
3126       DEBUGemitcode(";","adding lit to something. size %d",size);
3127       while(size--){
3128
3129       DEBUGemitcode(";","size %d",size);
3130
3131         switch (lit & 0xff) {
3132         case 0:
3133           break;
3134         case 1:
3135           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3136             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3137           else {
3138             know_W = 0;
3139             emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3140             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3141               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3142           }
3143           break;
3144         case 0xff:
3145           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3146             emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3147           else {
3148             know_W = 0;
3149             emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3150             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3151               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3152           }
3153           break;
3154         default:
3155           if( !know_W || ( (lit&0xff) != l1)  ) {
3156             know_W = 1;
3157             emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3158           }
3159           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3160             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3161           else {
3162             know_W = 0;
3163             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3164             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3165             if(size) {
3166               emitSKPNC;
3167               emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3168             }
3169           }
3170         }
3171
3172         l1 = lit & 0xff;
3173         lit >>= 8;
3174         offset++;
3175       }
3176
3177     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3178
3179       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3180       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3181       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3182
3183       /* here we are adding a bit to a char or int */
3184       if(size == 1) {
3185         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3186
3187           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3188           emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3189
3190           emitcode("btfsc","(%s >> 3), (%s & 7)",
3191                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3192                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3193           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3194         } else {
3195
3196           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3197             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3198             emitpcode(POC_XORLW , popGetLit(1));
3199
3200             emitcode("btfsc","(%s >> 3), (%s & 7)",
3201                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3202                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3203             emitcode(" xorlw","1");
3204           } else {
3205             emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3206             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3207             emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3208
3209             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3210             emitcode("btfsc","(%s >> 3), (%s & 7)",
3211                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3212                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3213             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3214           }
3215           
3216           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3217             
3218             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3219               emitpcode(POC_ANDLW , popGetLit(1));
3220               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3221               emitSKPZ;
3222               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3223 /*
3224               emitcode("andlw","1");
3225               emitcode("bcf","(%s >> 3), (%s & 7)",
3226                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3227                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3228               emitSKPZ;
3229               emitcode("bsf","(%s >> 3), (%s & 7)",
3230                        AOP(IC_RESULT(ic))->aopu.aop_dir,
3231                        AOP(IC_RESULT(ic))->aopu.aop_dir);
3232 */
3233
3234             } else {
3235               emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3236               emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3237             }
3238           }
3239         }
3240
3241       } else {
3242         int offset = 1;
3243
3244         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3245           emitCLRZ;
3246           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3247           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3248
3249           emitcode("clrz","");
3250
3251           emitcode("btfsc","(%s >> 3), (%s & 7)",
3252                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3253                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3254           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3255
3256         } else {
3257
3258           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3259           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3260           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3261           emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3262
3263
3264           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3265           emitcode("btfsc","(%s >> 3), (%s & 7)",
3266                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3267                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3268           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3269           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3270
3271         }
3272
3273         while(--size){
3274           emitSKPZ;
3275           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3276       //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3277         }
3278
3279       }
3280       
3281     } else {
3282     
3283       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3284         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3285         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3286       } else {
3287
3288         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3289           emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3290           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3291             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3292         } else {
3293
3294           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3295
3296           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3297             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3298           else {
3299             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3300                 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3301               emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3302             } else {
3303               emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3304               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3305                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3306             }
3307           }
3308         }
3309       }
3310
3311       offset = 1;
3312       size--;
3313
3314       while(size--){
3315         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3316           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3317           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3318
3319           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3320           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3321         }
3322
3323         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3324         emitSKPNC;
3325         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3326         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3327
3328         /*
3329         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3330         emitSKPNC;
3331         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3332         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3333         */
3334
3335         offset++;
3336       }
3337
3338     }
3339
3340     //adjustArithmeticResult(ic);
3341
3342  release:
3343       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3345       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3346 }
3347
3348 /*-----------------------------------------------------------------*/
3349 /* genMinusDec :- does subtraction with decrement if possible     */
3350 /*-----------------------------------------------------------------*/
3351 static bool genMinusDec (iCode *ic)
3352 {
3353     unsigned int icount ;
3354     unsigned int size = getDataSize(IC_RESULT(ic));
3355
3356     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3357     /* will try to generate an increment */
3358     /* if the right side is not a literal 
3359     we cannot */
3360     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3361         return FALSE ;
3362
3363     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3364
3365     /* if the literal value of the right hand side
3366     is greater than 4 then it is not worth it */
3367     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3368         return FALSE ;
3369
3370     /* if decrement 16 bits in register */
3371     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3372         (size > 1) &&
3373         (icount == 1)) {
3374
3375       if(size == 2) { 
3376         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3377         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3378         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3379       } else {
3380         /* size is 3 or 4 */
3381         emitcode("movlw","0xff");
3382         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3383
3384         emitSKPNC;
3385         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3386         emitSKPNC;
3387         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3388
3389         if(size > 3) {
3390           emitcode("skpnc","");
3391           emitSKPNC;
3392           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3393         }
3394
3395       }
3396
3397       return TRUE;
3398
3399     }
3400
3401     /* if the sizes are greater than 1 then we cannot */
3402     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3403         AOP_SIZE(IC_LEFT(ic)) > 1   )
3404         return FALSE ;
3405
3406     /* we can if the aops of the left & result match or
3407     if they are in registers and the registers are the
3408     same */
3409     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3410
3411       while (icount--) 
3412         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3413
3414         //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3415
3416         return TRUE ;
3417     }
3418
3419     DEBUGemitcode ("; returning"," result=%s, left=%s",
3420                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3421                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3422     if(size==1) {
3423       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3424       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3425       return TRUE;
3426     }
3427
3428     return FALSE ;
3429 }
3430
3431 /*-----------------------------------------------------------------*/
3432 /* addSign - complete with sign                                    */
3433 /*-----------------------------------------------------------------*/
3434 static void addSign(operand *result, int offset, int sign)
3435 {
3436     int size = (getDataSize(result) - offset);
3437     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3438     if(size > 0){
3439         if(sign){
3440             emitcode("rlc","a");
3441             emitcode("subb","a,acc");
3442             while(size--)
3443                 aopPut(AOP(result),"a",offset++); 
3444         } else
3445             while(size--)
3446                 aopPut(AOP(result),zero,offset++);
3447     }
3448 }
3449
3450 /*-----------------------------------------------------------------*/
3451 /* genMinusBits - generates code for subtraction  of two bits      */
3452 /*-----------------------------------------------------------------*/
3453 static void genMinusBits (iCode *ic)
3454 {
3455     symbol *lbl = newiTempLabel(NULL);
3456     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3457     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3458         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3459         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3460         emitcode("cpl","c");
3461         emitcode("","%05d_DS_:",(lbl->key+100));
3462         outBitC(IC_RESULT(ic));
3463     }
3464     else{
3465         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3466         emitcode("subb","a,acc");
3467         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3468         emitcode("inc","a");
3469         emitcode("","%05d_DS_:",(lbl->key+100));
3470         aopPut(AOP(IC_RESULT(ic)),"a",0);
3471         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3472     }
3473 }
3474
3475 /*-----------------------------------------------------------------*/
3476 /* genMinus - generates code for subtraction                       */
3477 /*-----------------------------------------------------------------*/
3478 static void genMinus (iCode *ic)
3479 {
3480     int size, offset = 0;
3481     unsigned long lit = 0L;
3482
3483     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3484     aopOp (IC_LEFT(ic),ic,FALSE);
3485     aopOp (IC_RIGHT(ic),ic,FALSE);
3486     aopOp (IC_RESULT(ic),ic,TRUE);
3487
3488     /* special cases :- */
3489     /* if both left & right are in bit space */
3490     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3491         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3492         genMinusBits (ic);
3493         goto release ;
3494     }
3495
3496     /* if I can do an decrement instead
3497     of subtract then GOOD for ME */
3498     if (genMinusDec (ic) == TRUE)
3499         goto release;   
3500
3501     size = getDataSize(IC_RESULT(ic));   
3502
3503     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3504       /* Add a literal to something else */
3505
3506       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3507       lit = - (long)lit;
3508
3509       /* add the first byte: */
3510       emitcode("movlw","0x%x", lit & 0xff);
3511       emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3512
3513       offset = 1;
3514       size--;
3515
3516       while(size--){
3517
3518         emitcode("rlf","_known_zero,w");
3519         emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3520
3521         lit >>= 8;
3522         if(lit & 0xff) {
3523           emitcode("movlw","0x%x", lit & 0xff);
3524           emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3525           
3526         }
3527         offset++;
3528       }
3529
3530     } else {
3531
3532       emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3533       emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3534
3535       offset = 1;
3536       size--;
3537
3538       while(size--){
3539         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3540         emitSKPNC;
3541         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3542         emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3543         
3544       }
3545
3546     }
3547
3548
3549     //    adjustArithmeticResult(ic);
3550         
3551 release:
3552     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3555 }
3556
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genMultbits :- multiplication of bits                           */
3560 /*-----------------------------------------------------------------*/
3561 static void genMultbits (operand *left, 
3562                          operand *right, 
3563                          operand *result)
3564 {
3565     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3566
3567     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3568     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3569     outBitC(result);
3570 }
3571
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genMultOneByte : 8 bit multiplication & division                */
3575 /*-----------------------------------------------------------------*/
3576 static void genMultOneByte (operand *left,
3577                             operand *right,
3578                             operand *result)
3579 {
3580     sym_link *opetype = operandType(result);
3581     char *l ;
3582     symbol *lbl ;
3583     int size,offset;
3584
3585     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3586     /* (if two literals, the value is computed before) */
3587     /* if one literal, literal on the right */
3588     if (AOP_TYPE(left) == AOP_LIT){
3589         operand *t = right;
3590         right = left;
3591         left = t;
3592     }
3593
3594     size = AOP_SIZE(result);
3595     /* signed or unsigned */
3596     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3597     l = aopGet(AOP(left),0,FALSE,FALSE);
3598     MOVA(l);       
3599     emitcode("mul","ab");
3600     /* if result size = 1, mul signed = mul unsigned */
3601     aopPut(AOP(result),"a",0);
3602     if (size > 1){
3603         if (SPEC_USIGN(opetype)){
3604             aopPut(AOP(result),"b",1);
3605             if (size > 2)
3606                 /* for filling the MSBs */
3607                 emitcode("clr","a");
3608         }
3609         else{
3610             emitcode("mov","a,b");
3611
3612             /* adjust the MSB if left or right neg */
3613
3614             /* if one literal */
3615             if (AOP_TYPE(right) == AOP_LIT){
3616                 /* AND literal negative */
3617                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3618                     /* adjust MSB (c==0 after mul) */
3619                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3620                 }
3621             }
3622             else{
3623                 lbl = newiTempLabel(NULL);
3624                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3625                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3626                 emitcode("","%05d_DS_:",(lbl->key+100));
3627                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3628                 lbl = newiTempLabel(NULL);      
3629                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3630                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3631                 emitcode("","%05d_DS_:",(lbl->key+100));
3632             }
3633
3634             lbl = newiTempLabel(NULL);
3635             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3636             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3637             emitcode("","%05d_DS_:",(lbl->key+100));
3638             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3639             lbl = newiTempLabel(NULL);      
3640             emitcode("jc","%05d_DS_",(lbl->key+100));          
3641             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3642             emitcode("","%05d_DS_:",(lbl->key+100));
3643
3644             aopPut(AOP(result),"a",1);
3645             if(size > 2){
3646                 /* get the sign */
3647                 emitcode("rlc","a");
3648                 emitcode("subb","a,acc");
3649             }
3650         }
3651         size -= 2;   
3652         offset = 2;
3653         if (size > 0)
3654             while (size--)
3655                 aopPut(AOP(result),"a",offset++);
3656     }
3657 }
3658
3659 /*-----------------------------------------------------------------*/
3660 /* genMult - generates code for multiplication                     */
3661 /*-----------------------------------------------------------------*/
3662 static void genMult (iCode *ic)
3663 {
3664     operand *left = IC_LEFT(ic);
3665     operand *right = IC_RIGHT(ic);
3666     operand *result= IC_RESULT(ic);   
3667
3668     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3669     /* assign the amsops */
3670     aopOp (left,ic,FALSE);
3671     aopOp (right,ic,FALSE);
3672     aopOp (result,ic,TRUE);
3673
3674     /* special cases first */
3675     /* both are bits */
3676     if (AOP_TYPE(left) == AOP_CRY &&
3677         AOP_TYPE(right)== AOP_CRY) {
3678         genMultbits(left,right,result);
3679         goto release ;
3680     }
3681
3682     /* if both are of size == 1 */
3683     if (AOP_SIZE(left) == 1 &&
3684         AOP_SIZE(right) == 1 ) {
3685         genMultOneByte(left,right,result);
3686         goto release ;
3687     }
3688
3689     /* should have been converted to function call */       
3690     assert(1) ;
3691
3692 release :
3693     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3694     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695     freeAsmop(result,NULL,ic,TRUE); 
3696 }
3697
3698 /*-----------------------------------------------------------------*/
3699 /* genDivbits :- division of bits                                  */
3700 /*-----------------------------------------------------------------*/
3701 static void genDivbits (operand *left, 
3702                         operand *right, 
3703                         operand *result)
3704 {
3705
3706     char *l;
3707
3708     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3709     /* the result must be bit */    
3710     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3711     l = aopGet(AOP(left),0,FALSE,FALSE);
3712
3713     MOVA(l);    
3714
3715     emitcode("div","ab");
3716     emitcode("rrc","a");
3717     aopPut(AOP(result),"c",0);
3718 }
3719
3720 /*-----------------------------------------------------------------*/
3721 /* genDivOneByte : 8 bit division                                  */
3722 /*-----------------------------------------------------------------*/
3723 static void genDivOneByte (operand *left,
3724                            operand *right,
3725                            operand *result)
3726 {
3727     sym_link *opetype = operandType(result);
3728     char *l ;
3729     symbol *lbl ;
3730     int size,offset;
3731
3732     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3733     size = AOP_SIZE(result) - 1;
3734     offset = 1;
3735     /* signed or unsigned */
3736     if (SPEC_USIGN(opetype)) {
3737         /* unsigned is easy */
3738         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3739         l = aopGet(AOP(left),0,FALSE,FALSE);
3740         MOVA(l);        
3741         emitcode("div","ab");
3742         aopPut(AOP(result),"a",0);
3743         while (size--)
3744             aopPut(AOP(result),zero,offset++);
3745         return ;
3746     }
3747
3748     /* signed is a little bit more difficult */
3749
3750     /* save the signs of the operands */
3751     l = aopGet(AOP(left),0,FALSE,FALSE);    
3752     MOVA(l);    
3753     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3754     emitcode("push","acc"); /* save it on the stack */
3755
3756     /* now sign adjust for both left & right */
3757     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3758     MOVA(l);       
3759     lbl = newiTempLabel(NULL);
3760     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3761     emitcode("cpl","a");   
3762     emitcode("inc","a");
3763     emitcode("","%05d_DS_:",(lbl->key+100));
3764     emitcode("mov","b,a");
3765
3766     /* sign adjust left side */
3767     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3768     MOVA(l);
3769
3770     lbl = newiTempLabel(NULL);
3771     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3772     emitcode("cpl","a");
3773     emitcode("inc","a");
3774     emitcode("","%05d_DS_:",(lbl->key+100));
3775
3776     /* now the division */
3777     emitcode("div","ab");
3778     /* we are interested in the lower order
3779     only */
3780     emitcode("mov","b,a");
3781     lbl = newiTempLabel(NULL);
3782     emitcode("pop","acc");   
3783     /* if there was an over flow we don't 
3784     adjust the sign of the result */
3785     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3786     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3787     CLRC;
3788     emitcode("clr","a");
3789     emitcode("subb","a,b");
3790     emitcode("mov","b,a");
3791     emitcode("","%05d_DS_:",(lbl->key+100));
3792
3793     /* now we are done */
3794     aopPut(AOP(result),"b",0);
3795     if(size > 0){
3796         emitcode("mov","c,b.7");
3797         emitcode("subb","a,acc");   
3798     }
3799     while (size--)
3800         aopPut(AOP(result),"a",offset++);
3801
3802 }
3803
3804 /*-----------------------------------------------------------------*/
3805 /* genDiv - generates code for division                            */
3806 /*-----------------------------------------------------------------*/
3807 static void genDiv (iCode *ic)
3808 {
3809     operand *left = IC_LEFT(ic);
3810     operand *right = IC_RIGHT(ic);
3811     operand *result= IC_RESULT(ic);   
3812
3813     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3814     /* assign the amsops */
3815     aopOp (left,ic,FALSE);
3816     aopOp (right,ic,FALSE);
3817     aopOp (result,ic,TRUE);
3818
3819     /* special cases first */
3820     /* both are bits */
3821     if (AOP_TYPE(left) == AOP_CRY &&
3822         AOP_TYPE(right)== AOP_CRY) {
3823         genDivbits(left,right,result);
3824         goto release ;
3825     }
3826
3827     /* if both are of size == 1 */
3828     if (AOP_SIZE(left) == 1 &&
3829         AOP_SIZE(right) == 1 ) {
3830         genDivOneByte(left,right,result);
3831         goto release ;
3832     }
3833
3834     /* should have been converted to function call */
3835     assert(1);
3836 release :
3837     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3838     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3839     freeAsmop(result,NULL,ic,TRUE); 
3840 }
3841
3842 /*-----------------------------------------------------------------*/
3843 /* genModbits :- modulus of bits                                   */
3844 /*-----------------------------------------------------------------*/
3845 static void genModbits (operand *left, 
3846                         operand *right, 
3847                         operand *result)
3848 {
3849
3850     char *l;
3851
3852     /* the result must be bit */    
3853     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3854     l = aopGet(AOP(left),0,FALSE,FALSE);
3855
3856     MOVA(l);       
3857
3858     emitcode("div","ab");
3859     emitcode("mov","a,b");
3860     emitcode("rrc","a");
3861     aopPut(AOP(result),"c",0);
3862 }
3863
3864 /*-----------------------------------------------------------------*/
3865 /* genModOneByte : 8 bit modulus                                   */
3866 /*-----------------------------------------------------------------*/
3867 static void genModOneByte (operand *left,
3868                            operand *right,
3869                            operand *result)
3870 {
3871     sym_link *opetype = operandType(result);
3872     char *l ;
3873     symbol *lbl ;
3874
3875     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3876     /* signed or unsigned */
3877     if (SPEC_USIGN(opetype)) {
3878         /* unsigned is easy */
3879         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3880         l = aopGet(AOP(left),0,FALSE,FALSE);
3881         MOVA(l);    
3882         emitcode("div","ab");
3883         aopPut(AOP(result),"b",0);
3884         return ;
3885     }
3886
3887     /* signed is a little bit more difficult */
3888
3889     /* save the signs of the operands */
3890     l = aopGet(AOP(left),0,FALSE,FALSE);    
3891     MOVA(l);
3892
3893     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3894     emitcode("push","acc"); /* save it on the stack */
3895
3896     /* now sign adjust for both left & right */
3897     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3898     MOVA(l);
3899
3900     lbl = newiTempLabel(NULL);
3901     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3902     emitcode("cpl","a");   
3903     emitcode("inc","a");
3904     emitcode("","%05d_DS_:",(lbl->key+100));
3905     emitcode("mov","b,a"); 
3906
3907     /* sign adjust left side */
3908     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3909     MOVA(l);
3910
3911     lbl = newiTempLabel(NULL);
3912     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3913     emitcode("cpl","a");   
3914     emitcode("inc","a");
3915     emitcode("","%05d_DS_:",(lbl->key+100));
3916
3917     /* now the multiplication */
3918     emitcode("div","ab");
3919     /* we are interested in the lower order
3920     only */
3921     lbl = newiTempLabel(NULL);
3922     emitcode("pop","acc");   
3923     /* if there was an over flow we don't 
3924     adjust the sign of the result */
3925     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3926     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3927     CLRC ;
3928     emitcode("clr","a");
3929     emitcode("subb","a,b");
3930     emitcode("mov","b,a");
3931     emitcode("","%05d_DS_:",(lbl->key+100));
3932
3933     /* now we are done */
3934     aopPut(AOP(result),"b",0);
3935
3936 }
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genMod - generates code for division                            */
3940 /*-----------------------------------------------------------------*/
3941 static void genMod (iCode *ic)
3942 {
3943     operand *left = IC_LEFT(ic);
3944     operand *right = IC_RIGHT(ic);
3945     operand *result= IC_RESULT(ic);  
3946
3947     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3948     /* assign the amsops */
3949     aopOp (left,ic,FALSE);
3950     aopOp (right,ic,FALSE);
3951     aopOp (result,ic,TRUE);
3952
3953     /* special cases first */
3954     /* both are bits */
3955     if (AOP_TYPE(left) == AOP_CRY &&
3956         AOP_TYPE(right)== AOP_CRY) {
3957         genModbits(left,right,result);
3958         goto release ;
3959     }
3960
3961     /* if both are of size == 1 */
3962     if (AOP_SIZE(left) == 1 &&
3963         AOP_SIZE(right) == 1 ) {
3964         genModOneByte(left,right,result);
3965         goto release ;
3966     }
3967
3968     /* should have been converted to function call */
3969     assert(1);
3970
3971 release :
3972     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3973     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3974     freeAsmop(result,NULL,ic,TRUE); 
3975 }
3976
3977 /*-----------------------------------------------------------------*/
3978 /* genIfxJump :- will create a jump depending on the ifx           */
3979 /*-----------------------------------------------------------------*/
3980 static void genIfxJump (iCode *ic, char *jval)
3981 {
3982
3983     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3984     /* if true label then we jump if condition
3985     supplied is true */
3986     if ( IC_TRUE(ic) ) {
3987
3988         if(strcmp(jval,"a") == 0)
3989           emitSKPZ;
3990         else if (strcmp(jval,"c") == 0)
3991           emitSKPC;
3992         else {
3993           //pCodeOp *p = popGetWithString(jval);
3994           //p->type = PO_BIT;
3995           //emitpcode(POC_BTFSC,  p);
3996           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,0));
3997         //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3998         }
3999
4000         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4001         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4002
4003     }
4004     else {
4005         /* false label is present */
4006         if(strcmp(jval,"a") == 0)
4007           emitSKPNZ;
4008         else if (strcmp(jval,"c") == 0)
4009           emitSKPNC;
4010         else {
4011           //pCodeOp *p = popGetWithString(jval);
4012           //p->type = PO_BIT;
4013           //emitpcode(POC_BTFSS,  p);
4014           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,0));
4015
4016         //        emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4017         }
4018
4019         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4020         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4021
4022     }
4023
4024
4025     /* mark the icode as generated */
4026     ic->generated = 1;
4027 }
4028
4029 /*-----------------------------------------------------------------*/
4030 /* genSkip                                                         */
4031 /*-----------------------------------------------------------------*/
4032 static void genSkip(iCode *ifx,int status_bit)
4033 {
4034   if(!ifx)
4035     return;
4036
4037   if ( IC_TRUE(ifx) ) {
4038     switch(status_bit) {
4039     case 'z':
4040       emitSKPNZ;
4041       break;
4042
4043     case 'c':
4044       emitSKPNC;
4045       break;
4046
4047     case 'd':
4048       emitcode("skpndc","");
4049       break;
4050
4051     }
4052
4053     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4054     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4055
4056   } else {
4057
4058     switch(status_bit) {
4059
4060     case 'z':
4061       emitSKPZ;
4062       break;
4063
4064     case 'c':
4065       emitSKPC;
4066       break;
4067
4068     case 'd':
4069       emitcode("skpdc","");
4070       break;
4071     }
4072     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4073     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4074
4075   }
4076
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* genSkipc                                                        */
4081 /*-----------------------------------------------------------------*/
4082 static void genSkipc(iCode *ifx, int condition)
4083 {
4084   if(!ifx)
4085     return;
4086
4087   if(condition)
4088     emitSKPNC;
4089   else
4090     emitSKPC;
4091
4092   if ( IC_TRUE(ifx) )
4093     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4094   else
4095     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4096
4097   if ( IC_TRUE(ifx) )
4098     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4099   else
4100     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4101
4102 }
4103
4104 /*-----------------------------------------------------------------*/
4105 /* genSkipz                                                        */
4106 /*-----------------------------------------------------------------*/
4107 static void genSkipz(iCode *ifx, int condition)
4108 {
4109   if(!ifx)
4110     return;
4111
4112   if(condition)
4113     emitSKPNZ;
4114   else
4115     emitSKPZ;
4116
4117   if ( IC_TRUE(ifx) )
4118     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4119   else
4120     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4121
4122   if ( IC_TRUE(ifx) )
4123     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4124   else
4125     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4126
4127 }
4128 /*-----------------------------------------------------------------*/
4129 /* genCmp :- greater or less than comparison                       */
4130 /*-----------------------------------------------------------------*/
4131 static void genCmp (operand *left,operand *right,
4132                     operand *result, iCode *ifx, int sign)
4133 {
4134   int size, offset = 0 ;
4135   unsigned long lit = 0L,i = 0;
4136
4137   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4138   /* if left & right are bit variables */
4139   if (AOP_TYPE(left) == AOP_CRY &&
4140       AOP_TYPE(right) == AOP_CRY ) {
4141     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4142     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4143   } else {
4144     /* subtract right from left if at the
4145        end the carry flag is set then we know that
4146        left is greater than right */
4147     size = max(AOP_SIZE(left),AOP_SIZE(right));
4148
4149     /* if unsigned char cmp with lit, do cjne left,#right,zz */
4150     if((size == 1) && !sign &&
4151        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4152       symbol *lbl  = newiTempLabel(NULL);
4153       emitcode("cjne","%s,%s,%05d_DS_",
4154                aopGet(AOP(left),offset,FALSE,FALSE),
4155                aopGet(AOP(right),offset,FALSE,FALSE),
4156                lbl->key+100);
4157       emitcode("","%05d_DS_:",lbl->key+100);
4158     } else {
4159
4160       if(AOP_TYPE(right) == AOP_LIT) {
4161
4162         DEBUGemitcode(";right lit","%d",sign);
4163
4164         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4165         //default:
4166         while(size--) {
4167           i = (lit >> (size*8)) & 0xff;
4168           if(i == 0) {
4169             emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4170             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4171             genSkipz(ifx,IC_TRUE(ifx) == NULL);
4172           } else {
4173             emitpcode(POC_MOVLW, popGetLit(i));
4174             emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4175
4176             emitcode("movlw","0x%x",i);
4177             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4178             genSkipc(ifx,IC_TRUE(ifx) == NULL);
4179           }
4180
4181         }
4182         ifx->generated = 1;
4183         return;
4184       }
4185       if(AOP_TYPE(left) == AOP_LIT) {
4186
4187         DEBUGemitcode(";left lit","%d",sign);
4188
4189         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4190
4191         //default:
4192         while(size--) {
4193           i = (lit >> (size*8)) & 0xff;
4194           if(i == 0) {
4195             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4196             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4197             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4198           } else if( i == 1 ) {
4199             emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4200             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4201             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4202
4203           } else {
4204             emitpcode(POC_MOVLW, popGetLit(i));
4205             emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4206
4207             emitcode("movlw","0x%x",i);
4208             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4209             genSkipc(ifx,IC_TRUE(ifx) != NULL);
4210           }
4211         }
4212         ifx->generated = 1;
4213         return;
4214       }
4215
4216
4217       // CLRC;
4218       DEBUGemitcode(";sign","%d",sign);
4219
4220       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4221       emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4222
4223       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4224       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4225
4226       size--;
4227       while (size--) {
4228
4229         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
4230         emitSKPC;
4231         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4232         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
4233
4234 /*
4235         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4236         emitSKPC;
4237         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4238         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4239 */
4240         offset++;
4241       }
4242     }
4243   }
4244
4245   //release:
4246   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4247     outBitC(result);
4248   } else {
4249     /* if the result is used in the next
4250        ifx conditional branch then generate
4251        code a little differently */
4252     if (ifx )
4253       genIfxJump (ifx,"c");
4254     else
4255       outBitC(result);
4256     /* leave the result in acc */
4257   }
4258
4259 }
4260
4261 /*-----------------------------------------------------------------*/
4262 /* genCmpGt :- greater than comparison                             */
4263 /*-----------------------------------------------------------------*/
4264 static void genCmpGt (iCode *ic, iCode *ifx)
4265 {
4266     operand *left, *right, *result;
4267     sym_link *letype , *retype;
4268     int sign ;
4269
4270     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4271     left = IC_LEFT(ic);
4272     right= IC_RIGHT(ic);
4273     result = IC_RESULT(ic);
4274
4275     letype = getSpec(operandType(left));
4276     retype =getSpec(operandType(right));
4277     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4278     /* assign the amsops */
4279     aopOp (left,ic,FALSE);
4280     aopOp (right,ic,FALSE);
4281     aopOp (result,ic,TRUE);
4282
4283     genCmp(right, left, result, ifx, sign);
4284
4285     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4286     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4287     freeAsmop(result,NULL,ic,TRUE); 
4288 }
4289
4290 /*-----------------------------------------------------------------*/
4291 /* genCmpLt - less than comparisons                                */
4292 /*-----------------------------------------------------------------*/
4293 static void genCmpLt (iCode *ic, iCode *ifx)
4294 {
4295     operand *left, *right, *result;
4296     sym_link *letype , *retype;
4297     int sign ;
4298
4299     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4300     left = IC_LEFT(ic);
4301     right= IC_RIGHT(ic);
4302     result = IC_RESULT(ic);
4303
4304     letype = getSpec(operandType(left));
4305     retype =getSpec(operandType(right));
4306     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4307
4308     /* assign the amsops */
4309     aopOp (left,ic,FALSE);
4310     aopOp (right,ic,FALSE);
4311     aopOp (result,ic,TRUE);
4312
4313     genCmp(left, right, result, ifx, sign);
4314
4315     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4316     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4317     freeAsmop(result,NULL,ic,TRUE); 
4318 }
4319
4320 /*-----------------------------------------------------------------*/
4321 /* gencjneshort - compare and jump if not equal                    */
4322 /*-----------------------------------------------------------------*/
4323 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4324 {
4325     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4326     int offset = 0;
4327     unsigned long lit = 0L;
4328
4329     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4330     /* if the left side is a literal or 
4331     if the right is in a pointer register and left 
4332     is not */
4333     if ((AOP_TYPE(left) == AOP_LIT) || 
4334         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4335         operand *t = right;
4336         right = left;
4337         left = t;
4338     }
4339     if(AOP_TYPE(right) == AOP_LIT)
4340         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4341
4342     /* if the right side is a literal then anything goes */
4343     if (AOP_TYPE(right) == AOP_LIT &&
4344         AOP_TYPE(left) != AOP_DIR ) {
4345         while (size--) {
4346           if(lit & 0xff) {
4347             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4348             emitcode("xorlw","0x%x",lit & 0xff);
4349           } else
4350             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4351
4352           emitSKPNZ;
4353           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4354           offset++;
4355           lit >>= 8;
4356         }
4357     }
4358
4359     /* if the right side is in a register or in direct space or
4360     if the left is a pointer register & right is not */    
4361     else if (AOP_TYPE(right) == AOP_REG ||
4362              AOP_TYPE(right) == AOP_DIR || 
4363              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4364              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4365         while (size--) {
4366           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4367              ( (lit & 0xff) != 0)) {
4368             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4369             emitcode("xorlw","0x%x",lit & 0xff);
4370             lit >>= 8;
4371           } else
4372             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4373
4374           emitSKPZ;
4375           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4376           offset++;
4377 /*
4378             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4379             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4380                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4381                 emitcode("jnz","%05d_DS_",lbl->key+100);
4382             else
4383                 emitcode("cjne","a,%s,%05d_DS_",
4384                          aopGet(AOP(right),offset,FALSE,TRUE),
4385                          lbl->key+100);
4386             offset++;
4387 */
4388         }
4389     } else {
4390         /* right is a pointer reg need both a & b */
4391         while(size--) {
4392             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4393             if(strcmp(l,"b"))
4394                 emitcode("mov","b,%s",l);
4395             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4396             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4397             offset++;
4398         }
4399     }
4400 }
4401
4402 /*-----------------------------------------------------------------*/
4403 /* gencjne - compare and jump if not equal                         */
4404 /*-----------------------------------------------------------------*/
4405 static void gencjne(operand *left, operand *right, symbol *lbl)
4406 {
4407     symbol *tlbl  = newiTempLabel(NULL);
4408
4409     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4410     gencjneshort(left, right, lbl);
4411
4412     emitcode("mov","a,%s",one);
4413     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4414     emitcode("","%05d_DS_:",lbl->key+100);
4415     emitcode("clr","a");
4416     emitcode("","%05d_DS_:",tlbl->key+100);
4417 }
4418
4419
4420 /*-----------------------------------------------------------------*/
4421 /* genCmpEq - generates code for equal to                          */
4422 /*-----------------------------------------------------------------*/
4423 static void genCmpEq (iCode *ic, iCode *ifx)
4424 {
4425     operand *left, *right, *result;
4426     unsigned long lit = 0L;
4427     int size,offset=0;
4428
4429     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4430     if(ifx)
4431       DEBUGemitcode ("; ifx is non-null","");
4432     else
4433       DEBUGemitcode ("; ifx is null","");
4434
4435     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4436     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4437     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4438
4439     size = max(AOP_SIZE(left),AOP_SIZE(right));
4440
4441     /* if literal, literal on the right or 
4442     if the right is in a pointer register and left 
4443     is not */
4444     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4445         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4446         operand *t = IC_RIGHT(ic);
4447         IC_RIGHT(ic) = IC_LEFT(ic);
4448         IC_LEFT(ic) = t;
4449     }
4450
4451     if(ifx && !AOP_SIZE(result)){
4452         symbol *tlbl;
4453         /* if they are both bit variables */
4454         if (AOP_TYPE(left) == AOP_CRY &&
4455             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4456             if(AOP_TYPE(right) == AOP_LIT){
4457                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4458                 if(lit == 0L){
4459                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4460                     emitcode("cpl","c");
4461                 } else if(lit == 1L) {
4462                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4463                 } else {
4464                     emitcode("clr","c");
4465                 }
4466                 /* AOP_TYPE(right) == AOP_CRY */
4467             } else {
4468                 symbol *lbl = newiTempLabel(NULL);
4469                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4470                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4471                 emitcode("cpl","c");
4472                 emitcode("","%05d_DS_:",(lbl->key+100));
4473             }
4474             /* if true label then we jump if condition
4475             supplied is true */
4476             tlbl = newiTempLabel(NULL);
4477             if ( IC_TRUE(ifx) ) {
4478                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4479                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4480             } else {
4481                 emitcode("jc","%05d_DS_",tlbl->key+100);
4482                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4483             }
4484             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4485         } else {
4486
4487           /* They're not both bit variables. Is the right a literal? */
4488           if(AOP_TYPE(right) == AOP_LIT) {
4489
4490             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4491             while (size--) {
4492
4493               if(size >= 1) {
4494                 int l = lit & 0xff;
4495                 int h = (lit>>8) & 0xff;
4496                 int optimized=0;
4497
4498                 /* Check special cases for integers */
4499                 switch(lit & 0xffff) {
4500                 case 0x0000:
4501                   emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4502                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4503                   //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4504                   //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4505                   genSkip(ifx,'z');
4506                   optimized++;
4507                   break;
4508                 case 0x0001:
4509                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4510                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4511                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4512                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4513                   genSkip(ifx,'z');
4514                   optimized++;
4515                   break;
4516                 case 0x0100:
4517                   emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4518                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4519                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4520                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4521                   genSkip(ifx,'z');
4522                   optimized++;
4523                   break;
4524                 case 0x00ff:
4525                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4526                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4527                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4528                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4529                   genSkip(ifx,'z');
4530                   optimized++;
4531                   break;
4532                 case 0xff00:
4533                   emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4534                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4535                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4536                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4537                   genSkip(ifx,'z');
4538                   optimized++;
4539                   break;
4540                 default:
4541                   if(h == 0) {
4542                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4543                     emitpcode(POC_XORLW,popGetLit(l));
4544                     emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4545
4546                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4547                     emitcode("xorlw","0x%x",l);
4548                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4549                     optimized++;
4550                     genSkip(ifx,'z');
4551                   } else if (l == 0) {
4552                     emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4553                     emitpcode(POC_XORLW,popGetLit(h));
4554                     emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4555
4556                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4557                     emitcode("xorlw","0x%x",h);
4558                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4559                     optimized++;
4560                     genSkip(ifx,'z');
4561                   } else {
4562                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4563                     emitpcode(POC_XORLW,popGetLit(l));
4564                     emitpcode(POC_MOVLW,popGetLit(h));
4565                     emitSKPZ;
4566                     emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4567 /*
4568                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4569                     emitcode("xorlw","0x%x",l);
4570                     emitcode("movlw","0x%x",h);
4571                     emitSKPZ;
4572                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4573 */
4574                     optimized++;
4575                     genSkip(ifx,'z');
4576                   }
4577
4578                 }
4579                 if(optimized) {
4580                   size--;
4581                   offset+=2;
4582                   lit>>=16;
4583
4584                   continue;
4585                 }
4586                   
4587               }
4588                 
4589               switch(lit & 0xff) {
4590               case 1:
4591                 if ( IC_TRUE(ifx) ) {
4592
4593                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4594
4595                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4596                   emitSKPNZ;
4597                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4598
4599                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4600                 } else {
4601                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4602                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4603
4604                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4605                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4606                 }
4607                 break;
4608               case 0xff:
4609                 if ( IC_TRUE(ifx) ) {
4610                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4611
4612                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4613                   emitSKPNZ;
4614                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4615
4616                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4617                 } else {
4618                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4619                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4620
4621                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4622                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4623                 }
4624                 break;
4625               default:
4626                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4627                 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4628                 if(lit)
4629                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4630                 //emitcode("xorlw","0x%x",lit & 0xff);
4631                 genSkip(ifx,'z');
4632               }
4633
4634
4635               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4636               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4637               offset++;
4638               lit >>= 8;
4639             }
4640
4641           } else if(AOP_TYPE(right) == AOP_CRY ) {
4642             /* we know the left is not a bit, but that the right is */
4643             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4644             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4645                       popGet(AOP(right),offset,FALSE,FALSE));
4646             emitpcode(POC_XORLW,popGetLit(1));
4647
4648             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4649             if ( IC_TRUE(ifx) )
4650               emitcode("btfsc","(%s >> 3), (%s & 7)",
4651                        AOP(right)->aopu.aop_dir,
4652                        AOP(right)->aopu.aop_dir);
4653             else
4654               emitcode("btfss","(%s >> 3), (%s & 7)",
4655                        AOP(right)->aopu.aop_dir,
4656                        AOP(right)->aopu.aop_dir);
4657
4658             emitcode("xorlw","1");
4659
4660             /* if the two are equal, then W will be 0 and the Z bit is set
4661              * we could test Z now, or go ahead and check the high order bytes if
4662              * the variable we're comparing is larger than a byte. */
4663
4664             while(--size)
4665               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4666             //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4667
4668             if ( IC_TRUE(ifx) ) {
4669               emitSKPNZ;
4670               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4671               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4672             } else {
4673               emitSKPZ;
4674               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4675               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4676             }
4677
4678           } else {
4679             /* They're both variables that are larger than bits */
4680             int s = size;
4681
4682             tlbl = newiTempLabel(NULL);
4683
4684             while(size--) {
4685               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4686               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4687
4688               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4689               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4690
4691               if ( IC_TRUE(ifx) ) {
4692                 if(size) {
4693                   emitSKPZ;
4694                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4695                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4696                 } else {
4697                   emitSKPNZ;
4698                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4699                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4700                 }
4701               } else {
4702                 emitSKPZ;
4703                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4704                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4705               }
4706               offset++;
4707             }
4708             if(s>1 && IC_TRUE(ifx)) {
4709               emitpLabel(tlbl->key+100+labelOffset);
4710               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4711             }
4712           }
4713         }
4714         /* mark the icode as generated */
4715         ifx->generated = 1;
4716         goto release ;
4717     }
4718
4719     /* if they are both bit variables */
4720     if (AOP_TYPE(left) == AOP_CRY &&
4721         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4722         if(AOP_TYPE(right) == AOP_LIT){
4723             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4724             if(lit == 0L){
4725                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4726                 emitcode("cpl","c");
4727             } else if(lit == 1L) {
4728                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4729             } else {
4730                 emitcode("clr","c");
4731             }
4732             /* AOP_TYPE(right) == AOP_CRY */
4733         } else {
4734             symbol *lbl = newiTempLabel(NULL);
4735             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4736             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4737             emitcode("cpl","c");
4738             emitcode("","%05d_DS_:",(lbl->key+100));
4739         }
4740         /* c = 1 if egal */
4741         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4742             outBitC(result);
4743             goto release ;
4744         }
4745         if (ifx) {
4746             genIfxJump (ifx,"c");
4747             goto release ;
4748         }
4749         /* if the result is used in an arithmetic operation
4750         then put the result in place */
4751         outBitC(result);
4752     } else {
4753         gencjne(left,right,newiTempLabel(NULL));    
4754         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4755             aopPut(AOP(result),"a",0);
4756             goto release ;
4757         }
4758         if (ifx) {
4759             genIfxJump (ifx,"a");
4760             goto release ;
4761         }
4762         /* if the result is used in an arithmetic operation
4763         then put the result in place */
4764         if (AOP_TYPE(result) != AOP_CRY) 
4765             outAcc(result);
4766         /* leave the result in acc */
4767     }
4768
4769 release:
4770     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4771     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4772     freeAsmop(result,NULL,ic,TRUE);
4773 }
4774
4775 /*-----------------------------------------------------------------*/
4776 /* ifxForOp - returns the icode containing the ifx for operand     */
4777 /*-----------------------------------------------------------------*/
4778 static iCode *ifxForOp ( operand *op, iCode *ic )
4779 {
4780     /* if true symbol then needs to be assigned */
4781     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4782     if (IS_TRUE_SYMOP(op))
4783         return NULL ;
4784
4785     /* if this has register type condition and
4786     the next instruction is ifx with the same operand
4787     and live to of the operand is upto the ifx only then */
4788     if (ic->next &&
4789         ic->next->op == IFX &&
4790         IC_COND(ic->next)->key == op->key &&
4791         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4792         return ic->next;
4793
4794     return NULL;
4795 }
4796 /*-----------------------------------------------------------------*/
4797 /* genAndOp - for && operation                                     */
4798 /*-----------------------------------------------------------------*/
4799 static void genAndOp (iCode *ic)
4800 {
4801     operand *left,*right, *result;
4802     symbol *tlbl;
4803
4804     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4805     /* note here that && operations that are in an
4806     if statement are taken away by backPatchLabels
4807     only those used in arthmetic operations remain */
4808     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4809     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4810     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4811
4812     /* if both are bit variables */
4813     if (AOP_TYPE(left) == AOP_CRY &&
4814         AOP_TYPE(right) == AOP_CRY ) {
4815         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4816         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4817         outBitC(result);
4818     } else {
4819         tlbl = newiTempLabel(NULL);
4820         toBoolean(left);    
4821         emitcode("jz","%05d_DS_",tlbl->key+100);
4822         toBoolean(right);
4823         emitcode("","%05d_DS_:",tlbl->key+100);
4824         outBitAcc(result);
4825     }
4826
4827     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4828     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4829     freeAsmop(result,NULL,ic,TRUE);
4830 }
4831
4832
4833 /*-----------------------------------------------------------------*/
4834 /* genOrOp - for || operation                                      */
4835 /*-----------------------------------------------------------------*/
4836 /*
4837   tsd pic port -
4838   modified this code, but it doesn't appear to ever get called
4839 */
4840
4841 static void genOrOp (iCode *ic)
4842 {
4843     operand *left,*right, *result;
4844     symbol *tlbl;
4845
4846     /* note here that || operations that are in an
4847     if statement are taken away by backPatchLabels
4848     only those used in arthmetic operations remain */
4849     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4850     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4851     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4852     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4853
4854     /* if both are bit variables */
4855     if (AOP_TYPE(left) == AOP_CRY &&
4856         AOP_TYPE(right) == AOP_CRY ) {
4857       emitcode("clrc","");
4858       emitcode("btfss","(%s >> 3), (%s & 7)",
4859                AOP(left)->aopu.aop_dir,
4860                AOP(left)->aopu.aop_dir);
4861       emitcode("btfsc","(%s >> 3), (%s & 7)",
4862                AOP(right)->aopu.aop_dir,
4863                AOP(right)->aopu.aop_dir);
4864       emitcode("setc","");
4865
4866     } else {
4867         tlbl = newiTempLabel(NULL);
4868         toBoolean(left);
4869         emitSKPZ;
4870         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4871         toBoolean(right);
4872         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4873
4874         outBitAcc(result);
4875     }
4876
4877     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4878     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4879     freeAsmop(result,NULL,ic,TRUE);            
4880 }
4881
4882 /*-----------------------------------------------------------------*/
4883 /* isLiteralBit - test if lit == 2^n                               */
4884 /*-----------------------------------------------------------------*/
4885 static int isLiteralBit(unsigned long lit)
4886 {
4887     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4888     0x100L,0x200L,0x400L,0x800L,
4889     0x1000L,0x2000L,0x4000L,0x8000L,
4890     0x10000L,0x20000L,0x40000L,0x80000L,
4891     0x100000L,0x200000L,0x400000L,0x800000L,
4892     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4893     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4894     int idx;
4895     
4896     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4897     for(idx = 0; idx < 32; idx++)
4898         if(lit == pw[idx])
4899             return idx+1;
4900     return 0;
4901 }
4902
4903 /*-----------------------------------------------------------------*/
4904 /* continueIfTrue -                                                */
4905 /*-----------------------------------------------------------------*/
4906 static void continueIfTrue (iCode *ic)
4907 {
4908     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4909     if(IC_TRUE(ic))
4910         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4911     ic->generated = 1;
4912 }
4913
4914 /*-----------------------------------------------------------------*/
4915 /* jmpIfTrue -                                                     */
4916 /*-----------------------------------------------------------------*/
4917 static void jumpIfTrue (iCode *ic)
4918 {
4919     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4920     if(!IC_TRUE(ic))
4921         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4922     ic->generated = 1;
4923 }
4924
4925 /*-----------------------------------------------------------------*/
4926 /* jmpTrueOrFalse -                                                */
4927 /*-----------------------------------------------------------------*/
4928 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4929 {
4930     // ugly but optimized by peephole
4931     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4932     if(IC_TRUE(ic)){
4933         symbol *nlbl = newiTempLabel(NULL);
4934         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4935         emitcode("","%05d_DS_:",tlbl->key+100);
4936         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4937         emitcode("","%05d_DS_:",nlbl->key+100);
4938     }
4939     else{
4940         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4941         emitcode("","%05d_DS_:",tlbl->key+100);
4942     }
4943     ic->generated = 1;
4944 }
4945
4946 /*-----------------------------------------------------------------*/
4947 /* genAnd  - code for and                                          */
4948 /*-----------------------------------------------------------------*/
4949 static void genAnd (iCode *ic, iCode *ifx)
4950 {
4951     operand *left, *right, *result;
4952     int size, offset=0;  
4953     unsigned long lit = 0L;
4954     int bytelit = 0;
4955     char buffer[10];
4956
4957     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4958     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4959     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4960     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4961
4962 #ifdef DEBUG_TYPE
4963     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4964              AOP_TYPE(result),
4965              AOP_TYPE(left), AOP_TYPE(right));
4966     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4967              AOP_SIZE(result),
4968              AOP_SIZE(left), AOP_SIZE(right));
4969 #endif
4970
4971     /* if left is a literal & right is not then exchange them */
4972     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4973         AOP_NEEDSACC(left)) {
4974         operand *tmp = right ;
4975         right = left;
4976         left = tmp;
4977     }
4978
4979     /* if result = right then exchange them */
4980     if(sameRegs(AOP(result),AOP(right))){
4981         operand *tmp = right ;
4982         right = left;
4983         left = tmp;
4984     }
4985
4986     /* if right is bit then exchange them */
4987     if (AOP_TYPE(right) == AOP_CRY &&
4988         AOP_TYPE(left) != AOP_CRY){
4989         operand *tmp = right ;
4990         right = left;
4991         left = tmp;
4992     }
4993     if(AOP_TYPE(right) == AOP_LIT)
4994         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4995
4996     size = AOP_SIZE(result);
4997
4998     // if(bit & yy)
4999     // result = bit & yy;
5000     if (AOP_TYPE(left) == AOP_CRY){
5001         // c = bit & literal;
5002         if(AOP_TYPE(right) == AOP_LIT){
5003             if(lit & 1) {
5004                 if(size && sameRegs(AOP(result),AOP(left)))
5005                     // no change
5006                     goto release;
5007                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5008             } else {
5009                 // bit(result) = 0;
5010                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5011                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5012                     goto release;
5013                 }
5014                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5015                     jumpIfTrue(ifx);
5016                     goto release;
5017                 }
5018                 emitcode("clr","c");
5019             }
5020         } else {
5021             if (AOP_TYPE(right) == AOP_CRY){
5022                 // c = bit & bit;
5023                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5024                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5025             } else {
5026                 // c = bit & val;
5027                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5028                 // c = lsb
5029                 emitcode("rrc","a");
5030                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5031             }
5032         }
5033         // bit = c
5034         // val = c
5035         if(size)
5036             outBitC(result);
5037         // if(bit & ...)
5038         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5039             genIfxJump(ifx, "c");           
5040         goto release ;
5041     }
5042
5043     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5044     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5045     if((AOP_TYPE(right) == AOP_LIT) &&
5046        (AOP_TYPE(result) == AOP_CRY) &&
5047        (AOP_TYPE(left) != AOP_CRY)){
5048         int posbit = isLiteralBit(lit);
5049         /* left &  2^n */
5050         if(posbit){
5051             posbit--;
5052             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5053             // bit = left & 2^n
5054             if(size)
5055                 emitcode("mov","c,acc.%d",posbit&0x07);
5056             // if(left &  2^n)
5057             else{
5058                 if(ifx){
5059                     sprintf(buffer,"acc.%d",posbit&0x07);
5060                     genIfxJump(ifx, buffer);
5061                 }
5062                 goto release;
5063             }
5064         } else {
5065             symbol *tlbl = newiTempLabel(NULL);
5066             int sizel = AOP_SIZE(left);
5067             if(size)
5068                 emitcode("setb","c");
5069             while(sizel--){
5070                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5071                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5072                     // byte ==  2^n ?
5073                     if((posbit = isLiteralBit(bytelit)) != 0)
5074                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5075                     else{
5076                         if(bytelit != 0x0FFL)
5077                             emitcode("anl","a,%s",
5078                                      aopGet(AOP(right),offset,FALSE,TRUE));
5079                         emitcode("jnz","%05d_DS_",tlbl->key+100);
5080                     }
5081                 }
5082                 offset++;
5083             }
5084             // bit = left & literal
5085             if(size){
5086                 emitcode("clr","c");
5087                 emitcode("","%05d_DS_:",tlbl->key+100);
5088             }
5089             // if(left & literal)
5090             else{
5091                 if(ifx)
5092                     jmpTrueOrFalse(ifx, tlbl);
5093                 goto release ;
5094             }
5095         }
5096         outBitC(result);
5097         goto release ;
5098     }
5099
5100     /* if left is same as result */
5101     if(sameRegs(AOP(result),AOP(left))){
5102       for(;size--; offset++,lit>>=8) {
5103         if(AOP_TYPE(right) == AOP_LIT){
5104           switch(lit & 0xff) {
5105           case 0x00:
5106             /*  and'ing with 0 has clears the result */
5107             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5108             break;
5109           case 0xff:
5110             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5111             break;
5112
5113           default:
5114             {
5115               int p = my_powof2( (~lit) & 0xff );
5116               if(p>=0) {
5117                 /* only one bit is set in the literal, so use a bcf instruction */
5118                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5119               } else {
5120                 emitcode("movlw","0x%x", (lit & 0xff));
5121                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5122               }
5123             }    
5124           }
5125         } else {
5126           if (AOP_TYPE(left) == AOP_ACC) 
5127             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5128           else {                    
5129             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5130             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5131
5132           }
5133         }
5134       }
5135
5136     } else {
5137         // left & result in different registers
5138         if(AOP_TYPE(result) == AOP_CRY){
5139             // result = bit
5140             // if(size), result in bit
5141             // if(!size && ifx), conditional oper: if(left & right)
5142             symbol *tlbl = newiTempLabel(NULL);
5143             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5144             if(size)
5145                 emitcode("setb","c");
5146             while(sizer--){
5147                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5148                 emitcode("anl","a,%s",
5149                          aopGet(AOP(left),offset,FALSE,FALSE));
5150                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5151                 offset++;
5152             }
5153             if(size){
5154                 CLRC;
5155                 emitcode("","%05d_DS_:",tlbl->key+100);
5156                 outBitC(result);
5157             } else if(ifx)
5158                 jmpTrueOrFalse(ifx, tlbl);
5159         } else {
5160           for(;(size--);offset++) {
5161             // normal case
5162             // result = left & right
5163             if(AOP_TYPE(right) == AOP_LIT){
5164               int t = (lit >> (offset*8)) & 0x0FFL;
5165               switch(t) { 
5166               case 0x00:
5167                 emitcode("clrf","%s",
5168                          aopGet(AOP(result),offset,FALSE,FALSE));
5169                 break;
5170               case 0xff:
5171                 emitcode("movf","%s,w",
5172                          aopGet(AOP(left),offset,FALSE,FALSE));
5173                 emitcode("movwf","%s",
5174                          aopGet(AOP(result),offset,FALSE,FALSE));
5175                 break;
5176               default:
5177                 emitcode("movlw","0x%x",t);
5178                 emitcode("andwf","%s,w",
5179                          aopGet(AOP(left),offset,FALSE,FALSE));
5180                 emitcode("movwf","%s",
5181                          aopGet(AOP(result),offset,FALSE,FALSE));
5182               
5183               }
5184               continue;
5185             }
5186
5187             if (AOP_TYPE(left) == AOP_ACC) 
5188               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5189             else {
5190               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5191               emitcode("andwf","%s,w",
5192                        aopGet(AOP(left),offset,FALSE,FALSE));
5193             }
5194             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5195           }
5196         }
5197     }
5198
5199 release :
5200     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5202     freeAsmop(result,NULL,ic,TRUE);     
5203 }
5204
5205 /*-----------------------------------------------------------------*/
5206 /* genOr  - code for or                                            */
5207 /*-----------------------------------------------------------------*/
5208 static void genOr (iCode *ic, iCode *ifx)
5209 {
5210     operand *left, *right, *result;
5211     int size, offset=0;
5212     unsigned long lit = 0L;
5213
5214     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5215
5216     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5217     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5218     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5219
5220
5221     /* if left is a literal & right is not then exchange them */
5222     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5223         AOP_NEEDSACC(left)) {
5224         operand *tmp = right ;
5225         right = left;
5226         left = tmp;
5227     }
5228
5229     /* if result = right then exchange them */
5230     if(sameRegs(AOP(result),AOP(right))){
5231         operand *tmp = right ;
5232         right = left;
5233         left = tmp;
5234     }
5235
5236     /* if right is bit then exchange them */
5237     if (AOP_TYPE(right) == AOP_CRY &&
5238         AOP_TYPE(left) != AOP_CRY){
5239         operand *tmp = right ;
5240         right = left;
5241         left = tmp;
5242     }
5243
5244     if(AOP_TYPE(right) == AOP_LIT)
5245         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5246
5247     size = AOP_SIZE(result);
5248
5249     // if(bit | yy)
5250     // xx = bit | yy;
5251     if (AOP_TYPE(left) == AOP_CRY){
5252         if(AOP_TYPE(right) == AOP_LIT){
5253             // c = bit & literal;
5254             if(lit){
5255                 // lit != 0 => result = 1
5256                 if(AOP_TYPE(result) == AOP_CRY){
5257                   if(size)
5258                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5259                   //emitcode("bsf","(%s >> 3), (%s & 7)",
5260                   //     AOP(result)->aopu.aop_dir,
5261                   //     AOP(result)->aopu.aop_dir);
5262                     else if(ifx)
5263                         continueIfTrue(ifx);
5264                     goto release;
5265                 }
5266             } else {
5267                 // lit == 0 => result = left
5268                 if(size && sameRegs(AOP(result),AOP(left)))
5269                     goto release;
5270                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5271             }
5272         } else {
5273             if (AOP_TYPE(right) == AOP_CRY){
5274               if(sameRegs(AOP(result),AOP(left))){
5275                 // c = bit | bit;
5276                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5277                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5278                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5279
5280                 emitcode("bcf","(%s >> 3), (%s & 7)",
5281                          AOP(result)->aopu.aop_dir,
5282                          AOP(result)->aopu.aop_dir);
5283                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5284                          AOP(right)->aopu.aop_dir,
5285                          AOP(right)->aopu.aop_dir);
5286                 emitcode("bsf","(%s >> 3), (%s & 7)",
5287                          AOP(result)->aopu.aop_dir,
5288                          AOP(result)->aopu.aop_dir);
5289               } else {
5290
5291                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5292                 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5293                 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5294                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5295
5296                 emitcode("bcf","(%s >> 3), (%s & 7)",
5297                          AOP(result)->aopu.aop_dir,
5298                          AOP(result)->aopu.aop_dir);
5299                 emitcode("btfss","(%s >> 3), (%s & 7)",
5300                          AOP(right)->aopu.aop_dir,
5301                          AOP(right)->aopu.aop_dir);
5302                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5303                          AOP(left)->aopu.aop_dir,
5304                          AOP(left)->aopu.aop_dir);
5305                 emitcode("bsf","(%s >> 3), (%s & 7)",
5306                          AOP(result)->aopu.aop_dir,
5307                          AOP(result)->aopu.aop_dir);
5308               }
5309             }
5310             else{
5311                 // c = bit | val;
5312                 symbol *tlbl = newiTempLabel(NULL);
5313                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5314                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5315                     emitcode(";XXX setb","c");
5316                 emitcode(";XXX jb","%s,%05d_DS_",
5317                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5318                 toBoolean(right);
5319                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5320                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5321                     jmpTrueOrFalse(ifx, tlbl);
5322                     goto release;
5323                 } else {
5324                     CLRC;
5325                     emitcode("","%05d_DS_:",tlbl->key+100);
5326                 }
5327             }
5328         }
5329         // bit = c
5330         // val = c
5331         if(size)
5332             outBitC(result);
5333         // if(bit | ...)
5334         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5335             genIfxJump(ifx, "c");           
5336         goto release ;
5337     }
5338
5339     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5340     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5341     if((AOP_TYPE(right) == AOP_LIT) &&
5342        (AOP_TYPE(result) == AOP_CRY) &&
5343        (AOP_TYPE(left) != AOP_CRY)){
5344         if(lit){
5345           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5346             // result = 1
5347             if(size)
5348                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5349             else 
5350                 continueIfTrue(ifx);
5351             goto release;
5352         } else {
5353           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5354             // lit = 0, result = boolean(left)
5355             if(size)
5356                 emitcode(";XXX setb","c");
5357             toBoolean(right);
5358             if(size){
5359                 symbol *tlbl = newiTempLabel(NULL);
5360                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5361                 CLRC;
5362                 emitcode("","%05d_DS_:",tlbl->key+100);
5363             } else {
5364                 genIfxJump (ifx,"a");
5365                 goto release;
5366             }
5367         }
5368         outBitC(result);
5369         goto release ;
5370     }
5371
5372     /* if left is same as result */
5373     if(sameRegs(AOP(result),AOP(left))){
5374       for(;size--; offset++,lit>>=8) {
5375         if(AOP_TYPE(right) == AOP_LIT){
5376           if((lit & 0xff) == 0)
5377             /*  or'ing with 0 has no effect */
5378             continue;
5379           else {
5380             int p = my_powof2(lit & 0xff);
5381             if(p>=0) {
5382               /* only one bit is set in the literal, so use a bsf instruction */
5383               emitpcode(POC_BSF,   popGet(AOP(left),offset,FALSE,FALSE));
5384               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5385             } else {
5386               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5387               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5388
5389               emitcode("movlw","0x%x", (lit & 0xff));
5390               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5391             }
5392                     
5393           }
5394         } else {
5395           if (AOP_TYPE(left) == AOP_ACC) {
5396             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5397             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5398           } else {                  
5399             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5400             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5401
5402             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5403             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5404
5405           }
5406         }
5407       }
5408     } else {
5409         // left & result in different registers
5410         if(AOP_TYPE(result) == AOP_CRY){
5411             // result = bit
5412             // if(size), result in bit
5413             // if(!size && ifx), conditional oper: if(left | right)
5414             symbol *tlbl = newiTempLabel(NULL);
5415             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5416             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5417
5418             if(size)
5419                 emitcode(";XXX setb","c");
5420             while(sizer--){
5421                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5422                 emitcode(";XXX orl","a,%s",
5423                          aopGet(AOP(left),offset,FALSE,FALSE));
5424                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5425                 offset++;
5426             }
5427             if(size){
5428                 CLRC;
5429                 emitcode("","%05d_DS_:",tlbl->key+100);
5430                 outBitC(result);
5431             } else if(ifx)
5432                 jmpTrueOrFalse(ifx, tlbl);
5433         } else for(;(size--);offset++){
5434           // normal case
5435           // result = left & right
5436           if(AOP_TYPE(right) == AOP_LIT){
5437             int t = (lit >> (offset*8)) & 0x0FFL;
5438             switch(t) { 
5439             case 0x00:
5440               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5441               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5442
5443               emitcode("movf","%s,w",
5444                        aopGet(AOP(left),offset,FALSE,FALSE));
5445               emitcode("movwf","%s",
5446                        aopGet(AOP(result),offset,FALSE,FALSE));
5447               break;
5448             default:
5449               emitpcode(POC_MOVLW,  popGetLit(t));
5450               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5451               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5452
5453               emitcode("movlw","0x%x",t);
5454               emitcode("iorwf","%s,w",
5455                        aopGet(AOP(left),offset,FALSE,FALSE));
5456               emitcode("movwf","%s",
5457                        aopGet(AOP(result),offset,FALSE,FALSE));
5458               
5459             }
5460             continue;
5461           }
5462
5463           // faster than result <- left, anl result,right
5464           // and better if result is SFR
5465           if (AOP_TYPE(left) == AOP_ACC) {
5466             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5467             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5468           } else {
5469             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5470             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5471
5472             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5473             emitcode("iorwf","%s,w",
5474                      aopGet(AOP(left),offset,FALSE,FALSE));
5475           }
5476           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5477           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5478         }
5479     }
5480
5481 release :
5482     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5483     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5484     freeAsmop(result,NULL,ic,TRUE);     
5485 }
5486
5487 /*-----------------------------------------------------------------*/
5488 /* genXor - code for xclusive or                                   */
5489 /*-----------------------------------------------------------------*/
5490 static void genXor (iCode *ic, iCode *ifx)
5491 {
5492     operand *left, *right, *result;
5493     int size, offset=0;
5494     unsigned long lit = 0L;
5495
5496     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5497
5498     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5499     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5500     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5501
5502     /* if left is a literal & right is not ||
5503        if left needs acc & right does not */
5504     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5505         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5506         operand *tmp = right ;
5507         right = left;
5508         left = tmp;
5509     }
5510
5511     /* if result = right then exchange them */
5512     if(sameRegs(AOP(result),AOP(right))){
5513         operand *tmp = right ;
5514         right = left;
5515         left = tmp;
5516     }
5517
5518     /* if right is bit then exchange them */
5519     if (AOP_TYPE(right) == AOP_CRY &&
5520         AOP_TYPE(left) != AOP_CRY){
5521         operand *tmp = right ;
5522         right = left;
5523         left = tmp;
5524     }
5525     if(AOP_TYPE(right) == AOP_LIT)
5526         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5527
5528     size = AOP_SIZE(result);
5529
5530     // if(bit ^ yy)
5531     // xx = bit ^ yy;
5532     if (AOP_TYPE(left) == AOP_CRY){
5533         if(AOP_TYPE(right) == AOP_LIT){
5534             // c = bit & literal;
5535             if(lit>>1){
5536                 // lit>>1  != 0 => result = 1
5537                 if(AOP_TYPE(result) == AOP_CRY){
5538                     if(size)
5539                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5540                     else if(ifx)
5541                         continueIfTrue(ifx);
5542                     goto release;
5543                 }
5544                 emitcode("setb","c");
5545             } else{
5546                 // lit == (0 or 1)
5547                 if(lit == 0){
5548                     // lit == 0, result = left
5549                     if(size && sameRegs(AOP(result),AOP(left)))
5550                         goto release;
5551                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5552                 } else{
5553                     // lit == 1, result = not(left)
5554                     if(size && sameRegs(AOP(result),AOP(left))){
5555                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5556                         goto release;
5557                     } else {
5558                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5559                         emitcode("cpl","c");
5560                     }
5561                 }
5562             }
5563
5564         } else {
5565             // right != literal
5566             symbol *tlbl = newiTempLabel(NULL);
5567             if (AOP_TYPE(right) == AOP_CRY){
5568                 // c = bit ^ bit;
5569                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5570             }
5571             else{
5572                 int sizer = AOP_SIZE(right);
5573                 // c = bit ^ val
5574                 // if val>>1 != 0, result = 1
5575                 emitcode("setb","c");
5576                 while(sizer){
5577                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5578                     if(sizer == 1)
5579                         // test the msb of the lsb
5580                         emitcode("anl","a,#0xfe");
5581                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5582                     sizer--;
5583                 }
5584                 // val = (0,1)
5585                 emitcode("rrc","a");
5586             }
5587             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5588             emitcode("cpl","c");
5589             emitcode("","%05d_DS_:",(tlbl->key+100));
5590         }
5591         // bit = c
5592         // val = c
5593         if(size)
5594             outBitC(result);
5595         // if(bit | ...)
5596         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5597             genIfxJump(ifx, "c");           
5598         goto release ;
5599     }
5600
5601     if(sameRegs(AOP(result),AOP(left))){
5602         /* if left is same as result */
5603         for(;size--; offset++) {
5604             if(AOP_TYPE(right) == AOP_LIT){
5605                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5606                     continue;
5607                 else
5608                     if (IS_AOP_PREG(left)) {
5609                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5610                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5611                         aopPut(AOP(result),"a",offset);
5612                     } else 
5613                         emitcode("xrl","%s,%s",
5614                                  aopGet(AOP(left),offset,FALSE,TRUE),
5615                                  aopGet(AOP(right),offset,FALSE,FALSE));
5616             } else {
5617                 if (AOP_TYPE(left) == AOP_ACC)
5618                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5619                 else {
5620                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5621                     if (IS_AOP_PREG(left)) {
5622                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5623                         aopPut(AOP(result),"a",offset);
5624                     } else
5625                         emitcode("xrl","%s,a",
5626                                  aopGet(AOP(left),offset,FALSE,TRUE));
5627                 }
5628             }
5629         }
5630     } else {
5631         // left & result in different registers
5632         if(AOP_TYPE(result) == AOP_CRY){
5633             // result = bit
5634             // if(size), result in bit
5635             // if(!size && ifx), conditional oper: if(left ^ right)
5636             symbol *tlbl = newiTempLabel(NULL);
5637             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5638             if(size)
5639                 emitcode("setb","c");
5640             while(sizer--){
5641                 if((AOP_TYPE(right) == AOP_LIT) &&
5642                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5643                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5644                 } else {
5645                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5646                     emitcode("xrl","a,%s",
5647                              aopGet(AOP(left),offset,FALSE,FALSE));
5648                 }
5649                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5650                 offset++;
5651             }
5652             if(size){
5653                 CLRC;
5654                 emitcode("","%05d_DS_:",tlbl->key+100);
5655                 outBitC(result);
5656             } else if(ifx)
5657                 jmpTrueOrFalse(ifx, tlbl);
5658         } else for(;(size--);offset++){
5659             // normal case
5660             // result = left & right
5661             if(AOP_TYPE(right) == AOP_LIT){
5662               int t = (lit >> (offset*8)) & 0x0FFL;
5663               switch(t) { 
5664               case 0x00:
5665                 emitcode("movf","%s,w",
5666                          aopGet(AOP(left),offset,FALSE,FALSE));
5667                 emitcode("movwf","%s",
5668                          aopGet(AOP(result),offset,FALSE,FALSE));
5669                 break;
5670               case 0xff:
5671                 emitcode("comf","%s,w",
5672                          aopGet(AOP(left),offset,FALSE,FALSE));
5673                 emitcode("movwf","%s",
5674                          aopGet(AOP(result),offset,FALSE,FALSE));
5675                 break;
5676               default:
5677                 emitcode("movlw","0x%x",t);
5678                 emitcode("xorwf","%s,w",
5679                          aopGet(AOP(left),offset,FALSE,FALSE));
5680                 emitcode("movwf","%s",
5681                          aopGet(AOP(result),offset,FALSE,FALSE));
5682
5683               }
5684               continue;
5685             }
5686
5687             // faster than result <- left, anl result,right
5688             // and better if result is SFR
5689             if (AOP_TYPE(left) == AOP_ACC)
5690                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5691             else {
5692                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5693                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5694             }
5695             if ( AOP_TYPE(result) != AOP_ACC)
5696               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5697         }
5698     }
5699
5700 release :
5701     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5702     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5703     freeAsmop(result,NULL,ic,TRUE);     
5704 }
5705
5706 /*-----------------------------------------------------------------*/
5707 /* genInline - write the inline code out                           */
5708 /*-----------------------------------------------------------------*/
5709 static void genInline (iCode *ic)
5710 {
5711     char buffer[MAX_INLINEASM];
5712     char *bp = buffer;
5713     char *bp1= buffer;
5714     
5715     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5716
5717     _G.inLine += (!options.asmpeep);
5718     strcpy(buffer,IC_INLINE(ic));
5719
5720     /* emit each line as a code */
5721     while (*bp) {
5722         if (*bp == '\n') {
5723             *bp++ = '\0';
5724             emitcode(bp1,"");
5725             bp1 = bp;
5726         } else {
5727             if (*bp == ':') {
5728                 bp++;
5729                 *bp = '\0';
5730                 bp++;
5731                 emitcode(bp1,"");
5732                 bp1 = bp;
5733             } else
5734                 bp++;
5735         }
5736     }
5737     if (bp1 != bp)
5738         emitcode(bp1,"");
5739     /*     emitcode("",buffer); */
5740     _G.inLine -= (!options.asmpeep);
5741 }
5742
5743 /*-----------------------------------------------------------------*/
5744 /* genRRC - rotate right with carry                                */
5745 /*-----------------------------------------------------------------*/
5746 static void genRRC (iCode *ic)
5747 {
5748     operand *left , *result ;
5749     int size, offset = 0;
5750     char *l;    
5751
5752     /* rotate right with carry */
5753     left = IC_LEFT(ic);
5754     result=IC_RESULT(ic);
5755     aopOp (left,ic,FALSE);
5756     aopOp (result,ic,FALSE);
5757
5758     /* move it to the result */
5759     size = AOP_SIZE(result);    
5760     offset = size - 1 ;
5761     CLRC;
5762     while (size--) {
5763         l = aopGet(AOP(left),offset,FALSE,FALSE);
5764         MOVA(l);
5765         emitcode("rrc","a");
5766         if (AOP_SIZE(result) > 1)
5767             aopPut(AOP(result),"a",offset--);
5768     }
5769     /* now we need to put the carry into the
5770     highest order byte of the result */
5771     if (AOP_SIZE(result) > 1) {
5772         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5773         MOVA(l);
5774     }
5775     emitcode("mov","acc.7,c");
5776     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5777     freeAsmop(left,NULL,ic,TRUE);
5778     freeAsmop(result,NULL,ic,TRUE);
5779 }
5780
5781 /*-----------------------------------------------------------------*/
5782 /* genRLC - generate code for rotate left with carry               */
5783 /*-----------------------------------------------------------------*/
5784 static void genRLC (iCode *ic)
5785 {    
5786     operand *left , *result ;
5787     int size, offset = 0;
5788     char *l;    
5789
5790     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5791     /* rotate right with carry */
5792     left = IC_LEFT(ic);
5793     result=IC_RESULT(ic);
5794     aopOp (left,ic,FALSE);
5795     aopOp (result,ic,FALSE);
5796
5797     /* move it to the result */
5798     size = AOP_SIZE(result);    
5799     offset = 0 ;
5800     if (size--) {
5801         l = aopGet(AOP(left),offset,FALSE,FALSE);
5802         MOVA(l);
5803         emitcode("add","a,acc");
5804         if (AOP_SIZE(result) > 1)
5805             aopPut(AOP(result),"a",offset++);
5806         while (size--) {
5807             l = aopGet(AOP(left),offset,FALSE,FALSE);
5808             MOVA(l);
5809             emitcode("rlc","a");
5810             if (AOP_SIZE(result) > 1)
5811                 aopPut(AOP(result),"a",offset++);
5812         }
5813     }
5814     /* now we need to put the carry into the
5815     highest order byte of the result */
5816     if (AOP_SIZE(result) > 1) {
5817         l = aopGet(AOP(result),0,FALSE,FALSE);
5818         MOVA(l);
5819     }
5820     emitcode("mov","acc.0,c");
5821     aopPut(AOP(result),"a",0);
5822     freeAsmop(left,NULL,ic,TRUE);
5823     freeAsmop(result,NULL,ic,TRUE);
5824 }
5825
5826 /*-----------------------------------------------------------------*/
5827 /* genGetHbit - generates code get highest order bit               */
5828 /*-----------------------------------------------------------------*/
5829 static void genGetHbit (iCode *ic)
5830 {
5831     operand *left, *result;
5832     left = IC_LEFT(ic);
5833     result=IC_RESULT(ic);
5834     aopOp (left,ic,FALSE);
5835     aopOp (result,ic,FALSE);
5836
5837     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5838     /* get the highest order byte into a */
5839     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5840     if(AOP_TYPE(result) == AOP_CRY){
5841         emitcode("rlc","a");
5842         outBitC(result);
5843     }
5844     else{
5845         emitcode("rl","a");
5846         emitcode("anl","a,#0x01");
5847         outAcc(result);
5848     }
5849
5850
5851     freeAsmop(left,NULL,ic,TRUE);
5852     freeAsmop(result,NULL,ic,TRUE);
5853 }
5854
5855 /*-----------------------------------------------------------------*/
5856 /* AccRol - rotate left accumulator by known count                 */
5857 /*-----------------------------------------------------------------*/
5858 static void AccRol (int shCount)
5859 {
5860     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5861     shCount &= 0x0007;              // shCount : 0..7
5862     switch(shCount){
5863         case 0 :
5864             break;
5865         case 1 :
5866             emitcode("rl","a");
5867             break;
5868         case 2 :
5869             emitcode("rl","a");
5870             emitcode("rl","a");
5871             break;
5872         case 3 :
5873             emitcode("swap","a");
5874             emitcode("rr","a");
5875             break;
5876         case 4 :
5877             emitcode("swap","a");
5878             break;
5879         case 5 :
5880             emitcode("swap","a");
5881             emitcode("rl","a");
5882             break;
5883         case 6 :
5884             emitcode("rr","a");
5885             emitcode("rr","a");
5886             break;
5887         case 7 :
5888             emitcode("rr","a");
5889             break;
5890     }
5891 }
5892
5893 /*-----------------------------------------------------------------*/
5894 /* AccLsh - left shift accumulator by known count                  */
5895 /*-----------------------------------------------------------------*/
5896 static void AccLsh (int shCount)
5897 {
5898     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899     if(shCount != 0){
5900         if(shCount == 1)
5901             emitcode("add","a,acc");
5902         else 
5903             if(shCount == 2) {
5904             emitcode("add","a,acc");
5905             emitcode("add","a,acc");
5906         } else {
5907             /* rotate left accumulator */
5908             AccRol(shCount);
5909             /* and kill the lower order bits */
5910             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5911         }
5912     }
5913 }
5914
5915 /*-----------------------------------------------------------------*/
5916 /* AccRsh - right shift accumulator by known count                 */
5917 /*-----------------------------------------------------------------*/
5918 static void AccRsh (int shCount)
5919 {
5920     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5921     if(shCount != 0){
5922         if(shCount == 1){
5923             CLRC;
5924             emitcode("rrc","a");
5925         } else {
5926             /* rotate right accumulator */
5927             AccRol(8 - shCount);
5928             /* and kill the higher order bits */
5929             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5930         }
5931     }
5932 }
5933
5934 /*-----------------------------------------------------------------*/
5935 /* AccSRsh - signed right shift accumulator by known count                 */
5936 /*-----------------------------------------------------------------*/
5937 static void AccSRsh (int shCount)
5938 {
5939     symbol *tlbl ;
5940     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5941     if(shCount != 0){
5942         if(shCount == 1){
5943             emitcode("mov","c,acc.7");
5944             emitcode("rrc","a");
5945         } else if(shCount == 2){
5946             emitcode("mov","c,acc.7");
5947             emitcode("rrc","a");
5948             emitcode("mov","c,acc.7");
5949             emitcode("rrc","a");
5950         } else {
5951             tlbl = newiTempLabel(NULL);
5952             /* rotate right accumulator */
5953             AccRol(8 - shCount);
5954             /* and kill the higher order bits */
5955             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5956             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5957             emitcode("orl","a,#0x%02x",
5958                      (unsigned char)~SRMask[shCount]);
5959             emitcode("","%05d_DS_:",tlbl->key+100);
5960         }
5961     }
5962 }
5963
5964 /*-----------------------------------------------------------------*/
5965 /* shiftR1Left2Result - shift right one byte from left to result   */
5966 /*-----------------------------------------------------------------*/
5967 static void shiftR1Left2Result (operand *left, int offl,
5968                                 operand *result, int offr,
5969                                 int shCount, int sign)
5970 {
5971     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5972     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5973     /* shift right accumulator */
5974     if(sign)
5975         AccSRsh(shCount);
5976     else
5977         AccRsh(shCount);
5978     aopPut(AOP(result),"a",offr);
5979 }
5980
5981 /*-----------------------------------------------------------------*/
5982 /* shiftL1Left2Result - shift left one byte from left to result    */
5983 /*-----------------------------------------------------------------*/
5984 static void shiftL1Left2Result (operand *left, int offl,
5985                                 operand *result, int offr, int shCount)
5986 {
5987     char *l;
5988     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5989     l = aopGet(AOP(left),offl,FALSE,FALSE);
5990     MOVA(l);
5991     /* shift left accumulator */
5992     AccLsh(shCount);
5993     aopPut(AOP(result),"a",offr);
5994 }
5995
5996 /*-----------------------------------------------------------------*/
5997 /* movLeft2Result - move byte from left to result                  */
5998 /*-----------------------------------------------------------------*/
5999 static void movLeft2Result (operand *left, int offl,
6000                             operand *result, int offr, int sign)
6001 {
6002     char *l;
6003     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6004     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6005         l = aopGet(AOP(left),offl,FALSE,FALSE);
6006
6007         if (*l == '@' && (IS_AOP_PREG(result))) {
6008             emitcode("mov","a,%s",l);
6009             aopPut(AOP(result),"a",offr);
6010         } else {
6011             if(!sign)
6012                 aopPut(AOP(result),l,offr);
6013             else{
6014                 /* MSB sign in acc.7 ! */
6015                 if(getDataSize(left) == offl+1){
6016                     emitcode("mov","a,%s",l);
6017                     aopPut(AOP(result),"a",offr);
6018                 }
6019             }
6020         }
6021     }
6022 }
6023
6024 /*-----------------------------------------------------------------*/
6025 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6026 /*-----------------------------------------------------------------*/
6027 static void AccAXRrl1 (char *x)
6028 {
6029     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6030     emitcode("rrc","a");
6031     emitcode("xch","a,%s", x);
6032     emitcode("rrc","a");
6033     emitcode("xch","a,%s", x);
6034 }
6035
6036 /*-----------------------------------------------------------------*/
6037 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6038 /*-----------------------------------------------------------------*/
6039 static void AccAXLrl1 (char *x)
6040 {
6041     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6042     emitcode("xch","a,%s",x);
6043     emitcode("rlc","a");
6044     emitcode("xch","a,%s",x);
6045     emitcode("rlc","a");
6046 }
6047
6048 /*-----------------------------------------------------------------*/
6049 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6050 /*-----------------------------------------------------------------*/
6051 static void AccAXLsh1 (char *x)
6052 {
6053     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6054     emitcode("xch","a,%s",x);
6055     emitcode("add","a,acc");
6056     emitcode("xch","a,%s",x);
6057     emitcode("rlc","a");
6058 }
6059
6060 /*-----------------------------------------------------------------*/
6061 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6062 /*-----------------------------------------------------------------*/
6063 static void AccAXLsh (char *x, int shCount)
6064 {
6065     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6066     switch(shCount){
6067         case 0 :
6068             break;
6069         case 1 :
6070             AccAXLsh1(x);
6071             break;
6072         case 2 :
6073             AccAXLsh1(x);
6074             AccAXLsh1(x);
6075             break;
6076         case 3 :
6077         case 4 :
6078         case 5 :                        // AAAAABBB:CCCCCDDD
6079             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
6080             emitcode("anl","a,#0x%02x",
6081                      SLMask[shCount]);  // BBB00000:CCCCCDDD
6082             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
6083             AccRol(shCount);            // DDDCCCCC:BBB00000
6084             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
6085             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
6086             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
6087             emitcode("anl","a,#0x%02x",
6088                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
6089             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
6090             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
6091             break;
6092         case 6 :                        // AAAAAABB:CCCCCCDD
6093             emitcode("anl","a,#0x%02x",
6094                      SRMask[shCount]);  // 000000BB:CCCCCCDD
6095             emitcode("mov","c,acc.0");  // c = B
6096             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
6097             AccAXRrl1(x);               // BCCCCCCD:D000000B
6098             AccAXRrl1(x);               // BBCCCCCC:DD000000
6099             break;
6100         case 7 :                        // a:x <<= 7
6101             emitcode("anl","a,#0x%02x",
6102                      SRMask[shCount]);  // 0000000B:CCCCCCCD
6103             emitcode("mov","c,acc.0");  // c = B
6104             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
6105             AccAXRrl1(x);               // BCCCCCCC:D0000000
6106             break;
6107         default :
6108             break;
6109     }
6110 }
6111
6112 /*-----------------------------------------------------------------*/
6113 /* AccAXRsh - right shift a:x known count (0..7)                   */
6114 /*-----------------------------------------------------------------*/
6115 static void AccAXRsh (char *x, int shCount)
6116 {   
6117     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6118     switch(shCount){
6119         case 0 :
6120             break;
6121         case 1 :
6122             CLRC;
6123             AccAXRrl1(x);               // 0->a:x
6124             break;
6125         case 2 :
6126             CLRC;
6127             AccAXRrl1(x);               // 0->a:x
6128             CLRC;
6129             AccAXRrl1(x);               // 0->a:x
6130             break;
6131         case 3 :
6132         case 4 :
6133         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6134             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
6135             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6136             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6137             emitcode("anl","a,#0x%02x",
6138                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6139             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6140             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6141             emitcode("anl","a,#0x%02x",
6142                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6143             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6144             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6145             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
6146             break;
6147         case 6 :                        // AABBBBBB:CCDDDDDD
6148             emitcode("mov","c,acc.7");
6149             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6150             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6151             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6152             emitcode("anl","a,#0x%02x",
6153                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6154             break;
6155         case 7 :                        // ABBBBBBB:CDDDDDDD
6156             emitcode("mov","c,acc.7");  // c = A
6157             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6158             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6159             emitcode("anl","a,#0x%02x",
6160                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6161             break;
6162         default :
6163             break;
6164     }
6165 }
6166
6167 /*-----------------------------------------------------------------*/
6168 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6169 /*-----------------------------------------------------------------*/
6170 static void AccAXRshS (char *x, int shCount)
6171 {   
6172     symbol *tlbl ;
6173     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6174     switch(shCount){
6175         case 0 :
6176             break;
6177         case 1 :
6178             emitcode("mov","c,acc.7");
6179             AccAXRrl1(x);               // s->a:x
6180             break;
6181         case 2 :
6182             emitcode("mov","c,acc.7");
6183             AccAXRrl1(x);               // s->a:x
6184             emitcode("mov","c,acc.7");
6185             AccAXRrl1(x);               // s->a:x
6186             break;
6187         case 3 :
6188         case 4 :
6189         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6190             tlbl = newiTempLabel(NULL);
6191             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6192             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6193             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6194             emitcode("anl","a,#0x%02x",
6195                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6196             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6197             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6198             emitcode("anl","a,#0x%02x",
6199                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6200             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6201             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6202             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6203             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6204             emitcode("orl","a,#0x%02x",
6205                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6206             emitcode("","%05d_DS_:",tlbl->key+100);
6207             break;                      // SSSSAAAA:BBBCCCCC
6208         case 6 :                        // AABBBBBB:CCDDDDDD
6209             tlbl = newiTempLabel(NULL);
6210             emitcode("mov","c,acc.7");
6211             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6212             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6213             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6214             emitcode("anl","a,#0x%02x",
6215                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6216             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6217             emitcode("orl","a,#0x%02x",
6218                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6219             emitcode("","%05d_DS_:",tlbl->key+100);
6220             break;
6221         case 7 :                        // ABBBBBBB:CDDDDDDD
6222             tlbl = newiTempLabel(NULL);
6223             emitcode("mov","c,acc.7");  // c = A
6224             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6225             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6226             emitcode("anl","a,#0x%02x",
6227                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6228             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6229             emitcode("orl","a,#0x%02x",
6230                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6231             emitcode("","%05d_DS_:",tlbl->key+100);
6232             break;
6233         default :
6234             break;
6235     }
6236 }
6237
6238 /*-----------------------------------------------------------------*/
6239 /* shiftL2Left2Result - shift left two bytes from left to result   */
6240 /*-----------------------------------------------------------------*/
6241 static void shiftL2Left2Result (operand *left, int offl,
6242                                 operand *result, int offr, int shCount)
6243 {
6244     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245     if(sameRegs(AOP(result), AOP(left)) &&
6246        ((offl + MSB16) == offr)){
6247         /* don't crash result[offr] */
6248         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6249         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6250     } else {
6251         movLeft2Result(left,offl, result, offr, 0);
6252         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6253     }
6254     /* ax << shCount (x = lsb(result))*/
6255     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6256     aopPut(AOP(result),"a",offr+MSB16);
6257 }
6258
6259
6260 /*-----------------------------------------------------------------*/
6261 /* shiftR2Left2Result - shift right two bytes from left to result  */
6262 /*-----------------------------------------------------------------*/
6263 static void shiftR2Left2Result (operand *left, int offl,
6264                                 operand *result, int offr,
6265                                 int shCount, int sign)
6266 {
6267     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6268     if(sameRegs(AOP(result), AOP(left)) &&
6269        ((offl + MSB16) == offr)){
6270         /* don't crash result[offr] */
6271         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6272         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6273     } else {
6274         movLeft2Result(left,offl, result, offr, 0);
6275         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6276     }
6277     /* a:x >> shCount (x = lsb(result))*/
6278     if(sign)
6279         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6280     else
6281         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6282     if(getDataSize(result) > 1)
6283         aopPut(AOP(result),"a",offr+MSB16);
6284 }
6285
6286 /*-----------------------------------------------------------------*/
6287 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6288 /*-----------------------------------------------------------------*/
6289 static void shiftLLeftOrResult (operand *left, int offl,
6290                                 operand *result, int offr, int shCount)
6291 {
6292     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6293     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6294     /* shift left accumulator */
6295     AccLsh(shCount);
6296     /* or with result */
6297     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6298     /* back to result */
6299     aopPut(AOP(result),"a",offr);
6300 }
6301
6302 /*-----------------------------------------------------------------*/
6303 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6304 /*-----------------------------------------------------------------*/
6305 static void shiftRLeftOrResult (operand *left, int offl,
6306                                 operand *result, int offr, int shCount)
6307 {
6308     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6309     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6310     /* shift right accumulator */
6311     AccRsh(shCount);
6312     /* or with result */
6313     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6314     /* back to result */
6315     aopPut(AOP(result),"a",offr);
6316 }
6317
6318 /*-----------------------------------------------------------------*/
6319 /* genlshOne - left shift a one byte quantity by known count       */
6320 /*-----------------------------------------------------------------*/
6321 static void genlshOne (operand *result, operand *left, int shCount)
6322 {       
6323     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6324     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6325 }
6326
6327 /*-----------------------------------------------------------------*/
6328 /* genlshTwo - left shift two bytes by known amount != 0           */
6329 /*-----------------------------------------------------------------*/
6330 static void genlshTwo (operand *result,operand *left, int shCount)
6331 {
6332     int size;
6333     
6334     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6335     size = getDataSize(result);
6336
6337     /* if shCount >= 8 */
6338     if (shCount >= 8) {
6339         shCount -= 8 ;
6340
6341         if (size > 1){
6342             if (shCount)
6343                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6344             else 
6345                 movLeft2Result(left, LSB, result, MSB16, 0);
6346         }
6347         aopPut(AOP(result),zero,LSB);   
6348     }
6349
6350     /*  1 <= shCount <= 7 */
6351     else {  
6352         if(size == 1)
6353             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6354         else 
6355             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6356     }
6357 }
6358
6359 /*-----------------------------------------------------------------*/
6360 /* shiftLLong - shift left one long from left to result            */
6361 /* offl = LSB or MSB16                                             */
6362 /*-----------------------------------------------------------------*/
6363 static void shiftLLong (operand *left, operand *result, int offr )
6364 {
6365     char *l;
6366     int size = AOP_SIZE(result);
6367
6368     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6369     if(size >= LSB+offr){
6370         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6371         MOVA(l);
6372         emitcode("add","a,acc");
6373         if (sameRegs(AOP(left),AOP(result)) && 
6374             size >= MSB16+offr && offr != LSB )
6375             emitcode("xch","a,%s",
6376                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6377         else        
6378             aopPut(AOP(result),"a",LSB+offr);
6379     }
6380
6381     if(size >= MSB16+offr){
6382         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6383             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6384             MOVA(l);
6385         }
6386         emitcode("rlc","a");
6387         if (sameRegs(AOP(left),AOP(result)) && 
6388             size >= MSB24+offr && offr != LSB)
6389             emitcode("xch","a,%s",
6390                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6391         else        
6392             aopPut(AOP(result),"a",MSB16+offr);
6393     }
6394
6395     if(size >= MSB24+offr){
6396         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6397             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6398             MOVA(l);
6399         }
6400         emitcode("rlc","a");
6401         if (sameRegs(AOP(left),AOP(result)) && 
6402             size >= MSB32+offr && offr != LSB )
6403             emitcode("xch","a,%s",
6404                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6405         else        
6406             aopPut(AOP(result),"a",MSB24+offr);
6407     }
6408
6409     if(size > MSB32+offr){
6410         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6411             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6412             MOVA(l);    
6413         }
6414         emitcode("rlc","a");
6415         aopPut(AOP(result),"a",MSB32+offr);
6416     }
6417     if(offr != LSB)
6418         aopPut(AOP(result),zero,LSB);       
6419 }
6420
6421 /*-----------------------------------------------------------------*/
6422 /* genlshFour - shift four byte by a known amount != 0             */
6423 /*-----------------------------------------------------------------*/
6424 static void genlshFour (operand *result, operand *left, int shCount)
6425 {
6426     int size;
6427
6428     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6429     size = AOP_SIZE(result);
6430
6431     /* if shifting more that 3 bytes */
6432     if (shCount >= 24 ) {
6433         shCount -= 24;
6434         if (shCount)
6435             /* lowest order of left goes to the highest
6436             order of the destination */
6437             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6438         else
6439             movLeft2Result(left, LSB, result, MSB32, 0);
6440         aopPut(AOP(result),zero,LSB);
6441         aopPut(AOP(result),zero,MSB16);
6442         aopPut(AOP(result),zero,MSB32);
6443         return;
6444     }
6445
6446     /* more than two bytes */
6447     else if ( shCount >= 16 ) {
6448         /* lower order two bytes goes to higher order two bytes */
6449         shCount -= 16;
6450         /* if some more remaining */
6451         if (shCount)
6452             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6453         else {
6454             movLeft2Result(left, MSB16, result, MSB32, 0);
6455             movLeft2Result(left, LSB, result, MSB24, 0);
6456         }
6457         aopPut(AOP(result),zero,MSB16);
6458         aopPut(AOP(result),zero,LSB);
6459         return;
6460     }    
6461
6462     /* if more than 1 byte */
6463     else if ( shCount >= 8 ) {
6464         /* lower order three bytes goes to higher order  three bytes */
6465         shCount -= 8;
6466         if(size == 2){
6467             if(shCount)
6468                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6469             else
6470                 movLeft2Result(left, LSB, result, MSB16, 0);
6471         }
6472         else{   /* size = 4 */
6473             if(shCount == 0){
6474                 movLeft2Result(left, MSB24, result, MSB32, 0);
6475                 movLeft2Result(left, MSB16, result, MSB24, 0);
6476                 movLeft2Result(left, LSB, result, MSB16, 0);
6477                 aopPut(AOP(result),zero,LSB);
6478             }
6479             else if(shCount == 1)
6480                 shiftLLong(left, result, MSB16);
6481             else{
6482                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6483                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6484                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6485                 aopPut(AOP(result),zero,LSB);
6486             }
6487         }
6488     }
6489
6490     /* 1 <= shCount <= 7 */
6491     else if(shCount <= 2){
6492         shiftLLong(left, result, LSB);
6493         if(shCount == 2)
6494             shiftLLong(result, result, LSB);
6495     }
6496     /* 3 <= shCount <= 7, optimize */
6497     else{
6498         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6499         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6500         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6501     }
6502 }
6503
6504 /*-----------------------------------------------------------------*/
6505 /* genLeftShiftLiteral - left shifting by known count              */
6506 /*-----------------------------------------------------------------*/
6507 static void genLeftShiftLiteral (operand *left,
6508                                  operand *right,
6509                                  operand *result,
6510                                  iCode *ic)
6511 {    
6512     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6513     int size;
6514
6515     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6516     freeAsmop(right,NULL,ic,TRUE);
6517
6518     aopOp(left,ic,FALSE);
6519     aopOp(result,ic,FALSE);
6520
6521     size = getSize(operandType(result));
6522
6523 #if VIEW_SIZE
6524     emitcode("; shift left ","result %d, left %d",size,
6525              AOP_SIZE(left));
6526 #endif
6527
6528     /* I suppose that the left size >= result size */
6529     if(shCount == 0){
6530         while(size--){
6531             movLeft2Result(left, size, result, size, 0);
6532         }
6533     }
6534
6535     else if(shCount >= (size * 8))
6536         while(size--)
6537             aopPut(AOP(result),zero,size);
6538     else{
6539         switch (size) {
6540             case 1:
6541                 genlshOne (result,left,shCount);
6542                 break;
6543
6544             case 2:
6545             case 3:
6546                 genlshTwo (result,left,shCount);
6547                 break;
6548
6549             case 4:
6550                 genlshFour (result,left,shCount);
6551                 break;
6552         }
6553     }
6554     freeAsmop(left,NULL,ic,TRUE);
6555     freeAsmop(result,NULL,ic,TRUE);
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* genLeftShift - generates code for left shifting                 */
6560 /*-----------------------------------------------------------------*/
6561 static void genLeftShift (iCode *ic)
6562 {
6563     operand *left,*right, *result;
6564     int size, offset;
6565     char *l;
6566     symbol *tlbl , *tlbl1;
6567
6568     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6569
6570     right = IC_RIGHT(ic);
6571     left  = IC_LEFT(ic);
6572     result = IC_RESULT(ic);
6573
6574     aopOp(right,ic,FALSE);
6575
6576     /* if the shift count is known then do it 
6577     as efficiently as possible */
6578     if (AOP_TYPE(right) == AOP_LIT) {
6579         genLeftShiftLiteral (left,right,result,ic);
6580         return ;
6581     }
6582
6583     /* shift count is unknown then we have to form 
6584     a loop get the loop count in B : Note: we take
6585     only the lower order byte since shifting
6586     more that 32 bits make no sense anyway, ( the
6587     largest size of an object can be only 32 bits ) */  
6588
6589     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6590     emitcode("inc","b");
6591     freeAsmop (right,NULL,ic,TRUE);
6592     aopOp(left,ic,FALSE);
6593     aopOp(result,ic,FALSE);
6594
6595     /* now move the left to the result if they are not the
6596     same */
6597     if (!sameRegs(AOP(left),AOP(result)) && 
6598         AOP_SIZE(result) > 1) {
6599
6600         size = AOP_SIZE(result);
6601         offset=0;
6602         while (size--) {
6603             l = aopGet(AOP(left),offset,FALSE,TRUE);
6604             if (*l == '@' && (IS_AOP_PREG(result))) {
6605
6606                 emitcode("mov","a,%s",l);
6607                 aopPut(AOP(result),"a",offset);
6608             } else
6609                 aopPut(AOP(result),l,offset);
6610             offset++;
6611         }
6612     }
6613
6614     tlbl = newiTempLabel(NULL);
6615     size = AOP_SIZE(result);
6616     offset = 0 ;   
6617     tlbl1 = newiTempLabel(NULL);
6618
6619     /* if it is only one byte then */
6620     if (size == 1) {
6621         symbol *tlbl1 = newiTempLabel(NULL);
6622
6623         l = aopGet(AOP(left),0,FALSE,FALSE);
6624         MOVA(l);
6625         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6626         emitcode("","%05d_DS_:",tlbl->key+100);
6627         emitcode("add","a,acc");
6628         emitcode("","%05d_DS_:",tlbl1->key+100);
6629         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6630         aopPut(AOP(result),"a",0);
6631         goto release ;
6632     }
6633     
6634     reAdjustPreg(AOP(result));    
6635     
6636     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6637     emitcode("","%05d_DS_:",tlbl->key+100);    
6638     l = aopGet(AOP(result),offset,FALSE,FALSE);
6639     MOVA(l);
6640     emitcode("add","a,acc");         
6641     aopPut(AOP(result),"a",offset++);
6642     while (--size) {
6643         l = aopGet(AOP(result),offset,FALSE,FALSE);
6644         MOVA(l);
6645         emitcode("rlc","a");         
6646         aopPut(AOP(result),"a",offset++);
6647     }
6648     reAdjustPreg(AOP(result));
6649
6650     emitcode("","%05d_DS_:",tlbl1->key+100);
6651     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6652 release:
6653     freeAsmop(left,NULL,ic,TRUE);
6654     freeAsmop(result,NULL,ic,TRUE);
6655 }
6656
6657 /*-----------------------------------------------------------------*/
6658 /* genrshOne - right shift a one byte quantity by known count      */
6659 /*-----------------------------------------------------------------*/
6660 static void genrshOne (operand *result, operand *left,
6661                        int shCount, int sign)
6662 {
6663     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6664     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6665 }
6666
6667 /*-----------------------------------------------------------------*/
6668 /* genrshTwo - right shift two bytes by known amount != 0          */
6669 /*-----------------------------------------------------------------*/
6670 static void genrshTwo (operand *result,operand *left,
6671                        int shCount, int sign)
6672 {
6673     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6674     /* if shCount >= 8 */
6675     if (shCount >= 8) {
6676         shCount -= 8 ;
6677         if (shCount)
6678             shiftR1Left2Result(left, MSB16, result, LSB,
6679                                shCount, sign);
6680         else 
6681             movLeft2Result(left, MSB16, result, LSB, sign);
6682         addSign(result, MSB16, sign);
6683     }
6684
6685     /*  1 <= shCount <= 7 */
6686     else
6687         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6688 }
6689
6690 /*-----------------------------------------------------------------*/
6691 /* shiftRLong - shift right one long from left to result           */
6692 /* offl = LSB or MSB16                                             */
6693 /*-----------------------------------------------------------------*/
6694 static void shiftRLong (operand *left, int offl,
6695                         operand *result, int sign)
6696 {
6697     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6698     if(!sign)
6699         emitcode("clr","c");
6700     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6701     if(sign)
6702         emitcode("mov","c,acc.7");
6703     emitcode("rrc","a");
6704     aopPut(AOP(result),"a",MSB32-offl);
6705     if(offl == MSB16)
6706         /* add sign of "a" */
6707         addSign(result, MSB32, sign);
6708
6709     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6710     emitcode("rrc","a");
6711     aopPut(AOP(result),"a",MSB24-offl);
6712
6713     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6714     emitcode("rrc","a");
6715     aopPut(AOP(result),"a",MSB16-offl);
6716
6717     if(offl == LSB){
6718         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6719         emitcode("rrc","a");
6720         aopPut(AOP(result),"a",LSB);
6721     }
6722 }
6723
6724 /*-----------------------------------------------------------------*/
6725 /* genrshFour - shift four byte by a known amount != 0             */
6726 /*-----------------------------------------------------------------*/
6727 static void genrshFour (operand *result, operand *left,
6728                         int shCount, int sign)
6729 {
6730     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6731     /* if shifting more that 3 bytes */
6732     if(shCount >= 24 ) {
6733         shCount -= 24;
6734         if(shCount)
6735             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6736         else
6737             movLeft2Result(left, MSB32, result, LSB, sign);
6738         addSign(result, MSB16, sign);
6739     }
6740     else if(shCount >= 16){
6741         shCount -= 16;
6742         if(shCount)
6743             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6744         else{
6745             movLeft2Result(left, MSB24, result, LSB, 0);
6746             movLeft2Result(left, MSB32, result, MSB16, sign);
6747         }
6748         addSign(result, MSB24, sign);
6749     }
6750     else if(shCount >= 8){
6751         shCount -= 8;
6752         if(shCount == 1)
6753             shiftRLong(left, MSB16, result, sign);
6754         else if(shCount == 0){
6755             movLeft2Result(left, MSB16, result, LSB, 0);
6756             movLeft2Result(left, MSB24, result, MSB16, 0);
6757             movLeft2Result(left, MSB32, result, MSB24, sign);
6758             addSign(result, MSB32, sign);
6759         }
6760         else{
6761             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6762             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6763             /* the last shift is signed */
6764             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6765             addSign(result, MSB32, sign);
6766         }
6767     }
6768     else{   /* 1 <= shCount <= 7 */
6769         if(shCount <= 2){
6770             shiftRLong(left, LSB, result, sign);
6771             if(shCount == 2)
6772                 shiftRLong(result, LSB, result, sign);
6773         }
6774         else{
6775             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6776             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6777             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6778         }
6779     }
6780 }
6781
6782 /*-----------------------------------------------------------------*/
6783 /* genRightShiftLiteral - right shifting by known count            */
6784 /*-----------------------------------------------------------------*/
6785 static void genRightShiftLiteral (operand *left,
6786                                   operand *right,
6787                                   operand *result,
6788                                   iCode *ic,
6789                                   int sign)
6790 {    
6791     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6792     int size;
6793
6794     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6795     freeAsmop(right,NULL,ic,TRUE);
6796
6797     aopOp(left,ic,FALSE);
6798     aopOp(result,ic,FALSE);
6799
6800 #if VIEW_SIZE
6801     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6802              AOP_SIZE(left));
6803 #endif
6804
6805     size = getDataSize(left);
6806     /* test the LEFT size !!! */
6807
6808     /* I suppose that the left size >= result size */
6809     if(shCount == 0){
6810         size = getDataSize(result);
6811         while(size--)
6812             movLeft2Result(left, size, result, size, 0);
6813     }
6814
6815     else if(shCount >= (size * 8)){
6816         if(sign)
6817             /* get sign in acc.7 */
6818             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6819         addSign(result, LSB, sign);
6820     } else{
6821         switch (size) {
6822             case 1:
6823                 genrshOne (result,left,shCount,sign);
6824                 break;
6825
6826             case 2:
6827                 genrshTwo (result,left,shCount,sign);
6828                 break;
6829
6830             case 4:
6831                 genrshFour (result,left,shCount,sign);
6832                 break;
6833             default :
6834                 break;
6835         }
6836
6837         freeAsmop(left,NULL,ic,TRUE);
6838         freeAsmop(result,NULL,ic,TRUE);
6839     }
6840 }
6841
6842 /*-----------------------------------------------------------------*/
6843 /* genSignedRightShift - right shift of signed number              */
6844 /*-----------------------------------------------------------------*/
6845 static void genSignedRightShift (iCode *ic)
6846 {
6847     operand *right, *left, *result;
6848     int size, offset;
6849     char *l;
6850     symbol *tlbl, *tlbl1 ;
6851
6852     /* we do it the hard way put the shift count in b
6853     and loop thru preserving the sign */
6854     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6855
6856     right = IC_RIGHT(ic);
6857     left  = IC_LEFT(ic);
6858     result = IC_RESULT(ic);
6859
6860     aopOp(right,ic,FALSE);  
6861
6862
6863     if ( AOP_TYPE(right) == AOP_LIT) {
6864         genRightShiftLiteral (left,right,result,ic,1);
6865         return ;
6866     }
6867         /* shift count is unknown then we have to form 
6868        a loop get the loop count in B : Note: we take
6869        only the lower order byte since shifting
6870        more that 32 bits make no sense anyway, ( the
6871        largest size of an object can be only 32 bits ) */  
6872
6873     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6874     emitcode("inc","b");
6875     freeAsmop (right,NULL,ic,TRUE);
6876     aopOp(left,ic,FALSE);
6877     aopOp(result,ic,FALSE);
6878
6879     /* now move the left to the result if they are not the
6880     same */
6881     if (!sameRegs(AOP(left),AOP(result)) && 
6882         AOP_SIZE(result) > 1) {
6883
6884         size = AOP_SIZE(result);
6885         offset=0;
6886         while (size--) {
6887             l = aopGet(AOP(left),offset,FALSE,TRUE);
6888             if (*l == '@' && IS_AOP_PREG(result)) {
6889
6890                 emitcode("mov","a,%s",l);
6891                 aopPut(AOP(result),"a",offset);
6892             } else
6893                 aopPut(AOP(result),l,offset);
6894             offset++;
6895         }
6896     }
6897
6898     /* mov the highest order bit to OVR */    
6899     tlbl = newiTempLabel(NULL);
6900     tlbl1= newiTempLabel(NULL);
6901
6902     size = AOP_SIZE(result);
6903     offset = size - 1;
6904     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6905     emitcode("rlc","a");
6906     emitcode("mov","ov,c");
6907     /* if it is only one byte then */
6908     if (size == 1) {
6909         l = aopGet(AOP(left),0,FALSE,FALSE);
6910         MOVA(l);
6911         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6912         emitcode("","%05d_DS_:",tlbl->key+100);
6913         emitcode("mov","c,ov");
6914         emitcode("rrc","a");
6915         emitcode("","%05d_DS_:",tlbl1->key+100);
6916         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6917         aopPut(AOP(result),"a",0);
6918         goto release ;
6919     }
6920
6921     reAdjustPreg(AOP(result));
6922     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6923     emitcode("","%05d_DS_:",tlbl->key+100);    
6924     emitcode("mov","c,ov");
6925     while (size--) {
6926         l = aopGet(AOP(result),offset,FALSE,FALSE);
6927         MOVA(l);
6928         emitcode("rrc","a");         
6929         aopPut(AOP(result),"a",offset--);
6930     }
6931     reAdjustPreg(AOP(result));
6932     emitcode("","%05d_DS_:",tlbl1->key+100);
6933     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6934
6935 release:
6936     freeAsmop(left,NULL,ic,TRUE);
6937     freeAsmop(result,NULL,ic,TRUE);
6938 }
6939
6940 /*-----------------------------------------------------------------*/
6941 /* genRightShift - generate code for right shifting                */
6942 /*-----------------------------------------------------------------*/
6943 static void genRightShift (iCode *ic)
6944 {
6945     operand *right, *left, *result;
6946     sym_link *retype ;
6947     int size, offset;
6948     char *l;
6949     symbol *tlbl, *tlbl1 ;
6950
6951     /* if signed then we do it the hard way preserve the
6952     sign bit moving it inwards */
6953     retype = getSpec(operandType(IC_RESULT(ic)));
6954     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6955
6956     if (!SPEC_USIGN(retype)) {
6957         genSignedRightShift (ic);
6958         return ;
6959     }
6960
6961     /* signed & unsigned types are treated the same : i.e. the
6962     signed is NOT propagated inwards : quoting from the
6963     ANSI - standard : "for E1 >> E2, is equivalent to division
6964     by 2**E2 if unsigned or if it has a non-negative value,
6965     otherwise the result is implementation defined ", MY definition
6966     is that the sign does not get propagated */
6967
6968     right = IC_RIGHT(ic);
6969     left  = IC_LEFT(ic);
6970     result = IC_RESULT(ic);
6971
6972     aopOp(right,ic,FALSE);
6973
6974     /* if the shift count is known then do it 
6975     as efficiently as possible */
6976     if (AOP_TYPE(right) == AOP_LIT) {
6977         genRightShiftLiteral (left,right,result,ic, 0);
6978         return ;
6979     }
6980
6981     /* shift count is unknown then we have to form 
6982     a loop get the loop count in B : Note: we take
6983     only the lower order byte since shifting
6984     more that 32 bits make no sense anyway, ( the
6985     largest size of an object can be only 32 bits ) */  
6986
6987     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6988     emitcode("inc","b");
6989     freeAsmop (right,NULL,ic,TRUE);
6990     aopOp(left,ic,FALSE);
6991     aopOp(result,ic,FALSE);
6992
6993     /* now move the left to the result if they are not the
6994     same */
6995     if (!sameRegs(AOP(left),AOP(result)) && 
6996         AOP_SIZE(result) > 1) {
6997
6998         size = AOP_SIZE(result);
6999         offset=0;
7000         while (size--) {
7001             l = aopGet(AOP(left),offset,FALSE,TRUE);
7002             if (*l == '@' && IS_AOP_PREG(result)) {
7003
7004                 emitcode("mov","a,%s",l);
7005                 aopPut(AOP(result),"a",offset);
7006             } else
7007                 aopPut(AOP(result),l,offset);
7008             offset++;
7009         }
7010     }
7011
7012     tlbl = newiTempLabel(NULL);
7013     tlbl1= newiTempLabel(NULL);
7014     size = AOP_SIZE(result);
7015     offset = size - 1;
7016
7017     /* if it is only one byte then */
7018     if (size == 1) {
7019         l = aopGet(AOP(left),0,FALSE,FALSE);
7020         MOVA(l);
7021         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7022         emitcode("","%05d_DS_:",tlbl->key+100);
7023         CLRC;
7024         emitcode("rrc","a");
7025         emitcode("","%05d_DS_:",tlbl1->key+100);
7026         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7027         aopPut(AOP(result),"a",0);
7028         goto release ;
7029     }
7030
7031     reAdjustPreg(AOP(result));
7032     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7033     emitcode("","%05d_DS_:",tlbl->key+100);    
7034     CLRC;
7035     while (size--) {
7036         l = aopGet(AOP(result),offset,FALSE,FALSE);
7037         MOVA(l);
7038         emitcode("rrc","a");         
7039         aopPut(AOP(result),"a",offset--);
7040     }
7041     reAdjustPreg(AOP(result));
7042
7043     emitcode("","%05d_DS_:",tlbl1->key+100);
7044     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7045
7046 release:
7047     freeAsmop(left,NULL,ic,TRUE);
7048     freeAsmop(result,NULL,ic,TRUE);
7049 }
7050
7051 /*-----------------------------------------------------------------*/
7052 /* genUnpackBits - generates code for unpacking bits               */
7053 /*-----------------------------------------------------------------*/
7054 static void genUnpackBits (operand *result, char *rname, int ptype)
7055 {    
7056     int shCnt ;
7057     int rlen = 0 ;
7058     sym_link *etype;
7059     int offset = 0 ;
7060
7061     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7062     etype = getSpec(operandType(result));
7063
7064     /* read the first byte  */
7065     switch (ptype) {
7066
7067     case POINTER:
7068     case IPOINTER:
7069         emitcode("mov","a,@%s",rname);
7070         break;
7071         
7072     case PPOINTER:
7073         emitcode("movx","a,@%s",rname);
7074         break;
7075         
7076     case FPOINTER:
7077         emitcode("movx","a,@dptr");
7078         break;
7079
7080     case CPOINTER:
7081         emitcode("clr","a");
7082         emitcode("movc","a","@a+dptr");
7083         break;
7084
7085     case GPOINTER:
7086         emitcode("lcall","__gptrget");
7087         break;
7088     }
7089
7090     /* if we have bitdisplacement then it fits   */
7091     /* into this byte completely or if length is */
7092     /* less than a byte                          */
7093     if ((shCnt = SPEC_BSTR(etype)) || 
7094         (SPEC_BLEN(etype) <= 8))  {
7095
7096         /* shift right acc */
7097         AccRsh(shCnt);
7098
7099         emitcode("anl","a,#0x%02x",
7100                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7101         aopPut(AOP(result),"a",offset);
7102         return ;
7103     }
7104
7105     /* bit field did not fit in a byte  */
7106     rlen = SPEC_BLEN(etype) - 8;
7107     aopPut(AOP(result),"a",offset++);
7108
7109     while (1)  {
7110
7111         switch (ptype) {
7112         case POINTER:
7113         case IPOINTER:
7114             emitcode("inc","%s",rname);
7115             emitcode("mov","a,@%s",rname);
7116             break;
7117             
7118         case PPOINTER:
7119             emitcode("inc","%s",rname);
7120             emitcode("movx","a,@%s",rname);
7121             break;
7122
7123         case FPOINTER:
7124             emitcode("inc","dptr");
7125             emitcode("movx","a,@dptr");
7126             break;
7127             
7128         case CPOINTER:
7129             emitcode("clr","a");
7130             emitcode("inc","dptr");
7131             emitcode("movc","a","@a+dptr");
7132             break;
7133             
7134         case GPOINTER:
7135             emitcode("inc","dptr");
7136             emitcode("lcall","__gptrget");
7137             break;
7138         }
7139
7140         rlen -= 8;            
7141         /* if we are done */
7142         if ( rlen <= 0 )
7143             break ;
7144         
7145         aopPut(AOP(result),"a",offset++);
7146                               
7147     }
7148     
7149     if (rlen) {
7150         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7151         aopPut(AOP(result),"a",offset);        
7152     }
7153     
7154     return ;
7155 }
7156
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genDataPointerGet - generates code when ptr offset is known     */
7160 /*-----------------------------------------------------------------*/
7161 static void genDataPointerGet (operand *left, 
7162                                operand *result, 
7163                                iCode *ic)
7164 {
7165     char *l;
7166     char buffer[256];
7167     int size , offset = 0;
7168     aopOp(result,ic,TRUE);
7169
7170     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7171
7172     /* get the string representation of the name */
7173     l = aopGet(AOP(left),0,FALSE,TRUE);
7174     size = AOP_SIZE(result);
7175     // tsd, was l+1 - the underline `_' prefix was being stripped
7176     while (size--) {
7177         if (offset)
7178             sprintf(buffer,"(%s + %d)",l,offset);
7179         else
7180             sprintf(buffer,"%s",l);
7181         aopPut(AOP(result),buffer,offset++);
7182     }
7183
7184     freeAsmop(left,NULL,ic,TRUE);
7185     freeAsmop(result,NULL,ic,TRUE);
7186 }
7187
7188 /*-----------------------------------------------------------------*/
7189 /* genNearPointerGet - emitcode for near pointer fetch             */
7190 /*-----------------------------------------------------------------*/
7191 static void genNearPointerGet (operand *left, 
7192                                operand *result, 
7193                                iCode *ic)
7194 {
7195     asmop *aop = NULL;
7196     regs *preg = NULL ;
7197     char *rname ;
7198     sym_link *rtype, *retype;
7199     sym_link *ltype = operandType(left);    
7200     char buffer[80];
7201
7202     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7203
7204     rtype = operandType(result);
7205     retype= getSpec(rtype);
7206     
7207     aopOp(left,ic,FALSE);
7208     
7209     /* if left is rematerialisable and
7210        result is not bit variable type and
7211        the left is pointer to data space i.e
7212        lower 128 bytes of space */
7213     if (AOP_TYPE(left) == AOP_IMMD &&
7214         !IS_BITVAR(retype)         &&
7215         DCL_TYPE(ltype) == POINTER) {
7216         genDataPointerGet (left,result,ic);
7217         return ;
7218     }
7219     
7220         /* if the value is already in a pointer register
7221        then don't need anything more */
7222     if (!AOP_INPREG(AOP(left))) {
7223         /* otherwise get a free pointer register */
7224         aop = newAsmop(0);
7225         preg = getFreePtr(ic,&aop,FALSE);
7226         emitcode("mov","%s,%s",
7227                 preg->name,
7228                 aopGet(AOP(left),0,FALSE,TRUE));
7229         rname = preg->name ;
7230     } else
7231         rname = aopGet(AOP(left),0,FALSE,FALSE);
7232     
7233     freeAsmop(left,NULL,ic,TRUE);
7234     aopOp (result,ic,FALSE);
7235     
7236       /* if bitfield then unpack the bits */
7237     if (IS_BITVAR(retype)) 
7238         genUnpackBits (result,rname,POINTER);
7239     else {
7240         /* we have can just get the values */
7241         int size = AOP_SIZE(result);
7242         int offset = 0 ;        
7243         
7244         while (size--) {
7245             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7246
7247                 emitcode("mov","a,@%s",rname);
7248                 aopPut(AOP(result),"a",offset);
7249             } else {
7250                 sprintf(buffer,"@%s",rname);
7251                 aopPut(AOP(result),buffer,offset);
7252             }
7253             offset++ ;
7254             if (size)
7255                 emitcode("inc","%s",rname);
7256         }
7257     }
7258
7259     /* now some housekeeping stuff */
7260     if (aop) {
7261         /* we had to allocate for this iCode */
7262         freeAsmop(NULL,aop,ic,TRUE);
7263     } else { 
7264         /* we did not allocate which means left
7265            already in a pointer register, then
7266            if size > 0 && this could be used again
7267            we have to point it back to where it 
7268            belongs */
7269         if (AOP_SIZE(result) > 1 &&
7270             !OP_SYMBOL(left)->remat &&
7271             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7272               ic->depth )) {
7273             int size = AOP_SIZE(result) - 1;
7274             while (size--)
7275                 emitcode("dec","%s",rname);
7276         }
7277     }
7278
7279     /* done */
7280     freeAsmop(result,NULL,ic,TRUE);
7281      
7282 }
7283
7284 /*-----------------------------------------------------------------*/
7285 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7286 /*-----------------------------------------------------------------*/
7287 static void genPagedPointerGet (operand *left, 
7288                                operand *result, 
7289                                iCode *ic)
7290 {
7291     asmop *aop = NULL;
7292     regs *preg = NULL ;
7293     char *rname ;
7294     sym_link *rtype, *retype;    
7295
7296     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7297
7298     rtype = operandType(result);
7299     retype= getSpec(rtype);
7300     
7301     aopOp(left,ic,FALSE);
7302
7303   /* if the value is already in a pointer register
7304        then don't need anything more */
7305     if (!AOP_INPREG(AOP(left))) {
7306         /* otherwise get a free pointer register */
7307         aop = newAsmop(0);
7308         preg = getFreePtr(ic,&aop,FALSE);
7309         emitcode("mov","%s,%s",
7310                 preg->name,
7311                 aopGet(AOP(left),0,FALSE,TRUE));
7312         rname = preg->name ;
7313     } else
7314         rname = aopGet(AOP(left),0,FALSE,FALSE);
7315     
7316     freeAsmop(left,NULL,ic,TRUE);
7317     aopOp (result,ic,FALSE);
7318
7319     /* if bitfield then unpack the bits */
7320     if (IS_BITVAR(retype)) 
7321         genUnpackBits (result,rname,PPOINTER);
7322     else {
7323         /* we have can just get the values */
7324         int size = AOP_SIZE(result);
7325         int offset = 0 ;        
7326         
7327         while (size--) {
7328             
7329             emitcode("movx","a,@%s",rname);
7330             aopPut(AOP(result),"a",offset);
7331             
7332             offset++ ;
7333             
7334             if (size)
7335                 emitcode("inc","%s",rname);
7336         }
7337     }
7338
7339     /* now some housekeeping stuff */
7340     if (aop) {
7341         /* we had to allocate for this iCode */
7342         freeAsmop(NULL,aop,ic,TRUE);
7343     } else { 
7344         /* we did not allocate which means left
7345            already in a pointer register, then
7346            if size > 0 && this could be used again
7347            we have to point it back to where it 
7348            belongs */
7349         if (AOP_SIZE(result) > 1 &&
7350             !OP_SYMBOL(left)->remat &&
7351             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7352               ic->depth )) {
7353             int size = AOP_SIZE(result) - 1;
7354             while (size--)
7355                 emitcode("dec","%s",rname);
7356         }
7357     }
7358
7359     /* done */
7360     freeAsmop(result,NULL,ic,TRUE);
7361     
7362         
7363 }
7364
7365 /*-----------------------------------------------------------------*/
7366 /* genFarPointerGet - gget value from far space                    */
7367 /*-----------------------------------------------------------------*/
7368 static void genFarPointerGet (operand *left,
7369                               operand *result, iCode *ic)
7370 {
7371     int size, offset ;
7372     sym_link *retype = getSpec(operandType(result));
7373
7374     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7375
7376     aopOp(left,ic,FALSE);
7377
7378     /* if the operand is already in dptr 
7379     then we do nothing else we move the value to dptr */
7380     if (AOP_TYPE(left) != AOP_STR) {
7381         /* if this is remateriazable */
7382         if (AOP_TYPE(left) == AOP_IMMD)
7383             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7384         else { /* we need to get it byte by byte */
7385             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7386             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7387             if (options.model == MODEL_FLAT24)
7388             {
7389                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7390             }
7391         }
7392     }
7393     /* so dptr know contains the address */
7394     freeAsmop(left,NULL,ic,TRUE);
7395     aopOp(result,ic,FALSE);
7396
7397     /* if bit then unpack */
7398     if (IS_BITVAR(retype)) 
7399         genUnpackBits(result,"dptr",FPOINTER);
7400     else {
7401         size = AOP_SIZE(result);
7402         offset = 0 ;
7403
7404         while (size--) {
7405             emitcode("movx","a,@dptr");
7406             aopPut(AOP(result),"a",offset++);
7407             if (size)
7408                 emitcode("inc","dptr");
7409         }
7410     }
7411
7412     freeAsmop(result,NULL,ic,TRUE);
7413 }
7414
7415 /*-----------------------------------------------------------------*/
7416 /* emitcodePointerGet - gget value from code space                  */
7417 /*-----------------------------------------------------------------*/
7418 static void emitcodePointerGet (operand *left,
7419                                 operand *result, iCode *ic)
7420 {
7421     int size, offset ;
7422     sym_link *retype = getSpec(operandType(result));
7423
7424     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7425
7426     aopOp(left,ic,FALSE);
7427
7428     /* if the operand is already in dptr 
7429     then we do nothing else we move the value to dptr */
7430     if (AOP_TYPE(left) != AOP_STR) {
7431         /* if this is remateriazable */
7432         if (AOP_TYPE(left) == AOP_IMMD)
7433             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7434         else { /* we need to get it byte by byte */
7435             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7436             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7437             if (options.model == MODEL_FLAT24)
7438             {
7439                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7440             }
7441         }
7442     }
7443     /* so dptr know contains the address */
7444     freeAsmop(left,NULL,ic,TRUE);
7445     aopOp(result,ic,FALSE);
7446
7447     /* if bit then unpack */
7448     if (IS_BITVAR(retype)) 
7449         genUnpackBits(result,"dptr",CPOINTER);
7450     else {
7451         size = AOP_SIZE(result);
7452         offset = 0 ;
7453
7454         while (size--) {
7455             emitcode("clr","a");
7456             emitcode("movc","a,@a+dptr");
7457             aopPut(AOP(result),"a",offset++);
7458             if (size)
7459                 emitcode("inc","dptr");
7460         }
7461     }
7462
7463     freeAsmop(result,NULL,ic,TRUE);
7464 }
7465
7466 /*-----------------------------------------------------------------*/
7467 /* genGenPointerGet - gget value from generic pointer space        */
7468 /*-----------------------------------------------------------------*/
7469 static void genGenPointerGet (operand *left,
7470                               operand *result, iCode *ic)
7471 {
7472     int size, offset ;
7473     sym_link *retype = getSpec(operandType(result));
7474
7475     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7476     aopOp(left,ic,FALSE);
7477
7478     /* if the operand is already in dptr 
7479     then we do nothing else we move the value to dptr */
7480     if (AOP_TYPE(left) != AOP_STR) {
7481         /* if this is remateriazable */
7482         if (AOP_TYPE(left) == AOP_IMMD) {
7483             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7484             emitcode("mov","b,#%d",pointerCode(retype));
7485         }
7486         else { /* we need to get it byte by byte */
7487           
7488           emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7489           emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7490           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7491           emitcode("movwf","FSR");
7492           /*
7493             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7494             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7495             if (options.model == MODEL_FLAT24)
7496             {
7497                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7498                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7499             }
7500             else
7501             {
7502                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7503             }
7504           */
7505         }
7506     }
7507     /* so dptr know contains the address */
7508     freeAsmop(left,NULL,ic,TRUE);
7509     aopOp(result,ic,FALSE); 
7510
7511     /* if bit then unpack */
7512     if (IS_BITVAR(retype)) 
7513         genUnpackBits(result,"dptr",GPOINTER);
7514     else {
7515         size = AOP_SIZE(result);
7516         offset = 0 ;
7517
7518         while (size--) {
7519           emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7520           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7521           if(size)
7522             emitpcode(POC_INCF,popCopy(&pc_fsr));
7523 /*
7524           emitcode("movf","indf,w");
7525           emitcode("movwf","%s",
7526                    aopGet(AOP(result),offset++,FALSE,FALSE));
7527           if (size)
7528             emitcode("incf","fsr,f");
7529 */
7530         }
7531     }
7532
7533     freeAsmop(result,NULL,ic,TRUE);
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* genPointerGet - generate code for pointer get                   */
7538 /*-----------------------------------------------------------------*/
7539 static void genPointerGet (iCode *ic)
7540 {
7541     operand *left, *result ;
7542     sym_link *type, *etype;
7543     int p_type;
7544
7545     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7546
7547     left = IC_LEFT(ic);
7548     result = IC_RESULT(ic) ;
7549
7550     /* depending on the type of pointer we need to
7551     move it to the correct pointer register */
7552     type = operandType(left);
7553     etype = getSpec(type);
7554     /* if left is of type of pointer then it is simple */
7555     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7556         p_type = DCL_TYPE(type);
7557     else {
7558         /* we have to go by the storage class */
7559         p_type = PTR_TYPE(SPEC_OCLS(etype));
7560
7561 /*      if (SPEC_OCLS(etype)->codesp ) { */
7562 /*          p_type = CPOINTER ;  */
7563 /*      } */
7564 /*      else */
7565 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7566 /*              p_type = FPOINTER ; */
7567 /*          else */
7568 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7569 /*                  p_type = PPOINTER; */
7570 /*              else */
7571 /*                  if (SPEC_OCLS(etype) == idata ) */
7572 /*                      p_type = IPOINTER; */
7573 /*                  else */
7574 /*                      p_type = POINTER ; */
7575     }
7576
7577     /* now that we have the pointer type we assign
7578     the pointer values */
7579     switch (p_type) {
7580
7581     case POINTER:       
7582     case IPOINTER:
7583         genNearPointerGet (left,result,ic);
7584         break;
7585
7586     case PPOINTER:
7587         genPagedPointerGet(left,result,ic);
7588         break;
7589
7590     case FPOINTER:
7591         genFarPointerGet (left,result,ic);
7592         break;
7593
7594     case CPOINTER:
7595         emitcodePointerGet (left,result,ic);
7596         break;
7597
7598     case GPOINTER:
7599         genGenPointerGet (left,result,ic);
7600         break;
7601     }
7602
7603 }
7604
7605 /*-----------------------------------------------------------------*/
7606 /* genPackBits - generates code for packed bit storage             */
7607 /*-----------------------------------------------------------------*/
7608 static void genPackBits (sym_link    *etype ,
7609                          operand *right ,
7610                          char *rname, int p_type)
7611 {
7612     int shCount = 0 ;
7613     int offset = 0  ;
7614     int rLen = 0 ;
7615     int blen, bstr ;   
7616     char *l ;
7617
7618     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7619     blen = SPEC_BLEN(etype);
7620     bstr = SPEC_BSTR(etype);
7621
7622     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7623     MOVA(l);   
7624
7625     /* if the bit lenth is less than or    */
7626     /* it exactly fits a byte then         */
7627     if (SPEC_BLEN(etype) <= 8 )  {
7628         shCount = SPEC_BSTR(etype) ;
7629
7630         /* shift left acc */
7631         AccLsh(shCount);
7632
7633         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7634
7635
7636             switch (p_type) {
7637                 case POINTER:
7638                     emitcode ("mov","b,a");
7639                     emitcode("mov","a,@%s",rname);
7640                     break;
7641
7642                 case FPOINTER:
7643                     emitcode ("mov","b,a");
7644                     emitcode("movx","a,@dptr");
7645                     break;
7646
7647                 case GPOINTER:
7648                     emitcode ("push","b");
7649                     emitcode ("push","acc");
7650                     emitcode ("lcall","__gptrget");
7651                     emitcode ("pop","b");
7652                     break;
7653             }
7654
7655             emitcode ("anl","a,#0x%02x",(unsigned char)
7656                       ((unsigned char)(0xFF << (blen+bstr)) | 
7657                        (unsigned char)(0xFF >> (8-bstr)) ) );
7658             emitcode ("orl","a,b");
7659             if (p_type == GPOINTER)
7660                 emitcode("pop","b");
7661         }
7662     }
7663
7664     switch (p_type) {
7665         case POINTER:
7666             emitcode("mov","@%s,a",rname);
7667             break;
7668
7669         case FPOINTER:
7670             emitcode("movx","@dptr,a");
7671             break;
7672
7673         case GPOINTER:
7674             DEBUGemitcode(";lcall","__gptrput");
7675             break;
7676     }
7677
7678     /* if we r done */
7679     if ( SPEC_BLEN(etype) <= 8 )
7680         return ;
7681
7682     emitcode("inc","%s",rname);
7683     rLen = SPEC_BLEN(etype) ;     
7684
7685     /* now generate for lengths greater than one byte */
7686     while (1) {
7687
7688         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7689
7690         rLen -= 8 ;
7691         if (rLen <= 0 )
7692             break ;
7693
7694         switch (p_type) {
7695             case POINTER:
7696                 if (*l == '@') {
7697                     MOVA(l);
7698                     emitcode("mov","@%s,a",rname);
7699                 } else
7700                     emitcode("mov","@%s,%s",rname,l);
7701                 break;
7702
7703             case FPOINTER:
7704                 MOVA(l);
7705                 emitcode("movx","@dptr,a");
7706                 break;
7707
7708             case GPOINTER:
7709                 MOVA(l);
7710                 DEBUGemitcode(";lcall","__gptrput");
7711                 break;  
7712         }   
7713         emitcode ("inc","%s",rname);
7714     }
7715
7716     MOVA(l);
7717
7718     /* last last was not complete */
7719     if (rLen)   {
7720         /* save the byte & read byte */
7721         switch (p_type) {
7722             case POINTER:
7723                 emitcode ("mov","b,a");
7724                 emitcode("mov","a,@%s",rname);
7725                 break;
7726
7727             case FPOINTER:
7728                 emitcode ("mov","b,a");
7729                 emitcode("movx","a,@dptr");
7730                 break;
7731
7732             case GPOINTER:
7733                 emitcode ("push","b");
7734                 emitcode ("push","acc");
7735                 emitcode ("lcall","__gptrget");
7736                 emitcode ("pop","b");
7737                 break;
7738         }
7739
7740         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7741         emitcode ("orl","a,b");
7742     }
7743
7744     if (p_type == GPOINTER)
7745         emitcode("pop","b");
7746
7747     switch (p_type) {
7748
7749     case POINTER:
7750         emitcode("mov","@%s,a",rname);
7751         break;
7752         
7753     case FPOINTER:
7754         emitcode("movx","@dptr,a");
7755         break;
7756         
7757     case GPOINTER:
7758         DEBUGemitcode(";lcall","__gptrput");
7759         break;                  
7760     }
7761 }
7762 /*-----------------------------------------------------------------*/
7763 /* genDataPointerSet - remat pointer to data space                 */
7764 /*-----------------------------------------------------------------*/
7765 static void genDataPointerSet(operand *right,
7766                               operand *result,
7767                               iCode *ic)
7768 {
7769     int size, offset = 0 ;
7770     char *l, buffer[256];
7771
7772     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7773     aopOp(right,ic,FALSE);
7774     
7775     l = aopGet(AOP(result),0,FALSE,TRUE);
7776     size = AOP_SIZE(right);
7777     // tsd, was l+1 - the underline `_' prefix was being stripped
7778     while (size--) {
7779         if (offset)
7780             sprintf(buffer,"(%s + %d)",l,offset);
7781         else
7782             sprintf(buffer,"%s",l);
7783
7784         if (AOP_TYPE(right) == AOP_LIT) {
7785           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7786           lit = lit >> (8*offset);
7787           if(lit) {
7788             emitcode("movlw","%s",lit);
7789             emitcode("movwf","%s",buffer);
7790           } else 
7791             emitcode("clrf","%s",buffer);
7792         }else {
7793           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7794           emitcode("movwf","%s",buffer);
7795         }
7796
7797         offset++;
7798     }
7799
7800     freeAsmop(right,NULL,ic,TRUE);
7801     freeAsmop(result,NULL,ic,TRUE);
7802 }
7803
7804 /*-----------------------------------------------------------------*/
7805 /* genNearPointerSet - emitcode for near pointer put                */
7806 /*-----------------------------------------------------------------*/
7807 static void genNearPointerSet (operand *right,
7808                                operand *result, 
7809                                iCode *ic)
7810 {
7811     asmop *aop = NULL;
7812     char *l;
7813     sym_link *retype;
7814     sym_link *ptype = operandType(result);
7815
7816     
7817     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7818     retype= getSpec(operandType(right));
7819
7820     aopOp(result,ic,FALSE);
7821     
7822     /* if the result is rematerializable &
7823        in data space & not a bit variable */
7824     if (AOP_TYPE(result) == AOP_IMMD &&
7825         DCL_TYPE(ptype) == POINTER   &&
7826         !IS_BITVAR(retype)) {
7827         genDataPointerSet (right,result,ic);
7828         return;
7829     }
7830
7831     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7832
7833     /* if the value is already in a pointer register
7834     then don't need anything more */
7835     if (!AOP_INPREG(AOP(result))) {
7836         /* otherwise get a free pointer register */
7837         //aop = newAsmop(0);
7838         //preg = getFreePtr(ic,&aop,FALSE);
7839         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7840         //emitcode("mov","%s,%s",
7841         //         preg->name,
7842         //         aopGet(AOP(result),0,FALSE,TRUE));
7843         //rname = preg->name ;
7844         emitcode("movwf","fsr");
7845     }// else
7846     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7847
7848     freeAsmop(result,NULL,ic,TRUE);
7849     aopOp (right,ic,FALSE);
7850     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7851
7852     /* if bitfield then unpack the bits */
7853     if (IS_BITVAR(retype)) {
7854       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7855              "The programmer is obviously confused");
7856       //genPackBits (retype,right,rname,POINTER);
7857       exit(1);
7858     }
7859     else {
7860         /* we have can just get the values */
7861         int size = AOP_SIZE(right);
7862         int offset = 0 ;    
7863
7864     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7865         while (size--) {
7866             l = aopGet(AOP(right),offset,FALSE,TRUE);
7867             if (*l == '@' ) {
7868               //MOVA(l);
7869               //emitcode("mov","@%s,a",rname);
7870               emitcode("movf","indf,w ;1");
7871             } else {
7872
7873               if (AOP_TYPE(right) == AOP_LIT) {
7874                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7875                 if(lit) {
7876                   emitcode("movlw","%s",l);
7877                   emitcode("movwf","indf ;2");
7878                 } else 
7879                   emitcode("clrf","indf");
7880               }else {
7881                 emitcode("movf","%s,w",l);
7882                 emitcode("movwf","indf ;2");
7883               }
7884             //emitcode("mov","@%s,%s",rname,l);
7885             }
7886             if (size)
7887               emitcode("incf","fsr,f ;3");
7888             //emitcode("inc","%s",rname);
7889             offset++;
7890         }
7891     }
7892
7893     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7894     /* now some housekeeping stuff */
7895     if (aop) {
7896         /* we had to allocate for this iCode */
7897         freeAsmop(NULL,aop,ic,TRUE);
7898     } else { 
7899         /* we did not allocate which means left
7900         already in a pointer register, then
7901         if size > 0 && this could be used again
7902         we have to point it back to where it 
7903         belongs */
7904     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7905         if (AOP_SIZE(right) > 1 &&
7906             !OP_SYMBOL(result)->remat &&
7907             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7908               ic->depth )) {
7909             int size = AOP_SIZE(right) - 1;
7910             while (size--)
7911               emitcode("decf","fsr,f");
7912               //emitcode("dec","%s",rname);
7913         }
7914     }
7915
7916     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7917     /* done */
7918     freeAsmop(right,NULL,ic,TRUE);
7919
7920
7921 }
7922
7923 /*-----------------------------------------------------------------*/
7924 /* genPagedPointerSet - emitcode for Paged pointer put             */
7925 /*-----------------------------------------------------------------*/
7926 static void genPagedPointerSet (operand *right,
7927                                operand *result, 
7928                                iCode *ic)
7929 {
7930     asmop *aop = NULL;
7931     regs *preg = NULL ;
7932     char *rname , *l;
7933     sym_link *retype;
7934        
7935     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7936
7937     retype= getSpec(operandType(right));
7938     
7939     aopOp(result,ic,FALSE);
7940     
7941     /* if the value is already in a pointer register
7942        then don't need anything more */
7943     if (!AOP_INPREG(AOP(result))) {
7944         /* otherwise get a free pointer register */
7945         aop = newAsmop(0);
7946         preg = getFreePtr(ic,&aop,FALSE);
7947         emitcode("mov","%s,%s",
7948                 preg->name,
7949                 aopGet(AOP(result),0,FALSE,TRUE));
7950         rname = preg->name ;
7951     } else
7952         rname = aopGet(AOP(result),0,FALSE,FALSE);
7953     
7954     freeAsmop(result,NULL,ic,TRUE);
7955     aopOp (right,ic,FALSE);
7956
7957     /* if bitfield then unpack the bits */
7958     if (IS_BITVAR(retype)) 
7959         genPackBits (retype,right,rname,PPOINTER);
7960     else {
7961         /* we have can just get the values */
7962         int size = AOP_SIZE(right);
7963         int offset = 0 ;        
7964         
7965         while (size--) {
7966             l = aopGet(AOP(right),offset,FALSE,TRUE);
7967             
7968             MOVA(l);
7969             emitcode("movx","@%s,a",rname);
7970
7971             if (size)
7972                 emitcode("inc","%s",rname);
7973
7974             offset++;
7975         }
7976     }
7977     
7978     /* now some housekeeping stuff */
7979     if (aop) {
7980         /* we had to allocate for this iCode */
7981         freeAsmop(NULL,aop,ic,TRUE);
7982     } else { 
7983         /* we did not allocate which means left
7984            already in a pointer register, then
7985            if size > 0 && this could be used again
7986            we have to point it back to where it 
7987            belongs */
7988         if (AOP_SIZE(right) > 1 &&
7989             !OP_SYMBOL(result)->remat &&
7990             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7991               ic->depth )) {
7992             int size = AOP_SIZE(right) - 1;
7993             while (size--)
7994                 emitcode("dec","%s",rname);
7995         }
7996     }
7997
7998     /* done */
7999     freeAsmop(right,NULL,ic,TRUE);
8000     
8001         
8002 }
8003
8004 /*-----------------------------------------------------------------*/
8005 /* genFarPointerSet - set value from far space                     */
8006 /*-----------------------------------------------------------------*/
8007 static void genFarPointerSet (operand *right,
8008                               operand *result, iCode *ic)
8009 {
8010     int size, offset ;
8011     sym_link *retype = getSpec(operandType(right));
8012
8013     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8014     aopOp(result,ic,FALSE);
8015
8016     /* if the operand is already in dptr 
8017     then we do nothing else we move the value to dptr */
8018     if (AOP_TYPE(result) != AOP_STR) {
8019         /* if this is remateriazable */
8020         if (AOP_TYPE(result) == AOP_IMMD)
8021             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8022         else { /* we need to get it byte by byte */
8023             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8024             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8025             if (options.model == MODEL_FLAT24)
8026             {
8027                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8028             }
8029         }
8030     }
8031     /* so dptr know contains the address */
8032     freeAsmop(result,NULL,ic,TRUE);
8033     aopOp(right,ic,FALSE);
8034
8035     /* if bit then unpack */
8036     if (IS_BITVAR(retype)) 
8037         genPackBits(retype,right,"dptr",FPOINTER);
8038     else {
8039         size = AOP_SIZE(right);
8040         offset = 0 ;
8041
8042         while (size--) {
8043             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8044             MOVA(l);
8045             emitcode("movx","@dptr,a");
8046             if (size)
8047                 emitcode("inc","dptr");
8048         }
8049     }
8050
8051     freeAsmop(right,NULL,ic,TRUE);
8052 }
8053
8054 /*-----------------------------------------------------------------*/
8055 /* genGenPointerSet - set value from generic pointer space         */
8056 /*-----------------------------------------------------------------*/
8057 static void genGenPointerSet (operand *right,
8058                               operand *result, iCode *ic)
8059 {
8060     int size, offset ;
8061     sym_link *retype = getSpec(operandType(right));
8062
8063     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8064
8065     aopOp(result,ic,FALSE);
8066
8067     /* if the operand is already in dptr 
8068     then we do nothing else we move the value to dptr */
8069     if (AOP_TYPE(result) != AOP_STR) {
8070         /* if this is remateriazable */
8071         if (AOP_TYPE(result) == AOP_IMMD) {
8072             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8073             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8074         }
8075         else { /* we need to get it byte by byte */
8076           char *l = aopGet(AOP(result),0,FALSE,FALSE);
8077
8078           if(strcmp("FSR",l))
8079             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8080           emitpcode(POC_MOVWF,popCopy(&pc_indf));
8081
8082           if(strcmp("FSR",l))
8083             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8084
8085           emitcode("movwf","INDF");
8086         }
8087     }
8088     /* so dptr know contains the address */
8089     freeAsmop(result,NULL,ic,TRUE);
8090     aopOp(right,ic,FALSE);
8091
8092     /* if bit then unpack */
8093     if (IS_BITVAR(retype)) 
8094         genPackBits(retype,right,"dptr",GPOINTER);
8095     else {
8096         size = AOP_SIZE(right);
8097         offset = 0 ;
8098
8099         while (--size) {
8100             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8101             if(size)
8102               emitcode("incf","fsr,f");
8103             emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8104             emitcode("movwf","indf");
8105             //MOVA(l);
8106             //DEBUGemitcode(";lcall","__gptrput");
8107             //if (size)
8108             //    emitcode("inc","dptr");
8109         }
8110     }
8111
8112     freeAsmop(right,NULL,ic,TRUE);
8113 }
8114
8115 /*-----------------------------------------------------------------*/
8116 /* genPointerSet - stores the value into a pointer location        */
8117 /*-----------------------------------------------------------------*/
8118 static void genPointerSet (iCode *ic)
8119 {    
8120     operand *right, *result ;
8121     sym_link *type, *etype;
8122     int p_type;
8123
8124     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8125
8126     right = IC_RIGHT(ic);
8127     result = IC_RESULT(ic) ;
8128
8129     /* depending on the type of pointer we need to
8130     move it to the correct pointer register */
8131     type = operandType(result);
8132     etype = getSpec(type);
8133     /* if left is of type of pointer then it is simple */
8134     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8135         p_type = DCL_TYPE(type);
8136     }
8137     else {
8138         /* we have to go by the storage class */
8139         p_type = PTR_TYPE(SPEC_OCLS(etype));
8140
8141 /*      if (SPEC_OCLS(etype)->codesp ) { */
8142 /*          p_type = CPOINTER ;  */
8143 /*      } */
8144 /*      else */
8145 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8146 /*              p_type = FPOINTER ; */
8147 /*          else */
8148 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8149 /*                  p_type = PPOINTER ; */
8150 /*              else */
8151 /*                  if (SPEC_OCLS(etype) == idata ) */
8152 /*                      p_type = IPOINTER ; */
8153 /*                  else */
8154 /*                      p_type = POINTER ; */
8155     }
8156
8157     /* now that we have the pointer type we assign
8158     the pointer values */
8159     switch (p_type) {
8160
8161     case POINTER:
8162     case IPOINTER:
8163         genNearPointerSet (right,result,ic);
8164         break;
8165
8166     case PPOINTER:
8167         genPagedPointerSet (right,result,ic);
8168         break;
8169
8170     case FPOINTER:
8171         genFarPointerSet (right,result,ic);
8172         break;
8173
8174     case GPOINTER:
8175         genGenPointerSet (right,result,ic);
8176         break;
8177     }
8178
8179 }
8180
8181 /*-----------------------------------------------------------------*/
8182 /* genIfx - generate code for Ifx statement                        */
8183 /*-----------------------------------------------------------------*/
8184 static void genIfx (iCode *ic, iCode *popIc)
8185 {
8186     operand *cond = IC_COND(ic);
8187     int isbit =0;
8188
8189     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8190     aopOp(cond,ic,FALSE);
8191
8192     /* get the value into acc */
8193     if (AOP_TYPE(cond) != AOP_CRY)
8194         toBoolean(cond);
8195     else
8196         isbit = 1;
8197     /* the result is now in the accumulator */
8198     freeAsmop(cond,NULL,ic,TRUE);
8199
8200     /* if there was something to be popped then do it */
8201     if (popIc)
8202         genIpop(popIc);
8203
8204     /* if the condition is  a bit variable */
8205     if (isbit && IS_ITEMP(cond) && 
8206         SPIL_LOC(cond)) {
8207       genIfxJump(ic,SPIL_LOC(cond)->rname);
8208       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8209     }
8210     else {
8211       /*
8212         if (isbit && !IS_ITEMP(cond))
8213           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8214         else
8215           DEBUGemitcode ("; isbit","a");
8216       */
8217
8218         if (isbit && !IS_ITEMP(cond))
8219             genIfxJump(ic,OP_SYMBOL(cond)->rname);
8220         else
8221             genIfxJump(ic,"a");
8222     }
8223     ic->generated = 1;
8224 }
8225
8226 /*-----------------------------------------------------------------*/
8227 /* genAddrOf - generates code for address of                       */
8228 /*-----------------------------------------------------------------*/
8229 static void genAddrOf (iCode *ic)
8230 {
8231     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8232     int size, offset ;
8233
8234     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8235
8236     aopOp(IC_RESULT(ic),ic,FALSE);
8237
8238     /* if the operand is on the stack then we 
8239     need to get the stack offset of this
8240     variable */
8241     if (sym->onStack) {
8242         /* if it has an offset then we need to compute
8243         it */
8244         if (sym->stack) {
8245             emitcode("mov","a,_bp");
8246             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8247             aopPut(AOP(IC_RESULT(ic)),"a",0);       
8248         } else {
8249             /* we can just move _bp */
8250             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8251         }
8252         /* fill the result with zero */
8253         size = AOP_SIZE(IC_RESULT(ic)) - 1;
8254         
8255         
8256         if (options.stack10bit && size < (FPTRSIZE - 1))
8257         {
8258             fprintf(stderr, 
8259                     "*** warning: pointer to stack var truncated.\n");
8260         }
8261         
8262         offset = 1;
8263         while (size--)
8264         {
8265             /* Yuck! */
8266             if (options.stack10bit && offset == 2)
8267             {
8268                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8269             }
8270             else
8271             {
8272                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8273             }
8274         }
8275
8276         goto release;
8277     }
8278
8279     /* object not on stack then we need the name */
8280     size = AOP_SIZE(IC_RESULT(ic));
8281     offset = 0;
8282
8283     while (size--) {
8284         char s[SDCC_NAME_MAX];
8285         if (offset) 
8286             sprintf(s,"#(%s >> %d)",
8287                     sym->rname,
8288                     offset*8);
8289         else
8290             sprintf(s,"#%s",sym->rname);
8291         aopPut(AOP(IC_RESULT(ic)),s,offset++);
8292     }
8293
8294 release:
8295     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8296
8297 }
8298
8299 #if 0
8300 /*-----------------------------------------------------------------*/
8301 /* genFarFarAssign - assignment when both are in far space         */
8302 /*-----------------------------------------------------------------*/
8303 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8304 {
8305     int size = AOP_SIZE(right);
8306     int offset = 0;
8307     char *l ;
8308     /* first push the right side on to the stack */
8309     while (size--) {
8310         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8311         MOVA(l);
8312         emitcode ("push","acc");
8313     }
8314     
8315     freeAsmop(right,NULL,ic,FALSE);
8316     /* now assign DPTR to result */
8317     aopOp(result,ic,FALSE);
8318     size = AOP_SIZE(result);
8319     while (size--) {
8320         emitcode ("pop","acc");
8321         aopPut(AOP(result),"a",--offset);
8322     }
8323     freeAsmop(result,NULL,ic,FALSE);
8324         
8325 }
8326 #endif
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genAssign - generate code for assignment                        */
8330 /*-----------------------------------------------------------------*/
8331 static void genAssign (iCode *ic)
8332 {
8333     operand *result, *right;
8334     int size, offset ;
8335         unsigned long lit = 0L;
8336
8337     result = IC_RESULT(ic);
8338     right  = IC_RIGHT(ic) ;
8339
8340     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8341
8342     /* if they are the same */
8343     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8344         return ;
8345
8346     aopOp(right,ic,FALSE);
8347     aopOp(result,ic,TRUE);
8348
8349     /* if they are the same registers */
8350     if (sameRegs(AOP(right),AOP(result)))
8351         goto release;
8352
8353     /* if the result is a bit */
8354     if (AOP_TYPE(result) == AOP_CRY) {
8355
8356         /* if the right size is a literal then
8357         we know what the value is */
8358         if (AOP_TYPE(right) == AOP_LIT) {
8359           
8360           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8361                       popGet(AOP(result),0,FALSE,FALSE));
8362
8363             if (((int) operandLitValue(right))) 
8364               emitcode("bsf","(%s >> 3),(%s & 7)",
8365                        AOP(result)->aopu.aop_dir,
8366                        AOP(result)->aopu.aop_dir);
8367             else
8368               emitcode("bcf","(%s >> 3),(%s & 7)",
8369                  AOP(result)->aopu.aop_dir,
8370                  AOP(result)->aopu.aop_dir);
8371             goto release;
8372         }
8373
8374         /* the right is also a bit variable */
8375         if (AOP_TYPE(right) == AOP_CRY) {
8376           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8377           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8378           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8379
8380           emitcode("bcf","(%s >> 3),(%s & 7)",
8381                    AOP(result)->aopu.aop_dir,
8382                    AOP(result)->aopu.aop_dir);
8383           emitcode("btfsc","(%s >> 3),(%s & 7)",
8384                    AOP(right)->aopu.aop_dir,
8385                    AOP(right)->aopu.aop_dir);
8386           emitcode("bsf","(%s >> 3),(%s & 7)",
8387                    AOP(result)->aopu.aop_dir,
8388                    AOP(result)->aopu.aop_dir);
8389           goto release ;
8390         }
8391
8392         /* we need to or */
8393         toBoolean(right);
8394         aopPut(AOP(result),"a",0);
8395         goto release ;
8396     }
8397
8398     /* bit variables done */
8399     /* general case */
8400     size = AOP_SIZE(result);
8401     offset = 0 ;
8402     if(AOP_TYPE(right) == AOP_LIT)
8403         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8404     if((AOP_TYPE(result) != AOP_REG) &&
8405        (AOP_TYPE(right) == AOP_LIT) &&
8406        !IS_FLOAT(operandType(right)) &&
8407        (lit < 256L)){
8408
8409         while (size--) {
8410           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8411             //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8412               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8413             }else {
8414               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8415               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8416               //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8417               //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8418             }
8419         }
8420     } else {
8421         while (size--) {
8422           if(AOP_TYPE(right) == AOP_LIT)
8423             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8424           //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8425           else
8426             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8427           //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8428             
8429           emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8430           //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8431           offset++;
8432         }
8433     }
8434     
8435 release:
8436     freeAsmop (right,NULL,ic,FALSE);
8437     freeAsmop (result,NULL,ic,TRUE);
8438 }   
8439
8440 /*-----------------------------------------------------------------*/
8441 /* genJumpTab - genrates code for jump table                       */
8442 /*-----------------------------------------------------------------*/
8443 static void genJumpTab (iCode *ic)
8444 {
8445     symbol *jtab;
8446     char *l;
8447
8448     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8449
8450     aopOp(IC_JTCOND(ic),ic,FALSE);
8451     /* get the condition into accumulator */
8452     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8453     MOVA(l);
8454     /* multiply by three */
8455     emitcode("add","a,acc");
8456     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8457     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8458
8459     jtab = newiTempLabel(NULL);
8460     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8461     emitcode("jmp","@a+dptr");
8462     emitcode("","%05d_DS_:",jtab->key+100);
8463     /* now generate the jump labels */
8464     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8465          jtab = setNextItem(IC_JTLABELS(ic)))
8466         emitcode("ljmp","%05d_DS_",jtab->key+100);
8467
8468 }
8469
8470 /*-----------------------------------------------------------------*/
8471 /* genMixedOperation - gen code for operators between mixed types  */
8472 /*-----------------------------------------------------------------*/
8473 /*
8474   TSD - Written for the PIC port - but this unfortunately is buggy.
8475   This routine is good in that it is able to efficiently promote 
8476   types to different (larger) sizes. Unfortunately, the temporary
8477   variables that are optimized out by this routine are sometimes
8478   used in other places. So until I know how to really parse the 
8479   iCode tree, I'm going to not be using this routine :(.
8480 */
8481 static int genMixedOperation (iCode *ic)
8482 {
8483 #if 0
8484   operand *result = IC_RESULT(ic);
8485   sym_link *ctype = operandType(IC_LEFT(ic));
8486   operand *right = IC_RIGHT(ic);
8487   int ret = 0;
8488   int big,small;
8489   int offset;
8490
8491   iCode *nextic;
8492   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8493
8494   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8495
8496   nextic = ic->next;
8497   if(!nextic)
8498     return 0;
8499
8500   nextright = IC_RIGHT(nextic);
8501   nextleft  = IC_LEFT(nextic);
8502   nextresult = IC_RESULT(nextic);
8503
8504   aopOp(right,ic,FALSE);
8505   aopOp(result,ic,FALSE);
8506   aopOp(nextright,  nextic, FALSE);
8507   aopOp(nextleft,   nextic, FALSE);
8508   aopOp(nextresult, nextic, FALSE);
8509
8510   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8511
8512     operand *t = right;
8513     right = nextright;
8514     nextright = t; 
8515
8516     emitcode(";remove right +","");
8517
8518   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8519 /*
8520     operand *t = right;
8521     right = nextleft;
8522     nextleft = t; 
8523 */
8524     emitcode(";remove left +","");
8525   } else
8526     return 0;
8527
8528   big = AOP_SIZE(nextleft);
8529   small = AOP_SIZE(nextright);
8530
8531   switch(nextic->op) {
8532
8533   case '+':
8534     emitcode(";optimize a +","");
8535     /* if unsigned or not an integral type */
8536     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8537       emitcode(";add a bit to something","");
8538     } else {
8539
8540       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8541
8542       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8543         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8544         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8545       } else
8546         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8547
8548       offset = 0;
8549       while(--big) {
8550
8551         offset++;
8552
8553         if(--small) {
8554           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8555             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8556             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8557           }
8558
8559           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8560           emitSKPNC;
8561           emitcode("btfsc","(%s >> 3), (%s & 7)",
8562                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8563                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8564           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8565           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8566
8567         } else {
8568           emitcode("rlf","known_zero,w");
8569
8570           /*
8571             if right is signed
8572               btfsc  right,7
8573                addlw ff
8574           */
8575           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8576             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8577             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8578           } else {
8579             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8580           }
8581         }
8582       }
8583       ret = 1;
8584     }
8585   }
8586   ret = 1;
8587
8588 release:
8589   freeAsmop(right,NULL,ic,TRUE);
8590   freeAsmop(result,NULL,ic,TRUE);
8591   freeAsmop(nextright,NULL,ic,TRUE);
8592   freeAsmop(nextleft,NULL,ic,TRUE);
8593   if(ret)
8594     nextic->generated = 1;
8595
8596   return ret;
8597 #else
8598   return 0;
8599 #endif
8600 }
8601 /*-----------------------------------------------------------------*/
8602 /* genCast - gen code for casting                                  */
8603 /*-----------------------------------------------------------------*/
8604 static void genCast (iCode *ic)
8605 {
8606     operand *result = IC_RESULT(ic);
8607     sym_link *ctype = operandType(IC_LEFT(ic));
8608     operand *right = IC_RIGHT(ic);
8609     int size, offset ;
8610
8611     DEBUGemitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8612     /* if they are equivalent then do nothing */
8613     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8614         return ;
8615
8616     aopOp(right,ic,FALSE) ;
8617     aopOp(result,ic,FALSE);
8618
8619     /* if the result is a bit */
8620     if (AOP_TYPE(result) == AOP_CRY) {
8621         /* if the right size is a literal then
8622         we know what the value is */
8623         if (AOP_TYPE(right) == AOP_LIT) {
8624
8625           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8626                       popGet(AOP(result),0,FALSE,FALSE));
8627
8628             if (((int) operandLitValue(right))) 
8629               emitcode("bsf","(%s >> 3), (%s & 7)",
8630                        AOP(result)->aopu.aop_dir,
8631                        AOP(result)->aopu.aop_dir);
8632             else
8633               emitcode("bcf","(%s >> 3), (%s & 7)",
8634                        AOP(result)->aopu.aop_dir,
8635                        AOP(result)->aopu.aop_dir);
8636
8637             goto release;
8638         }
8639
8640         /* the right is also a bit variable */
8641         if (AOP_TYPE(right) == AOP_CRY) {
8642
8643           emitCLRC;
8644           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8645
8646           emitcode("clrc","");
8647           emitcode("btfsc","(%s >> 3), (%s & 7)",
8648                    AOP(right)->aopu.aop_dir,
8649                    AOP(right)->aopu.aop_dir);
8650             aopPut(AOP(result),"c",0);
8651             goto release ;
8652         }
8653
8654         /* we need to or */
8655         toBoolean(right);
8656         aopPut(AOP(result),"a",0);
8657         goto release ;
8658     }
8659
8660     /* if they are the same size : or less */
8661     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8662
8663         /* if they are in the same place */
8664         if (sameRegs(AOP(right),AOP(result)))
8665             goto release;
8666
8667         /* if they in different places then copy */
8668         size = AOP_SIZE(result);
8669         offset = 0 ;
8670         while (size--) {
8671             aopPut(AOP(result),
8672                    aopGet(AOP(right),offset,FALSE,FALSE),
8673                    offset);
8674             offset++;
8675         }
8676         goto release;
8677     }
8678
8679
8680     /* if the result is of type pointer */
8681     if (IS_PTR(ctype)) {
8682
8683         int p_type;
8684         sym_link *type = operandType(right);
8685         sym_link *etype = getSpec(type);
8686
8687         /* pointer to generic pointer */
8688         if (IS_GENPTR(ctype)) {
8689             char *l = zero;
8690             
8691             if (IS_PTR(type)) 
8692                 p_type = DCL_TYPE(type);
8693             else {
8694                 /* we have to go by the storage class */
8695                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8696
8697 /*              if (SPEC_OCLS(etype)->codesp )  */
8698 /*                  p_type = CPOINTER ;  */
8699 /*              else */
8700 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8701 /*                      p_type = FPOINTER ; */
8702 /*                  else */
8703 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8704 /*                          p_type = PPOINTER; */
8705 /*                      else */
8706 /*                          if (SPEC_OCLS(etype) == idata ) */
8707 /*                              p_type = IPOINTER ; */
8708 /*                          else */
8709 /*                              p_type = POINTER ; */
8710             }
8711                 
8712             /* the first two bytes are known */
8713             size = GPTRSIZE - 1; 
8714             offset = 0 ;
8715             while (size--) {
8716                 aopPut(AOP(result),
8717                        aopGet(AOP(right),offset,FALSE,FALSE),
8718                        offset);
8719                 offset++;
8720             }
8721             /* the last byte depending on type */
8722             switch (p_type) {
8723             case IPOINTER:
8724             case POINTER:
8725                 l = zero;
8726                 break;
8727             case FPOINTER:
8728                 l = one;
8729                 break;
8730             case CPOINTER:
8731                 l = "#0x02";
8732                 break;                          
8733             case PPOINTER:
8734                 l = "#0x03";
8735                 break;
8736                 
8737             default:
8738                 /* this should never happen */
8739                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8740                        "got unknown pointer type");
8741                 exit(1);
8742             }
8743             aopPut(AOP(result),l, GPTRSIZE - 1);            
8744             goto release ;
8745         }
8746         
8747         /* just copy the pointers */
8748         size = AOP_SIZE(result);
8749         offset = 0 ;
8750         while (size--) {
8751             aopPut(AOP(result),
8752                    aopGet(AOP(right),offset,FALSE,FALSE),
8753                    offset);
8754             offset++;
8755         }
8756         goto release ;
8757     }
8758     
8759
8760     if (AOP_TYPE(right) == AOP_CRY) {
8761       int offset = 1;
8762       size = AOP_SIZE(right);
8763
8764       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8765       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8766       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8767
8768       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8769       emitcode("btfsc","(%s >> 3), (%s & 7)",
8770                AOP(right)->aopu.aop_dir,
8771                AOP(right)->aopu.aop_dir);
8772       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8773       while (size--) {
8774         emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8775         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8776       }
8777       goto release;
8778     }
8779
8780     /* so we now know that the size of destination is greater
8781     than the size of the source.
8782     Now, if the next iCode is an operator then we might be
8783     able to optimize the operation without performing a cast.
8784     */
8785     if(genMixedOperation(ic))
8786       goto release;
8787
8788     
8789     /* we move to result for the size of source */
8790     size = AOP_SIZE(right);
8791     offset = 0 ;
8792     while (size--) {
8793       emitcode(";","%d",__LINE__);
8794         aopPut(AOP(result),
8795                aopGet(AOP(right),offset,FALSE,FALSE),
8796                offset);
8797         offset++;
8798     }
8799
8800     /* now depending on the sign of the destination */
8801     size = AOP_SIZE(result) - AOP_SIZE(right);
8802     /* if unsigned or not an integral type */
8803     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8804       while (size--) {
8805           emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8806           emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8807       }
8808     } else {
8809       /* we need to extend the sign :{ */
8810       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8811       //MOVA(l);
8812
8813       emitpcode(POC_CLRW,    NULL);
8814       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8815       emitpcode(POC_MOVLW,   popGetLit(0xff));
8816
8817         emitcode("clrw","");
8818         emitcode("btfsc","(%s >> 3), (%s & 7)",
8819                  AOP(right)->aopu.aop_dir,
8820                  AOP(right)->aopu.aop_dir);
8821         emitcode("movlw","0xff");
8822         while (size--) {
8823           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++,FALSE,FALSE));
8824           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8825           // aopPut(AOP(result),"a",offset++);
8826         }
8827
8828     }
8829
8830     /* we are done hurray !!!! */
8831
8832 release:
8833     freeAsmop(right,NULL,ic,TRUE);
8834     freeAsmop(result,NULL,ic,TRUE);
8835
8836 }
8837
8838 /*-----------------------------------------------------------------*/
8839 /* genDjnz - generate decrement & jump if not zero instrucion      */
8840 /*-----------------------------------------------------------------*/
8841 static int genDjnz (iCode *ic, iCode *ifx)
8842 {
8843     symbol *lbl, *lbl1;
8844     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8845
8846     if (!ifx)
8847         return 0;
8848     
8849     /* if the if condition has a false label
8850        then we cannot save */
8851     if (IC_FALSE(ifx))
8852         return 0;
8853
8854     /* if the minus is not of the form 
8855        a = a - 1 */
8856     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8857         !IS_OP_LITERAL(IC_RIGHT(ic)))
8858         return 0;
8859
8860     if (operandLitValue(IC_RIGHT(ic)) != 1)
8861         return 0;
8862
8863     /* if the size of this greater than one then no
8864        saving */
8865     if (getSize(operandType(IC_RESULT(ic))) > 1)
8866         return 0;
8867
8868     /* otherwise we can save BIG */
8869     lbl = newiTempLabel(NULL);
8870     lbl1= newiTempLabel(NULL);
8871
8872     aopOp(IC_RESULT(ic),ic,FALSE);
8873     
8874     if (IS_AOP_PREG(IC_RESULT(ic))) {
8875         emitcode("dec","%s",
8876                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8877         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8878         emitcode("jnz","%05d_DS_",lbl->key+100);
8879     } else {    
8880
8881
8882       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8883       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8884
8885       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8886       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8887
8888     }
8889 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8890 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
8891 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8892 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
8893
8894     
8895     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8896     ifx->generated = 1;
8897     return 1;
8898 }
8899
8900 /*-----------------------------------------------------------------*/
8901 /* genReceive - generate code for a receive iCode                  */
8902 /*-----------------------------------------------------------------*/
8903 static void genReceive (iCode *ic)
8904 {    
8905     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8906
8907     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8908         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8909           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8910
8911         int size = getSize(operandType(IC_RESULT(ic)));
8912         int offset =  fReturnSizePic - size;
8913         while (size--) {
8914             emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8915                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
8916             offset++;
8917         }
8918         aopOp(IC_RESULT(ic),ic,FALSE);  
8919         size = AOP_SIZE(IC_RESULT(ic));
8920         offset = 0;
8921         while (size--) {
8922             emitcode ("pop","acc");
8923             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8924         }
8925         
8926     } else {
8927         _G.accInUse++;
8928         aopOp(IC_RESULT(ic),ic,FALSE);  
8929         _G.accInUse--;
8930         assignResultValue(IC_RESULT(ic));       
8931     }
8932
8933     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8934 }
8935
8936 /*-----------------------------------------------------------------*/
8937 /* genpic14Code - generate code for pic14 based controllers        */
8938 /*-----------------------------------------------------------------*/
8939 /*
8940  * At this point, ralloc.c has gone through the iCode and attempted
8941  * to optimize in a way suitable for a PIC. Now we've got to generate
8942  * PIC instructions that correspond to the iCode.
8943  *
8944  * Once the instructions are generated, we'll pass through both the
8945  * peep hole optimizer and the pCode optimizer.
8946  *-----------------------------------------------------------------*/
8947
8948 void genpic14Code (iCode *lic)
8949 {
8950     iCode *ic;
8951     int cln = 0;
8952
8953     lineHead = lineCurr = NULL;
8954
8955     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8956     addpBlock(pb);
8957
8958     /* if debug information required */
8959 /*     if (options.debug && currFunc) { */
8960     if (currFunc) {
8961         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8962         _G.debugLine = 1;
8963         if (IS_STATIC(currFunc->etype)) {
8964             emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8965             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8966         } else {
8967             emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8968             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8969         }
8970         _G.debugLine = 0;
8971     }
8972
8973
8974     for (ic = lic ; ic ; ic = ic->next ) {
8975
8976       DEBUGemitcode(";ic","");
8977         if ( cln != ic->lineno ) {
8978             if ( options.debug ) {
8979                 _G.debugLine = 1;
8980                 emitcode("",";C$%s$%d$%d$%d ==.",
8981                          FileBaseName(ic->filename),ic->lineno,
8982                          ic->level,ic->block);
8983                 _G.debugLine = 0;
8984             }
8985             emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8986             cln = ic->lineno ;
8987         }
8988         /* if the result is marked as
8989            spilt and rematerializable or code for
8990            this has already been generated then
8991            do nothing */
8992         if (resultRemat(ic) || ic->generated ) 
8993             continue ;
8994         
8995         /* depending on the operation */
8996         switch (ic->op) {
8997         case '!' :
8998             genNot(ic);
8999             break;
9000             
9001         case '~' :
9002             genCpl(ic);
9003             break;
9004             
9005         case UNARYMINUS:
9006             genUminus (ic);
9007             break;
9008             
9009         case IPUSH:
9010             genIpush (ic);
9011             break;
9012             
9013         case IPOP:
9014             /* IPOP happens only when trying to restore a 
9015                spilt live range, if there is an ifx statement
9016                following this pop then the if statement might
9017                be using some of the registers being popped which
9018                would destory the contents of the register so
9019                we need to check for this condition and handle it */
9020             if (ic->next            && 
9021                 ic->next->op == IFX &&
9022                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9023                 genIfx (ic->next,ic);
9024             else
9025                 genIpop (ic);
9026             break; 
9027             
9028         case CALL:
9029             genCall (ic);
9030             break;
9031             
9032         case PCALL:
9033             genPcall (ic);
9034             break;
9035             
9036         case FUNCTION:
9037             genFunction (ic);
9038             break;
9039             
9040         case ENDFUNCTION:
9041             genEndFunction (ic);
9042             break;
9043             
9044         case RETURN:
9045             genRet (ic);
9046             break;
9047             
9048         case LABEL:
9049             genLabel (ic);
9050             break;
9051             
9052         case GOTO:
9053             genGoto (ic);
9054             break;
9055             
9056         case '+' :
9057             genPlus (ic) ;
9058             break;
9059             
9060         case '-' :
9061             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9062                 genMinus (ic);
9063             break;
9064             
9065         case '*' :
9066             genMult (ic);
9067             break;
9068             
9069         case '/' :
9070             genDiv (ic) ;
9071             break;
9072             
9073         case '%' :
9074             genMod (ic);
9075             break;
9076             
9077         case '>' :
9078             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9079             break;
9080             
9081         case '<' :
9082             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9083             break;
9084             
9085         case LE_OP:
9086         case GE_OP:
9087         case NE_OP:
9088             
9089             /* note these two are xlated by algebraic equivalence
9090                during parsing SDCC.y */
9091             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9092                    "got '>=' or '<=' shouldn't have come here");
9093             break;      
9094             
9095         case EQ_OP:
9096             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9097             break;          
9098             
9099         case AND_OP:
9100             genAndOp (ic);
9101             break;
9102             
9103         case OR_OP:
9104             genOrOp (ic);
9105             break;
9106             
9107         case '^' :
9108             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9109             break;
9110             
9111         case '|' :
9112                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9113             break;
9114             
9115         case BITWISEAND:
9116             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9117             break;
9118             
9119         case INLINEASM:
9120             genInline (ic);
9121             break;
9122             
9123         case RRC:
9124             genRRC (ic);
9125             break;
9126             
9127         case RLC:
9128             genRLC (ic);
9129             break;
9130             
9131         case GETHBIT:
9132             genGetHbit (ic);
9133             break;
9134             
9135         case LEFT_OP:
9136             genLeftShift (ic);
9137             break;
9138             
9139         case RIGHT_OP:
9140             genRightShift (ic);
9141             break;
9142             
9143         case GET_VALUE_AT_ADDRESS:
9144             genPointerGet(ic);
9145             break;
9146             
9147         case '=' :
9148             if (POINTER_SET(ic))
9149                 genPointerSet(ic);
9150             else
9151                 genAssign(ic);
9152             break;
9153             
9154         case IFX:
9155             genIfx (ic,NULL);
9156             break;
9157             
9158         case ADDRESS_OF:
9159             genAddrOf (ic);
9160             break;
9161             
9162         case JUMPTABLE:
9163             genJumpTab (ic);
9164             break;
9165             
9166         case CAST:
9167             genCast (ic);
9168             break;
9169             
9170         case RECEIVE:
9171             genReceive(ic);
9172             break;
9173             
9174         case SEND:
9175             addSet(&_G.sendSet,ic);
9176             break;
9177
9178         default :
9179             ic = ic;
9180             /*      piCode(ic,stdout); */
9181             
9182         }
9183     }
9184     
9185
9186     /* now we are ready to call the 
9187        peep hole optimizer */
9188     if (!options.nopeep) {
9189       printf("peep hole optimizing\n");
9190         peepHole (&lineHead);
9191     }
9192     /* now do the actual printing */
9193     printLine (lineHead,codeOutFile);
9194
9195     printf("printing pBlock\n\n");
9196     printpBlock(stdout,pb);
9197
9198     return;
9199 }