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