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