More enhancements to register optimization algorithms.
[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 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62
63 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
65 void genMult8X8_8 (operand *, operand *,operand *);
66
67 static int labelOffset=0;
68 static int debug_verbose=1;
69 static int optimized_for_speed = 0;
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic14aopLiteral (value *val, int offset);
80 const char *AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
82
83 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
84
85 /* this is the down and dirty file with all kinds of 
86    kludgy & hacky stuff. This is what it is all about
87    CODE GENERATION for a specific MCU . some of the
88    routines may be reusable, will have to see */
89
90 static char *zero = "#0x00";
91 static char *one  = "#0x01";
92 static char *spname = "sp";
93
94 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
95 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
96 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
97 static char **fReturn = fReturnpic14;
98
99 static char *accUse[] = {"a","b"};
100
101 //static short rbank = -1;
102
103 static struct {
104     short r0Pushed;
105     short r1Pushed;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111 } _G;
112
113 /* Resolved ifx structure. This structure stores information
114    about an iCode ifx that makes it easier to generate code.
115 */
116 typedef struct resolvedIfx {
117   symbol *lbl;     /* pointer to a label */
118   int condition;   /* true or false ifx */
119   int generated;   /* set true when the code associated with the ifx
120                     * is generated */
121 } resolvedIfx;
122
123 extern int pic14_ptrRegReq ;
124 extern int pic14_nRegs;
125 extern FILE *codeOutFile;
126 static void saverbank (int, iCode *,bool);
127
128 static lineNode *lineHead = NULL;
129 static lineNode *lineCurr = NULL;
130
131 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
132 0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
134 0x07, 0x03, 0x01, 0x00};
135
136 static  pBlock *pb;
137
138 /*-----------------------------------------------------------------*/
139 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
140 /*                 exponent of 2 is returned, otherwise -1 is      */
141 /*                 returned.                                       */
142 /* note that this is similar to the function `powof2' in SDCCsymt  */
143 /* if(n == 2^y)                                                    */
144 /*   return y;                                                     */
145 /* return -1;                                                      */
146 /*-----------------------------------------------------------------*/
147 static int my_powof2 (unsigned long num)
148 {
149   if(num) {
150     if( (num & (num-1)) == 0) {
151       int nshifts = -1;
152       while(num) {
153         num>>=1;
154         nshifts++;
155       }
156       return nshifts;
157     }
158   }
159
160   return -1;
161 }
162
163 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
174                        ((result) ? AOP_SIZE(result) : 0));
175
176 }
177
178 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 {
180
181   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
182                        line_no,
183                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
184                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
185                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
186                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
187                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
188                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
189
190 }
191
192 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 {
194     va_list ap;
195     char lb[INITIAL_INLINEASM];  
196     char *lbp = lb;
197
198     if(!debug_verbose)
199       return;
200
201     va_start(ap,fmt);   
202
203     if (inst && *inst) {
204         if (fmt && *fmt)
205             sprintf(lb,"%s\t",inst);
206         else
207             sprintf(lb,"%s",inst);
208         vsprintf(lb+(strlen(lb)),fmt,ap);
209     }  else
210         vsprintf(lb,fmt,ap);
211
212     while (isspace(*lbp)) lbp++;
213
214     if (lbp && *lbp) 
215         lineCurr = (lineCurr ?
216                     connectLine(lineCurr,newLineNode(lb)) :
217                     (lineHead = newLineNode(lb)));
218     lineCurr->isInline = _G.inLine;
219     lineCurr->isDebug  = _G.debugLine;
220
221     addpCode2pBlock(pb,newpCodeCharP(lb));
222
223     va_end(ap);
224 }
225
226
227 void emitpLabel(int key)
228 {
229   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
230 }
231
232 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
233 {
234
235   if(pcop)
236     addpCode2pBlock(pb,newpCode(poc,pcop));
237   else
238     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
239 }
240
241 void emitpcodeNULLop(PIC_OPCODE poc)
242 {
243
244   addpCode2pBlock(pb,newpCode(poc,NULL));
245
246 }
247
248 /*-----------------------------------------------------------------*/
249 /* pic14_emitcode - writes the code into a file : for now it is simple    */
250 /*-----------------------------------------------------------------*/
251 void pic14_emitcode (char *inst,char *fmt, ...)
252 {
253     va_list ap;
254     char lb[INITIAL_INLINEASM];  
255     char *lbp = lb;
256
257     va_start(ap,fmt);   
258
259     if (inst && *inst) {
260         if (fmt && *fmt)
261             sprintf(lb,"%s\t",inst);
262         else
263             sprintf(lb,"%s",inst);
264         vsprintf(lb+(strlen(lb)),fmt,ap);
265     }  else
266         vsprintf(lb,fmt,ap);
267
268     while (isspace(*lbp)) lbp++;
269
270     if (lbp && *lbp) 
271         lineCurr = (lineCurr ?
272                     connectLine(lineCurr,newLineNode(lb)) :
273                     (lineHead = newLineNode(lb)));
274     lineCurr->isInline = _G.inLine;
275     lineCurr->isDebug  = _G.debugLine;
276
277     if(debug_verbose)
278       addpCode2pBlock(pb,newpCodeCharP(lb));
279
280     va_end(ap);
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
286 /*-----------------------------------------------------------------*/
287 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
288 {
289     bool r0iu = FALSE , r1iu = FALSE;
290     bool r0ou = FALSE , r1ou = FALSE;
291
292     /* the logic: if r0 & r1 used in the instruction
293     then we are in trouble otherwise */
294
295     /* first check if r0 & r1 are used by this
296     instruction, in which case we are in trouble */
297     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
298         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
299     {
300         goto endOfWorld;      
301     }
302
303     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
304     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
305
306     /* if no usage of r0 then return it */
307     if (!r0iu && !r0ou) {
308         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
309         (*aopp)->type = AOP_R0;
310         
311         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
312     }
313
314     /* if no usage of r1 then return it */
315     if (!r1iu && !r1ou) {
316         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
317         (*aopp)->type = AOP_R1;
318
319         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
320     }    
321
322     /* now we know they both have usage */
323     /* if r0 not used in this instruction */
324     if (!r0iu) {
325         /* push it if not already pushed */
326         if (!_G.r0Pushed) {
327           //pic14_emitcode ("push","%s",
328           //          pic14_regWithIdx(R0_IDX)->dname);
329             _G.r0Pushed++ ;
330         }
331         
332         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
333         (*aopp)->type = AOP_R0;
334
335         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
336     }
337
338     /* if r1 not used then */
339
340     if (!r1iu) {
341         /* push it if not already pushed */
342         if (!_G.r1Pushed) {
343           //pic14_emitcode ("push","%s",
344           //          pic14_regWithIdx(R1_IDX)->dname);
345             _G.r1Pushed++ ;
346         }
347         
348         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349         (*aopp)->type = AOP_R1;
350         return pic14_regWithIdx(R1_IDX);
351     }
352
353 endOfWorld :
354     /* I said end of world but not quite end of world yet */
355     /* if this is a result then we can push it on the stack*/
356     if (result) {
357         (*aopp)->type = AOP_STK;    
358         return NULL;
359     }
360
361     /* other wise this is true end of the world */
362     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
363            "getFreePtr should never reach here");
364     exit(0);
365 }
366
367 /*-----------------------------------------------------------------*/
368 /* newAsmop - creates a new asmOp                                  */
369 /*-----------------------------------------------------------------*/
370 asmop *newAsmop (short type)
371 {
372     asmop *aop;
373
374     aop = Safe_calloc(1,sizeof(asmop));
375     aop->type = type;
376     return aop;
377 }
378
379 static void genSetDPTR(int n)
380 {
381     if (!n)
382     {
383         pic14_emitcode(";", "Select standard DPTR");
384         pic14_emitcode("mov", "dps, #0x00");
385     }
386     else
387     {
388         pic14_emitcode(";", "Select alternate DPTR");
389         pic14_emitcode("mov", "dps, #0x01");
390     }
391 }
392
393 /*-----------------------------------------------------------------*/
394 /* resolveIfx - converts an iCode ifx into a form more useful for  */
395 /*              generating code                                    */
396 /*-----------------------------------------------------------------*/
397 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
398 {
399   if(!resIfx) 
400     return;
401
402   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
403
404   resIfx->condition = 1;    /* assume that the ifx is true */
405   resIfx->generated = 0;    /* indicate that the ifx has not been used */
406
407   if(!ifx) {
408     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
409     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
410                         __FUNCTION__,__LINE__,resIfx->lbl->key);
411   } else {
412     if(IC_TRUE(ifx)) {
413       resIfx->lbl = IC_TRUE(ifx);
414     } else {
415       resIfx->lbl = IC_FALSE(ifx);
416       resIfx->condition = 0;
417     }
418     if(IC_TRUE(ifx)) 
419       DEBUGpic14_emitcode("; ***","ifx true is non-null");
420     if(IC_FALSE(ifx)) 
421       DEBUGpic14_emitcode("; ***","ifx false is non-null");
422   }
423
424   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
425
426 }
427 /*-----------------------------------------------------------------*/
428 /* pointerCode - returns the code for a pointer type               */
429 /*-----------------------------------------------------------------*/
430 static int pointerCode (sym_link *etype)
431 {
432
433     return PTR_TYPE(SPEC_OCLS(etype));
434
435 }
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
441 {
442     asmop *aop;
443     memmap *space= SPEC_OCLS(sym->etype);
444
445     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
446     /* if already has one */
447     if (sym->aop)
448         return sym->aop;
449
450     /* assign depending on the storage class */
451     /* if it is on the stack or indirectly addressable */
452     /* space we need to assign either r0 or r1 to it   */    
453     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
454         sym->aop = aop = newAsmop(0);
455         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
456         aop->size = getSize(sym->type);
457
458         /* now assign the address of the variable to 
459         the pointer register */
460         if (aop->type != AOP_STK) {
461
462             if (sym->onStack) {
463                     if ( _G.accInUse )
464                         pic14_emitcode("push","acc");
465
466                     pic14_emitcode("mov","a,_bp");
467                     pic14_emitcode("add","a,#0x%02x",
468                              ((sym->stack < 0) ?
469                               ((char)(sym->stack - _G.nRegsSaved )) :
470                               ((char)sym->stack)) & 0xff);
471                     pic14_emitcode("mov","%s,a",
472                              aop->aopu.aop_ptr->name);
473
474                     if ( _G.accInUse )
475                         pic14_emitcode("pop","acc");
476             } else
477                 pic14_emitcode("mov","%s,#%s",
478                          aop->aopu.aop_ptr->name,
479                          sym->rname);
480             aop->paged = space->paged;
481         } else
482             aop->aopu.aop_stk = sym->stack;
483         return aop;
484     }
485     
486     if (sym->onStack && options.stack10bit)
487     {
488         /* It's on the 10 bit stack, which is located in
489          * far data space.
490          */
491          
492       //DEBUGpic14_emitcode(";","%d",__LINE__);
493
494         if ( _G.accInUse )
495                 pic14_emitcode("push","acc");
496
497         pic14_emitcode("mov","a,_bp");
498         pic14_emitcode("add","a,#0x%02x",
499                  ((sym->stack < 0) ?
500                    ((char)(sym->stack - _G.nRegsSaved )) :
501                    ((char)sym->stack)) & 0xff);
502         
503         genSetDPTR(1);
504         pic14_emitcode ("mov","dpx1,#0x40");
505         pic14_emitcode ("mov","dph1,#0x00");
506         pic14_emitcode ("mov","dpl1, a");
507         genSetDPTR(0);
508         
509         if ( _G.accInUse )
510             pic14_emitcode("pop","acc");
511             
512         sym->aop = aop = newAsmop(AOP_DPTR2);
513         aop->size = getSize(sym->type); 
514         return aop;
515     }
516
517     //DEBUGpic14_emitcode(";","%d",__LINE__);
518     /* if in bit space */
519     if (IN_BITSPACE(space)) {
520         sym->aop = aop = newAsmop (AOP_CRY);
521         aop->aopu.aop_dir = sym->rname ;
522         aop->size = getSize(sym->type);
523         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
524         return aop;
525     }
526     /* if it is in direct space */
527     if (IN_DIRSPACE(space)) {
528         sym->aop = aop = newAsmop (AOP_DIR);
529         aop->aopu.aop_dir = sym->rname ;
530         aop->size = getSize(sym->type);
531         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
532         return aop;
533     }
534
535     /* special case for a function */
536     if (IS_FUNC(sym->type)) {   
537         sym->aop = aop = newAsmop(AOP_IMMD);    
538         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
539         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
540         strcpy(aop->aopu.aop_immd,sym->rname);
541         aop->size = FPTRSIZE; 
542         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
543         return aop;
544     }
545
546
547     /* only remaining is far space */
548     /* in which case DPTR gets the address */
549     sym->aop = aop = newAsmop(AOP_PCODE);
550
551     aop->aopu.pcop = popGetImmd(sym->rname,0,0);
552     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
553     PCOI(aop->aopu.pcop)->index = 0;
554
555     DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
556                         sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
557
558     allocDirReg (IC_LEFT(ic));
559
560     aop->size = FPTRSIZE; 
561 /*
562     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
563     sym->aop = aop = newAsmop(AOP_DPTR);
564     pic14_emitcode ("mov","dptr,#%s", sym->rname);
565     aop->size = getSize(sym->type);
566
567     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
568 */
569
570     /* if it is in code space */
571     if (IN_CODESPACE(space))
572         aop->code = 1;
573
574     return aop;     
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object                           */
579 /*-----------------------------------------------------------------*/
580 static asmop *aopForRemat (operand *op) // x symbol *sym)
581 {
582   symbol *sym = OP_SYMBOL(op);
583   iCode *ic = NULL;
584   asmop *aop = newAsmop(AOP_PCODE);
585   int val = 0;
586   int offset = 0;
587
588   ic = sym->rematiCode;
589
590   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
591   if(IS_OP_POINTER(op)) {
592     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
593   }
594   for (;;) {
595     if (ic->op == '+') {
596       val += (int) operandLitValue(IC_RIGHT(ic));
597     } else if (ic->op == '-') {
598       val -= (int) operandLitValue(IC_RIGHT(ic));
599     } else
600       break;
601         
602     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
603   }
604
605   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
606   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
607   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
608   PCOI(aop->aopu.pcop)->index = val;
609
610   DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
611                       OP_SYMBOL(IC_LEFT(ic))->rname,
612                       val, IS_PTR_CONST(operandType(op)));
613
614   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
615
616   allocDirReg (IC_LEFT(ic));
617
618   return aop;        
619 }
620
621 int aopIdx (asmop *aop, int offset)
622 {
623   if(!aop)
624     return -1;
625
626   if(aop->type !=  AOP_REG)
627     return -2;
628         
629   return aop->aopu.aop_reg[offset]->rIdx;
630
631 }
632 /*-----------------------------------------------------------------*/
633 /* regsInCommon - two operands have some registers in common       */
634 /*-----------------------------------------------------------------*/
635 static bool regsInCommon (operand *op1, operand *op2)
636 {
637     symbol *sym1, *sym2;
638     int i;
639
640     /* if they have registers in common */
641     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
642         return FALSE ;
643
644     sym1 = OP_SYMBOL(op1);
645     sym2 = OP_SYMBOL(op2);
646
647     if (sym1->nRegs == 0 || sym2->nRegs == 0)
648         return FALSE ;
649
650     for (i = 0 ; i < sym1->nRegs ; i++) {
651         int j;
652         if (!sym1->regs[i])
653             continue ;
654
655         for (j = 0 ; j < sym2->nRegs ;j++ ) {
656             if (!sym2->regs[j])
657                 continue ;
658
659             if (sym2->regs[j] == sym1->regs[i])
660                 return TRUE ;
661         }
662     }
663
664     return FALSE ;
665 }
666
667 /*-----------------------------------------------------------------*/
668 /* operandsEqu - equivalent                                        */
669 /*-----------------------------------------------------------------*/
670 static bool operandsEqu ( operand *op1, operand *op2)
671 {
672     symbol *sym1, *sym2;
673
674     /* if they not symbols */
675     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
676         return FALSE;
677
678     sym1 = OP_SYMBOL(op1);
679     sym2 = OP_SYMBOL(op2);
680
681     /* if both are itemps & one is spilt
682        and the other is not then false */
683     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
684         sym1->isspilt != sym2->isspilt )
685         return FALSE ;
686
687     /* if they are the same */
688     if (sym1 == sym2)
689         return TRUE ;
690
691     if (strcmp(sym1->rname,sym2->rname) == 0)
692         return TRUE;
693
694
695     /* if left is a tmp & right is not */
696     if (IS_ITEMP(op1)  && 
697         !IS_ITEMP(op2) &&
698         sym1->isspilt  &&
699         (sym1->usl.spillLoc == sym2))
700         return TRUE;
701
702     if (IS_ITEMP(op2)  && 
703         !IS_ITEMP(op1) &&
704         sym2->isspilt  &&
705         sym1->level > 0 &&
706         (sym2->usl.spillLoc == sym1))
707         return TRUE ;
708
709     return FALSE ;
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* pic14_sameRegs - two asmops have the same registers                   */
714 /*-----------------------------------------------------------------*/
715 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
716 {
717     int i;
718
719     if (aop1 == aop2)
720         return TRUE ;
721
722     if (aop1->type != AOP_REG ||
723         aop2->type != AOP_REG )
724         return FALSE ;
725
726     if (aop1->size != aop2->size )
727         return FALSE ;
728
729     for (i = 0 ; i < aop1->size ; i++ )
730         if (aop1->aopu.aop_reg[i] !=
731             aop2->aopu.aop_reg[i] )
732             return FALSE ;
733
734     return TRUE ;
735 }
736
737 /*-----------------------------------------------------------------*/
738 /* aopOp - allocates an asmop for an operand  :                    */
739 /*-----------------------------------------------------------------*/
740 void aopOp (operand *op, iCode *ic, bool result)
741 {
742     asmop *aop;
743     symbol *sym;
744     int i;
745
746     if (!op)
747         return ;
748
749     //    DEBUGpic14_emitcode(";","%d",__LINE__);
750     /* if this a literal */
751     if (IS_OP_LITERAL(op)) {
752         op->aop = aop = newAsmop(AOP_LIT);
753         aop->aopu.aop_lit = op->operand.valOperand;
754         aop->size = getSize(operandType(op));
755         return;
756     }
757
758     {
759       sym_link *type = operandType(op);
760       if(IS_PTR_CONST(type))
761         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
762     }
763
764     /* if already has a asmop then continue */
765     if (op->aop)
766         return ;
767
768     /* if the underlying symbol has a aop */
769     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
770       DEBUGpic14_emitcode(";","%d",__LINE__);
771         op->aop = OP_SYMBOL(op)->aop;
772         return;
773     }
774
775     /* if this is a true symbol */
776     if (IS_TRUE_SYMOP(op)) {    
777       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
778       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
779       return ;
780     }
781
782     /* this is a temporary : this has
783     only four choices :
784     a) register
785     b) spillocation
786     c) rematerialize 
787     d) conditional   
788     e) can be a return use only */
789
790     sym = OP_SYMBOL(op);
791
792
793     /* if the type is a conditional */
794     if (sym->regType == REG_CND) {
795         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
796         aop->size = 0;
797         return;
798     }
799
800     /* if it is spilt then two situations
801     a) is rematerialize 
802     b) has a spill location */
803     if (sym->isspilt || sym->nRegs == 0) {
804
805       DEBUGpic14_emitcode(";","%d",__LINE__);
806         /* rematerialize it NOW */
807         if (sym->remat) {
808
809             sym->aop = op->aop = aop =
810                                       aopForRemat (op);
811             aop->size = getSize(sym->type);
812             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
813             return;
814         }
815
816         if (sym->accuse) {
817             int i;
818             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
819             aop->size = getSize(sym->type);
820             for ( i = 0 ; i < 2 ; i++ )
821                 aop->aopu.aop_str[i] = accUse[i];
822             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
823             return;  
824         }
825
826         if (sym->ruonly ) {
827           /*
828           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
829           aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
830           //allocDirReg (IC_LEFT(ic));
831           aop->size = getSize(sym->type);
832           */
833
834           unsigned i;
835
836           aop = op->aop = sym->aop = newAsmop(AOP_STR);
837           aop->size = getSize(sym->type);
838           for ( i = 0 ; i < fReturnSizePic ; i++ )
839             aop->aopu.aop_str[i] = fReturn[i];
840
841           DEBUGpic14_emitcode(";","%d",__LINE__);
842           return;
843         }
844
845         /* else spill location  */
846         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
847             /* force a new aop if sizes differ */
848             sym->usl.spillLoc->aop = NULL;
849         }
850         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
851                             __FUNCTION__,__LINE__,
852                             sym->usl.spillLoc->rname,
853                             sym->rname, sym->usl.spillLoc->offset);
854
855         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
856         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
857         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
858                                           getSize(sym->type), 
859                                           sym->usl.spillLoc->offset);
860         aop->size = getSize(sym->type);
861
862         return;
863     }
864
865     {
866       sym_link *type = operandType(op);
867       if(IS_PTR_CONST(type)) 
868         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
869     }
870
871     /* must be in a register */
872     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
873     sym->aop = op->aop = aop = newAsmop(AOP_REG);
874     aop->size = sym->nRegs;
875     for ( i = 0 ; i < sym->nRegs ;i++)
876         aop->aopu.aop_reg[i] = sym->regs[i];
877 }
878
879 /*-----------------------------------------------------------------*/
880 /* freeAsmop - free up the asmop given to an operand               */
881 /*----------------------------------------------------------------*/
882 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
883 {   
884     asmop *aop ;
885
886     if (!op)
887         aop = aaop;
888     else 
889         aop = op->aop;
890
891     if (!aop)
892         return ;
893
894     if (aop->freed)
895         goto dealloc; 
896
897     aop->freed = 1;
898
899     /* depending on the asmop type only three cases need work AOP_RO
900        , AOP_R1 && AOP_STK */
901 #if 0
902     switch (aop->type) {
903         case AOP_R0 :
904             if (_G.r0Pushed ) {
905                 if (pop) {
906                     pic14_emitcode ("pop","ar0");     
907                     _G.r0Pushed--;
908                 }
909             }
910             bitVectUnSetBit(ic->rUsed,R0_IDX);
911             break;
912
913         case AOP_R1 :
914             if (_G.r1Pushed ) {
915                 if (pop) {
916                     pic14_emitcode ("pop","ar1");
917                     _G.r1Pushed--;
918                 }
919             }
920             bitVectUnSetBit(ic->rUsed,R1_IDX);          
921             break;
922
923         case AOP_STK :
924         {
925             int sz = aop->size;    
926             int stk = aop->aopu.aop_stk + aop->size;
927             bitVectUnSetBit(ic->rUsed,R0_IDX);
928             bitVectUnSetBit(ic->rUsed,R1_IDX);          
929
930             getFreePtr(ic,&aop,FALSE);
931             
932             if (options.stack10bit)
933             {
934                 /* I'm not sure what to do here yet... */
935                 /* #STUB */
936                 fprintf(stderr, 
937                         "*** Warning: probably generating bad code for "
938                         "10 bit stack mode.\n");
939             }
940             
941             if (stk) {
942                 pic14_emitcode ("mov","a,_bp");
943                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
944                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
945             } else {
946                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
947             }
948
949             while (sz--) {
950                 pic14_emitcode("pop","acc");
951                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
952                 if (!sz) break;
953                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
954             }
955             op->aop = aop;
956             freeAsmop(op,NULL,ic,TRUE);
957             if (_G.r0Pushed) {
958                 pic14_emitcode("pop","ar0");
959                 _G.r0Pushed--;
960             }
961
962             if (_G.r1Pushed) {
963                 pic14_emitcode("pop","ar1");
964                 _G.r1Pushed--;
965             }       
966         }
967     }
968 #endif
969
970 dealloc:
971     /* all other cases just dealloc */
972     if (op ) {
973         op->aop = NULL;
974         if (IS_SYMOP(op)) {
975             OP_SYMBOL(op)->aop = NULL;    
976             /* if the symbol has a spill */
977             if (SPIL_LOC(op))
978                 SPIL_LOC(op)->aop = NULL;
979         }
980     }
981 }
982
983 /*-----------------------------------------------------------------*/
984 /* aopGet - for fetching value of the aop                          */
985 /*-----------------------------------------------------------------*/
986 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
987 {
988     char *s = buffer ;
989     char *rs;
990
991     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
992     /* offset is greater than
993     size then zero */
994     if (offset > (aop->size - 1) &&
995         aop->type != AOP_LIT)
996         return zero;
997
998     /* depending on type */
999     switch (aop->type) {
1000         
1001     case AOP_R0:
1002     case AOP_R1:
1003         DEBUGpic14_emitcode(";","%d",__LINE__);
1004         /* if we need to increment it */       
1005         while (offset > aop->coff) {        
1006             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1007             aop->coff++;
1008         }
1009         
1010         while (offset < aop->coff) {
1011             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1012             aop->coff--;
1013         }
1014         
1015         aop->coff = offset ;
1016         if (aop->paged) {
1017             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1018             return (dname ? "acc" : "a");
1019         }       
1020         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1021         rs = Safe_calloc(1,strlen(s)+1);
1022         strcpy(rs,s);   
1023         return rs;
1024         
1025     case AOP_DPTR:
1026     case AOP_DPTR2:
1027         DEBUGpic14_emitcode(";","%d",__LINE__);
1028     if (aop->type == AOP_DPTR2)
1029     {
1030         genSetDPTR(1);
1031     }
1032     
1033         while (offset > aop->coff) {
1034             pic14_emitcode ("inc","dptr");
1035             aop->coff++;
1036         }
1037         
1038         while (offset < aop->coff) {        
1039             pic14_emitcode("lcall","__decdptr");
1040             aop->coff--;
1041         }
1042         
1043         aop->coff = offset;
1044         if (aop->code) {
1045             pic14_emitcode("clr","a");
1046             pic14_emitcode("movc","a,@a+dptr");
1047         }
1048     else {
1049             pic14_emitcode("movx","a,@dptr");
1050     }
1051             
1052     if (aop->type == AOP_DPTR2)
1053     {
1054         genSetDPTR(0);
1055     }
1056             
1057     return (dname ? "acc" : "a");
1058         
1059         
1060     case AOP_IMMD:
1061         if (bit16) 
1062             sprintf (s,"%s",aop->aopu.aop_immd);
1063         else
1064             if (offset) 
1065                 sprintf(s,"(%s >> %d)",
1066                         aop->aopu.aop_immd,
1067                         offset*8);
1068             else
1069                 sprintf(s,"%s",
1070                         aop->aopu.aop_immd);
1071         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1072         rs = Safe_calloc(1,strlen(s)+1);
1073         strcpy(rs,s);   
1074         return rs;
1075         
1076     case AOP_DIR:
1077       if (offset) {
1078         sprintf(s,"(%s + %d)",
1079                 aop->aopu.aop_dir,
1080                 offset);
1081         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1082       } else
1083             sprintf(s,"%s",aop->aopu.aop_dir);
1084         rs = Safe_calloc(1,strlen(s)+1);
1085         strcpy(rs,s);   
1086         return rs;
1087         
1088     case AOP_REG:
1089       //if (dname) 
1090       //    return aop->aopu.aop_reg[offset]->dname;
1091       //else
1092             return aop->aopu.aop_reg[offset]->name;
1093         
1094     case AOP_CRY:
1095       //pic14_emitcode(";","%d",__LINE__);
1096       return aop->aopu.aop_dir;
1097         
1098     case AOP_ACC:
1099         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1100         return "AOP_accumulator_bug";
1101
1102     case AOP_LIT:
1103         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1104         rs = Safe_calloc(1,strlen(s)+1);
1105         strcpy(rs,s);   
1106         return rs;
1107         
1108     case AOP_STR:
1109         DEBUGpic14_emitcode(";","%d",__LINE__);
1110         aop->coff = offset ;
1111         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1112             dname)
1113             return "acc";
1114         
1115         return aop->aopu.aop_str[offset];
1116         
1117     case AOP_PCODE:
1118       {
1119         pCodeOp *pcop = aop->aopu.pcop;
1120         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1121         if(pcop->name) {
1122           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1123           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1124           sprintf(s,"%s", pcop->name);
1125         } else
1126           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1127
1128       }
1129       rs = Safe_calloc(1,strlen(s)+1);
1130       strcpy(rs,s);   
1131       return rs;
1132
1133     }
1134
1135     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1136            "aopget got unsupported aop->type");
1137     exit(0);
1138 }
1139
1140
1141 /*-----------------------------------------------------------------*/
1142 /* popGetTempReg - create a new temporary pCodeOp                  */
1143 /*-----------------------------------------------------------------*/
1144 pCodeOp *popGetTempReg(void)
1145 {
1146
1147   pCodeOp *pcop;
1148
1149   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1150   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1151     PCOR(pcop)->r->wasUsed=1;
1152     PCOR(pcop)->r->isFree=0;
1153   }
1154
1155   return pcop;
1156 }
1157
1158 /*-----------------------------------------------------------------*/
1159 /* popGetTempReg - create a new temporary pCodeOp                  */
1160 /*-----------------------------------------------------------------*/
1161 void popReleaseTempReg(pCodeOp *pcop)
1162 {
1163
1164   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1165     PCOR(pcop)->r->isFree = 1;
1166
1167 }
1168 /*-----------------------------------------------------------------*/
1169 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1170 /*-----------------------------------------------------------------*/
1171 pCodeOp *popGetLabel(unsigned int key)
1172 {
1173
1174   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1175
1176   if(key>max_key)
1177     max_key = key;
1178
1179   return newpCodeOpLabel(NULL,key+100+labelOffset);
1180 }
1181
1182 /*-----------------------------------------------------------------*/
1183 /* popCopyReg - copy a pcode operator                              */
1184 /*-----------------------------------------------------------------*/
1185 pCodeOp *popCopyReg(pCodeOpReg *pc)
1186 {
1187   pCodeOpReg *pcor;
1188
1189   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1190   pcor->pcop.type = pc->pcop.type;
1191   if(pc->pcop.name) {
1192     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1193       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1194   } else
1195     pcor->pcop.name = NULL;
1196
1197   pcor->r = pc->r;
1198   pcor->rIdx = pc->rIdx;
1199   pcor->r->wasUsed=1;
1200
1201   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1202
1203   return PCOP(pcor);
1204 }
1205 /*-----------------------------------------------------------------*/
1206 /* popGet - asm operator to pcode operator conversion              */
1207 /*-----------------------------------------------------------------*/
1208 pCodeOp *popGetLit(unsigned int lit)
1209 {
1210
1211   return newpCodeOpLit(lit);
1212 }
1213
1214
1215 /*-----------------------------------------------------------------*/
1216 /* popGetImmd - asm operator to pcode immediate conversion         */
1217 /*-----------------------------------------------------------------*/
1218 pCodeOp *popGetImmd(char *name, unsigned int offset, int index)
1219 {
1220
1221   return newpCodeOpImmd(name, offset,index, 0);
1222 }
1223
1224
1225 /*-----------------------------------------------------------------*/
1226 /* popGet - asm operator to pcode operator conversion              */
1227 /*-----------------------------------------------------------------*/
1228 pCodeOp *popGetWithString(char *str)
1229 {
1230   pCodeOp *pcop;
1231
1232
1233   if(!str) {
1234     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1235     exit (1);
1236   }
1237
1238   pcop = newpCodeOp(str,PO_STR);
1239
1240   return pcop;
1241 }
1242
1243 /*-----------------------------------------------------------------*/
1244 /* popRegFromString -                                              */
1245 /*-----------------------------------------------------------------*/
1246 pCodeOp *popRegFromString(char *str, int size, int offset)
1247 {
1248
1249   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1250   pcop->type = PO_DIR;
1251
1252   DEBUGpic14_emitcode(";","%d",__LINE__);
1253
1254   if(!str)
1255     str = "BAD_STRING";
1256
1257   pcop->name = Safe_calloc(1,strlen(str)+1);
1258   strcpy(pcop->name,str);
1259
1260   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1261
1262   PCOR(pcop)->r = dirregWithName(pcop->name);
1263   if(PCOR(pcop)->r == NULL) {
1264     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1265     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1266     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1267   } else {
1268     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1269   }
1270   PCOR(pcop)->instance = offset;
1271
1272   return pcop;
1273 }
1274
1275 pCodeOp *popRegFromIdx(int rIdx)
1276 {
1277   pCodeOp *pcop;
1278
1279   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1280                        __FUNCTION__,__LINE__,rIdx);
1281
1282   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1283
1284   PCOR(pcop)->rIdx = rIdx;
1285   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1286   PCOR(pcop)->r->isFree = 0;
1287   PCOR(pcop)->r->wasUsed = 1;
1288
1289   pcop->type = PCOR(pcop)->r->pc_type;
1290
1291
1292   return pcop;
1293 }
1294 /*-----------------------------------------------------------------*/
1295 /* popGet - asm operator to pcode operator conversion              */
1296 /*-----------------------------------------------------------------*/
1297 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1298 {
1299   //char *s = buffer ;
1300     //char *rs;
1301
1302     pCodeOp *pcop;
1303
1304     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1305     /* offset is greater than
1306     size then zero */
1307
1308     if (offset > (aop->size - 1) &&
1309         aop->type != AOP_LIT)
1310       return NULL;  //zero;
1311
1312     /* depending on type */
1313     switch (aop->type) {
1314         
1315     case AOP_R0:
1316     case AOP_R1:
1317     case AOP_DPTR:
1318     case AOP_DPTR2:
1319     case AOP_ACC:
1320         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1321         return NULL;
1322         
1323     case AOP_IMMD:
1324       DEBUGpic14_emitcode(";","%d",__LINE__);
1325       return popGetImmd(aop->aopu.aop_immd,offset,0);
1326
1327     case AOP_DIR:
1328       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1329 #if 0
1330         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1331         pcop->type = PO_DIR;
1332
1333         /*
1334         if (offset)
1335             sprintf(s,"(%s + %d)",
1336                     aop->aopu.aop_dir,
1337                     offset);
1338         else
1339             sprintf(s,"%s",aop->aopu.aop_dir);
1340         pcop->name = Safe_calloc(1,strlen(s)+1);
1341         strcpy(pcop->name,s);   
1342         */
1343         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1344         strcpy(pcop->name,aop->aopu.aop_dir);   
1345         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1346         if(PCOR(pcop)->r == NULL) {
1347           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1348           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1349           DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1350         } else {
1351           DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1352         }
1353         PCOR(pcop)->instance = offset;
1354
1355         return pcop;
1356 #endif
1357         
1358     case AOP_REG:
1359       {
1360         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1361
1362         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1363         PCOR(pcop)->rIdx = rIdx;
1364         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1365         PCOR(pcop)->r->wasUsed=1;
1366         PCOR(pcop)->r->isFree=0;
1367
1368         PCOR(pcop)->instance = offset;
1369         pcop->type = PCOR(pcop)->r->pc_type;
1370         //rs = aop->aopu.aop_reg[offset]->name;
1371         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1372         return pcop;
1373       }
1374
1375     case AOP_CRY:
1376       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1377       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1378       //if(PCOR(pcop)->r == NULL)
1379       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1380       return pcop;
1381         
1382     case AOP_LIT:
1383       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1384
1385     case AOP_STR:
1386       DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1387       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1388       /*
1389       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1390       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1391       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1392       pcop->type = PCOR(pcop)->r->pc_type;
1393       pcop->name = PCOR(pcop)->r->name;
1394
1395       return pcop;
1396       */
1397
1398     case AOP_PCODE:
1399       DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1400                           __LINE__, 
1401                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1402       pcop = pCodeOpCopy(aop->aopu.pcop);
1403       PCOI(pcop)->offset = offset;
1404       return pcop;
1405     }
1406
1407     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1408            "popGet got unsupported aop->type");
1409     exit(0);
1410 }
1411 /*-----------------------------------------------------------------*/
1412 /* aopPut - puts a string for a aop                                */
1413 /*-----------------------------------------------------------------*/
1414 void aopPut (asmop *aop, char *s, int offset)
1415 {
1416     char *d = buffer ;
1417     symbol *lbl ;
1418
1419     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1420
1421     if (aop->size && offset > ( aop->size - 1)) {
1422         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1423                "aopPut got offset > aop->size");
1424         exit(0);
1425     }
1426
1427     /* will assign value to value */
1428     /* depending on where it is ofcourse */
1429     switch (aop->type) {
1430     case AOP_DIR:
1431       if (offset) {
1432         sprintf(d,"(%s + %d)",
1433                 aop->aopu.aop_dir,offset);
1434         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1435
1436       } else
1437             sprintf(d,"%s",aop->aopu.aop_dir);
1438         
1439         if (strcmp(d,s)) {
1440           DEBUGpic14_emitcode(";","%d",__LINE__);
1441           if(strcmp(s,"W"))
1442             pic14_emitcode("movf","%s,w",s);
1443           pic14_emitcode("movwf","%s",d);
1444
1445           if(strcmp(s,"W")) {
1446             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1447             if(offset >= aop->size) {
1448               emitpcode(POC_CLRF,popGet(aop,offset));
1449               break;
1450             } else
1451               emitpcode(POC_MOVLW,popGetImmd(s,offset,0));
1452           }
1453
1454           emitpcode(POC_MOVWF,popGet(aop,offset));
1455
1456
1457         }
1458         break;
1459         
1460     case AOP_REG:
1461       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1462         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1463           /*
1464             if (*s == '@'           ||
1465                 strcmp(s,"r0") == 0 ||
1466                 strcmp(s,"r1") == 0 ||
1467                 strcmp(s,"r2") == 0 ||
1468                 strcmp(s,"r3") == 0 ||
1469                 strcmp(s,"r4") == 0 ||
1470                 strcmp(s,"r5") == 0 ||
1471                 strcmp(s,"r6") == 0 || 
1472                 strcmp(s,"r7") == 0 )
1473                 pic14_emitcode("mov","%s,%s  ; %d",
1474                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1475             else
1476           */
1477
1478           if(strcmp(s,"W")==0 )
1479             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1480
1481           pic14_emitcode("movwf","%s",
1482                    aop->aopu.aop_reg[offset]->name);
1483
1484           if(strcmp(s,zero)==0) {
1485             emitpcode(POC_CLRF,popGet(aop,offset));
1486
1487           } else if(strcmp(s,"W")==0) {
1488             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1489             pcop->type = PO_GPR_REGISTER;
1490
1491             PCOR(pcop)->rIdx = -1;
1492             PCOR(pcop)->r = NULL;
1493
1494             DEBUGpic14_emitcode(";","%d",__LINE__);
1495             pcop->name = Safe_strdup(s);
1496             emitpcode(POC_MOVFW,pcop);
1497             emitpcode(POC_MOVWF,popGet(aop,offset));
1498           } else if(strcmp(s,one)==0) {
1499             emitpcode(POC_CLRF,popGet(aop,offset));
1500             emitpcode(POC_INCF,popGet(aop,offset));
1501           } else {
1502             emitpcode(POC_MOVWF,popGet(aop,offset));
1503           }
1504         }
1505         break;
1506         
1507     case AOP_DPTR:
1508     case AOP_DPTR2:
1509     
1510     if (aop->type == AOP_DPTR2)
1511     {
1512         genSetDPTR(1);
1513     }
1514     
1515         if (aop->code) {
1516             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1517                    "aopPut writting to code space");
1518             exit(0);
1519         }
1520         
1521         while (offset > aop->coff) {
1522             aop->coff++;
1523             pic14_emitcode ("inc","dptr");
1524         }
1525         
1526         while (offset < aop->coff) {
1527             aop->coff-- ;
1528             pic14_emitcode("lcall","__decdptr");
1529         }
1530         
1531         aop->coff = offset;
1532         
1533         /* if not in accumulater */
1534         MOVA(s);        
1535         
1536         pic14_emitcode ("movx","@dptr,a");
1537         
1538     if (aop->type == AOP_DPTR2)
1539     {
1540         genSetDPTR(0);
1541     }
1542         break;
1543         
1544     case AOP_R0:
1545     case AOP_R1:
1546         while (offset > aop->coff) {
1547             aop->coff++;
1548             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1549         }
1550         while (offset < aop->coff) {
1551             aop->coff-- ;
1552             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1553         }
1554         aop->coff = offset;
1555         
1556         if (aop->paged) {
1557             MOVA(s);           
1558             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1559             
1560         } else
1561             if (*s == '@') {
1562                 MOVA(s);
1563                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1564             } else
1565                 if (strcmp(s,"r0") == 0 ||
1566                     strcmp(s,"r1") == 0 ||
1567                     strcmp(s,"r2") == 0 ||
1568                     strcmp(s,"r3") == 0 ||
1569                     strcmp(s,"r4") == 0 ||
1570                     strcmp(s,"r5") == 0 ||
1571                     strcmp(s,"r6") == 0 || 
1572                     strcmp(s,"r7") == 0 ) {
1573                     char buffer[10];
1574                     sprintf(buffer,"a%s",s);
1575                     pic14_emitcode("mov","@%s,%s",
1576                              aop->aopu.aop_ptr->name,buffer);
1577                 } else
1578                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1579         
1580         break;
1581         
1582     case AOP_STK:
1583         if (strcmp(s,"a") == 0)
1584             pic14_emitcode("push","acc");
1585         else
1586             pic14_emitcode("push","%s",s);
1587         
1588         break;
1589         
1590     case AOP_CRY:
1591         /* if bit variable */
1592         if (!aop->aopu.aop_dir) {
1593             pic14_emitcode("clr","a");
1594             pic14_emitcode("rlc","a");
1595         } else {
1596             if (s == zero) 
1597                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1598             else
1599                 if (s == one)
1600                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1601                 else
1602                     if (!strcmp(s,"c"))
1603                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1604                     else {
1605                         lbl = newiTempLabel(NULL);
1606                         
1607                         if (strcmp(s,"a")) {
1608                             MOVA(s);
1609                         }
1610                         pic14_emitcode("clr","c");
1611                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1612                         pic14_emitcode("cpl","c");
1613                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1614                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1615                     }
1616         }
1617         break;
1618         
1619     case AOP_STR:
1620         aop->coff = offset;
1621         if (strcmp(aop->aopu.aop_str[offset],s))
1622             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1623         break;
1624         
1625     case AOP_ACC:
1626         aop->coff = offset;
1627         if (!offset && (strcmp(s,"acc") == 0))
1628             break;
1629         
1630         if (strcmp(aop->aopu.aop_str[offset],s))
1631             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1632         break;
1633
1634     default :
1635         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1636                "aopPut got unsupported aop->type");
1637         exit(0);    
1638     }    
1639
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1644 /*-----------------------------------------------------------------*/
1645 void mov2w (asmop *aop, int offset)
1646 {
1647
1648   if(!aop)
1649     return;
1650
1651   if ( aop->type == AOP_PCODE ||
1652        aop->type == AOP_LIT )
1653     emitpcode(POC_MOVLW,popGet(aop,offset));
1654   else
1655     emitpcode(POC_MOVFW,popGet(aop,offset));
1656
1657 }
1658
1659 /*-----------------------------------------------------------------*/
1660 /* reAdjustPreg - points a register back to where it should        */
1661 /*-----------------------------------------------------------------*/
1662 static void reAdjustPreg (asmop *aop)
1663 {
1664     int size ;
1665
1666     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1667     aop->coff = 0;
1668     if ((size = aop->size) <= 1)
1669         return ;
1670     size-- ;
1671     switch (aop->type) {
1672         case AOP_R0 :
1673         case AOP_R1 :
1674             while (size--)
1675                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1676             break;          
1677         case AOP_DPTR :
1678         case AOP_DPTR2:
1679             if (aop->type == AOP_DPTR2)
1680             {
1681                 genSetDPTR(1);
1682             } 
1683             while (size--)
1684             {
1685                 pic14_emitcode("lcall","__decdptr");
1686             }
1687                 
1688             if (aop->type == AOP_DPTR2)
1689             {
1690                 genSetDPTR(0);
1691             }                
1692             break;  
1693
1694     }   
1695
1696 }
1697
1698 /*-----------------------------------------------------------------*/
1699 /* genNotFloat - generates not for float operations              */
1700 /*-----------------------------------------------------------------*/
1701 static void genNotFloat (operand *op, operand *res)
1702 {
1703     int size, offset;
1704     char *l;
1705     symbol *tlbl ;
1706
1707     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1708     /* we will put 127 in the first byte of 
1709     the result */
1710     aopPut(AOP(res),"#127",0);
1711     size = AOP_SIZE(op) - 1;
1712     offset = 1;
1713
1714     l = aopGet(op->aop,offset++,FALSE,FALSE);
1715     MOVA(l);    
1716
1717     while(size--) {
1718         pic14_emitcode("orl","a,%s",
1719                  aopGet(op->aop,
1720                         offset++,FALSE,FALSE));
1721     }
1722     tlbl = newiTempLabel(NULL);
1723
1724     tlbl = newiTempLabel(NULL);
1725     aopPut(res->aop,one,1);
1726     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1727     aopPut(res->aop,zero,1);
1728     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1729
1730     size = res->aop->size - 2;
1731     offset = 2;    
1732     /* put zeros in the rest */
1733     while (size--) 
1734         aopPut(res->aop,zero,offset++);
1735 }
1736
1737 #if 0
1738 /*-----------------------------------------------------------------*/
1739 /* opIsGptr: returns non-zero if the passed operand is             */   
1740 /* a generic pointer type.                                         */
1741 /*-----------------------------------------------------------------*/ 
1742 static int opIsGptr(operand *op)
1743 {
1744     sym_link *type = operandType(op);
1745     
1746     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1747     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1748     {
1749         return 1;
1750     }
1751     return 0;        
1752 }
1753 #endif
1754
1755 /*-----------------------------------------------------------------*/
1756 /* pic14_getDataSize - get the operand data size                         */
1757 /*-----------------------------------------------------------------*/
1758 int pic14_getDataSize(operand *op)
1759 {
1760     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1761
1762
1763     return AOP_SIZE(op);
1764
1765     // tsd- in the pic port, the genptr size is 1, so this code here
1766     // fails. ( in the 8051 port, the size was 4).
1767 #if 0
1768     int size;
1769     size = AOP_SIZE(op);
1770     if (size == GPTRSIZE)
1771     {
1772         sym_link *type = operandType(op);
1773         if (IS_GENPTR(type))
1774         {
1775             /* generic pointer; arithmetic operations
1776              * should ignore the high byte (pointer type).
1777              */
1778             size--;
1779     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780         }
1781     }
1782     return size;
1783 #endif
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic14_outAcc - output Acc                                             */
1788 /*-----------------------------------------------------------------*/
1789 void pic14_outAcc(operand *result)
1790 {
1791   int size,offset;
1792   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1793   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1794
1795
1796   size = pic14_getDataSize(result);
1797   if(size){
1798     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1799     size--;
1800     offset = 1;
1801     /* unsigned or positive */
1802     while(size--)
1803       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1804   }
1805
1806 }
1807
1808 /*-----------------------------------------------------------------*/
1809 /* pic14_outBitC - output a bit C                                        */
1810 /*-----------------------------------------------------------------*/
1811 void pic14_outBitC(operand *result)
1812 {
1813
1814     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1815     /* if the result is bit */
1816     if (AOP_TYPE(result) == AOP_CRY) 
1817         aopPut(AOP(result),"c",0);
1818     else {
1819         pic14_emitcode("clr","a  ; %d", __LINE__);
1820         pic14_emitcode("rlc","a");
1821         pic14_outAcc(result);
1822     }
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1827 /*-----------------------------------------------------------------*/
1828 void pic14_toBoolean(operand *oper)
1829 {
1830     int size = AOP_SIZE(oper) - 1;
1831     int offset = 1;
1832
1833     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1834
1835     if ( AOP_TYPE(oper) != AOP_ACC) {
1836       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1837     }
1838     while (size--) {
1839       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1840     }
1841 }
1842
1843
1844 /*-----------------------------------------------------------------*/
1845 /* genNot - generate code for ! operation                          */
1846 /*-----------------------------------------------------------------*/
1847 static void genNot (iCode *ic)
1848 {
1849   symbol *tlbl;
1850   sym_link *optype = operandType(IC_LEFT(ic));
1851   int size;
1852
1853   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1854   /* assign asmOps to operand & result */
1855   aopOp (IC_LEFT(ic),ic,FALSE);
1856   aopOp (IC_RESULT(ic),ic,TRUE);
1857
1858   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1859   /* if in bit space then a special case */
1860   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1861     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1862       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1863       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1864     } else {
1865       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1866       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1867       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1868     }
1869     goto release;
1870   }
1871
1872   /* if type float then do float */
1873   if (IS_FLOAT(optype)) {
1874     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1875     goto release;
1876   }
1877
1878   size = AOP_SIZE(IC_RESULT(ic));
1879   if(size == 1) {
1880     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1881     emitpcode(POC_ANDLW,popGetLit(1));
1882     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1883     goto release;
1884   }
1885   pic14_toBoolean(IC_LEFT(ic));
1886
1887   tlbl = newiTempLabel(NULL);
1888   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1889   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1890   pic14_outBitC(IC_RESULT(ic));
1891
1892  release:    
1893   /* release the aops */
1894   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1895   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1896 }
1897
1898
1899 /*-----------------------------------------------------------------*/
1900 /* genCpl - generate code for complement                           */
1901 /*-----------------------------------------------------------------*/
1902 static void genCpl (iCode *ic)
1903 {
1904     int offset = 0;
1905     int size ;
1906
1907
1908     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909     /* assign asmOps to operand & result */
1910     aopOp (IC_LEFT(ic),ic,FALSE);
1911     aopOp (IC_RESULT(ic),ic,TRUE);
1912
1913     /* if both are in bit space then 
1914     a special case */
1915     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1916         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1917
1918         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1919         pic14_emitcode("cpl","c"); 
1920         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1921         goto release; 
1922     } 
1923
1924     size = AOP_SIZE(IC_RESULT(ic));
1925     while (size--) {
1926         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1927         MOVA(l);       
1928         pic14_emitcode("cpl","a");
1929         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1930     }
1931
1932
1933 release:
1934     /* release the aops */
1935     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1936     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* genUminusFloat - unary minus for floating points                */
1941 /*-----------------------------------------------------------------*/
1942 static void genUminusFloat(operand *op,operand *result)
1943 {
1944     int size ,offset =0 ;
1945     char *l;
1946
1947     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1948     /* for this we just need to flip the 
1949     first it then copy the rest in place */
1950     size = AOP_SIZE(op) - 1;
1951     l = aopGet(AOP(op),3,FALSE,FALSE);
1952
1953     MOVA(l);    
1954
1955     pic14_emitcode("cpl","acc.7");
1956     aopPut(AOP(result),"a",3);    
1957
1958     while(size--) {
1959         aopPut(AOP(result),
1960                aopGet(AOP(op),offset,FALSE,FALSE),
1961                offset);
1962         offset++;
1963     }          
1964 }
1965
1966 /*-----------------------------------------------------------------*/
1967 /* genUminus - unary minus code generation                         */
1968 /*-----------------------------------------------------------------*/
1969 static void genUminus (iCode *ic)
1970 {
1971   int size, i;
1972   sym_link *optype, *rtype;
1973
1974
1975   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1976   /* assign asmops */
1977   aopOp(IC_LEFT(ic),ic,FALSE);
1978   aopOp(IC_RESULT(ic),ic,TRUE);
1979
1980   /* if both in bit space then special
1981      case */
1982   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1983       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1984
1985     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1986     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1987     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1988
1989     goto release; 
1990   } 
1991
1992   optype = operandType(IC_LEFT(ic));
1993   rtype = operandType(IC_RESULT(ic));
1994
1995   /* if float then do float stuff */
1996   if (IS_FLOAT(optype)) {
1997     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1998     goto release;
1999   }
2000
2001   /* otherwise subtract from zero by taking the 2's complement */
2002   size = AOP_SIZE(IC_LEFT(ic));
2003
2004   for(i=0; i<size; i++) {
2005     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2006       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2007     else {
2008       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2009       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2010     }
2011   }
2012
2013   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2014   for(i=1; i<size; i++) {
2015     emitSKPNZ;
2016     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2017   }
2018
2019  release:
2020   /* release the aops */
2021   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2022   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2023 }
2024
2025 /*-----------------------------------------------------------------*/
2026 /* saveRegisters - will look for a call and save the registers     */
2027 /*-----------------------------------------------------------------*/
2028 static void saveRegisters(iCode *lic) 
2029 {
2030     int i;
2031     iCode *ic;
2032     bitVect *rsave;
2033     sym_link *dtype;
2034
2035     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2036     /* look for call */
2037     for (ic = lic ; ic ; ic = ic->next) 
2038         if (ic->op == CALL || ic->op == PCALL)
2039             break;
2040
2041     if (!ic) {
2042         fprintf(stderr,"found parameter push with no function call\n");
2043         return ;
2044     }
2045
2046     /* if the registers have been saved already then
2047     do nothing */
2048     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2049         return ;
2050
2051     /* find the registers in use at this time 
2052     and push them away to safety */
2053     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2054                           ic->rUsed);
2055
2056     ic->regsSaved = 1;
2057     if (options.useXstack) {
2058         if (bitVectBitValue(rsave,R0_IDX))
2059             pic14_emitcode("mov","b,r0");
2060         pic14_emitcode("mov","r0,%s",spname);
2061         for (i = 0 ; i < pic14_nRegs ; i++) {
2062             if (bitVectBitValue(rsave,i)) {
2063                 if (i == R0_IDX)
2064                     pic14_emitcode("mov","a,b");
2065                 else
2066                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2067                 pic14_emitcode("movx","@r0,a");
2068                 pic14_emitcode("inc","r0");
2069             }
2070         }
2071         pic14_emitcode("mov","%s,r0",spname);
2072         if (bitVectBitValue(rsave,R0_IDX))
2073             pic14_emitcode("mov","r0,b");           
2074     }// else
2075     //for (i = 0 ; i < pic14_nRegs ; i++) {
2076     //    if (bitVectBitValue(rsave,i))
2077     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2078     //}
2079
2080     dtype = operandType(IC_LEFT(ic));
2081     if (currFunc && dtype && 
2082         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2083         IFFUNC_ISISR(currFunc->type) &&
2084         !ic->bankSaved) 
2085
2086         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2087
2088 }
2089 /*-----------------------------------------------------------------*/
2090 /* unsaveRegisters - pop the pushed registers                      */
2091 /*-----------------------------------------------------------------*/
2092 static void unsaveRegisters (iCode *ic)
2093 {
2094     int i;
2095     bitVect *rsave;
2096
2097     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2098     /* find the registers in use at this time 
2099     and push them away to safety */
2100     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2101                           ic->rUsed);
2102     
2103     if (options.useXstack) {
2104         pic14_emitcode("mov","r0,%s",spname);   
2105         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2106             if (bitVectBitValue(rsave,i)) {
2107                 pic14_emitcode("dec","r0");
2108                 pic14_emitcode("movx","a,@r0");
2109                 if (i == R0_IDX)
2110                     pic14_emitcode("mov","b,a");
2111                 else
2112                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2113             }       
2114
2115         }
2116         pic14_emitcode("mov","%s,r0",spname);
2117         if (bitVectBitValue(rsave,R0_IDX))
2118             pic14_emitcode("mov","r0,b");
2119     } //else
2120     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2121     //    if (bitVectBitValue(rsave,i))
2122     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2123     //}
2124
2125 }  
2126
2127
2128 /*-----------------------------------------------------------------*/
2129 /* pushSide -                                                      */
2130 /*-----------------------------------------------------------------*/
2131 static void pushSide(operand * oper, int size)
2132 {
2133 #if 0
2134         int offset = 0;
2135     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2136         while (size--) {
2137                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2138                 if (AOP_TYPE(oper) != AOP_REG &&
2139                     AOP_TYPE(oper) != AOP_DIR &&
2140                     strcmp(l,"a") ) {
2141                         pic14_emitcode("mov","a,%s",l);
2142                         pic14_emitcode("push","acc");
2143                 } else
2144                         pic14_emitcode("push","%s",l);
2145         }
2146 #endif
2147 }
2148
2149 /*-----------------------------------------------------------------*/
2150 /* assignResultValue -                                             */
2151 /*-----------------------------------------------------------------*/
2152 static void assignResultValue(operand * oper)
2153 {
2154   int size = AOP_SIZE(oper);
2155
2156   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2157
2158   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2159
2160   if(!GpsuedoStkPtr) {
2161     /* The last byte in the assignment is in W */
2162     size--;
2163     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2164     GpsuedoStkPtr++;
2165   }
2166
2167   while (size--) {
2168     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2169     GpsuedoStkPtr++;
2170     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2171   }
2172 }
2173
2174
2175 /*-----------------------------------------------------------------*/
2176 /* genIpush - genrate code for pushing this gets a little complex  */
2177 /*-----------------------------------------------------------------*/
2178 static void genIpush (iCode *ic)
2179 {
2180
2181   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2182 #if 0
2183     int size, offset = 0 ;
2184     char *l;
2185
2186
2187     /* if this is not a parm push : ie. it is spill push 
2188     and spill push is always done on the local stack */
2189     if (!ic->parmPush) {
2190
2191         /* and the item is spilt then do nothing */
2192         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2193             return ;
2194
2195         aopOp(IC_LEFT(ic),ic,FALSE);
2196         size = AOP_SIZE(IC_LEFT(ic));
2197         /* push it on the stack */
2198         while(size--) {
2199             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2200             if (*l == '#') {
2201                 MOVA(l);
2202                 l = "acc";
2203             }
2204             pic14_emitcode("push","%s",l);
2205         }
2206         return ;        
2207     }
2208
2209     /* this is a paramter push: in this case we call
2210     the routine to find the call and save those
2211     registers that need to be saved */   
2212     saveRegisters(ic);
2213
2214     /* then do the push */
2215     aopOp(IC_LEFT(ic),ic,FALSE);
2216
2217
2218         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2219     size = AOP_SIZE(IC_LEFT(ic));
2220
2221     while (size--) {
2222         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2223         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2224             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2225             strcmp(l,"a") ) {
2226             pic14_emitcode("mov","a,%s",l);
2227             pic14_emitcode("push","acc");
2228         } else
2229             pic14_emitcode("push","%s",l);
2230     }       
2231
2232     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2233 #endif
2234 }
2235
2236 /*-----------------------------------------------------------------*/
2237 /* genIpop - recover the registers: can happen only for spilling   */
2238 /*-----------------------------------------------------------------*/
2239 static void genIpop (iCode *ic)
2240 {
2241   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2242 #if 0
2243     int size,offset ;
2244
2245
2246     /* if the temp was not pushed then */
2247     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2248         return ;
2249
2250     aopOp(IC_LEFT(ic),ic,FALSE);
2251     size = AOP_SIZE(IC_LEFT(ic));
2252     offset = (size-1);
2253     while (size--) 
2254         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2255                                    FALSE,TRUE));
2256
2257     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2258 #endif
2259 }
2260
2261 /*-----------------------------------------------------------------*/
2262 /* unsaverbank - restores the resgister bank from stack            */
2263 /*-----------------------------------------------------------------*/
2264 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2265 {
2266   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2267 #if 0
2268     int i;
2269     asmop *aop ;
2270     regs *r = NULL;
2271
2272     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2273     if (popPsw) {
2274         if (options.useXstack) {
2275             aop = newAsmop(0);
2276             r = getFreePtr(ic,&aop,FALSE);
2277             
2278             
2279             pic14_emitcode("mov","%s,_spx",r->name);
2280             pic14_emitcode("movx","a,@%s",r->name);
2281             pic14_emitcode("mov","psw,a");
2282             pic14_emitcode("dec","%s",r->name);
2283             
2284         }else
2285             pic14_emitcode ("pop","psw");
2286     }
2287
2288     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2289         if (options.useXstack) {       
2290             pic14_emitcode("movx","a,@%s",r->name);
2291             //pic14_emitcode("mov","(%s+%d),a",
2292             //       regspic14[i].base,8*bank+regspic14[i].offset);
2293             pic14_emitcode("dec","%s",r->name);
2294
2295         } else 
2296           pic14_emitcode("pop",""); //"(%s+%d)",
2297         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2298     }
2299
2300     if (options.useXstack) {
2301
2302         pic14_emitcode("mov","_spx,%s",r->name);
2303         freeAsmop(NULL,aop,ic,TRUE);
2304
2305     }
2306 #endif 
2307 }
2308
2309 /*-----------------------------------------------------------------*/
2310 /* saverbank - saves an entire register bank on the stack          */
2311 /*-----------------------------------------------------------------*/
2312 static void saverbank (int bank, iCode *ic, bool pushPsw)
2313 {
2314   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2315 #if 0
2316     int i;
2317     asmop *aop ;
2318     regs *r = NULL;
2319
2320     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2321     if (options.useXstack) {
2322
2323         aop = newAsmop(0);
2324         r = getFreePtr(ic,&aop,FALSE);  
2325         pic14_emitcode("mov","%s,_spx",r->name);
2326
2327     }
2328
2329     for (i = 0 ; i < pic14_nRegs ;i++) {
2330         if (options.useXstack) {
2331             pic14_emitcode("inc","%s",r->name);
2332             //pic14_emitcode("mov","a,(%s+%d)",
2333             //         regspic14[i].base,8*bank+regspic14[i].offset);
2334             pic14_emitcode("movx","@%s,a",r->name);           
2335         } else 
2336           pic14_emitcode("push","");// "(%s+%d)",
2337                      //regspic14[i].base,8*bank+regspic14[i].offset);
2338     }
2339     
2340     if (pushPsw) {
2341         if (options.useXstack) {
2342             pic14_emitcode("mov","a,psw");
2343             pic14_emitcode("movx","@%s,a",r->name);     
2344             pic14_emitcode("inc","%s",r->name);
2345             pic14_emitcode("mov","_spx,%s",r->name);       
2346             freeAsmop (NULL,aop,ic,TRUE);
2347             
2348         } else
2349             pic14_emitcode("push","psw");
2350         
2351         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2352     }
2353     ic->bankSaved = 1;
2354 #endif
2355 }
2356
2357 /*-----------------------------------------------------------------*/
2358 /* genCall - generates a call statement                            */
2359 /*-----------------------------------------------------------------*/
2360 static void genCall (iCode *ic)
2361 {
2362   sym_link *dtype;   
2363
2364   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2365
2366   /* if caller saves & we have not saved then */
2367   if (!ic->regsSaved)
2368     saveRegisters(ic);
2369
2370   /* if we are calling a function that is not using
2371      the same register bank then we need to save the
2372      destination registers on the stack */
2373   dtype = operandType(IC_LEFT(ic));
2374   if (currFunc && dtype && 
2375       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2376       IFFUNC_ISISR(currFunc->type) &&
2377       !ic->bankSaved) 
2378
2379     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2380
2381   /* if send set is not empty the assign */
2382   if (_G.sendSet) {
2383     iCode *sic;
2384     /* For the Pic port, there is no data stack.
2385      * So parameters passed to functions are stored
2386      * in registers. (The pCode optimizer will get
2387      * rid of most of these :).
2388      */
2389     int psuedoStkPtr=-1; 
2390     int firstTimeThruLoop = 1;
2391
2392     _G.sendSet = reverseSet(_G.sendSet);
2393
2394     /* First figure how many parameters are getting passed */
2395     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2396          sic = setNextItem(_G.sendSet)) {
2397
2398       aopOp(IC_LEFT(sic),sic,FALSE);
2399       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2400       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2401     }
2402
2403     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2404          sic = setNextItem(_G.sendSet)) {
2405       int size, offset = 0;
2406
2407       aopOp(IC_LEFT(sic),sic,FALSE);
2408       size = AOP_SIZE(IC_LEFT(sic));
2409
2410       while (size--) {
2411         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2412                              AopType(AOP_TYPE(IC_LEFT(sic))));
2413
2414         if(!firstTimeThruLoop) {
2415           /* If this is not the first time we've been through the loop
2416            * then we need to save the parameter in a temporary
2417            * register. The last byte of the last parameter is
2418            * passed in W. */
2419           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2420
2421         }
2422         firstTimeThruLoop=0;
2423
2424         //if (strcmp(l,fReturn[offset])) {
2425         mov2w (AOP(IC_LEFT(sic)),  offset);
2426 /*
2427         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2428              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2429           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2430         else
2431           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2432 */
2433         //}
2434         offset++;
2435       }
2436       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2437     }
2438     _G.sendSet = NULL;
2439   }
2440   /* make the call */
2441   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2442                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2443                                       OP_SYMBOL(IC_LEFT(ic))->name));
2444
2445   GpsuedoStkPtr=0;
2446   /* if we need assign a result value */
2447   if ((IS_ITEMP(IC_RESULT(ic)) && 
2448        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2449         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2450       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2451
2452     _G.accInUse++;
2453     aopOp(IC_RESULT(ic),ic,FALSE);
2454     _G.accInUse--;
2455
2456     assignResultValue(IC_RESULT(ic));
2457
2458     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2459                          AopType(AOP_TYPE(IC_RESULT(ic))));
2460                 
2461     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2462   }
2463
2464   /* adjust the stack for parameters if 
2465      required */
2466   if (ic->parmBytes) {
2467     int i;
2468     if (ic->parmBytes > 3) {
2469       pic14_emitcode("mov","a,%s",spname);
2470       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2471       pic14_emitcode("mov","%s,a",spname);
2472     } else 
2473       for ( i = 0 ; i <  ic->parmBytes ;i++)
2474         pic14_emitcode("dec","%s",spname);
2475
2476   }
2477
2478   /* if register bank was saved then pop them */
2479   if (ic->bankSaved)
2480     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2481
2482   /* if we hade saved some registers then unsave them */
2483   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2484     unsaveRegisters (ic);
2485
2486
2487 }
2488
2489 /*-----------------------------------------------------------------*/
2490 /* genPcall - generates a call by pointer statement                */
2491 /*-----------------------------------------------------------------*/
2492 static void genPcall (iCode *ic)
2493 {
2494     sym_link *dtype;
2495     symbol *rlbl = newiTempLabel(NULL);
2496
2497
2498     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2499     /* if caller saves & we have not saved then */
2500     if (!ic->regsSaved)
2501         saveRegisters(ic);
2502
2503     /* if we are calling a function that is not using
2504     the same register bank then we need to save the
2505     destination registers on the stack */
2506     dtype = operandType(IC_LEFT(ic));
2507     if (currFunc && dtype && 
2508         IFFUNC_ISISR(currFunc->type) &&
2509         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2510         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2511
2512
2513     /* push the return address on to the stack */
2514     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2515     pic14_emitcode("push","acc");    
2516     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2517     pic14_emitcode("push","acc");
2518     
2519     if (options.model == MODEL_FLAT24)
2520     {
2521         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2522         pic14_emitcode("push","acc");    
2523     }
2524
2525     /* now push the calling address */
2526     aopOp(IC_LEFT(ic),ic,FALSE);
2527
2528     pushSide(IC_LEFT(ic), FPTRSIZE);
2529
2530     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2531
2532     /* if send set is not empty the assign */
2533     if (_G.sendSet) {
2534         iCode *sic ;
2535
2536         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2537              sic = setNextItem(_G.sendSet)) {
2538             int size, offset = 0;
2539             aopOp(IC_LEFT(sic),sic,FALSE);
2540             size = AOP_SIZE(IC_LEFT(sic));
2541             while (size--) {
2542                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2543                                 FALSE,FALSE);
2544                 if (strcmp(l,fReturn[offset]))
2545                     pic14_emitcode("mov","%s,%s",
2546                              fReturn[offset],
2547                              l);
2548                 offset++;
2549             }
2550             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2551         }
2552         _G.sendSet = NULL;
2553     }
2554
2555     pic14_emitcode("ret","");
2556     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2557
2558
2559     /* if we need assign a result value */
2560     if ((IS_ITEMP(IC_RESULT(ic)) &&
2561          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2562           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2563         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2564
2565         _G.accInUse++;
2566         aopOp(IC_RESULT(ic),ic,FALSE);
2567         _G.accInUse--;
2568         
2569         assignResultValue(IC_RESULT(ic));
2570
2571         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2572     }
2573
2574     /* adjust the stack for parameters if 
2575     required */
2576     if (ic->parmBytes) {
2577         int i;
2578         if (ic->parmBytes > 3) {
2579             pic14_emitcode("mov","a,%s",spname);
2580             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2581             pic14_emitcode("mov","%s,a",spname);
2582         } else 
2583             for ( i = 0 ; i <  ic->parmBytes ;i++)
2584                 pic14_emitcode("dec","%s",spname);
2585
2586     }
2587
2588     /* if register bank was saved then unsave them */
2589     if (currFunc && dtype && 
2590         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2591         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2592
2593     /* if we hade saved some registers then
2594     unsave them */
2595     if (ic->regsSaved)
2596         unsaveRegisters (ic);
2597
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* resultRemat - result  is rematerializable                       */
2602 /*-----------------------------------------------------------------*/
2603 static int resultRemat (iCode *ic)
2604 {
2605     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2606     if (SKIP_IC(ic) || ic->op == IFX)
2607         return 0;
2608
2609     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2610         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2611         if (sym->remat && !POINTER_SET(ic)) 
2612             return 1;
2613     }
2614
2615     return 0;
2616 }
2617
2618 #if defined(__BORLANDC__) || defined(_MSC_VER)
2619 #define STRCASECMP stricmp
2620 #else
2621 #define STRCASECMP strcasecmp
2622 #endif
2623
2624 #if 0
2625 /*-----------------------------------------------------------------*/
2626 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2627 /*-----------------------------------------------------------------*/
2628 static bool inExcludeList(char *s)
2629 {
2630   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2631     int i =0;
2632     
2633     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2634     if (options.excludeRegs[i] &&
2635     STRCASECMP(options.excludeRegs[i],"none") == 0)
2636         return FALSE ;
2637
2638     for ( i = 0 ; options.excludeRegs[i]; i++) {
2639         if (options.excludeRegs[i] &&
2640         STRCASECMP(s,options.excludeRegs[i]) == 0)
2641             return TRUE;
2642     }
2643     return FALSE ;
2644 }
2645 #endif
2646
2647 /*-----------------------------------------------------------------*/
2648 /* genFunction - generated code for function entry                 */
2649 /*-----------------------------------------------------------------*/
2650 static void genFunction (iCode *ic)
2651 {
2652     symbol *sym;
2653     sym_link *ftype;
2654
2655     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2656
2657     labelOffset += (max_key+4);
2658     max_key=0;
2659     GpsuedoStkPtr=0;
2660     _G.nRegsSaved = 0;
2661     /* create the function header */
2662     pic14_emitcode(";","-----------------------------------------");
2663     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2664     pic14_emitcode(";","-----------------------------------------");
2665
2666     pic14_emitcode("","%s:",sym->rname);
2667     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2668
2669     ftype = operandType(IC_LEFT(ic));
2670
2671     /* if critical function then turn interrupts off */
2672     if (IFFUNC_ISCRITICAL(ftype))
2673         pic14_emitcode("clr","ea");
2674
2675     /* here we need to generate the equates for the
2676        register bank if required */
2677 #if 0
2678     if (FUNC_REGBANK(ftype) != rbank) {
2679         int i ;
2680
2681         rbank = FUNC_REGBANK(ftype);
2682         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2683             if (strcmp(regspic14[i].base,"0") == 0)
2684                 pic14_emitcode("","%s = 0x%02x",
2685                          regspic14[i].dname,
2686                          8*rbank+regspic14[i].offset);
2687             else
2688                 pic14_emitcode ("","%s = %s + 0x%02x",
2689                           regspic14[i].dname,
2690                           regspic14[i].base,
2691                           8*rbank+regspic14[i].offset);
2692         }
2693     }
2694 #endif
2695
2696     /* if this is an interrupt service routine then
2697     save acc, b, dpl, dph  */
2698     if (IFFUNC_ISISR(sym->type)) {
2699       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2700       emitpcodeNULLop(POC_NOP);
2701       emitpcodeNULLop(POC_NOP);
2702       emitpcodeNULLop(POC_NOP);
2703       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2704       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2705       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2706       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2707
2708       pBlockConvert2ISR(pb);
2709 #if 0  
2710         if (!inExcludeList("acc"))          
2711             pic14_emitcode ("push","acc");      
2712         if (!inExcludeList("b"))
2713             pic14_emitcode ("push","b");
2714         if (!inExcludeList("dpl"))
2715             pic14_emitcode ("push","dpl");
2716         if (!inExcludeList("dph"))
2717             pic14_emitcode ("push","dph");
2718         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2719         {
2720             pic14_emitcode ("push", "dpx");
2721             /* Make sure we're using standard DPTR */
2722             pic14_emitcode ("push", "dps");
2723             pic14_emitcode ("mov", "dps, #0x00");
2724             if (options.stack10bit)
2725             {   
2726                 /* This ISR could conceivably use DPTR2. Better save it. */
2727                 pic14_emitcode ("push", "dpl1");
2728                 pic14_emitcode ("push", "dph1");
2729                 pic14_emitcode ("push", "dpx1");
2730             }
2731         }
2732         /* if this isr has no bank i.e. is going to
2733            run with bank 0 , then we need to save more
2734            registers :-) */
2735         if (!FUNC_REGBANK(sym->type)) {
2736
2737             /* if this function does not call any other
2738                function then we can be economical and
2739                save only those registers that are used */
2740             if (! IFFUNC_HASFCALL(sym->type)) {
2741                 int i;
2742
2743                 /* if any registers used */
2744                 if (sym->regsUsed) {
2745                     /* save the registers used */
2746                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2747                         if (bitVectBitValue(sym->regsUsed,i) ||
2748                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2749                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2750                     }
2751                 }
2752                 
2753             } else {
2754                 /* this function has  a function call cannot
2755                    determines register usage so we will have the
2756                    entire bank */
2757                 saverbank(0,ic,FALSE);
2758             }       
2759         }
2760 #endif
2761     } else {
2762         /* if callee-save to be used for this function
2763            then save the registers being used in this function */
2764         if (IFFUNC_CALLEESAVES(sym->type)) {
2765             int i;
2766             
2767             /* if any registers used */
2768             if (sym->regsUsed) {
2769                 /* save the registers used */
2770                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2771                     if (bitVectBitValue(sym->regsUsed,i) ||
2772                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2773                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2774                         _G.nRegsSaved++;
2775                     }
2776                 }
2777             }
2778         }
2779     }
2780
2781     /* set the register bank to the desired value */
2782     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2783         pic14_emitcode("push","psw");
2784         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2785     }
2786
2787     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2788
2789         if (options.useXstack) {
2790             pic14_emitcode("mov","r0,%s",spname);
2791             pic14_emitcode("mov","a,_bp");
2792             pic14_emitcode("movx","@r0,a");
2793             pic14_emitcode("inc","%s",spname);
2794         }
2795         else
2796         {
2797             /* set up the stack */
2798             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2799         }
2800         pic14_emitcode ("mov","_bp,%s",spname);
2801     }
2802
2803     /* adjust the stack for the function */
2804     if (sym->stack) {
2805
2806         int i = sym->stack;
2807         if (i > 256 ) 
2808             werror(W_STACK_OVERFLOW,sym->name);
2809
2810         if (i > 3 && sym->recvSize < 4) {              
2811
2812             pic14_emitcode ("mov","a,sp");
2813             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2814             pic14_emitcode ("mov","sp,a");
2815            
2816         }
2817         else
2818             while(i--)
2819                 pic14_emitcode("inc","sp");
2820     }
2821
2822      if (sym->xstack) {
2823
2824         pic14_emitcode ("mov","a,_spx");
2825         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2826         pic14_emitcode ("mov","_spx,a");
2827     }    
2828
2829 }
2830
2831 /*-----------------------------------------------------------------*/
2832 /* genEndFunction - generates epilogue for functions               */
2833 /*-----------------------------------------------------------------*/
2834 static void genEndFunction (iCode *ic)
2835 {
2836     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2837
2838     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2839
2840     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2841     {
2842         pic14_emitcode ("mov","%s,_bp",spname);
2843     }
2844
2845     /* if use external stack but some variables were
2846     added to the local stack then decrement the
2847     local stack */
2848     if (options.useXstack && sym->stack) {      
2849         pic14_emitcode("mov","a,sp");
2850         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2851         pic14_emitcode("mov","sp,a");
2852     }
2853
2854
2855     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2856         if (options.useXstack) {
2857             pic14_emitcode("mov","r0,%s",spname);
2858             pic14_emitcode("movx","a,@r0");
2859             pic14_emitcode("mov","_bp,a");
2860             pic14_emitcode("dec","%s",spname);
2861         }
2862         else
2863         {
2864             pic14_emitcode ("pop","_bp");
2865         }
2866     }
2867
2868     /* restore the register bank  */    
2869     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2870         pic14_emitcode ("pop","psw");
2871
2872     if (IFFUNC_ISISR(sym->type)) {
2873
2874         /* now we need to restore the registers */
2875         /* if this isr has no bank i.e. is going to
2876            run with bank 0 , then we need to save more
2877            registers :-) */
2878         if (!FUNC_REGBANK(sym->type)) {
2879             
2880             /* if this function does not call any other
2881                function then we can be economical and
2882                save only those registers that are used */
2883             if (! IFFUNC_HASFCALL(sym->type)) {
2884                 int i;
2885                 
2886                 /* if any registers used */
2887                 if (sym->regsUsed) {
2888                     /* save the registers used */
2889                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2890                         if (bitVectBitValue(sym->regsUsed,i) ||
2891                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2892                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2893                     }
2894                 }
2895                 
2896             } else {
2897                 /* this function has  a function call cannot
2898                    determines register usage so we will have the
2899                    entire bank */
2900                 unsaverbank(0,ic,FALSE);
2901             }       
2902         }
2903 #if 0
2904         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2905         {
2906             if (options.stack10bit)
2907             {
2908                 pic14_emitcode ("pop", "dpx1");
2909                 pic14_emitcode ("pop", "dph1");
2910                 pic14_emitcode ("pop", "dpl1");
2911             }   
2912             pic14_emitcode ("pop", "dps");
2913             pic14_emitcode ("pop", "dpx");
2914         }
2915         if (!inExcludeList("dph"))
2916             pic14_emitcode ("pop","dph");
2917         if (!inExcludeList("dpl"))
2918             pic14_emitcode ("pop","dpl");
2919         if (!inExcludeList("b"))
2920             pic14_emitcode ("pop","b");
2921         if (!inExcludeList("acc"))
2922             pic14_emitcode ("pop","acc");
2923
2924         if (IFFUNC_ISCRITICAL(sym->type))
2925             pic14_emitcode("setb","ea");
2926 #endif
2927
2928         /* if debug then send end of function */
2929 /*      if (options.debug && currFunc) { */
2930         if (currFunc) {
2931             _G.debugLine = 1;
2932             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2933                      FileBaseName(ic->filename),currFunc->lastLine,
2934                      ic->level,ic->block); 
2935             if (IS_STATIC(currFunc->etype))         
2936                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2937             else
2938                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2939             _G.debugLine = 0;
2940         }
2941         
2942         pic14_emitcode ("reti","");
2943
2944         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2945         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2946         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2947         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2948         emitpcode(POC_MOVFW,  popCopyReg(&pc_wsave));
2949         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2950
2951         emitpcodeNULLop(POC_RETFIE);
2952
2953     }
2954     else {
2955         if (IFFUNC_ISCRITICAL(sym->type))
2956             pic14_emitcode("setb","ea");
2957         
2958         if (IFFUNC_CALLEESAVES(sym->type)) {
2959             int i;
2960             
2961             /* if any registers used */
2962             if (sym->regsUsed) {
2963                 /* save the registers used */
2964                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2965                     if (bitVectBitValue(sym->regsUsed,i) ||
2966                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2967                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2968                 }
2969             }
2970             
2971         }
2972
2973         /* if debug then send end of function */
2974         if (currFunc) {
2975             _G.debugLine = 1;
2976             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2977                      FileBaseName(ic->filename),currFunc->lastLine,
2978                      ic->level,ic->block); 
2979             if (IS_STATIC(currFunc->etype))         
2980                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2981             else
2982                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2983             _G.debugLine = 0;
2984         }
2985
2986         pic14_emitcode ("return","");
2987         emitpcodeNULLop(POC_RETURN);
2988
2989         /* Mark the end of a function */
2990         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2991     }
2992
2993 }
2994
2995 /*-----------------------------------------------------------------*/
2996 /* genRet - generate code for return statement                     */
2997 /*-----------------------------------------------------------------*/
2998 static void genRet (iCode *ic)
2999 {
3000   int size,offset = 0 , pushed = 0;
3001     
3002   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3003   /* if we have no return value then
3004      just generate the "ret" */
3005   if (!IC_LEFT(ic)) 
3006     goto jumpret;       
3007     
3008   /* we have something to return then
3009      move the return value into place */
3010   aopOp(IC_LEFT(ic),ic,FALSE);
3011   size = AOP_SIZE(IC_LEFT(ic));
3012     
3013   while (size--) {
3014     char *l ;
3015     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3016       /* #NOCHANGE */
3017       l = aopGet(AOP(IC_LEFT(ic)),offset++,
3018                  FALSE,TRUE);
3019       pic14_emitcode("push","%s",l);
3020       pushed++;
3021     } else {
3022       l = aopGet(AOP(IC_LEFT(ic)),offset,
3023                  FALSE,FALSE);
3024       if (strcmp(fReturn[offset],l)) {
3025         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3026             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3027           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
3028         }else {
3029           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3030         }
3031         if(size) {
3032           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
3033         }
3034         offset++;
3035       }
3036     }
3037   }    
3038
3039   if (pushed) {
3040     while(pushed) {
3041       pushed--;
3042       if (strcmp(fReturn[pushed],"a"))
3043         pic14_emitcode("pop",fReturn[pushed]);
3044       else
3045         pic14_emitcode("pop","acc");
3046     }
3047   }
3048   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3049     
3050  jumpret:
3051   /* generate a jump to the return label
3052      if the next is not the return statement */
3053   if (!(ic->next && ic->next->op == LABEL &&
3054         IC_LABEL(ic->next) == returnLabel)) {
3055         
3056     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3057     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3058   }
3059     
3060 }
3061
3062 /*-----------------------------------------------------------------*/
3063 /* genLabel - generates a label                                    */
3064 /*-----------------------------------------------------------------*/
3065 static void genLabel (iCode *ic)
3066 {
3067     /* special case never generate */
3068     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3069     if (IC_LABEL(ic) == entryLabel)
3070         return ;
3071
3072     emitpLabel(IC_LABEL(ic)->key);
3073     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3074 }
3075
3076 /*-----------------------------------------------------------------*/
3077 /* genGoto - generates a goto                                      */
3078 /*-----------------------------------------------------------------*/
3079 //tsd
3080 static void genGoto (iCode *ic)
3081 {
3082   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3083   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3084 }
3085
3086
3087 /*-----------------------------------------------------------------*/
3088 /* genMultbits :- multiplication of bits                           */
3089 /*-----------------------------------------------------------------*/
3090 static void genMultbits (operand *left, 
3091                          operand *right, 
3092                          operand *result)
3093 {
3094   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3095
3096   if(!pic14_sameRegs(AOP(result),AOP(right)))
3097     emitpcode(POC_BSF,  popGet(AOP(result),0));
3098
3099   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3100   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3101   emitpcode(POC_BCF,  popGet(AOP(result),0));
3102
3103 }
3104
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genMultOneByte : 8 bit multiplication & division                */
3108 /*-----------------------------------------------------------------*/
3109 static void genMultOneByte (operand *left,
3110                             operand *right,
3111                             operand *result)
3112 {
3113   sym_link *opetype = operandType(result);
3114
3115   // symbol *lbl ;
3116   int size,offset;
3117
3118   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3119   DEBUGpic14_AopType(__LINE__,left,right,result);
3120   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3121
3122   /* (if two literals, the value is computed before) */
3123   /* if one literal, literal on the right */
3124   if (AOP_TYPE(left) == AOP_LIT){
3125     operand *t = right;
3126     right = left;
3127     left = t;
3128   }
3129
3130   size = AOP_SIZE(result);
3131   if(size == 1) {
3132
3133     if (AOP_TYPE(right) == AOP_LIT){
3134       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3135                      aopGet(AOP(right),0,FALSE,FALSE), 
3136                      aopGet(AOP(left),0,FALSE,FALSE), 
3137                      aopGet(AOP(result),0,FALSE,FALSE));
3138       pic14_emitcode("call","genMultLit");
3139     } else {
3140       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3141                      aopGet(AOP(right),0,FALSE,FALSE), 
3142                      aopGet(AOP(left),0,FALSE,FALSE), 
3143                      aopGet(AOP(result),0,FALSE,FALSE));
3144       pic14_emitcode("call","genMult8X8_8");
3145
3146     }
3147     genMult8X8_8 (left, right,result);
3148
3149
3150     /* signed or unsigned */
3151     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3152     //l = aopGet(AOP(left),0,FALSE,FALSE);
3153     //MOVA(l);       
3154     //pic14_emitcode("mul","ab");
3155     /* if result size = 1, mul signed = mul unsigned */
3156     //aopPut(AOP(result),"a",0);
3157
3158   } else {  // (size > 1)
3159
3160     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3161                    aopGet(AOP(right),0,FALSE,FALSE), 
3162                    aopGet(AOP(left),0,FALSE,FALSE), 
3163                    aopGet(AOP(result),0,FALSE,FALSE));
3164
3165     if (SPEC_USIGN(opetype)){
3166       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3167       genUMult8X8_16 (left, right, result, NULL);
3168
3169       if (size > 2) {
3170         /* for filling the MSBs */
3171         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3172         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3173       }
3174     }
3175     else{
3176       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3177
3178       pic14_emitcode("mov","a,b");
3179
3180       /* adjust the MSB if left or right neg */
3181
3182       /* if one literal */
3183       if (AOP_TYPE(right) == AOP_LIT){
3184         pic14_emitcode("multiply ","right is a lit");
3185         /* AND literal negative */
3186         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3187           /* adjust MSB (c==0 after mul) */
3188           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3189         }
3190       }
3191       else{
3192         genSMult8X8_16 (left, right, result, NULL);
3193       }
3194
3195       if(size > 2){
3196         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3197         /* get the sign */
3198         pic14_emitcode("rlc","a");
3199         pic14_emitcode("subb","a,acc");
3200       }
3201     }
3202
3203     size -= 2;   
3204     offset = 2;
3205     if (size > 0)
3206       while (size--)
3207         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3208     //aopPut(AOP(result),"a",offset++);
3209   }
3210 }
3211
3212 /*-----------------------------------------------------------------*/
3213 /* genMult - generates code for multiplication                     */
3214 /*-----------------------------------------------------------------*/
3215 static void genMult (iCode *ic)
3216 {
3217     operand *left = IC_LEFT(ic);
3218     operand *right = IC_RIGHT(ic);
3219     operand *result= IC_RESULT(ic);   
3220
3221     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3222     /* assign the amsops */
3223     aopOp (left,ic,FALSE);
3224     aopOp (right,ic,FALSE);
3225     aopOp (result,ic,TRUE);
3226
3227   DEBUGpic14_AopType(__LINE__,left,right,result);
3228
3229     /* special cases first */
3230     /* both are bits */
3231     if (AOP_TYPE(left) == AOP_CRY &&
3232         AOP_TYPE(right)== AOP_CRY) {
3233         genMultbits(left,right,result);
3234         goto release ;
3235     }
3236
3237     /* if both are of size == 1 */
3238     if (AOP_SIZE(left) == 1 &&
3239         AOP_SIZE(right) == 1 ) {
3240         genMultOneByte(left,right,result);
3241         goto release ;
3242     }
3243
3244     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3245
3246     /* should have been converted to function call */
3247     //assert(0) ;
3248
3249 release :
3250     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3251     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3252     freeAsmop(result,NULL,ic,TRUE); 
3253 }
3254
3255 /*-----------------------------------------------------------------*/
3256 /* genDivbits :- division of bits                                  */
3257 /*-----------------------------------------------------------------*/
3258 static void genDivbits (operand *left, 
3259                         operand *right, 
3260                         operand *result)
3261 {
3262
3263     char *l;
3264
3265     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3266     /* the result must be bit */    
3267     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3268     l = aopGet(AOP(left),0,FALSE,FALSE);
3269
3270     MOVA(l);    
3271
3272     pic14_emitcode("div","ab");
3273     pic14_emitcode("rrc","a");
3274     aopPut(AOP(result),"c",0);
3275 }
3276
3277 /*-----------------------------------------------------------------*/
3278 /* genDivOneByte : 8 bit division                                  */
3279 /*-----------------------------------------------------------------*/
3280 static void genDivOneByte (operand *left,
3281                            operand *right,
3282                            operand *result)
3283 {
3284     sym_link *opetype = operandType(result);
3285     char *l ;
3286     symbol *lbl ;
3287     int size,offset;
3288
3289     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3290     size = AOP_SIZE(result) - 1;
3291     offset = 1;
3292     /* signed or unsigned */
3293     if (SPEC_USIGN(opetype)) {
3294         /* unsigned is easy */
3295         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3296         l = aopGet(AOP(left),0,FALSE,FALSE);
3297         MOVA(l);        
3298         pic14_emitcode("div","ab");
3299         aopPut(AOP(result),"a",0);
3300         while (size--)
3301             aopPut(AOP(result),zero,offset++);
3302         return ;
3303     }
3304
3305     /* signed is a little bit more difficult */
3306
3307     /* save the signs of the operands */
3308     l = aopGet(AOP(left),0,FALSE,FALSE);    
3309     MOVA(l);    
3310     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3311     pic14_emitcode("push","acc"); /* save it on the stack */
3312
3313     /* now sign adjust for both left & right */
3314     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3315     MOVA(l);       
3316     lbl = newiTempLabel(NULL);
3317     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3318     pic14_emitcode("cpl","a");   
3319     pic14_emitcode("inc","a");
3320     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3321     pic14_emitcode("mov","b,a");
3322
3323     /* sign adjust left side */
3324     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3325     MOVA(l);
3326
3327     lbl = newiTempLabel(NULL);
3328     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3329     pic14_emitcode("cpl","a");
3330     pic14_emitcode("inc","a");
3331     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3332
3333     /* now the division */
3334     pic14_emitcode("div","ab");
3335     /* we are interested in the lower order
3336     only */
3337     pic14_emitcode("mov","b,a");
3338     lbl = newiTempLabel(NULL);
3339     pic14_emitcode("pop","acc");   
3340     /* if there was an over flow we don't 
3341     adjust the sign of the result */
3342     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3343     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3344     CLRC;
3345     pic14_emitcode("clr","a");
3346     pic14_emitcode("subb","a,b");
3347     pic14_emitcode("mov","b,a");
3348     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3349
3350     /* now we are done */
3351     aopPut(AOP(result),"b",0);
3352     if(size > 0){
3353         pic14_emitcode("mov","c,b.7");
3354         pic14_emitcode("subb","a,acc");   
3355     }
3356     while (size--)
3357         aopPut(AOP(result),"a",offset++);
3358
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genDiv - generates code for division                            */
3363 /*-----------------------------------------------------------------*/
3364 static void genDiv (iCode *ic)
3365 {
3366     operand *left = IC_LEFT(ic);
3367     operand *right = IC_RIGHT(ic);
3368     operand *result= IC_RESULT(ic);   
3369
3370     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3371     /* assign the amsops */
3372     aopOp (left,ic,FALSE);
3373     aopOp (right,ic,FALSE);
3374     aopOp (result,ic,TRUE);
3375
3376     /* special cases first */
3377     /* both are bits */
3378     if (AOP_TYPE(left) == AOP_CRY &&
3379         AOP_TYPE(right)== AOP_CRY) {
3380         genDivbits(left,right,result);
3381         goto release ;
3382     }
3383
3384     /* if both are of size == 1 */
3385     if (AOP_SIZE(left) == 1 &&
3386         AOP_SIZE(right) == 1 ) {
3387         genDivOneByte(left,right,result);
3388         goto release ;
3389     }
3390
3391     /* should have been converted to function call */
3392     assert(0);
3393 release :
3394     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3395     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3396     freeAsmop(result,NULL,ic,TRUE); 
3397 }
3398
3399 /*-----------------------------------------------------------------*/
3400 /* genModbits :- modulus of bits                                   */
3401 /*-----------------------------------------------------------------*/
3402 static void genModbits (operand *left, 
3403                         operand *right, 
3404                         operand *result)
3405 {
3406
3407     char *l;
3408
3409     /* the result must be bit */    
3410     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3411     l = aopGet(AOP(left),0,FALSE,FALSE);
3412
3413     MOVA(l);       
3414
3415     pic14_emitcode("div","ab");
3416     pic14_emitcode("mov","a,b");
3417     pic14_emitcode("rrc","a");
3418     aopPut(AOP(result),"c",0);
3419 }
3420
3421 /*-----------------------------------------------------------------*/
3422 /* genModOneByte : 8 bit modulus                                   */
3423 /*-----------------------------------------------------------------*/
3424 static void genModOneByte (operand *left,
3425                            operand *right,
3426                            operand *result)
3427 {
3428     sym_link *opetype = operandType(result);
3429     char *l ;
3430     symbol *lbl ;
3431
3432     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3433     /* signed or unsigned */
3434     if (SPEC_USIGN(opetype)) {
3435         /* unsigned is easy */
3436         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3437         l = aopGet(AOP(left),0,FALSE,FALSE);
3438         MOVA(l);    
3439         pic14_emitcode("div","ab");
3440         aopPut(AOP(result),"b",0);
3441         return ;
3442     }
3443
3444     /* signed is a little bit more difficult */
3445
3446     /* save the signs of the operands */
3447     l = aopGet(AOP(left),0,FALSE,FALSE);    
3448     MOVA(l);
3449
3450     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3451     pic14_emitcode("push","acc"); /* save it on the stack */
3452
3453     /* now sign adjust for both left & right */
3454     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3455     MOVA(l);
3456
3457     lbl = newiTempLabel(NULL);
3458     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3459     pic14_emitcode("cpl","a");   
3460     pic14_emitcode("inc","a");
3461     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3462     pic14_emitcode("mov","b,a"); 
3463
3464     /* sign adjust left side */
3465     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3466     MOVA(l);
3467
3468     lbl = newiTempLabel(NULL);
3469     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3470     pic14_emitcode("cpl","a");   
3471     pic14_emitcode("inc","a");
3472     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3473
3474     /* now the multiplication */
3475     pic14_emitcode("div","ab");
3476     /* we are interested in the lower order
3477     only */
3478     lbl = newiTempLabel(NULL);
3479     pic14_emitcode("pop","acc");   
3480     /* if there was an over flow we don't 
3481     adjust the sign of the result */
3482     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3483     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3484     CLRC ;
3485     pic14_emitcode("clr","a");
3486     pic14_emitcode("subb","a,b");
3487     pic14_emitcode("mov","b,a");
3488     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3489
3490     /* now we are done */
3491     aopPut(AOP(result),"b",0);
3492
3493 }
3494
3495 /*-----------------------------------------------------------------*/
3496 /* genMod - generates code for division                            */
3497 /*-----------------------------------------------------------------*/
3498 static void genMod (iCode *ic)
3499 {
3500     operand *left = IC_LEFT(ic);
3501     operand *right = IC_RIGHT(ic);
3502     operand *result= IC_RESULT(ic);  
3503
3504     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3505     /* assign the amsops */
3506     aopOp (left,ic,FALSE);
3507     aopOp (right,ic,FALSE);
3508     aopOp (result,ic,TRUE);
3509
3510     /* special cases first */
3511     /* both are bits */
3512     if (AOP_TYPE(left) == AOP_CRY &&
3513         AOP_TYPE(right)== AOP_CRY) {
3514         genModbits(left,right,result);
3515         goto release ;
3516     }
3517
3518     /* if both are of size == 1 */
3519     if (AOP_SIZE(left) == 1 &&
3520         AOP_SIZE(right) == 1 ) {
3521         genModOneByte(left,right,result);
3522         goto release ;
3523     }
3524
3525     /* should have been converted to function call */
3526     assert(0);
3527
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 /* genIfxJump :- will create a jump depending on the ifx           */
3536 /*-----------------------------------------------------------------*/
3537 /*
3538   note: May need to add parameter to indicate when a variable is in bit space.
3539 */
3540 static void genIfxJump (iCode *ic, char *jval)
3541 {
3542
3543     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3544     /* if true label then we jump if condition
3545     supplied is true */
3546     if ( IC_TRUE(ic) ) {
3547
3548         if(strcmp(jval,"a") == 0)
3549           emitSKPZ;
3550         else if (strcmp(jval,"c") == 0)
3551           emitSKPC;
3552         else {
3553           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3554           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3555         }
3556
3557         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3558         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3559
3560     }
3561     else {
3562         /* false label is present */
3563         if(strcmp(jval,"a") == 0)
3564           emitSKPNZ;
3565         else if (strcmp(jval,"c") == 0)
3566           emitSKPNC;
3567         else {
3568           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3569           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3570         }
3571
3572         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3573         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3574
3575     }
3576
3577
3578     /* mark the icode as generated */
3579     ic->generated = 1;
3580 }
3581
3582 /*-----------------------------------------------------------------*/
3583 /* genSkip                                                         */
3584 /*-----------------------------------------------------------------*/
3585 static void genSkip(iCode *ifx,int status_bit)
3586 {
3587   if(!ifx)
3588     return;
3589
3590   if ( IC_TRUE(ifx) ) {
3591     switch(status_bit) {
3592     case 'z':
3593       emitSKPNZ;
3594       break;
3595
3596     case 'c':
3597       emitSKPNC;
3598       break;
3599
3600     case 'd':
3601       emitSKPDC;
3602       break;
3603
3604     }
3605
3606     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3607     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3608
3609   } else {
3610
3611     switch(status_bit) {
3612
3613     case 'z':
3614       emitSKPZ;
3615       break;
3616
3617     case 'c':
3618       emitSKPC;
3619       break;
3620
3621     case 'd':
3622       emitSKPDC;
3623       break;
3624     }
3625     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3626     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3627
3628   }
3629
3630 }
3631
3632 /*-----------------------------------------------------------------*/
3633 /* genSkipc                                                        */
3634 /*-----------------------------------------------------------------*/
3635 static void genSkipc(resolvedIfx *rifx)
3636 {
3637   if(!rifx)
3638     return;
3639
3640   if(rifx->condition)
3641     emitSKPC;
3642   else
3643     emitSKPNC;
3644
3645   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3646   rifx->generated = 1;
3647 }
3648
3649 /*-----------------------------------------------------------------*/
3650 /* genSkipz2                                                       */
3651 /*-----------------------------------------------------------------*/
3652 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3653 {
3654   if(!rifx)
3655     return;
3656
3657   if( (rifx->condition ^ invert_condition) & 1)
3658     emitSKPZ;
3659   else
3660     emitSKPNZ;
3661
3662   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3663   rifx->generated = 1;
3664 }
3665
3666 /*-----------------------------------------------------------------*/
3667 /* genSkipz                                                        */
3668 /*-----------------------------------------------------------------*/
3669 static void genSkipz(iCode *ifx, int condition)
3670 {
3671   if(!ifx)
3672     return;
3673
3674   if(condition)
3675     emitSKPNZ;
3676   else
3677     emitSKPZ;
3678
3679   if ( IC_TRUE(ifx) )
3680     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3681   else
3682     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3683
3684   if ( IC_TRUE(ifx) )
3685     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3686   else
3687     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3688
3689 }
3690 /*-----------------------------------------------------------------*/
3691 /* genSkipCond                                                     */
3692 /*-----------------------------------------------------------------*/
3693 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3694 {
3695   if(!rifx)
3696     return;
3697
3698   if(rifx->condition)
3699     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3700   else
3701     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3702
3703
3704   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3705   rifx->generated = 1;
3706 }
3707
3708 #if 0
3709 /*-----------------------------------------------------------------*/
3710 /* genChkZeroes :- greater or less than comparison                 */
3711 /*     For each byte in a literal that is zero, inclusive or the   */
3712 /*     the corresponding byte in the operand with W                */
3713 /*     returns true if any of the bytes are zero                   */
3714 /*-----------------------------------------------------------------*/
3715 static int genChkZeroes(operand *op, int lit,  int size)
3716 {
3717
3718   int i;
3719   int flag =1;
3720
3721   while(size--) {
3722     i = (lit >> (size*8)) & 0xff;
3723
3724     if(i==0) {
3725       if(flag) 
3726         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3727       else
3728         emitpcode(POC_IORFW, popGet(AOP(op),size));
3729       flag = 0;
3730     }
3731   }
3732
3733   return (flag==0);
3734 }
3735 #endif
3736
3737 /*-----------------------------------------------------------------*/
3738 /* genCmp :- greater or less than comparison                       */
3739 /*-----------------------------------------------------------------*/
3740 static void genCmp (operand *left,operand *right,
3741                     operand *result, iCode *ifx, int sign)
3742 {
3743   int size; //, offset = 0 ;
3744   unsigned long lit = 0L,i = 0;
3745   resolvedIfx rFalseIfx;
3746   //  resolvedIfx rTrueIfx;
3747   symbol *truelbl;
3748   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3749   if(ifx) {
3750     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3751     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3752   }
3753
3754
3755   resolveIfx(&rFalseIfx,ifx);
3756   truelbl  = newiTempLabel(NULL);
3757   size = max(AOP_SIZE(left),AOP_SIZE(right));
3758
3759 #define _swapp
3760
3761   /* if literal is on the right then swap with left */
3762   if ((AOP_TYPE(right) == AOP_LIT)) {
3763     operand *tmp = right ;
3764     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3765     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3766 #ifdef _swapp
3767     DEBUGpic14_emitcode ("; ***","%d swapping left&right, lit =0x%x",__LINE__,lit);
3768     lit = (lit - 1) & mask;
3769     DEBUGpic14_emitcode ("; ***","%d swapping left&right, lit =0x%x, mask 0x%x",__LINE__,lit,mask);
3770
3771     right = left;
3772     left = tmp;
3773     rFalseIfx.condition ^= 1;
3774 #endif
3775
3776   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3777     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3778   }
3779
3780
3781   //if(IC_TRUE(ifx) == NULL)
3782   /* if left & right are bit variables */
3783   if (AOP_TYPE(left) == AOP_CRY &&
3784       AOP_TYPE(right) == AOP_CRY ) {
3785     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3786     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3787   } else {
3788     /* subtract right from left if at the
3789        end the carry flag is set then we know that
3790        left is greater than right */
3791
3792     //    {
3793
3794     symbol *lbl  = newiTempLabel(NULL);
3795
3796 #ifndef _swapp
3797     if(AOP_TYPE(right) == AOP_LIT) {
3798
3799       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3800
3801       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3802
3803       /* special cases */
3804
3805       if(lit == 0) {
3806
3807         if(sign != 0) 
3808           genSkipCond(&rFalseIfx,left,size-1,7);
3809         else 
3810           /* no need to compare to 0...*/
3811           /* NOTE: this is a de-generate compare that most certainly 
3812            *       creates some dead code. */
3813           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3814
3815         if(ifx) ifx->generated = 1;
3816         return;
3817
3818       }
3819       size--;
3820
3821       if(size == 0) {
3822         //i = (lit >> (size*8)) & 0xff;
3823         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3824         
3825         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3826
3827         i = ((0-lit) & 0xff);
3828         if(sign) {
3829           if( i == 0x81) { 
3830             /* lit is 0x7f, all signed chars are less than
3831              * this except for 0x7f itself */
3832             emitpcode(POC_XORLW, popGetLit(0x7f));
3833             genSkipz2(&rFalseIfx,0);
3834           } else {
3835             emitpcode(POC_ADDLW, popGetLit(0x80));
3836             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3837             genSkipc(&rFalseIfx);
3838           }
3839
3840         } else {
3841           if(lit == 1) {
3842             genSkipz2(&rFalseIfx,1);
3843           } else {
3844             emitpcode(POC_ADDLW, popGetLit(i));
3845             genSkipc(&rFalseIfx);
3846           }
3847         }
3848
3849         if(ifx) ifx->generated = 1;
3850         return;
3851       }
3852
3853       /* chars are out of the way. now do ints and longs */
3854
3855
3856       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3857         
3858       /* special cases */
3859
3860       if(sign) {
3861
3862         if(lit == 0) {
3863           genSkipCond(&rFalseIfx,left,size,7);
3864           if(ifx) ifx->generated = 1;
3865           return;
3866         }
3867
3868         if(lit <0x100) {
3869           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3870
3871           //rFalseIfx.condition ^= 1;
3872           //genSkipCond(&rFalseIfx,left,size,7);
3873           //rFalseIfx.condition ^= 1;
3874
3875           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3876           if(rFalseIfx.condition)
3877             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3878           else
3879             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3880
3881           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3882           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3883           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3884
3885           while(size > 1)
3886             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3887
3888           if(rFalseIfx.condition) {
3889             emitSKPZ;
3890             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3891
3892           } else {
3893             emitSKPNZ;
3894           }
3895
3896           genSkipc(&rFalseIfx);
3897           emitpLabel(truelbl->key);
3898           if(ifx) ifx->generated = 1;
3899           return;
3900
3901         }
3902
3903         if(size == 1) {
3904
3905           if( (lit & 0xff) == 0) {
3906             /* lower byte is zero */
3907             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3908             i = ((lit >> 8) & 0xff) ^0x80;
3909             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3910             emitpcode(POC_ADDLW, popGetLit( 0x80));
3911             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3912             genSkipc(&rFalseIfx);
3913
3914
3915             if(ifx) ifx->generated = 1;
3916             return;
3917
3918           }
3919         } else {
3920           /* Special cases for signed longs */
3921           if( (lit & 0xffffff) == 0) {
3922             /* lower byte is zero */
3923             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3924             i = ((lit >> 8*3) & 0xff) ^0x80;
3925             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3926             emitpcode(POC_ADDLW, popGetLit( 0x80));
3927             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3928             genSkipc(&rFalseIfx);
3929
3930
3931             if(ifx) ifx->generated = 1;
3932             return;
3933
3934           }
3935
3936         }
3937
3938
3939         if(lit & (0x80 << (size*8))) {
3940           /* lit is negative */
3941           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3942
3943           //genSkipCond(&rFalseIfx,left,size,7);
3944
3945           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3946
3947           if(rFalseIfx.condition)
3948             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3949           else
3950             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3951
3952
3953         } else {
3954           /* lit is positive */
3955           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3956           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3957           if(rFalseIfx.condition)
3958             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3959           else
3960             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3961
3962         }
3963
3964         /*
3965           This works, but is only good for ints.
3966           It also requires a "known zero" register.
3967           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3968           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3969           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3970           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3971           emitpcode(POC_ADDFW, popGet(AOP(left),1));
3972           genSkipc(&rFalseIfx);
3973
3974           emitpLabel(truelbl->key);
3975           if(ifx) ifx->generated = 1;
3976           return;
3977         **/
3978           
3979         /* There are no more special cases, so perform a general compare */
3980   
3981         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3982         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3983
3984         while(size--) {
3985
3986           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3987           emitSKPNZ;
3988           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3989         }
3990         //rFalseIfx.condition ^= 1;
3991         genSkipc(&rFalseIfx);
3992
3993         emitpLabel(truelbl->key);
3994
3995         if(ifx) ifx->generated = 1;
3996         return;
3997
3998
3999       }
4000
4001
4002       /* sign is out of the way. So now do an unsigned compare */
4003       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4004
4005
4006       /* General case - compare to an unsigned literal on the right.*/
4007
4008       i = (lit >> (size*8)) & 0xff;
4009       emitpcode(POC_MOVLW, popGetLit(i));
4010       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4011       while(size--) {
4012         i = (lit >> (size*8)) & 0xff;
4013
4014         if(i) {
4015           emitpcode(POC_MOVLW, popGetLit(i));
4016           emitSKPNZ;
4017           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4018         } else {
4019           /* this byte of the lit is zero, 
4020            *if it's not the last then OR in the variable */
4021           if(size)
4022             emitpcode(POC_IORFW, popGet(AOP(left),size));
4023         }
4024       }
4025
4026
4027       emitpLabel(lbl->key);
4028       //if(emitFinalCheck)
4029       genSkipc(&rFalseIfx);
4030       if(sign)
4031         emitpLabel(truelbl->key);
4032
4033       if(ifx) ifx->generated = 1;
4034       return;
4035
4036
4037     }
4038 #endif
4039     if(AOP_TYPE(left) == AOP_LIT) {
4040       //symbol *lbl = newiTempLabel(NULL);
4041
4042       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4043
4044
4045       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4046
4047       /* Special cases */
4048       if((lit == 0) && (sign == 0)){
4049
4050         size--;
4051         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4052         while(size) 
4053           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4054
4055         genSkipz2(&rFalseIfx,0);
4056         if(ifx) ifx->generated = 1;
4057         return;
4058       }
4059
4060       if(size==1) {
4061         /* Special cases */
4062         lit &= 0xff;
4063         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4064           /* degenerate compare can never be true */
4065           if(rFalseIfx.condition == 0)
4066             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4067
4068           if(ifx) ifx->generated = 1;
4069           return;
4070         }
4071
4072         if(sign) {
4073           /* signed comparisons to a literal byte */
4074
4075           int lp1 = (lit+1) & 0xff;
4076
4077           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4078           switch (lp1) {
4079           case 0:
4080             rFalseIfx.condition ^= 1;
4081             genSkipCond(&rFalseIfx,right,0,7);
4082             break;
4083           case 0x7f:
4084             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4085             emitpcode(POC_XORLW, popGetLit(0x7f));
4086             genSkipz2(&rFalseIfx,1);
4087             break;
4088           default:
4089             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4090             emitpcode(POC_ADDLW, popGetLit(0x80));
4091             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4092             rFalseIfx.condition ^= 1;
4093             genSkipc(&rFalseIfx);
4094             break;
4095           }
4096         } else {
4097           /* unsigned comparisons to a literal byte */
4098
4099           switch(lit & 0xff ) {
4100           case 0:
4101             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4102             genSkipz2(&rFalseIfx,0);
4103             break;
4104           case 0x7f:
4105             rFalseIfx.condition ^= 1;
4106             genSkipCond(&rFalseIfx,right,0,7);
4107             break;
4108
4109           default:
4110             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4111             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4112             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4113             rFalseIfx.condition ^= 1;
4114             genSkipc(&rFalseIfx);
4115             break;
4116           }
4117         }
4118
4119         if(ifx) ifx->generated = 1;
4120         return;
4121
4122       } else {
4123
4124         /* Size is greater than 1 */
4125
4126         if(sign) {
4127           int lp1 = lit+1;
4128
4129           size--;
4130
4131           if(lp1 == 0) {
4132             /* this means lit = 0xffffffff, or -1 */
4133
4134
4135             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4136             rFalseIfx.condition ^= 1;
4137             genSkipCond(&rFalseIfx,right,size,7);
4138             if(ifx) ifx->generated = 1;
4139             return;
4140           }
4141
4142           if(lit == 0) {
4143             int s = size;
4144
4145             if(rFalseIfx.condition) {
4146               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4147               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4148             }
4149
4150             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4151             while(size--)
4152               emitpcode(POC_IORFW, popGet(AOP(right),size));
4153
4154
4155             emitSKPZ;
4156             if(rFalseIfx.condition) {
4157               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4158               emitpLabel(truelbl->key);
4159             }else {
4160               rFalseIfx.condition ^= 1;
4161               genSkipCond(&rFalseIfx,right,s,7);
4162             }
4163
4164             if(ifx) ifx->generated = 1;
4165             return;
4166           }
4167
4168           if((size == 1) &&  (0 == (lp1&0xff))) {
4169             /* lower byte of signed word is zero */
4170             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4171             i = ((lp1 >> 8) & 0xff) ^0x80;
4172             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4173             emitpcode(POC_ADDLW, popGetLit( 0x80));
4174             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4175             rFalseIfx.condition ^= 1;
4176             genSkipc(&rFalseIfx);
4177
4178
4179             if(ifx) ifx->generated = 1;
4180             return;
4181           }
4182
4183           if(lit & (0x80 << (size*8))) {
4184             /* Lit is less than zero */
4185             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4186             //rFalseIfx.condition ^= 1;
4187             //genSkipCond(&rFalseIfx,left,size,7);
4188             //rFalseIfx.condition ^= 1;
4189             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4190             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4191
4192             if(rFalseIfx.condition)
4193               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4194             else
4195               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4196
4197
4198           } else {
4199             /* Lit is greater than or equal to zero */
4200             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4201             //rFalseIfx.condition ^= 1;
4202             //genSkipCond(&rFalseIfx,right,size,7);
4203             //rFalseIfx.condition ^= 1;
4204
4205             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4206             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4207
4208             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4209             if(rFalseIfx.condition)
4210               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4211             else
4212               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4213
4214           }
4215
4216
4217           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4218           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4219
4220           while(size--) {
4221
4222             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4223             emitSKPNZ;
4224             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4225           }
4226           rFalseIfx.condition ^= 1;
4227           //rFalseIfx.condition = 1;
4228           genSkipc(&rFalseIfx);
4229
4230           emitpLabel(truelbl->key);
4231
4232           if(ifx) ifx->generated = 1;
4233           return;
4234           // end of if (sign)
4235         } else {
4236
4237           /* compare word or long to an unsigned literal on the right.*/
4238
4239
4240           size--;
4241           if(lit < 0xff) {
4242             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4243             switch (lit) {
4244             case 0:
4245               break; /* handled above */
4246 /*
4247             case 0xff:
4248               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4249               while(size--)
4250                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4251               genSkipz2(&rFalseIfx,0);
4252               break;
4253 */
4254             default:
4255               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4256               while(--size)
4257                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4258
4259               emitSKPZ;
4260               if(rFalseIfx.condition)
4261                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4262               else
4263                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4264
4265
4266               emitpcode(POC_MOVLW, popGetLit(lit+1));
4267               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4268
4269               rFalseIfx.condition ^= 1;
4270               genSkipc(&rFalseIfx);
4271             }
4272
4273             emitpLabel(truelbl->key);
4274
4275             if(ifx) ifx->generated = 1;
4276             return;
4277           }
4278
4279
4280           lit++;
4281           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4282           i = (lit >> (size*8)) & 0xff;
4283
4284           emitpcode(POC_MOVLW, popGetLit(i));
4285           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4286
4287           while(size--) {
4288             i = (lit >> (size*8)) & 0xff;
4289
4290             if(i) {
4291               emitpcode(POC_MOVLW, popGetLit(i));
4292               emitSKPNZ;
4293               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4294             } else {
4295               /* this byte of the lit is zero, 
4296                *if it's not the last then OR in the variable */
4297               if(size)
4298                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4299             }
4300           }
4301
4302
4303           emitpLabel(lbl->key);
4304
4305           rFalseIfx.condition ^= 1;
4306           genSkipc(&rFalseIfx);
4307         }
4308
4309         if(sign)
4310           emitpLabel(truelbl->key);
4311         if(ifx) ifx->generated = 1;
4312         return;
4313       }
4314     }
4315     /* Compare two variables */
4316
4317     DEBUGpic14_emitcode(";sign","%d",sign);
4318
4319     size--;
4320     if(sign) {
4321       /* Sigh. thus sucks... */
4322       if(size) {
4323         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4324         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4325         emitpcode(POC_MOVLW, popGetLit(0x80));
4326         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4327         emitpcode(POC_XORFW, popGet(AOP(right),size));
4328         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4329       } else {
4330         /* Signed char comparison */
4331         /* Special thanks to Nikolai Golovchenko for this snippet */
4332         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4333         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4334         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4335         emitpcode(POC_XORFW, popGet(AOP(left),0));
4336         emitpcode(POC_XORFW, popGet(AOP(right),0));
4337         emitpcode(POC_ADDLW, popGetLit(0x80));
4338
4339         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4340         genSkipc(&rFalseIfx);
4341           
4342         if(ifx) ifx->generated = 1;
4343         return;
4344       }
4345
4346     } else {
4347
4348       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4349       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4350     }
4351
4352
4353     /* The rest of the bytes of a multi-byte compare */
4354     while (size) {
4355
4356       emitSKPZ;
4357       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4358       size--;
4359
4360       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4361       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4362
4363
4364     }
4365
4366     emitpLabel(lbl->key);
4367
4368     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4369     genSkipc(&rFalseIfx);
4370     if(ifx) ifx->generated = 1;
4371     return;
4372
4373   }
4374
4375   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4376     pic14_outBitC(result);
4377   } else {
4378     /* if the result is used in the next
4379        ifx conditional branch then generate
4380        code a little differently */
4381     if (ifx )
4382       genIfxJump (ifx,"c");
4383     else
4384       pic14_outBitC(result);
4385     /* leave the result in acc */
4386   }
4387
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genCmpGt :- greater than comparison                             */
4392 /*-----------------------------------------------------------------*/
4393 static void genCmpGt (iCode *ic, iCode *ifx)
4394 {
4395     operand *left, *right, *result;
4396     sym_link *letype , *retype;
4397     int sign ;
4398
4399     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4400     left = IC_LEFT(ic);
4401     right= IC_RIGHT(ic);
4402     result = IC_RESULT(ic);
4403
4404     letype = getSpec(operandType(left));
4405     retype =getSpec(operandType(right));
4406     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4407     /* assign the amsops */
4408     aopOp (left,ic,FALSE);
4409     aopOp (right,ic,FALSE);
4410     aopOp (result,ic,TRUE);
4411
4412     genCmp(right, left, result, ifx, sign);
4413
4414     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4415     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4416     freeAsmop(result,NULL,ic,TRUE); 
4417 }
4418
4419 /*-----------------------------------------------------------------*/
4420 /* genCmpLt - less than comparisons                                */
4421 /*-----------------------------------------------------------------*/
4422 static void genCmpLt (iCode *ic, iCode *ifx)
4423 {
4424     operand *left, *right, *result;
4425     sym_link *letype , *retype;
4426     int sign ;
4427
4428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4429     left = IC_LEFT(ic);
4430     right= IC_RIGHT(ic);
4431     result = IC_RESULT(ic);
4432
4433     letype = getSpec(operandType(left));
4434     retype =getSpec(operandType(right));
4435     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4436
4437     /* assign the amsops */
4438     aopOp (left,ic,FALSE);
4439     aopOp (right,ic,FALSE);
4440     aopOp (result,ic,TRUE);
4441
4442     genCmp(left, right, result, ifx, sign);
4443
4444     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4445     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4446     freeAsmop(result,NULL,ic,TRUE); 
4447 }
4448
4449 /*-----------------------------------------------------------------*/
4450 /* genc16bit2lit - compare a 16 bit value to a literal             */
4451 /*-----------------------------------------------------------------*/
4452 static void genc16bit2lit(operand *op, int lit, int offset)
4453 {
4454   int i;
4455
4456   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4457   if( (lit&0xff) == 0) 
4458     i=1;
4459   else
4460     i=0;
4461
4462   switch( BYTEofLONG(lit,i)) { 
4463   case 0:
4464     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4465     break;
4466   case 1:
4467     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4468     break;
4469   case 0xff:
4470     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4471     break;
4472   default:
4473     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4474     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4475   }
4476
4477   i ^= 1;
4478
4479   switch( BYTEofLONG(lit,i)) { 
4480   case 0:
4481     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4482     break;
4483   case 1:
4484     emitSKPNZ;
4485     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4486     break;
4487   case 0xff:
4488     emitSKPNZ;
4489     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4490     break;
4491   default:
4492     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4493     emitSKPNZ;
4494     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4495
4496   }
4497
4498 }
4499
4500 /*-----------------------------------------------------------------*/
4501 /* gencjneshort - compare and jump if not equal                    */
4502 /*-----------------------------------------------------------------*/
4503 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4504 {
4505   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4506   int offset = 0;
4507   resolvedIfx rIfx;
4508   symbol *lbl;
4509
4510   unsigned long lit = 0L;
4511   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4512   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4513
4514   resolveIfx(&rIfx,ifx);
4515   lbl =  newiTempLabel(NULL);
4516
4517
4518   /* if the left side is a literal or 
4519      if the right is in a pointer register and left 
4520      is not */
4521   if ((AOP_TYPE(left) == AOP_LIT) || 
4522       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4523     operand *t = right;
4524     right = left;
4525     left = t;
4526   }
4527   if(AOP_TYPE(right) == AOP_LIT)
4528     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4529
4530   /* if the right side is a literal then anything goes */
4531   if (AOP_TYPE(right) == AOP_LIT &&
4532       AOP_TYPE(left) != AOP_DIR ) {
4533     switch(size) {
4534     case 2:
4535       genc16bit2lit(left, lit, 0);
4536       emitSKPNZ;
4537       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4538       break;
4539     default:
4540       while (size--) {
4541         if(lit & 0xff) {
4542           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4543           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4544         } else {
4545           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4546         }
4547
4548         emitSKPNZ;
4549         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4550         offset++;
4551         lit >>= 8;
4552       }
4553       break;
4554     }
4555   }
4556
4557   /* if the right side is in a register or in direct space or
4558      if the left is a pointer register & right is not */    
4559   else if (AOP_TYPE(right) == AOP_REG ||
4560            AOP_TYPE(right) == AOP_DIR || 
4561            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4562            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4563     switch(size) {
4564     case 2:
4565       genc16bit2lit(left, lit, 0);
4566       emitSKPNZ;
4567       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4568       break;
4569     default:
4570       while (size--) {
4571         int emit_skip=1;
4572         if((AOP_TYPE(left) == AOP_DIR) && 
4573            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4574
4575           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4576           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4577
4578         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4579             
4580           switch (lit & 0xff) {
4581           case 0:
4582             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4583             break;
4584           case 1:
4585             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4586             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4587             emit_skip=0;
4588             break;
4589           case 0xff:
4590             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4591             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4592             emit_skip=0;
4593             break;
4594           default:
4595             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4596             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4597           }
4598           lit >>= 8;
4599
4600         } else {
4601           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4602         }
4603         if(emit_skip) {
4604           if(AOP_TYPE(result) == AOP_CRY) {
4605             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4606             if(rIfx.condition)
4607               emitSKPNZ;
4608             else
4609               emitSKPZ;
4610             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4611           } else {
4612             /* fix me. probably need to check result size too */
4613             emitpcode(POC_CLRF,popGet(AOP(result),0));
4614             if(rIfx.condition)
4615               emitSKPNZ;
4616             else
4617               emitSKPZ;
4618             emitpcode(POC_INCF,popGet(AOP(result),0));
4619           }
4620           if(ifx)
4621             ifx->generated=1;
4622         }
4623         emit_skip++;
4624         offset++;
4625       }
4626       break;
4627     }
4628   } else if(AOP_TYPE(right) == AOP_REG &&
4629             AOP_TYPE(left) != AOP_DIR){
4630
4631     while(size--) {
4632       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4633       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4634       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4635       if(rIfx.condition)
4636         emitSKPNZ;
4637       else
4638         emitSKPZ;
4639       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4640       offset++;
4641     }
4642       
4643   }else{
4644     /* right is a pointer reg need both a & b */
4645     while(size--) {
4646       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4647       if(strcmp(l,"b"))
4648         pic14_emitcode("mov","b,%s",l);
4649       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4650       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4651       offset++;
4652     }
4653   }
4654   emitpLabel(lbl->key);
4655
4656   if(ifx)
4657     ifx->generated = 1;
4658 }
4659
4660 #if 0
4661 /*-----------------------------------------------------------------*/
4662 /* gencjne - compare and jump if not equal                         */
4663 /*-----------------------------------------------------------------*/
4664 static void gencjne(operand *left, operand *right, iCode *ifx)
4665 {
4666     symbol *tlbl  = newiTempLabel(NULL);
4667
4668     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4669     gencjneshort(left, right, lbl);
4670
4671     pic14_emitcode("mov","a,%s",one);
4672     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4673     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4674     pic14_emitcode("clr","a");
4675     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4676
4677     emitpLabel(lbl->key);
4678     emitpLabel(tlbl->key);
4679
4680 }
4681 #endif
4682
4683 /*-----------------------------------------------------------------*/
4684 /* genCmpEq - generates code for equal to                          */
4685 /*-----------------------------------------------------------------*/
4686 static void genCmpEq (iCode *ic, iCode *ifx)
4687 {
4688     operand *left, *right, *result;
4689     unsigned long lit = 0L;
4690     int size,offset=0;
4691
4692     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4693
4694     if(ifx)
4695       DEBUGpic14_emitcode ("; ifx is non-null","");
4696     else
4697       DEBUGpic14_emitcode ("; ifx is null","");
4698
4699     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4700     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4701     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4702
4703     size = max(AOP_SIZE(left),AOP_SIZE(right));
4704
4705     DEBUGpic14_AopType(__LINE__,left,right,result);
4706
4707     /* if literal, literal on the right or 
4708     if the right is in a pointer register and left 
4709     is not */
4710     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4711         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4712       operand *tmp = right ;
4713       right = left;
4714       left = tmp;
4715     }
4716
4717
4718     if(ifx && !AOP_SIZE(result)){
4719         symbol *tlbl;
4720         /* if they are both bit variables */
4721         if (AOP_TYPE(left) == AOP_CRY &&
4722             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4723             if(AOP_TYPE(right) == AOP_LIT){
4724                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4725                 if(lit == 0L){
4726                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4727                     pic14_emitcode("cpl","c");
4728                 } else if(lit == 1L) {
4729                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4730                 } else {
4731                     pic14_emitcode("clr","c");
4732                 }
4733                 /* AOP_TYPE(right) == AOP_CRY */
4734             } else {
4735                 symbol *lbl = newiTempLabel(NULL);
4736                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4737                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4738                 pic14_emitcode("cpl","c");
4739                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4740             }
4741             /* if true label then we jump if condition
4742             supplied is true */
4743             tlbl = newiTempLabel(NULL);
4744             if ( IC_TRUE(ifx) ) {
4745                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4746                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4747             } else {
4748                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4749                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4750             }
4751             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4752
4753             {
4754               /* left and right are both bit variables, result is carry */
4755               resolvedIfx rIfx;
4756               
4757               resolveIfx(&rIfx,ifx);
4758
4759               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4760               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4761               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4762               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4763               genSkipz2(&rIfx,0);
4764             }
4765         } else {
4766
4767           /* They're not both bit variables. Is the right a literal? */
4768           if(AOP_TYPE(right) == AOP_LIT) {
4769             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4770             
4771             switch(size) {
4772
4773             case 1:
4774               switch(lit & 0xff) {
4775               case 1:
4776                 if ( IC_TRUE(ifx) ) {
4777                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4778                   emitSKPNZ;
4779                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4780                 } else {
4781                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4782                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4783                 }
4784                 break;
4785               case 0xff:
4786                 if ( IC_TRUE(ifx) ) {
4787                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4788                   emitSKPNZ;
4789                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4790                 } else {
4791                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4792                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4793                 }
4794                 break;
4795               default:
4796                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4797                 if(lit)
4798                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4799                 genSkip(ifx,'z');
4800               }
4801
4802
4803               /* end of size == 1 */
4804               break;
4805               
4806             case 2:
4807               genc16bit2lit(left,lit,offset);
4808               genSkip(ifx,'z');
4809               break;
4810               /* end of size == 2 */
4811
4812             default:
4813               /* size is 4 */
4814               if(lit==0) {
4815                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4816                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4817                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4818                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4819
4820               } else {
4821
4822                 /* search for patterns that can be optimized */
4823
4824                 genc16bit2lit(left,lit,0);
4825                 lit >>= 16;
4826                 if(lit) {
4827                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4828                   //genSkip(ifx,'z');
4829                   genc16bit2lit(left,lit,2);
4830                 } else {
4831                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4832                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4833
4834                 }
4835                 
4836               }
4837
4838               genSkip(ifx,'z');
4839             }
4840           
4841             ifx->generated = 1;
4842             goto release ;
4843             
4844
4845           } else if(AOP_TYPE(right) == AOP_CRY ) {
4846             /* we know the left is not a bit, but that the right is */
4847             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4848             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4849                       popGet(AOP(right),offset));
4850             emitpcode(POC_XORLW,popGetLit(1));
4851
4852             /* if the two are equal, then W will be 0 and the Z bit is set
4853              * we could test Z now, or go ahead and check the high order bytes if
4854              * the variable we're comparing is larger than a byte. */
4855
4856             while(--size)
4857               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4858
4859             if ( IC_TRUE(ifx) ) {
4860               emitSKPNZ;
4861               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4862               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4863             } else {
4864               emitSKPZ;
4865               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4866               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4867             }
4868
4869           } else {
4870             /* They're both variables that are larger than bits */
4871             int s = size;
4872
4873             tlbl = newiTempLabel(NULL);
4874
4875             while(size--) {
4876               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4877               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4878
4879               if ( IC_TRUE(ifx) ) {
4880                 if(size) {
4881                   emitSKPZ;
4882                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4883                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4884                 } else {
4885                   emitSKPNZ;
4886                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4887                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4888                 }
4889               } else {
4890                 emitSKPZ;
4891                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4892                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4893               }
4894               offset++;
4895             }
4896             if(s>1 && IC_TRUE(ifx)) {
4897               emitpLabel(tlbl->key);
4898               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4899             }
4900           }
4901         }
4902         /* mark the icode as generated */
4903         ifx->generated = 1;
4904         goto release ;
4905     }
4906
4907     /* if they are both bit variables */
4908     if (AOP_TYPE(left) == AOP_CRY &&
4909         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4910         if(AOP_TYPE(right) == AOP_LIT){
4911             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4912             if(lit == 0L){
4913                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4914                 pic14_emitcode("cpl","c");
4915             } else if(lit == 1L) {
4916                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4917             } else {
4918                 pic14_emitcode("clr","c");
4919             }
4920             /* AOP_TYPE(right) == AOP_CRY */
4921         } else {
4922             symbol *lbl = newiTempLabel(NULL);
4923             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4924             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4925             pic14_emitcode("cpl","c");
4926             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4927         }
4928         /* c = 1 if egal */
4929         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4930             pic14_outBitC(result);
4931             goto release ;
4932         }
4933         if (ifx) {
4934             genIfxJump (ifx,"c");
4935             goto release ;
4936         }
4937         /* if the result is used in an arithmetic operation
4938         then put the result in place */
4939         pic14_outBitC(result);
4940     } else {
4941       
4942       gencjne(left,right,result,ifx);
4943 /*
4944       if(ifx) 
4945         gencjne(left,right,newiTempLabel(NULL));
4946       else {
4947         if(IC_TRUE(ifx)->key)
4948           gencjne(left,right,IC_TRUE(ifx)->key);
4949         else
4950           gencjne(left,right,IC_FALSE(ifx)->key);
4951         ifx->generated = 1;
4952         goto release ;
4953       }
4954       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4955         aopPut(AOP(result),"a",0);
4956         goto release ;
4957       }
4958
4959       if (ifx) {
4960         genIfxJump (ifx,"a");
4961         goto release ;
4962       }
4963 */
4964       /* if the result is used in an arithmetic operation
4965          then put the result in place */
4966 /*
4967       if (AOP_TYPE(result) != AOP_CRY) 
4968         pic14_outAcc(result);
4969 */
4970       /* leave the result in acc */
4971     }
4972
4973 release:
4974     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4975     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4976     freeAsmop(result,NULL,ic,TRUE);
4977 }
4978
4979 /*-----------------------------------------------------------------*/
4980 /* ifxForOp - returns the icode containing the ifx for operand     */
4981 /*-----------------------------------------------------------------*/
4982 static iCode *ifxForOp ( operand *op, iCode *ic )
4983 {
4984     /* if true symbol then needs to be assigned */
4985     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4986     if (IS_TRUE_SYMOP(op))
4987         return NULL ;
4988
4989     /* if this has register type condition and
4990     the next instruction is ifx with the same operand
4991     and live to of the operand is upto the ifx only then */
4992     if (ic->next &&
4993         ic->next->op == IFX &&
4994         IC_COND(ic->next)->key == op->key &&
4995         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4996         return ic->next;
4997
4998     if (ic->next &&
4999         ic->next->op == IFX &&
5000         IC_COND(ic->next)->key == op->key) {
5001       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5002       return ic->next;
5003     }
5004
5005     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5006     if (ic->next &&
5007         ic->next->op == IFX)
5008       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5009
5010     if (ic->next &&
5011         ic->next->op == IFX &&
5012         IC_COND(ic->next)->key == op->key) {
5013       DEBUGpic14_emitcode ("; "," key is okay");
5014       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5015                            OP_SYMBOL(op)->liveTo,
5016                            ic->next->seq);
5017     }
5018
5019
5020     return NULL;
5021 }
5022 /*-----------------------------------------------------------------*/
5023 /* genAndOp - for && operation                                     */
5024 /*-----------------------------------------------------------------*/
5025 static void genAndOp (iCode *ic)
5026 {
5027     operand *left,*right, *result;
5028     symbol *tlbl;
5029
5030     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5031     /* note here that && operations that are in an
5032     if statement are taken away by backPatchLabels
5033     only those used in arthmetic operations remain */
5034     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5035     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5036     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5037
5038     /* if both are bit variables */
5039     if (AOP_TYPE(left) == AOP_CRY &&
5040         AOP_TYPE(right) == AOP_CRY ) {
5041         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5042         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
5043         pic14_outBitC(result);
5044     } else {
5045         tlbl = newiTempLabel(NULL);
5046         pic14_toBoolean(left);    
5047         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
5048         pic14_toBoolean(right);
5049         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5050         pic14_outBitAcc(result);
5051     }
5052
5053     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5054     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5055     freeAsmop(result,NULL,ic,TRUE);
5056 }
5057
5058
5059 /*-----------------------------------------------------------------*/
5060 /* genOrOp - for || operation                                      */
5061 /*-----------------------------------------------------------------*/
5062 /*
5063   tsd pic port -
5064   modified this code, but it doesn't appear to ever get called
5065 */
5066
5067 static void genOrOp (iCode *ic)
5068 {
5069     operand *left,*right, *result;
5070     symbol *tlbl;
5071
5072     /* note here that || operations that are in an
5073     if statement are taken away by backPatchLabels
5074     only those used in arthmetic operations remain */
5075     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5076     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5077     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5078     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5079
5080     DEBUGpic14_AopType(__LINE__,left,right,result);
5081
5082     /* if both are bit variables */
5083     if (AOP_TYPE(left) == AOP_CRY &&
5084         AOP_TYPE(right) == AOP_CRY ) {
5085       pic14_emitcode("clrc","");
5086       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5087                AOP(left)->aopu.aop_dir,
5088                AOP(left)->aopu.aop_dir);
5089       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5090                AOP(right)->aopu.aop_dir,
5091                AOP(right)->aopu.aop_dir);
5092       pic14_emitcode("setc","");
5093
5094     } else {
5095         tlbl = newiTempLabel(NULL);
5096         pic14_toBoolean(left);
5097         emitSKPZ;
5098         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5099         pic14_toBoolean(right);
5100         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5101
5102         pic14_outBitAcc(result);
5103     }
5104
5105     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5106     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5107     freeAsmop(result,NULL,ic,TRUE);            
5108 }
5109
5110 /*-----------------------------------------------------------------*/
5111 /* isLiteralBit - test if lit == 2^n                               */
5112 /*-----------------------------------------------------------------*/
5113 static int isLiteralBit(unsigned long lit)
5114 {
5115     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5116     0x100L,0x200L,0x400L,0x800L,
5117     0x1000L,0x2000L,0x4000L,0x8000L,
5118     0x10000L,0x20000L,0x40000L,0x80000L,
5119     0x100000L,0x200000L,0x400000L,0x800000L,
5120     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5121     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5122     int idx;
5123     
5124     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5125     for(idx = 0; idx < 32; idx++)
5126         if(lit == pw[idx])
5127             return idx+1;
5128     return 0;
5129 }
5130
5131 /*-----------------------------------------------------------------*/
5132 /* continueIfTrue -                                                */
5133 /*-----------------------------------------------------------------*/
5134 static void continueIfTrue (iCode *ic)
5135 {
5136     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137     if(IC_TRUE(ic))
5138         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5139     ic->generated = 1;
5140 }
5141
5142 /*-----------------------------------------------------------------*/
5143 /* jmpIfTrue -                                                     */
5144 /*-----------------------------------------------------------------*/
5145 static void jumpIfTrue (iCode *ic)
5146 {
5147     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5148     if(!IC_TRUE(ic))
5149         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5150     ic->generated = 1;
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* jmpTrueOrFalse -                                                */
5155 /*-----------------------------------------------------------------*/
5156 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5157 {
5158     // ugly but optimized by peephole
5159     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5160     if(IC_TRUE(ic)){
5161         symbol *nlbl = newiTempLabel(NULL);
5162         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5163         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5164         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5165         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5166     }
5167     else{
5168         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5169         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5170     }
5171     ic->generated = 1;
5172 }
5173
5174 /*-----------------------------------------------------------------*/
5175 /* genAnd  - code for and                                          */
5176 /*-----------------------------------------------------------------*/
5177 static void genAnd (iCode *ic, iCode *ifx)
5178 {
5179   operand *left, *right, *result;
5180   int size, offset=0;  
5181   unsigned long lit = 0L;
5182   int bytelit = 0;
5183   resolvedIfx rIfx;
5184
5185
5186   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5187   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5188   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5189   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5190
5191   resolveIfx(&rIfx,ifx);
5192
5193   /* if left is a literal & right is not then exchange them */
5194   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5195       AOP_NEEDSACC(left)) {
5196     operand *tmp = right ;
5197     right = left;
5198     left = tmp;
5199   }
5200
5201   /* if result = right then exchange them */
5202   if(pic14_sameRegs(AOP(result),AOP(right))){
5203     operand *tmp = right ;
5204     right = left;
5205     left = tmp;
5206   }
5207
5208   /* if right is bit then exchange them */
5209   if (AOP_TYPE(right) == AOP_CRY &&
5210       AOP_TYPE(left) != AOP_CRY){
5211     operand *tmp = right ;
5212     right = left;
5213     left = tmp;
5214   }
5215   if(AOP_TYPE(right) == AOP_LIT)
5216     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5217
5218   size = AOP_SIZE(result);
5219
5220   DEBUGpic14_AopType(__LINE__,left,right,result);
5221
5222   // if(bit & yy)
5223   // result = bit & yy;
5224   if (AOP_TYPE(left) == AOP_CRY){
5225     // c = bit & literal;
5226     if(AOP_TYPE(right) == AOP_LIT){
5227       if(lit & 1) {
5228         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5229           // no change
5230           goto release;
5231         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5232       } else {
5233         // bit(result) = 0;
5234         if(size && (AOP_TYPE(result) == AOP_CRY)){
5235           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5236           goto release;
5237         }
5238         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5239           jumpIfTrue(ifx);
5240           goto release;
5241         }
5242         pic14_emitcode("clr","c");
5243       }
5244     } else {
5245       if (AOP_TYPE(right) == AOP_CRY){
5246         // c = bit & bit;
5247         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5248         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5249       } else {
5250         // c = bit & val;
5251         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5252         // c = lsb
5253         pic14_emitcode("rrc","a");
5254         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5255       }
5256     }
5257     // bit = c
5258     // val = c
5259     if(size)
5260       pic14_outBitC(result);
5261     // if(bit & ...)
5262     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5263       genIfxJump(ifx, "c");           
5264     goto release ;
5265   }
5266
5267   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5268   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5269   if((AOP_TYPE(right) == AOP_LIT) &&
5270      (AOP_TYPE(result) == AOP_CRY) &&
5271      (AOP_TYPE(left) != AOP_CRY)){
5272     int posbit = isLiteralBit(lit);
5273     /* left &  2^n */
5274     if(posbit){
5275       posbit--;
5276       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5277       // bit = left & 2^n
5278       if(size)
5279         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5280       // if(left &  2^n)
5281       else{
5282         if(ifx){
5283 /*
5284           if(IC_TRUE(ifx)) {
5285             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5286             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5287           } else {
5288             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5289             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5290           }
5291 */
5292           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5293                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5294           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5295           
5296           ifx->generated = 1;
5297         }
5298         goto release;
5299       }
5300     } else {
5301       symbol *tlbl = newiTempLabel(NULL);
5302       int sizel = AOP_SIZE(left);
5303       if(size)
5304         pic14_emitcode("setb","c");
5305       while(sizel--){
5306         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5307           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5308           // byte ==  2^n ?
5309           if((posbit = isLiteralBit(bytelit)) != 0)
5310             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5311           else{
5312             if(bytelit != 0x0FFL)
5313               pic14_emitcode("anl","a,%s",
5314                              aopGet(AOP(right),offset,FALSE,TRUE));
5315             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5316           }
5317         }
5318         offset++;
5319       }
5320       // bit = left & literal
5321       if(size){
5322         pic14_emitcode("clr","c");
5323         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5324       }
5325       // if(left & literal)
5326       else{
5327         if(ifx)
5328           jmpTrueOrFalse(ifx, tlbl);
5329         goto release ;
5330       }
5331     }
5332     pic14_outBitC(result);
5333     goto release ;
5334   }
5335
5336   /* if left is same as result */
5337   if(pic14_sameRegs(AOP(result),AOP(left))){
5338     int know_W = -1;
5339     for(;size--; offset++,lit>>=8) {
5340       if(AOP_TYPE(right) == AOP_LIT){
5341         switch(lit & 0xff) {
5342         case 0x00:
5343           /*  and'ing with 0 has clears the result */
5344           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5345           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5346           break;
5347         case 0xff:
5348           /* and'ing with 0xff is a nop when the result and left are the same */
5349           break;
5350
5351         default:
5352           {
5353             int p = my_powof2( (~lit) & 0xff );
5354             if(p>=0) {
5355               /* only one bit is set in the literal, so use a bcf instruction */
5356               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5357               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5358
5359             } else {
5360               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5361               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5362               if(know_W != (lit&0xff))
5363                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5364               know_W = lit &0xff;
5365               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5366             }
5367           }    
5368         }
5369       } else {
5370         if (AOP_TYPE(left) == AOP_ACC) {
5371           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5372         } else {                    
5373           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5374           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5375
5376         }
5377       }
5378     }
5379
5380   } else {
5381     // left & result in different registers
5382     if(AOP_TYPE(result) == AOP_CRY){
5383       // result = bit
5384       // if(size), result in bit
5385       // if(!size && ifx), conditional oper: if(left & right)
5386       symbol *tlbl = newiTempLabel(NULL);
5387       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5388       if(size)
5389         pic14_emitcode("setb","c");
5390       while(sizer--){
5391         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5392         pic14_emitcode("anl","a,%s",
5393                        aopGet(AOP(left),offset,FALSE,FALSE));
5394         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5395         offset++;
5396       }
5397       if(size){
5398         CLRC;
5399         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5400         pic14_outBitC(result);
5401       } else if(ifx)
5402         jmpTrueOrFalse(ifx, tlbl);
5403     } else {
5404       for(;(size--);offset++) {
5405         // normal case
5406         // result = left & right
5407         if(AOP_TYPE(right) == AOP_LIT){
5408           int t = (lit >> (offset*8)) & 0x0FFL;
5409           switch(t) { 
5410           case 0x00:
5411             pic14_emitcode("clrf","%s",
5412                            aopGet(AOP(result),offset,FALSE,FALSE));
5413             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5414             break;
5415           case 0xff:
5416             pic14_emitcode("movf","%s,w",
5417                            aopGet(AOP(left),offset,FALSE,FALSE));
5418             pic14_emitcode("movwf","%s",
5419                            aopGet(AOP(result),offset,FALSE,FALSE));
5420             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5421             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5422             break;
5423           default:
5424             pic14_emitcode("movlw","0x%x",t);
5425             pic14_emitcode("andwf","%s,w",
5426                            aopGet(AOP(left),offset,FALSE,FALSE));
5427             pic14_emitcode("movwf","%s",
5428                            aopGet(AOP(result),offset,FALSE,FALSE));
5429               
5430             emitpcode(POC_MOVLW, popGetLit(t));
5431             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5432             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5433           }
5434           continue;
5435         }
5436
5437         if (AOP_TYPE(left) == AOP_ACC) {
5438           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5439           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5440         } else {
5441           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5442           pic14_emitcode("andwf","%s,w",
5443                          aopGet(AOP(left),offset,FALSE,FALSE));
5444           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5445           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5446         }
5447         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5448         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5449       }
5450     }
5451   }
5452
5453   release :
5454     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5455   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456   freeAsmop(result,NULL,ic,TRUE);     
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* genOr  - code for or                                            */
5461 /*-----------------------------------------------------------------*/
5462 static void genOr (iCode *ic, iCode *ifx)
5463 {
5464     operand *left, *right, *result;
5465     int size, offset=0;
5466     unsigned long lit = 0L;
5467
5468     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5469
5470     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5471     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5472     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5473
5474     DEBUGpic14_AopType(__LINE__,left,right,result);
5475
5476     /* if left is a literal & right is not then exchange them */
5477     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5478         AOP_NEEDSACC(left)) {
5479         operand *tmp = right ;
5480         right = left;
5481         left = tmp;
5482     }
5483
5484     /* if result = right then exchange them */
5485     if(pic14_sameRegs(AOP(result),AOP(right))){
5486         operand *tmp = right ;
5487         right = left;
5488         left = tmp;
5489     }
5490
5491     /* if right is bit then exchange them */
5492     if (AOP_TYPE(right) == AOP_CRY &&
5493         AOP_TYPE(left) != AOP_CRY){
5494         operand *tmp = right ;
5495         right = left;
5496         left = tmp;
5497     }
5498
5499     DEBUGpic14_AopType(__LINE__,left,right,result);
5500
5501     if(AOP_TYPE(right) == AOP_LIT)
5502         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5503
5504     size = AOP_SIZE(result);
5505
5506     // if(bit | yy)
5507     // xx = bit | yy;
5508     if (AOP_TYPE(left) == AOP_CRY){
5509         if(AOP_TYPE(right) == AOP_LIT){
5510             // c = bit & literal;
5511             if(lit){
5512                 // lit != 0 => result = 1
5513                 if(AOP_TYPE(result) == AOP_CRY){
5514                   if(size)
5515                     emitpcode(POC_BSF, popGet(AOP(result),0));
5516                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5517                   //     AOP(result)->aopu.aop_dir,
5518                   //     AOP(result)->aopu.aop_dir);
5519                     else if(ifx)
5520                         continueIfTrue(ifx);
5521                     goto release;
5522                 }
5523             } else {
5524                 // lit == 0 => result = left
5525                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5526                     goto release;
5527                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5528             }
5529         } else {
5530             if (AOP_TYPE(right) == AOP_CRY){
5531               if(pic14_sameRegs(AOP(result),AOP(left))){
5532                 // c = bit | bit;
5533                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5534                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5535                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5536
5537                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5538                          AOP(result)->aopu.aop_dir,
5539                          AOP(result)->aopu.aop_dir);
5540                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5541                          AOP(right)->aopu.aop_dir,
5542                          AOP(right)->aopu.aop_dir);
5543                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5544                          AOP(result)->aopu.aop_dir,
5545                          AOP(result)->aopu.aop_dir);
5546               } else {
5547                 if( AOP_TYPE(result) == AOP_ACC) {
5548                   emitpcode(POC_MOVLW, popGetLit(0));
5549                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5550                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5551                   emitpcode(POC_MOVLW, popGetLit(1));
5552
5553                 } else {
5554
5555                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5556                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5557                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5558                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5559
5560                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5561                                  AOP(result)->aopu.aop_dir,
5562                                  AOP(result)->aopu.aop_dir);
5563                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5564                                  AOP(right)->aopu.aop_dir,
5565                                  AOP(right)->aopu.aop_dir);
5566                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5567                                  AOP(left)->aopu.aop_dir,
5568                                  AOP(left)->aopu.aop_dir);
5569                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5570                                  AOP(result)->aopu.aop_dir,
5571                                  AOP(result)->aopu.aop_dir);
5572                 }
5573               }
5574             } else {
5575                 // c = bit | val;
5576                 symbol *tlbl = newiTempLabel(NULL);
5577                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5578
5579
5580                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5581                 if( AOP_TYPE(right) == AOP_ACC) {
5582                   emitpcode(POC_IORLW, popGetLit(0));
5583                   emitSKPNZ;
5584                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5585                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5586                 }
5587
5588
5589
5590                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5591                     pic14_emitcode(";XXX setb","c");
5592                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5593                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5594                 pic14_toBoolean(right);
5595                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5596                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5597                     jmpTrueOrFalse(ifx, tlbl);
5598                     goto release;
5599                 } else {
5600                     CLRC;
5601                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5602                 }
5603             }
5604         }
5605         // bit = c
5606         // val = c
5607         if(size)
5608             pic14_outBitC(result);
5609         // if(bit | ...)
5610         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5611             genIfxJump(ifx, "c");           
5612         goto release ;
5613     }
5614
5615     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5616     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5617     if((AOP_TYPE(right) == AOP_LIT) &&
5618        (AOP_TYPE(result) == AOP_CRY) &&
5619        (AOP_TYPE(left) != AOP_CRY)){
5620         if(lit){
5621           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5622             // result = 1
5623             if(size)
5624                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5625             else 
5626                 continueIfTrue(ifx);
5627             goto release;
5628         } else {
5629           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5630             // lit = 0, result = boolean(left)
5631             if(size)
5632                 pic14_emitcode(";XXX setb","c");
5633             pic14_toBoolean(right);
5634             if(size){
5635                 symbol *tlbl = newiTempLabel(NULL);
5636                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5637                 CLRC;
5638                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5639             } else {
5640                 genIfxJump (ifx,"a");
5641                 goto release;
5642             }
5643         }
5644         pic14_outBitC(result);
5645         goto release ;
5646     }
5647
5648     /* if left is same as result */
5649     if(pic14_sameRegs(AOP(result),AOP(left))){
5650       int know_W = -1;
5651       for(;size--; offset++,lit>>=8) {
5652         if(AOP_TYPE(right) == AOP_LIT){
5653           if((lit & 0xff) == 0)
5654             /*  or'ing with 0 has no effect */
5655             continue;
5656           else {
5657             int p = my_powof2(lit & 0xff);
5658             if(p>=0) {
5659               /* only one bit is set in the literal, so use a bsf instruction */
5660               emitpcode(POC_BSF,
5661                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5662             } else {
5663               if(know_W != (lit & 0xff))
5664                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5665               know_W = lit & 0xff;
5666               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5667             }
5668                     
5669           }
5670         } else {
5671           if (AOP_TYPE(left) == AOP_ACC) {
5672             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5673             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5674           } else {                  
5675             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5676             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5677
5678             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5679             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5680
5681           }
5682         }
5683       }
5684     } else {
5685         // left & result in different registers
5686         if(AOP_TYPE(result) == AOP_CRY){
5687             // result = bit
5688             // if(size), result in bit
5689             // if(!size && ifx), conditional oper: if(left | right)
5690             symbol *tlbl = newiTempLabel(NULL);
5691             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5692             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5693
5694
5695             if(size)
5696                 pic14_emitcode(";XXX setb","c");
5697             while(sizer--){
5698                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5699                 pic14_emitcode(";XXX orl","a,%s",
5700                          aopGet(AOP(left),offset,FALSE,FALSE));
5701                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5702                 offset++;
5703             }
5704             if(size){
5705                 CLRC;
5706                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5707                 pic14_outBitC(result);
5708             } else if(ifx)
5709                 jmpTrueOrFalse(ifx, tlbl);
5710         } else for(;(size--);offset++){
5711           // normal case
5712           // result = left & right
5713           if(AOP_TYPE(right) == AOP_LIT){
5714             int t = (lit >> (offset*8)) & 0x0FFL;
5715             switch(t) { 
5716             case 0x00:
5717               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5718               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5719
5720               pic14_emitcode("movf","%s,w",
5721                        aopGet(AOP(left),offset,FALSE,FALSE));
5722               pic14_emitcode("movwf","%s",
5723                        aopGet(AOP(result),offset,FALSE,FALSE));
5724               break;
5725             default:
5726               emitpcode(POC_MOVLW,  popGetLit(t));
5727               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5728               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5729
5730               pic14_emitcode("movlw","0x%x",t);
5731               pic14_emitcode("iorwf","%s,w",
5732                        aopGet(AOP(left),offset,FALSE,FALSE));
5733               pic14_emitcode("movwf","%s",
5734                        aopGet(AOP(result),offset,FALSE,FALSE));
5735               
5736             }
5737             continue;
5738           }
5739
5740           // faster than result <- left, anl result,right
5741           // and better if result is SFR
5742           if (AOP_TYPE(left) == AOP_ACC) {
5743             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5744             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5745           } else {
5746             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5747             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5748
5749             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5750             pic14_emitcode("iorwf","%s,w",
5751                      aopGet(AOP(left),offset,FALSE,FALSE));
5752           }
5753           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5754           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5755         }
5756     }
5757
5758 release :
5759     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5760     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5761     freeAsmop(result,NULL,ic,TRUE);     
5762 }
5763
5764 /*-----------------------------------------------------------------*/
5765 /* genXor - code for xclusive or                                   */
5766 /*-----------------------------------------------------------------*/
5767 static void genXor (iCode *ic, iCode *ifx)
5768 {
5769   operand *left, *right, *result;
5770   int size, offset=0;
5771   unsigned long lit = 0L;
5772
5773   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5774
5775   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5776   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5777   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5778
5779   /* if left is a literal & right is not ||
5780      if left needs acc & right does not */
5781   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5782       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5783     operand *tmp = right ;
5784     right = left;
5785     left = tmp;
5786   }
5787
5788   /* if result = right then exchange them */
5789   if(pic14_sameRegs(AOP(result),AOP(right))){
5790     operand *tmp = right ;
5791     right = left;
5792     left = tmp;
5793   }
5794
5795   /* if right is bit then exchange them */
5796   if (AOP_TYPE(right) == AOP_CRY &&
5797       AOP_TYPE(left) != AOP_CRY){
5798     operand *tmp = right ;
5799     right = left;
5800     left = tmp;
5801   }
5802   if(AOP_TYPE(right) == AOP_LIT)
5803     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5804
5805   size = AOP_SIZE(result);
5806
5807   // if(bit ^ yy)
5808   // xx = bit ^ yy;
5809   if (AOP_TYPE(left) == AOP_CRY){
5810     if(AOP_TYPE(right) == AOP_LIT){
5811       // c = bit & literal;
5812       if(lit>>1){
5813         // lit>>1  != 0 => result = 1
5814         if(AOP_TYPE(result) == AOP_CRY){
5815           if(size)
5816             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5817             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5818           else if(ifx)
5819             continueIfTrue(ifx);
5820           goto release;
5821         }
5822         pic14_emitcode("setb","c");
5823       } else{
5824         // lit == (0 or 1)
5825         if(lit == 0){
5826           // lit == 0, result = left
5827           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5828             goto release;
5829           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5830         } else{
5831           // lit == 1, result = not(left)
5832           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5833             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5834             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5835             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5836             goto release;
5837           } else {
5838             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5839             pic14_emitcode("cpl","c");
5840           }
5841         }
5842       }
5843
5844     } else {
5845       // right != literal
5846       symbol *tlbl = newiTempLabel(NULL);
5847       if (AOP_TYPE(right) == AOP_CRY){
5848         // c = bit ^ bit;
5849         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5850       }
5851       else{
5852         int sizer = AOP_SIZE(right);
5853         // c = bit ^ val
5854         // if val>>1 != 0, result = 1
5855         pic14_emitcode("setb","c");
5856         while(sizer){
5857           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5858           if(sizer == 1)
5859             // test the msb of the lsb
5860             pic14_emitcode("anl","a,#0xfe");
5861           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5862           sizer--;
5863         }
5864         // val = (0,1)
5865         pic14_emitcode("rrc","a");
5866       }
5867       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5868       pic14_emitcode("cpl","c");
5869       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5870     }
5871     // bit = c
5872     // val = c
5873     if(size)
5874       pic14_outBitC(result);
5875     // if(bit | ...)
5876     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5877       genIfxJump(ifx, "c");           
5878     goto release ;
5879   }
5880
5881   if(pic14_sameRegs(AOP(result),AOP(left))){
5882     /* if left is same as result */
5883     for(;size--; offset++) {
5884       if(AOP_TYPE(right) == AOP_LIT){
5885         int t  = (lit >> (offset*8)) & 0x0FFL;
5886         if(t == 0x00L)
5887           continue;
5888         else
5889           if (IS_AOP_PREG(left)) {
5890             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5891             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5892             aopPut(AOP(result),"a",offset);
5893           } else {
5894             emitpcode(POC_MOVLW, popGetLit(t));
5895             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5896             pic14_emitcode("xrl","%s,%s",
5897                            aopGet(AOP(left),offset,FALSE,TRUE),
5898                            aopGet(AOP(right),offset,FALSE,FALSE));
5899           }
5900       } else {
5901         if (AOP_TYPE(left) == AOP_ACC)
5902           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5903         else {
5904           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5905           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5906 /*
5907           if (IS_AOP_PREG(left)) {
5908             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5909             aopPut(AOP(result),"a",offset);
5910           } else
5911             pic14_emitcode("xrl","%s,a",
5912                            aopGet(AOP(left),offset,FALSE,TRUE));
5913 */
5914         }
5915       }
5916     }
5917   } else {
5918     // left & result in different registers
5919     if(AOP_TYPE(result) == AOP_CRY){
5920       // result = bit
5921       // if(size), result in bit
5922       // if(!size && ifx), conditional oper: if(left ^ right)
5923       symbol *tlbl = newiTempLabel(NULL);
5924       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5925       if(size)
5926         pic14_emitcode("setb","c");
5927       while(sizer--){
5928         if((AOP_TYPE(right) == AOP_LIT) &&
5929            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5930           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5931         } else {
5932           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5933           pic14_emitcode("xrl","a,%s",
5934                          aopGet(AOP(left),offset,FALSE,FALSE));
5935         }
5936         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5937         offset++;
5938       }
5939       if(size){
5940         CLRC;
5941         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5942         pic14_outBitC(result);
5943       } else if(ifx)
5944         jmpTrueOrFalse(ifx, tlbl);
5945     } else for(;(size--);offset++){
5946       // normal case
5947       // result = left & right
5948       if(AOP_TYPE(right) == AOP_LIT){
5949         int t = (lit >> (offset*8)) & 0x0FFL;
5950         switch(t) { 
5951         case 0x00:
5952           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5953           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5954           pic14_emitcode("movf","%s,w",
5955                          aopGet(AOP(left),offset,FALSE,FALSE));
5956           pic14_emitcode("movwf","%s",
5957                          aopGet(AOP(result),offset,FALSE,FALSE));
5958           break;
5959         case 0xff:
5960           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5961           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5962           pic14_emitcode("comf","%s,w",
5963                          aopGet(AOP(left),offset,FALSE,FALSE));
5964           pic14_emitcode("movwf","%s",
5965                          aopGet(AOP(result),offset,FALSE,FALSE));
5966           break;
5967         default:
5968           emitpcode(POC_MOVLW, popGetLit(t));
5969           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5970           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5971           pic14_emitcode("movlw","0x%x",t);
5972           pic14_emitcode("xorwf","%s,w",
5973                          aopGet(AOP(left),offset,FALSE,FALSE));
5974           pic14_emitcode("movwf","%s",
5975                          aopGet(AOP(result),offset,FALSE,FALSE));
5976
5977         }
5978         continue;
5979       }
5980
5981       // faster than result <- left, anl result,right
5982       // and better if result is SFR
5983       if (AOP_TYPE(left) == AOP_ACC) {
5984         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5985         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5986       } else {
5987         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5988         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5989         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5990         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5991       }
5992       if ( AOP_TYPE(result) != AOP_ACC){
5993         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5994         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5995       }
5996     }
5997   }
5998
5999   release :
6000     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6001   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6002   freeAsmop(result,NULL,ic,TRUE);     
6003 }
6004
6005 /*-----------------------------------------------------------------*/
6006 /* genInline - write the inline code out                           */
6007 /*-----------------------------------------------------------------*/
6008 static void genInline (iCode *ic)
6009 {
6010     char *buffer, *bp, *bp1;
6011     
6012     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6013
6014     _G.inLine += (!options.asmpeep);
6015
6016     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6017     strcpy(buffer,IC_INLINE(ic));
6018
6019     /* emit each line as a code */
6020     while (*bp) {
6021         if (*bp == '\n') {
6022             *bp++ = '\0';
6023             pic14_emitcode(bp1,"");
6024             addpCode2pBlock(pb,newpCodeInlineP(bp1));
6025             bp1 = bp;
6026         } else {
6027             if (*bp == ':') {
6028                 bp++;
6029                 *bp = '\0';
6030                 bp++;
6031                 pic14_emitcode(bp1,"");
6032                 bp1 = bp;
6033             } else
6034                 bp++;
6035         }
6036     }
6037     if (bp1 != bp) {
6038         pic14_emitcode(bp1,"");
6039         addpCode2pBlock(pb,newpCodeInlineP(bp1));
6040     }
6041     /*     pic14_emitcode("",buffer); */
6042     _G.inLine -= (!options.asmpeep);
6043 }
6044
6045 /*-----------------------------------------------------------------*/
6046 /* genRRC - rotate right with carry                                */
6047 /*-----------------------------------------------------------------*/
6048 static void genRRC (iCode *ic)
6049 {
6050   operand *left , *result ;
6051   int size, offset = 0, same;
6052
6053   /* rotate right with carry */
6054   left = IC_LEFT(ic);
6055   result=IC_RESULT(ic);
6056   aopOp (left,ic,FALSE);
6057   aopOp (result,ic,FALSE);
6058
6059   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6060
6061   same = pic14_sameRegs(AOP(result),AOP(left));
6062
6063   size = AOP_SIZE(result);    
6064
6065   /* get the lsb and put it into the carry */
6066   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6067
6068   offset = 0 ;
6069
6070   while(size--) {
6071
6072     if(same) {
6073       emitpcode(POC_RRF, popGet(AOP(left),offset));
6074     } else {
6075       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6076       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6077     }
6078
6079     offset++;
6080   }
6081
6082   freeAsmop(left,NULL,ic,TRUE);
6083   freeAsmop(result,NULL,ic,TRUE);
6084 }
6085
6086 /*-----------------------------------------------------------------*/
6087 /* genRLC - generate code for rotate left with carry               */
6088 /*-----------------------------------------------------------------*/
6089 static void genRLC (iCode *ic)
6090 {    
6091   operand *left , *result ;
6092   int size, offset = 0;
6093   int same;
6094
6095   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6096   /* rotate right with carry */
6097   left = IC_LEFT(ic);
6098   result=IC_RESULT(ic);
6099   aopOp (left,ic,FALSE);
6100   aopOp (result,ic,FALSE);
6101
6102   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6103
6104   same = pic14_sameRegs(AOP(result),AOP(left));
6105
6106   /* move it to the result */
6107   size = AOP_SIZE(result);    
6108
6109   /* get the msb and put it into the carry */
6110   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6111
6112   offset = 0 ;
6113
6114   while(size--) {
6115
6116     if(same) {
6117       emitpcode(POC_RLF, popGet(AOP(left),offset));
6118     } else {
6119       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6120       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6121     }
6122
6123     offset++;
6124   }
6125
6126
6127   freeAsmop(left,NULL,ic,TRUE);
6128   freeAsmop(result,NULL,ic,TRUE);
6129 }
6130
6131 /*-----------------------------------------------------------------*/
6132 /* genGetHbit - generates code get highest order bit               */
6133 /*-----------------------------------------------------------------*/
6134 static void genGetHbit (iCode *ic)
6135 {
6136     operand *left, *result;
6137     left = IC_LEFT(ic);
6138     result=IC_RESULT(ic);
6139     aopOp (left,ic,FALSE);
6140     aopOp (result,ic,FALSE);
6141
6142     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6143     /* get the highest order byte into a */
6144     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6145     if(AOP_TYPE(result) == AOP_CRY){
6146         pic14_emitcode("rlc","a");
6147         pic14_outBitC(result);
6148     }
6149     else{
6150         pic14_emitcode("rl","a");
6151         pic14_emitcode("anl","a,#0x01");
6152         pic14_outAcc(result);
6153     }
6154
6155
6156     freeAsmop(left,NULL,ic,TRUE);
6157     freeAsmop(result,NULL,ic,TRUE);
6158 }
6159
6160 /*-----------------------------------------------------------------*/
6161 /* AccRol - rotate left accumulator by known count                 */
6162 /*-----------------------------------------------------------------*/
6163 static void AccRol (int shCount)
6164 {
6165     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6166     shCount &= 0x0007;              // shCount : 0..7
6167     switch(shCount){
6168         case 0 :
6169             break;
6170         case 1 :
6171             pic14_emitcode("rl","a");
6172             break;
6173         case 2 :
6174             pic14_emitcode("rl","a");
6175             pic14_emitcode("rl","a");
6176             break;
6177         case 3 :
6178             pic14_emitcode("swap","a");
6179             pic14_emitcode("rr","a");
6180             break;
6181         case 4 :
6182             pic14_emitcode("swap","a");
6183             break;
6184         case 5 :
6185             pic14_emitcode("swap","a");
6186             pic14_emitcode("rl","a");
6187             break;
6188         case 6 :
6189             pic14_emitcode("rr","a");
6190             pic14_emitcode("rr","a");
6191             break;
6192         case 7 :
6193             pic14_emitcode("rr","a");
6194             break;
6195     }
6196 }
6197
6198 /*-----------------------------------------------------------------*/
6199 /* AccLsh - left shift accumulator by known count                  */
6200 /*-----------------------------------------------------------------*/
6201 static void AccLsh (int shCount)
6202 {
6203     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6204     if(shCount != 0){
6205         if(shCount == 1)
6206             pic14_emitcode("add","a,acc");
6207         else 
6208             if(shCount == 2) {
6209             pic14_emitcode("add","a,acc");
6210             pic14_emitcode("add","a,acc");
6211         } else {
6212             /* rotate left accumulator */
6213             AccRol(shCount);
6214             /* and kill the lower order bits */
6215             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6216         }
6217     }
6218 }
6219
6220 /*-----------------------------------------------------------------*/
6221 /* AccRsh - right shift accumulator by known count                 */
6222 /*-----------------------------------------------------------------*/
6223 static void AccRsh (int shCount)
6224 {
6225     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6226     if(shCount != 0){
6227         if(shCount == 1){
6228             CLRC;
6229             pic14_emitcode("rrc","a");
6230         } else {
6231             /* rotate right accumulator */
6232             AccRol(8 - shCount);
6233             /* and kill the higher order bits */
6234             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6235         }
6236     }
6237 }
6238
6239 #if 0
6240 /*-----------------------------------------------------------------*/
6241 /* AccSRsh - signed right shift accumulator by known count                 */
6242 /*-----------------------------------------------------------------*/
6243 static void AccSRsh (int shCount)
6244 {
6245     symbol *tlbl ;
6246     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6247     if(shCount != 0){
6248         if(shCount == 1){
6249             pic14_emitcode("mov","c,acc.7");
6250             pic14_emitcode("rrc","a");
6251         } else if(shCount == 2){
6252             pic14_emitcode("mov","c,acc.7");
6253             pic14_emitcode("rrc","a");
6254             pic14_emitcode("mov","c,acc.7");
6255             pic14_emitcode("rrc","a");
6256         } else {
6257             tlbl = newiTempLabel(NULL);
6258             /* rotate right accumulator */
6259             AccRol(8 - shCount);
6260             /* and kill the higher order bits */
6261             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6262             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6263             pic14_emitcode("orl","a,#0x%02x",
6264                      (unsigned char)~SRMask[shCount]);
6265             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6266         }
6267     }
6268 }
6269 #endif
6270 /*-----------------------------------------------------------------*/
6271 /* shiftR1Left2Result - shift right one byte from left to result   */
6272 /*-----------------------------------------------------------------*/
6273 static void shiftR1Left2ResultSigned (operand *left, int offl,
6274                                 operand *result, int offr,
6275                                 int shCount)
6276 {
6277   int same;
6278
6279   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6280
6281   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6282
6283   switch(shCount) {
6284   case 1:
6285     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6286     if(same) 
6287       emitpcode(POC_RRF, popGet(AOP(result),offr));
6288     else {
6289       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6290       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6291     }
6292
6293     break;
6294   case 2:
6295
6296     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6297     if(same) 
6298       emitpcode(POC_RRF, popGet(AOP(result),offr));
6299     else {
6300       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6301       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6302     }
6303     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6304     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6305
6306     break;
6307
6308   case 3:
6309     if(same)
6310       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6311     else {
6312       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6313       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6314     }
6315
6316     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6317     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6318     emitpcode(POC_ANDLW, popGetLit(0x1f));
6319
6320     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6321     emitpcode(POC_IORLW, popGetLit(0xe0));
6322
6323     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6324     break;
6325
6326   case 4:
6327     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6328     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6329     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6330     emitpcode(POC_IORLW,  popGetLit(0xf0));
6331     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6332     break;
6333   case 5:
6334     if(same) {
6335       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6336     } else {
6337       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6338       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6339     }
6340     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6341     emitpcode(POC_ANDLW,  popGetLit(0x07));
6342     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6343     emitpcode(POC_IORLW,  popGetLit(0xf8));
6344     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6345     break;
6346
6347   case 6:
6348     if(same) {
6349       emitpcode(POC_MOVLW, popGetLit(0x00));
6350       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6351       emitpcode(POC_MOVLW, popGetLit(0xfe));
6352       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6353       emitpcode(POC_IORLW, popGetLit(0x01));
6354       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6355     } else {
6356       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6357       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6358       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6359       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6360       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6361     }
6362     break;
6363
6364   case 7:
6365     if(same) {
6366       emitpcode(POC_MOVLW, popGetLit(0x00));
6367       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6368       emitpcode(POC_MOVLW, popGetLit(0xff));
6369       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6370     } else {
6371       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6372       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6373       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6374     }
6375
6376   default:
6377     break;
6378   }
6379 }
6380
6381 /*-----------------------------------------------------------------*/
6382 /* shiftR1Left2Result - shift right one byte from left to result   */
6383 /*-----------------------------------------------------------------*/
6384 static void shiftR1Left2Result (operand *left, int offl,
6385                                 operand *result, int offr,
6386                                 int shCount, int sign)
6387 {
6388   int same;
6389
6390   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6391
6392   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6393
6394   /* Copy the msb into the carry if signed. */
6395   if(sign) {
6396     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6397     return;
6398   }
6399
6400
6401
6402   switch(shCount) {
6403   case 1:
6404     emitCLRC;
6405     if(same) 
6406       emitpcode(POC_RRF, popGet(AOP(result),offr));
6407     else {
6408       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6409       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6410     }
6411     break;
6412   case 2:
6413     emitCLRC;
6414     if(same) {
6415       emitpcode(POC_RRF, popGet(AOP(result),offr));
6416     } else {
6417       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6418       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6419     }
6420     emitCLRC;
6421     emitpcode(POC_RRF, popGet(AOP(result),offr));
6422
6423     break;
6424   case 3:
6425     if(same)
6426       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6427     else {
6428       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6429       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6430     }
6431
6432     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6433     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6434     emitpcode(POC_ANDLW, popGetLit(0x1f));
6435     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6436     break;
6437       
6438   case 4:
6439     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6440     emitpcode(POC_ANDLW, popGetLit(0x0f));
6441     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6442     break;
6443
6444   case 5:
6445     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6446     emitpcode(POC_ANDLW, popGetLit(0x0f));
6447     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6448     emitCLRC;
6449     emitpcode(POC_RRF, popGet(AOP(result),offr));
6450
6451     break;
6452   case 6:
6453
6454     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6455     emitpcode(POC_ANDLW, popGetLit(0x80));
6456     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6457     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6458     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6459     break;
6460
6461   case 7:
6462
6463     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6464     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6465     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6466
6467     break;
6468
6469   default:
6470     break;
6471   }
6472 }
6473
6474 /*-----------------------------------------------------------------*/
6475 /* shiftL1Left2Result - shift left one byte from left to result    */
6476 /*-----------------------------------------------------------------*/
6477 static void shiftL1Left2Result (operand *left, int offl,
6478                                 operand *result, int offr, int shCount)
6479 {
6480   int same;
6481
6482   //    char *l;
6483   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6484
6485   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6486   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6487     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6488     //    MOVA(l);
6489     /* shift left accumulator */
6490     //AccLsh(shCount); // don't comment out just yet...
6491   //    aopPut(AOP(result),"a",offr);
6492
6493   switch(shCount) {
6494   case 1:
6495     /* Shift left 1 bit position */
6496     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6497     if(same) {
6498       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6499     } else {
6500       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6501       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6502     }
6503     break;
6504   case 2:
6505     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6506     emitpcode(POC_ANDLW,popGetLit(0x7e));
6507     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6508     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6509     break;
6510   case 3:
6511     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6512     emitpcode(POC_ANDLW,popGetLit(0x3e));
6513     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6514     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6515     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6516     break;
6517   case 4:
6518     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6519     emitpcode(POC_ANDLW, popGetLit(0xf0));
6520     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6521     break;
6522   case 5:
6523     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6524     emitpcode(POC_ANDLW, popGetLit(0xf0));
6525     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6526     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6527     break;
6528   case 6:
6529     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6530     emitpcode(POC_ANDLW, popGetLit(0x30));
6531     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6532     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6533     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6534     break;
6535   case 7:
6536     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6537     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6538     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6539     break;
6540
6541   default:
6542     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6543   }
6544
6545 }
6546
6547 /*-----------------------------------------------------------------*/
6548 /* movLeft2Result - move byte from left to result                  */
6549 /*-----------------------------------------------------------------*/
6550 static void movLeft2Result (operand *left, int offl,
6551                             operand *result, int offr)
6552 {
6553   char *l;
6554   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6555   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6556     l = aopGet(AOP(left),offl,FALSE,FALSE);
6557
6558     if (*l == '@' && (IS_AOP_PREG(result))) {
6559       pic14_emitcode("mov","a,%s",l);
6560       aopPut(AOP(result),"a",offr);
6561     } else {
6562       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6563       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6564     }
6565   }
6566 }
6567
6568 /*-----------------------------------------------------------------*/
6569 /* shiftL2Left2Result - shift left two bytes from left to result   */
6570 /*-----------------------------------------------------------------*/
6571 static void shiftL2Left2Result (operand *left, int offl,
6572                                 operand *result, int offr, int shCount)
6573 {
6574
6575
6576   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6577
6578   if(pic14_sameRegs(AOP(result), AOP(left))) {
6579     switch(shCount) {
6580     case 0:
6581       break;
6582     case 1:
6583     case 2:
6584     case 3:
6585
6586       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6587       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6588       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6589
6590       while(--shCount) {
6591         emitCLRC;
6592         emitpcode(POC_RLF, popGet(AOP(result),offr));
6593         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6594       }
6595
6596       break;
6597     case 4:
6598     case 5:
6599       emitpcode(POC_MOVLW, popGetLit(0x0f));
6600       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6601       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6602       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6603       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6604       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6605       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6606       if(shCount >=5) {
6607         emitpcode(POC_RLF, popGet(AOP(result),offr));
6608         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6609       }
6610       break;
6611     case 6:
6612       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6613       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6614       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6615       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6616       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6617       emitpcode(POC_ANDLW,popGetLit(0xc0));
6618       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6619       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6620       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6621       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6622       break;
6623     case 7:
6624       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6625       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6626       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6627       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6628       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6629     }
6630
6631   } else {
6632     switch(shCount) {
6633     case 0:
6634       break;
6635     case 1:
6636     case 2:
6637     case 3:
6638       /* note, use a mov/add for the shift since the mov has a
6639          chance of getting optimized out */
6640       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6641       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6642       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6643       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6644       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6645
6646       while(--shCount) {
6647         emitCLRC;
6648         emitpcode(POC_RLF, popGet(AOP(result),offr));
6649         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6650       }
6651       break;
6652
6653     case 4:
6654     case 5:
6655       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6656       emitpcode(POC_ANDLW, popGetLit(0xF0));
6657       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6658       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6659       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6660       emitpcode(POC_ANDLW, popGetLit(0xF0));
6661       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6662       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6663
6664
6665       if(shCount == 5) {
6666         emitpcode(POC_RLF, popGet(AOP(result),offr));
6667         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6668       }
6669       break;
6670     case 6:
6671       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6672       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6673       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6674       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6675
6676       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6677       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6678       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6679       emitpcode(POC_ANDLW,popGetLit(0xc0));
6680       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6681       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6682       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6683       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6684       break;
6685     case 7:
6686       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6687       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6688       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6689       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6690       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6691     }
6692   }
6693
6694 }
6695 /*-----------------------------------------------------------------*/
6696 /* shiftR2Left2Result - shift right two bytes from left to result  */
6697 /*-----------------------------------------------------------------*/
6698 static void shiftR2Left2Result (operand *left, int offl,
6699                                 operand *result, int offr,
6700                                 int shCount, int sign)
6701 {
6702   int same=0;
6703
6704   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6705   same = pic14_sameRegs(AOP(result), AOP(left));
6706
6707   if(same && ((offl + MSB16) == offr)){
6708     same=1;
6709     /* don't crash result[offr] */
6710     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6711     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6712   } else {
6713     movLeft2Result(left,offl, result, offr);
6714     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6715   }
6716   /* a:x >> shCount (x = lsb(result))*/
6717 /*
6718   if(sign)
6719     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6720   else {
6721     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6722 */
6723   switch(shCount) {
6724   case 0:
6725     break;
6726   case 1:
6727   case 2:
6728   case 3:
6729     if(sign)
6730       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6731     else
6732       emitCLRC;
6733
6734     if(same) {
6735       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6736       emitpcode(POC_RRF,popGet(AOP(result),offr));
6737     } else {
6738       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6739       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6740       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6741       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6742     }
6743
6744     while(--shCount) {
6745       if(sign)
6746         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6747       else
6748         emitCLRC;
6749       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6750       emitpcode(POC_RRF,popGet(AOP(result),offr));
6751     }
6752     break;
6753   case 4:
6754   case 5:
6755     if(same) {
6756
6757       emitpcode(POC_MOVLW, popGetLit(0xf0));
6758       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6759       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6760
6761       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6762       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6763       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6764       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6765     } else {
6766       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6767       emitpcode(POC_ANDLW, popGetLit(0x0f));
6768       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6769
6770       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6771       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6772       emitpcode(POC_ANDLW, popGetLit(0xf0));
6773       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6774       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6775     }
6776
6777     if(shCount >=5) {
6778       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6779       emitpcode(POC_RRF, popGet(AOP(result),offr));
6780     }
6781
6782     if(sign) {
6783       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6784       emitpcode(POC_BTFSC, 
6785                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6786       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6787     }
6788
6789     break;
6790
6791   case 6:
6792     if(same) {
6793
6794       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6795       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6796
6797       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6798       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6799       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6800       emitpcode(POC_ANDLW,popGetLit(0x03));
6801       if(sign) {
6802         emitpcode(POC_BTFSC, 
6803                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6804         emitpcode(POC_IORLW,popGetLit(0xfc));
6805       }
6806       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6807       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6809       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6810     } else {
6811       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6812       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6813       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6814       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6815       emitpcode(POC_RLFW,  popGet(AOP(result),offr+MSB16));
6816       emitpcode(POC_ANDLW,popGetLit(0x03));
6817       if(sign) {
6818         emitpcode(POC_BTFSC, 
6819                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6820         emitpcode(POC_IORLW,popGetLit(0xfc));
6821       }
6822       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6823       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6824
6825         
6826     }
6827
6828     break;
6829   case 7:
6830     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6831     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6832     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6833     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6834     if(sign) {
6835       emitSKPNC;
6836       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6837     } else 
6838       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6839   }
6840 }
6841
6842
6843 /*-----------------------------------------------------------------*/
6844 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6845 /*-----------------------------------------------------------------*/
6846 static void shiftLLeftOrResult (operand *left, int offl,
6847                                 operand *result, int offr, int shCount)
6848 {
6849     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6850     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6851     /* shift left accumulator */
6852     AccLsh(shCount);
6853     /* or with result */
6854     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6855     /* back to result */
6856     aopPut(AOP(result),"a",offr);
6857 }
6858
6859 /*-----------------------------------------------------------------*/
6860 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6861 /*-----------------------------------------------------------------*/
6862 static void shiftRLeftOrResult (operand *left, int offl,
6863                                 operand *result, int offr, int shCount)
6864 {
6865     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6866     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6867     /* shift right accumulator */
6868     AccRsh(shCount);
6869     /* or with result */
6870     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6871     /* back to result */
6872     aopPut(AOP(result),"a",offr);
6873 }
6874
6875 /*-----------------------------------------------------------------*/
6876 /* genlshOne - left shift a one byte quantity by known count       */
6877 /*-----------------------------------------------------------------*/
6878 static void genlshOne (operand *result, operand *left, int shCount)
6879 {       
6880     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6881     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6882 }
6883
6884 /*-----------------------------------------------------------------*/
6885 /* genlshTwo - left shift two bytes by known amount != 0           */
6886 /*-----------------------------------------------------------------*/
6887 static void genlshTwo (operand *result,operand *left, int shCount)
6888 {
6889     int size;
6890     
6891     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6892     size = pic14_getDataSize(result);
6893
6894     /* if shCount >= 8 */
6895     if (shCount >= 8) {
6896         shCount -= 8 ;
6897
6898         if (size > 1){
6899             if (shCount)
6900                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6901             else 
6902                 movLeft2Result(left, LSB, result, MSB16);
6903         }
6904         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6905     }
6906
6907     /*  1 <= shCount <= 7 */
6908     else {  
6909         if(size == 1)
6910             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6911         else 
6912             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6913     }
6914 }
6915
6916 /*-----------------------------------------------------------------*/
6917 /* shiftLLong - shift left one long from left to result            */
6918 /* offl = LSB or MSB16                                             */
6919 /*-----------------------------------------------------------------*/
6920 static void shiftLLong (operand *left, operand *result, int offr )
6921 {
6922     char *l;
6923     int size = AOP_SIZE(result);
6924
6925     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6926     if(size >= LSB+offr){
6927         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6928         MOVA(l);
6929         pic14_emitcode("add","a,acc");
6930         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6931             size >= MSB16+offr && offr != LSB )
6932             pic14_emitcode("xch","a,%s",
6933                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6934         else        
6935             aopPut(AOP(result),"a",LSB+offr);
6936     }
6937
6938     if(size >= MSB16+offr){
6939         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6940             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6941             MOVA(l);
6942         }
6943         pic14_emitcode("rlc","a");
6944         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6945             size >= MSB24+offr && offr != LSB)
6946             pic14_emitcode("xch","a,%s",
6947                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6948         else        
6949             aopPut(AOP(result),"a",MSB16+offr);
6950     }
6951
6952     if(size >= MSB24+offr){
6953         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6954             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6955             MOVA(l);
6956         }
6957         pic14_emitcode("rlc","a");
6958         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6959             size >= MSB32+offr && offr != LSB )
6960             pic14_emitcode("xch","a,%s",
6961                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6962         else        
6963             aopPut(AOP(result),"a",MSB24+offr);
6964     }
6965
6966     if(size > MSB32+offr){
6967         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6968             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6969             MOVA(l);    
6970         }
6971         pic14_emitcode("rlc","a");
6972         aopPut(AOP(result),"a",MSB32+offr);
6973     }
6974     if(offr != LSB)
6975         aopPut(AOP(result),zero,LSB);       
6976 }
6977
6978 /*-----------------------------------------------------------------*/
6979 /* genlshFour - shift four byte by a known amount != 0             */
6980 /*-----------------------------------------------------------------*/
6981 static void genlshFour (operand *result, operand *left, int shCount)
6982 {
6983     int size;
6984
6985     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6986     size = AOP_SIZE(result);
6987
6988     /* if shifting more that 3 bytes */
6989     if (shCount >= 24 ) {
6990         shCount -= 24;
6991         if (shCount)
6992             /* lowest order of left goes to the highest
6993             order of the destination */
6994             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6995         else
6996             movLeft2Result(left, LSB, result, MSB32);
6997         aopPut(AOP(result),zero,LSB);
6998         aopPut(AOP(result),zero,MSB16);
6999         aopPut(AOP(result),zero,MSB32);
7000         return;
7001     }
7002
7003     /* more than two bytes */
7004     else if ( shCount >= 16 ) {
7005         /* lower order two bytes goes to higher order two bytes */
7006         shCount -= 16;
7007         /* if some more remaining */
7008         if (shCount)
7009             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7010         else {
7011             movLeft2Result(left, MSB16, result, MSB32);
7012             movLeft2Result(left, LSB, result, MSB24);
7013         }
7014         aopPut(AOP(result),zero,MSB16);
7015         aopPut(AOP(result),zero,LSB);
7016         return;
7017     }    
7018
7019     /* if more than 1 byte */
7020     else if ( shCount >= 8 ) {
7021         /* lower order three bytes goes to higher order  three bytes */
7022         shCount -= 8;
7023         if(size == 2){
7024             if(shCount)
7025                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7026             else
7027                 movLeft2Result(left, LSB, result, MSB16);
7028         }
7029         else{   /* size = 4 */
7030             if(shCount == 0){
7031                 movLeft2Result(left, MSB24, result, MSB32);
7032                 movLeft2Result(left, MSB16, result, MSB24);
7033                 movLeft2Result(left, LSB, result, MSB16);
7034                 aopPut(AOP(result),zero,LSB);
7035             }
7036             else if(shCount == 1)
7037                 shiftLLong(left, result, MSB16);
7038             else{
7039                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7040                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7041                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7042                 aopPut(AOP(result),zero,LSB);
7043             }
7044         }
7045     }
7046
7047     /* 1 <= shCount <= 7 */
7048     else if(shCount <= 2){
7049         shiftLLong(left, result, LSB);
7050         if(shCount == 2)
7051             shiftLLong(result, result, LSB);
7052     }
7053     /* 3 <= shCount <= 7, optimize */
7054     else{
7055         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7056         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7057         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7058     }
7059 }
7060
7061 /*-----------------------------------------------------------------*/
7062 /* genLeftShiftLiteral - left shifting by known count              */
7063 /*-----------------------------------------------------------------*/
7064 static void genLeftShiftLiteral (operand *left,
7065                                  operand *right,
7066                                  operand *result,
7067                                  iCode *ic)
7068 {    
7069     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7070     int size;
7071
7072     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7073     freeAsmop(right,NULL,ic,TRUE);
7074
7075     aopOp(left,ic,FALSE);
7076     aopOp(result,ic,FALSE);
7077
7078     size = getSize(operandType(result));
7079
7080 #if VIEW_SIZE
7081     pic14_emitcode("; shift left ","result %d, left %d",size,
7082              AOP_SIZE(left));
7083 #endif
7084
7085     /* I suppose that the left size >= result size */
7086     if(shCount == 0){
7087         while(size--){
7088             movLeft2Result(left, size, result, size);
7089         }
7090     }
7091
7092     else if(shCount >= (size * 8))
7093         while(size--)
7094             aopPut(AOP(result),zero,size);
7095     else{
7096         switch (size) {
7097             case 1:
7098                 genlshOne (result,left,shCount);
7099                 break;
7100
7101             case 2:
7102             case 3:
7103                 genlshTwo (result,left,shCount);
7104                 break;
7105
7106             case 4:
7107                 genlshFour (result,left,shCount);
7108                 break;
7109         }
7110     }
7111     freeAsmop(left,NULL,ic,TRUE);
7112     freeAsmop(result,NULL,ic,TRUE);
7113 }
7114
7115 /*-----------------------------------------------------------------*
7116  * genMultiAsm - repeat assembly instruction for size of register.
7117  * if endian == 1, then the high byte (i.e base address + size of 
7118  * register) is used first else the low byte is used first;
7119  *-----------------------------------------------------------------*/
7120 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7121 {
7122
7123   int offset = 0;
7124
7125   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7126
7127   if(!reg)
7128     return;
7129
7130   if(!endian) {
7131     endian = 1;
7132   } else {
7133     endian = -1;
7134     offset = size-1;
7135   }
7136
7137   while(size--) {
7138     emitpcode(poc,    popGet(AOP(reg),offset));
7139     offset += endian;
7140   }
7141
7142 }
7143 /*-----------------------------------------------------------------*/
7144 /* genLeftShift - generates code for left shifting                 */
7145 /*-----------------------------------------------------------------*/
7146 static void genLeftShift (iCode *ic)
7147 {
7148   operand *left,*right, *result;
7149   int size, offset;
7150   char *l;
7151   symbol *tlbl , *tlbl1;
7152   pCodeOp *pctemp;
7153
7154   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7155
7156   right = IC_RIGHT(ic);
7157   left  = IC_LEFT(ic);
7158   result = IC_RESULT(ic);
7159
7160   aopOp(right,ic,FALSE);
7161
7162   /* if the shift count is known then do it 
7163      as efficiently as possible */
7164   if (AOP_TYPE(right) == AOP_LIT) {
7165     genLeftShiftLiteral (left,right,result,ic);
7166     return ;
7167   }
7168
7169   /* shift count is unknown then we have to form 
7170      a loop get the loop count in B : Note: we take
7171      only the lower order byte since shifting
7172      more that 32 bits make no sense anyway, ( the
7173      largest size of an object can be only 32 bits ) */  
7174
7175     
7176   aopOp(left,ic,FALSE);
7177   aopOp(result,ic,FALSE);
7178
7179   /* now move the left to the result if they are not the
7180      same */
7181   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7182       AOP_SIZE(result) > 1) {
7183
7184     size = AOP_SIZE(result);
7185     offset=0;
7186     while (size--) {
7187       l = aopGet(AOP(left),offset,FALSE,TRUE);
7188       if (*l == '@' && (IS_AOP_PREG(result))) {
7189
7190         pic14_emitcode("mov","a,%s",l);
7191         aopPut(AOP(result),"a",offset);
7192       } else {
7193         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7194         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7195         //aopPut(AOP(result),l,offset);
7196       }
7197       offset++;
7198     }
7199   }
7200
7201   size = AOP_SIZE(result);
7202
7203   /* if it is only one byte then */
7204   if (size == 1) {
7205     if(optimized_for_speed) {
7206       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7207       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7208       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7209       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7210       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7211       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7212       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7213       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7214       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7215       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7216       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7217       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7218     } else {
7219
7220       tlbl = newiTempLabel(NULL);
7221       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7222         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7223         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7224       }
7225
7226       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7227       emitpcode(POC_RRF,    popGet(AOP(result),0));
7228       emitpLabel(tlbl->key);
7229       emitpcode(POC_RLF,    popGet(AOP(result),0));
7230       emitpcode(POC_ADDLW,  popGetLit(1));
7231       emitSKPC;
7232       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7233     }
7234     goto release ;
7235   }
7236     
7237   if (pic14_sameRegs(AOP(left),AOP(result))) {
7238
7239     tlbl = newiTempLabel(NULL);
7240     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7241     genMultiAsm(POC_RRF, result, size,1);
7242     emitpLabel(tlbl->key);
7243     genMultiAsm(POC_RLF, result, size,0);
7244     emitpcode(POC_ADDLW,  popGetLit(1));
7245     emitSKPC;
7246     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7247     goto release;
7248   }
7249
7250   //tlbl = newiTempLabel(NULL);
7251   //offset = 0 ;   
7252   //tlbl1 = newiTempLabel(NULL);
7253
7254   //reAdjustPreg(AOP(result));    
7255     
7256   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7257   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7258   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7259   //MOVA(l);
7260   //pic14_emitcode("add","a,acc");         
7261   //aopPut(AOP(result),"a",offset++);
7262   //while (--size) {
7263   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7264   //  MOVA(l);
7265   //  pic14_emitcode("rlc","a");         
7266   //  aopPut(AOP(result),"a",offset++);
7267   //}
7268   //reAdjustPreg(AOP(result));
7269
7270   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7271   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7272
7273
7274   tlbl = newiTempLabel(NULL);
7275   tlbl1= newiTempLabel(NULL);
7276
7277   size = AOP_SIZE(result);
7278   offset = 1;
7279
7280   pctemp = popGetTempReg();  /* grab a temporary working register. */
7281
7282   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7283
7284   /* offset should be 0, 1 or 3 */
7285   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7286   emitSKPNZ;
7287   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7288
7289   emitpcode(POC_MOVWF, pctemp);
7290
7291
7292   emitpLabel(tlbl->key);
7293
7294   emitCLRC;
7295   emitpcode(POC_RLF,  popGet(AOP(result),0));
7296   while(--size)
7297     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7298
7299   emitpcode(POC_DECFSZ,  pctemp);
7300   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7301   emitpLabel(tlbl1->key);
7302
7303   popReleaseTempReg(pctemp);
7304
7305
7306  release:
7307   freeAsmop (right,NULL,ic,TRUE);
7308   freeAsmop(left,NULL,ic,TRUE);
7309   freeAsmop(result,NULL,ic,TRUE);
7310 }
7311
7312 /*-----------------------------------------------------------------*/
7313 /* genrshOne - right shift a one byte quantity by known count      */
7314 /*-----------------------------------------------------------------*/
7315 static void genrshOne (operand *result, operand *left,
7316                        int shCount, int sign)
7317 {
7318     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7319     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7320 }
7321
7322 /*-----------------------------------------------------------------*/
7323 /* genrshTwo - right shift two bytes by known amount != 0          */
7324 /*-----------------------------------------------------------------*/
7325 static void genrshTwo (operand *result,operand *left,
7326                        int shCount, int sign)
7327 {
7328   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7329   /* if shCount >= 8 */
7330   if (shCount >= 8) {
7331     shCount -= 8 ;
7332     if (shCount)
7333       shiftR1Left2Result(left, MSB16, result, LSB,
7334                          shCount, sign);
7335     else
7336       movLeft2Result(left, MSB16, result, LSB);
7337
7338     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7339
7340     if(sign) {
7341       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7342       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7343     }
7344   }
7345
7346   /*  1 <= shCount <= 7 */
7347   else
7348     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7349 }
7350
7351 /*-----------------------------------------------------------------*/
7352 /* shiftRLong - shift right one long from left to result           */
7353 /* offl = LSB or MSB16                                             */
7354 /*-----------------------------------------------------------------*/
7355 static void shiftRLong (operand *left, int offl,
7356                         operand *result, int sign)
7357 {
7358     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7359     if(!sign)
7360         pic14_emitcode("clr","c");
7361     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7362     if(sign)
7363         pic14_emitcode("mov","c,acc.7");
7364     pic14_emitcode("rrc","a");
7365     aopPut(AOP(result),"a",MSB32-offl);
7366     if(offl == MSB16)
7367         /* add sign of "a" */
7368         addSign(result, MSB32, sign);
7369
7370     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7371     pic14_emitcode("rrc","a");
7372     aopPut(AOP(result),"a",MSB24-offl);
7373
7374     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7375     pic14_emitcode("rrc","a");
7376     aopPut(AOP(result),"a",MSB16-offl);
7377
7378     if(offl == LSB){
7379         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7380         pic14_emitcode("rrc","a");
7381         aopPut(AOP(result),"a",LSB);
7382     }
7383 }
7384
7385 /*-----------------------------------------------------------------*/
7386 /* genrshFour - shift four byte by a known amount != 0             */
7387 /*-----------------------------------------------------------------*/
7388 static void genrshFour (operand *result, operand *left,
7389                         int shCount, int sign)
7390 {
7391   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7392   /* if shifting more that 3 bytes */
7393   if(shCount >= 24 ) {
7394     shCount -= 24;
7395     if(shCount)
7396       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7397     else
7398       movLeft2Result(left, MSB32, result, LSB);
7399
7400     addSign(result, MSB16, sign);
7401   }
7402   else if(shCount >= 16){
7403     shCount -= 16;
7404     if(shCount)
7405       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7406     else{
7407       movLeft2Result(left, MSB24, result, LSB);
7408       movLeft2Result(left, MSB32, result, MSB16);
7409     }
7410     addSign(result, MSB24, sign);
7411   }
7412   else if(shCount >= 8){
7413     shCount -= 8;
7414     if(shCount == 1)
7415       shiftRLong(left, MSB16, result, sign);
7416     else if(shCount == 0){
7417       movLeft2Result(left, MSB16, result, LSB);
7418       movLeft2Result(left, MSB24, result, MSB16);
7419       movLeft2Result(left, MSB32, result, MSB24);
7420       addSign(result, MSB32, sign);
7421     }
7422     else{
7423       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7424       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7425       /* the last shift is signed */
7426       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7427       addSign(result, MSB32, sign);
7428     }
7429   }
7430   else{   /* 1 <= shCount <= 7 */
7431     if(shCount <= 2){
7432       shiftRLong(left, LSB, result, sign);
7433       if(shCount == 2)
7434         shiftRLong(result, LSB, result, sign);
7435     }
7436     else{
7437       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7438       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7439       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7440     }
7441   }
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* genRightShiftLiteral - right shifting by known count            */
7446 /*-----------------------------------------------------------------*/
7447 static void genRightShiftLiteral (operand *left,
7448                                   operand *right,
7449                                   operand *result,
7450                                   iCode *ic,
7451                                   int sign)
7452 {    
7453   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7454   int lsize,res_size;
7455
7456   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7457   freeAsmop(right,NULL,ic,TRUE);
7458
7459   aopOp(left,ic,FALSE);
7460   aopOp(result,ic,FALSE);
7461
7462 #if VIEW_SIZE
7463   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7464                  AOP_SIZE(left));
7465 #endif
7466
7467   lsize = pic14_getDataSize(left);
7468   res_size = pic14_getDataSize(result);
7469   /* test the LEFT size !!! */
7470
7471   /* I suppose that the left size >= result size */
7472   if(shCount == 0){
7473     while(res_size--)
7474       movLeft2Result(left, lsize, result, res_size);
7475   }
7476
7477   else if(shCount >= (lsize * 8)){
7478
7479     if(res_size == 1) {
7480       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7481       if(sign) {
7482         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7483         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7484       }
7485     } else {
7486
7487       if(sign) {
7488         emitpcode(POC_MOVLW, popGetLit(0));
7489         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7490         emitpcode(POC_MOVLW, popGetLit(0xff));
7491         while(res_size--)
7492           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7493
7494       } else {
7495
7496         while(res_size--)
7497           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7498       }
7499     }
7500   } else {
7501
7502     switch (res_size) {
7503     case 1:
7504       genrshOne (result,left,shCount,sign);
7505       break;
7506
7507     case 2:
7508       genrshTwo (result,left,shCount,sign);
7509       break;
7510
7511     case 4:
7512       genrshFour (result,left,shCount,sign);
7513       break;
7514     default :
7515       break;
7516     }
7517
7518   }
7519
7520   freeAsmop(left,NULL,ic,TRUE);
7521   freeAsmop(result,NULL,ic,TRUE);
7522 }
7523
7524 /*-----------------------------------------------------------------*/
7525 /* genSignedRightShift - right shift of signed number              */
7526 /*-----------------------------------------------------------------*/
7527 static void genSignedRightShift (iCode *ic)
7528 {
7529   operand *right, *left, *result;
7530   int size, offset;
7531   //  char *l;
7532   symbol *tlbl, *tlbl1 ;
7533   pCodeOp *pctemp;
7534
7535   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7536
7537   /* we do it the hard way put the shift count in b
7538      and loop thru preserving the sign */
7539   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7540
7541   right = IC_RIGHT(ic);
7542   left  = IC_LEFT(ic);
7543   result = IC_RESULT(ic);
7544
7545   aopOp(right,ic,FALSE);  
7546   aopOp(left,ic,FALSE);
7547   aopOp(result,ic,FALSE);
7548
7549
7550   if ( AOP_TYPE(right) == AOP_LIT) {
7551     genRightShiftLiteral (left,right,result,ic,1);
7552     return ;
7553   }
7554   /* shift count is unknown then we have to form 
7555      a loop get the loop count in B : Note: we take
7556      only the lower order byte since shifting
7557      more that 32 bits make no sense anyway, ( the
7558      largest size of an object can be only 32 bits ) */  
7559
7560   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7561   //pic14_emitcode("inc","b");
7562   //freeAsmop (right,NULL,ic,TRUE);
7563   //aopOp(left,ic,FALSE);
7564   //aopOp(result,ic,FALSE);
7565
7566   /* now move the left to the result if they are not the
7567      same */
7568   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7569       AOP_SIZE(result) > 1) {
7570
7571     size = AOP_SIZE(result);
7572     offset=0;
7573     while (size--) { 
7574       /*
7575         l = aopGet(AOP(left),offset,FALSE,TRUE);
7576         if (*l == '@' && IS_AOP_PREG(result)) {
7577
7578         pic14_emitcode("mov","a,%s",l);
7579         aopPut(AOP(result),"a",offset);
7580         } else
7581         aopPut(AOP(result),l,offset);
7582       */
7583       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7584       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7585
7586       offset++;
7587     }
7588   }
7589
7590   /* mov the highest order bit to OVR */    
7591   tlbl = newiTempLabel(NULL);
7592   tlbl1= newiTempLabel(NULL);
7593
7594   size = AOP_SIZE(result);
7595   offset = size - 1;
7596
7597   pctemp = popGetTempReg();  /* grab a temporary working register. */
7598
7599   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7600
7601   /* offset should be 0, 1 or 3 */
7602   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7603   emitSKPNZ;
7604   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7605
7606   emitpcode(POC_MOVWF, pctemp);
7607
7608
7609   emitpLabel(tlbl->key);
7610
7611   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7612   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7613
7614   while(--size) {
7615     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7616   }
7617
7618   emitpcode(POC_DECFSZ,  pctemp);
7619   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7620   emitpLabel(tlbl1->key);
7621
7622   popReleaseTempReg(pctemp);
7623 #if 0
7624   size = AOP_SIZE(result);
7625   offset = size - 1;
7626   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7627   pic14_emitcode("rlc","a");
7628   pic14_emitcode("mov","ov,c");
7629   /* if it is only one byte then */
7630   if (size == 1) {
7631     l = aopGet(AOP(left),0,FALSE,FALSE);
7632     MOVA(l);
7633     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7634     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7635     pic14_emitcode("mov","c,ov");
7636     pic14_emitcode("rrc","a");
7637     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7638     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7639     aopPut(AOP(result),"a",0);
7640     goto release ;
7641   }
7642
7643   reAdjustPreg(AOP(result));
7644   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7645   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7646   pic14_emitcode("mov","c,ov");
7647   while (size--) {
7648     l = aopGet(AOP(result),offset,FALSE,FALSE);
7649     MOVA(l);
7650     pic14_emitcode("rrc","a");         
7651     aopPut(AOP(result),"a",offset--);
7652   }
7653   reAdjustPreg(AOP(result));
7654   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7655   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7656
7657  release:
7658 #endif
7659
7660   freeAsmop(left,NULL,ic,TRUE);
7661   freeAsmop(result,NULL,ic,TRUE);
7662   freeAsmop(right,NULL,ic,TRUE);
7663 }
7664
7665 /*-----------------------------------------------------------------*/
7666 /* genRightShift - generate code for right shifting                */
7667 /*-----------------------------------------------------------------*/
7668 static void genRightShift (iCode *ic)
7669 {
7670     operand *right, *left, *result;
7671     sym_link *retype ;
7672     int size, offset;
7673     char *l;
7674     symbol *tlbl, *tlbl1 ;
7675
7676     /* if signed then we do it the hard way preserve the
7677     sign bit moving it inwards */
7678     retype = getSpec(operandType(IC_RESULT(ic)));
7679     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7680
7681     if (!SPEC_USIGN(retype)) {
7682         genSignedRightShift (ic);
7683         return ;
7684     }
7685
7686     /* signed & unsigned types are treated the same : i.e. the
7687     signed is NOT propagated inwards : quoting from the
7688     ANSI - standard : "for E1 >> E2, is equivalent to division
7689     by 2**E2 if unsigned or if it has a non-negative value,
7690     otherwise the result is implementation defined ", MY definition
7691     is that the sign does not get propagated */
7692
7693     right = IC_RIGHT(ic);
7694     left  = IC_LEFT(ic);
7695     result = IC_RESULT(ic);
7696
7697     aopOp(right,ic,FALSE);
7698
7699     /* if the shift count is known then do it 
7700     as efficiently as possible */
7701     if (AOP_TYPE(right) == AOP_LIT) {
7702         genRightShiftLiteral (left,right,result,ic, 0);
7703         return ;
7704     }
7705
7706     /* shift count is unknown then we have to form 
7707     a loop get the loop count in B : Note: we take
7708     only the lower order byte since shifting
7709     more that 32 bits make no sense anyway, ( the
7710     largest size of an object can be only 32 bits ) */  
7711
7712     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7713     pic14_emitcode("inc","b");
7714     aopOp(left,ic,FALSE);
7715     aopOp(result,ic,FALSE);
7716
7717     /* now move the left to the result if they are not the
7718     same */
7719     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7720         AOP_SIZE(result) > 1) {
7721
7722         size = AOP_SIZE(result);
7723         offset=0;
7724         while (size--) {
7725             l = aopGet(AOP(left),offset,FALSE,TRUE);
7726             if (*l == '@' && IS_AOP_PREG(result)) {
7727
7728                 pic14_emitcode("mov","a,%s",l);
7729                 aopPut(AOP(result),"a",offset);
7730             } else
7731                 aopPut(AOP(result),l,offset);
7732             offset++;
7733         }
7734     }
7735
7736     tlbl = newiTempLabel(NULL);
7737     tlbl1= newiTempLabel(NULL);
7738     size = AOP_SIZE(result);
7739     offset = size - 1;
7740
7741     /* if it is only one byte then */
7742     if (size == 1) {
7743
7744       tlbl = newiTempLabel(NULL);
7745       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7746         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7747         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7748       }
7749
7750       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7751       emitpcode(POC_RLF,    popGet(AOP(result),0));
7752       emitpLabel(tlbl->key);
7753       emitpcode(POC_RRF,    popGet(AOP(result),0));
7754       emitpcode(POC_ADDLW,  popGetLit(1));
7755       emitSKPC;
7756       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7757
7758       goto release ;
7759     }
7760
7761     reAdjustPreg(AOP(result));
7762     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7763     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7764     CLRC;
7765     while (size--) {
7766         l = aopGet(AOP(result),offset,FALSE,FALSE);
7767         MOVA(l);
7768         pic14_emitcode("rrc","a");         
7769         aopPut(AOP(result),"a",offset--);
7770     }
7771     reAdjustPreg(AOP(result));
7772
7773     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7774     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7775
7776 release:
7777     freeAsmop(left,NULL,ic,TRUE);
7778     freeAsmop (right,NULL,ic,TRUE);
7779     freeAsmop(result,NULL,ic,TRUE);
7780 }
7781
7782 /*-----------------------------------------------------------------*/
7783 /* genUnpackBits - generates code for unpacking bits               */
7784 /*-----------------------------------------------------------------*/
7785 static void genUnpackBits (operand *result, char *rname, int ptype)
7786 {    
7787     int shCnt ;
7788     int rlen = 0 ;
7789     sym_link *etype;
7790     int offset = 0 ;
7791
7792     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7793     etype = getSpec(operandType(result));
7794
7795     /* read the first byte  */
7796     switch (ptype) {
7797
7798     case POINTER:
7799     case IPOINTER:
7800         pic14_emitcode("mov","a,@%s",rname);
7801         break;
7802         
7803     case PPOINTER:
7804         pic14_emitcode("movx","a,@%s",rname);
7805         break;
7806         
7807     case FPOINTER:
7808         pic14_emitcode("movx","a,@dptr");
7809         break;
7810
7811     case CPOINTER:
7812         pic14_emitcode("clr","a");
7813         pic14_emitcode("movc","a","@a+dptr");
7814         break;
7815
7816     case GPOINTER:
7817         pic14_emitcode("lcall","__gptrget");
7818         break;
7819     }
7820
7821     /* if we have bitdisplacement then it fits   */
7822     /* into this byte completely or if length is */
7823     /* less than a byte                          */
7824     if ((shCnt = SPEC_BSTR(etype)) || 
7825         (SPEC_BLEN(etype) <= 8))  {
7826
7827         /* shift right acc */
7828         AccRsh(shCnt);
7829
7830         pic14_emitcode("anl","a,#0x%02x",
7831                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7832         aopPut(AOP(result),"a",offset);
7833         return ;
7834     }
7835
7836     /* bit field did not fit in a byte  */
7837     rlen = SPEC_BLEN(etype) - 8;
7838     aopPut(AOP(result),"a",offset++);
7839
7840     while (1)  {
7841
7842         switch (ptype) {
7843         case POINTER:
7844         case IPOINTER:
7845             pic14_emitcode("inc","%s",rname);
7846             pic14_emitcode("mov","a,@%s",rname);
7847             break;
7848             
7849         case PPOINTER:
7850             pic14_emitcode("inc","%s",rname);
7851             pic14_emitcode("movx","a,@%s",rname);
7852             break;
7853
7854         case FPOINTER:
7855             pic14_emitcode("inc","dptr");
7856             pic14_emitcode("movx","a,@dptr");
7857             break;
7858             
7859         case CPOINTER:
7860             pic14_emitcode("clr","a");
7861             pic14_emitcode("inc","dptr");
7862             pic14_emitcode("movc","a","@a+dptr");
7863             break;
7864             
7865         case GPOINTER:
7866             pic14_emitcode("inc","dptr");
7867             pic14_emitcode("lcall","__gptrget");
7868             break;
7869         }
7870
7871         rlen -= 8;            
7872         /* if we are done */
7873         if ( rlen <= 0 )
7874             break ;
7875         
7876         aopPut(AOP(result),"a",offset++);
7877                               
7878     }
7879     
7880     if (rlen) {
7881         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7882         aopPut(AOP(result),"a",offset);        
7883     }
7884     
7885     return ;
7886 }
7887
7888
7889 /*-----------------------------------------------------------------*/
7890 /* genDataPointerGet - generates code when ptr offset is known     */
7891 /*-----------------------------------------------------------------*/
7892 static void genDataPointerGet (operand *left, 
7893                                operand *result, 
7894                                iCode *ic)
7895 {
7896   int size , offset = 0;
7897
7898
7899   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7900
7901
7902   /* optimization - most of the time, left and result are the same
7903    * address, but different types. for the pic code, we could omit
7904    * the following
7905    */
7906
7907   aopOp(result,ic,TRUE);
7908
7909   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7910
7911   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7912
7913   size = AOP_SIZE(result);
7914
7915   while (size--) {
7916     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7917     offset++;
7918   }
7919
7920   freeAsmop(left,NULL,ic,TRUE);
7921   freeAsmop(result,NULL,ic,TRUE);
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7926 /*-----------------------------------------------------------------*/
7927 static void genNearPointerGet (operand *left, 
7928                                operand *result, 
7929                                iCode *ic)
7930 {
7931     asmop *aop = NULL;
7932     regs *preg = NULL ;
7933     char *rname ;
7934     sym_link *rtype, *retype;
7935     sym_link *ltype = operandType(left);    
7936     char buffer[80];
7937
7938     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7939
7940     rtype = operandType(result);
7941     retype= getSpec(rtype);
7942     
7943     aopOp(left,ic,FALSE);
7944     
7945     /* if left is rematerialisable and
7946        result is not bit variable type and
7947        the left is pointer to data space i.e
7948        lower 128 bytes of space */
7949     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7950         !IS_BITVAR(retype)         &&
7951         DCL_TYPE(ltype) == POINTER) {
7952       //genDataPointerGet (left,result,ic);
7953         return ;
7954     }
7955     
7956     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957
7958         /* if the value is already in a pointer register
7959        then don't need anything more */
7960     if (!AOP_INPREG(AOP(left))) {
7961         /* otherwise get a free pointer register */
7962     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7963 /*
7964         aop = newAsmop(0);
7965         preg = getFreePtr(ic,&aop,FALSE);
7966         pic14_emitcode("mov","%s,%s",
7967                 preg->name,
7968                 aopGet(AOP(left),0,FALSE,TRUE));
7969         rname = preg->name ;
7970 */
7971     rname ="BAD";
7972     } else
7973         rname = aopGet(AOP(left),0,FALSE,FALSE);
7974     
7975     aopOp (result,ic,FALSE);
7976     
7977       /* if bitfield then unpack the bits */
7978     if (IS_BITVAR(retype)) 
7979         genUnpackBits (result,rname,POINTER);
7980     else {
7981         /* we have can just get the values */
7982       int size = AOP_SIZE(result);
7983       int offset = 0 ;  
7984         
7985       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7986
7987       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7988       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7989       while(size--) {
7990         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7991         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7992         if(size)
7993           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7994       }
7995 /*
7996         while (size--) {
7997             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7998
7999                 pic14_emitcode("mov","a,@%s",rname);
8000                 aopPut(AOP(result),"a",offset);
8001             } else {
8002                 sprintf(buffer,"@%s",rname);
8003                 aopPut(AOP(result),buffer,offset);
8004             }
8005             offset++ ;
8006             if (size)
8007                 pic14_emitcode("inc","%s",rname);
8008         }
8009 */
8010     }
8011
8012     /* now some housekeeping stuff */
8013     if (aop) {
8014         /* we had to allocate for this iCode */
8015     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8016         freeAsmop(NULL,aop,ic,TRUE);
8017     } else { 
8018         /* we did not allocate which means left
8019            already in a pointer register, then
8020            if size > 0 && this could be used again
8021            we have to point it back to where it 
8022            belongs */
8023     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8024         if (AOP_SIZE(result) > 1 &&
8025             !OP_SYMBOL(left)->remat &&
8026             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8027               ic->depth )) {
8028             int size = AOP_SIZE(result) - 1;
8029             while (size--)
8030                 pic14_emitcode("dec","%s",rname);
8031         }
8032     }
8033
8034     /* done */
8035     freeAsmop(left,NULL,ic,TRUE);
8036     freeAsmop(result,NULL,ic,TRUE);
8037      
8038 }
8039
8040 /*-----------------------------------------------------------------*/
8041 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8042 /*-----------------------------------------------------------------*/
8043 static void genPagedPointerGet (operand *left, 
8044                                operand *result, 
8045                                iCode *ic)
8046 {
8047     asmop *aop = NULL;
8048     regs *preg = NULL ;
8049     char *rname ;
8050     sym_link *rtype, *retype;    
8051
8052     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8053
8054     rtype = operandType(result);
8055     retype= getSpec(rtype);
8056     
8057     aopOp(left,ic,FALSE);
8058
8059   /* if the value is already in a pointer register
8060        then don't need anything more */
8061     if (!AOP_INPREG(AOP(left))) {
8062         /* otherwise get a free pointer register */
8063         aop = newAsmop(0);
8064         preg = getFreePtr(ic,&aop,FALSE);
8065         pic14_emitcode("mov","%s,%s",
8066                 preg->name,
8067                 aopGet(AOP(left),0,FALSE,TRUE));
8068         rname = preg->name ;
8069     } else
8070         rname = aopGet(AOP(left),0,FALSE,FALSE);
8071     
8072     freeAsmop(left,NULL,ic,TRUE);
8073     aopOp (result,ic,FALSE);
8074
8075     /* if bitfield then unpack the bits */
8076     if (IS_BITVAR(retype)) 
8077         genUnpackBits (result,rname,PPOINTER);
8078     else {
8079         /* we have can just get the values */
8080         int size = AOP_SIZE(result);
8081         int offset = 0 ;        
8082         
8083         while (size--) {
8084             
8085             pic14_emitcode("movx","a,@%s",rname);
8086             aopPut(AOP(result),"a",offset);
8087             
8088             offset++ ;
8089             
8090             if (size)
8091                 pic14_emitcode("inc","%s",rname);
8092         }
8093     }
8094
8095     /* now some housekeeping stuff */
8096     if (aop) {
8097         /* we had to allocate for this iCode */
8098         freeAsmop(NULL,aop,ic,TRUE);
8099     } else { 
8100         /* we did not allocate which means left
8101            already in a pointer register, then
8102            if size > 0 && this could be used again
8103            we have to point it back to where it 
8104            belongs */
8105         if (AOP_SIZE(result) > 1 &&
8106             !OP_SYMBOL(left)->remat &&
8107             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8108               ic->depth )) {
8109             int size = AOP_SIZE(result) - 1;
8110             while (size--)
8111                 pic14_emitcode("dec","%s",rname);
8112         }
8113     }
8114
8115     /* done */
8116     freeAsmop(result,NULL,ic,TRUE);
8117     
8118         
8119 }
8120
8121 /*-----------------------------------------------------------------*/
8122 /* genFarPointerGet - gget value from far space                    */
8123 /*-----------------------------------------------------------------*/
8124 static void genFarPointerGet (operand *left,
8125                               operand *result, iCode *ic)
8126 {
8127     int size, offset ;
8128     sym_link *retype = getSpec(operandType(result));
8129
8130     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8131
8132     aopOp(left,ic,FALSE);
8133
8134     /* if the operand is already in dptr 
8135     then we do nothing else we move the value to dptr */
8136     if (AOP_TYPE(left) != AOP_STR) {
8137         /* if this is remateriazable */
8138         if (AOP_TYPE(left) == AOP_IMMD)
8139             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8140         else { /* we need to get it byte by byte */
8141             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8142             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8143             if (options.model == MODEL_FLAT24)
8144             {
8145                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8146             }
8147         }
8148     }
8149     /* so dptr know contains the address */
8150     freeAsmop(left,NULL,ic,TRUE);
8151     aopOp(result,ic,FALSE);
8152
8153     /* if bit then unpack */
8154     if (IS_BITVAR(retype)) 
8155         genUnpackBits(result,"dptr",FPOINTER);
8156     else {
8157         size = AOP_SIZE(result);
8158         offset = 0 ;
8159
8160         while (size--) {
8161             pic14_emitcode("movx","a,@dptr");
8162             aopPut(AOP(result),"a",offset++);
8163             if (size)
8164                 pic14_emitcode("inc","dptr");
8165         }
8166     }
8167
8168     freeAsmop(result,NULL,ic,TRUE);
8169 }
8170 #if 0
8171 /*-----------------------------------------------------------------*/
8172 /* genCodePointerGet - get value from code space                  */
8173 /*-----------------------------------------------------------------*/
8174 static void genCodePointerGet (operand *left,
8175                                 operand *result, iCode *ic)
8176 {
8177     int size, offset ;
8178     sym_link *retype = getSpec(operandType(result));
8179
8180     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8181
8182     aopOp(left,ic,FALSE);
8183
8184     /* if the operand is already in dptr 
8185     then we do nothing else we move the value to dptr */
8186     if (AOP_TYPE(left) != AOP_STR) {
8187         /* if this is remateriazable */
8188         if (AOP_TYPE(left) == AOP_IMMD)
8189             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8190         else { /* we need to get it byte by byte */
8191             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8192             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8193             if (options.model == MODEL_FLAT24)
8194             {
8195                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8196             }
8197         }
8198     }
8199     /* so dptr know contains the address */
8200     freeAsmop(left,NULL,ic,TRUE);
8201     aopOp(result,ic,FALSE);
8202
8203     /* if bit then unpack */
8204     if (IS_BITVAR(retype)) 
8205         genUnpackBits(result,"dptr",CPOINTER);
8206     else {
8207         size = AOP_SIZE(result);
8208         offset = 0 ;
8209
8210         while (size--) {
8211             pic14_emitcode("clr","a");
8212             pic14_emitcode("movc","a,@a+dptr");
8213             aopPut(AOP(result),"a",offset++);
8214             if (size)
8215                 pic14_emitcode("inc","dptr");
8216         }
8217     }
8218
8219     freeAsmop(result,NULL,ic,TRUE);
8220 }
8221 #endif
8222 /*-----------------------------------------------------------------*/
8223 /* genGenPointerGet - gget value from generic pointer space        */
8224 /*-----------------------------------------------------------------*/
8225 static void genGenPointerGet (operand *left,
8226                               operand *result, iCode *ic)
8227 {
8228   int size, offset ;
8229   sym_link *retype = getSpec(operandType(result));
8230
8231   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8232   aopOp(left,ic,FALSE);
8233   aopOp(result,ic,FALSE);
8234
8235
8236   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8237
8238   /* if the operand is already in dptr 
8239      then we do nothing else we move the value to dptr */
8240   //  if (AOP_TYPE(left) != AOP_STR) {
8241     /* if this is remateriazable */
8242     if (AOP_TYPE(left) == AOP_IMMD) {
8243       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8244       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8245     }
8246     else { /* we need to get it byte by byte */
8247
8248       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8249       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8250
8251       size = AOP_SIZE(result);
8252       offset = 0 ;
8253
8254       while(size--) {
8255         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8256         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8257         if(size)
8258           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8259       }
8260       goto release;
8261     }
8262     //}
8263   /* so dptr know contains the address */
8264
8265   /* if bit then unpack */
8266   //if (IS_BITVAR(retype)) 
8267   //  genUnpackBits(result,"dptr",GPOINTER);
8268
8269  release:
8270   freeAsmop(left,NULL,ic,TRUE);
8271   freeAsmop(result,NULL,ic,TRUE);
8272
8273 }
8274
8275 /*-----------------------------------------------------------------*/
8276 /* genConstPointerGet - get value from const generic pointer space */
8277 /*-----------------------------------------------------------------*/
8278 static void genConstPointerGet (operand *left,
8279                                 operand *result, iCode *ic)
8280 {
8281   //sym_link *retype = getSpec(operandType(result));
8282   symbol *albl = newiTempLabel(NULL);
8283   symbol *blbl = newiTempLabel(NULL);
8284   PIC_OPCODE poc;
8285
8286   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8287   aopOp(left,ic,FALSE);
8288   aopOp(result,ic,FALSE);
8289
8290
8291   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8292
8293   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8294
8295   emitpcode(POC_CALL,popGetLabel(albl->key));
8296   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8297   emitpLabel(albl->key);
8298
8299   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8300     
8301   emitpcode(poc,popGet(AOP(left),1));
8302   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8303   emitpcode(poc,popGet(AOP(left),0));
8304   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8305
8306   emitpLabel(blbl->key);
8307
8308   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8309
8310
8311   freeAsmop(left,NULL,ic,TRUE);
8312   freeAsmop(result,NULL,ic,TRUE);
8313
8314 }
8315 /*-----------------------------------------------------------------*/
8316 /* genPointerGet - generate code for pointer get                   */
8317 /*-----------------------------------------------------------------*/
8318 static void genPointerGet (iCode *ic)
8319 {
8320     operand *left, *result ;
8321     sym_link *type, *etype;
8322     int p_type;
8323
8324     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8325
8326     left = IC_LEFT(ic);
8327     result = IC_RESULT(ic) ;
8328
8329     /* depending on the type of pointer we need to
8330     move it to the correct pointer register */
8331     type = operandType(left);
8332     etype = getSpec(type);
8333
8334     if (IS_PTR_CONST(type))
8335       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8336
8337     /* if left is of type of pointer then it is simple */
8338     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8339         p_type = DCL_TYPE(type);
8340     else {
8341         /* we have to go by the storage class */
8342         p_type = PTR_TYPE(SPEC_OCLS(etype));
8343
8344         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8345
8346         if (SPEC_OCLS(etype)->codesp ) {
8347           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8348           //p_type = CPOINTER ; 
8349         }
8350         else
8351             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8352               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8353                /*p_type = FPOINTER ;*/ 
8354             else
8355                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8356                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8357 /*                  p_type = PPOINTER; */
8358                 else
8359                     if (SPEC_OCLS(etype) == idata )
8360                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8361 /*                      p_type = IPOINTER; */
8362                     else
8363                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8364 /*                      p_type = POINTER ; */
8365     }
8366
8367     /* now that we have the pointer type we assign
8368     the pointer values */
8369     switch (p_type) {
8370
8371     case POINTER:       
8372     case IPOINTER:
8373         genNearPointerGet (left,result,ic);
8374         break;
8375
8376     case PPOINTER:
8377         genPagedPointerGet(left,result,ic);
8378         break;
8379
8380     case FPOINTER:
8381         genFarPointerGet (left,result,ic);
8382         break;
8383
8384     case CPOINTER:
8385         genConstPointerGet (left,result,ic);
8386         //pic14_emitcodePointerGet (left,result,ic);
8387         break;
8388
8389     case GPOINTER:
8390       if (IS_PTR_CONST(type))
8391         genConstPointerGet (left,result,ic);
8392       else
8393         genGenPointerGet (left,result,ic);
8394       break;
8395     }
8396
8397 }
8398
8399 /*-----------------------------------------------------------------*/
8400 /* genPackBits - generates code for packed bit storage             */
8401 /*-----------------------------------------------------------------*/
8402 static void genPackBits (sym_link    *etype ,
8403                          operand *right ,
8404                          char *rname, int p_type)
8405 {
8406     int shCount = 0 ;
8407     int offset = 0  ;
8408     int rLen = 0 ;
8409     int blen, bstr ;   
8410     char *l ;
8411
8412     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8413     blen = SPEC_BLEN(etype);
8414     bstr = SPEC_BSTR(etype);
8415
8416     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8417     MOVA(l);   
8418
8419     /* if the bit lenth is less than or    */
8420     /* it exactly fits a byte then         */
8421     if (SPEC_BLEN(etype) <= 8 )  {
8422         shCount = SPEC_BSTR(etype) ;
8423
8424         /* shift left acc */
8425         AccLsh(shCount);
8426
8427         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8428
8429
8430             switch (p_type) {
8431                 case POINTER:
8432                     pic14_emitcode ("mov","b,a");
8433                     pic14_emitcode("mov","a,@%s",rname);
8434                     break;
8435
8436                 case FPOINTER:
8437                     pic14_emitcode ("mov","b,a");
8438                     pic14_emitcode("movx","a,@dptr");
8439                     break;
8440
8441                 case GPOINTER:
8442                     pic14_emitcode ("push","b");
8443                     pic14_emitcode ("push","acc");
8444                     pic14_emitcode ("lcall","__gptrget");
8445                     pic14_emitcode ("pop","b");
8446                     break;
8447             }
8448
8449             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8450                       ((unsigned char)(0xFF << (blen+bstr)) | 
8451                        (unsigned char)(0xFF >> (8-bstr)) ) );
8452             pic14_emitcode ("orl","a,b");
8453             if (p_type == GPOINTER)
8454                 pic14_emitcode("pop","b");
8455         }
8456     }
8457
8458     switch (p_type) {
8459         case POINTER:
8460             pic14_emitcode("mov","@%s,a",rname);
8461             break;
8462
8463         case FPOINTER:
8464             pic14_emitcode("movx","@dptr,a");
8465             break;
8466
8467         case GPOINTER:
8468             DEBUGpic14_emitcode(";lcall","__gptrput");
8469             break;
8470     }
8471
8472     /* if we r done */
8473     if ( SPEC_BLEN(etype) <= 8 )
8474         return ;
8475
8476     pic14_emitcode("inc","%s",rname);
8477     rLen = SPEC_BLEN(etype) ;     
8478
8479     /* now generate for lengths greater than one byte */
8480     while (1) {
8481
8482         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8483
8484         rLen -= 8 ;
8485         if (rLen <= 0 )
8486             break ;
8487
8488         switch (p_type) {
8489             case POINTER:
8490                 if (*l == '@') {
8491                     MOVA(l);
8492                     pic14_emitcode("mov","@%s,a",rname);
8493                 } else
8494                     pic14_emitcode("mov","@%s,%s",rname,l);
8495                 break;
8496
8497             case FPOINTER:
8498                 MOVA(l);
8499                 pic14_emitcode("movx","@dptr,a");
8500                 break;
8501
8502             case GPOINTER:
8503                 MOVA(l);
8504                 DEBUGpic14_emitcode(";lcall","__gptrput");
8505                 break;  
8506         }   
8507         pic14_emitcode ("inc","%s",rname);
8508     }
8509
8510     MOVA(l);
8511
8512     /* last last was not complete */
8513     if (rLen)   {
8514         /* save the byte & read byte */
8515         switch (p_type) {
8516             case POINTER:
8517                 pic14_emitcode ("mov","b,a");
8518                 pic14_emitcode("mov","a,@%s",rname);
8519                 break;
8520
8521             case FPOINTER:
8522                 pic14_emitcode ("mov","b,a");
8523                 pic14_emitcode("movx","a,@dptr");
8524                 break;
8525
8526             case GPOINTER:
8527                 pic14_emitcode ("push","b");
8528                 pic14_emitcode ("push","acc");
8529                 pic14_emitcode ("lcall","__gptrget");
8530                 pic14_emitcode ("pop","b");
8531                 break;
8532         }
8533
8534         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8535         pic14_emitcode ("orl","a,b");
8536     }
8537
8538     if (p_type == GPOINTER)
8539         pic14_emitcode("pop","b");
8540
8541     switch (p_type) {
8542
8543     case POINTER:
8544         pic14_emitcode("mov","@%s,a",rname);
8545         break;
8546         
8547     case FPOINTER:
8548         pic14_emitcode("movx","@dptr,a");
8549         break;
8550         
8551     case GPOINTER:
8552         DEBUGpic14_emitcode(";lcall","__gptrput");
8553         break;                  
8554     }
8555 }
8556 /*-----------------------------------------------------------------*/
8557 /* genDataPointerSet - remat pointer to data space                 */
8558 /*-----------------------------------------------------------------*/
8559 static void genDataPointerSet(operand *right,
8560                               operand *result,
8561                               iCode *ic)
8562 {
8563     int size, offset = 0 ;
8564     char *l, buffer[256];
8565
8566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8567     aopOp(right,ic,FALSE);
8568     
8569     l = aopGet(AOP(result),0,FALSE,TRUE);
8570     size = AOP_SIZE(right);
8571 /*
8572     if ( AOP_TYPE(result) == AOP_PCODE) {
8573       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8574               AOP(result)->aopu.pcop->name,
8575               PCOI(AOP(result)->aopu.pcop)->offset);
8576     }
8577 */
8578
8579     // tsd, was l+1 - the underline `_' prefix was being stripped
8580     while (size--) {
8581       if (offset) {
8582         sprintf(buffer,"(%s + %d)",l,offset);
8583         fprintf(stderr,"oops  %s\n",buffer);
8584       } else
8585         sprintf(buffer,"%s",l);
8586
8587         if (AOP_TYPE(right) == AOP_LIT) {
8588           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8589           lit = lit >> (8*offset);
8590           if(lit&0xff) {
8591             pic14_emitcode("movlw","%d",lit);
8592             pic14_emitcode("movwf","%s",buffer);
8593
8594             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8595             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8596             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8597
8598           } else {
8599             pic14_emitcode("clrf","%s",buffer);
8600             //emitpcode(POC_CLRF, popRegFromString(buffer));
8601             emitpcode(POC_CLRF, popGet(AOP(result),0));
8602           }
8603         }else {
8604           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8605           pic14_emitcode("movwf","%s",buffer);
8606
8607           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8608           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8609           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8610
8611         }
8612
8613         offset++;
8614     }
8615
8616     freeAsmop(right,NULL,ic,TRUE);
8617     freeAsmop(result,NULL,ic,TRUE);
8618 }
8619
8620 /*-----------------------------------------------------------------*/
8621 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8622 /*-----------------------------------------------------------------*/
8623 static void genNearPointerSet (operand *right,
8624                                operand *result, 
8625                                iCode *ic)
8626 {
8627   asmop *aop = NULL;
8628   char *l;
8629   sym_link *retype;
8630   sym_link *ptype = operandType(result);
8631
8632     
8633   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8634   retype= getSpec(operandType(right));
8635
8636   aopOp(result,ic,FALSE);
8637
8638     
8639   /* if the result is rematerializable &
8640      in data space & not a bit variable */
8641   //if (AOP_TYPE(result) == AOP_IMMD &&
8642   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8643       DCL_TYPE(ptype) == POINTER   &&
8644       !IS_BITVAR(retype)) {
8645     genDataPointerSet (right,result,ic);
8646     freeAsmop(result,NULL,ic,TRUE);
8647     return;
8648   }
8649
8650   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8651   aopOp(right,ic,FALSE);
8652   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8653
8654   /* if the value is already in a pointer register
8655      then don't need anything more */
8656   if (!AOP_INPREG(AOP(result))) {
8657     /* otherwise get a free pointer register */
8658     //aop = newAsmop(0);
8659     //preg = getFreePtr(ic,&aop,FALSE);
8660     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8661     //pic14_emitcode("mov","%s,%s",
8662     //         preg->name,
8663     //         aopGet(AOP(result),0,FALSE,TRUE));
8664     //rname = preg->name ;
8665     //pic14_emitcode("movwf","fsr");
8666     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8667     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8668     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8669     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8670     goto release;
8671
8672   }// else
8673   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8674
8675
8676   /* if bitfield then unpack the bits */
8677   if (IS_BITVAR(retype)) {
8678     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8679            "The programmer is obviously confused");
8680     //genPackBits (retype,right,rname,POINTER);
8681     exit(1);
8682   }
8683   else {
8684     /* we have can just get the values */
8685     int size = AOP_SIZE(right);
8686     int offset = 0 ;    
8687
8688     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8689     while (size--) {
8690       l = aopGet(AOP(right),offset,FALSE,TRUE);
8691       if (*l == '@' ) {
8692         //MOVA(l);
8693         //pic14_emitcode("mov","@%s,a",rname);
8694         pic14_emitcode("movf","indf,w ;1");
8695       } else {
8696
8697         if (AOP_TYPE(right) == AOP_LIT) {
8698           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8699           if(lit) {
8700             pic14_emitcode("movlw","%s",l);
8701             pic14_emitcode("movwf","indf ;2");
8702           } else 
8703             pic14_emitcode("clrf","indf");
8704         }else {
8705           pic14_emitcode("movf","%s,w",l);
8706           pic14_emitcode("movwf","indf ;2");
8707         }
8708         //pic14_emitcode("mov","@%s,%s",rname,l);
8709       }
8710       if (size)
8711         pic14_emitcode("incf","fsr,f ;3");
8712       //pic14_emitcode("inc","%s",rname);
8713       offset++;
8714     }
8715   }
8716
8717   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8718   /* now some housekeeping stuff */
8719   if (aop) {
8720     /* we had to allocate for this iCode */
8721     freeAsmop(NULL,aop,ic,TRUE);
8722   } else { 
8723     /* we did not allocate which means left
8724        already in a pointer register, then
8725        if size > 0 && this could be used again
8726        we have to point it back to where it 
8727        belongs */
8728     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8729     if (AOP_SIZE(right) > 1 &&
8730         !OP_SYMBOL(result)->remat &&
8731         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8732           ic->depth )) {
8733       int size = AOP_SIZE(right) - 1;
8734       while (size--)
8735         pic14_emitcode("decf","fsr,f");
8736       //pic14_emitcode("dec","%s",rname);
8737     }
8738   }
8739
8740   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741   /* done */
8742  release:
8743   freeAsmop(right,NULL,ic,TRUE);
8744   freeAsmop(result,NULL,ic,TRUE);
8745 }
8746
8747 /*-----------------------------------------------------------------*/
8748 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8749 /*-----------------------------------------------------------------*/
8750 static void genPagedPointerSet (operand *right,
8751                                operand *result, 
8752                                iCode *ic)
8753 {
8754     asmop *aop = NULL;
8755     regs *preg = NULL ;
8756     char *rname , *l;
8757     sym_link *retype;
8758        
8759     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760
8761     retype= getSpec(operandType(right));
8762     
8763     aopOp(result,ic,FALSE);
8764     
8765     /* if the value is already in a pointer register
8766        then don't need anything more */
8767     if (!AOP_INPREG(AOP(result))) {
8768         /* otherwise get a free pointer register */
8769         aop = newAsmop(0);
8770         preg = getFreePtr(ic,&aop,FALSE);
8771         pic14_emitcode("mov","%s,%s",
8772                 preg->name,
8773                 aopGet(AOP(result),0,FALSE,TRUE));
8774         rname = preg->name ;
8775     } else
8776         rname = aopGet(AOP(result),0,FALSE,FALSE);
8777     
8778     freeAsmop(result,NULL,ic,TRUE);
8779     aopOp (right,ic,FALSE);
8780
8781     /* if bitfield then unpack the bits */
8782     if (IS_BITVAR(retype)) 
8783         genPackBits (retype,right,rname,PPOINTER);
8784     else {
8785         /* we have can just get the values */
8786         int size = AOP_SIZE(right);
8787         int offset = 0 ;        
8788         
8789         while (size--) {
8790             l = aopGet(AOP(right),offset,FALSE,TRUE);
8791             
8792             MOVA(l);
8793             pic14_emitcode("movx","@%s,a",rname);
8794
8795             if (size)
8796                 pic14_emitcode("inc","%s",rname);
8797
8798             offset++;
8799         }
8800     }
8801     
8802     /* now some housekeeping stuff */
8803     if (aop) {
8804         /* we had to allocate for this iCode */
8805         freeAsmop(NULL,aop,ic,TRUE);
8806     } else { 
8807         /* we did not allocate which means left
8808            already in a pointer register, then
8809            if size > 0 && this could be used again
8810            we have to point it back to where it 
8811            belongs */
8812         if (AOP_SIZE(right) > 1 &&
8813             !OP_SYMBOL(result)->remat &&
8814             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8815               ic->depth )) {
8816             int size = AOP_SIZE(right) - 1;
8817             while (size--)
8818                 pic14_emitcode("dec","%s",rname);
8819         }
8820     }
8821
8822     /* done */
8823     freeAsmop(right,NULL,ic,TRUE);
8824     
8825         
8826 }
8827
8828 /*-----------------------------------------------------------------*/
8829 /* genFarPointerSet - set value from far space                     */
8830 /*-----------------------------------------------------------------*/
8831 static void genFarPointerSet (operand *right,
8832                               operand *result, iCode *ic)
8833 {
8834     int size, offset ;
8835     sym_link *retype = getSpec(operandType(right));
8836
8837     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838     aopOp(result,ic,FALSE);
8839
8840     /* if the operand is already in dptr 
8841     then we do nothing else we move the value to dptr */
8842     if (AOP_TYPE(result) != AOP_STR) {
8843         /* if this is remateriazable */
8844         if (AOP_TYPE(result) == AOP_IMMD)
8845             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8846         else { /* we need to get it byte by byte */
8847             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8848             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8849             if (options.model == MODEL_FLAT24)
8850             {
8851                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8852             }
8853         }
8854     }
8855     /* so dptr know contains the address */
8856     freeAsmop(result,NULL,ic,TRUE);
8857     aopOp(right,ic,FALSE);
8858
8859     /* if bit then unpack */
8860     if (IS_BITVAR(retype)) 
8861         genPackBits(retype,right,"dptr",FPOINTER);
8862     else {
8863         size = AOP_SIZE(right);
8864         offset = 0 ;
8865
8866         while (size--) {
8867             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8868             MOVA(l);
8869             pic14_emitcode("movx","@dptr,a");
8870             if (size)
8871                 pic14_emitcode("inc","dptr");
8872         }
8873     }
8874
8875     freeAsmop(right,NULL,ic,TRUE);
8876 }
8877
8878 /*-----------------------------------------------------------------*/
8879 /* genGenPointerSet - set value from generic pointer space         */
8880 /*-----------------------------------------------------------------*/
8881 static void genGenPointerSet (operand *right,
8882                               operand *result, iCode *ic)
8883 {
8884   int size, offset ;
8885   sym_link *retype = getSpec(operandType(right));
8886
8887   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888
8889   aopOp(result,ic,FALSE);
8890   aopOp(right,ic,FALSE);
8891   size = AOP_SIZE(right);
8892
8893   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8894
8895   /* if the operand is already in dptr 
8896      then we do nothing else we move the value to dptr */
8897   if (AOP_TYPE(result) != AOP_STR) {
8898     /* if this is remateriazable */
8899     if (AOP_TYPE(result) == AOP_IMMD) {
8900       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8901       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8902     }
8903     else { /* we need to get it byte by byte */
8904       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8905       size = AOP_SIZE(right);
8906       offset = 0 ;
8907
8908       /* hack hack! see if this the FSR. If so don't load W */
8909       if(AOP_TYPE(right) != AOP_ACC) {
8910
8911         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8912         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8913
8914         //if(size==2)
8915         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8916         //if(size==4) {
8917         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8918         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8919         //}
8920
8921         while(size--) {
8922           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8923           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8924           
8925           if(size)
8926             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8927         }
8928
8929
8930         goto release;
8931       } 
8932
8933       if(aopIdx(AOP(result),0) != 4) {
8934
8935         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8936         goto release;
8937       }
8938
8939       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8940       goto release;
8941
8942     }
8943   }
8944   /* so dptr know contains the address */
8945
8946
8947   /* if bit then unpack */
8948   if (IS_BITVAR(retype)) 
8949     genPackBits(retype,right,"dptr",GPOINTER);
8950   else {
8951     size = AOP_SIZE(right);
8952     offset = 0 ;
8953
8954   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8955
8956     while (size--) {
8957
8958       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8959       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8960
8961       if (AOP_TYPE(right) == AOP_LIT) 
8962         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8963       else
8964         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8965
8966       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8967
8968       offset++;
8969     }
8970   }
8971
8972  release:
8973   freeAsmop(right,NULL,ic,TRUE);
8974   freeAsmop(result,NULL,ic,TRUE);
8975 }
8976
8977 /*-----------------------------------------------------------------*/
8978 /* genPointerSet - stores the value into a pointer location        */
8979 /*-----------------------------------------------------------------*/
8980 static void genPointerSet (iCode *ic)
8981 {    
8982     operand *right, *result ;
8983     sym_link *type, *etype;
8984     int p_type;
8985
8986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8987
8988     right = IC_RIGHT(ic);
8989     result = IC_RESULT(ic) ;
8990
8991     /* depending on the type of pointer we need to
8992     move it to the correct pointer register */
8993     type = operandType(result);
8994     etype = getSpec(type);
8995     /* if left is of type of pointer then it is simple */
8996     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8997         p_type = DCL_TYPE(type);
8998     }
8999     else {
9000         /* we have to go by the storage class */
9001         p_type = PTR_TYPE(SPEC_OCLS(etype));
9002
9003 /*      if (SPEC_OCLS(etype)->codesp ) { */
9004 /*          p_type = CPOINTER ;  */
9005 /*      } */
9006 /*      else */
9007 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9008 /*              p_type = FPOINTER ; */
9009 /*          else */
9010 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9011 /*                  p_type = PPOINTER ; */
9012 /*              else */
9013 /*                  if (SPEC_OCLS(etype) == idata ) */
9014 /*                      p_type = IPOINTER ; */
9015 /*                  else */
9016 /*                      p_type = POINTER ; */
9017     }
9018
9019     /* now that we have the pointer type we assign
9020     the pointer values */
9021     switch (p_type) {
9022
9023     case POINTER:
9024     case IPOINTER:
9025         genNearPointerSet (right,result,ic);
9026         break;
9027
9028     case PPOINTER:
9029         genPagedPointerSet (right,result,ic);
9030         break;
9031
9032     case FPOINTER:
9033         genFarPointerSet (right,result,ic);
9034         break;
9035
9036     case GPOINTER:
9037         genGenPointerSet (right,result,ic);
9038         break;
9039
9040     default:
9041       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9042               "genPointerSet: illegal pointer type");
9043     }
9044 }
9045
9046 /*-----------------------------------------------------------------*/
9047 /* genIfx - generate code for Ifx statement                        */
9048 /*-----------------------------------------------------------------*/
9049 static void genIfx (iCode *ic, iCode *popIc)
9050 {
9051   operand *cond = IC_COND(ic);
9052   int isbit =0;
9053
9054   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9055
9056   aopOp(cond,ic,FALSE);
9057
9058   /* get the value into acc */
9059   if (AOP_TYPE(cond) != AOP_CRY)
9060     pic14_toBoolean(cond);
9061   else
9062     isbit = 1;
9063   /* the result is now in the accumulator */
9064   freeAsmop(cond,NULL,ic,TRUE);
9065
9066   /* if there was something to be popped then do it */
9067   if (popIc)
9068     genIpop(popIc);
9069
9070   /* if the condition is  a bit variable */
9071   if (isbit && IS_ITEMP(cond) && 
9072       SPIL_LOC(cond)) {
9073     genIfxJump(ic,SPIL_LOC(cond)->rname);
9074     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9075   }
9076   else {
9077     if (isbit && !IS_ITEMP(cond))
9078       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9079     else
9080       genIfxJump(ic,"a");
9081   }
9082   ic->generated = 1;
9083
9084 }
9085
9086 /*-----------------------------------------------------------------*/
9087 /* genAddrOf - generates code for address of                       */
9088 /*-----------------------------------------------------------------*/
9089 static void genAddrOf (iCode *ic)
9090 {
9091   operand *right, *result, *left;
9092   int size, offset ;
9093
9094   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9095
9096
9097   //aopOp(IC_RESULT(ic),ic,FALSE);
9098
9099   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9100   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9101   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9102
9103   DEBUGpic14_AopType(__LINE__,left,right,result);
9104
9105   size = AOP_SIZE(IC_RESULT(ic));
9106   offset = 0;
9107
9108   while (size--) {
9109     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9110     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9111     offset++;
9112   }
9113
9114   freeAsmop(left,NULL,ic,FALSE);
9115   freeAsmop(result,NULL,ic,TRUE);
9116
9117 }
9118
9119 #if 0
9120 /*-----------------------------------------------------------------*/
9121 /* genFarFarAssign - assignment when both are in far space         */
9122 /*-----------------------------------------------------------------*/
9123 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9124 {
9125     int size = AOP_SIZE(right);
9126     int offset = 0;
9127     char *l ;
9128     /* first push the right side on to the stack */
9129     while (size--) {
9130         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9131         MOVA(l);
9132         pic14_emitcode ("push","acc");
9133     }
9134     
9135     freeAsmop(right,NULL,ic,FALSE);
9136     /* now assign DPTR to result */
9137     aopOp(result,ic,FALSE);
9138     size = AOP_SIZE(result);
9139     while (size--) {
9140         pic14_emitcode ("pop","acc");
9141         aopPut(AOP(result),"a",--offset);
9142     }
9143     freeAsmop(result,NULL,ic,FALSE);
9144         
9145 }
9146 #endif
9147
9148 /*-----------------------------------------------------------------*/
9149 /* genAssign - generate code for assignment                        */
9150 /*-----------------------------------------------------------------*/
9151 static void genAssign (iCode *ic)
9152 {
9153   operand *result, *right;
9154   int size, offset,know_W;
9155   unsigned long lit = 0L;
9156
9157   result = IC_RESULT(ic);
9158   right  = IC_RIGHT(ic) ;
9159
9160   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9161
9162   /* if they are the same */
9163   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9164     return ;
9165
9166   aopOp(right,ic,FALSE);
9167   aopOp(result,ic,TRUE);
9168
9169   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9170
9171   /* if they are the same registers */
9172   if (pic14_sameRegs(AOP(right),AOP(result)))
9173     goto release;
9174
9175   /* if the result is a bit */
9176   if (AOP_TYPE(result) == AOP_CRY) {
9177
9178     /* if the right size is a literal then
9179        we know what the value is */
9180     if (AOP_TYPE(right) == AOP_LIT) {
9181           
9182       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9183                   popGet(AOP(result),0));
9184
9185       if (((int) operandLitValue(right))) 
9186         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9187                        AOP(result)->aopu.aop_dir,
9188                        AOP(result)->aopu.aop_dir);
9189       else
9190         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9191                        AOP(result)->aopu.aop_dir,
9192                        AOP(result)->aopu.aop_dir);
9193       goto release;
9194     }
9195
9196     /* the right is also a bit variable */
9197     if (AOP_TYPE(right) == AOP_CRY) {
9198       emitpcode(POC_BCF,    popGet(AOP(result),0));
9199       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9200       emitpcode(POC_BSF,    popGet(AOP(result),0));
9201
9202       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9203                      AOP(result)->aopu.aop_dir,
9204                      AOP(result)->aopu.aop_dir);
9205       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9206                      AOP(right)->aopu.aop_dir,
9207                      AOP(right)->aopu.aop_dir);
9208       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9209                      AOP(result)->aopu.aop_dir,
9210                      AOP(result)->aopu.aop_dir);
9211       goto release ;
9212     }
9213
9214     /* we need to or */
9215     emitpcode(POC_BCF,    popGet(AOP(result),0));
9216     pic14_toBoolean(right);
9217     emitSKPZ;
9218     emitpcode(POC_BSF,    popGet(AOP(result),0));
9219     //aopPut(AOP(result),"a",0);
9220     goto release ;
9221   }
9222
9223   /* bit variables done */
9224   /* general case */
9225   size = AOP_SIZE(result);
9226   offset = 0 ;
9227   if(AOP_TYPE(right) == AOP_LIT)
9228     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9229
9230   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9231   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9232     if(aopIdx(AOP(result),0) == 4) {
9233   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9234       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9235       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9236       goto release;
9237     } else
9238       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9239   }
9240
9241   know_W=-1;
9242   while (size--) {
9243   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9244     if(AOP_TYPE(right) == AOP_LIT) {
9245       if(lit&0xff) {
9246         if(know_W != (lit&0xff))
9247           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9248         know_W = lit&0xff;
9249         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9250       } else
9251         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9252
9253       lit >>= 8;
9254
9255     } else if (AOP_TYPE(right) == AOP_CRY) {
9256       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9257       if(offset == 0) {
9258         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9259         emitpcode(POC_INCF, popGet(AOP(result),0));
9260       }
9261     } else {
9262   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9263       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9264       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9265     }
9266             
9267     offset++;
9268   }
9269
9270     
9271  release:
9272   freeAsmop (right,NULL,ic,FALSE);
9273   freeAsmop (result,NULL,ic,TRUE);
9274 }   
9275
9276 /*-----------------------------------------------------------------*/
9277 /* genJumpTab - genrates code for jump table                       */
9278 /*-----------------------------------------------------------------*/
9279 static void genJumpTab (iCode *ic)
9280 {
9281     symbol *jtab;
9282     char *l;
9283
9284     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9285
9286     aopOp(IC_JTCOND(ic),ic,FALSE);
9287     /* get the condition into accumulator */
9288     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9289     MOVA(l);
9290     /* multiply by three */
9291     pic14_emitcode("add","a,acc");
9292     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9293
9294     jtab = newiTempLabel(NULL);
9295     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9296     pic14_emitcode("jmp","@a+dptr");
9297     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9298
9299     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9300     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9301     emitSKPNC;
9302     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9303     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9304     emitpLabel(jtab->key);
9305
9306     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9307
9308     /* now generate the jump labels */
9309     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9310          jtab = setNextItem(IC_JTLABELS(ic))) {
9311         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9312         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9313         
9314     }
9315
9316 }
9317
9318 /*-----------------------------------------------------------------*/
9319 /* genMixedOperation - gen code for operators between mixed types  */
9320 /*-----------------------------------------------------------------*/
9321 /*
9322   TSD - Written for the PIC port - but this unfortunately is buggy.
9323   This routine is good in that it is able to efficiently promote 
9324   types to different (larger) sizes. Unfortunately, the temporary
9325   variables that are optimized out by this routine are sometimes
9326   used in other places. So until I know how to really parse the 
9327   iCode tree, I'm going to not be using this routine :(.
9328 */
9329 static int genMixedOperation (iCode *ic)
9330 {
9331 #if 0
9332   operand *result = IC_RESULT(ic);
9333   sym_link *ctype = operandType(IC_LEFT(ic));
9334   operand *right = IC_RIGHT(ic);
9335   int ret = 0;
9336   int big,small;
9337   int offset;
9338
9339   iCode *nextic;
9340   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9341
9342   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9343
9344   nextic = ic->next;
9345   if(!nextic)
9346     return 0;
9347
9348   nextright = IC_RIGHT(nextic);
9349   nextleft  = IC_LEFT(nextic);
9350   nextresult = IC_RESULT(nextic);
9351
9352   aopOp(right,ic,FALSE);
9353   aopOp(result,ic,FALSE);
9354   aopOp(nextright,  nextic, FALSE);
9355   aopOp(nextleft,   nextic, FALSE);
9356   aopOp(nextresult, nextic, FALSE);
9357
9358   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9359
9360     operand *t = right;
9361     right = nextright;
9362     nextright = t; 
9363
9364     pic14_emitcode(";remove right +","");
9365
9366   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9367 /*
9368     operand *t = right;
9369     right = nextleft;
9370     nextleft = t; 
9371 */
9372     pic14_emitcode(";remove left +","");
9373   } else
9374     return 0;
9375
9376   big = AOP_SIZE(nextleft);
9377   small = AOP_SIZE(nextright);
9378
9379   switch(nextic->op) {
9380
9381   case '+':
9382     pic14_emitcode(";optimize a +","");
9383     /* if unsigned or not an integral type */
9384     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9385       pic14_emitcode(";add a bit to something","");
9386     } else {
9387
9388       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9389
9390       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9391         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9392         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9393       } else
9394         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9395
9396       offset = 0;
9397       while(--big) {
9398
9399         offset++;
9400
9401         if(--small) {
9402           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9403             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9404             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9405           }
9406
9407           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9408           emitSKPNC;
9409           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9410                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9411                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9412           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9413           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9414
9415         } else {
9416           pic14_emitcode("rlf","known_zero,w");
9417
9418           /*
9419             if right is signed
9420               btfsc  right,7
9421                addlw ff
9422           */
9423           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9424             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9425             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9426           } else {
9427             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9428           }
9429         }
9430       }
9431       ret = 1;
9432     }
9433   }
9434   ret = 1;
9435
9436 release:
9437   freeAsmop(right,NULL,ic,TRUE);
9438   freeAsmop(result,NULL,ic,TRUE);
9439   freeAsmop(nextright,NULL,ic,TRUE);
9440   freeAsmop(nextleft,NULL,ic,TRUE);
9441   if(ret)
9442     nextic->generated = 1;
9443
9444   return ret;
9445 #else
9446   return 0;
9447 #endif
9448 }
9449 /*-----------------------------------------------------------------*/
9450 /* genCast - gen code for casting                                  */
9451 /*-----------------------------------------------------------------*/
9452 static void genCast (iCode *ic)
9453 {
9454     operand *result = IC_RESULT(ic);
9455     sym_link *ctype = operandType(IC_LEFT(ic));
9456     sym_link *rtype = operandType(IC_RIGHT(ic));
9457     operand *right = IC_RIGHT(ic);
9458     int size, offset ;
9459
9460     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9461     /* if they are equivalent then do nothing */
9462     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9463         return ;
9464
9465     aopOp(right,ic,FALSE) ;
9466     aopOp(result,ic,FALSE);
9467
9468     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9469
9470     /* if the result is a bit */
9471     if (AOP_TYPE(result) == AOP_CRY) {
9472         /* if the right size is a literal then
9473         we know what the value is */
9474       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9475         if (AOP_TYPE(right) == AOP_LIT) {
9476
9477           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9478                       popGet(AOP(result),0));
9479
9480             if (((int) operandLitValue(right))) 
9481               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9482                        AOP(result)->aopu.aop_dir,
9483                        AOP(result)->aopu.aop_dir);
9484             else
9485               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9486                        AOP(result)->aopu.aop_dir,
9487                        AOP(result)->aopu.aop_dir);
9488
9489             goto release;
9490         }
9491
9492         /* the right is also a bit variable */
9493         if (AOP_TYPE(right) == AOP_CRY) {
9494
9495           emitCLRC;
9496           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9497
9498           pic14_emitcode("clrc","");
9499           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9500                    AOP(right)->aopu.aop_dir,
9501                    AOP(right)->aopu.aop_dir);
9502             aopPut(AOP(result),"c",0);
9503             goto release ;
9504         }
9505
9506         /* we need to or */
9507         if (AOP_TYPE(right) == AOP_REG) {
9508           emitpcode(POC_BCF,    popGet(AOP(result),0));
9509           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9510           emitpcode(POC_BSF,    popGet(AOP(result),0));
9511         }
9512         pic14_toBoolean(right);
9513         aopPut(AOP(result),"a",0);
9514         goto release ;
9515     }
9516
9517     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9518       int offset = 1;
9519       size = AOP_SIZE(result);
9520
9521       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9522
9523       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9524       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9525       emitpcode(POC_INCF,   popGet(AOP(result),0));
9526
9527       while (size--)
9528         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9529
9530       goto release;
9531     }
9532
9533     /* if they are the same size : or less */
9534     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9535
9536         /* if they are in the same place */
9537       if (pic14_sameRegs(AOP(right),AOP(result)))
9538         goto release;
9539
9540       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9541       if (IS_PTR_CONST(rtype))
9542         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9543       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9544         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9545
9546       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9547         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9548         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9549         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9550         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9551         if(AOP_SIZE(result) <2)
9552           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9553
9554       } else {
9555
9556         /* if they in different places then copy */
9557         size = AOP_SIZE(result);
9558         offset = 0 ;
9559         while (size--) {
9560           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9561           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9562
9563           //aopPut(AOP(result),
9564           // aopGet(AOP(right),offset,FALSE,FALSE),
9565           // offset);
9566
9567           offset++;
9568         }
9569       }
9570       goto release;
9571     }
9572
9573
9574     /* if the result is of type pointer */
9575     if (IS_PTR(ctype)) {
9576
9577         int p_type;
9578         sym_link *type = operandType(right);
9579         sym_link *etype = getSpec(type);
9580       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9581
9582         /* pointer to generic pointer */
9583         if (IS_GENPTR(ctype)) {
9584             char *l = zero;
9585             
9586             if (IS_PTR(type)) 
9587                 p_type = DCL_TYPE(type);
9588             else {
9589                 /* we have to go by the storage class */
9590                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9591
9592 /*              if (SPEC_OCLS(etype)->codesp )  */
9593 /*                  p_type = CPOINTER ;  */
9594 /*              else */
9595 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9596 /*                      p_type = FPOINTER ; */
9597 /*                  else */
9598 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9599 /*                          p_type = PPOINTER; */
9600 /*                      else */
9601 /*                          if (SPEC_OCLS(etype) == idata ) */
9602 /*                              p_type = IPOINTER ; */
9603 /*                          else */
9604 /*                              p_type = POINTER ; */
9605             }
9606                 
9607             /* the first two bytes are known */
9608       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9609             size = GPTRSIZE - 1; 
9610             offset = 0 ;
9611             while (size--) {
9612               if(offset < AOP_SIZE(right)) {
9613       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9614                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9615                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9616                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9617                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9618                 } else { 
9619                   aopPut(AOP(result),
9620                          aopGet(AOP(right),offset,FALSE,FALSE),
9621                          offset);
9622                 }
9623               } else 
9624                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9625               offset++;
9626             }
9627             /* the last byte depending on type */
9628             switch (p_type) {
9629             case IPOINTER:
9630             case POINTER:
9631                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9632                 break;
9633             case FPOINTER:
9634               pic14_emitcode(";BUG!? ","%d",__LINE__);
9635                 l = one;
9636                 break;
9637             case CPOINTER:
9638               pic14_emitcode(";BUG!? ","%d",__LINE__);
9639                 l = "#0x02";
9640                 break;                          
9641             case PPOINTER:
9642               pic14_emitcode(";BUG!? ","%d",__LINE__);
9643                 l = "#0x03";
9644                 break;
9645                 
9646             default:
9647                 /* this should never happen */
9648                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9649                        "got unknown pointer type");
9650                 exit(1);
9651             }
9652             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9653             goto release ;
9654         }
9655         
9656         /* just copy the pointers */
9657         size = AOP_SIZE(result);
9658         offset = 0 ;
9659         while (size--) {
9660             aopPut(AOP(result),
9661                    aopGet(AOP(right),offset,FALSE,FALSE),
9662                    offset);
9663             offset++;
9664         }
9665         goto release ;
9666     }
9667     
9668
9669
9670     /* so we now know that the size of destination is greater
9671     than the size of the source.
9672     Now, if the next iCode is an operator then we might be
9673     able to optimize the operation without performing a cast.
9674     */
9675     if(genMixedOperation(ic))
9676       goto release;
9677
9678     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9679     
9680     /* we move to result for the size of source */
9681     size = AOP_SIZE(right);
9682     offset = 0 ;
9683     while (size--) {
9684       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9685       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9686       offset++;
9687     }
9688
9689     /* now depending on the sign of the destination */
9690     size = AOP_SIZE(result) - AOP_SIZE(right);
9691     /* if unsigned or not an integral type */
9692     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9693       while (size--)
9694         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9695     } else {
9696       /* we need to extend the sign :{ */
9697
9698       if(size == 1) {
9699         /* Save one instruction of casting char to int */
9700         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9701         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9702         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9703       } else {
9704         emitpcodeNULLop(POC_CLRW);
9705
9706         if(offset)
9707           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9708         else
9709           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9710         
9711         emitpcode(POC_MOVLW,   popGetLit(0xff));
9712
9713         while (size--)
9714           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9715       }
9716     }
9717
9718 release:
9719     freeAsmop(right,NULL,ic,TRUE);
9720     freeAsmop(result,NULL,ic,TRUE);
9721
9722 }
9723
9724 /*-----------------------------------------------------------------*/
9725 /* genDjnz - generate decrement & jump if not zero instrucion      */
9726 /*-----------------------------------------------------------------*/
9727 static int genDjnz (iCode *ic, iCode *ifx)
9728 {
9729     symbol *lbl, *lbl1;
9730     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9731
9732     if (!ifx)
9733         return 0;
9734     
9735     /* if the if condition has a false label
9736        then we cannot save */
9737     if (IC_FALSE(ifx))
9738         return 0;
9739
9740     /* if the minus is not of the form 
9741        a = a - 1 */
9742     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9743         !IS_OP_LITERAL(IC_RIGHT(ic)))
9744         return 0;
9745
9746     if (operandLitValue(IC_RIGHT(ic)) != 1)
9747         return 0;
9748
9749     /* if the size of this greater than one then no
9750        saving */
9751     if (getSize(operandType(IC_RESULT(ic))) > 1)
9752         return 0;
9753
9754     /* otherwise we can save BIG */
9755     lbl = newiTempLabel(NULL);
9756     lbl1= newiTempLabel(NULL);
9757
9758     aopOp(IC_RESULT(ic),ic,FALSE);
9759     
9760     if (IS_AOP_PREG(IC_RESULT(ic))) {
9761         pic14_emitcode("dec","%s",
9762                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9763         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9764         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9765     } else {    
9766
9767
9768       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9769       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9770
9771       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9772       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9773
9774     }
9775 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9776 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9777 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9778 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9779
9780     
9781     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9782     ifx->generated = 1;
9783     return 1;
9784 }
9785
9786 /*-----------------------------------------------------------------*/
9787 /* genReceive - generate code for a receive iCode                  */
9788 /*-----------------------------------------------------------------*/
9789 static void genReceive (iCode *ic)
9790 {    
9791   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9792
9793   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9794       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9795         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9796
9797     int size = getSize(operandType(IC_RESULT(ic)));
9798     int offset =  fReturnSizePic - size;
9799     while (size--) {
9800       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9801                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9802       offset++;
9803     }
9804     aopOp(IC_RESULT(ic),ic,FALSE);  
9805     size = AOP_SIZE(IC_RESULT(ic));
9806     offset = 0;
9807     while (size--) {
9808       pic14_emitcode ("pop","acc");
9809       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9810     }
9811         
9812   } else {
9813     _G.accInUse++;
9814     aopOp(IC_RESULT(ic),ic,FALSE);  
9815     _G.accInUse--;
9816     assignResultValue(IC_RESULT(ic));   
9817   }
9818
9819   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9820 }
9821
9822 /*-----------------------------------------------------------------*/
9823 /* genpic14Code - generate code for pic14 based controllers        */
9824 /*-----------------------------------------------------------------*/
9825 /*
9826  * At this point, ralloc.c has gone through the iCode and attempted
9827  * to optimize in a way suitable for a PIC. Now we've got to generate
9828  * PIC instructions that correspond to the iCode.
9829  *
9830  * Once the instructions are generated, we'll pass through both the
9831  * peep hole optimizer and the pCode optimizer.
9832  *-----------------------------------------------------------------*/
9833
9834 void genpic14Code (iCode *lic)
9835 {
9836     iCode *ic;
9837     int cln = 0;
9838
9839     lineHead = lineCurr = NULL;
9840
9841     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9842     addpBlock(pb);
9843
9844     /* if debug information required */
9845     if (options.debug && currFunc) { 
9846       if (currFunc) {
9847         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9848         _G.debugLine = 1;
9849         if (IS_STATIC(currFunc->etype)) {
9850           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9851           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9852         } else {
9853           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9854           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9855         }
9856         _G.debugLine = 0;
9857       }
9858     }
9859
9860
9861     for (ic = lic ; ic ; ic = ic->next ) {
9862
9863       DEBUGpic14_emitcode(";ic","");
9864         if ( cln != ic->lineno ) {
9865             if ( options.debug ) {
9866                 _G.debugLine = 1;
9867                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9868                          FileBaseName(ic->filename),ic->lineno,
9869                          ic->level,ic->block);
9870                 _G.debugLine = 0;
9871             }
9872             /*
9873               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9874               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9875               printCLine(ic->filename, ic->lineno));
9876             */
9877             addpCode2pBlock(pb,
9878                             newpCodeCSource(ic->lineno, 
9879                                             ic->filename, 
9880                                             printCLine(ic->filename, ic->lineno)));
9881
9882             cln = ic->lineno ;
9883         }
9884         /* if the result is marked as
9885            spilt and rematerializable or code for
9886            this has already been generated then
9887            do nothing */
9888         if (resultRemat(ic) || ic->generated ) 
9889             continue ;
9890         
9891         /* depending on the operation */
9892         switch (ic->op) {
9893         case '!' :
9894             genNot(ic);
9895             break;
9896             
9897         case '~' :
9898             genCpl(ic);
9899             break;
9900             
9901         case UNARYMINUS:
9902             genUminus (ic);
9903             break;
9904             
9905         case IPUSH:
9906             genIpush (ic);
9907             break;
9908             
9909         case IPOP:
9910             /* IPOP happens only when trying to restore a 
9911                spilt live range, if there is an ifx statement
9912                following this pop then the if statement might
9913                be using some of the registers being popped which
9914                would destory the contents of the register so
9915                we need to check for this condition and handle it */
9916             if (ic->next            && 
9917                 ic->next->op == IFX &&
9918                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9919                 genIfx (ic->next,ic);
9920             else
9921                 genIpop (ic);
9922             break; 
9923             
9924         case CALL:
9925             genCall (ic);
9926             break;
9927             
9928         case PCALL:
9929             genPcall (ic);
9930             break;
9931             
9932         case FUNCTION:
9933             genFunction (ic);
9934             break;
9935             
9936         case ENDFUNCTION:
9937             genEndFunction (ic);
9938             break;
9939             
9940         case RETURN:
9941             genRet (ic);
9942             break;
9943             
9944         case LABEL:
9945             genLabel (ic);
9946             break;
9947             
9948         case GOTO:
9949             genGoto (ic);
9950             break;
9951             
9952         case '+' :
9953             genPlus (ic) ;
9954             break;
9955             
9956         case '-' :
9957             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9958                 genMinus (ic);
9959             break;
9960             
9961         case '*' :
9962             genMult (ic);
9963             break;
9964             
9965         case '/' :
9966             genDiv (ic) ;
9967             break;
9968             
9969         case '%' :
9970             genMod (ic);
9971             break;
9972             
9973         case '>' :
9974             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9975             break;
9976             
9977         case '<' :
9978             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9979             break;
9980             
9981         case LE_OP:
9982         case GE_OP:
9983         case NE_OP:
9984             
9985             /* note these two are xlated by algebraic equivalence
9986                during parsing SDCC.y */
9987             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9988                    "got '>=' or '<=' shouldn't have come here");
9989             break;      
9990             
9991         case EQ_OP:
9992             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9993             break;          
9994             
9995         case AND_OP:
9996             genAndOp (ic);
9997             break;
9998             
9999         case OR_OP:
10000             genOrOp (ic);
10001             break;
10002             
10003         case '^' :
10004             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10005             break;
10006             
10007         case '|' :
10008                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10009             break;
10010             
10011         case BITWISEAND:
10012             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10013             break;
10014             
10015         case INLINEASM:
10016             genInline (ic);
10017             break;
10018             
10019         case RRC:
10020             genRRC (ic);
10021             break;
10022             
10023         case RLC:
10024             genRLC (ic);
10025             break;
10026             
10027         case GETHBIT:
10028             genGetHbit (ic);
10029             break;
10030             
10031         case LEFT_OP:
10032             genLeftShift (ic);
10033             break;
10034             
10035         case RIGHT_OP:
10036             genRightShift (ic);
10037             break;
10038             
10039         case GET_VALUE_AT_ADDRESS:
10040             genPointerGet(ic);
10041             break;
10042             
10043         case '=' :
10044             if (POINTER_SET(ic))
10045                 genPointerSet(ic);
10046             else
10047                 genAssign(ic);
10048             break;
10049             
10050         case IFX:
10051             genIfx (ic,NULL);
10052             break;
10053             
10054         case ADDRESS_OF:
10055             genAddrOf (ic);
10056             break;
10057             
10058         case JUMPTABLE:
10059             genJumpTab (ic);
10060             break;
10061             
10062         case CAST:
10063             genCast (ic);
10064             break;
10065             
10066         case RECEIVE:
10067             genReceive(ic);
10068             break;
10069             
10070         case SEND:
10071             addSet(&_G.sendSet,ic);
10072             break;
10073
10074         default :
10075             ic = ic;
10076         }
10077     }
10078     
10079
10080     /* now we are ready to call the 
10081        peep hole optimizer */
10082     if (!options.nopeep) {
10083       peepHole (&lineHead);
10084     }
10085     /* now do the actual printing */
10086     printLine (lineHead,codeOutFile);
10087
10088 #ifdef PCODE_DEBUG
10089     DFPRINTF((stderr,"printing pBlock\n\n"));
10090     printpBlock(stdout,pb);
10091 #endif
10092
10093     return;
10094 }