MS VC6 Port
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37
38 #if defined(_MSC_VER)
39 #define __FUNCTION__            __FILE__
40 #endif
41
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54
55 #include "common.h"
56 #include "SDCCpeeph.h"
57 #include "ralloc.h"
58 #include "gen.h"
59
60 //char *aopLiteral (value *val, int offset);
61 char *pic14aopLiteral (value *val, int offset);
62
63 /* this is the down and dirty file with all kinds of 
64    kludgy & hacky stuff. This is what it is all about
65    CODE GENERATION for a specific MCU . some of the
66    routines may be reusable, will have to see */
67
68 static char *zero = "#0x00";
69 static char *one  = "#0x01";
70 static char *spname = "sp";
71
72 char *fReturnpic14[] = {"fsr","dph","b","a" };
73 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
74 static unsigned fReturnSize = 4; /* shared with ralloc.c */
75 static char **fReturn = fReturnpic14;
76
77 static char *accUse[] = {"a","b"};
78
79 //static short rbank = -1;
80
81 static struct {
82     short r0Pushed;
83     short r1Pushed;
84     short accInUse;
85     short inLine;
86     short debugLine;
87     short nRegsSaved;
88     set *sendSet;
89 } _G;
90
91 extern int pic14_ptrRegReq ;
92 extern int pic14_nRegs;
93 extern FILE *codeOutFile;
94 static void saverbank (int, iCode *,bool);
95 #define RESULTONSTACK(x) \
96                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
97                          IC_RESULT(x)->aop->type == AOP_STK )
98
99 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
100 #define CLRC    emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
101
102 #define BIT_NUMBER(x) (x & 7)
103 #define BIT_REGISTER(x) (x>>3)
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
112
113 #define LSB     0
114 #define MSB16   1
115 #define MSB24   2
116 #define MSB32   3
117
118
119 #define FUNCTION_LABEL_INC  20
120 static int labelOffset=0;
121 static int debug_verbose=1;
122
123
124 /*-----------------------------------------------------------------*/
125 /* Macros for emitting instructions                                */
126 /*-----------------------------------------------------------------*/
127 #define emitSKPC    emitcode("btfss","status,c")
128 #define emitSKPNC   emitcode("btfsc","status,c")
129 #define emitSKPZ    emitcode("btfss","status,z")
130 #define emitSKPNZ   emitcode("btfsc","status,z")
131
132 /*-----------------------------------------------------------------*/
133 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
134 /*                 exponent of 2 is returned, otherwise -1 is      */
135 /*                 returned.                                       */
136 /* note that this is similar to the function `powof2' in SDCCsymt  */
137 /* if(n == 2^y)                                                    */
138 /*   return y;                                                     */
139 /* return -1;                                                      */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
142 {
143   if(num) {
144     if( (num & (num-1)) == 0) {
145       int nshifts = -1;
146       while(num) {
147         num>>=1;
148         nshifts++;
149       }
150       return nshifts;
151     }
152   }
153
154   return -1;
155 }
156
157
158 /*-----------------------------------------------------------------*/
159 /* emitcode - writes the code into a file : for now it is simple    */
160 /*-----------------------------------------------------------------*/
161 static void emitcode (char *inst,char *fmt, ...)
162 {
163     va_list ap;
164     char lb[MAX_INLINEASM];  
165     char *lbp = lb;
166
167     va_start(ap,fmt);   
168
169     if (inst && *inst) {
170         if (fmt && *fmt)
171             sprintf(lb,"%s\t",inst);
172         else
173             sprintf(lb,"%s",inst);
174         vsprintf(lb+(strlen(lb)),fmt,ap);
175     }  else
176         vsprintf(lb,fmt,ap);
177
178     while (isspace(*lbp)) lbp++;
179
180     if (lbp && *lbp) 
181         lineCurr = (lineCurr ?
182                     connectLine(lineCurr,newLineNode(lb)) :
183                     (lineHead = newLineNode(lb)));
184     lineCurr->isInline = _G.inLine;
185     lineCurr->isDebug  = _G.debugLine;
186     va_end(ap);
187 }
188
189 static void DEBUGemitcode (char *inst,char *fmt, ...)
190 {
191     va_list ap;
192     char lb[MAX_INLINEASM];  
193     char *lbp = lb;
194
195     if(!debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     if (inst && *inst) {
201         if (fmt && *fmt)
202             sprintf(lb,"%s\t",inst);
203         else
204             sprintf(lb,"%s",inst);
205         vsprintf(lb+(strlen(lb)),fmt,ap);
206     }  else
207         vsprintf(lb,fmt,ap);
208
209     while (isspace(*lbp)) lbp++;
210
211     if (lbp && *lbp) 
212         lineCurr = (lineCurr ?
213                     connectLine(lineCurr,newLineNode(lb)) :
214                     (lineHead = newLineNode(lb)));
215     lineCurr->isInline = _G.inLine;
216     lineCurr->isDebug  = _G.debugLine;
217     va_end(ap);
218 }
219
220
221 /*-----------------------------------------------------------------*/
222 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
223 /*-----------------------------------------------------------------*/
224 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
225 {
226     bool r0iu = FALSE , r1iu = FALSE;
227     bool r0ou = FALSE , r1ou = FALSE;
228
229     /* the logic: if r0 & r1 used in the instruction
230     then we are in trouble otherwise */
231
232     /* first check if r0 & r1 are used by this
233     instruction, in which case we are in trouble */
234     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
235         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
236     {
237         goto endOfWorld;      
238     }
239
240     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
241     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
242
243     /* if no usage of r0 then return it */
244     if (!r0iu && !r0ou) {
245         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
246         (*aopp)->type = AOP_R0;
247         
248         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
249     }
250
251     /* if no usage of r1 then return it */
252     if (!r1iu && !r1ou) {
253         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
254         (*aopp)->type = AOP_R1;
255
256         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
257     }    
258
259     /* now we know they both have usage */
260     /* if r0 not used in this instruction */
261     if (!r0iu) {
262         /* push it if not already pushed */
263         if (!_G.r0Pushed) {
264             emitcode ("push","%s",
265                       pic14_regWithIdx(R0_IDX)->dname);
266             _G.r0Pushed++ ;
267         }
268         
269         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
270         (*aopp)->type = AOP_R0;
271
272         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
273     }
274
275     /* if r1 not used then */
276
277     if (!r1iu) {
278         /* push it if not already pushed */
279         if (!_G.r1Pushed) {
280             emitcode ("push","%s",
281                       pic14_regWithIdx(R1_IDX)->dname);
282             _G.r1Pushed++ ;
283         }
284         
285         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
286         (*aopp)->type = AOP_R1;
287         return pic14_regWithIdx(R1_IDX);
288     }
289
290 endOfWorld :
291     /* I said end of world but not quite end of world yet */
292     /* if this is a result then we can push it on the stack*/
293     if (result) {
294         (*aopp)->type = AOP_STK;    
295         return NULL;
296     }
297
298     piCode(ic,stdout);
299     /* other wise this is true end of the world */
300     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
301            "getFreePtr should never reach here");
302     exit(0);
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* newAsmop - creates a new asmOp                                  */
307 /*-----------------------------------------------------------------*/
308 static asmop *newAsmop (short type)
309 {
310     asmop *aop;
311
312     ALLOC(aop,sizeof(asmop));
313     aop->type = type;
314     return aop;
315 }
316
317 static void genSetDPTR(int n)
318 {
319     if (!n)
320     {
321         emitcode(";", "Select standard DPTR");
322         emitcode("mov", "dps, #0x00");
323     }
324     else
325     {
326         emitcode(";", "Select alternate DPTR");
327         emitcode("mov", "dps, #0x01");
328     }
329 }
330
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type               */
333 /*-----------------------------------------------------------------*/
334 static int pointerCode (sym_link *etype)
335 {
336
337     return PTR_TYPE(SPEC_OCLS(etype));
338
339 }
340
341 /*-----------------------------------------------------------------*/
342 /* aopForSym - for a true symbol                                   */
343 /*-----------------------------------------------------------------*/
344 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
345 {
346     asmop *aop;
347     memmap *space= SPEC_OCLS(sym->etype);
348
349     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
350     /* if already has one */
351     if (sym->aop)
352         return sym->aop;
353
354     /* assign depending on the storage class */
355     /* if it is on the stack or indirectly addressable */
356     /* space we need to assign either r0 or r1 to it   */    
357     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
358         sym->aop = aop = newAsmop(0);
359         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
360         aop->size = getSize(sym->type);
361
362         /* now assign the address of the variable to 
363         the pointer register */
364         if (aop->type != AOP_STK) {
365
366             if (sym->onStack) {
367                     if ( _G.accInUse )
368                         emitcode("push","acc");
369
370                     emitcode("mov","a,_bp");
371                     emitcode("add","a,#0x%02x",
372                              ((sym->stack < 0) ?
373                               ((char)(sym->stack - _G.nRegsSaved )) :
374                               ((char)sym->stack)) & 0xff);
375                     emitcode("mov","%s,a",
376                              aop->aopu.aop_ptr->name);
377
378                     if ( _G.accInUse )
379                         emitcode("pop","acc");
380             } else
381                 emitcode("mov","%s,#%s",
382                          aop->aopu.aop_ptr->name,
383                          sym->rname);
384             aop->paged = space->paged;
385         } else
386             aop->aopu.aop_stk = sym->stack;
387         return aop;
388     }
389     
390     if (sym->onStack && options.stack10bit)
391     {
392         /* It's on the 10 bit stack, which is located in
393          * far data space.
394          */
395          
396       //DEBUGemitcode(";","%d",__LINE__);
397
398         if ( _G.accInUse )
399                 emitcode("push","acc");
400
401         emitcode("mov","a,_bp");
402         emitcode("add","a,#0x%02x",
403                  ((sym->stack < 0) ?
404                    ((char)(sym->stack - _G.nRegsSaved )) :
405                    ((char)sym->stack)) & 0xff);
406         
407         genSetDPTR(1);
408         emitcode ("mov","dpx1,#0x40");
409         emitcode ("mov","dph1,#0x00");
410         emitcode ("mov","dpl1, a");
411         genSetDPTR(0);
412         
413         if ( _G.accInUse )
414             emitcode("pop","acc");
415             
416         sym->aop = aop = newAsmop(AOP_DPTR2);
417         aop->size = getSize(sym->type); 
418         return aop;
419     }
420
421     //DEBUGemitcode(";","%d",__LINE__);
422     /* if in bit space */
423     if (IN_BITSPACE(space)) {
424         sym->aop = aop = newAsmop (AOP_CRY);
425         aop->aopu.aop_dir = sym->rname ;
426         aop->size = getSize(sym->type);
427         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
428         return aop;
429     }
430     /* if it is in direct space */
431     if (IN_DIRSPACE(space)) {
432         sym->aop = aop = newAsmop (AOP_DIR);
433         aop->aopu.aop_dir = sym->rname ;
434         aop->size = getSize(sym->type);
435         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
436         return aop;
437     }
438
439     /* special case for a function */
440     if (IS_FUNC(sym->type)) {   
441         sym->aop = aop = newAsmop(AOP_IMMD);    
442         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
443         strcpy(aop->aopu.aop_immd,sym->rname);
444         aop->size = FPTRSIZE; 
445         return aop;
446     }
447
448
449     /* only remaining is far space */
450     /* in which case DPTR gets the address */
451     sym->aop = aop = newAsmop(AOP_DPTR);
452     emitcode ("mov","dptr,#%s", sym->rname);
453     aop->size = getSize(sym->type);
454
455     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
456     /* if it is in code space */
457     if (IN_CODESPACE(space))
458         aop->code = 1;
459
460     return aop;     
461 }
462
463 /*-----------------------------------------------------------------*/
464 /* aopForRemat - rematerialzes an object                           */
465 /*-----------------------------------------------------------------*/
466 static asmop *aopForRemat (symbol *sym)
467 {
468     iCode *ic = sym->rematiCode;
469     asmop *aop = newAsmop(AOP_IMMD);
470     int val = 0;
471     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
472     for (;;) {
473         if (ic->op == '+')
474             val += operandLitValue(IC_RIGHT(ic));
475         else if (ic->op == '-')
476             val -= operandLitValue(IC_RIGHT(ic));
477         else
478             break;
479         
480         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
481     }
482
483     if (val)
484         sprintf(buffer,"(%s %c 0x%04x)",
485                 OP_SYMBOL(IC_LEFT(ic))->rname, 
486                 val >= 0 ? '+' : '-',
487                 abs(val) & 0xffff);
488     else
489         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
490
491     //DEBUGemitcode(";","%s",buffer);
492     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
493     strcpy(aop->aopu.aop_immd,buffer);    
494     return aop;        
495 }
496
497 /*-----------------------------------------------------------------*/
498 /* regsInCommon - two operands have some registers in common       */
499 /*-----------------------------------------------------------------*/
500 static bool regsInCommon (operand *op1, operand *op2)
501 {
502     symbol *sym1, *sym2;
503     int i;
504
505     /* if they have registers in common */
506     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
507         return FALSE ;
508
509     sym1 = OP_SYMBOL(op1);
510     sym2 = OP_SYMBOL(op2);
511
512     if (sym1->nRegs == 0 || sym2->nRegs == 0)
513         return FALSE ;
514
515     for (i = 0 ; i < sym1->nRegs ; i++) {
516         int j;
517         if (!sym1->regs[i])
518             continue ;
519
520         for (j = 0 ; j < sym2->nRegs ;j++ ) {
521             if (!sym2->regs[j])
522                 continue ;
523
524             if (sym2->regs[j] == sym1->regs[i])
525                 return TRUE ;
526         }
527     }
528
529     return FALSE ;
530 }
531
532 /*-----------------------------------------------------------------*/
533 /* operandsEqu - equivalent                                        */
534 /*-----------------------------------------------------------------*/
535 static bool operandsEqu ( operand *op1, operand *op2)
536 {
537     symbol *sym1, *sym2;
538
539     /* if they not symbols */
540     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
541         return FALSE;
542
543     sym1 = OP_SYMBOL(op1);
544     sym2 = OP_SYMBOL(op2);
545
546     /* if both are itemps & one is spilt
547        and the other is not then false */
548     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
549         sym1->isspilt != sym2->isspilt )
550         return FALSE ;
551
552     /* if they are the same */
553     if (sym1 == sym2)
554         return TRUE ;
555
556     if (strcmp(sym1->rname,sym2->rname) == 0)
557         return TRUE;
558
559
560     /* if left is a tmp & right is not */
561     if (IS_ITEMP(op1)  && 
562         !IS_ITEMP(op2) &&
563         sym1->isspilt  &&
564         (sym1->usl.spillLoc == sym2))
565         return TRUE;
566
567     if (IS_ITEMP(op2)  && 
568         !IS_ITEMP(op1) &&
569         sym2->isspilt  &&
570         sym1->level > 0 &&
571         (sym2->usl.spillLoc == sym1))
572         return TRUE ;
573
574     return FALSE ;
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* sameRegs - two asmops have the same registers                   */
579 /*-----------------------------------------------------------------*/
580 static bool sameRegs (asmop *aop1, asmop *aop2 )
581 {
582     int i;
583
584     if (aop1 == aop2)
585         return TRUE ;
586
587     if (aop1->type != AOP_REG ||
588         aop2->type != AOP_REG )
589         return FALSE ;
590
591     if (aop1->size != aop2->size )
592         return FALSE ;
593
594     for (i = 0 ; i < aop1->size ; i++ )
595         if (aop1->aopu.aop_reg[i] !=
596             aop2->aopu.aop_reg[i] )
597             return FALSE ;
598
599     return TRUE ;
600 }
601
602 /*-----------------------------------------------------------------*/
603 /* aopOp - allocates an asmop for an operand  :                    */
604 /*-----------------------------------------------------------------*/
605 static void aopOp (operand *op, iCode *ic, bool result)
606 {
607     asmop *aop;
608     symbol *sym;
609     int i;
610
611     if (!op)
612         return ;
613
614     DEBUGemitcode(";","%d",__LINE__);
615     /* if this a literal */
616     if (IS_OP_LITERAL(op)) {
617       DEBUGemitcode(";","%d",__LINE__);
618         op->aop = aop = newAsmop(AOP_LIT);
619         aop->aopu.aop_lit = op->operand.valOperand;
620         aop->size = getSize(operandType(op));
621         return;
622     }
623
624     /* if already has a asmop then continue */
625     if (op->aop)
626         return ;
627
628     /* if the underlying symbol has a aop */
629     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
630       DEBUGemitcode(";","%d",__LINE__);
631         op->aop = OP_SYMBOL(op)->aop;
632         return;
633     }
634
635     /* if this is a true symbol */
636     if (IS_TRUE_SYMOP(op)) {    
637       DEBUGemitcode(";","%d",__LINE__);
638         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
639         return ;
640     }
641
642     /* this is a temporary : this has
643     only four choices :
644     a) register
645     b) spillocation
646     c) rematerialize 
647     d) conditional   
648     e) can be a return use only */
649
650     sym = OP_SYMBOL(op);
651
652
653     /* if the type is a conditional */
654     if (sym->regType == REG_CND) {
655       DEBUGemitcode(";","%d",__LINE__);
656         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
657         aop->size = 0;
658         return;
659     }
660
661     /* if it is spilt then two situations
662     a) is rematerialize 
663     b) has a spill location */
664     if (sym->isspilt || sym->nRegs == 0) {
665
666       DEBUGemitcode(";","%d",__LINE__);
667         /* rematerialize it NOW */
668         if (sym->remat) {
669             sym->aop = op->aop = aop =
670                                       aopForRemat (sym);
671             aop->size = getSize(sym->type);
672             DEBUGemitcode(";","%d",__LINE__);
673             return;
674         }
675
676         if (sym->accuse) {
677             int i;
678             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
679             aop->size = getSize(sym->type);
680             for ( i = 0 ; i < 2 ; i++ )
681                 aop->aopu.aop_str[i] = accUse[i];
682             DEBUGemitcode(";","%d",__LINE__);
683             return;  
684         }
685
686         if (sym->ruonly ) {
687             int i;
688             aop = op->aop = sym->aop = newAsmop(AOP_STR);
689             aop->size = getSize(sym->type);
690             for ( i = 0 ; i < fReturnSize ; i++ )
691               aop->aopu.aop_str[i] = fReturn[i];
692             DEBUGemitcode(";","%d",__LINE__);
693             return;
694         }
695
696         /* else spill location  */
697         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
698         sym->aop = op->aop = aop = 
699                                   aopForSym(ic,sym->usl.spillLoc,result);
700         aop->size = getSize(sym->type);
701         return;
702     }
703
704     /* must be in a register */
705     sym->aop = op->aop = aop = newAsmop(AOP_REG);
706     aop->size = sym->nRegs;
707     for ( i = 0 ; i < sym->nRegs ;i++)
708         aop->aopu.aop_reg[i] = sym->regs[i];
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* freeAsmop - free up the asmop given to an operand               */
713 /*----------------------------------------------------------------*/
714 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
715 {   
716     asmop *aop ;
717
718     if (!op)
719         aop = aaop;
720     else 
721         aop = op->aop;
722
723     if (!aop)
724         return ;
725
726     if (aop->freed)
727         goto dealloc; 
728
729     aop->freed = 1;
730
731     /* depending on the asmop type only three cases need work AOP_RO
732        , AOP_R1 && AOP_STK */
733     switch (aop->type) {
734         case AOP_R0 :
735             if (_G.r0Pushed ) {
736                 if (pop) {
737                     emitcode ("pop","ar0");     
738                     _G.r0Pushed--;
739                 }
740             }
741             bitVectUnSetBit(ic->rUsed,R0_IDX);
742             break;
743
744         case AOP_R1 :
745             if (_G.r1Pushed ) {
746                 if (pop) {
747                     emitcode ("pop","ar1");
748                     _G.r1Pushed--;
749                 }
750             }
751             bitVectUnSetBit(ic->rUsed,R1_IDX);          
752             break;
753
754         case AOP_STK :
755         {
756             int sz = aop->size;    
757             int stk = aop->aopu.aop_stk + aop->size;
758             bitVectUnSetBit(ic->rUsed,R0_IDX);
759             bitVectUnSetBit(ic->rUsed,R1_IDX);          
760
761             getFreePtr(ic,&aop,FALSE);
762             
763             if (options.stack10bit)
764             {
765                 /* I'm not sure what to do here yet... */
766                 /* #STUB */
767                 fprintf(stderr, 
768                         "*** Warning: probably generating bad code for "
769                         "10 bit stack mode.\n");
770             }
771             
772             if (stk) {
773                 emitcode ("mov","a,_bp");
774                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
775                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
776             } else {
777                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
778             }
779
780             while (sz--) {
781                 emitcode("pop","acc");
782                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
783                 if (!sz) break;
784                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
785             }
786             op->aop = aop;
787             freeAsmop(op,NULL,ic,TRUE);
788             if (_G.r0Pushed) {
789                 emitcode("pop","ar0");
790                 _G.r0Pushed--;
791             }
792
793             if (_G.r1Pushed) {
794                 emitcode("pop","ar1");
795                 _G.r1Pushed--;
796             }       
797         }
798     }
799
800 dealloc:
801     /* all other cases just dealloc */
802     if (op ) {
803         op->aop = NULL;
804         if (IS_SYMOP(op)) {
805             OP_SYMBOL(op)->aop = NULL;    
806             /* if the symbol has a spill */
807             if (SPIL_LOC(op))
808                 SPIL_LOC(op)->aop = NULL;
809         }
810     }
811 }
812
813 /*-----------------------------------------------------------------*/
814 /* aopGet - for fetching value of the aop                          */
815 /*-----------------------------------------------------------------*/
816 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
817 {
818     char *s = buffer ;
819     char *rs;
820
821     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
822     /* offset is greater than
823     size then zero */
824     if (offset > (aop->size - 1) &&
825         aop->type != AOP_LIT)
826         return zero;
827
828     /* depending on type */
829     switch (aop->type) {
830         
831     case AOP_R0:
832     case AOP_R1:
833         DEBUGemitcode(";","%d",__LINE__);
834         /* if we need to increment it */       
835         while (offset > aop->coff) {        
836             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
837             aop->coff++;
838         }
839         
840         while (offset < aop->coff) {
841             emitcode("dec","%s",aop->aopu.aop_ptr->name);
842             aop->coff--;
843         }
844         
845         aop->coff = offset ;
846         if (aop->paged) {
847             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
848             return (dname ? "acc" : "a");
849         }       
850         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
851         ALLOC_ATOMIC(rs,strlen(s)+1);
852         strcpy(rs,s);   
853         return rs;
854         
855     case AOP_DPTR:
856     case AOP_DPTR2:
857         DEBUGemitcode(";","%d",__LINE__);
858     if (aop->type == AOP_DPTR2)
859     {
860         genSetDPTR(1);
861     }
862     
863         while (offset > aop->coff) {
864             emitcode ("inc","dptr");
865             aop->coff++;
866         }
867         
868         while (offset < aop->coff) {        
869             emitcode("lcall","__decdptr");
870             aop->coff--;
871         }
872         
873         aop->coff = offset;
874         if (aop->code) {
875             emitcode("clr","a");
876             emitcode("movc","a,@a+dptr");
877         }
878     else {
879             emitcode("movx","a,@dptr");
880     }
881             
882     if (aop->type == AOP_DPTR2)
883     {
884         genSetDPTR(0);
885     }
886             
887     return (dname ? "acc" : "a");
888         
889         
890     case AOP_IMMD:
891       DEBUGemitcode(";","%d",__LINE__);
892         if (bit16) 
893             sprintf (s,"%s",aop->aopu.aop_immd);
894         else
895             if (offset) 
896                 sprintf(s,"(%s >> %d)",
897                         aop->aopu.aop_immd,
898                         offset*8);
899             else
900                 sprintf(s,"%s",
901                         aop->aopu.aop_immd);
902         ALLOC_ATOMIC(rs,strlen(s)+1);
903         strcpy(rs,s);   
904         return rs;
905         
906     case AOP_DIR:
907         if (offset)
908             sprintf(s,"(%s + %d)",
909                     aop->aopu.aop_dir,
910                     offset);
911         else
912             sprintf(s,"%s",aop->aopu.aop_dir);
913         ALLOC_ATOMIC(rs,strlen(s)+1);
914         strcpy(rs,s);   
915         return rs;
916         
917     case AOP_REG:
918       DEBUGemitcode(";","%d",__LINE__);
919         if (dname) 
920             return aop->aopu.aop_reg[offset]->dname;
921         else
922             return aop->aopu.aop_reg[offset]->name;
923         
924     case AOP_CRY:
925       emitcode(";","%d",__LINE__);
926       //emitcode("clr","a");
927       //emitcode("mov","c,%s",aop->aopu.aop_dir);
928       //emitcode("rlc","a") ;
929       //return (dname ? "acc" : "a");
930       return aop->aopu.aop_dir;
931         
932     case AOP_ACC:
933         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
934         //if (!offset && dname)
935         //    return "acc";
936         //return aop->aopu.aop_str[offset];
937         return "AOP_accumulator_bug";
938
939     case AOP_LIT:
940         DEBUGemitcode(";","%d",__LINE__);
941         return pic14aopLiteral (aop->aopu.aop_lit,offset);
942         
943     case AOP_STR:
944         DEBUGemitcode(";","%d",__LINE__);
945         aop->coff = offset ;
946         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
947             dname)
948             return "acc";
949         
950         return aop->aopu.aop_str[offset];
951         
952     }
953
954     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
955            "aopget got unsupported aop->type");
956     exit(0);
957 }
958 /*-----------------------------------------------------------------*/
959 /* aopPut - puts a string for a aop                                */
960 /*-----------------------------------------------------------------*/
961 static void aopPut (asmop *aop, char *s, int offset)
962 {
963     char *d = buffer ;
964     symbol *lbl ;
965
966     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
967
968     if (aop->size && offset > ( aop->size - 1)) {
969         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
970                "aopPut got offset > aop->size");
971         exit(0);
972     }
973
974     /* will assign value to value */
975     /* depending on where it is ofcourse */
976     switch (aop->type) {
977     case AOP_DIR:
978         if (offset)
979             sprintf(d,"(%s + %d)",
980                     aop->aopu.aop_dir,offset);
981         else
982             sprintf(d,"%s",aop->aopu.aop_dir);
983         
984         if (strcmp(d,s)) {
985           DEBUGemitcode(";","%d",__LINE__);
986           emitcode("movf","%s,w",s);
987           emitcode("movwf","%s",d);
988         }
989         break;
990         
991     case AOP_REG:
992         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
993             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
994             if (*s == '@'           ||
995                 strcmp(s,"r0") == 0 ||
996                 strcmp(s,"r1") == 0 ||
997                 strcmp(s,"r2") == 0 ||
998                 strcmp(s,"r3") == 0 ||
999                 strcmp(s,"r4") == 0 ||
1000                 strcmp(s,"r5") == 0 ||
1001                 strcmp(s,"r6") == 0 || 
1002                 strcmp(s,"r7") == 0 )
1003                 emitcode("mov","%s,%s  ; %d",
1004                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1005             else
1006                 emitcode("mov","%s,%s  ; %d",
1007                          aop->aopu.aop_reg[offset]->name,s,__LINE__);
1008         }
1009         break;
1010         
1011     case AOP_DPTR:
1012     case AOP_DPTR2:
1013     
1014     if (aop->type == AOP_DPTR2)
1015     {
1016         genSetDPTR(1);
1017     }
1018     
1019         if (aop->code) {
1020             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1021                    "aopPut writting to code space");
1022             exit(0);
1023         }
1024         
1025         while (offset > aop->coff) {
1026             aop->coff++;
1027             emitcode ("inc","dptr");
1028         }
1029         
1030         while (offset < aop->coff) {
1031             aop->coff-- ;
1032             emitcode("lcall","__decdptr");
1033         }
1034         
1035         aop->coff = offset;
1036         
1037         /* if not in accumulater */
1038         MOVA(s);        
1039         
1040         emitcode ("movx","@dptr,a");
1041         
1042     if (aop->type == AOP_DPTR2)
1043     {
1044         genSetDPTR(0);
1045     }
1046         break;
1047         
1048     case AOP_R0:
1049     case AOP_R1:
1050         while (offset > aop->coff) {
1051             aop->coff++;
1052             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1053         }
1054         while (offset < aop->coff) {
1055             aop->coff-- ;
1056             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1057         }
1058         aop->coff = offset;
1059         
1060         if (aop->paged) {
1061             MOVA(s);           
1062             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1063             
1064         } else
1065             if (*s == '@') {
1066                 MOVA(s);
1067                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1068             } else
1069                 if (strcmp(s,"r0") == 0 ||
1070                     strcmp(s,"r1") == 0 ||
1071                     strcmp(s,"r2") == 0 ||
1072                     strcmp(s,"r3") == 0 ||
1073                     strcmp(s,"r4") == 0 ||
1074                     strcmp(s,"r5") == 0 ||
1075                     strcmp(s,"r6") == 0 || 
1076                     strcmp(s,"r7") == 0 ) {
1077                     char buffer[10];
1078                     sprintf(buffer,"a%s",s);
1079                     emitcode("mov","@%s,%s",
1080                              aop->aopu.aop_ptr->name,buffer);
1081                 } else
1082                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1083         
1084         break;
1085         
1086     case AOP_STK:
1087         if (strcmp(s,"a") == 0)
1088             emitcode("push","acc");
1089         else
1090             emitcode("push","%s",s);
1091         
1092         break;
1093         
1094     case AOP_CRY:
1095         /* if bit variable */
1096         if (!aop->aopu.aop_dir) {
1097             emitcode("clr","a");
1098             emitcode("rlc","a");
1099         } else {
1100             if (s == zero) 
1101                 emitcode("clr","%s",aop->aopu.aop_dir);
1102             else
1103                 if (s == one)
1104                     emitcode("setb","%s",aop->aopu.aop_dir);
1105                 else
1106                     if (!strcmp(s,"c"))
1107                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1108                     else {
1109                         lbl = newiTempLabel(NULL);
1110                         
1111                         if (strcmp(s,"a")) {
1112                             MOVA(s);
1113                         }
1114                         emitcode("clr","c");
1115                         emitcode("jz","%05d_DS_",lbl->key+100);
1116                         emitcode("cpl","c");
1117                         emitcode("","%05d_DS_:",lbl->key+100);
1118                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1119                     }
1120         }
1121         break;
1122         
1123     case AOP_STR:
1124         aop->coff = offset;
1125         if (strcmp(aop->aopu.aop_str[offset],s))
1126             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1127         break;
1128         
1129     case AOP_ACC:
1130         aop->coff = offset;
1131         if (!offset && (strcmp(s,"acc") == 0))
1132             break;
1133         
1134         if (strcmp(aop->aopu.aop_str[offset],s))
1135             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1136         break;
1137
1138     default :
1139         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1140                "aopPut got unsupported aop->type");
1141         exit(0);    
1142     }    
1143
1144 }
1145
1146 /*-----------------------------------------------------------------*/
1147 /* reAdjustPreg - points a register back to where it should        */
1148 /*-----------------------------------------------------------------*/
1149 static void reAdjustPreg (asmop *aop)
1150 {
1151     int size ;
1152
1153     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1154     aop->coff = 0;
1155     if ((size = aop->size) <= 1)
1156         return ;
1157     size-- ;
1158     switch (aop->type) {
1159         case AOP_R0 :
1160         case AOP_R1 :
1161             while (size--)
1162                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1163             break;          
1164         case AOP_DPTR :
1165         case AOP_DPTR2:
1166             if (aop->type == AOP_DPTR2)
1167             {
1168                 genSetDPTR(1);
1169             } 
1170             while (size--)
1171             {
1172                 emitcode("lcall","__decdptr");
1173             }
1174                 
1175             if (aop->type == AOP_DPTR2)
1176             {
1177                 genSetDPTR(0);
1178             }                
1179             break;  
1180
1181     }   
1182
1183 }
1184
1185 #define AOP(op) op->aop
1186 #define AOP_TYPE(op) AOP(op)->type
1187 #define AOP_SIZE(op) AOP(op)->size
1188 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1189                        AOP_TYPE(x) == AOP_R0))
1190
1191 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1192                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1193                          AOP(x)->paged)) 
1194
1195 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1196                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1197                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1198
1199 /*-----------------------------------------------------------------*/
1200 /* genNotFloat - generates not for float operations              */
1201 /*-----------------------------------------------------------------*/
1202 static void genNotFloat (operand *op, operand *res)
1203 {
1204     int size, offset;
1205     char *l;
1206     symbol *tlbl ;
1207
1208     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1209     /* we will put 127 in the first byte of 
1210     the result */
1211     aopPut(AOP(res),"#127",0);
1212     size = AOP_SIZE(op) - 1;
1213     offset = 1;
1214
1215     l = aopGet(op->aop,offset++,FALSE,FALSE);
1216     MOVA(l);    
1217
1218     while(size--) {
1219         emitcode("orl","a,%s",
1220                  aopGet(op->aop,
1221                         offset++,FALSE,FALSE));
1222     }
1223     tlbl = newiTempLabel(NULL);
1224
1225     tlbl = newiTempLabel(NULL);
1226     aopPut(res->aop,one,1);
1227     emitcode("jz","%05d_DS_",(tlbl->key+100));
1228     aopPut(res->aop,zero,1);
1229     emitcode("","%05d_DS_:",(tlbl->key+100));
1230
1231     size = res->aop->size - 2;
1232     offset = 2;    
1233     /* put zeros in the rest */
1234     while (size--) 
1235         aopPut(res->aop,zero,offset++);
1236 }
1237
1238 #if 0
1239 /*-----------------------------------------------------------------*/
1240 /* opIsGptr: returns non-zero if the passed operand is             */   
1241 /* a generic pointer type.                                         */
1242 /*-----------------------------------------------------------------*/ 
1243 static int opIsGptr(operand *op)
1244 {
1245     sym_link *type = operandType(op);
1246     
1247     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1248     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1249     {
1250         return 1;
1251     }
1252     return 0;        
1253 }
1254 #endif
1255
1256 /*-----------------------------------------------------------------*/
1257 /* getDataSize - get the operand data size                         */
1258 /*-----------------------------------------------------------------*/
1259 static int getDataSize(operand *op)
1260 {
1261     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1262
1263
1264     return AOP_SIZE(op);
1265
1266     // tsd- in the pic port, the genptr size is 1, so this code here
1267     // fails. ( in the 8051 port, the size was 4).
1268 #if 0
1269     int size;
1270     size = AOP_SIZE(op);
1271     if (size == GPTRSIZE)
1272     {
1273         sym_link *type = operandType(op);
1274         if (IS_GENPTR(type))
1275         {
1276             /* generic pointer; arithmetic operations
1277              * should ignore the high byte (pointer type).
1278              */
1279             size--;
1280     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1281         }
1282     }
1283     return size;
1284 #endif
1285 }
1286
1287 /*-----------------------------------------------------------------*/
1288 /* outAcc - output Acc                                             */
1289 /*-----------------------------------------------------------------*/
1290 static void outAcc(operand *result)
1291 {
1292     int size, offset;
1293     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1294     size = getDataSize(result);
1295     if(size){
1296         aopPut(AOP(result),"a",0);
1297         size--;
1298         offset = 1;
1299         /* unsigned or positive */
1300         while(size--){
1301             aopPut(AOP(result),zero,offset++);
1302         }
1303     }
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* outBitC - output a bit C                                        */
1308 /*-----------------------------------------------------------------*/
1309 static void outBitC(operand *result)
1310 {
1311
1312     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1313     /* if the result is bit */
1314     if (AOP_TYPE(result) == AOP_CRY) 
1315         aopPut(AOP(result),"c",0);
1316     else {
1317         emitcode("clr","a  ; %d", __LINE__);
1318         emitcode("rlc","a");
1319         outAcc(result);
1320     }
1321 }
1322
1323 /*-----------------------------------------------------------------*/
1324 /* toBoolean - emit code for orl a,operator(sizeop)                */
1325 /*-----------------------------------------------------------------*/
1326 static void toBoolean(operand *oper)
1327 {
1328     int size = AOP_SIZE(oper) - 1;
1329     int offset = 1;
1330
1331     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1332
1333     if ( AOP_TYPE(oper) != AOP_ACC)
1334       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1335
1336     while (size--) 
1337         emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1338 }
1339
1340
1341 /*-----------------------------------------------------------------*/
1342 /* genNot - generate code for ! operation                          */
1343 /*-----------------------------------------------------------------*/
1344 static void genNot (iCode *ic)
1345 {
1346     symbol *tlbl;
1347     sym_link *optype = operandType(IC_LEFT(ic));
1348
1349     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1350     /* assign asmOps to operand & result */
1351     aopOp (IC_LEFT(ic),ic,FALSE);
1352     aopOp (IC_RESULT(ic),ic,TRUE);
1353
1354     /* if in bit space then a special case */
1355     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1356       emitcode("movlw","1<<%s");
1357       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1358       //emitcode("cpl","c"); 
1359       //outBitC(IC_RESULT(ic));
1360       goto release;
1361     }
1362
1363     /* if type float then do float */
1364     if (IS_FLOAT(optype)) {
1365         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1366         goto release;
1367     }
1368
1369     toBoolean(IC_LEFT(ic));
1370
1371     tlbl = newiTempLabel(NULL);
1372     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1373     emitcode("","%05d_DS_:",tlbl->key+100);
1374     outBitC(IC_RESULT(ic));
1375
1376 release:    
1377     /* release the aops */
1378     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1379     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1380 }
1381
1382
1383 /*-----------------------------------------------------------------*/
1384 /* genCpl - generate code for complement                           */
1385 /*-----------------------------------------------------------------*/
1386 static void genCpl (iCode *ic)
1387 {
1388     int offset = 0;
1389     int size ;
1390
1391
1392     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1393     /* assign asmOps to operand & result */
1394     aopOp (IC_LEFT(ic),ic,FALSE);
1395     aopOp (IC_RESULT(ic),ic,TRUE);
1396
1397     /* if both are in bit space then 
1398     a special case */
1399     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1400         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1401
1402         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1403         emitcode("cpl","c"); 
1404         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1405         goto release; 
1406     } 
1407
1408     size = AOP_SIZE(IC_RESULT(ic));
1409     while (size--) {
1410         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1411         MOVA(l);       
1412         emitcode("cpl","a");
1413         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1414     }
1415
1416
1417 release:
1418     /* release the aops */
1419     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1420     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1421 }
1422
1423 /*-----------------------------------------------------------------*/
1424 /* genUminusFloat - unary minus for floating points                */
1425 /*-----------------------------------------------------------------*/
1426 static void genUminusFloat(operand *op,operand *result)
1427 {
1428     int size ,offset =0 ;
1429     char *l;
1430
1431     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1432     /* for this we just need to flip the 
1433     first it then copy the rest in place */
1434     size = AOP_SIZE(op) - 1;
1435     l = aopGet(AOP(op),3,FALSE,FALSE);
1436
1437     MOVA(l);    
1438
1439     emitcode("cpl","acc.7");
1440     aopPut(AOP(result),"a",3);    
1441
1442     while(size--) {
1443         aopPut(AOP(result),
1444                aopGet(AOP(op),offset,FALSE,FALSE),
1445                offset);
1446         offset++;
1447     }          
1448 }
1449
1450 /*-----------------------------------------------------------------*/
1451 /* genUminus - unary minus code generation                         */
1452 /*-----------------------------------------------------------------*/
1453 static void genUminus (iCode *ic)
1454 {
1455     int offset ,size ;
1456     sym_link *optype, *rtype;
1457
1458
1459     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1460     /* assign asmops */
1461     aopOp(IC_LEFT(ic),ic,FALSE);
1462     aopOp(IC_RESULT(ic),ic,TRUE);
1463
1464     /* if both in bit space then special
1465     case */
1466     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1467         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1468
1469         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1470         emitcode("cpl","c"); 
1471         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1472         goto release; 
1473     } 
1474
1475     optype = operandType(IC_LEFT(ic));
1476     rtype = operandType(IC_RESULT(ic));
1477
1478     /* if float then do float stuff */
1479     if (IS_FLOAT(optype)) {
1480         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1481         goto release;
1482     }
1483
1484     /* otherwise subtract from zero */
1485     size = AOP_SIZE(IC_LEFT(ic));
1486     offset = 0 ;
1487     CLRC ;
1488     while(size--) {
1489         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1490         if (!strcmp(l,"a")) {
1491             emitcode("cpl","a");
1492             emitcode("inc","a");
1493         } else {
1494             emitcode("clr","a");
1495             emitcode("subb","a,%s",l);
1496         }       
1497         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1498     }
1499
1500     /* if any remaining bytes in the result */
1501     /* we just need to propagate the sign   */
1502     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1503         emitcode("rlc","a");
1504         emitcode("subb","a,acc");
1505         while (size--) 
1506             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1507     }       
1508
1509 release:
1510     /* release the aops */
1511     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1512     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* saveRegisters - will look for a call and save the registers     */
1517 /*-----------------------------------------------------------------*/
1518 static void saveRegisters(iCode *lic) 
1519 {
1520     int i;
1521     iCode *ic;
1522     bitVect *rsave;
1523     sym_link *detype;
1524
1525     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1526     /* look for call */
1527     for (ic = lic ; ic ; ic = ic->next) 
1528         if (ic->op == CALL || ic->op == PCALL)
1529             break;
1530
1531     if (!ic) {
1532         fprintf(stderr,"found parameter push with no function call\n");
1533         return ;
1534     }
1535
1536     /* if the registers have been saved already then
1537     do nothing */
1538     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1539         return ;
1540
1541     /* find the registers in use at this time 
1542     and push them away to safety */
1543     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1544                           ic->rUsed);
1545
1546     ic->regsSaved = 1;
1547     if (options.useXstack) {
1548         if (bitVectBitValue(rsave,R0_IDX))
1549             emitcode("mov","b,r0");
1550         emitcode("mov","r0,%s",spname);
1551         for (i = 0 ; i < pic14_nRegs ; i++) {
1552             if (bitVectBitValue(rsave,i)) {
1553                 if (i == R0_IDX)
1554                     emitcode("mov","a,b");
1555                 else
1556                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1557                 emitcode("movx","@r0,a");
1558                 emitcode("inc","r0");
1559             }
1560         }
1561         emitcode("mov","%s,r0",spname);
1562         if (bitVectBitValue(rsave,R0_IDX))
1563             emitcode("mov","r0,b");         
1564     } else
1565         for (i = 0 ; i < pic14_nRegs ; i++) {
1566             if (bitVectBitValue(rsave,i))
1567                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1568         }
1569
1570     detype = getSpec(operandType(IC_LEFT(ic)));
1571     if (detype        && 
1572         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1573         IS_ISR(currFunc->etype) &&
1574         !ic->bankSaved) 
1575
1576         saverbank(SPEC_BANK(detype),ic,TRUE);
1577
1578 }
1579 /*-----------------------------------------------------------------*/
1580 /* unsaveRegisters - pop the pushed registers                      */
1581 /*-----------------------------------------------------------------*/
1582 static void unsaveRegisters (iCode *ic)
1583 {
1584     int i;
1585     bitVect *rsave;
1586
1587     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1588     /* find the registers in use at this time 
1589     and push them away to safety */
1590     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1591                           ic->rUsed);
1592     
1593     if (options.useXstack) {
1594         emitcode("mov","r0,%s",spname); 
1595         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1596             if (bitVectBitValue(rsave,i)) {
1597                 emitcode("dec","r0");
1598                 emitcode("movx","a,@r0");
1599                 if (i == R0_IDX)
1600                     emitcode("mov","b,a");
1601                 else
1602                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1603             }       
1604
1605         }
1606         emitcode("mov","%s,r0",spname);
1607         if (bitVectBitValue(rsave,R0_IDX))
1608             emitcode("mov","r0,b");
1609     } else
1610         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1611             if (bitVectBitValue(rsave,i))
1612                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1613         }
1614
1615 }  
1616
1617
1618 /*-----------------------------------------------------------------*/
1619 /* pushSide -                                                      */
1620 /*-----------------------------------------------------------------*/
1621 static void pushSide(operand * oper, int size)
1622 {
1623         int offset = 0;
1624     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1625         while (size--) {
1626                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1627                 if (AOP_TYPE(oper) != AOP_REG &&
1628                     AOP_TYPE(oper) != AOP_DIR &&
1629                     strcmp(l,"a") ) {
1630                         emitcode("mov","a,%s",l);
1631                         emitcode("push","acc");
1632                 } else
1633                         emitcode("push","%s",l);
1634         }
1635 }
1636
1637 /*-----------------------------------------------------------------*/
1638 /* assignResultValue -                                             */
1639 /*-----------------------------------------------------------------*/
1640 static void assignResultValue(operand * oper)
1641 {
1642         int offset = 0;
1643         int size = AOP_SIZE(oper);
1644
1645     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1646
1647         while (size--) {
1648                 aopPut(AOP(oper),fReturn[offset],offset);
1649                 offset++;
1650         }
1651 }
1652
1653
1654 /*-----------------------------------------------------------------*/
1655 /* genXpush - pushes onto the external stack                       */
1656 /*-----------------------------------------------------------------*/
1657 static void genXpush (iCode *ic)
1658 {
1659     asmop *aop = newAsmop(0);
1660     regs *r ;
1661     int size,offset = 0;
1662
1663     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1664     aopOp(IC_LEFT(ic),ic,FALSE);
1665     r = getFreePtr(ic,&aop,FALSE);
1666
1667     
1668     emitcode("mov","%s,_spx",r->name);
1669
1670     size = AOP_SIZE(IC_LEFT(ic));
1671     while(size--) {
1672
1673         char *l = aopGet(AOP(IC_LEFT(ic)),
1674                          offset++,FALSE,FALSE); 
1675         MOVA(l);            
1676         emitcode("movx","@%s,a",r->name);       
1677         emitcode("inc","%s",r->name);
1678
1679     }
1680
1681         
1682     emitcode("mov","_spx,%s",r->name);
1683
1684     freeAsmop(NULL,aop,ic,TRUE);
1685     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* genIpush - genrate code for pushing this gets a little complex  */
1690 /*-----------------------------------------------------------------*/
1691 static void genIpush (iCode *ic)
1692 {
1693     int size, offset = 0 ;
1694     char *l;
1695
1696
1697     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698     /* if this is not a parm push : ie. it is spill push 
1699     and spill push is always done on the local stack */
1700     if (!ic->parmPush) {
1701
1702         /* and the item is spilt then do nothing */
1703         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1704             return ;
1705
1706         aopOp(IC_LEFT(ic),ic,FALSE);
1707         size = AOP_SIZE(IC_LEFT(ic));
1708         /* push it on the stack */
1709         while(size--) {
1710             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1711             if (*l == '#') {
1712                 MOVA(l);
1713                 l = "acc";
1714             }
1715             emitcode("push","%s",l);
1716         }
1717         return ;        
1718     }
1719
1720     /* this is a paramter push: in this case we call
1721     the routine to find the call and save those
1722     registers that need to be saved */   
1723     saveRegisters(ic);
1724
1725     /* if use external stack then call the external
1726     stack pushing routine */
1727     if (options.useXstack) {
1728         genXpush(ic);
1729         return ;
1730     }
1731
1732     /* then do the push */
1733     aopOp(IC_LEFT(ic),ic,FALSE);
1734
1735
1736         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1737     size = AOP_SIZE(IC_LEFT(ic));
1738
1739     while (size--) {
1740         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1741         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1742             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1743             strcmp(l,"a") ) {
1744             emitcode("mov","a,%s",l);
1745             emitcode("push","acc");
1746         } else
1747             emitcode("push","%s",l);
1748     }       
1749
1750     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* genIpop - recover the registers: can happen only for spilling   */
1755 /*-----------------------------------------------------------------*/
1756 static void genIpop (iCode *ic)
1757 {
1758     int size,offset ;
1759
1760
1761     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1762     /* if the temp was not pushed then */
1763     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1764         return ;
1765
1766     aopOp(IC_LEFT(ic),ic,FALSE);
1767     size = AOP_SIZE(IC_LEFT(ic));
1768     offset = (size-1);
1769     while (size--) 
1770         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1771                                    FALSE,TRUE));
1772
1773     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* unsaverbank - restores the resgister bank from stack            */
1778 /*-----------------------------------------------------------------*/
1779 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1780 {
1781     int i;
1782     asmop *aop ;
1783     regs *r = NULL;
1784
1785     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1786     if (popPsw) {
1787         if (options.useXstack) {
1788             aop = newAsmop(0);
1789             r = getFreePtr(ic,&aop,FALSE);
1790             
1791             
1792             emitcode("mov","%s,_spx",r->name);
1793             emitcode("movx","a,@%s",r->name);
1794             emitcode("mov","psw,a");
1795             emitcode("dec","%s",r->name);
1796             
1797         }else
1798             emitcode ("pop","psw");
1799     }
1800
1801     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1802         if (options.useXstack) {       
1803             emitcode("movx","a,@%s",r->name);
1804             emitcode("mov","(%s+%d),a",
1805                      regspic14[i].base,8*bank+regspic14[i].offset);
1806             emitcode("dec","%s",r->name);
1807
1808         } else 
1809             emitcode("pop","(%s+%d)",
1810                      regspic14[i].base,8*bank+regspic14[i].offset);
1811     }
1812
1813     if (options.useXstack) {
1814
1815         emitcode("mov","_spx,%s",r->name);
1816         freeAsmop(NULL,aop,ic,TRUE);
1817
1818     } 
1819 }
1820
1821 /*-----------------------------------------------------------------*/
1822 /* saverbank - saves an entire register bank on the stack          */
1823 /*-----------------------------------------------------------------*/
1824 static void saverbank (int bank, iCode *ic, bool pushPsw)
1825 {
1826     int i;
1827     asmop *aop ;
1828     regs *r = NULL;
1829
1830     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1831     if (options.useXstack) {
1832
1833         aop = newAsmop(0);
1834         r = getFreePtr(ic,&aop,FALSE);  
1835         emitcode("mov","%s,_spx",r->name);
1836
1837     }
1838
1839     for (i = 0 ; i < pic14_nRegs ;i++) {
1840         if (options.useXstack) {
1841             emitcode("inc","%s",r->name);
1842             emitcode("mov","a,(%s+%d)",
1843                      regspic14[i].base,8*bank+regspic14[i].offset);
1844             emitcode("movx","@%s,a",r->name);           
1845         } else 
1846             emitcode("push","(%s+%d)",
1847                      regspic14[i].base,8*bank+regspic14[i].offset);
1848     }
1849     
1850     if (pushPsw) {
1851         if (options.useXstack) {
1852             emitcode("mov","a,psw");
1853             emitcode("movx","@%s,a",r->name);   
1854             emitcode("inc","%s",r->name);
1855             emitcode("mov","_spx,%s",r->name);       
1856             freeAsmop (NULL,aop,ic,TRUE);
1857             
1858         } else
1859             emitcode("push","psw");
1860         
1861         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1862     }
1863     ic->bankSaved = 1;
1864
1865 }
1866
1867 /*-----------------------------------------------------------------*/
1868 /* genCall - generates a call statement                            */
1869 /*-----------------------------------------------------------------*/
1870 static void genCall (iCode *ic)
1871 {
1872     sym_link *detype;   
1873
1874     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1875
1876     /* if caller saves & we have not saved then */
1877     if (!ic->regsSaved)
1878         saveRegisters(ic);
1879
1880     /* if we are calling a function that is not using
1881     the same register bank then we need to save the
1882     destination registers on the stack */
1883     detype = getSpec(operandType(IC_LEFT(ic)));
1884     if (detype        && 
1885         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1886         IS_ISR(currFunc->etype) &&
1887         !ic->bankSaved) 
1888
1889         saverbank(SPEC_BANK(detype),ic,TRUE);
1890
1891     /* if send set is not empty the assign */
1892     if (_G.sendSet) {
1893         iCode *sic ;
1894
1895         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1896              sic = setNextItem(_G.sendSet)) {
1897             int size, offset = 0;
1898
1899             aopOp(IC_LEFT(sic),sic,FALSE);
1900             size = AOP_SIZE(IC_LEFT(sic));
1901             while (size--) {
1902                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1903                                 FALSE,FALSE);
1904                 DEBUGemitcode(";","%d",__LINE__);
1905
1906                 if (strcmp(l,fReturn[offset])) {
1907
1908                   if ( (AOP(IC_LEFT(sic))->type) == AOP_IMMD)
1909                     emitcode("movlw","%s",l);
1910                   else
1911                     emitcode("movf","%s,w",l);
1912                   emitcode("movwf","%s",fReturn[offset]);
1913                 }
1914                 offset++;
1915             }
1916             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1917         }
1918         _G.sendSet = NULL;
1919     }
1920     /* make the call */
1921     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1922                            OP_SYMBOL(IC_LEFT(ic))->rname :
1923                            OP_SYMBOL(IC_LEFT(ic))->name));
1924
1925     /* if we need assign a result value */
1926     if ((IS_ITEMP(IC_RESULT(ic)) && 
1927          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1928           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1929         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1930
1931         _G.accInUse++;
1932         aopOp(IC_RESULT(ic),ic,FALSE);
1933         _G.accInUse--;
1934
1935         assignResultValue(IC_RESULT(ic));
1936                 
1937         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1938     }
1939
1940     /* adjust the stack for parameters if 
1941     required */
1942     if (IC_LEFT(ic)->parmBytes) {
1943         int i;
1944         if (IC_LEFT(ic)->parmBytes > 3) {
1945             emitcode("mov","a,%s",spname);
1946             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1947             emitcode("mov","%s,a",spname);
1948         } else 
1949             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1950                 emitcode("dec","%s",spname);
1951
1952     }
1953
1954     /* if register bank was saved then pop them */
1955     if (ic->bankSaved)
1956         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1957
1958     /* if we hade saved some registers then unsave them */
1959     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1960         unsaveRegisters (ic);
1961
1962
1963 }
1964
1965 /*-----------------------------------------------------------------*/
1966 /* genPcall - generates a call by pointer statement                */
1967 /*-----------------------------------------------------------------*/
1968 static void genPcall (iCode *ic)
1969 {
1970     sym_link *detype;
1971     symbol *rlbl = newiTempLabel(NULL);
1972
1973
1974     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1975     /* if caller saves & we have not saved then */
1976     if (!ic->regsSaved)
1977         saveRegisters(ic);
1978
1979     /* if we are calling a function that is not using
1980     the same register bank then we need to save the
1981     destination registers on the stack */
1982     detype = getSpec(operandType(IC_LEFT(ic)));
1983     if (detype        && 
1984         IS_ISR(currFunc->etype) &&
1985         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1986         saverbank(SPEC_BANK(detype),ic,TRUE);
1987
1988
1989     /* push the return address on to the stack */
1990     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
1991     emitcode("push","acc");    
1992     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
1993     emitcode("push","acc");
1994     
1995     if (options.model == MODEL_FLAT24)
1996     {
1997         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
1998         emitcode("push","acc");    
1999     }
2000
2001     /* now push the calling address */
2002     aopOp(IC_LEFT(ic),ic,FALSE);
2003
2004     pushSide(IC_LEFT(ic), FPTRSIZE);
2005
2006     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2007
2008     /* if send set is not empty the assign */
2009     if (_G.sendSet) {
2010         iCode *sic ;
2011
2012         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2013              sic = setNextItem(_G.sendSet)) {
2014             int size, offset = 0;
2015             aopOp(IC_LEFT(sic),sic,FALSE);
2016             size = AOP_SIZE(IC_LEFT(sic));
2017             while (size--) {
2018                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2019                                 FALSE,FALSE);
2020                 if (strcmp(l,fReturn[offset]))
2021                     emitcode("mov","%s,%s",
2022                              fReturn[offset],
2023                              l);
2024                 offset++;
2025             }
2026             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2027         }
2028         _G.sendSet = NULL;
2029     }
2030
2031     emitcode("ret","");
2032     emitcode("","%05d_DS_:",(rlbl->key+100));
2033
2034
2035     /* if we need assign a result value */
2036     if ((IS_ITEMP(IC_RESULT(ic)) &&
2037          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2038           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2039         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2040
2041         _G.accInUse++;
2042         aopOp(IC_RESULT(ic),ic,FALSE);
2043         _G.accInUse--;
2044         
2045         assignResultValue(IC_RESULT(ic));
2046
2047         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2048     }
2049
2050     /* adjust the stack for parameters if 
2051     required */
2052     if (IC_LEFT(ic)->parmBytes) {
2053         int i;
2054         if (IC_LEFT(ic)->parmBytes > 3) {
2055             emitcode("mov","a,%s",spname);
2056             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2057             emitcode("mov","%s,a",spname);
2058         } else 
2059             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2060                 emitcode("dec","%s",spname);
2061
2062     }
2063
2064     /* if register bank was saved then unsave them */
2065     if (detype        && 
2066         (SPEC_BANK(currFunc->etype) != 
2067          SPEC_BANK(detype)))
2068         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2069
2070     /* if we hade saved some registers then
2071     unsave them */
2072     if (ic->regsSaved)
2073         unsaveRegisters (ic);
2074
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* resultRemat - result  is rematerializable                       */
2079 /*-----------------------------------------------------------------*/
2080 static int resultRemat (iCode *ic)
2081 {
2082     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2083     if (SKIP_IC(ic) || ic->op == IFX)
2084         return 0;
2085
2086     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2087         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2088         if (sym->remat && !POINTER_SET(ic)) 
2089             return 1;
2090     }
2091
2092     return 0;
2093 }
2094
2095 #if defined(__BORLANDC__) || defined(_MSC_VER)
2096 #define STRCASECMP stricmp
2097 #else
2098 #define STRCASECMP strcasecmp
2099 #endif
2100
2101 /*-----------------------------------------------------------------*/
2102 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2103 /*-----------------------------------------------------------------*/
2104 static bool inExcludeList(char *s)
2105 {
2106     int i =0;
2107     
2108     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109     if (options.excludeRegs[i] &&
2110     STRCASECMP(options.excludeRegs[i],"none") == 0)
2111         return FALSE ;
2112
2113     for ( i = 0 ; options.excludeRegs[i]; i++) {
2114         if (options.excludeRegs[i] &&
2115         STRCASECMP(s,options.excludeRegs[i]) == 0)
2116             return TRUE;
2117     }
2118     return FALSE ;
2119 }
2120
2121 /*-----------------------------------------------------------------*/
2122 /* genFunction - generated code for function entry                 */
2123 /*-----------------------------------------------------------------*/
2124 static void genFunction (iCode *ic)
2125 {
2126     symbol *sym;
2127     sym_link *fetype;
2128
2129     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2130     labelOffset += FUNCTION_LABEL_INC;
2131
2132     _G.nRegsSaved = 0;
2133     /* create the function header */
2134     emitcode(";","-----------------------------------------");
2135     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2136     emitcode(";","-----------------------------------------");
2137
2138     emitcode("","%s:",sym->rname);
2139     fetype = getSpec(operandType(IC_LEFT(ic)));
2140
2141     /* if critical function then turn interrupts off */
2142     if (SPEC_CRTCL(fetype))
2143         emitcode("clr","ea");
2144
2145     /* here we need to generate the equates for the
2146        register bank if required */
2147 #if 0
2148     if (SPEC_BANK(fetype) != rbank) {
2149         int i ;
2150
2151         rbank = SPEC_BANK(fetype);
2152         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2153             if (strcmp(regspic14[i].base,"0") == 0)
2154                 emitcode("","%s = 0x%02x",
2155                          regspic14[i].dname,
2156                          8*rbank+regspic14[i].offset);
2157             else
2158                 emitcode ("","%s = %s + 0x%02x",
2159                           regspic14[i].dname,
2160                           regspic14[i].base,
2161                           8*rbank+regspic14[i].offset);
2162         }
2163     }
2164 #endif
2165
2166     /* if this is an interrupt service routine then
2167     save acc, b, dpl, dph  */
2168     if (IS_ISR(sym->etype)) {
2169         
2170         if (!inExcludeList("acc"))          
2171             emitcode ("push","acc");    
2172         if (!inExcludeList("b"))
2173             emitcode ("push","b");
2174         if (!inExcludeList("dpl"))
2175             emitcode ("push","dpl");
2176         if (!inExcludeList("dph"))
2177             emitcode ("push","dph");
2178         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2179         {
2180             emitcode ("push", "dpx");
2181             /* Make sure we're using standard DPTR */
2182             emitcode ("push", "dps");
2183             emitcode ("mov", "dps, #0x00");
2184             if (options.stack10bit)
2185             {   
2186                 /* This ISR could conceivably use DPTR2. Better save it. */
2187                 emitcode ("push", "dpl1");
2188                 emitcode ("push", "dph1");
2189                 emitcode ("push", "dpx1");
2190             }
2191         }
2192         /* if this isr has no bank i.e. is going to
2193            run with bank 0 , then we need to save more
2194            registers :-) */
2195         if (!SPEC_BANK(sym->etype)) {
2196
2197             /* if this function does not call any other
2198                function then we can be economical and
2199                save only those registers that are used */
2200             if (! sym->hasFcall) {
2201                 int i;
2202
2203                 /* if any registers used */
2204                 if (sym->regsUsed) {
2205                     /* save the registers used */
2206                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2207                         if (bitVectBitValue(sym->regsUsed,i) ||
2208                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2209                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2210                     }
2211                 }
2212                 
2213             } else {
2214                 /* this function has  a function call cannot
2215                    determines register usage so we will have the
2216                    entire bank */
2217                 saverbank(0,ic,FALSE);
2218             }       
2219         }
2220     } else {
2221         /* if callee-save to be used for this function
2222            then save the registers being used in this function */
2223         if (sym->calleeSave) {
2224             int i;
2225             
2226             /* if any registers used */
2227             if (sym->regsUsed) {
2228                 /* save the registers used */
2229                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230                     if (bitVectBitValue(sym->regsUsed,i) ||
2231                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2232                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2233                         _G.nRegsSaved++;
2234                     }
2235                 }
2236             }
2237         }
2238     }
2239
2240     /* set the register bank to the desired value */
2241     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2242         emitcode("push","psw");
2243         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2244     }
2245
2246     if (IS_RENT(sym->etype) || options.stackAuto) {
2247
2248         if (options.useXstack) {
2249             emitcode("mov","r0,%s",spname);
2250             emitcode("mov","a,_bp");
2251             emitcode("movx","@r0,a");
2252             emitcode("inc","%s",spname);
2253         }
2254         else
2255         {
2256             /* set up the stack */
2257             emitcode ("push","_bp");     /* save the callers stack  */
2258         }
2259         emitcode ("mov","_bp,%s",spname);
2260     }
2261
2262     /* adjust the stack for the function */
2263     if (sym->stack) {
2264
2265         int i = sym->stack;
2266         if (i > 256 ) 
2267             werror(W_STACK_OVERFLOW,sym->name);
2268
2269         if (i > 3 && sym->recvSize < 4) {              
2270
2271             emitcode ("mov","a,sp");
2272             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2273             emitcode ("mov","sp,a");
2274            
2275         }
2276         else
2277             while(i--)
2278                 emitcode("inc","sp");
2279     }
2280
2281      if (sym->xstack) {
2282
2283         emitcode ("mov","a,_spx");
2284         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2285         emitcode ("mov","_spx,a");
2286     }    
2287
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* genEndFunction - generates epilogue for functions               */
2292 /*-----------------------------------------------------------------*/
2293 static void genEndFunction (iCode *ic)
2294 {
2295     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2296
2297     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2298
2299     if (IS_RENT(sym->etype) || options.stackAuto)
2300     {
2301         emitcode ("mov","%s,_bp",spname);
2302     }
2303
2304     /* if use external stack but some variables were
2305     added to the local stack then decrement the
2306     local stack */
2307     if (options.useXstack && sym->stack) {      
2308         emitcode("mov","a,sp");
2309         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2310         emitcode("mov","sp,a");
2311     }
2312
2313
2314     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2315         if (options.useXstack) {
2316             emitcode("mov","r0,%s",spname);
2317             emitcode("movx","a,@r0");
2318             emitcode("mov","_bp,a");
2319             emitcode("dec","%s",spname);
2320         }
2321         else
2322         {
2323             emitcode ("pop","_bp");
2324         }
2325     }
2326
2327     /* restore the register bank  */    
2328     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2329         emitcode ("pop","psw");
2330
2331     if (IS_ISR(sym->etype)) {
2332
2333         /* now we need to restore the registers */
2334         /* if this isr has no bank i.e. is going to
2335            run with bank 0 , then we need to save more
2336            registers :-) */
2337         if (!SPEC_BANK(sym->etype)) {
2338             
2339             /* if this function does not call any other
2340                function then we can be economical and
2341                save only those registers that are used */
2342             if (! sym->hasFcall) {
2343                 int i;
2344                 
2345                 /* if any registers used */
2346                 if (sym->regsUsed) {
2347                     /* save the registers used */
2348                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2349                         if (bitVectBitValue(sym->regsUsed,i) ||
2350                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2351                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2352                     }
2353                 }
2354                 
2355             } else {
2356                 /* this function has  a function call cannot
2357                    determines register usage so we will have the
2358                    entire bank */
2359                 unsaverbank(0,ic,FALSE);
2360             }       
2361         }
2362
2363         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2364         {
2365             if (options.stack10bit)
2366             {
2367                 emitcode ("pop", "dpx1");
2368                 emitcode ("pop", "dph1");
2369                 emitcode ("pop", "dpl1");
2370             }   
2371             emitcode ("pop", "dps");
2372             emitcode ("pop", "dpx");
2373         }
2374         if (!inExcludeList("dph"))
2375             emitcode ("pop","dph");
2376         if (!inExcludeList("dpl"))
2377             emitcode ("pop","dpl");
2378         if (!inExcludeList("b"))
2379             emitcode ("pop","b");
2380         if (!inExcludeList("acc"))
2381             emitcode ("pop","acc");
2382
2383         if (SPEC_CRTCL(sym->etype))
2384             emitcode("setb","ea");
2385
2386         /* if debug then send end of function */
2387 /*      if (options.debug && currFunc) { */
2388         if (currFunc) {
2389             _G.debugLine = 1;
2390             emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2391                      ic->filename,currFunc->lastLine,
2392                      ic->level,ic->block); 
2393             if (IS_STATIC(currFunc->etype))         
2394                 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name); 
2395             else
2396                 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2397             _G.debugLine = 0;
2398         }
2399         
2400         emitcode ("reti","");
2401     }
2402     else {
2403         if (SPEC_CRTCL(sym->etype))
2404             emitcode("setb","ea");
2405         
2406         if (sym->calleeSave) {
2407             int i;
2408             
2409             /* if any registers used */
2410             if (sym->regsUsed) {
2411                 /* save the registers used */
2412                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2413                     if (bitVectBitValue(sym->regsUsed,i) ||
2414                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2415                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2416                 }
2417             }
2418             
2419         }
2420
2421         /* if debug then send end of function */
2422         if (currFunc) {
2423             _G.debugLine = 1;
2424             emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2425                      ic->filename,currFunc->lastLine,
2426                      ic->level,ic->block); 
2427             if (IS_STATIC(currFunc->etype))         
2428                 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name); 
2429             else
2430                 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2431             _G.debugLine = 0;
2432         }
2433
2434         emitcode ("return","");
2435     }
2436
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* genRet - generate code for return statement                     */
2441 /*-----------------------------------------------------------------*/
2442 static void genRet (iCode *ic)
2443 {
2444     int size,offset = 0 , pushed = 0;
2445     
2446     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2447     /* if we have no return value then
2448        just generate the "ret" */
2449     if (!IC_LEFT(ic)) 
2450         goto jumpret;       
2451     
2452     /* we have something to return then
2453        move the return value into place */
2454     aopOp(IC_LEFT(ic),ic,FALSE);
2455     size = AOP_SIZE(IC_LEFT(ic));
2456     
2457     while (size--) {
2458             char *l ;
2459             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2460                     /* #NOCHANGE */
2461                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2462                            FALSE,TRUE);
2463                     emitcode("push","%s",l);
2464                     pushed++;
2465             } else {
2466                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2467                                FALSE,FALSE);
2468                     if (strcmp(fReturn[offset],l)) {
2469                       if ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
2470                         emitcode("movlw","%s",l);
2471                       else
2472                         emitcode("movf","%s,w",l);
2473                       emitcode("movwf","%s",fReturn[offset++]);
2474                     }
2475             }
2476     }    
2477
2478     if (pushed) {
2479         while(pushed) {
2480             pushed--;
2481             if (strcmp(fReturn[pushed],"a"))
2482                 emitcode("pop",fReturn[pushed]);
2483             else
2484                 emitcode("pop","acc");
2485         }
2486     }
2487     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2488     
2489  jumpret:
2490         /* generate a jump to the return label
2491            if the next is not the return statement */
2492     if (!(ic->next && ic->next->op == LABEL &&
2493           IC_LABEL(ic->next) == returnLabel))
2494         
2495         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2496     
2497 }
2498
2499 /*-----------------------------------------------------------------*/
2500 /* genLabel - generates a label                                    */
2501 /*-----------------------------------------------------------------*/
2502 static void genLabel (iCode *ic)
2503 {
2504     /* special case never generate */
2505     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2506     if (IC_LABEL(ic) == entryLabel)
2507         return ;
2508
2509     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2510 }
2511
2512 /*-----------------------------------------------------------------*/
2513 /* genGoto - generates a goto                                      */
2514 /*-----------------------------------------------------------------*/
2515 //tsd
2516 static void genGoto (iCode *ic)
2517 {
2518     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2519 }
2520
2521 /*-----------------------------------------------------------------*/
2522 /* findLabelBackwards: walks back through the iCode chain looking  */
2523 /* for the given label. Returns number of iCode instructions       */
2524 /* between that label and given ic.                                */
2525 /* Returns zero if label not found.                                */
2526 /*-----------------------------------------------------------------*/
2527 #if 0
2528 static int findLabelBackwards(iCode *ic, int key)
2529 {
2530     int count = 0;
2531     
2532     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2533     while (ic->prev)
2534     {
2535         ic = ic->prev;
2536         count++;
2537         
2538         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2539         {
2540             /* printf("findLabelBackwards = %d\n", count); */
2541             return count;
2542         }
2543     }
2544     
2545     return 0;
2546 }
2547 #endif
2548 /*-----------------------------------------------------------------*/
2549 /* genPlusIncr :- does addition with increment if possible         */
2550 /*-----------------------------------------------------------------*/
2551 static bool genPlusIncr (iCode *ic)
2552 {
2553     unsigned int icount ;
2554     unsigned int size = getDataSize(IC_RESULT(ic));
2555
2556     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557     DEBUGemitcode ("; ","result %d, left %d, right %d",
2558                    AOP_TYPE(IC_RESULT(ic)),
2559                    AOP_TYPE(IC_LEFT(ic)),
2560                    AOP_TYPE(IC_RIGHT(ic)));
2561
2562     /* will try to generate an increment */
2563     /* if the right side is not a literal 
2564        we cannot */
2565     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2566         return FALSE ;
2567     
2568     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2569     /* if the literal value of the right hand side
2570        is greater than 1 then it is faster to add */
2571     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2572         return FALSE ;
2573     
2574     /* if increment 16 bits in register */
2575     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2576         (icount == 1)) {
2577
2578       int offset = MSB16;
2579
2580       emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2581
2582       while(--size) {
2583         emitSKPNZ;
2584         emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2585       }
2586
2587       return TRUE;
2588     }
2589     
2590     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2591     /* if left is in accumulator  - probably a bit operation*/
2592     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2593         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2594       
2595       emitcode("bcf","(%s >> 3), (%s & 7)",
2596                AOP(IC_RESULT(ic))->aopu.aop_dir,
2597                AOP(IC_RESULT(ic))->aopu.aop_dir);
2598       if(icount)
2599         emitcode("xorlw","1");
2600       else
2601         emitcode("andlw","1");
2602
2603       emitSKPZ;
2604       emitcode("bsf","(%s >> 3), (%s & 7)",
2605                AOP(IC_RESULT(ic))->aopu.aop_dir,
2606                AOP(IC_RESULT(ic))->aopu.aop_dir);
2607
2608       return TRUE;
2609     }
2610
2611
2612
2613     /* if the sizes are greater than 1 then we cannot */
2614     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2615         AOP_SIZE(IC_LEFT(ic)) > 1   )
2616         return FALSE ;
2617     
2618     /* If we are incrementing the same register by two: */
2619
2620     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2621         
2622       while (icount--) 
2623         emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2624         
2625       return TRUE ;
2626     }
2627     
2628     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2629                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2630                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2631     return FALSE ;
2632 }
2633
2634 /*-----------------------------------------------------------------*/
2635 /* outBitAcc - output a bit in acc                                 */
2636 /*-----------------------------------------------------------------*/
2637 static void outBitAcc(operand *result)
2638 {
2639     symbol *tlbl = newiTempLabel(NULL);
2640     /* if the result is a bit */
2641     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2642
2643     if (AOP_TYPE(result) == AOP_CRY){
2644         aopPut(AOP(result),"a",0);
2645     }
2646     else {
2647         emitcode("jz","%05d_DS_",tlbl->key+100);
2648         emitcode("mov","a,%s",one);
2649         emitcode("","%05d_DS_:",tlbl->key+100);
2650         outAcc(result);
2651     }
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* genPlusBits - generates code for addition of two bits           */
2656 /*-----------------------------------------------------------------*/
2657 static void genPlusBits (iCode *ic)
2658 {
2659
2660     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2661     /*
2662       The following block of code will add two bits. 
2663       Note that it'll even work if the destination is
2664       the carry (C in the status register).
2665       It won't work if the 'Z' bit is a source or destination.
2666     */
2667
2668     /* If the result is stored in the accumulator (w) */
2669     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2670         emitcode("movlw","(1 << (%s & 7))",
2671                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2672                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2673         emitcode("bcf","(%s >> 3), (%s & 7)",
2674                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2675                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2676         emitcode("btfsc","(%s >> 3), (%s & 7)",
2677                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2678                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2679         emitcode("xorwf","(%s >>3),f",
2680                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2681         emitcode("btfsc","(%s >> 3), (%s & 7)",
2682                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2683                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2684         emitcode("xorwf","(%s>>3),f",
2685                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2686     } else { 
2687
2688       emitcode("clrw","");
2689       emitcode("btfsc","(%s >> 3), (%s & 7)",
2690                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2691                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2692       emitcode("xorlw","1");
2693       emitcode("btfsc","(%s >> 3), (%s & 7)",
2694                AOP(IC_LEFT(ic))->aopu.aop_dir,
2695                AOP(IC_LEFT(ic))->aopu.aop_dir);
2696       emitcode("xorlw","1");
2697     }
2698
2699 }
2700
2701 #if 0
2702 /* This is the original version of this code.
2703  *
2704  * This is being kept around for reference, 
2705  * because I am not entirely sure I got it right...
2706  */
2707 static void adjustArithmeticResult(iCode *ic)
2708 {
2709     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2710         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2711         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2712         aopPut(AOP(IC_RESULT(ic)),
2713                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2714                2);
2715
2716     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2717         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2718         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2719         aopPut(AOP(IC_RESULT(ic)),
2720                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2721                2);
2722     
2723     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2724         AOP_SIZE(IC_LEFT(ic)) < 3    &&
2725         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
2726         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2727         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2728         char buffer[5];
2729         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2730         aopPut(AOP(IC_RESULT(ic)),buffer,2);
2731     }
2732 }
2733 //#else
2734 /* This is the pure and virtuous version of this code.
2735  * I'm pretty certain it's right, but not enough to toss the old 
2736  * code just yet...
2737  */
2738 static void adjustArithmeticResult(iCode *ic)
2739 {
2740     if (opIsGptr(IC_RESULT(ic)) &&
2741         opIsGptr(IC_LEFT(ic))   &&
2742         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2743     {
2744         aopPut(AOP(IC_RESULT(ic)),
2745                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2746                GPTRSIZE - 1);
2747     }
2748
2749     if (opIsGptr(IC_RESULT(ic)) &&
2750         opIsGptr(IC_RIGHT(ic))   &&
2751         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2752     {
2753         aopPut(AOP(IC_RESULT(ic)),
2754                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2755                GPTRSIZE - 1);
2756     }
2757
2758     if (opIsGptr(IC_RESULT(ic))            &&
2759         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2760         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2761          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2762          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2763          char buffer[5];
2764          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2765          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2766      }
2767 }
2768 #endif
2769
2770 /*-----------------------------------------------------------------*/
2771 /* genPlus - generates code for addition                           */
2772 /*-----------------------------------------------------------------*/
2773 static void genPlus (iCode *ic)
2774 {
2775     int size, offset = 0;
2776
2777     /* special cases :- */
2778     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2779
2780     aopOp (IC_LEFT(ic),ic,FALSE);
2781     aopOp (IC_RIGHT(ic),ic,FALSE);
2782     aopOp (IC_RESULT(ic),ic,TRUE);
2783
2784     /* if literal, literal on the right or
2785        if left requires ACC or right is already
2786        in ACC */
2787
2788     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2789         operand *t = IC_RIGHT(ic);
2790         IC_RIGHT(ic) = IC_LEFT(ic);
2791         IC_LEFT(ic) = t;
2792     }
2793
2794     /* if both left & right are in bit space */
2795     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2796         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2797         genPlusBits (ic);
2798         goto release ;
2799     }
2800
2801     /* if left in bit space & right literal */
2802     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2803         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2804         /* if result in bit space */
2805         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2806           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
2807             emitcode("movlw","(1 << (%s & 7)) ;%d",AOP(IC_RESULT(ic))->aopu.aop_dir,__LINE__);
2808             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2809               emitcode("btfsc","(%s >> 3), (%s & 7)",
2810                        AOP(IC_LEFT(ic))->aopu.aop_dir,
2811                        AOP(IC_LEFT(ic))->aopu.aop_dir);
2812
2813             emitcode("xorwf","(%s>>3),f",AOP(IC_RESULT(ic))->aopu.aop_dir);
2814           }
2815         } else {
2816             size = getDataSize(IC_RESULT(ic));
2817             while (size--) {
2818                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
2819                 emitcode("addc","a,#00  ;%d",__LINE__);
2820                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2821             }
2822         }
2823         goto release ;
2824     }
2825
2826     /* if I can do an increment instead
2827     of add then GOOD for ME */
2828     if (genPlusIncr (ic) == TRUE)
2829         goto release;   
2830
2831     size = getDataSize(IC_RESULT(ic));
2832
2833     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2834       /* Add a literal to something else */
2835       bool know_W=0;
2836       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2837       unsigned l1=0;
2838
2839       offset = 0;
2840       DEBUGemitcode(";","adding lit to something. size %d",size);
2841       while(size--){
2842
2843       DEBUGemitcode(";","size %d",size);
2844
2845         switch (lit & 0xff) {
2846         case 0:
2847           break;
2848         case 1:
2849           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2850             emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2851           else {
2852             know_W = 0;
2853             emitcode("incf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2854             emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2855           }
2856           break;
2857         case 0xff:
2858           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2859             emitcode("decf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2860           else {
2861             know_W = 0;
2862             emitcode("decf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2863             emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2864           }
2865           break;
2866         default:
2867           if( !know_W || ( (lit&0xff) != l1)  ) {
2868             know_W = 1;
2869             emitcode("movlw","0x%x", lit&0xff);
2870           }
2871           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2872             emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2873           else {
2874             know_W = 0;
2875             emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2876             emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2877             if(size) {
2878               emitSKPNC;
2879               emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
2880             }
2881           }
2882         }
2883
2884         l1 = lit & 0xff;
2885         lit >>= 8;
2886         offset++;
2887       }
2888
2889     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2890
2891       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2892       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2893       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2894
2895       /* here we are adding a bit to a char or int */
2896       if(size == 1) {
2897         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2898
2899           emitcode("btfsc","(%s >> 3), (%s & 7)",
2900                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
2901                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
2902           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2903         } else {
2904
2905           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2906             emitcode("btfsc","(%s >> 3), (%s & 7)",
2907                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
2908                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
2909             emitcode(" xorlw","1");
2910           } else {
2911             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2912             emitcode("btfsc","(%s >> 3), (%s & 7)",
2913                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
2914                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
2915             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2916           }
2917           
2918           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
2919             
2920             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2921               emitcode("andlw","1");
2922               emitcode("bcf","(%s >> 3), (%s & 7)",
2923                        AOP(IC_RESULT(ic))->aopu.aop_dir,
2924                        AOP(IC_RESULT(ic))->aopu.aop_dir);
2925               emitSKPZ;
2926               emitcode("bsf","(%s >> 3), (%s & 7)",
2927                        AOP(IC_RESULT(ic))->aopu.aop_dir,
2928                        AOP(IC_RESULT(ic))->aopu.aop_dir);
2929
2930             } else
2931                 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2932           }
2933         }
2934
2935       } else {
2936         int offset = 1;
2937
2938         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2939           emitcode("clrz","");
2940
2941           emitcode("btfsc","(%s >> 3), (%s & 7)",
2942                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
2943                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
2944           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2945
2946         } else {
2947
2948           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2949           emitcode("btfsc","(%s >> 3), (%s & 7)",
2950                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
2951                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
2952           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2953           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2954
2955         }
2956
2957         while(--size){
2958           emitSKPZ;
2959           emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2960         }
2961
2962       }
2963       
2964     } else {
2965     
2966       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2967         emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2968         emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2969       } else {
2970         //if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2971         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2972           emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2973           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2974             emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2975         } else {
2976
2977         emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2978
2979           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2980               emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2981           else {
2982             emitcode(";ic_left type","%d",AOP_TYPE(IC_LEFT(ic)));
2983             if(AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) {
2984               emitcode("addlw","%s", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2985             } else {
2986               emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2987               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2988                 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2989             }
2990           }
2991         }
2992       }
2993
2994       offset = 1;
2995       size--;
2996
2997       while(size--){
2998         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2999           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3000           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3001         }
3002         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3003         emitSKPNC;
3004         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3005         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3006         
3007       }
3008
3009     }
3010
3011     //adjustArithmeticResult(ic);
3012
3013  release:
3014       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3015       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3016       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3017 }
3018
3019 /*-----------------------------------------------------------------*/
3020 /* genMinusDec :- does subtraction with decrement if possible     */
3021 /*-----------------------------------------------------------------*/
3022 static bool genMinusDec (iCode *ic)
3023 {
3024     unsigned int icount ;
3025     unsigned int size = getDataSize(IC_RESULT(ic));
3026
3027     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3028     /* will try to generate an increment */
3029     /* if the right side is not a literal 
3030     we cannot */
3031     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3032         return FALSE ;
3033
3034     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3035
3036     /* if the literal value of the right hand side
3037     is greater than 4 then it is not worth it */
3038     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3039         return FALSE ;
3040
3041     /* if decrement 16 bits in register */
3042     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3043         (size > 1) &&
3044         (icount == 1)) {
3045
3046       if(size == 2) { 
3047         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3048         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3049         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3050       } else {
3051         /* size is 3 or 4 */
3052         emitcode("movlw","0xff");
3053         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3054
3055         emitSKPNC;
3056         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3057         emitSKPNC;
3058         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3059
3060         if(size > 3) {
3061           emitcode("skpnc","");
3062           emitSKPNC;
3063           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3064         }
3065
3066       }
3067
3068       return TRUE;
3069
3070     }
3071
3072     /* if the sizes are greater than 1 then we cannot */
3073     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3074         AOP_SIZE(IC_LEFT(ic)) > 1   )
3075         return FALSE ;
3076
3077     /* we can if the aops of the left & result match or
3078     if they are in registers and the registers are the
3079     same */
3080     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3081
3082         while (icount--) 
3083             emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3084
3085         return TRUE ;
3086     }
3087
3088     DEBUGemitcode ("; returning"," result=%s, left=%s",
3089                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3090                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3091     if(size==1) {
3092       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3093       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3094       return TRUE;
3095     }
3096
3097     return FALSE ;
3098 }
3099
3100 /*-----------------------------------------------------------------*/
3101 /* addSign - complete with sign                                    */
3102 /*-----------------------------------------------------------------*/
3103 static void addSign(operand *result, int offset, int sign)
3104 {
3105     int size = (getDataSize(result) - offset);
3106     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3107     if(size > 0){
3108         if(sign){
3109             emitcode("rlc","a");
3110             emitcode("subb","a,acc");
3111             while(size--)
3112                 aopPut(AOP(result),"a",offset++); 
3113         } else
3114             while(size--)
3115                 aopPut(AOP(result),zero,offset++);
3116     }
3117 }
3118
3119 /*-----------------------------------------------------------------*/
3120 /* genMinusBits - generates code for subtraction  of two bits      */
3121 /*-----------------------------------------------------------------*/
3122 static void genMinusBits (iCode *ic)
3123 {
3124     symbol *lbl = newiTempLabel(NULL);
3125     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3126     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3127         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3128         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3129         emitcode("cpl","c");
3130         emitcode("","%05d_DS_:",(lbl->key+100));
3131         outBitC(IC_RESULT(ic));
3132     }
3133     else{
3134         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3135         emitcode("subb","a,acc");
3136         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3137         emitcode("inc","a");
3138         emitcode("","%05d_DS_:",(lbl->key+100));
3139         aopPut(AOP(IC_RESULT(ic)),"a",0);
3140         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3141     }
3142 }
3143
3144 /*-----------------------------------------------------------------*/
3145 /* genMinus - generates code for subtraction                       */
3146 /*-----------------------------------------------------------------*/
3147 static void genMinus (iCode *ic)
3148 {
3149     int size, offset = 0;
3150     unsigned long lit = 0L;
3151
3152     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3153     aopOp (IC_LEFT(ic),ic,FALSE);
3154     aopOp (IC_RIGHT(ic),ic,FALSE);
3155     aopOp (IC_RESULT(ic),ic,TRUE);
3156
3157     /* special cases :- */
3158     /* if both left & right are in bit space */
3159     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3160         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3161         genMinusBits (ic);
3162         goto release ;
3163     }
3164
3165     /* if I can do an decrement instead
3166     of subtract then GOOD for ME */
3167     if (genMinusDec (ic) == TRUE)
3168         goto release;   
3169
3170     size = getDataSize(IC_RESULT(ic));   
3171
3172     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3173       /* Add a literal to something else */
3174
3175       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3176       lit = - (long)lit;
3177
3178       /* add the first byte: */
3179       emitcode("movlw","0x%x", lit & 0xff);
3180       emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3181
3182       offset = 1;
3183       size--;
3184
3185       while(size--){
3186
3187         emitcode("rlf","_known_zero,w");
3188         emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3189
3190         lit >>= 8;
3191         if(lit & 0xff) {
3192           emitcode("movlw","0x%x", lit & 0xff);
3193           emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3194           
3195         }
3196         offset++;
3197       }
3198
3199     } else {
3200
3201       emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3202       emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3203
3204       offset = 1;
3205       size--;
3206
3207       while(size--){
3208         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3209         emitSKPNC;
3210         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3211         emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3212         
3213       }
3214
3215     }
3216
3217
3218     //    adjustArithmeticResult(ic);
3219         
3220 release:
3221     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3222     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3223     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3224 }
3225
3226
3227 /*-----------------------------------------------------------------*/
3228 /* genMultbits :- multiplication of bits                           */
3229 /*-----------------------------------------------------------------*/
3230 static void genMultbits (operand *left, 
3231                          operand *right, 
3232                          operand *result)
3233 {
3234     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3235
3236     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3237     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3238     outBitC(result);
3239 }
3240
3241
3242 /*-----------------------------------------------------------------*/
3243 /* genMultOneByte : 8 bit multiplication & division                */
3244 /*-----------------------------------------------------------------*/
3245 static void genMultOneByte (operand *left,
3246                             operand *right,
3247                             operand *result)
3248 {
3249     sym_link *opetype = operandType(result);
3250     char *l ;
3251     symbol *lbl ;
3252     int size,offset;
3253
3254     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3255     /* (if two literals, the value is computed before) */
3256     /* if one literal, literal on the right */
3257     if (AOP_TYPE(left) == AOP_LIT){
3258         operand *t = right;
3259         right = left;
3260         left = t;
3261     }
3262
3263     size = AOP_SIZE(result);
3264     /* signed or unsigned */
3265     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3266     l = aopGet(AOP(left),0,FALSE,FALSE);
3267     MOVA(l);       
3268     emitcode("mul","ab");
3269     /* if result size = 1, mul signed = mul unsigned */
3270     aopPut(AOP(result),"a",0);
3271     if (size > 1){
3272         if (SPEC_USIGN(opetype)){
3273             aopPut(AOP(result),"b",1);
3274             if (size > 2)
3275                 /* for filling the MSBs */
3276                 emitcode("clr","a");
3277         }
3278         else{
3279             emitcode("mov","a,b");
3280
3281             /* adjust the MSB if left or right neg */
3282
3283             /* if one literal */
3284             if (AOP_TYPE(right) == AOP_LIT){
3285                 /* AND literal negative */
3286                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3287                     /* adjust MSB (c==0 after mul) */
3288                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3289                 }
3290             }
3291             else{
3292                 lbl = newiTempLabel(NULL);
3293                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3294                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3295                 emitcode("","%05d_DS_:",(lbl->key+100));
3296                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3297                 lbl = newiTempLabel(NULL);      
3298                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3299                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3300                 emitcode("","%05d_DS_:",(lbl->key+100));
3301             }
3302
3303             lbl = newiTempLabel(NULL);
3304             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3305             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3306             emitcode("","%05d_DS_:",(lbl->key+100));
3307             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3308             lbl = newiTempLabel(NULL);      
3309             emitcode("jc","%05d_DS_",(lbl->key+100));          
3310             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3311             emitcode("","%05d_DS_:",(lbl->key+100));
3312
3313             aopPut(AOP(result),"a",1);
3314             if(size > 2){
3315                 /* get the sign */
3316                 emitcode("rlc","a");
3317                 emitcode("subb","a,acc");
3318             }
3319         }
3320         size -= 2;   
3321         offset = 2;
3322         if (size > 0)
3323             while (size--)
3324                 aopPut(AOP(result),"a",offset++);
3325     }
3326 }
3327
3328 /*-----------------------------------------------------------------*/
3329 /* genMult - generates code for multiplication                     */
3330 /*-----------------------------------------------------------------*/
3331 static void genMult (iCode *ic)
3332 {
3333     operand *left = IC_LEFT(ic);
3334     operand *right = IC_RIGHT(ic);
3335     operand *result= IC_RESULT(ic);   
3336
3337     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3338     /* assign the amsops */
3339     aopOp (left,ic,FALSE);
3340     aopOp (right,ic,FALSE);
3341     aopOp (result,ic,TRUE);
3342
3343     /* special cases first */
3344     /* both are bits */
3345     if (AOP_TYPE(left) == AOP_CRY &&
3346         AOP_TYPE(right)== AOP_CRY) {
3347         genMultbits(left,right,result);
3348         goto release ;
3349     }
3350
3351     /* if both are of size == 1 */
3352     if (AOP_SIZE(left) == 1 &&
3353         AOP_SIZE(right) == 1 ) {
3354         genMultOneByte(left,right,result);
3355         goto release ;
3356     }
3357
3358     /* should have been converted to function call */       
3359     assert(1) ;
3360
3361 release :
3362     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3363     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3364     freeAsmop(result,NULL,ic,TRUE); 
3365 }
3366
3367 /*-----------------------------------------------------------------*/
3368 /* genDivbits :- division of bits                                  */
3369 /*-----------------------------------------------------------------*/
3370 static void genDivbits (operand *left, 
3371                         operand *right, 
3372                         operand *result)
3373 {
3374
3375     char *l;
3376
3377     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3378     /* the result must be bit */    
3379     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3380     l = aopGet(AOP(left),0,FALSE,FALSE);
3381
3382     MOVA(l);    
3383
3384     emitcode("div","ab");
3385     emitcode("rrc","a");
3386     aopPut(AOP(result),"c",0);
3387 }
3388
3389 /*-----------------------------------------------------------------*/
3390 /* genDivOneByte : 8 bit division                                  */
3391 /*-----------------------------------------------------------------*/
3392 static void genDivOneByte (operand *left,
3393                            operand *right,
3394                            operand *result)
3395 {
3396     sym_link *opetype = operandType(result);
3397     char *l ;
3398     symbol *lbl ;
3399     int size,offset;
3400
3401     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3402     size = AOP_SIZE(result) - 1;
3403     offset = 1;
3404     /* signed or unsigned */
3405     if (SPEC_USIGN(opetype)) {
3406         /* unsigned is easy */
3407         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3408         l = aopGet(AOP(left),0,FALSE,FALSE);
3409         MOVA(l);        
3410         emitcode("div","ab");
3411         aopPut(AOP(result),"a",0);
3412         while (size--)
3413             aopPut(AOP(result),zero,offset++);
3414         return ;
3415     }
3416
3417     /* signed is a little bit more difficult */
3418
3419     /* save the signs of the operands */
3420     l = aopGet(AOP(left),0,FALSE,FALSE);    
3421     MOVA(l);    
3422     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3423     emitcode("push","acc"); /* save it on the stack */
3424
3425     /* now sign adjust for both left & right */
3426     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3427     MOVA(l);       
3428     lbl = newiTempLabel(NULL);
3429     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3430     emitcode("cpl","a");   
3431     emitcode("inc","a");
3432     emitcode("","%05d_DS_:",(lbl->key+100));
3433     emitcode("mov","b,a");
3434
3435     /* sign adjust left side */
3436     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3437     MOVA(l);
3438
3439     lbl = newiTempLabel(NULL);
3440     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3441     emitcode("cpl","a");
3442     emitcode("inc","a");
3443     emitcode("","%05d_DS_:",(lbl->key+100));
3444
3445     /* now the division */
3446     emitcode("div","ab");
3447     /* we are interested in the lower order
3448     only */
3449     emitcode("mov","b,a");
3450     lbl = newiTempLabel(NULL);
3451     emitcode("pop","acc");   
3452     /* if there was an over flow we don't 
3453     adjust the sign of the result */
3454     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3455     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3456     CLRC;
3457     emitcode("clr","a");
3458     emitcode("subb","a,b");
3459     emitcode("mov","b,a");
3460     emitcode("","%05d_DS_:",(lbl->key+100));
3461
3462     /* now we are done */
3463     aopPut(AOP(result),"b",0);
3464     if(size > 0){
3465         emitcode("mov","c,b.7");
3466         emitcode("subb","a,acc");   
3467     }
3468     while (size--)
3469         aopPut(AOP(result),"a",offset++);
3470
3471 }
3472
3473 /*-----------------------------------------------------------------*/
3474 /* genDiv - generates code for division                            */
3475 /*-----------------------------------------------------------------*/
3476 static void genDiv (iCode *ic)
3477 {
3478     operand *left = IC_LEFT(ic);
3479     operand *right = IC_RIGHT(ic);
3480     operand *result= IC_RESULT(ic);   
3481
3482     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3483     /* assign the amsops */
3484     aopOp (left,ic,FALSE);
3485     aopOp (right,ic,FALSE);
3486     aopOp (result,ic,TRUE);
3487
3488     /* special cases first */
3489     /* both are bits */
3490     if (AOP_TYPE(left) == AOP_CRY &&
3491         AOP_TYPE(right)== AOP_CRY) {
3492         genDivbits(left,right,result);
3493         goto release ;
3494     }
3495
3496     /* if both are of size == 1 */
3497     if (AOP_SIZE(left) == 1 &&
3498         AOP_SIZE(right) == 1 ) {
3499         genDivOneByte(left,right,result);
3500         goto release ;
3501     }
3502
3503     /* should have been converted to function call */
3504     assert(1);
3505 release :
3506     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508     freeAsmop(result,NULL,ic,TRUE); 
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* genModbits :- modulus of bits                                   */
3513 /*-----------------------------------------------------------------*/
3514 static void genModbits (operand *left, 
3515                         operand *right, 
3516                         operand *result)
3517 {
3518
3519     char *l;
3520
3521     /* the result must be bit */    
3522     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3523     l = aopGet(AOP(left),0,FALSE,FALSE);
3524
3525     MOVA(l);       
3526
3527     emitcode("div","ab");
3528     emitcode("mov","a,b");
3529     emitcode("rrc","a");
3530     aopPut(AOP(result),"c",0);
3531 }
3532
3533 /*-----------------------------------------------------------------*/
3534 /* genModOneByte : 8 bit modulus                                   */
3535 /*-----------------------------------------------------------------*/
3536 static void genModOneByte (operand *left,
3537                            operand *right,
3538                            operand *result)
3539 {
3540     sym_link *opetype = operandType(result);
3541     char *l ;
3542     symbol *lbl ;
3543
3544     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545     /* signed or unsigned */
3546     if (SPEC_USIGN(opetype)) {
3547         /* unsigned is easy */
3548         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3549         l = aopGet(AOP(left),0,FALSE,FALSE);
3550         MOVA(l);    
3551         emitcode("div","ab");
3552         aopPut(AOP(result),"b",0);
3553         return ;
3554     }
3555
3556     /* signed is a little bit more difficult */
3557
3558     /* save the signs of the operands */
3559     l = aopGet(AOP(left),0,FALSE,FALSE);    
3560     MOVA(l);
3561
3562     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3563     emitcode("push","acc"); /* save it on the stack */
3564
3565     /* now sign adjust for both left & right */
3566     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3567     MOVA(l);
3568
3569     lbl = newiTempLabel(NULL);
3570     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3571     emitcode("cpl","a");   
3572     emitcode("inc","a");
3573     emitcode("","%05d_DS_:",(lbl->key+100));
3574     emitcode("mov","b,a"); 
3575
3576     /* sign adjust left side */
3577     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3578     MOVA(l);
3579
3580     lbl = newiTempLabel(NULL);
3581     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3582     emitcode("cpl","a");   
3583     emitcode("inc","a");
3584     emitcode("","%05d_DS_:",(lbl->key+100));
3585
3586     /* now the multiplication */
3587     emitcode("div","ab");
3588     /* we are interested in the lower order
3589     only */
3590     lbl = newiTempLabel(NULL);
3591     emitcode("pop","acc");   
3592     /* if there was an over flow we don't 
3593     adjust the sign of the result */
3594     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3595     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3596     CLRC ;
3597     emitcode("clr","a");
3598     emitcode("subb","a,b");
3599     emitcode("mov","b,a");
3600     emitcode("","%05d_DS_:",(lbl->key+100));
3601
3602     /* now we are done */
3603     aopPut(AOP(result),"b",0);
3604
3605 }
3606
3607 /*-----------------------------------------------------------------*/
3608 /* genMod - generates code for division                            */
3609 /*-----------------------------------------------------------------*/
3610 static void genMod (iCode *ic)
3611 {
3612     operand *left = IC_LEFT(ic);
3613     operand *right = IC_RIGHT(ic);
3614     operand *result= IC_RESULT(ic);  
3615
3616     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3617     /* assign the amsops */
3618     aopOp (left,ic,FALSE);
3619     aopOp (right,ic,FALSE);
3620     aopOp (result,ic,TRUE);
3621
3622     /* special cases first */
3623     /* both are bits */
3624     if (AOP_TYPE(left) == AOP_CRY &&
3625         AOP_TYPE(right)== AOP_CRY) {
3626         genModbits(left,right,result);
3627         goto release ;
3628     }
3629
3630     /* if both are of size == 1 */
3631     if (AOP_SIZE(left) == 1 &&
3632         AOP_SIZE(right) == 1 ) {
3633         genModOneByte(left,right,result);
3634         goto release ;
3635     }
3636
3637     /* should have been converted to function call */
3638     assert(1);
3639
3640 release :
3641     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3642     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3643     freeAsmop(result,NULL,ic,TRUE); 
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genIfxJump :- will create a jump depending on the ifx           */
3648 /*-----------------------------------------------------------------*/
3649 static void genIfxJump (iCode *ic, char *jval)
3650 {
3651
3652     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3653     /* if true label then we jump if condition
3654     supplied is true */
3655     if ( IC_TRUE(ic) ) {
3656
3657         if(strcmp(jval,"a") == 0)
3658           emitSKPZ;
3659         else if (strcmp(jval,"c") == 0)
3660           emitSKPC;
3661         else
3662           emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3663
3664         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3665
3666     }
3667     else {
3668         /* false label is present */
3669         if(strcmp(jval,"a") == 0)
3670           emitSKPNZ;
3671         else if (strcmp(jval,"c") == 0)
3672           emitSKPNC;
3673         else
3674           emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
3675
3676         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3677
3678     }
3679
3680
3681     /* mark the icode as generated */
3682     ic->generated = 1;
3683 }
3684
3685 /*-----------------------------------------------------------------*/
3686 /* genSkip                                                         */
3687 /*-----------------------------------------------------------------*/
3688 static void genSkip(iCode *ifx,int status_bit)
3689 {
3690   if(!ifx)
3691     return;
3692
3693   if ( IC_TRUE(ifx) ) {
3694     switch(status_bit) {
3695     case 'z':
3696       emitSKPNZ;
3697       break;
3698
3699     case 'c':
3700       emitSKPNC;
3701       break;
3702
3703     case 'd':
3704       emitcode("skpndc","");
3705       break;
3706
3707     }
3708
3709     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3710
3711   } else {
3712
3713     switch(status_bit) {
3714
3715     case 'z':
3716       emitSKPZ;
3717       break;
3718
3719     case 'c':
3720       emitSKPC;
3721       break;
3722
3723     case 'd':
3724       emitcode("skpdc","");
3725       break;
3726     }
3727     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3728
3729   }
3730
3731 }
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genSkipc                                                        */
3735 /*-----------------------------------------------------------------*/
3736 static void genSkipc(iCode *ifx, int condition)
3737 {
3738   if(!ifx)
3739     return;
3740
3741   if(condition)
3742     emitSKPNC;
3743   else
3744     emitSKPC;
3745
3746   if ( IC_TRUE(ifx) )
3747     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3748   else
3749     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3750
3751 }
3752
3753 /*-----------------------------------------------------------------*/
3754 /* genSkipz                                                        */
3755 /*-----------------------------------------------------------------*/
3756 static void genSkipz(iCode *ifx, int condition)
3757 {
3758   if(!ifx)
3759     return;
3760
3761   if(condition)
3762     emitSKPNZ;
3763   else
3764     emitSKPZ;
3765
3766   if ( IC_TRUE(ifx) )
3767     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3768   else
3769     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3770
3771 }
3772 /*-----------------------------------------------------------------*/
3773 /* genCmp :- greater or less than comparison                       */
3774 /*-----------------------------------------------------------------*/
3775 static void genCmp (operand *left,operand *right,
3776                     operand *result, iCode *ifx, int sign)
3777 {
3778   int size, offset = 0 ;
3779   unsigned long lit = 0L,i = 0;
3780
3781   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3782   /* if left & right are bit variables */
3783   if (AOP_TYPE(left) == AOP_CRY &&
3784       AOP_TYPE(right) == AOP_CRY ) {
3785     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3786     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3787   } else {
3788     /* subtract right from left if at the
3789        end the carry flag is set then we know that
3790        left is greater than right */
3791     size = max(AOP_SIZE(left),AOP_SIZE(right));
3792
3793     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3794     if((size == 1) && !sign &&
3795        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3796       symbol *lbl  = newiTempLabel(NULL);
3797       emitcode("cjne","%s,%s,%05d_DS_",
3798                aopGet(AOP(left),offset,FALSE,FALSE),
3799                aopGet(AOP(right),offset,FALSE,FALSE),
3800                lbl->key+100);
3801       emitcode("","%05d_DS_:",lbl->key+100);
3802     } else {
3803
3804       if(AOP_TYPE(right) == AOP_LIT) {
3805
3806         DEBUGemitcode(";right lit","%d",sign);
3807
3808         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3809         //default:
3810         while(size--) {
3811           i = (lit >> (size*8)) & 0xff;
3812           if(i == 0) {
3813             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3814             genSkipz(ifx,IC_TRUE(ifx) == NULL);
3815           } else {
3816             emitcode("movlw","0x%x",i);
3817             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3818             genSkipc(ifx,IC_TRUE(ifx) == NULL);
3819           }
3820
3821         }
3822         ifx->generated = 1;
3823         return;
3824       }
3825       if(AOP_TYPE(left) == AOP_LIT) {
3826
3827         DEBUGemitcode(";left lit","%d",sign);
3828
3829         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3830
3831         //default:
3832         while(size--) {
3833           i = (lit >> (size*8)) & 0xff;
3834           if(i == 0) {
3835             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3836             genSkipz(ifx,IC_TRUE(ifx) != NULL);
3837           } else if( i == 1 ) {
3838             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3839             genSkipz(ifx,IC_TRUE(ifx) != NULL);
3840
3841           } else {
3842             emitcode("movlw","0x%x",i);
3843             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3844             genSkipc(ifx,IC_TRUE(ifx) != NULL);
3845           }
3846         }
3847         ifx->generated = 1;
3848         return;
3849       }
3850
3851
3852       // CLRC;
3853       DEBUGemitcode(";sign","%d",sign);
3854       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3855       emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3856       size--;
3857       while (size--) {
3858
3859         /*if (AOP_TYPE(right) == AOP_LIT){
3860           unsigned long lit = (unsigned long)
3861           floatFromVal(AOP(right)->aopu.aop_lit);
3862           emitcode("subb","a,#0x%02x",
3863           0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));                       
3864           } else {
3865           emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3866           emitcode("xrl","b,#0x80");
3867           emitcode("subb","a,b");
3868           }
3869           } else      
3870           emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3871         */
3872         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3873         emitSKPC;
3874         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3875         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3876         offset++;
3877       }
3878     }
3879   }
3880
3881   //release:
3882   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3883     outBitC(result);
3884   } else {
3885     /* if the result is used in the next
3886        ifx conditional branch then generate
3887        code a little differently */
3888     if (ifx )
3889       genIfxJump (ifx,"c");
3890     else
3891       outBitC(result);
3892     /* leave the result in acc */
3893   }
3894
3895 }
3896
3897 /*-----------------------------------------------------------------*/
3898 /* genCmpGt :- greater than comparison                             */
3899 /*-----------------------------------------------------------------*/
3900 static void genCmpGt (iCode *ic, iCode *ifx)
3901 {
3902     operand *left, *right, *result;
3903     sym_link *letype , *retype;
3904     int sign ;
3905
3906     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3907     left = IC_LEFT(ic);
3908     right= IC_RIGHT(ic);
3909     result = IC_RESULT(ic);
3910
3911     letype = getSpec(operandType(left));
3912     retype =getSpec(operandType(right));
3913     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3914     /* assign the amsops */
3915     aopOp (left,ic,FALSE);
3916     aopOp (right,ic,FALSE);
3917     aopOp (result,ic,TRUE);
3918
3919     genCmp(right, left, result, ifx, sign);
3920
3921     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3922     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3923     freeAsmop(result,NULL,ic,TRUE); 
3924 }
3925
3926 /*-----------------------------------------------------------------*/
3927 /* genCmpLt - less than comparisons                                */
3928 /*-----------------------------------------------------------------*/
3929 static void genCmpLt (iCode *ic, iCode *ifx)
3930 {
3931     operand *left, *right, *result;
3932     sym_link *letype , *retype;
3933     int sign ;
3934
3935     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3936     left = IC_LEFT(ic);
3937     right= IC_RIGHT(ic);
3938     result = IC_RESULT(ic);
3939
3940     letype = getSpec(operandType(left));
3941     retype =getSpec(operandType(right));
3942     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3943
3944     /* assign the amsops */
3945     aopOp (left,ic,FALSE);
3946     aopOp (right,ic,FALSE);
3947     aopOp (result,ic,TRUE);
3948
3949     genCmp(left, right, result, ifx, sign);
3950
3951     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3952     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3953     freeAsmop(result,NULL,ic,TRUE); 
3954 }
3955
3956 /*-----------------------------------------------------------------*/
3957 /* gencjneshort - compare and jump if not equal                    */
3958 /*-----------------------------------------------------------------*/
3959 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3960 {
3961     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3962     int offset = 0;
3963     unsigned long lit = 0L;
3964
3965     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3966     /* if the left side is a literal or 
3967     if the right is in a pointer register and left 
3968     is not */
3969     if ((AOP_TYPE(left) == AOP_LIT) || 
3970         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3971         operand *t = right;
3972         right = left;
3973         left = t;
3974     }
3975     if(AOP_TYPE(right) == AOP_LIT)
3976         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3977
3978     /* if the right side is a literal then anything goes */
3979     if (AOP_TYPE(right) == AOP_LIT &&
3980         AOP_TYPE(left) != AOP_DIR ) {
3981         while (size--) {
3982           if(lit & 0xff) {
3983             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3984             emitcode("xorlw","0x%x",lit & 0xff);
3985           } else
3986             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3987
3988           emitSKPNZ;
3989           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3990           offset++;
3991           lit >>= 8;
3992         }
3993     }
3994
3995     /* if the right side is in a register or in direct space or
3996     if the left is a pointer register & right is not */    
3997     else if (AOP_TYPE(right) == AOP_REG ||
3998              AOP_TYPE(right) == AOP_DIR || 
3999              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4000              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4001         while (size--) {
4002           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4003              ( (lit & 0xff) != 0)) {
4004             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4005             emitcode("xorlw","0x%x",lit & 0xff);
4006             lit >>= 8;
4007           } else
4008             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4009
4010           emitSKPZ;
4011           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4012           offset++;
4013 /*
4014             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4015             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4016                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4017                 emitcode("jnz","%05d_DS_",lbl->key+100);
4018             else
4019                 emitcode("cjne","a,%s,%05d_DS_",
4020                          aopGet(AOP(right),offset,FALSE,TRUE),
4021                          lbl->key+100);
4022             offset++;
4023 */
4024         }
4025     } else {
4026         /* right is a pointer reg need both a & b */
4027         while(size--) {
4028             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4029             if(strcmp(l,"b"))
4030                 emitcode("mov","b,%s",l);
4031             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4032             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4033             offset++;
4034         }
4035     }
4036 }
4037
4038 /*-----------------------------------------------------------------*/
4039 /* gencjne - compare and jump if not equal                         */
4040 /*-----------------------------------------------------------------*/
4041 static void gencjne(operand *left, operand *right, symbol *lbl)
4042 {
4043     symbol *tlbl  = newiTempLabel(NULL);
4044
4045     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4046     gencjneshort(left, right, lbl);
4047
4048     emitcode("mov","a,%s",one);
4049     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4050     emitcode("","%05d_DS_:",lbl->key+100);
4051     emitcode("clr","a");
4052     emitcode("","%05d_DS_:",tlbl->key+100);
4053 }
4054
4055
4056 /*-----------------------------------------------------------------*/
4057 /* genCmpEq - generates code for equal to                          */
4058 /*-----------------------------------------------------------------*/
4059 static void genCmpEq (iCode *ic, iCode *ifx)
4060 {
4061     operand *left, *right, *result;
4062     unsigned long lit = 0L;
4063     int size,offset=0;
4064
4065     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4066     if(ifx)
4067       DEBUGemitcode ("; ifx is non-null","");
4068     else
4069       DEBUGemitcode ("; ifx is null","");
4070
4071     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4072     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4073     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4074
4075     size = max(AOP_SIZE(left),AOP_SIZE(right));
4076
4077     /* if literal, literal on the right or 
4078     if the right is in a pointer register and left 
4079     is not */
4080     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4081         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4082         operand *t = IC_RIGHT(ic);
4083         IC_RIGHT(ic) = IC_LEFT(ic);
4084         IC_LEFT(ic) = t;
4085     }
4086
4087     if(ifx && !AOP_SIZE(result)){
4088         symbol *tlbl;
4089         /* if they are both bit variables */
4090         if (AOP_TYPE(left) == AOP_CRY &&
4091             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4092             if(AOP_TYPE(right) == AOP_LIT){
4093                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4094                 if(lit == 0L){
4095                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4096                     emitcode("cpl","c");
4097                 } else if(lit == 1L) {
4098                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4099                 } else {
4100                     emitcode("clr","c");
4101                 }
4102                 /* AOP_TYPE(right) == AOP_CRY */
4103             } else {
4104                 symbol *lbl = newiTempLabel(NULL);
4105                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4106                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4107                 emitcode("cpl","c");
4108                 emitcode("","%05d_DS_:",(lbl->key+100));
4109             }
4110             /* if true label then we jump if condition
4111             supplied is true */
4112             tlbl = newiTempLabel(NULL);
4113             if ( IC_TRUE(ifx) ) {
4114                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4115                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4116             } else {
4117                 emitcode("jc","%05d_DS_",tlbl->key+100);
4118                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4119             }
4120             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4121         } else {
4122
4123           /* They're not both bit variables. Is the right a literal? */
4124           if(AOP_TYPE(right) == AOP_LIT) {
4125
4126             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4127             while (size--) {
4128
4129               if(size >= 1) {
4130                 int l = lit & 0xff;
4131                 int h = (lit>>8) & 0xff;
4132                 int optimized=0;
4133
4134                 /* Check special cases for integers */
4135                 switch(lit & 0xffff) {
4136                 case 0x0000:
4137                   emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4138                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4139                   genSkip(ifx,'z');
4140                   optimized++;
4141                   break;
4142                 case 0x0001:
4143                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4144                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4145                   genSkip(ifx,'z');
4146                   optimized++;
4147                   break;
4148                 case 0x0100:
4149                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4150                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4151                   genSkip(ifx,'z');
4152                   optimized++;
4153                   break;
4154                 case 0x00ff:
4155                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4156                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4157                   genSkip(ifx,'z');
4158                   optimized++;
4159                   break;
4160                 case 0xff00:
4161                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4162                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4163                   genSkip(ifx,'z');
4164                   optimized++;
4165                   break;
4166                 default:
4167                   if(h == 0) {
4168                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4169                     emitcode("xorlw","0x%x",l);
4170                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4171                     optimized++;
4172                     genSkip(ifx,'z');
4173                   } else if (l == 0) {
4174                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4175                     emitcode("xorlw","0x%x",h);
4176                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4177                     optimized++;
4178                     genSkip(ifx,'z');
4179                   } else {
4180                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4181                     emitcode("xorlw","0x%x",l);
4182                     emitcode("movlw","0x%x",h);
4183                     emitSKPZ;
4184                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4185                     optimized++;
4186                     genSkip(ifx,'z');
4187                   }
4188
4189                 }
4190                 if(optimized) {
4191                   size--;
4192                   offset+=2;
4193                   lit>>=16;
4194
4195                   continue;
4196                 }
4197                   
4198               }
4199                 
4200               switch(lit & 0xff) {
4201               case 1:
4202                 if ( IC_TRUE(ifx) ) {
4203                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4204                   emitSKPNZ;
4205                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4206                 } else {
4207                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4208                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4209                 }
4210                 break;
4211               case 0xff:
4212                 if ( IC_TRUE(ifx) ) {
4213                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4214                   emitSKPNZ;
4215                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4216                 } else {
4217                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4218                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4219                 }
4220                 break;
4221               default:
4222                 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4223                 if(lit)
4224                   emitcode("xorlw","0x%x",lit & 0xff);
4225                 genSkip(ifx,'z');
4226               }
4227
4228
4229               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4230               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4231               offset++;
4232               lit >>= 8;
4233             }
4234
4235           } else if(AOP_TYPE(right) == AOP_CRY ) {
4236             /* we know the left is not a bit, but that the right is */
4237             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4238             if ( IC_TRUE(ifx) )
4239               emitcode("btfsc","(%s >> 3), (%s & 7)",
4240                        AOP(right)->aopu.aop_dir,
4241                        AOP(right)->aopu.aop_dir);
4242             else
4243               emitcode("btfss","(%s >> 3), (%s & 7)",
4244                        AOP(right)->aopu.aop_dir,
4245                        AOP(right)->aopu.aop_dir);
4246
4247             emitcode("xorlw","1");
4248
4249             /* if the two are equal, then W will be 0 and the Z bit is set
4250              * we could test Z now, or go ahead and check the high order bytes if
4251              * the variable we're comparing is larger than a byte. */
4252
4253             while(--size)
4254               emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4255
4256             if ( IC_TRUE(ifx) ) {
4257               emitSKPNZ;
4258               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4259             } else {
4260               emitSKPZ;
4261               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4262             }
4263
4264           } else {
4265             /* They're both variables that are larger than bits */
4266             int s = size;
4267
4268             tlbl = newiTempLabel(NULL);
4269
4270             while(size--) {
4271
4272               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4273               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4274
4275               if ( IC_TRUE(ifx) ) {
4276                 if(size) {
4277                   emitSKPZ;
4278                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4279                 } else {
4280                   emitSKPNZ;
4281                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4282                 }
4283               } else {
4284                 emitSKPZ;
4285                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4286               }
4287               offset++;
4288             }
4289             if(s>1 && IC_TRUE(ifx))
4290               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4291           }
4292         }
4293         /* mark the icode as generated */
4294         ifx->generated = 1;
4295         goto release ;
4296     }
4297
4298     /* if they are both bit variables */
4299     if (AOP_TYPE(left) == AOP_CRY &&
4300         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4301         if(AOP_TYPE(right) == AOP_LIT){
4302             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4303             if(lit == 0L){
4304                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4305                 emitcode("cpl","c");
4306             } else if(lit == 1L) {
4307                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4308             } else {
4309                 emitcode("clr","c");
4310             }
4311             /* AOP_TYPE(right) == AOP_CRY */
4312         } else {
4313             symbol *lbl = newiTempLabel(NULL);
4314             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4315             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4316             emitcode("cpl","c");
4317             emitcode("","%05d_DS_:",(lbl->key+100));
4318         }
4319         /* c = 1 if egal */
4320         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4321             outBitC(result);
4322             goto release ;
4323         }
4324         if (ifx) {
4325             genIfxJump (ifx,"c");
4326             goto release ;
4327         }
4328         /* if the result is used in an arithmetic operation
4329         then put the result in place */
4330         outBitC(result);
4331     } else {
4332         gencjne(left,right,newiTempLabel(NULL));    
4333         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4334             aopPut(AOP(result),"a",0);
4335             goto release ;
4336         }
4337         if (ifx) {
4338             genIfxJump (ifx,"a");
4339             goto release ;
4340         }
4341         /* if the result is used in an arithmetic operation
4342         then put the result in place */
4343         if (AOP_TYPE(result) != AOP_CRY) 
4344             outAcc(result);
4345         /* leave the result in acc */
4346     }
4347
4348 release:
4349     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351     freeAsmop(result,NULL,ic,TRUE);
4352 }
4353
4354 /*-----------------------------------------------------------------*/
4355 /* ifxForOp - returns the icode containing the ifx for operand     */
4356 /*-----------------------------------------------------------------*/
4357 static iCode *ifxForOp ( operand *op, iCode *ic )
4358 {
4359     /* if true symbol then needs to be assigned */
4360     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4361     if (IS_TRUE_SYMOP(op))
4362         return NULL ;
4363
4364     /* if this has register type condition and
4365     the next instruction is ifx with the same operand
4366     and live to of the operand is upto the ifx only then */
4367     if (ic->next &&
4368         ic->next->op == IFX &&
4369         IC_COND(ic->next)->key == op->key &&
4370         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4371         return ic->next;
4372
4373     return NULL;
4374 }
4375 /*-----------------------------------------------------------------*/
4376 /* genAndOp - for && operation                                     */
4377 /*-----------------------------------------------------------------*/
4378 static void genAndOp (iCode *ic)
4379 {
4380     operand *left,*right, *result;
4381     symbol *tlbl;
4382
4383     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4384     /* note here that && operations that are in an
4385     if statement are taken away by backPatchLabels
4386     only those used in arthmetic operations remain */
4387     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4388     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4389     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4390
4391     /* if both are bit variables */
4392     if (AOP_TYPE(left) == AOP_CRY &&
4393         AOP_TYPE(right) == AOP_CRY ) {
4394         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4395         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4396         outBitC(result);
4397     } else {
4398         tlbl = newiTempLabel(NULL);
4399         toBoolean(left);    
4400         emitcode("jz","%05d_DS_",tlbl->key+100);
4401         toBoolean(right);
4402         emitcode("","%05d_DS_:",tlbl->key+100);
4403         outBitAcc(result);
4404     }
4405
4406     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4407     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4408     freeAsmop(result,NULL,ic,TRUE);
4409 }
4410
4411
4412 /*-----------------------------------------------------------------*/
4413 /* genOrOp - for || operation                                      */
4414 /*-----------------------------------------------------------------*/
4415 /*
4416   tsd pic port -
4417   modified this code, but it doesn't appear to ever get called
4418 */
4419
4420 static void genOrOp (iCode *ic)
4421 {
4422     operand *left,*right, *result;
4423     symbol *tlbl;
4424
4425     /* note here that || operations that are in an
4426     if statement are taken away by backPatchLabels
4427     only those used in arthmetic operations remain */
4428     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4429     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4430     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4431     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4432
4433     /* if both are bit variables */
4434     if (AOP_TYPE(left) == AOP_CRY &&
4435         AOP_TYPE(right) == AOP_CRY ) {
4436       emitcode("clrc","");
4437       emitcode("btfss","(%s >> 3), (%s & 7)",
4438                AOP(left)->aopu.aop_dir,
4439                AOP(left)->aopu.aop_dir);
4440       emitcode("btfsc","(%s >> 3), (%s & 7)",
4441                AOP(right)->aopu.aop_dir,
4442                AOP(right)->aopu.aop_dir);
4443       emitcode("setc","");
4444
4445     } else {
4446         tlbl = newiTempLabel(NULL);
4447         toBoolean(left);
4448         emitSKPZ;
4449         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4450         toBoolean(right);
4451         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4452
4453         outBitAcc(result);
4454     }
4455
4456     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4457     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4458     freeAsmop(result,NULL,ic,TRUE);            
4459 }
4460
4461 /*-----------------------------------------------------------------*/
4462 /* isLiteralBit - test if lit == 2^n                               */
4463 /*-----------------------------------------------------------------*/
4464 static int isLiteralBit(unsigned long lit)
4465 {
4466     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4467     0x100L,0x200L,0x400L,0x800L,
4468     0x1000L,0x2000L,0x4000L,0x8000L,
4469     0x10000L,0x20000L,0x40000L,0x80000L,
4470     0x100000L,0x200000L,0x400000L,0x800000L,
4471     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4472     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4473     int idx;
4474     
4475     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4476     for(idx = 0; idx < 32; idx++)
4477         if(lit == pw[idx])
4478             return idx+1;
4479     return 0;
4480 }
4481
4482 /*-----------------------------------------------------------------*/
4483 /* continueIfTrue -                                                */
4484 /*-----------------------------------------------------------------*/
4485 static void continueIfTrue (iCode *ic)
4486 {
4487     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4488     if(IC_TRUE(ic))
4489         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4490     ic->generated = 1;
4491 }
4492
4493 /*-----------------------------------------------------------------*/
4494 /* jmpIfTrue -                                                     */
4495 /*-----------------------------------------------------------------*/
4496 static void jumpIfTrue (iCode *ic)
4497 {
4498     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4499     if(!IC_TRUE(ic))
4500         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4501     ic->generated = 1;
4502 }
4503
4504 /*-----------------------------------------------------------------*/
4505 /* jmpTrueOrFalse -                                                */
4506 /*-----------------------------------------------------------------*/
4507 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4508 {
4509     // ugly but optimized by peephole
4510     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4511     if(IC_TRUE(ic)){
4512         symbol *nlbl = newiTempLabel(NULL);
4513         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4514         emitcode("","%05d_DS_:",tlbl->key+100);
4515         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4516         emitcode("","%05d_DS_:",nlbl->key+100);
4517     }
4518     else{
4519         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4520         emitcode("","%05d_DS_:",tlbl->key+100);
4521     }
4522     ic->generated = 1;
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* genAnd  - code for and                                          */
4527 /*-----------------------------------------------------------------*/
4528 static void genAnd (iCode *ic, iCode *ifx)
4529 {
4530     operand *left, *right, *result;
4531     int size, offset=0;  
4532     unsigned long lit = 0L;
4533     int bytelit = 0;
4534     char buffer[10];
4535
4536     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4537     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4538     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4539     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4540
4541 #ifdef DEBUG_TYPE
4542     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4543              AOP_TYPE(result),
4544              AOP_TYPE(left), AOP_TYPE(right));
4545     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4546              AOP_SIZE(result),
4547              AOP_SIZE(left), AOP_SIZE(right));
4548 #endif
4549
4550     /* if left is a literal & right is not then exchange them */
4551     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4552         AOP_NEEDSACC(left)) {
4553         operand *tmp = right ;
4554         right = left;
4555         left = tmp;
4556     }
4557
4558     /* if result = right then exchange them */
4559     if(sameRegs(AOP(result),AOP(right))){
4560         operand *tmp = right ;
4561         right = left;
4562         left = tmp;
4563     }
4564
4565     /* if right is bit then exchange them */
4566     if (AOP_TYPE(right) == AOP_CRY &&
4567         AOP_TYPE(left) != AOP_CRY){
4568         operand *tmp = right ;
4569         right = left;
4570         left = tmp;
4571     }
4572     if(AOP_TYPE(right) == AOP_LIT)
4573         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4574
4575     size = AOP_SIZE(result);
4576
4577     // if(bit & yy)
4578     // result = bit & yy;
4579     if (AOP_TYPE(left) == AOP_CRY){
4580         // c = bit & literal;
4581         if(AOP_TYPE(right) == AOP_LIT){
4582             if(lit & 1) {
4583                 if(size && sameRegs(AOP(result),AOP(left)))
4584                     // no change
4585                     goto release;
4586                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4587             } else {
4588                 // bit(result) = 0;
4589                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4590                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4591                     goto release;
4592                 }
4593                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4594                     jumpIfTrue(ifx);
4595                     goto release;
4596                 }
4597                 emitcode("clr","c");
4598             }
4599         } else {
4600             if (AOP_TYPE(right) == AOP_CRY){
4601                 // c = bit & bit;
4602                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4603                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4604             } else {
4605                 // c = bit & val;
4606                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4607                 // c = lsb
4608                 emitcode("rrc","a");
4609                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4610             }
4611         }
4612         // bit = c
4613         // val = c
4614         if(size)
4615             outBitC(result);
4616         // if(bit & ...)
4617         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4618             genIfxJump(ifx, "c");           
4619         goto release ;
4620     }
4621
4622     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4623     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4624     if((AOP_TYPE(right) == AOP_LIT) &&
4625        (AOP_TYPE(result) == AOP_CRY) &&
4626        (AOP_TYPE(left) != AOP_CRY)){
4627         int posbit = isLiteralBit(lit);
4628         /* left &  2^n */
4629         if(posbit){
4630             posbit--;
4631             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4632             // bit = left & 2^n
4633             if(size)
4634                 emitcode("mov","c,acc.%d",posbit&0x07);
4635             // if(left &  2^n)
4636             else{
4637                 if(ifx){
4638                     sprintf(buffer,"acc.%d",posbit&0x07);
4639                     genIfxJump(ifx, buffer);
4640                 }
4641                 goto release;
4642             }
4643         } else {
4644             symbol *tlbl = newiTempLabel(NULL);
4645             int sizel = AOP_SIZE(left);
4646             if(size)
4647                 emitcode("setb","c");
4648             while(sizel--){
4649                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4650                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4651                     // byte ==  2^n ?
4652                     if((posbit = isLiteralBit(bytelit)) != 0)
4653                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4654                     else{
4655                         if(bytelit != 0x0FFL)
4656                             emitcode("anl","a,%s",
4657                                      aopGet(AOP(right),offset,FALSE,TRUE));
4658                         emitcode("jnz","%05d_DS_",tlbl->key+100);
4659                     }
4660                 }
4661                 offset++;
4662             }
4663             // bit = left & literal
4664             if(size){
4665                 emitcode("clr","c");
4666                 emitcode("","%05d_DS_:",tlbl->key+100);
4667             }
4668             // if(left & literal)
4669             else{
4670                 if(ifx)
4671                     jmpTrueOrFalse(ifx, tlbl);
4672                 goto release ;
4673             }
4674         }
4675         outBitC(result);
4676         goto release ;
4677     }
4678
4679     /* if left is same as result */
4680     if(sameRegs(AOP(result),AOP(left))){
4681       for(;size--; offset++,lit>>=8) {
4682         if(AOP_TYPE(right) == AOP_LIT){
4683           switch(lit & 0xff) {
4684           case 0x00:
4685             /*  and'ing with 0 has clears the result */
4686             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4687             break;
4688           case 0xff:
4689             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4690             break;
4691
4692           default:
4693             {
4694               int p = my_powof2( (~lit) & 0xff );
4695               if(p>=0) {
4696                 /* only one bit is set in the literal, so use a bcf instruction */
4697                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4698               } else {
4699                 emitcode("movlw","0x%x", (lit & 0xff));
4700                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4701               }
4702             }    
4703           }
4704         } else {
4705           if (AOP_TYPE(left) == AOP_ACC) 
4706             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4707           else {                    
4708             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4709             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4710
4711           }
4712         }
4713       }
4714
4715     } else {
4716         // left & result in different registers
4717         if(AOP_TYPE(result) == AOP_CRY){
4718             // result = bit
4719             // if(size), result in bit
4720             // if(!size && ifx), conditional oper: if(left & right)
4721             symbol *tlbl = newiTempLabel(NULL);
4722             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4723             if(size)
4724                 emitcode("setb","c");
4725             while(sizer--){
4726                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4727                 emitcode("anl","a,%s",
4728                          aopGet(AOP(left),offset,FALSE,FALSE));
4729                 emitcode("jnz","%05d_DS_",tlbl->key+100);
4730                 offset++;
4731             }
4732             if(size){
4733                 CLRC;
4734                 emitcode("","%05d_DS_:",tlbl->key+100);
4735                 outBitC(result);
4736             } else if(ifx)
4737                 jmpTrueOrFalse(ifx, tlbl);
4738         } else {
4739           for(;(size--);offset++) {
4740             // normal case
4741             // result = left & right
4742             if(AOP_TYPE(right) == AOP_LIT){
4743               int t = (lit >> (offset*8)) & 0x0FFL;
4744               switch(t) { 
4745               case 0x00:
4746                 emitcode("clrf","%s",
4747                          aopGet(AOP(result),offset,FALSE,FALSE));
4748                 break;
4749               case 0xff:
4750                 emitcode("movf","%s,w",
4751                          aopGet(AOP(left),offset,FALSE,FALSE));
4752                 emitcode("movwf","%s",
4753                          aopGet(AOP(result),offset,FALSE,FALSE));
4754                 break;
4755               default:
4756                 emitcode("movlw","0x%x",t);
4757                 emitcode("andwf","%s,w",
4758                          aopGet(AOP(left),offset,FALSE,FALSE));
4759                 emitcode("movwf","%s",
4760                          aopGet(AOP(result),offset,FALSE,FALSE));
4761               
4762               }
4763               continue;
4764             }
4765
4766             if (AOP_TYPE(left) == AOP_ACC) 
4767               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4768             else {
4769               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4770               emitcode("andwf","%s,w",
4771                        aopGet(AOP(left),offset,FALSE,FALSE));
4772             }
4773             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4774           }
4775         }
4776     }
4777
4778 release :
4779     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4780     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4781     freeAsmop(result,NULL,ic,TRUE);     
4782 }
4783
4784 /*-----------------------------------------------------------------*/
4785 /* genOr  - code for or                                            */
4786 /*-----------------------------------------------------------------*/
4787 static void genOr (iCode *ic, iCode *ifx)
4788 {
4789     operand *left, *right, *result;
4790     int size, offset=0;
4791     unsigned long lit = 0L;
4792
4793     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4794
4795     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4796     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4797     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4798
4799
4800     /* if left is a literal & right is not then exchange them */
4801     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4802         AOP_NEEDSACC(left)) {
4803         operand *tmp = right ;
4804         right = left;
4805         left = tmp;
4806     }
4807
4808     /* if result = right then exchange them */
4809     if(sameRegs(AOP(result),AOP(right))){
4810         operand *tmp = right ;
4811         right = left;
4812         left = tmp;
4813     }
4814
4815     /* if right is bit then exchange them */
4816     if (AOP_TYPE(right) == AOP_CRY &&
4817         AOP_TYPE(left) != AOP_CRY){
4818         operand *tmp = right ;
4819         right = left;
4820         left = tmp;
4821     }
4822
4823     if(AOP_TYPE(right) == AOP_LIT)
4824         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4825
4826     size = AOP_SIZE(result);
4827
4828     // if(bit | yy)
4829     // xx = bit | yy;
4830     if (AOP_TYPE(left) == AOP_CRY){
4831         if(AOP_TYPE(right) == AOP_LIT){
4832             // c = bit & literal;
4833             if(lit){
4834                 // lit != 0 => result = 1
4835                 if(AOP_TYPE(result) == AOP_CRY){
4836                     if(size)
4837                         emitcode("bsf","(%s >> 3), (%s & 7)",
4838                                  AOP(result)->aopu.aop_dir,
4839                                  AOP(result)->aopu.aop_dir);
4840                     else if(ifx)
4841                         continueIfTrue(ifx);
4842                     goto release;
4843                 }
4844                 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4845             } else {
4846                 // lit == 0 => result = left
4847                 if(size && sameRegs(AOP(result),AOP(left)))
4848                     goto release;
4849                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4850             }
4851         } else {
4852             if (AOP_TYPE(right) == AOP_CRY){
4853               if(sameRegs(AOP(result),AOP(left))){
4854                 // c = bit | bit;
4855                 emitcode("bcf","(%s >> 3), (%s & 7)",
4856                          AOP(result)->aopu.aop_dir,
4857                          AOP(result)->aopu.aop_dir);
4858                 emitcode("btfsc","(%s >> 3), (%s & 7)",
4859                          AOP(right)->aopu.aop_dir,
4860                          AOP(right)->aopu.aop_dir);
4861                 emitcode("bsf","(%s >> 3), (%s & 7)",
4862                          AOP(result)->aopu.aop_dir,
4863                          AOP(result)->aopu.aop_dir);
4864               } else {
4865
4866                 emitcode("bcf","(%s >> 3), (%s & 7)",
4867                          AOP(result)->aopu.aop_dir,
4868                          AOP(result)->aopu.aop_dir);
4869                 emitcode("btfss","(%s >> 3), (%s & 7)",
4870                          AOP(right)->aopu.aop_dir,
4871                          AOP(right)->aopu.aop_dir);
4872                 emitcode("btfsc","(%s >> 3), (%s & 7)",
4873                          AOP(left)->aopu.aop_dir,
4874                          AOP(left)->aopu.aop_dir);
4875                 emitcode("bsf","(%s >> 3), (%s & 7)",
4876                          AOP(result)->aopu.aop_dir,
4877                          AOP(result)->aopu.aop_dir);
4878               }
4879             }
4880             else{
4881                 // c = bit | val;
4882                 symbol *tlbl = newiTempLabel(NULL);
4883                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4884                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4885                     emitcode(";XXX setb","c");
4886                 emitcode(";XXX jb","%s,%05d_DS_",
4887                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4888                 toBoolean(right);
4889                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4890                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4891                     jmpTrueOrFalse(ifx, tlbl);
4892                     goto release;
4893                 } else {
4894                     CLRC;
4895                     emitcode("","%05d_DS_:",tlbl->key+100);
4896                 }
4897             }
4898         }
4899         // bit = c
4900         // val = c
4901         if(size)
4902             outBitC(result);
4903         // if(bit | ...)
4904         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4905             genIfxJump(ifx, "c");           
4906         goto release ;
4907     }
4908
4909     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4910     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4911     if((AOP_TYPE(right) == AOP_LIT) &&
4912        (AOP_TYPE(result) == AOP_CRY) &&
4913        (AOP_TYPE(left) != AOP_CRY)){
4914         if(lit){
4915           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4916             // result = 1
4917             if(size)
4918                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4919             else 
4920                 continueIfTrue(ifx);
4921             goto release;
4922         } else {
4923           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4924             // lit = 0, result = boolean(left)
4925             if(size)
4926                 emitcode(";XXX setb","c");
4927             toBoolean(right);
4928             if(size){
4929                 symbol *tlbl = newiTempLabel(NULL);
4930                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4931                 CLRC;
4932                 emitcode("","%05d_DS_:",tlbl->key+100);
4933             } else {
4934                 genIfxJump (ifx,"a");
4935                 goto release;
4936             }
4937         }
4938         outBitC(result);
4939         goto release ;
4940     }
4941
4942     /* if left is same as result */
4943     if(sameRegs(AOP(result),AOP(left))){
4944       for(;size--; offset++,lit>>=8) {
4945         if(AOP_TYPE(right) == AOP_LIT){
4946           if((lit & 0xff) == 0)
4947             /*  or'ing with 0 has no effect */
4948             continue;
4949           else {
4950             int p = my_powof2(lit & 0xff);
4951             if(p>=0) {
4952               /* only one bit is set in the literal, so use a bsf instruction */
4953               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4954             } else {
4955               emitcode("movlw","0x%x", (lit & 0xff));
4956               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4957             }
4958                     
4959           }
4960         } else {
4961           if (AOP_TYPE(left) == AOP_ACC) 
4962             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4963           else {                    
4964             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4965             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4966
4967           }
4968         }
4969       }
4970     } else {
4971         // left & result in different registers
4972         if(AOP_TYPE(result) == AOP_CRY){
4973             // result = bit
4974             // if(size), result in bit
4975             // if(!size && ifx), conditional oper: if(left | right)
4976             symbol *tlbl = newiTempLabel(NULL);
4977             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4978             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4979
4980             if(size)
4981                 emitcode(";XXX setb","c");
4982             while(sizer--){
4983                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4984                 emitcode(";XXX orl","a,%s",
4985                          aopGet(AOP(left),offset,FALSE,FALSE));
4986                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4987                 offset++;
4988             }
4989             if(size){
4990                 CLRC;
4991                 emitcode("","%05d_DS_:",tlbl->key+100);
4992                 outBitC(result);
4993             } else if(ifx)
4994                 jmpTrueOrFalse(ifx, tlbl);
4995         } else for(;(size--);offset++){
4996           // normal case
4997           // result = left & right
4998           if(AOP_TYPE(right) == AOP_LIT){
4999             int t = (lit >> (offset*8)) & 0x0FFL;
5000             switch(t) { 
5001             case 0x00:
5002               emitcode("movf","%s,w",
5003                        aopGet(AOP(left),offset,FALSE,FALSE));
5004               emitcode("movwf","%s",
5005                        aopGet(AOP(result),offset,FALSE,FALSE));
5006               break;
5007             default:
5008               emitcode("movlw","0x%x",t);
5009               emitcode("iorwf","%s,w",
5010                        aopGet(AOP(left),offset,FALSE,FALSE));
5011               emitcode("movwf","%s",
5012                        aopGet(AOP(result),offset,FALSE,FALSE));
5013               
5014             }
5015             continue;
5016           }
5017
5018           // faster than result <- left, anl result,right
5019           // and better if result is SFR
5020           if (AOP_TYPE(left) == AOP_ACC) 
5021             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5022           else {
5023             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5024             emitcode("iorwf","%s,w",
5025                      aopGet(AOP(left),offset,FALSE,FALSE));
5026           }
5027           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5028         }
5029     }
5030
5031 release :
5032     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5033     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5034     freeAsmop(result,NULL,ic,TRUE);     
5035 }
5036
5037 /*-----------------------------------------------------------------*/
5038 /* genXor - code for xclusive or                                   */
5039 /*-----------------------------------------------------------------*/
5040 static void genXor (iCode *ic, iCode *ifx)
5041 {
5042     operand *left, *right, *result;
5043     int size, offset=0;
5044     unsigned long lit = 0L;
5045
5046     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5047
5048     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5049     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5050     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5051
5052     /* if left is a literal & right is not ||
5053        if left needs acc & right does not */
5054     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5055         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5056         operand *tmp = right ;
5057         right = left;
5058         left = tmp;
5059     }
5060
5061     /* if result = right then exchange them */
5062     if(sameRegs(AOP(result),AOP(right))){
5063         operand *tmp = right ;
5064         right = left;
5065         left = tmp;
5066     }
5067
5068     /* if right is bit then exchange them */
5069     if (AOP_TYPE(right) == AOP_CRY &&
5070         AOP_TYPE(left) != AOP_CRY){
5071         operand *tmp = right ;
5072         right = left;
5073         left = tmp;
5074     }
5075     if(AOP_TYPE(right) == AOP_LIT)
5076         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5077
5078     size = AOP_SIZE(result);
5079
5080     // if(bit ^ yy)
5081     // xx = bit ^ yy;
5082     if (AOP_TYPE(left) == AOP_CRY){
5083         if(AOP_TYPE(right) == AOP_LIT){
5084             // c = bit & literal;
5085             if(lit>>1){
5086                 // lit>>1  != 0 => result = 1
5087                 if(AOP_TYPE(result) == AOP_CRY){
5088                     if(size)
5089                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5090                     else if(ifx)
5091                         continueIfTrue(ifx);
5092                     goto release;
5093                 }
5094                 emitcode("setb","c");
5095             } else{
5096                 // lit == (0 or 1)
5097                 if(lit == 0){
5098                     // lit == 0, result = left
5099                     if(size && sameRegs(AOP(result),AOP(left)))
5100                         goto release;
5101                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5102                 } else{
5103                     // lit == 1, result = not(left)
5104                     if(size && sameRegs(AOP(result),AOP(left))){
5105                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5106                         goto release;
5107                     } else {
5108                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5109                         emitcode("cpl","c");
5110                     }
5111                 }
5112             }
5113
5114         } else {
5115             // right != literal
5116             symbol *tlbl = newiTempLabel(NULL);
5117             if (AOP_TYPE(right) == AOP_CRY){
5118                 // c = bit ^ bit;
5119                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5120             }
5121             else{
5122                 int sizer = AOP_SIZE(right);
5123                 // c = bit ^ val
5124                 // if val>>1 != 0, result = 1
5125                 emitcode("setb","c");
5126                 while(sizer){
5127                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5128                     if(sizer == 1)
5129                         // test the msb of the lsb
5130                         emitcode("anl","a,#0xfe");
5131                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5132                     sizer--;
5133                 }
5134                 // val = (0,1)
5135                 emitcode("rrc","a");
5136             }
5137             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5138             emitcode("cpl","c");
5139             emitcode("","%05d_DS_:",(tlbl->key+100));
5140         }
5141         // bit = c
5142         // val = c
5143         if(size)
5144             outBitC(result);
5145         // if(bit | ...)
5146         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5147             genIfxJump(ifx, "c");           
5148         goto release ;
5149     }
5150
5151     if(sameRegs(AOP(result),AOP(left))){
5152         /* if left is same as result */
5153         for(;size--; offset++) {
5154             if(AOP_TYPE(right) == AOP_LIT){
5155                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5156                     continue;
5157                 else
5158                     if (IS_AOP_PREG(left)) {
5159                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5160                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5161                         aopPut(AOP(result),"a",offset);
5162                     } else 
5163                         emitcode("xrl","%s,%s",
5164                                  aopGet(AOP(left),offset,FALSE,TRUE),
5165                                  aopGet(AOP(right),offset,FALSE,FALSE));
5166             } else {
5167                 if (AOP_TYPE(left) == AOP_ACC)
5168                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5169                 else {
5170                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5171                     if (IS_AOP_PREG(left)) {
5172                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5173                         aopPut(AOP(result),"a",offset);
5174                     } else
5175                         emitcode("xrl","%s,a",
5176                                  aopGet(AOP(left),offset,FALSE,TRUE));
5177                 }
5178             }
5179         }
5180     } else {
5181         // left & result in different registers
5182         if(AOP_TYPE(result) == AOP_CRY){
5183             // result = bit
5184             // if(size), result in bit
5185             // if(!size && ifx), conditional oper: if(left ^ right)
5186             symbol *tlbl = newiTempLabel(NULL);
5187             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5188             if(size)
5189                 emitcode("setb","c");
5190             while(sizer--){
5191                 if((AOP_TYPE(right) == AOP_LIT) &&
5192                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5193                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5194                 } else {
5195                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5196                     emitcode("xrl","a,%s",
5197                              aopGet(AOP(left),offset,FALSE,FALSE));
5198                 }
5199                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5200                 offset++;
5201             }
5202             if(size){
5203                 CLRC;
5204                 emitcode("","%05d_DS_:",tlbl->key+100);
5205                 outBitC(result);
5206             } else if(ifx)
5207                 jmpTrueOrFalse(ifx, tlbl);
5208         } else for(;(size--);offset++){
5209             // normal case
5210             // result = left & right
5211             if(AOP_TYPE(right) == AOP_LIT){
5212               int t = (lit >> (offset*8)) & 0x0FFL;
5213               switch(t) { 
5214               case 0x00:
5215                 emitcode("movf","%s,w",
5216                          aopGet(AOP(left),offset,FALSE,FALSE));
5217                 emitcode("movwf","%s",
5218                          aopGet(AOP(result),offset,FALSE,FALSE));
5219                 break;
5220               case 0xff:
5221                 emitcode("comf","%s,w",
5222                          aopGet(AOP(left),offset,FALSE,FALSE));
5223                 emitcode("movwf","%s",
5224                          aopGet(AOP(result),offset,FALSE,FALSE));
5225                 break;
5226               default:
5227                 emitcode("movlw","0x%x",t);
5228                 emitcode("xorwf","%s,w",
5229                          aopGet(AOP(left),offset,FALSE,FALSE));
5230                 emitcode("movwf","%s",
5231                          aopGet(AOP(result),offset,FALSE,FALSE));
5232
5233               }
5234               continue;
5235             }
5236
5237             // faster than result <- left, anl result,right
5238             // and better if result is SFR
5239             if (AOP_TYPE(left) == AOP_ACC)
5240                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5241             else {
5242                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5243                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5244             }
5245             if ( AOP_TYPE(result) != AOP_ACC)
5246               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5247         }
5248     }
5249
5250 release :
5251     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5252     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5253     freeAsmop(result,NULL,ic,TRUE);     
5254 }
5255
5256 /*-----------------------------------------------------------------*/
5257 /* genInline - write the inline code out                           */
5258 /*-----------------------------------------------------------------*/
5259 static void genInline (iCode *ic)
5260 {
5261     char buffer[MAX_INLINEASM];
5262     char *bp = buffer;
5263     char *bp1= buffer;
5264     
5265     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5266
5267     _G.inLine += (!options.asmpeep);
5268     strcpy(buffer,IC_INLINE(ic));
5269
5270     /* emit each line as a code */
5271     while (*bp) {
5272         if (*bp == '\n') {
5273             *bp++ = '\0';
5274             emitcode(bp1,"");
5275             bp1 = bp;
5276         } else {
5277             if (*bp == ':') {
5278                 bp++;
5279                 *bp = '\0';
5280                 bp++;
5281                 emitcode(bp1,"");
5282                 bp1 = bp;
5283             } else
5284                 bp++;
5285         }
5286     }
5287     if (bp1 != bp)
5288         emitcode(bp1,"");
5289     /*     emitcode("",buffer); */
5290     _G.inLine -= (!options.asmpeep);
5291 }
5292
5293 /*-----------------------------------------------------------------*/
5294 /* genRRC - rotate right with carry                                */
5295 /*-----------------------------------------------------------------*/
5296 static void genRRC (iCode *ic)
5297 {
5298     operand *left , *result ;
5299     int size, offset = 0;
5300     char *l;    
5301
5302     /* rotate right with carry */
5303     left = IC_LEFT(ic);
5304     result=IC_RESULT(ic);
5305     aopOp (left,ic,FALSE);
5306     aopOp (result,ic,FALSE);
5307
5308     /* move it to the result */
5309     size = AOP_SIZE(result);    
5310     offset = size - 1 ;
5311     CLRC;
5312     while (size--) {
5313         l = aopGet(AOP(left),offset,FALSE,FALSE);
5314         MOVA(l);
5315         emitcode("rrc","a");
5316         if (AOP_SIZE(result) > 1)
5317             aopPut(AOP(result),"a",offset--);
5318     }
5319     /* now we need to put the carry into the
5320     highest order byte of the result */
5321     if (AOP_SIZE(result) > 1) {
5322         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5323         MOVA(l);
5324     }
5325     emitcode("mov","acc.7,c");
5326     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5327     freeAsmop(left,NULL,ic,TRUE);
5328     freeAsmop(result,NULL,ic,TRUE);
5329 }
5330
5331 /*-----------------------------------------------------------------*/
5332 /* genRLC - generate code for rotate left with carry               */
5333 /*-----------------------------------------------------------------*/
5334 static void genRLC (iCode *ic)
5335 {    
5336     operand *left , *result ;
5337     int size, offset = 0;
5338     char *l;    
5339
5340     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5341     /* rotate right with carry */
5342     left = IC_LEFT(ic);
5343     result=IC_RESULT(ic);
5344     aopOp (left,ic,FALSE);
5345     aopOp (result,ic,FALSE);
5346
5347     /* move it to the result */
5348     size = AOP_SIZE(result);    
5349     offset = 0 ;
5350     if (size--) {
5351         l = aopGet(AOP(left),offset,FALSE,FALSE);
5352         MOVA(l);
5353         emitcode("add","a,acc");
5354         if (AOP_SIZE(result) > 1)
5355             aopPut(AOP(result),"a",offset++);
5356         while (size--) {
5357             l = aopGet(AOP(left),offset,FALSE,FALSE);
5358             MOVA(l);
5359             emitcode("rlc","a");
5360             if (AOP_SIZE(result) > 1)
5361                 aopPut(AOP(result),"a",offset++);
5362         }
5363     }
5364     /* now we need to put the carry into the
5365     highest order byte of the result */
5366     if (AOP_SIZE(result) > 1) {
5367         l = aopGet(AOP(result),0,FALSE,FALSE);
5368         MOVA(l);
5369     }
5370     emitcode("mov","acc.0,c");
5371     aopPut(AOP(result),"a",0);
5372     freeAsmop(left,NULL,ic,TRUE);
5373     freeAsmop(result,NULL,ic,TRUE);
5374 }
5375
5376 /*-----------------------------------------------------------------*/
5377 /* genGetHbit - generates code get highest order bit               */
5378 /*-----------------------------------------------------------------*/
5379 static void genGetHbit (iCode *ic)
5380 {
5381     operand *left, *result;
5382     left = IC_LEFT(ic);
5383     result=IC_RESULT(ic);
5384     aopOp (left,ic,FALSE);
5385     aopOp (result,ic,FALSE);
5386
5387     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5388     /* get the highest order byte into a */
5389     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5390     if(AOP_TYPE(result) == AOP_CRY){
5391         emitcode("rlc","a");
5392         outBitC(result);
5393     }
5394     else{
5395         emitcode("rl","a");
5396         emitcode("anl","a,#0x01");
5397         outAcc(result);
5398     }
5399
5400
5401     freeAsmop(left,NULL,ic,TRUE);
5402     freeAsmop(result,NULL,ic,TRUE);
5403 }
5404
5405 /*-----------------------------------------------------------------*/
5406 /* AccRol - rotate left accumulator by known count                 */
5407 /*-----------------------------------------------------------------*/
5408 static void AccRol (int shCount)
5409 {
5410     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5411     shCount &= 0x0007;              // shCount : 0..7
5412     switch(shCount){
5413         case 0 :
5414             break;
5415         case 1 :
5416             emitcode("rl","a");
5417             break;
5418         case 2 :
5419             emitcode("rl","a");
5420             emitcode("rl","a");
5421             break;
5422         case 3 :
5423             emitcode("swap","a");
5424             emitcode("rr","a");
5425             break;
5426         case 4 :
5427             emitcode("swap","a");
5428             break;
5429         case 5 :
5430             emitcode("swap","a");
5431             emitcode("rl","a");
5432             break;
5433         case 6 :
5434             emitcode("rr","a");
5435             emitcode("rr","a");
5436             break;
5437         case 7 :
5438             emitcode("rr","a");
5439             break;
5440     }
5441 }
5442
5443 /*-----------------------------------------------------------------*/
5444 /* AccLsh - left shift accumulator by known count                  */
5445 /*-----------------------------------------------------------------*/
5446 static void AccLsh (int shCount)
5447 {
5448     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5449     if(shCount != 0){
5450         if(shCount == 1)
5451             emitcode("add","a,acc");
5452         else 
5453             if(shCount == 2) {
5454             emitcode("add","a,acc");
5455             emitcode("add","a,acc");
5456         } else {
5457             /* rotate left accumulator */
5458             AccRol(shCount);
5459             /* and kill the lower order bits */
5460             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5461         }
5462     }
5463 }
5464
5465 /*-----------------------------------------------------------------*/
5466 /* AccRsh - right shift accumulator by known count                 */
5467 /*-----------------------------------------------------------------*/
5468 static void AccRsh (int shCount)
5469 {
5470     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5471     if(shCount != 0){
5472         if(shCount == 1){
5473             CLRC;
5474             emitcode("rrc","a");
5475         } else {
5476             /* rotate right accumulator */
5477             AccRol(8 - shCount);
5478             /* and kill the higher order bits */
5479             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5480         }
5481     }
5482 }
5483
5484 /*-----------------------------------------------------------------*/
5485 /* AccSRsh - signed right shift accumulator by known count                 */
5486 /*-----------------------------------------------------------------*/
5487 static void AccSRsh (int shCount)
5488 {
5489     symbol *tlbl ;
5490     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5491     if(shCount != 0){
5492         if(shCount == 1){
5493             emitcode("mov","c,acc.7");
5494             emitcode("rrc","a");
5495         } else if(shCount == 2){
5496             emitcode("mov","c,acc.7");
5497             emitcode("rrc","a");
5498             emitcode("mov","c,acc.7");
5499             emitcode("rrc","a");
5500         } else {
5501             tlbl = newiTempLabel(NULL);
5502             /* rotate right accumulator */
5503             AccRol(8 - shCount);
5504             /* and kill the higher order bits */
5505             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5506             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5507             emitcode("orl","a,#0x%02x",
5508                      (unsigned char)~SRMask[shCount]);
5509             emitcode("","%05d_DS_:",tlbl->key+100);
5510         }
5511     }
5512 }
5513
5514 /*-----------------------------------------------------------------*/
5515 /* shiftR1Left2Result - shift right one byte from left to result   */
5516 /*-----------------------------------------------------------------*/
5517 static void shiftR1Left2Result (operand *left, int offl,
5518                                 operand *result, int offr,
5519                                 int shCount, int sign)
5520 {
5521     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5522     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5523     /* shift right accumulator */
5524     if(sign)
5525         AccSRsh(shCount);
5526     else
5527         AccRsh(shCount);
5528     aopPut(AOP(result),"a",offr);
5529 }
5530
5531 /*-----------------------------------------------------------------*/
5532 /* shiftL1Left2Result - shift left one byte from left to result    */
5533 /*-----------------------------------------------------------------*/
5534 static void shiftL1Left2Result (operand *left, int offl,
5535                                 operand *result, int offr, int shCount)
5536 {
5537     char *l;
5538     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5539     l = aopGet(AOP(left),offl,FALSE,FALSE);
5540     MOVA(l);
5541     /* shift left accumulator */
5542     AccLsh(shCount);
5543     aopPut(AOP(result),"a",offr);
5544 }
5545
5546 /*-----------------------------------------------------------------*/
5547 /* movLeft2Result - move byte from left to result                  */
5548 /*-----------------------------------------------------------------*/
5549 static void movLeft2Result (operand *left, int offl,
5550                             operand *result, int offr, int sign)
5551 {
5552     char *l;
5553     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5554     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5555         l = aopGet(AOP(left),offl,FALSE,FALSE);
5556
5557         if (*l == '@' && (IS_AOP_PREG(result))) {
5558             emitcode("mov","a,%s",l);
5559             aopPut(AOP(result),"a",offr);
5560         } else {
5561             if(!sign)
5562                 aopPut(AOP(result),l,offr);
5563             else{
5564                 /* MSB sign in acc.7 ! */
5565                 if(getDataSize(left) == offl+1){
5566                     emitcode("mov","a,%s",l);
5567                     aopPut(AOP(result),"a",offr);
5568                 }
5569             }
5570         }
5571     }
5572 }
5573
5574 /*-----------------------------------------------------------------*/
5575 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5576 /*-----------------------------------------------------------------*/
5577 static void AccAXRrl1 (char *x)
5578 {
5579     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5580     emitcode("rrc","a");
5581     emitcode("xch","a,%s", x);
5582     emitcode("rrc","a");
5583     emitcode("xch","a,%s", x);
5584 }
5585
5586 /*-----------------------------------------------------------------*/
5587 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5588 /*-----------------------------------------------------------------*/
5589 static void AccAXLrl1 (char *x)
5590 {
5591     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5592     emitcode("xch","a,%s",x);
5593     emitcode("rlc","a");
5594     emitcode("xch","a,%s",x);
5595     emitcode("rlc","a");
5596 }
5597
5598 /*-----------------------------------------------------------------*/
5599 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5600 /*-----------------------------------------------------------------*/
5601 static void AccAXLsh1 (char *x)
5602 {
5603     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5604     emitcode("xch","a,%s",x);
5605     emitcode("add","a,acc");
5606     emitcode("xch","a,%s",x);
5607     emitcode("rlc","a");
5608 }
5609
5610 /*-----------------------------------------------------------------*/
5611 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5612 /*-----------------------------------------------------------------*/
5613 static void AccAXLsh (char *x, int shCount)
5614 {
5615     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5616     switch(shCount){
5617         case 0 :
5618             break;
5619         case 1 :
5620             AccAXLsh1(x);
5621             break;
5622         case 2 :
5623             AccAXLsh1(x);
5624             AccAXLsh1(x);
5625             break;
5626         case 3 :
5627         case 4 :
5628         case 5 :                        // AAAAABBB:CCCCCDDD
5629             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5630             emitcode("anl","a,#0x%02x",
5631                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5632             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5633             AccRol(shCount);            // DDDCCCCC:BBB00000
5634             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5635             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5636             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5637             emitcode("anl","a,#0x%02x",
5638                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5639             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5640             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5641             break;
5642         case 6 :                        // AAAAAABB:CCCCCCDD
5643             emitcode("anl","a,#0x%02x",
5644                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5645             emitcode("mov","c,acc.0");  // c = B
5646             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5647             AccAXRrl1(x);               // BCCCCCCD:D000000B
5648             AccAXRrl1(x);               // BBCCCCCC:DD000000
5649             break;
5650         case 7 :                        // a:x <<= 7
5651             emitcode("anl","a,#0x%02x",
5652                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5653             emitcode("mov","c,acc.0");  // c = B
5654             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5655             AccAXRrl1(x);               // BCCCCCCC:D0000000
5656             break;
5657         default :
5658             break;
5659     }
5660 }
5661
5662 /*-----------------------------------------------------------------*/
5663 /* AccAXRsh - right shift a:x known count (0..7)                   */
5664 /*-----------------------------------------------------------------*/
5665 static void AccAXRsh (char *x, int shCount)
5666 {   
5667     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5668     switch(shCount){
5669         case 0 :
5670             break;
5671         case 1 :
5672             CLRC;
5673             AccAXRrl1(x);               // 0->a:x
5674             break;
5675         case 2 :
5676             CLRC;
5677             AccAXRrl1(x);               // 0->a:x
5678             CLRC;
5679             AccAXRrl1(x);               // 0->a:x
5680             break;
5681         case 3 :
5682         case 4 :
5683         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5684             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5685             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5686             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5687             emitcode("anl","a,#0x%02x",
5688                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5689             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5690             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5691             emitcode("anl","a,#0x%02x",
5692                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5693             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5694             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5695             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5696             break;
5697         case 6 :                        // AABBBBBB:CCDDDDDD
5698             emitcode("mov","c,acc.7");
5699             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5700             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5701             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5702             emitcode("anl","a,#0x%02x",
5703                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5704             break;
5705         case 7 :                        // ABBBBBBB:CDDDDDDD
5706             emitcode("mov","c,acc.7");  // c = A
5707             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5708             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5709             emitcode("anl","a,#0x%02x",
5710                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5711             break;
5712         default :
5713             break;
5714     }
5715 }
5716
5717 /*-----------------------------------------------------------------*/
5718 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5719 /*-----------------------------------------------------------------*/
5720 static void AccAXRshS (char *x, int shCount)
5721 {   
5722     symbol *tlbl ;
5723     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5724     switch(shCount){
5725         case 0 :
5726             break;
5727         case 1 :
5728             emitcode("mov","c,acc.7");
5729             AccAXRrl1(x);               // s->a:x
5730             break;
5731         case 2 :
5732             emitcode("mov","c,acc.7");
5733             AccAXRrl1(x);               // s->a:x
5734             emitcode("mov","c,acc.7");
5735             AccAXRrl1(x);               // s->a:x
5736             break;
5737         case 3 :
5738         case 4 :
5739         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5740             tlbl = newiTempLabel(NULL);
5741             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5742             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5743             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5744             emitcode("anl","a,#0x%02x",
5745                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5746             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5747             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5748             emitcode("anl","a,#0x%02x",
5749                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5750             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5751             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5752             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5753             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
5754             emitcode("orl","a,#0x%02x",
5755                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5756             emitcode("","%05d_DS_:",tlbl->key+100);
5757             break;                      // SSSSAAAA:BBBCCCCC
5758         case 6 :                        // AABBBBBB:CCDDDDDD
5759             tlbl = newiTempLabel(NULL);
5760             emitcode("mov","c,acc.7");
5761             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5762             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5763             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5764             emitcode("anl","a,#0x%02x",
5765                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5766             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
5767             emitcode("orl","a,#0x%02x",
5768                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5769             emitcode("","%05d_DS_:",tlbl->key+100);
5770             break;
5771         case 7 :                        // ABBBBBBB:CDDDDDDD
5772             tlbl = newiTempLabel(NULL);
5773             emitcode("mov","c,acc.7");  // c = A
5774             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5775             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5776             emitcode("anl","a,#0x%02x",
5777                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5778             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
5779             emitcode("orl","a,#0x%02x",
5780                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5781             emitcode("","%05d_DS_:",tlbl->key+100);
5782             break;
5783         default :
5784             break;
5785     }
5786 }
5787
5788 /*-----------------------------------------------------------------*/
5789 /* shiftL2Left2Result - shift left two bytes from left to result   */
5790 /*-----------------------------------------------------------------*/
5791 static void shiftL2Left2Result (operand *left, int offl,
5792                                 operand *result, int offr, int shCount)
5793 {
5794     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5795     if(sameRegs(AOP(result), AOP(left)) &&
5796        ((offl + MSB16) == offr)){
5797         /* don't crash result[offr] */
5798         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5799         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5800     } else {
5801         movLeft2Result(left,offl, result, offr, 0);
5802         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5803     }
5804     /* ax << shCount (x = lsb(result))*/
5805     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5806     aopPut(AOP(result),"a",offr+MSB16);
5807 }
5808
5809
5810 /*-----------------------------------------------------------------*/
5811 /* shiftR2Left2Result - shift right two bytes from left to result  */
5812 /*-----------------------------------------------------------------*/
5813 static void shiftR2Left2Result (operand *left, int offl,
5814                                 operand *result, int offr,
5815                                 int shCount, int sign)
5816 {
5817     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5818     if(sameRegs(AOP(result), AOP(left)) &&
5819        ((offl + MSB16) == offr)){
5820         /* don't crash result[offr] */
5821         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5822         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5823     } else {
5824         movLeft2Result(left,offl, result, offr, 0);
5825         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5826     }
5827     /* a:x >> shCount (x = lsb(result))*/
5828     if(sign)
5829         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5830     else
5831         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5832     if(getDataSize(result) > 1)
5833         aopPut(AOP(result),"a",offr+MSB16);
5834 }
5835
5836 /*-----------------------------------------------------------------*/
5837 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5838 /*-----------------------------------------------------------------*/
5839 static void shiftLLeftOrResult (operand *left, int offl,
5840                                 operand *result, int offr, int shCount)
5841 {
5842     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5843     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5844     /* shift left accumulator */
5845     AccLsh(shCount);
5846     /* or with result */
5847     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5848     /* back to result */
5849     aopPut(AOP(result),"a",offr);
5850 }
5851
5852 /*-----------------------------------------------------------------*/
5853 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5854 /*-----------------------------------------------------------------*/
5855 static void shiftRLeftOrResult (operand *left, int offl,
5856                                 operand *result, int offr, int shCount)
5857 {
5858     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5859     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5860     /* shift right accumulator */
5861     AccRsh(shCount);
5862     /* or with result */
5863     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5864     /* back to result */
5865     aopPut(AOP(result),"a",offr);
5866 }
5867
5868 /*-----------------------------------------------------------------*/
5869 /* genlshOne - left shift a one byte quantity by known count       */
5870 /*-----------------------------------------------------------------*/
5871 static void genlshOne (operand *result, operand *left, int shCount)
5872 {       
5873     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5874     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5875 }
5876
5877 /*-----------------------------------------------------------------*/
5878 /* genlshTwo - left shift two bytes by known amount != 0           */
5879 /*-----------------------------------------------------------------*/
5880 static void genlshTwo (operand *result,operand *left, int shCount)
5881 {
5882     int size;
5883     
5884     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5885     size = getDataSize(result);
5886
5887     /* if shCount >= 8 */
5888     if (shCount >= 8) {
5889         shCount -= 8 ;
5890
5891         if (size > 1){
5892             if (shCount)
5893                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5894             else 
5895                 movLeft2Result(left, LSB, result, MSB16, 0);
5896         }
5897         aopPut(AOP(result),zero,LSB);   
5898     }
5899
5900     /*  1 <= shCount <= 7 */
5901     else {  
5902         if(size == 1)
5903             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5904         else 
5905             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5906     }
5907 }
5908
5909 /*-----------------------------------------------------------------*/
5910 /* shiftLLong - shift left one long from left to result            */
5911 /* offl = LSB or MSB16                                             */
5912 /*-----------------------------------------------------------------*/
5913 static void shiftLLong (operand *left, operand *result, int offr )
5914 {
5915     char *l;
5916     int size = AOP_SIZE(result);
5917
5918     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5919     if(size >= LSB+offr){
5920         l = aopGet(AOP(left),LSB,FALSE,FALSE);
5921         MOVA(l);
5922         emitcode("add","a,acc");
5923         if (sameRegs(AOP(left),AOP(result)) && 
5924             size >= MSB16+offr && offr != LSB )
5925             emitcode("xch","a,%s",
5926                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5927         else        
5928             aopPut(AOP(result),"a",LSB+offr);
5929     }
5930
5931     if(size >= MSB16+offr){
5932         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5933             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5934             MOVA(l);
5935         }
5936         emitcode("rlc","a");
5937         if (sameRegs(AOP(left),AOP(result)) && 
5938             size >= MSB24+offr && offr != LSB)
5939             emitcode("xch","a,%s",
5940                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5941         else        
5942             aopPut(AOP(result),"a",MSB16+offr);
5943     }
5944
5945     if(size >= MSB24+offr){
5946         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5947             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5948             MOVA(l);
5949         }
5950         emitcode("rlc","a");
5951         if (sameRegs(AOP(left),AOP(result)) && 
5952             size >= MSB32+offr && offr != LSB )
5953             emitcode("xch","a,%s",
5954                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5955         else        
5956             aopPut(AOP(result),"a",MSB24+offr);
5957     }
5958
5959     if(size > MSB32+offr){
5960         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5961             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5962             MOVA(l);    
5963         }
5964         emitcode("rlc","a");
5965         aopPut(AOP(result),"a",MSB32+offr);
5966     }
5967     if(offr != LSB)
5968         aopPut(AOP(result),zero,LSB);       
5969 }
5970
5971 /*-----------------------------------------------------------------*/
5972 /* genlshFour - shift four byte by a known amount != 0             */
5973 /*-----------------------------------------------------------------*/
5974 static void genlshFour (operand *result, operand *left, int shCount)
5975 {
5976     int size;
5977
5978     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5979     size = AOP_SIZE(result);
5980
5981     /* if shifting more that 3 bytes */
5982     if (shCount >= 24 ) {
5983         shCount -= 24;
5984         if (shCount)
5985             /* lowest order of left goes to the highest
5986             order of the destination */
5987             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5988         else
5989             movLeft2Result(left, LSB, result, MSB32, 0);
5990         aopPut(AOP(result),zero,LSB);
5991         aopPut(AOP(result),zero,MSB16);
5992         aopPut(AOP(result),zero,MSB32);
5993         return;
5994     }
5995
5996     /* more than two bytes */
5997     else if ( shCount >= 16 ) {
5998         /* lower order two bytes goes to higher order two bytes */
5999         shCount -= 16;
6000         /* if some more remaining */
6001         if (shCount)
6002             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6003         else {
6004             movLeft2Result(left, MSB16, result, MSB32, 0);
6005             movLeft2Result(left, LSB, result, MSB24, 0);
6006         }
6007         aopPut(AOP(result),zero,MSB16);
6008         aopPut(AOP(result),zero,LSB);
6009         return;
6010     }    
6011
6012     /* if more than 1 byte */
6013     else if ( shCount >= 8 ) {
6014         /* lower order three bytes goes to higher order  three bytes */
6015         shCount -= 8;
6016         if(size == 2){
6017             if(shCount)
6018                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6019             else
6020                 movLeft2Result(left, LSB, result, MSB16, 0);
6021         }
6022         else{   /* size = 4 */
6023             if(shCount == 0){
6024                 movLeft2Result(left, MSB24, result, MSB32, 0);
6025                 movLeft2Result(left, MSB16, result, MSB24, 0);
6026                 movLeft2Result(left, LSB, result, MSB16, 0);
6027                 aopPut(AOP(result),zero,LSB);
6028             }
6029             else if(shCount == 1)
6030                 shiftLLong(left, result, MSB16);
6031             else{
6032                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6033                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6034                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6035                 aopPut(AOP(result),zero,LSB);
6036             }
6037         }
6038     }
6039
6040     /* 1 <= shCount <= 7 */
6041     else if(shCount <= 2){
6042         shiftLLong(left, result, LSB);
6043         if(shCount == 2)
6044             shiftLLong(result, result, LSB);
6045     }
6046     /* 3 <= shCount <= 7, optimize */
6047     else{
6048         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6049         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6050         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6051     }
6052 }
6053
6054 /*-----------------------------------------------------------------*/
6055 /* genLeftShiftLiteral - left shifting by known count              */
6056 /*-----------------------------------------------------------------*/
6057 static void genLeftShiftLiteral (operand *left,
6058                                  operand *right,
6059                                  operand *result,
6060                                  iCode *ic)
6061 {    
6062     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6063     int size;
6064
6065     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6066     freeAsmop(right,NULL,ic,TRUE);
6067
6068     aopOp(left,ic,FALSE);
6069     aopOp(result,ic,FALSE);
6070
6071     size = getSize(operandType(result));
6072
6073 #if VIEW_SIZE
6074     emitcode("; shift left ","result %d, left %d",size,
6075              AOP_SIZE(left));
6076 #endif
6077
6078     /* I suppose that the left size >= result size */
6079     if(shCount == 0){
6080         while(size--){
6081             movLeft2Result(left, size, result, size, 0);
6082         }
6083     }
6084
6085     else if(shCount >= (size * 8))
6086         while(size--)
6087             aopPut(AOP(result),zero,size);
6088     else{
6089         switch (size) {
6090             case 1:
6091                 genlshOne (result,left,shCount);
6092                 break;
6093
6094             case 2:
6095             case 3:
6096                 genlshTwo (result,left,shCount);
6097                 break;
6098
6099             case 4:
6100                 genlshFour (result,left,shCount);
6101                 break;
6102         }
6103     }
6104     freeAsmop(left,NULL,ic,TRUE);
6105     freeAsmop(result,NULL,ic,TRUE);
6106 }
6107
6108 /*-----------------------------------------------------------------*/
6109 /* genLeftShift - generates code for left shifting                 */
6110 /*-----------------------------------------------------------------*/
6111 static void genLeftShift (iCode *ic)
6112 {
6113     operand *left,*right, *result;
6114     int size, offset;
6115     char *l;
6116     symbol *tlbl , *tlbl1;
6117
6118     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6119
6120     right = IC_RIGHT(ic);
6121     left  = IC_LEFT(ic);
6122     result = IC_RESULT(ic);
6123
6124     aopOp(right,ic,FALSE);
6125
6126     /* if the shift count is known then do it 
6127     as efficiently as possible */
6128     if (AOP_TYPE(right) == AOP_LIT) {
6129         genLeftShiftLiteral (left,right,result,ic);
6130         return ;
6131     }
6132
6133     /* shift count is unknown then we have to form 
6134     a loop get the loop count in B : Note: we take
6135     only the lower order byte since shifting
6136     more that 32 bits make no sense anyway, ( the
6137     largest size of an object can be only 32 bits ) */  
6138
6139     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6140     emitcode("inc","b");
6141     freeAsmop (right,NULL,ic,TRUE);
6142     aopOp(left,ic,FALSE);
6143     aopOp(result,ic,FALSE);
6144
6145     /* now move the left to the result if they are not the
6146     same */
6147     if (!sameRegs(AOP(left),AOP(result)) && 
6148         AOP_SIZE(result) > 1) {
6149
6150         size = AOP_SIZE(result);
6151         offset=0;
6152         while (size--) {
6153             l = aopGet(AOP(left),offset,FALSE,TRUE);
6154             if (*l == '@' && (IS_AOP_PREG(result))) {
6155
6156                 emitcode("mov","a,%s",l);
6157                 aopPut(AOP(result),"a",offset);
6158             } else
6159                 aopPut(AOP(result),l,offset);
6160             offset++;
6161         }
6162     }
6163
6164     tlbl = newiTempLabel(NULL);
6165     size = AOP_SIZE(result);
6166     offset = 0 ;   
6167     tlbl1 = newiTempLabel(NULL);
6168
6169     /* if it is only one byte then */
6170     if (size == 1) {
6171         symbol *tlbl1 = newiTempLabel(NULL);
6172
6173         l = aopGet(AOP(left),0,FALSE,FALSE);
6174         MOVA(l);
6175         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6176         emitcode("","%05d_DS_:",tlbl->key+100);
6177         emitcode("add","a,acc");
6178         emitcode("","%05d_DS_:",tlbl1->key+100);
6179         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6180         aopPut(AOP(result),"a",0);
6181         goto release ;
6182     }
6183     
6184     reAdjustPreg(AOP(result));    
6185     
6186     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6187     emitcode("","%05d_DS_:",tlbl->key+100);    
6188     l = aopGet(AOP(result),offset,FALSE,FALSE);
6189     MOVA(l);
6190     emitcode("add","a,acc");         
6191     aopPut(AOP(result),"a",offset++);
6192     while (--size) {
6193         l = aopGet(AOP(result),offset,FALSE,FALSE);
6194         MOVA(l);
6195         emitcode("rlc","a");         
6196         aopPut(AOP(result),"a",offset++);
6197     }
6198     reAdjustPreg(AOP(result));
6199
6200     emitcode("","%05d_DS_:",tlbl1->key+100);
6201     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6202 release:
6203     freeAsmop(left,NULL,ic,TRUE);
6204     freeAsmop(result,NULL,ic,TRUE);
6205 }
6206
6207 /*-----------------------------------------------------------------*/
6208 /* genrshOne - right shift a one byte quantity by known count      */
6209 /*-----------------------------------------------------------------*/
6210 static void genrshOne (operand *result, operand *left,
6211                        int shCount, int sign)
6212 {
6213     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6214     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* genrshTwo - right shift two bytes by known amount != 0          */
6219 /*-----------------------------------------------------------------*/
6220 static void genrshTwo (operand *result,operand *left,
6221                        int shCount, int sign)
6222 {
6223     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6224     /* if shCount >= 8 */
6225     if (shCount >= 8) {
6226         shCount -= 8 ;
6227         if (shCount)
6228             shiftR1Left2Result(left, MSB16, result, LSB,
6229                                shCount, sign);
6230         else 
6231             movLeft2Result(left, MSB16, result, LSB, sign);
6232         addSign(result, MSB16, sign);
6233     }
6234
6235     /*  1 <= shCount <= 7 */
6236     else
6237         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6238 }
6239
6240 /*-----------------------------------------------------------------*/
6241 /* shiftRLong - shift right one long from left to result           */
6242 /* offl = LSB or MSB16                                             */
6243 /*-----------------------------------------------------------------*/
6244 static void shiftRLong (operand *left, int offl,
6245                         operand *result, int sign)
6246 {
6247     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6248     if(!sign)
6249         emitcode("clr","c");
6250     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6251     if(sign)
6252         emitcode("mov","c,acc.7");
6253     emitcode("rrc","a");
6254     aopPut(AOP(result),"a",MSB32-offl);
6255     if(offl == MSB16)
6256         /* add sign of "a" */
6257         addSign(result, MSB32, sign);
6258
6259     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6260     emitcode("rrc","a");
6261     aopPut(AOP(result),"a",MSB24-offl);
6262
6263     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6264     emitcode("rrc","a");
6265     aopPut(AOP(result),"a",MSB16-offl);
6266
6267     if(offl == LSB){
6268         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6269         emitcode("rrc","a");
6270         aopPut(AOP(result),"a",LSB);
6271     }
6272 }
6273
6274 /*-----------------------------------------------------------------*/
6275 /* genrshFour - shift four byte by a known amount != 0             */
6276 /*-----------------------------------------------------------------*/
6277 static void genrshFour (operand *result, operand *left,
6278                         int shCount, int sign)
6279 {
6280     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6281     /* if shifting more that 3 bytes */
6282     if(shCount >= 24 ) {
6283         shCount -= 24;
6284         if(shCount)
6285             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6286         else
6287             movLeft2Result(left, MSB32, result, LSB, sign);
6288         addSign(result, MSB16, sign);
6289     }
6290     else if(shCount >= 16){
6291         shCount -= 16;
6292         if(shCount)
6293             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6294         else{
6295             movLeft2Result(left, MSB24, result, LSB, 0);
6296             movLeft2Result(left, MSB32, result, MSB16, sign);
6297         }
6298         addSign(result, MSB24, sign);
6299     }
6300     else if(shCount >= 8){
6301         shCount -= 8;
6302         if(shCount == 1)
6303             shiftRLong(left, MSB16, result, sign);
6304         else if(shCount == 0){
6305             movLeft2Result(left, MSB16, result, LSB, 0);
6306             movLeft2Result(left, MSB24, result, MSB16, 0);
6307             movLeft2Result(left, MSB32, result, MSB24, sign);
6308             addSign(result, MSB32, sign);
6309         }
6310         else{
6311             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6312             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6313             /* the last shift is signed */
6314             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6315             addSign(result, MSB32, sign);
6316         }
6317     }
6318     else{   /* 1 <= shCount <= 7 */
6319         if(shCount <= 2){
6320             shiftRLong(left, LSB, result, sign);
6321             if(shCount == 2)
6322                 shiftRLong(result, LSB, result, sign);
6323         }
6324         else{
6325             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6326             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6327             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6328         }
6329     }
6330 }
6331
6332 /*-----------------------------------------------------------------*/
6333 /* genRightShiftLiteral - right shifting by known count            */
6334 /*-----------------------------------------------------------------*/
6335 static void genRightShiftLiteral (operand *left,
6336                                   operand *right,
6337                                   operand *result,
6338                                   iCode *ic,
6339                                   int sign)
6340 {    
6341     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6342     int size;
6343
6344     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6345     freeAsmop(right,NULL,ic,TRUE);
6346
6347     aopOp(left,ic,FALSE);
6348     aopOp(result,ic,FALSE);
6349
6350 #if VIEW_SIZE
6351     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6352              AOP_SIZE(left));
6353 #endif
6354
6355     size = getDataSize(left);
6356     /* test the LEFT size !!! */
6357
6358     /* I suppose that the left size >= result size */
6359     if(shCount == 0){
6360         size = getDataSize(result);
6361         while(size--)
6362             movLeft2Result(left, size, result, size, 0);
6363     }
6364
6365     else if(shCount >= (size * 8)){
6366         if(sign)
6367             /* get sign in acc.7 */
6368             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6369         addSign(result, LSB, sign);
6370     } else{
6371         switch (size) {
6372             case 1:
6373                 genrshOne (result,left,shCount,sign);
6374                 break;
6375
6376             case 2:
6377                 genrshTwo (result,left,shCount,sign);
6378                 break;
6379
6380             case 4:
6381                 genrshFour (result,left,shCount,sign);
6382                 break;
6383             default :
6384                 break;
6385         }
6386
6387         freeAsmop(left,NULL,ic,TRUE);
6388         freeAsmop(result,NULL,ic,TRUE);
6389     }
6390 }
6391
6392 /*-----------------------------------------------------------------*/
6393 /* genSignedRightShift - right shift of signed number              */
6394 /*-----------------------------------------------------------------*/
6395 static void genSignedRightShift (iCode *ic)
6396 {
6397     operand *right, *left, *result;
6398     int size, offset;
6399     char *l;
6400     symbol *tlbl, *tlbl1 ;
6401
6402     /* we do it the hard way put the shift count in b
6403     and loop thru preserving the sign */
6404     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6405
6406     right = IC_RIGHT(ic);
6407     left  = IC_LEFT(ic);
6408     result = IC_RESULT(ic);
6409
6410     aopOp(right,ic,FALSE);  
6411
6412
6413     if ( AOP_TYPE(right) == AOP_LIT) {
6414         genRightShiftLiteral (left,right,result,ic,1);
6415         return ;
6416     }
6417         /* shift count is unknown then we have to form 
6418        a loop get the loop count in B : Note: we take
6419        only the lower order byte since shifting
6420        more that 32 bits make no sense anyway, ( the
6421        largest size of an object can be only 32 bits ) */  
6422
6423     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6424     emitcode("inc","b");
6425     freeAsmop (right,NULL,ic,TRUE);
6426     aopOp(left,ic,FALSE);
6427     aopOp(result,ic,FALSE);
6428
6429     /* now move the left to the result if they are not the
6430     same */
6431     if (!sameRegs(AOP(left),AOP(result)) && 
6432         AOP_SIZE(result) > 1) {
6433
6434         size = AOP_SIZE(result);
6435         offset=0;
6436         while (size--) {
6437             l = aopGet(AOP(left),offset,FALSE,TRUE);
6438             if (*l == '@' && IS_AOP_PREG(result)) {
6439
6440                 emitcode("mov","a,%s",l);
6441                 aopPut(AOP(result),"a",offset);
6442             } else
6443                 aopPut(AOP(result),l,offset);
6444             offset++;
6445         }
6446     }
6447
6448     /* mov the highest order bit to OVR */    
6449     tlbl = newiTempLabel(NULL);
6450     tlbl1= newiTempLabel(NULL);
6451
6452     size = AOP_SIZE(result);
6453     offset = size - 1;
6454     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6455     emitcode("rlc","a");
6456     emitcode("mov","ov,c");
6457     /* if it is only one byte then */
6458     if (size == 1) {
6459         l = aopGet(AOP(left),0,FALSE,FALSE);
6460         MOVA(l);
6461         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6462         emitcode("","%05d_DS_:",tlbl->key+100);
6463         emitcode("mov","c,ov");
6464         emitcode("rrc","a");
6465         emitcode("","%05d_DS_:",tlbl1->key+100);
6466         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6467         aopPut(AOP(result),"a",0);
6468         goto release ;
6469     }
6470
6471     reAdjustPreg(AOP(result));
6472     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6473     emitcode("","%05d_DS_:",tlbl->key+100);    
6474     emitcode("mov","c,ov");
6475     while (size--) {
6476         l = aopGet(AOP(result),offset,FALSE,FALSE);
6477         MOVA(l);
6478         emitcode("rrc","a");         
6479         aopPut(AOP(result),"a",offset--);
6480     }
6481     reAdjustPreg(AOP(result));
6482     emitcode("","%05d_DS_:",tlbl1->key+100);
6483     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6484
6485 release:
6486     freeAsmop(left,NULL,ic,TRUE);
6487     freeAsmop(result,NULL,ic,TRUE);
6488 }
6489
6490 /*-----------------------------------------------------------------*/
6491 /* genRightShift - generate code for right shifting                */
6492 /*-----------------------------------------------------------------*/
6493 static void genRightShift (iCode *ic)
6494 {
6495     operand *right, *left, *result;
6496     sym_link *retype ;
6497     int size, offset;
6498     char *l;
6499     symbol *tlbl, *tlbl1 ;
6500
6501     /* if signed then we do it the hard way preserve the
6502     sign bit moving it inwards */
6503     retype = getSpec(operandType(IC_RESULT(ic)));
6504     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6505
6506     if (!SPEC_USIGN(retype)) {
6507         genSignedRightShift (ic);
6508         return ;
6509     }
6510
6511     /* signed & unsigned types are treated the same : i.e. the
6512     signed is NOT propagated inwards : quoting from the
6513     ANSI - standard : "for E1 >> E2, is equivalent to division
6514     by 2**E2 if unsigned or if it has a non-negative value,
6515     otherwise the result is implementation defined ", MY definition
6516     is that the sign does not get propagated */
6517
6518     right = IC_RIGHT(ic);
6519     left  = IC_LEFT(ic);
6520     result = IC_RESULT(ic);
6521
6522     aopOp(right,ic,FALSE);
6523
6524     /* if the shift count is known then do it 
6525     as efficiently as possible */
6526     if (AOP_TYPE(right) == AOP_LIT) {
6527         genRightShiftLiteral (left,right,result,ic, 0);
6528         return ;
6529     }
6530
6531     /* shift count is unknown then we have to form 
6532     a loop get the loop count in B : Note: we take
6533     only the lower order byte since shifting
6534     more that 32 bits make no sense anyway, ( the
6535     largest size of an object can be only 32 bits ) */  
6536
6537     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6538     emitcode("inc","b");
6539     freeAsmop (right,NULL,ic,TRUE);
6540     aopOp(left,ic,FALSE);
6541     aopOp(result,ic,FALSE);
6542
6543     /* now move the left to the result if they are not the
6544     same */
6545     if (!sameRegs(AOP(left),AOP(result)) && 
6546         AOP_SIZE(result) > 1) {
6547
6548         size = AOP_SIZE(result);
6549         offset=0;
6550         while (size--) {
6551             l = aopGet(AOP(left),offset,FALSE,TRUE);
6552             if (*l == '@' && IS_AOP_PREG(result)) {
6553
6554                 emitcode("mov","a,%s",l);
6555                 aopPut(AOP(result),"a",offset);
6556             } else
6557                 aopPut(AOP(result),l,offset);
6558             offset++;
6559         }
6560     }
6561
6562     tlbl = newiTempLabel(NULL);
6563     tlbl1= newiTempLabel(NULL);
6564     size = AOP_SIZE(result);
6565     offset = size - 1;
6566
6567     /* if it is only one byte then */
6568     if (size == 1) {
6569         l = aopGet(AOP(left),0,FALSE,FALSE);
6570         MOVA(l);
6571         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6572         emitcode("","%05d_DS_:",tlbl->key+100);
6573         CLRC;
6574         emitcode("rrc","a");
6575         emitcode("","%05d_DS_:",tlbl1->key+100);
6576         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6577         aopPut(AOP(result),"a",0);
6578         goto release ;
6579     }
6580
6581     reAdjustPreg(AOP(result));
6582     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6583     emitcode("","%05d_DS_:",tlbl->key+100);    
6584     CLRC;
6585     while (size--) {
6586         l = aopGet(AOP(result),offset,FALSE,FALSE);
6587         MOVA(l);
6588         emitcode("rrc","a");         
6589         aopPut(AOP(result),"a",offset--);
6590     }
6591     reAdjustPreg(AOP(result));
6592
6593     emitcode("","%05d_DS_:",tlbl1->key+100);
6594     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6595
6596 release:
6597     freeAsmop(left,NULL,ic,TRUE);
6598     freeAsmop(result,NULL,ic,TRUE);
6599 }
6600
6601 /*-----------------------------------------------------------------*/
6602 /* genUnpackBits - generates code for unpacking bits               */
6603 /*-----------------------------------------------------------------*/
6604 static void genUnpackBits (operand *result, char *rname, int ptype)
6605 {    
6606     int shCnt ;
6607     int rlen = 0 ;
6608     sym_link *etype;
6609     int offset = 0 ;
6610
6611     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6612     etype = getSpec(operandType(result));
6613
6614     /* read the first byte  */
6615     switch (ptype) {
6616
6617     case POINTER:
6618     case IPOINTER:
6619         emitcode("mov","a,@%s",rname);
6620         break;
6621         
6622     case PPOINTER:
6623         emitcode("movx","a,@%s",rname);
6624         break;
6625         
6626     case FPOINTER:
6627         emitcode("movx","a,@dptr");
6628         break;
6629
6630     case CPOINTER:
6631         emitcode("clr","a");
6632         emitcode("movc","a","@a+dptr");
6633         break;
6634
6635     case GPOINTER:
6636         emitcode("lcall","__gptrget");
6637         break;
6638     }
6639
6640     /* if we have bitdisplacement then it fits   */
6641     /* into this byte completely or if length is */
6642     /* less than a byte                          */
6643     if ((shCnt = SPEC_BSTR(etype)) || 
6644         (SPEC_BLEN(etype) <= 8))  {
6645
6646         /* shift right acc */
6647         AccRsh(shCnt);
6648
6649         emitcode("anl","a,#0x%02x",
6650                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6651         aopPut(AOP(result),"a",offset);
6652         return ;
6653     }
6654
6655     /* bit field did not fit in a byte  */
6656     rlen = SPEC_BLEN(etype) - 8;
6657     aopPut(AOP(result),"a",offset++);
6658
6659     while (1)  {
6660
6661         switch (ptype) {
6662         case POINTER:
6663         case IPOINTER:
6664             emitcode("inc","%s",rname);
6665             emitcode("mov","a,@%s",rname);
6666             break;
6667             
6668         case PPOINTER:
6669             emitcode("inc","%s",rname);
6670             emitcode("movx","a,@%s",rname);
6671             break;
6672
6673         case FPOINTER:
6674             emitcode("inc","dptr");
6675             emitcode("movx","a,@dptr");
6676             break;
6677             
6678         case CPOINTER:
6679             emitcode("clr","a");
6680             emitcode("inc","dptr");
6681             emitcode("movc","a","@a+dptr");
6682             break;
6683             
6684         case GPOINTER:
6685             emitcode("inc","dptr");
6686             emitcode("lcall","__gptrget");
6687             break;
6688         }
6689
6690         rlen -= 8;            
6691         /* if we are done */
6692         if ( rlen <= 0 )
6693             break ;
6694         
6695         aopPut(AOP(result),"a",offset++);
6696                               
6697     }
6698     
6699     if (rlen) {
6700         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6701         aopPut(AOP(result),"a",offset);        
6702     }
6703     
6704     return ;
6705 }
6706
6707
6708 /*-----------------------------------------------------------------*/
6709 /* genDataPointerGet - generates code when ptr offset is known     */
6710 /*-----------------------------------------------------------------*/
6711 static void genDataPointerGet (operand *left, 
6712                                operand *result, 
6713                                iCode *ic)
6714 {
6715     char *l;
6716     char buffer[256];
6717     int size , offset = 0;
6718     aopOp(result,ic,TRUE);
6719
6720     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6721
6722     /* get the string representation of the name */
6723     l = aopGet(AOP(left),0,FALSE,TRUE);
6724     size = AOP_SIZE(result);
6725     // tsd, was l+1 - the underline `_' prefix was being stripped
6726     while (size--) {
6727         if (offset)
6728             sprintf(buffer,"(%s + %d)",l,offset);
6729         else
6730             sprintf(buffer,"%s",l);
6731         aopPut(AOP(result),buffer,offset++);
6732     }
6733
6734     freeAsmop(left,NULL,ic,TRUE);
6735     freeAsmop(result,NULL,ic,TRUE);
6736 }
6737
6738 /*-----------------------------------------------------------------*/
6739 /* genNearPointerGet - emitcode for near pointer fetch             */
6740 /*-----------------------------------------------------------------*/
6741 static void genNearPointerGet (operand *left, 
6742                                operand *result, 
6743                                iCode *ic)
6744 {
6745     asmop *aop = NULL;
6746     regs *preg = NULL ;
6747     char *rname ;
6748     sym_link *rtype, *retype;
6749     sym_link *ltype = operandType(left);    
6750     char buffer[80];
6751
6752     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6753
6754     rtype = operandType(result);
6755     retype= getSpec(rtype);
6756     
6757     aopOp(left,ic,FALSE);
6758     
6759     /* if left is rematerialisable and
6760        result is not bit variable type and
6761        the left is pointer to data space i.e
6762        lower 128 bytes of space */
6763     if (AOP_TYPE(left) == AOP_IMMD &&
6764         !IS_BITVAR(retype)         &&
6765         DCL_TYPE(ltype) == POINTER) {
6766         genDataPointerGet (left,result,ic);
6767         return ;
6768     }
6769     
6770         /* if the value is already in a pointer register
6771        then don't need anything more */
6772     if (!AOP_INPREG(AOP(left))) {
6773         /* otherwise get a free pointer register */
6774         aop = newAsmop(0);
6775         preg = getFreePtr(ic,&aop,FALSE);
6776         emitcode("mov","%s,%s",
6777                 preg->name,
6778                 aopGet(AOP(left),0,FALSE,TRUE));
6779         rname = preg->name ;
6780     } else
6781         rname = aopGet(AOP(left),0,FALSE,FALSE);
6782     
6783     freeAsmop(left,NULL,ic,TRUE);
6784     aopOp (result,ic,FALSE);
6785     
6786       /* if bitfield then unpack the bits */
6787     if (IS_BITVAR(retype)) 
6788         genUnpackBits (result,rname,POINTER);
6789     else {
6790         /* we have can just get the values */
6791         int size = AOP_SIZE(result);
6792         int offset = 0 ;        
6793         
6794         while (size--) {
6795             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6796
6797                 emitcode("mov","a,@%s",rname);
6798                 aopPut(AOP(result),"a",offset);
6799             } else {
6800                 sprintf(buffer,"@%s",rname);
6801                 aopPut(AOP(result),buffer,offset);
6802             }
6803             offset++ ;
6804             if (size)
6805                 emitcode("inc","%s",rname);
6806         }
6807     }
6808
6809     /* now some housekeeping stuff */
6810     if (aop) {
6811         /* we had to allocate for this iCode */
6812         freeAsmop(NULL,aop,ic,TRUE);
6813     } else { 
6814         /* we did not allocate which means left
6815            already in a pointer register, then
6816            if size > 0 && this could be used again
6817            we have to point it back to where it 
6818            belongs */
6819         if (AOP_SIZE(result) > 1 &&
6820             !OP_SYMBOL(left)->remat &&
6821             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6822               ic->depth )) {
6823             int size = AOP_SIZE(result) - 1;
6824             while (size--)
6825                 emitcode("dec","%s",rname);
6826         }
6827     }
6828
6829     /* done */
6830     freeAsmop(result,NULL,ic,TRUE);
6831      
6832 }
6833
6834 /*-----------------------------------------------------------------*/
6835 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6836 /*-----------------------------------------------------------------*/
6837 static void genPagedPointerGet (operand *left, 
6838                                operand *result, 
6839                                iCode *ic)
6840 {
6841     asmop *aop = NULL;
6842     regs *preg = NULL ;
6843     char *rname ;
6844     sym_link *rtype, *retype;    
6845
6846     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6847
6848     rtype = operandType(result);
6849     retype= getSpec(rtype);
6850     
6851     aopOp(left,ic,FALSE);
6852
6853   /* if the value is already in a pointer register
6854        then don't need anything more */
6855     if (!AOP_INPREG(AOP(left))) {
6856         /* otherwise get a free pointer register */
6857         aop = newAsmop(0);
6858         preg = getFreePtr(ic,&aop,FALSE);
6859         emitcode("mov","%s,%s",
6860                 preg->name,
6861                 aopGet(AOP(left),0,FALSE,TRUE));
6862         rname = preg->name ;
6863     } else
6864         rname = aopGet(AOP(left),0,FALSE,FALSE);
6865     
6866     freeAsmop(left,NULL,ic,TRUE);
6867     aopOp (result,ic,FALSE);
6868
6869     /* if bitfield then unpack the bits */
6870     if (IS_BITVAR(retype)) 
6871         genUnpackBits (result,rname,PPOINTER);
6872     else {
6873         /* we have can just get the values */
6874         int size = AOP_SIZE(result);
6875         int offset = 0 ;        
6876         
6877         while (size--) {
6878             
6879             emitcode("movx","a,@%s",rname);
6880             aopPut(AOP(result),"a",offset);
6881             
6882             offset++ ;
6883             
6884             if (size)
6885                 emitcode("inc","%s",rname);
6886         }
6887     }
6888
6889     /* now some housekeeping stuff */
6890     if (aop) {
6891         /* we had to allocate for this iCode */
6892         freeAsmop(NULL,aop,ic,TRUE);
6893     } else { 
6894         /* we did not allocate which means left
6895            already in a pointer register, then
6896            if size > 0 && this could be used again
6897            we have to point it back to where it 
6898            belongs */
6899         if (AOP_SIZE(result) > 1 &&
6900             !OP_SYMBOL(left)->remat &&
6901             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6902               ic->depth )) {
6903             int size = AOP_SIZE(result) - 1;
6904             while (size--)
6905                 emitcode("dec","%s",rname);
6906         }
6907     }
6908
6909     /* done */
6910     freeAsmop(result,NULL,ic,TRUE);
6911     
6912         
6913 }
6914
6915 /*-----------------------------------------------------------------*/
6916 /* genFarPointerGet - gget value from far space                    */
6917 /*-----------------------------------------------------------------*/
6918 static void genFarPointerGet (operand *left,
6919                               operand *result, iCode *ic)
6920 {
6921     int size, offset ;
6922     sym_link *retype = getSpec(operandType(result));
6923
6924     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6925
6926     aopOp(left,ic,FALSE);
6927
6928     /* if the operand is already in dptr 
6929     then we do nothing else we move the value to dptr */
6930     if (AOP_TYPE(left) != AOP_STR) {
6931         /* if this is remateriazable */
6932         if (AOP_TYPE(left) == AOP_IMMD)
6933             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6934         else { /* we need to get it byte by byte */
6935             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6936             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6937             if (options.model == MODEL_FLAT24)
6938             {
6939                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6940             }
6941         }
6942     }
6943     /* so dptr know contains the address */
6944     freeAsmop(left,NULL,ic,TRUE);
6945     aopOp(result,ic,FALSE);
6946
6947     /* if bit then unpack */
6948     if (IS_BITVAR(retype)) 
6949         genUnpackBits(result,"dptr",FPOINTER);
6950     else {
6951         size = AOP_SIZE(result);
6952         offset = 0 ;
6953
6954         while (size--) {
6955             emitcode("movx","a,@dptr");
6956             aopPut(AOP(result),"a",offset++);
6957             if (size)
6958                 emitcode("inc","dptr");
6959         }
6960     }
6961
6962     freeAsmop(result,NULL,ic,TRUE);
6963 }
6964
6965 /*-----------------------------------------------------------------*/
6966 /* emitcodePointerGet - gget value from code space                  */
6967 /*-----------------------------------------------------------------*/
6968 static void emitcodePointerGet (operand *left,
6969                                 operand *result, iCode *ic)
6970 {
6971     int size, offset ;
6972     sym_link *retype = getSpec(operandType(result));
6973
6974     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6975
6976     aopOp(left,ic,FALSE);
6977
6978     /* if the operand is already in dptr 
6979     then we do nothing else we move the value to dptr */
6980     if (AOP_TYPE(left) != AOP_STR) {
6981         /* if this is remateriazable */
6982         if (AOP_TYPE(left) == AOP_IMMD)
6983             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6984         else { /* we need to get it byte by byte */
6985             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6986             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6987             if (options.model == MODEL_FLAT24)
6988             {
6989                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6990             }
6991         }
6992     }
6993     /* so dptr know contains the address */
6994     freeAsmop(left,NULL,ic,TRUE);
6995     aopOp(result,ic,FALSE);
6996
6997     /* if bit then unpack */
6998     if (IS_BITVAR(retype)) 
6999         genUnpackBits(result,"dptr",CPOINTER);
7000     else {
7001         size = AOP_SIZE(result);
7002         offset = 0 ;
7003
7004         while (size--) {
7005             emitcode("clr","a");
7006             emitcode("movc","a,@a+dptr");
7007             aopPut(AOP(result),"a",offset++);
7008             if (size)
7009                 emitcode("inc","dptr");
7010         }
7011     }
7012
7013     freeAsmop(result,NULL,ic,TRUE);
7014 }
7015
7016 /*-----------------------------------------------------------------*/
7017 /* genGenPointerGet - gget value from generic pointer space        */
7018 /*-----------------------------------------------------------------*/
7019 static void genGenPointerGet (operand *left,
7020                               operand *result, iCode *ic)
7021 {
7022     int size, offset ;
7023     sym_link *retype = getSpec(operandType(result));
7024
7025     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7026     aopOp(left,ic,FALSE);
7027
7028     /* if the operand is already in dptr 
7029     then we do nothing else we move the value to dptr */
7030     if (AOP_TYPE(left) != AOP_STR) {
7031         /* if this is remateriazable */
7032         if (AOP_TYPE(left) == AOP_IMMD) {
7033             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7034             emitcode("mov","b,#%d",pointerCode(retype));
7035         }
7036         else { /* we need to get it byte by byte */
7037           
7038           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7039           emitcode("movwf","FSR");
7040           /*
7041             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7042             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7043             if (options.model == MODEL_FLAT24)
7044             {
7045                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7046                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7047             }
7048             else
7049             {
7050                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7051             }
7052           */
7053         }
7054     }
7055     /* so dptr know contains the address */
7056     freeAsmop(left,NULL,ic,TRUE);
7057     aopOp(result,ic,FALSE); 
7058
7059     /* if bit then unpack */
7060     if (IS_BITVAR(retype)) 
7061         genUnpackBits(result,"dptr",GPOINTER);
7062     else {
7063         size = AOP_SIZE(result);
7064         offset = 0 ;
7065
7066         while (size--) {
7067           //emitcode("lcall","__gptrget");
7068             emitcode("movf","indf,w");
7069             //aopPut(AOP(result),"a",offset++);
7070             emitcode("movwf","%s",
7071                      aopGet(AOP(result),offset++,FALSE,FALSE));
7072             if (size)
7073                 emitcode("incf","fsr,f");
7074         }
7075     }
7076
7077     freeAsmop(result,NULL,ic,TRUE);
7078 }
7079
7080 /*-----------------------------------------------------------------*/
7081 /* genPointerGet - generate code for pointer get                   */
7082 /*-----------------------------------------------------------------*/
7083 static void genPointerGet (iCode *ic)
7084 {
7085     operand *left, *result ;
7086     sym_link *type, *etype;
7087     int p_type;
7088
7089     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7090
7091     left = IC_LEFT(ic);
7092     result = IC_RESULT(ic) ;
7093
7094     /* depending on the type of pointer we need to
7095     move it to the correct pointer register */
7096     type = operandType(left);
7097     etype = getSpec(type);
7098     /* if left is of type of pointer then it is simple */
7099     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7100         p_type = DCL_TYPE(type);
7101     else {
7102         /* we have to go by the storage class */
7103         p_type = PTR_TYPE(SPEC_OCLS(etype));
7104
7105 /*      if (SPEC_OCLS(etype)->codesp ) { */
7106 /*          p_type = CPOINTER ;  */
7107 /*      } */
7108 /*      else */
7109 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7110 /*              p_type = FPOINTER ; */
7111 /*          else */
7112 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7113 /*                  p_type = PPOINTER; */
7114 /*              else */
7115 /*                  if (SPEC_OCLS(etype) == idata ) */
7116 /*                      p_type = IPOINTER; */
7117 /*                  else */
7118 /*                      p_type = POINTER ; */
7119     }
7120
7121     /* now that we have the pointer type we assign
7122     the pointer values */
7123     switch (p_type) {
7124
7125     case POINTER:       
7126     case IPOINTER:
7127         genNearPointerGet (left,result,ic);
7128         break;
7129
7130     case PPOINTER:
7131         genPagedPointerGet(left,result,ic);
7132         break;
7133
7134     case FPOINTER:
7135         genFarPointerGet (left,result,ic);
7136         break;
7137
7138     case CPOINTER:
7139         emitcodePointerGet (left,result,ic);
7140         break;
7141
7142     case GPOINTER:
7143         genGenPointerGet (left,result,ic);
7144         break;
7145     }
7146
7147 }
7148
7149 /*-----------------------------------------------------------------*/
7150 /* genPackBits - generates code for packed bit storage             */
7151 /*-----------------------------------------------------------------*/
7152 static void genPackBits (sym_link    *etype ,
7153                          operand *right ,
7154                          char *rname, int p_type)
7155 {
7156     int shCount = 0 ;
7157     int offset = 0  ;
7158     int rLen = 0 ;
7159     int blen, bstr ;   
7160     char *l ;
7161
7162     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7163     blen = SPEC_BLEN(etype);
7164     bstr = SPEC_BSTR(etype);
7165
7166     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7167     MOVA(l);   
7168
7169     /* if the bit lenth is less than or    */
7170     /* it exactly fits a byte then         */
7171     if (SPEC_BLEN(etype) <= 8 )  {
7172         shCount = SPEC_BSTR(etype) ;
7173
7174         /* shift left acc */
7175         AccLsh(shCount);
7176
7177         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7178
7179
7180             switch (p_type) {
7181                 case POINTER:
7182                     emitcode ("mov","b,a");
7183                     emitcode("mov","a,@%s",rname);
7184                     break;
7185
7186                 case FPOINTER:
7187                     emitcode ("mov","b,a");
7188                     emitcode("movx","a,@dptr");
7189                     break;
7190
7191                 case GPOINTER:
7192                     emitcode ("push","b");
7193                     emitcode ("push","acc");
7194                     emitcode ("lcall","__gptrget");
7195                     emitcode ("pop","b");
7196                     break;
7197             }
7198
7199             emitcode ("anl","a,#0x%02x",(unsigned char)
7200                       ((unsigned char)(0xFF << (blen+bstr)) | 
7201                        (unsigned char)(0xFF >> (8-bstr)) ) );
7202             emitcode ("orl","a,b");
7203             if (p_type == GPOINTER)
7204                 emitcode("pop","b");
7205         }
7206     }
7207
7208     switch (p_type) {
7209         case POINTER:
7210             emitcode("mov","@%s,a",rname);
7211             break;
7212
7213         case FPOINTER:
7214             emitcode("movx","@dptr,a");
7215             break;
7216
7217         case GPOINTER:
7218             DEBUGemitcode(";lcall","__gptrput");
7219             break;
7220     }
7221
7222     /* if we r done */
7223     if ( SPEC_BLEN(etype) <= 8 )
7224         return ;
7225
7226     emitcode("inc","%s",rname);
7227     rLen = SPEC_BLEN(etype) ;     
7228
7229     /* now generate for lengths greater than one byte */
7230     while (1) {
7231
7232         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7233
7234         rLen -= 8 ;
7235         if (rLen <= 0 )
7236             break ;
7237
7238         switch (p_type) {
7239             case POINTER:
7240                 if (*l == '@') {
7241                     MOVA(l);
7242                     emitcode("mov","@%s,a",rname);
7243                 } else
7244                     emitcode("mov","@%s,%s",rname,l);
7245                 break;
7246
7247             case FPOINTER:
7248                 MOVA(l);
7249                 emitcode("movx","@dptr,a");
7250                 break;
7251
7252             case GPOINTER:
7253                 MOVA(l);
7254                 DEBUGemitcode(";lcall","__gptrput");
7255                 break;  
7256         }   
7257         emitcode ("inc","%s",rname);
7258     }
7259
7260     MOVA(l);
7261
7262     /* last last was not complete */
7263     if (rLen)   {
7264         /* save the byte & read byte */
7265         switch (p_type) {
7266             case POINTER:
7267                 emitcode ("mov","b,a");
7268                 emitcode("mov","a,@%s",rname);
7269                 break;
7270
7271             case FPOINTER:
7272                 emitcode ("mov","b,a");
7273                 emitcode("movx","a,@dptr");
7274                 break;
7275
7276             case GPOINTER:
7277                 emitcode ("push","b");
7278                 emitcode ("push","acc");
7279                 emitcode ("lcall","__gptrget");
7280                 emitcode ("pop","b");
7281                 break;
7282         }
7283
7284         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7285         emitcode ("orl","a,b");
7286     }
7287
7288     if (p_type == GPOINTER)
7289         emitcode("pop","b");
7290
7291     switch (p_type) {
7292
7293     case POINTER:
7294         emitcode("mov","@%s,a",rname);
7295         break;
7296         
7297     case FPOINTER:
7298         emitcode("movx","@dptr,a");
7299         break;
7300         
7301     case GPOINTER:
7302         DEBUGemitcode(";lcall","__gptrput");
7303         break;                  
7304     }
7305 }
7306 /*-----------------------------------------------------------------*/
7307 /* genDataPointerSet - remat pointer to data space                 */
7308 /*-----------------------------------------------------------------*/
7309 static void genDataPointerSet(operand *right,
7310                               operand *result,
7311                               iCode *ic)
7312 {
7313     int size, offset = 0 ;
7314     char *l, buffer[256];
7315
7316     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7317     aopOp(right,ic,FALSE);
7318     
7319     l = aopGet(AOP(result),0,FALSE,TRUE);
7320     size = AOP_SIZE(right);
7321     // tsd, was l+1 - the underline `_' prefix was being stripped
7322     while (size--) {
7323         if (offset)
7324             sprintf(buffer,"(%s + %d)",l,offset);
7325         else
7326             sprintf(buffer,"%s",l);
7327
7328         if (AOP_TYPE(right) == AOP_LIT) {
7329           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7330           lit = lit >> (8*offset);
7331           if(lit) {
7332             emitcode("movlw","%s",lit);
7333             emitcode("movwf","%s",buffer);
7334           } else 
7335             emitcode("clrf","%s",buffer);
7336         }else {
7337           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7338           emitcode("movwf","%s",buffer);
7339         }
7340
7341         offset++;
7342     }
7343
7344     freeAsmop(right,NULL,ic,TRUE);
7345     freeAsmop(result,NULL,ic,TRUE);
7346 }
7347
7348 /*-----------------------------------------------------------------*/
7349 /* genNearPointerSet - emitcode for near pointer put                */
7350 /*-----------------------------------------------------------------*/
7351 static void genNearPointerSet (operand *right,
7352                                operand *result, 
7353                                iCode *ic)
7354 {
7355     asmop *aop = NULL;
7356     char *l;
7357     sym_link *retype;
7358     sym_link *ptype = operandType(result);
7359
7360     
7361     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7362     retype= getSpec(operandType(right));
7363
7364     aopOp(result,ic,FALSE);
7365     
7366     /* if the result is rematerializable &
7367        in data space & not a bit variable */
7368     if (AOP_TYPE(result) == AOP_IMMD &&
7369         DCL_TYPE(ptype) == POINTER   &&
7370         !IS_BITVAR(retype)) {
7371         genDataPointerSet (right,result,ic);
7372         return;
7373     }
7374
7375     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7376
7377     /* if the value is already in a pointer register
7378     then don't need anything more */
7379     if (!AOP_INPREG(AOP(result))) {
7380         /* otherwise get a free pointer register */
7381         //aop = newAsmop(0);
7382         //preg = getFreePtr(ic,&aop,FALSE);
7383         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7384         //emitcode("mov","%s,%s",
7385         //         preg->name,
7386         //         aopGet(AOP(result),0,FALSE,TRUE));
7387         //rname = preg->name ;
7388         emitcode("movwf","fsr");
7389     }// else
7390     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7391
7392     freeAsmop(result,NULL,ic,TRUE);
7393     aopOp (right,ic,FALSE);
7394     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7395
7396     /* if bitfield then unpack the bits */
7397     if (IS_BITVAR(retype)) {
7398       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7399              "The programmer is obviously confused");
7400       //genPackBits (retype,right,rname,POINTER);
7401       exit(1);
7402     }
7403     else {
7404         /* we have can just get the values */
7405         int size = AOP_SIZE(right);
7406         int offset = 0 ;    
7407
7408     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7409         while (size--) {
7410             l = aopGet(AOP(right),offset,FALSE,TRUE);
7411             if (*l == '@' ) {
7412               //MOVA(l);
7413               //emitcode("mov","@%s,a",rname);
7414               emitcode("movf","indf,w ;1");
7415             } else {
7416
7417               if (AOP_TYPE(right) == AOP_LIT) {
7418                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7419                 if(lit) {
7420                   emitcode("movlw","%s",l);
7421                   emitcode("movwf","indf ;2");
7422                 } else 
7423                   emitcode("clrf","indf");
7424               }else {
7425                 emitcode("movf","%s,w",l);
7426                 emitcode("movwf","indf ;2");
7427               }
7428             //emitcode("mov","@%s,%s",rname,l);
7429             }
7430             if (size)
7431               emitcode("incf","fsr,f ;3");
7432             //emitcode("inc","%s",rname);
7433             offset++;
7434         }
7435     }
7436
7437     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7438     /* now some housekeeping stuff */
7439     if (aop) {
7440         /* we had to allocate for this iCode */
7441         freeAsmop(NULL,aop,ic,TRUE);
7442     } else { 
7443         /* we did not allocate which means left
7444         already in a pointer register, then
7445         if size > 0 && this could be used again
7446         we have to point it back to where it 
7447         belongs */
7448     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7449         if (AOP_SIZE(right) > 1 &&
7450             !OP_SYMBOL(result)->remat &&
7451             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7452               ic->depth )) {
7453             int size = AOP_SIZE(right) - 1;
7454             while (size--)
7455               emitcode("decf","fsr,f");
7456               //emitcode("dec","%s",rname);
7457         }
7458     }
7459
7460     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7461     /* done */
7462     freeAsmop(right,NULL,ic,TRUE);
7463
7464
7465 }
7466
7467 /*-----------------------------------------------------------------*/
7468 /* genPagedPointerSet - emitcode for Paged pointer put             */
7469 /*-----------------------------------------------------------------*/
7470 static void genPagedPointerSet (operand *right,
7471                                operand *result, 
7472                                iCode *ic)
7473 {
7474     asmop *aop = NULL;
7475     regs *preg = NULL ;
7476     char *rname , *l;
7477     sym_link *retype;
7478        
7479     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7480
7481     retype= getSpec(operandType(right));
7482     
7483     aopOp(result,ic,FALSE);
7484     
7485     /* if the value is already in a pointer register
7486        then don't need anything more */
7487     if (!AOP_INPREG(AOP(result))) {
7488         /* otherwise get a free pointer register */
7489         aop = newAsmop(0);
7490         preg = getFreePtr(ic,&aop,FALSE);
7491         emitcode("mov","%s,%s",
7492                 preg->name,
7493                 aopGet(AOP(result),0,FALSE,TRUE));
7494         rname = preg->name ;
7495     } else
7496         rname = aopGet(AOP(result),0,FALSE,FALSE);
7497     
7498     freeAsmop(result,NULL,ic,TRUE);
7499     aopOp (right,ic,FALSE);
7500
7501     /* if bitfield then unpack the bits */
7502     if (IS_BITVAR(retype)) 
7503         genPackBits (retype,right,rname,PPOINTER);
7504     else {
7505         /* we have can just get the values */
7506         int size = AOP_SIZE(right);
7507         int offset = 0 ;        
7508         
7509         while (size--) {
7510             l = aopGet(AOP(right),offset,FALSE,TRUE);
7511             
7512             MOVA(l);
7513             emitcode("movx","@%s,a",rname);
7514
7515             if (size)
7516                 emitcode("inc","%s",rname);
7517
7518             offset++;
7519         }
7520     }
7521     
7522     /* now some housekeeping stuff */
7523     if (aop) {
7524         /* we had to allocate for this iCode */
7525         freeAsmop(NULL,aop,ic,TRUE);
7526     } else { 
7527         /* we did not allocate which means left
7528            already in a pointer register, then
7529            if size > 0 && this could be used again
7530            we have to point it back to where it 
7531            belongs */
7532         if (AOP_SIZE(right) > 1 &&
7533             !OP_SYMBOL(result)->remat &&
7534             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7535               ic->depth )) {
7536             int size = AOP_SIZE(right) - 1;
7537             while (size--)
7538                 emitcode("dec","%s",rname);
7539         }
7540     }
7541
7542     /* done */
7543     freeAsmop(right,NULL,ic,TRUE);
7544     
7545         
7546 }
7547
7548 /*-----------------------------------------------------------------*/
7549 /* genFarPointerSet - set value from far space                     */
7550 /*-----------------------------------------------------------------*/
7551 static void genFarPointerSet (operand *right,
7552                               operand *result, iCode *ic)
7553 {
7554     int size, offset ;
7555     sym_link *retype = getSpec(operandType(right));
7556
7557     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7558     aopOp(result,ic,FALSE);
7559
7560     /* if the operand is already in dptr 
7561     then we do nothing else we move the value to dptr */
7562     if (AOP_TYPE(result) != AOP_STR) {
7563         /* if this is remateriazable */
7564         if (AOP_TYPE(result) == AOP_IMMD)
7565             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7566         else { /* we need to get it byte by byte */
7567             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7568             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7569             if (options.model == MODEL_FLAT24)
7570             {
7571                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7572             }
7573         }
7574     }
7575     /* so dptr know contains the address */
7576     freeAsmop(result,NULL,ic,TRUE);
7577     aopOp(right,ic,FALSE);
7578
7579     /* if bit then unpack */
7580     if (IS_BITVAR(retype)) 
7581         genPackBits(retype,right,"dptr",FPOINTER);
7582     else {
7583         size = AOP_SIZE(right);
7584         offset = 0 ;
7585
7586         while (size--) {
7587             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7588             MOVA(l);
7589             emitcode("movx","@dptr,a");
7590             if (size)
7591                 emitcode("inc","dptr");
7592         }
7593     }
7594
7595     freeAsmop(right,NULL,ic,TRUE);
7596 }
7597
7598 /*-----------------------------------------------------------------*/
7599 /* genGenPointerSet - set value from generic pointer space         */
7600 /*-----------------------------------------------------------------*/
7601 static void genGenPointerSet (operand *right,
7602                               operand *result, iCode *ic)
7603 {
7604     int size, offset ;
7605     sym_link *retype = getSpec(operandType(right));
7606
7607     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7608
7609     aopOp(result,ic,FALSE);
7610
7611     /* if the operand is already in dptr 
7612     then we do nothing else we move the value to dptr */
7613     if (AOP_TYPE(result) != AOP_STR) {
7614         /* if this is remateriazable */
7615         if (AOP_TYPE(result) == AOP_IMMD) {
7616             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7617             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7618         }
7619         else { /* we need to get it byte by byte */
7620             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7621             emitcode("movwf","fsr");
7622
7623             //emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7624             //emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7625             //if (options.model == MODEL_FLAT24)
7626             //{
7627             //   emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7628             //   emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7629             //}
7630             //else
7631             //{
7632             //  emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7633             //}
7634         }
7635     }
7636     /* so dptr know contains the address */
7637     freeAsmop(result,NULL,ic,TRUE);
7638     aopOp(right,ic,FALSE);
7639
7640     /* if bit then unpack */
7641     if (IS_BITVAR(retype)) 
7642         genPackBits(retype,right,"dptr",GPOINTER);
7643     else {
7644         size = AOP_SIZE(right);
7645         offset = 0 ;
7646
7647         while (size--) {
7648             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7649             //emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7650             emitcode("movwf","indf");
7651             if(size)
7652               emitcode("incf","fsr,f");
7653             //MOVA(l);
7654             //DEBUGemitcode(";lcall","__gptrput");
7655             //if (size)
7656             //    emitcode("inc","dptr");
7657         }
7658     }
7659
7660     freeAsmop(right,NULL,ic,TRUE);
7661 }
7662
7663 /*-----------------------------------------------------------------*/
7664 /* genPointerSet - stores the value into a pointer location        */
7665 /*-----------------------------------------------------------------*/
7666 static void genPointerSet (iCode *ic)
7667 {    
7668     operand *right, *result ;
7669     sym_link *type, *etype;
7670     int p_type;
7671
7672     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7673
7674     right = IC_RIGHT(ic);
7675     result = IC_RESULT(ic) ;
7676
7677     /* depending on the type of pointer we need to
7678     move it to the correct pointer register */
7679     type = operandType(result);
7680     etype = getSpec(type);
7681     /* if left is of type of pointer then it is simple */
7682     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7683         p_type = DCL_TYPE(type);
7684     }
7685     else {
7686         /* we have to go by the storage class */
7687         p_type = PTR_TYPE(SPEC_OCLS(etype));
7688
7689 /*      if (SPEC_OCLS(etype)->codesp ) { */
7690 /*          p_type = CPOINTER ;  */
7691 /*      } */
7692 /*      else */
7693 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7694 /*              p_type = FPOINTER ; */
7695 /*          else */
7696 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7697 /*                  p_type = PPOINTER ; */
7698 /*              else */
7699 /*                  if (SPEC_OCLS(etype) == idata ) */
7700 /*                      p_type = IPOINTER ; */
7701 /*                  else */
7702 /*                      p_type = POINTER ; */
7703     }
7704
7705     /* now that we have the pointer type we assign
7706     the pointer values */
7707     switch (p_type) {
7708
7709     case POINTER:
7710     case IPOINTER:
7711         genNearPointerSet (right,result,ic);
7712         break;
7713
7714     case PPOINTER:
7715         genPagedPointerSet (right,result,ic);
7716         break;
7717
7718     case FPOINTER:
7719         genFarPointerSet (right,result,ic);
7720         break;
7721
7722     case GPOINTER:
7723         genGenPointerSet (right,result,ic);
7724         break;
7725     }
7726
7727 }
7728
7729 /*-----------------------------------------------------------------*/
7730 /* genIfx - generate code for Ifx statement                        */
7731 /*-----------------------------------------------------------------*/
7732 static void genIfx (iCode *ic, iCode *popIc)
7733 {
7734     operand *cond = IC_COND(ic);
7735     int isbit =0;
7736
7737     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7738     aopOp(cond,ic,FALSE);
7739
7740     /* get the value into acc */
7741     if (AOP_TYPE(cond) != AOP_CRY)
7742         toBoolean(cond);
7743     else
7744         isbit = 1;
7745     /* the result is now in the accumulator */
7746     freeAsmop(cond,NULL,ic,TRUE);
7747
7748     /* if there was something to be popped then do it */
7749     if (popIc)
7750         genIpop(popIc);
7751
7752     /* if the condition is  a bit variable */
7753     if (isbit && IS_ITEMP(cond) && 
7754         SPIL_LOC(cond)) {
7755       genIfxJump(ic,SPIL_LOC(cond)->rname);
7756       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7757     }
7758     else {
7759       /*
7760         if (isbit && !IS_ITEMP(cond))
7761           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7762         else
7763           DEBUGemitcode ("; isbit","a");
7764       */
7765
7766         if (isbit && !IS_ITEMP(cond))
7767             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7768         else
7769             genIfxJump(ic,"a");
7770     }
7771     ic->generated = 1;
7772 }
7773
7774 /*-----------------------------------------------------------------*/
7775 /* genAddrOf - generates code for address of                       */
7776 /*-----------------------------------------------------------------*/
7777 static void genAddrOf (iCode *ic)
7778 {
7779     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7780     int size, offset ;
7781
7782     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7783
7784     aopOp(IC_RESULT(ic),ic,FALSE);
7785
7786     /* if the operand is on the stack then we 
7787     need to get the stack offset of this
7788     variable */
7789     if (sym->onStack) {
7790         /* if it has an offset then we need to compute
7791         it */
7792         if (sym->stack) {
7793             emitcode("mov","a,_bp");
7794             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7795             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7796         } else {
7797             /* we can just move _bp */
7798             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7799         }
7800         /* fill the result with zero */
7801         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7802         
7803         
7804         if (options.stack10bit && size < (FPTRSIZE - 1))
7805         {
7806             fprintf(stderr, 
7807                     "*** warning: pointer to stack var truncated.\n");
7808         }
7809         
7810         offset = 1;
7811         while (size--)
7812         {
7813             /* Yuck! */
7814             if (options.stack10bit && offset == 2)
7815             {
7816                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7817             }
7818             else
7819             {
7820                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7821             }
7822         }
7823
7824         goto release;
7825     }
7826
7827     /* object not on stack then we need the name */
7828     size = AOP_SIZE(IC_RESULT(ic));
7829     offset = 0;
7830
7831     while (size--) {
7832         char s[SDCC_NAME_MAX];
7833         if (offset) 
7834             sprintf(s,"#(%s >> %d)",
7835                     sym->rname,
7836                     offset*8);
7837         else
7838             sprintf(s,"#%s",sym->rname);
7839         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7840     }
7841
7842 release:
7843     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7844
7845 }
7846
7847 #if 0
7848 /*-----------------------------------------------------------------*/
7849 /* genFarFarAssign - assignment when both are in far space         */
7850 /*-----------------------------------------------------------------*/
7851 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7852 {
7853     int size = AOP_SIZE(right);
7854     int offset = 0;
7855     char *l ;
7856     /* first push the right side on to the stack */
7857     while (size--) {
7858         l = aopGet(AOP(right),offset++,FALSE,FALSE);
7859         MOVA(l);
7860         emitcode ("push","acc");
7861     }
7862     
7863     freeAsmop(right,NULL,ic,FALSE);
7864     /* now assign DPTR to result */
7865     aopOp(result,ic,FALSE);
7866     size = AOP_SIZE(result);
7867     while (size--) {
7868         emitcode ("pop","acc");
7869         aopPut(AOP(result),"a",--offset);
7870     }
7871     freeAsmop(result,NULL,ic,FALSE);
7872         
7873 }
7874 #endif
7875
7876 /*-----------------------------------------------------------------*/
7877 /* genAssign - generate code for assignment                        */
7878 /*-----------------------------------------------------------------*/
7879 static void genAssign (iCode *ic)
7880 {
7881     operand *result, *right;
7882     int size, offset ;
7883         unsigned long lit = 0L;
7884
7885     result = IC_RESULT(ic);
7886     right  = IC_RIGHT(ic) ;
7887
7888     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7889
7890     /* if they are the same */
7891     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7892         return ;
7893
7894     aopOp(right,ic,FALSE);
7895     aopOp(result,ic,TRUE);
7896
7897     /* if they are the same registers */
7898     if (sameRegs(AOP(right),AOP(result)))
7899         goto release;
7900
7901     /* if the result is a bit */
7902     if (AOP_TYPE(result) == AOP_CRY) {
7903
7904         /* if the right size is a literal then
7905         we know what the value is */
7906         if (AOP_TYPE(right) == AOP_LIT) {
7907             if (((int) operandLitValue(right))) 
7908               emitcode("bsf","(%s >> 3),(%s & 7)",
7909                  AOP(result)->aopu.aop_dir,
7910                  AOP(result)->aopu.aop_dir);
7911             else
7912               emitcode("bcf","(%s >> 3),(%s & 7)",
7913                  AOP(result)->aopu.aop_dir,
7914                  AOP(result)->aopu.aop_dir);
7915             goto release;
7916         }
7917
7918         /* the right is also a bit variable */
7919         if (AOP_TYPE(right) == AOP_CRY) {
7920           emitcode("bcf","(%s >> 3),(%s & 7)",
7921                    AOP(result)->aopu.aop_dir,
7922                    AOP(result)->aopu.aop_dir);
7923           emitcode("btfsc","(%s >> 3),(%s & 7)",
7924                    AOP(right)->aopu.aop_dir,
7925                    AOP(right)->aopu.aop_dir);
7926           emitcode("bsf","(%s >> 3),(%s & 7)",
7927                    AOP(result)->aopu.aop_dir,
7928                    AOP(result)->aopu.aop_dir);
7929           goto release ;
7930         }
7931
7932         /* we need to or */
7933         toBoolean(right);
7934         aopPut(AOP(result),"a",0);
7935         goto release ;
7936     }
7937
7938     /* bit variables done */
7939     /* general case */
7940     size = AOP_SIZE(result);
7941     offset = 0 ;
7942     if(AOP_TYPE(right) == AOP_LIT)
7943         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7944     if((AOP_TYPE(result) != AOP_REG) &&
7945        (AOP_TYPE(right) == AOP_LIT) &&
7946        !IS_FLOAT(operandType(right)) &&
7947        (lit < 256L)){
7948
7949         while (size--) {
7950             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7951               emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7952             else {
7953               emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7954               emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7955             }
7956         }
7957     } else {
7958         while (size--) {
7959           if(AOP_TYPE(right) == AOP_LIT)
7960             emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7961           else
7962             emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7963             
7964           emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7965           offset++;
7966         }
7967     }
7968     
7969 release:
7970     freeAsmop (right,NULL,ic,FALSE);
7971     freeAsmop (result,NULL,ic,TRUE);
7972 }   
7973
7974 /*-----------------------------------------------------------------*/
7975 /* genJumpTab - genrates code for jump table                       */
7976 /*-----------------------------------------------------------------*/
7977 static void genJumpTab (iCode *ic)
7978 {
7979     symbol *jtab;
7980     char *l;
7981
7982     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7983
7984     aopOp(IC_JTCOND(ic),ic,FALSE);
7985     /* get the condition into accumulator */
7986     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7987     MOVA(l);
7988     /* multiply by three */
7989     emitcode("add","a,acc");
7990     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7991     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7992
7993     jtab = newiTempLabel(NULL);
7994     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
7995     emitcode("jmp","@a+dptr");
7996     emitcode("","%05d_DS_:",jtab->key+100);
7997     /* now generate the jump labels */
7998     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7999          jtab = setNextItem(IC_JTLABELS(ic)))
8000         emitcode("ljmp","%05d_DS_",jtab->key+100);
8001
8002 }
8003
8004 /*-----------------------------------------------------------------*/
8005 /* genMixedOperation - gen code for operators between mixed types  */
8006 /*-----------------------------------------------------------------*/
8007 /*
8008   TSD - Written for the PIC port - but this unfortunately is buggy.
8009   This routine is good in that it is able to efficiently promote 
8010   types to different (larger) sizes. Unfortunately, the temporary
8011   variables that are optimized out by this routine are sometimes
8012   used in other places. So until I know how to really parse the 
8013   iCode tree, I'm going to not be using this routine :(.
8014 */
8015 static int genMixedOperation (iCode *ic)
8016 {
8017 #if 0
8018   operand *result = IC_RESULT(ic);
8019   sym_link *ctype = operandType(IC_LEFT(ic));
8020   operand *right = IC_RIGHT(ic);
8021   int ret = 0;
8022   int big,small;
8023   int offset;
8024
8025   iCode *nextic;
8026   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8027
8028   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8029
8030   nextic = ic->next;
8031   if(!nextic)
8032     return 0;
8033
8034   nextright = IC_RIGHT(nextic);
8035   nextleft  = IC_LEFT(nextic);
8036   nextresult = IC_RESULT(nextic);
8037
8038   aopOp(right,ic,FALSE);
8039   aopOp(result,ic,FALSE);
8040   aopOp(nextright,  nextic, FALSE);
8041   aopOp(nextleft,   nextic, FALSE);
8042   aopOp(nextresult, nextic, FALSE);
8043
8044   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8045
8046     operand *t = right;
8047     right = nextright;
8048     nextright = t; 
8049
8050     emitcode(";remove right +","");
8051
8052   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8053 /*
8054     operand *t = right;
8055     right = nextleft;
8056     nextleft = t; 
8057 */
8058     emitcode(";remove left +","");
8059   } else
8060     return 0;
8061
8062   big = AOP_SIZE(nextleft);
8063   small = AOP_SIZE(nextright);
8064
8065   switch(nextic->op) {
8066
8067   case '+':
8068     emitcode(";optimize a +","");
8069     /* if unsigned or not an integral type */
8070     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8071       emitcode(";add a bit to something","");
8072     } else {
8073
8074       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8075
8076       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8077         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8078         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8079       } else
8080         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8081
8082       offset = 0;
8083       while(--big) {
8084
8085         offset++;
8086
8087         if(--small) {
8088           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8089             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8090             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8091           }
8092
8093           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8094           emitSKPNC;
8095           emitcode("btfsc","(%s >> 3), (%s & 7)",
8096                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8097                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8098           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8099           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8100
8101         } else {
8102           emitcode("rlf","known_zero,w");
8103
8104           /*
8105             if right is signed
8106               btfsc  right,7
8107                addlw ff
8108           */
8109           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8110             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8111             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8112           } else {
8113             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8114           }
8115         }
8116       }
8117       ret = 1;
8118     }
8119   }
8120   ret = 1;
8121
8122 release:
8123   freeAsmop(right,NULL,ic,TRUE);
8124   freeAsmop(result,NULL,ic,TRUE);
8125   freeAsmop(nextright,NULL,ic,TRUE);
8126   freeAsmop(nextleft,NULL,ic,TRUE);
8127   if(ret)
8128     nextic->generated = 1;
8129
8130   return ret;
8131 #else
8132   return 0;
8133 #endif
8134 }
8135 /*-----------------------------------------------------------------*/
8136 /* genCast - gen code for casting                                  */
8137 /*-----------------------------------------------------------------*/
8138 static void genCast (iCode *ic)
8139 {
8140     operand *result = IC_RESULT(ic);
8141     sym_link *ctype = operandType(IC_LEFT(ic));
8142     operand *right = IC_RIGHT(ic);
8143     int size, offset ;
8144
8145     emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8146     /* if they are equivalent then do nothing */
8147     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8148         return ;
8149
8150     aopOp(right,ic,FALSE) ;
8151     aopOp(result,ic,FALSE);
8152
8153     /* if the result is a bit */
8154     if (AOP_TYPE(result) == AOP_CRY) {
8155         /* if the right size is a literal then
8156         we know what the value is */
8157         if (AOP_TYPE(right) == AOP_LIT) {
8158           emitcode("; ***  right is a lit","%s  %d",__FUNCTION__,__LINE__);
8159             if (((int) operandLitValue(right))) 
8160               emitcode("bsf","(%s >> 3), (%s & 7)",
8161                        AOP(result)->aopu.aop_dir,
8162                        AOP(result)->aopu.aop_dir);
8163             else
8164               emitcode("bcf","(%s >> 3), (%s & 7)",
8165                        AOP(result)->aopu.aop_dir,
8166                        AOP(result)->aopu.aop_dir);
8167
8168             goto release;
8169         }
8170
8171         /* the right is also a bit variable */
8172         if (AOP_TYPE(right) == AOP_CRY) {
8173           emitcode("clrc","");
8174           emitcode("btfsc","(%s >> 3), (%s & 7)",
8175                    AOP(right)->aopu.aop_dir,
8176                    AOP(right)->aopu.aop_dir);
8177             aopPut(AOP(result),"c",0);
8178             goto release ;
8179         }
8180
8181         /* we need to or */
8182         toBoolean(right);
8183         aopPut(AOP(result),"a",0);
8184         goto release ;
8185     }
8186
8187     /* if they are the same size : or less */
8188     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8189
8190         /* if they are in the same place */
8191         if (sameRegs(AOP(right),AOP(result)))
8192             goto release;
8193
8194         /* if they in different places then copy */
8195         size = AOP_SIZE(result);
8196         offset = 0 ;
8197         while (size--) {
8198             aopPut(AOP(result),
8199                    aopGet(AOP(right),offset,FALSE,FALSE),
8200                    offset);
8201             offset++;
8202         }
8203         goto release;
8204     }
8205
8206
8207     /* if the result is of type pointer */
8208     if (IS_PTR(ctype)) {
8209
8210         int p_type;
8211         sym_link *type = operandType(right);
8212         sym_link *etype = getSpec(type);
8213
8214         /* pointer to generic pointer */
8215         if (IS_GENPTR(ctype)) {
8216             char *l = zero;
8217             
8218             if (IS_PTR(type)) 
8219                 p_type = DCL_TYPE(type);
8220             else {
8221                 /* we have to go by the storage class */
8222                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8223
8224 /*              if (SPEC_OCLS(etype)->codesp )  */
8225 /*                  p_type = CPOINTER ;  */
8226 /*              else */
8227 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8228 /*                      p_type = FPOINTER ; */
8229 /*                  else */
8230 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8231 /*                          p_type = PPOINTER; */
8232 /*                      else */
8233 /*                          if (SPEC_OCLS(etype) == idata ) */
8234 /*                              p_type = IPOINTER ; */
8235 /*                          else */
8236 /*                              p_type = POINTER ; */
8237             }
8238                 
8239             /* the first two bytes are known */
8240             size = GPTRSIZE - 1; 
8241             offset = 0 ;
8242             while (size--) {
8243                 aopPut(AOP(result),
8244                        aopGet(AOP(right),offset,FALSE,FALSE),
8245                        offset);
8246                 offset++;
8247             }
8248             /* the last byte depending on type */
8249             switch (p_type) {
8250             case IPOINTER:
8251             case POINTER:
8252                 l = zero;
8253                 break;
8254             case FPOINTER:
8255                 l = one;
8256                 break;
8257             case CPOINTER:
8258                 l = "#0x02";
8259                 break;                          
8260             case PPOINTER:
8261                 l = "#0x03";
8262                 break;
8263                 
8264             default:
8265                 /* this should never happen */
8266                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8267                        "got unknown pointer type");
8268                 exit(1);
8269             }
8270             aopPut(AOP(result),l, GPTRSIZE - 1);            
8271             goto release ;
8272         }
8273         
8274         /* just copy the pointers */
8275         size = AOP_SIZE(result);
8276         offset = 0 ;
8277         while (size--) {
8278             aopPut(AOP(result),
8279                    aopGet(AOP(right),offset,FALSE,FALSE),
8280                    offset);
8281             offset++;
8282         }
8283         goto release ;
8284     }
8285     
8286
8287     if (AOP_TYPE(right) == AOP_CRY) {
8288       int offset = 1;
8289       size = AOP_SIZE(right);
8290
8291       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8292       emitcode("btfsc","(%s >> 3), (%s & 7)",
8293                AOP(right)->aopu.aop_dir,
8294                AOP(right)->aopu.aop_dir);
8295       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8296       while (size--) {
8297         emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8298       }
8299       goto release;
8300     }
8301
8302     /* so we now know that the size of destination is greater
8303     than the size of the source.
8304     Now, if the next iCode is an operator then we might be
8305     able to optimize the operation without performing a cast.
8306     */
8307     if(genMixedOperation(ic))
8308       goto release;
8309
8310     
8311     /* we move to result for the size of source */
8312     size = AOP_SIZE(right);
8313     offset = 0 ;
8314     while (size--) {
8315       emitcode(";","%d",__LINE__);
8316         aopPut(AOP(result),
8317                aopGet(AOP(right),offset,FALSE,FALSE),
8318                offset);
8319         offset++;
8320     }
8321
8322     /* now depending on the sign of the destination */
8323     size = AOP_SIZE(result) - AOP_SIZE(right);
8324     /* if unsigned or not an integral type */
8325     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8326         while (size--)
8327           emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8328     } else {
8329       /* we need to extend the sign :{ */
8330       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8331       //MOVA(l);
8332
8333         emitcode("clrw","");
8334         emitcode("btfsc","(%s >> 3), (%s & 7)",
8335                  AOP(right)->aopu.aop_dir,
8336                  AOP(right)->aopu.aop_dir);
8337         emitcode("movlw","0xff");
8338         while (size--) {
8339           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8340           // aopPut(AOP(result),"a",offset++);
8341         }
8342
8343     }
8344
8345     /* we are done hurray !!!! */
8346
8347 release:
8348     freeAsmop(right,NULL,ic,TRUE);
8349     freeAsmop(result,NULL,ic,TRUE);
8350
8351 }
8352
8353 /*-----------------------------------------------------------------*/
8354 /* genDjnz - generate decrement & jump if not zero instrucion      */
8355 /*-----------------------------------------------------------------*/
8356 static int genDjnz (iCode *ic, iCode *ifx)
8357 {
8358     symbol *lbl, *lbl1;
8359     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8360
8361     if (!ifx)
8362         return 0;
8363     
8364     /* if the if condition has a false label
8365        then we cannot save */
8366     if (IC_FALSE(ifx))
8367         return 0;
8368
8369     /* if the minus is not of the form 
8370        a = a - 1 */
8371     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8372         !IS_OP_LITERAL(IC_RIGHT(ic)))
8373         return 0;
8374
8375     if (operandLitValue(IC_RIGHT(ic)) != 1)
8376         return 0;
8377
8378     /* if the size of this greater than one then no
8379        saving */
8380     if (getSize(operandType(IC_RESULT(ic))) > 1)
8381         return 0;
8382
8383     /* otherwise we can save BIG */
8384     lbl = newiTempLabel(NULL);
8385     lbl1= newiTempLabel(NULL);
8386
8387     aopOp(IC_RESULT(ic),ic,FALSE);
8388     
8389     if (IS_AOP_PREG(IC_RESULT(ic))) {
8390         emitcode("dec","%s",
8391                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8392         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8393         emitcode("jnz","%05d_DS_",lbl->key+100);
8394     } else {    
8395       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8396       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8397
8398     }
8399 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8400 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
8401 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8402 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
8403
8404     
8405     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8406     ifx->generated = 1;
8407     return 1;
8408 }
8409
8410 /*-----------------------------------------------------------------*/
8411 /* genReceive - generate code for a receive iCode                  */
8412 /*-----------------------------------------------------------------*/
8413 static void genReceive (iCode *ic)
8414 {    
8415     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8416
8417     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8418         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8419           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8420
8421         int size = getSize(operandType(IC_RESULT(ic)));
8422         int offset =  fReturnSize - size;
8423         while (size--) {
8424             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8425                                     fReturn[fReturnSize - offset - 1] : "acc"));
8426             offset++;
8427         }
8428         aopOp(IC_RESULT(ic),ic,FALSE);  
8429         size = AOP_SIZE(IC_RESULT(ic));
8430         offset = 0;
8431         while (size--) {
8432             emitcode ("pop","acc");
8433             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8434         }
8435         
8436     } else {
8437         _G.accInUse++;
8438         aopOp(IC_RESULT(ic),ic,FALSE);  
8439         _G.accInUse--;
8440         assignResultValue(IC_RESULT(ic));       
8441     }
8442
8443     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8444 }
8445
8446 /*-----------------------------------------------------------------*/
8447 /* genpic14Code - generate code for pic14 based controllers            */
8448 /*-----------------------------------------------------------------*/
8449 void genpic14Code (iCode *lic)
8450 {
8451     iCode *ic;
8452     int cln = 0;
8453
8454     lineHead = lineCurr = NULL;
8455
8456     /* if debug information required */
8457 /*     if (options.debug && currFunc) { */
8458     if (currFunc) {
8459         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8460         _G.debugLine = 1;
8461         if (IS_STATIC(currFunc->etype))
8462             emitcode("",";F%s_DS_%s_DS_0_DS_0     %d",moduleName,currFunc->name,__LINE__); 
8463         else
8464             emitcode("",";G_DS_%s_DS_0_DS_0   %d",currFunc->name,__LINE__);
8465         _G.debugLine = 0;
8466     }
8467
8468
8469     for (ic = lic ; ic ; ic = ic->next ) {
8470
8471       DEBUGemitcode(";ic","");
8472         if ( cln != ic->lineno ) {
8473             if ( options.debug ) {
8474                 _G.debugLine = 1;
8475                 emitcode("",";C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
8476                          ic->filename,ic->lineno,
8477                          ic->level,ic->block);
8478                 _G.debugLine = 0;
8479             }
8480             emitcode(";","%s %d",ic->filename,ic->lineno);
8481             cln = ic->lineno ;
8482         }
8483         /* if the result is marked as
8484            spilt and rematerializable or code for
8485            this has already been generated then
8486            do nothing */
8487         if (resultRemat(ic) || ic->generated ) 
8488             continue ;
8489         
8490         /* depending on the operation */
8491         switch (ic->op) {
8492         case '!' :
8493             genNot(ic);
8494             break;
8495             
8496         case '~' :
8497             genCpl(ic);
8498             break;
8499             
8500         case UNARYMINUS:
8501             genUminus (ic);
8502             break;
8503             
8504         case IPUSH:
8505             genIpush (ic);
8506             break;
8507             
8508         case IPOP:
8509             /* IPOP happens only when trying to restore a 
8510                spilt live range, if there is an ifx statement
8511                following this pop then the if statement might
8512                be using some of the registers being popped which
8513                would destory the contents of the register so
8514                we need to check for this condition and handle it */
8515             if (ic->next            && 
8516                 ic->next->op == IFX &&
8517                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8518                 genIfx (ic->next,ic);
8519             else
8520                 genIpop (ic);
8521             break; 
8522             
8523         case CALL:
8524             genCall (ic);
8525             break;
8526             
8527         case PCALL:
8528             genPcall (ic);
8529             break;
8530             
8531         case FUNCTION:
8532             genFunction (ic);
8533             break;
8534             
8535         case ENDFUNCTION:
8536             genEndFunction (ic);
8537             break;
8538             
8539         case RETURN:
8540             genRet (ic);
8541             break;
8542             
8543         case LABEL:
8544             genLabel (ic);
8545             break;
8546             
8547         case GOTO:
8548             genGoto (ic);
8549             break;
8550             
8551         case '+' :
8552             genPlus (ic) ;
8553             break;
8554             
8555         case '-' :
8556             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8557                 genMinus (ic);
8558             break;
8559             
8560         case '*' :
8561             genMult (ic);
8562             break;
8563             
8564         case '/' :
8565             genDiv (ic) ;
8566             break;
8567             
8568         case '%' :
8569             genMod (ic);
8570             break;
8571             
8572         case '>' :
8573             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8574             break;
8575             
8576         case '<' :
8577             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8578             break;
8579             
8580         case LE_OP:
8581         case GE_OP:
8582         case NE_OP:
8583             
8584             /* note these two are xlated by algebraic equivalence
8585                during parsing SDCC.y */
8586             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8587                    "got '>=' or '<=' shouldn't have come here");
8588             break;      
8589             
8590         case EQ_OP:
8591             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8592             break;          
8593             
8594         case AND_OP:
8595             genAndOp (ic);
8596             break;
8597             
8598         case OR_OP:
8599             genOrOp (ic);
8600             break;
8601             
8602         case '^' :
8603             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8604             break;
8605             
8606         case '|' :
8607                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8608             break;
8609             
8610         case BITWISEAND:
8611             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8612             break;
8613             
8614         case INLINEASM:
8615             genInline (ic);
8616             break;
8617             
8618         case RRC:
8619             genRRC (ic);
8620             break;
8621             
8622         case RLC:
8623             genRLC (ic);
8624             break;
8625             
8626         case GETHBIT:
8627             genGetHbit (ic);
8628             break;
8629             
8630         case LEFT_OP:
8631             genLeftShift (ic);
8632             break;
8633             
8634         case RIGHT_OP:
8635             genRightShift (ic);
8636             break;
8637             
8638         case GET_VALUE_AT_ADDRESS:
8639             genPointerGet(ic);
8640             break;
8641             
8642         case '=' :
8643             if (POINTER_SET(ic))
8644                 genPointerSet(ic);
8645             else
8646                 genAssign(ic);
8647             break;
8648             
8649         case IFX:
8650             genIfx (ic,NULL);
8651             break;
8652             
8653         case ADDRESS_OF:
8654             genAddrOf (ic);
8655             break;
8656             
8657         case JUMPTABLE:
8658             genJumpTab (ic);
8659             break;
8660             
8661         case CAST:
8662             genCast (ic);
8663             break;
8664             
8665         case RECEIVE:
8666             genReceive(ic);
8667             break;
8668             
8669         case SEND:
8670             addSet(&_G.sendSet,ic);
8671             break;
8672
8673         default :
8674             ic = ic;
8675             /*      piCode(ic,stdout); */
8676             
8677         }
8678     }
8679     
8680
8681     /* now we are ready to call the 
8682        peep hole optimizer */
8683     if (!options.nopeep) {
8684       printf("peep hole optimizing\n");
8685         peepHole (&lineHead);
8686     }
8687     /* now do the actual printing */
8688     printLine (lineHead,codeOutFile);
8689     return;
8690 }