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