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