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