Fixed some pointer bugs. Added option to selectively enable/disable function inlining.
[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",__LINE__);
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           pic14_emitcode("movwf","%s",fReturn[offset]);
3034         }
3035         offset++;
3036       }
3037     }
3038   }    
3039
3040   if (pushed) {
3041     while(pushed) {
3042       pushed--;
3043       if (strcmp(fReturn[pushed],"a"))
3044         pic14_emitcode("pop",fReturn[pushed]);
3045       else
3046         pic14_emitcode("pop","acc");
3047     }
3048   }
3049   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3050     
3051  jumpret:
3052   /* generate a jump to the return label
3053      if the next is not the return statement */
3054   if (!(ic->next && ic->next->op == LABEL &&
3055         IC_LABEL(ic->next) == returnLabel)) {
3056         
3057     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3058     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3059   }
3060     
3061 }
3062
3063 /*-----------------------------------------------------------------*/
3064 /* genLabel - generates a label                                    */
3065 /*-----------------------------------------------------------------*/
3066 static void genLabel (iCode *ic)
3067 {
3068     /* special case never generate */
3069     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3070     if (IC_LABEL(ic) == entryLabel)
3071         return ;
3072
3073     emitpLabel(IC_LABEL(ic)->key);
3074     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3075 }
3076
3077 /*-----------------------------------------------------------------*/
3078 /* genGoto - generates a goto                                      */
3079 /*-----------------------------------------------------------------*/
3080 //tsd
3081 static void genGoto (iCode *ic)
3082 {
3083   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3084   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3085 }
3086
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genMultbits :- multiplication of bits                           */
3090 /*-----------------------------------------------------------------*/
3091 static void genMultbits (operand *left, 
3092                          operand *right, 
3093                          operand *result)
3094 {
3095   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3096
3097   if(!pic14_sameRegs(AOP(result),AOP(right)))
3098     emitpcode(POC_BSF,  popGet(AOP(result),0));
3099
3100   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3101   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3102   emitpcode(POC_BCF,  popGet(AOP(result),0));
3103
3104 }
3105
3106
3107 /*-----------------------------------------------------------------*/
3108 /* genMultOneByte : 8 bit multiplication & division                */
3109 /*-----------------------------------------------------------------*/
3110 static void genMultOneByte (operand *left,
3111                             operand *right,
3112                             operand *result)
3113 {
3114   sym_link *opetype = operandType(result);
3115
3116   // symbol *lbl ;
3117   int size,offset;
3118
3119   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3120   DEBUGpic14_AopType(__LINE__,left,right,result);
3121   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3122
3123   /* (if two literals, the value is computed before) */
3124   /* if one literal, literal on the right */
3125   if (AOP_TYPE(left) == AOP_LIT){
3126     operand *t = right;
3127     right = left;
3128     left = t;
3129   }
3130
3131   size = AOP_SIZE(result);
3132   if(size == 1) {
3133
3134     if (AOP_TYPE(right) == AOP_LIT){
3135       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3136                      aopGet(AOP(right),0,FALSE,FALSE), 
3137                      aopGet(AOP(left),0,FALSE,FALSE), 
3138                      aopGet(AOP(result),0,FALSE,FALSE));
3139       pic14_emitcode("call","genMultLit");
3140     } else {
3141       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3142                      aopGet(AOP(right),0,FALSE,FALSE), 
3143                      aopGet(AOP(left),0,FALSE,FALSE), 
3144                      aopGet(AOP(result),0,FALSE,FALSE));
3145       pic14_emitcode("call","genMult8X8_8");
3146
3147     }
3148     genMult8X8_8 (left, right,result);
3149
3150
3151     /* signed or unsigned */
3152     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3153     //l = aopGet(AOP(left),0,FALSE,FALSE);
3154     //MOVA(l);       
3155     //pic14_emitcode("mul","ab");
3156     /* if result size = 1, mul signed = mul unsigned */
3157     //aopPut(AOP(result),"a",0);
3158
3159   } else {  // (size > 1)
3160
3161     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3162                    aopGet(AOP(right),0,FALSE,FALSE), 
3163                    aopGet(AOP(left),0,FALSE,FALSE), 
3164                    aopGet(AOP(result),0,FALSE,FALSE));
3165
3166     if (SPEC_USIGN(opetype)){
3167       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3168       genUMult8X8_16 (left, right, result, NULL);
3169
3170       if (size > 2) {
3171         /* for filling the MSBs */
3172         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3173         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3174       }
3175     }
3176     else{
3177       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3178
3179       pic14_emitcode("mov","a,b");
3180
3181       /* adjust the MSB if left or right neg */
3182
3183       /* if one literal */
3184       if (AOP_TYPE(right) == AOP_LIT){
3185         pic14_emitcode("multiply ","right is a lit");
3186         /* AND literal negative */
3187         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3188           /* adjust MSB (c==0 after mul) */
3189           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3190         }
3191       }
3192       else{
3193         genSMult8X8_16 (left, right, result, NULL);
3194       }
3195
3196       if(size > 2){
3197         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3198         /* get the sign */
3199         pic14_emitcode("rlc","a");
3200         pic14_emitcode("subb","a,acc");
3201       }
3202     }
3203
3204     size -= 2;   
3205     offset = 2;
3206     if (size > 0)
3207       while (size--)
3208         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3209     //aopPut(AOP(result),"a",offset++);
3210   }
3211 }
3212
3213 /*-----------------------------------------------------------------*/
3214 /* genMult - generates code for multiplication                     */
3215 /*-----------------------------------------------------------------*/
3216 static void genMult (iCode *ic)
3217 {
3218     operand *left = IC_LEFT(ic);
3219     operand *right = IC_RIGHT(ic);
3220     operand *result= IC_RESULT(ic);   
3221
3222     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3223     /* assign the amsops */
3224     aopOp (left,ic,FALSE);
3225     aopOp (right,ic,FALSE);
3226     aopOp (result,ic,TRUE);
3227
3228   DEBUGpic14_AopType(__LINE__,left,right,result);
3229
3230     /* special cases first */
3231     /* both are bits */
3232     if (AOP_TYPE(left) == AOP_CRY &&
3233         AOP_TYPE(right)== AOP_CRY) {
3234         genMultbits(left,right,result);
3235         goto release ;
3236     }
3237
3238     /* if both are of size == 1 */
3239     if (AOP_SIZE(left) == 1 &&
3240         AOP_SIZE(right) == 1 ) {
3241         genMultOneByte(left,right,result);
3242         goto release ;
3243     }
3244
3245     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3246
3247     /* should have been converted to function call */
3248     //assert(0) ;
3249
3250 release :
3251     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3252     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3253     freeAsmop(result,NULL,ic,TRUE); 
3254 }
3255
3256 /*-----------------------------------------------------------------*/
3257 /* genDivbits :- division of bits                                  */
3258 /*-----------------------------------------------------------------*/
3259 static void genDivbits (operand *left, 
3260                         operand *right, 
3261                         operand *result)
3262 {
3263
3264     char *l;
3265
3266     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3267     /* the result must be bit */    
3268     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3269     l = aopGet(AOP(left),0,FALSE,FALSE);
3270
3271     MOVA(l);    
3272
3273     pic14_emitcode("div","ab");
3274     pic14_emitcode("rrc","a");
3275     aopPut(AOP(result),"c",0);
3276 }
3277
3278 /*-----------------------------------------------------------------*/
3279 /* genDivOneByte : 8 bit division                                  */
3280 /*-----------------------------------------------------------------*/
3281 static void genDivOneByte (operand *left,
3282                            operand *right,
3283                            operand *result)
3284 {
3285     sym_link *opetype = operandType(result);
3286     char *l ;
3287     symbol *lbl ;
3288     int size,offset;
3289
3290     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3291     size = AOP_SIZE(result) - 1;
3292     offset = 1;
3293     /* signed or unsigned */
3294     if (SPEC_USIGN(opetype)) {
3295         /* unsigned is easy */
3296         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3297         l = aopGet(AOP(left),0,FALSE,FALSE);
3298         MOVA(l);        
3299         pic14_emitcode("div","ab");
3300         aopPut(AOP(result),"a",0);
3301         while (size--)
3302             aopPut(AOP(result),zero,offset++);
3303         return ;
3304     }
3305
3306     /* signed is a little bit more difficult */
3307
3308     /* save the signs of the operands */
3309     l = aopGet(AOP(left),0,FALSE,FALSE);    
3310     MOVA(l);    
3311     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3312     pic14_emitcode("push","acc"); /* save it on the stack */
3313
3314     /* now sign adjust for both left & right */
3315     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3316     MOVA(l);       
3317     lbl = newiTempLabel(NULL);
3318     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3319     pic14_emitcode("cpl","a");   
3320     pic14_emitcode("inc","a");
3321     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3322     pic14_emitcode("mov","b,a");
3323
3324     /* sign adjust left side */
3325     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3326     MOVA(l);
3327
3328     lbl = newiTempLabel(NULL);
3329     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3330     pic14_emitcode("cpl","a");
3331     pic14_emitcode("inc","a");
3332     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3333
3334     /* now the division */
3335     pic14_emitcode("div","ab");
3336     /* we are interested in the lower order
3337     only */
3338     pic14_emitcode("mov","b,a");
3339     lbl = newiTempLabel(NULL);
3340     pic14_emitcode("pop","acc");   
3341     /* if there was an over flow we don't 
3342     adjust the sign of the result */
3343     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3344     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3345     CLRC;
3346     pic14_emitcode("clr","a");
3347     pic14_emitcode("subb","a,b");
3348     pic14_emitcode("mov","b,a");
3349     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3350
3351     /* now we are done */
3352     aopPut(AOP(result),"b",0);
3353     if(size > 0){
3354         pic14_emitcode("mov","c,b.7");
3355         pic14_emitcode("subb","a,acc");   
3356     }
3357     while (size--)
3358         aopPut(AOP(result),"a",offset++);
3359
3360 }
3361
3362 /*-----------------------------------------------------------------*/
3363 /* genDiv - generates code for division                            */
3364 /*-----------------------------------------------------------------*/
3365 static void genDiv (iCode *ic)
3366 {
3367     operand *left = IC_LEFT(ic);
3368     operand *right = IC_RIGHT(ic);
3369     operand *result= IC_RESULT(ic);   
3370
3371     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3372     /* assign the amsops */
3373     aopOp (left,ic,FALSE);
3374     aopOp (right,ic,FALSE);
3375     aopOp (result,ic,TRUE);
3376
3377     /* special cases first */
3378     /* both are bits */
3379     if (AOP_TYPE(left) == AOP_CRY &&
3380         AOP_TYPE(right)== AOP_CRY) {
3381         genDivbits(left,right,result);
3382         goto release ;
3383     }
3384
3385     /* if both are of size == 1 */
3386     if (AOP_SIZE(left) == 1 &&
3387         AOP_SIZE(right) == 1 ) {
3388         genDivOneByte(left,right,result);
3389         goto release ;
3390     }
3391
3392     /* should have been converted to function call */
3393     assert(0);
3394 release :
3395     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3396     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3397     freeAsmop(result,NULL,ic,TRUE); 
3398 }
3399
3400 /*-----------------------------------------------------------------*/
3401 /* genModbits :- modulus of bits                                   */
3402 /*-----------------------------------------------------------------*/
3403 static void genModbits (operand *left, 
3404                         operand *right, 
3405                         operand *result)
3406 {
3407
3408     char *l;
3409
3410     /* the result must be bit */    
3411     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3412     l = aopGet(AOP(left),0,FALSE,FALSE);
3413
3414     MOVA(l);       
3415
3416     pic14_emitcode("div","ab");
3417     pic14_emitcode("mov","a,b");
3418     pic14_emitcode("rrc","a");
3419     aopPut(AOP(result),"c",0);
3420 }
3421
3422 /*-----------------------------------------------------------------*/
3423 /* genModOneByte : 8 bit modulus                                   */
3424 /*-----------------------------------------------------------------*/
3425 static void genModOneByte (operand *left,
3426                            operand *right,
3427                            operand *result)
3428 {
3429     sym_link *opetype = operandType(result);
3430     char *l ;
3431     symbol *lbl ;
3432
3433     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3434     /* signed or unsigned */
3435     if (SPEC_USIGN(opetype)) {
3436         /* unsigned is easy */
3437         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3438         l = aopGet(AOP(left),0,FALSE,FALSE);
3439         MOVA(l);    
3440         pic14_emitcode("div","ab");
3441         aopPut(AOP(result),"b",0);
3442         return ;
3443     }
3444
3445     /* signed is a little bit more difficult */
3446
3447     /* save the signs of the operands */
3448     l = aopGet(AOP(left),0,FALSE,FALSE);    
3449     MOVA(l);
3450
3451     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3452     pic14_emitcode("push","acc"); /* save it on the stack */
3453
3454     /* now sign adjust for both left & right */
3455     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3456     MOVA(l);
3457
3458     lbl = newiTempLabel(NULL);
3459     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3460     pic14_emitcode("cpl","a");   
3461     pic14_emitcode("inc","a");
3462     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3463     pic14_emitcode("mov","b,a"); 
3464
3465     /* sign adjust left side */
3466     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3467     MOVA(l);
3468
3469     lbl = newiTempLabel(NULL);
3470     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3471     pic14_emitcode("cpl","a");   
3472     pic14_emitcode("inc","a");
3473     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3474
3475     /* now the multiplication */
3476     pic14_emitcode("div","ab");
3477     /* we are interested in the lower order
3478     only */
3479     lbl = newiTempLabel(NULL);
3480     pic14_emitcode("pop","acc");   
3481     /* if there was an over flow we don't 
3482     adjust the sign of the result */
3483     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3484     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3485     CLRC ;
3486     pic14_emitcode("clr","a");
3487     pic14_emitcode("subb","a,b");
3488     pic14_emitcode("mov","b,a");
3489     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3490
3491     /* now we are done */
3492     aopPut(AOP(result),"b",0);
3493
3494 }
3495
3496 /*-----------------------------------------------------------------*/
3497 /* genMod - generates code for division                            */
3498 /*-----------------------------------------------------------------*/
3499 static void genMod (iCode *ic)
3500 {
3501     operand *left = IC_LEFT(ic);
3502     operand *right = IC_RIGHT(ic);
3503     operand *result= IC_RESULT(ic);  
3504
3505     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3506     /* assign the amsops */
3507     aopOp (left,ic,FALSE);
3508     aopOp (right,ic,FALSE);
3509     aopOp (result,ic,TRUE);
3510
3511     /* special cases first */
3512     /* both are bits */
3513     if (AOP_TYPE(left) == AOP_CRY &&
3514         AOP_TYPE(right)== AOP_CRY) {
3515         genModbits(left,right,result);
3516         goto release ;
3517     }
3518
3519     /* if both are of size == 1 */
3520     if (AOP_SIZE(left) == 1 &&
3521         AOP_SIZE(right) == 1 ) {
3522         genModOneByte(left,right,result);
3523         goto release ;
3524     }
3525
3526     /* should have been converted to function call */
3527     assert(0);
3528
3529 release :
3530     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3531     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3532     freeAsmop(result,NULL,ic,TRUE); 
3533 }
3534
3535 /*-----------------------------------------------------------------*/
3536 /* genIfxJump :- will create a jump depending on the ifx           */
3537 /*-----------------------------------------------------------------*/
3538 /*
3539   note: May need to add parameter to indicate when a variable is in bit space.
3540 */
3541 static void genIfxJump (iCode *ic, char *jval)
3542 {
3543
3544     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545     /* if true label then we jump if condition
3546     supplied is true */
3547     if ( IC_TRUE(ic) ) {
3548
3549         if(strcmp(jval,"a") == 0)
3550           emitSKPZ;
3551         else if (strcmp(jval,"c") == 0)
3552           emitSKPC;
3553         else {
3554           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3555           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3556         }
3557
3558         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3559         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3560
3561     }
3562     else {
3563         /* false label is present */
3564         if(strcmp(jval,"a") == 0)
3565           emitSKPNZ;
3566         else if (strcmp(jval,"c") == 0)
3567           emitSKPNC;
3568         else {
3569           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3570           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3571         }
3572
3573         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3574         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3575
3576     }
3577
3578
3579     /* mark the icode as generated */
3580     ic->generated = 1;
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* genSkip                                                         */
3585 /*-----------------------------------------------------------------*/
3586 static void genSkip(iCode *ifx,int status_bit)
3587 {
3588   if(!ifx)
3589     return;
3590
3591   if ( IC_TRUE(ifx) ) {
3592     switch(status_bit) {
3593     case 'z':
3594       emitSKPNZ;
3595       break;
3596
3597     case 'c':
3598       emitSKPNC;
3599       break;
3600
3601     case 'd':
3602       emitSKPDC;
3603       break;
3604
3605     }
3606
3607     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3608     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3609
3610   } else {
3611
3612     switch(status_bit) {
3613
3614     case 'z':
3615       emitSKPZ;
3616       break;
3617
3618     case 'c':
3619       emitSKPC;
3620       break;
3621
3622     case 'd':
3623       emitSKPDC;
3624       break;
3625     }
3626     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3627     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3628
3629   }
3630
3631 }
3632
3633 /*-----------------------------------------------------------------*/
3634 /* genSkipc                                                        */
3635 /*-----------------------------------------------------------------*/
3636 static void genSkipc(resolvedIfx *rifx)
3637 {
3638   if(!rifx)
3639     return;
3640
3641   if(rifx->condition)
3642     emitSKPC;
3643   else
3644     emitSKPNC;
3645
3646   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3647   rifx->generated = 1;
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genSkipz2                                                       */
3652 /*-----------------------------------------------------------------*/
3653 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3654 {
3655   if(!rifx)
3656     return;
3657
3658   if( (rifx->condition ^ invert_condition) & 1)
3659     emitSKPZ;
3660   else
3661     emitSKPNZ;
3662
3663   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3664   rifx->generated = 1;
3665 }
3666
3667 /*-----------------------------------------------------------------*/
3668 /* genSkipz                                                        */
3669 /*-----------------------------------------------------------------*/
3670 static void genSkipz(iCode *ifx, int condition)
3671 {
3672   if(!ifx)
3673     return;
3674
3675   if(condition)
3676     emitSKPNZ;
3677   else
3678     emitSKPZ;
3679
3680   if ( IC_TRUE(ifx) )
3681     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3682   else
3683     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3684
3685   if ( IC_TRUE(ifx) )
3686     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3687   else
3688     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3689
3690 }
3691 /*-----------------------------------------------------------------*/
3692 /* genSkipCond                                                     */
3693 /*-----------------------------------------------------------------*/
3694 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3695 {
3696   if(!rifx)
3697     return;
3698
3699   if(rifx->condition)
3700     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3701   else
3702     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3703
3704
3705   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3706   rifx->generated = 1;
3707 }
3708
3709 #if 0
3710 /*-----------------------------------------------------------------*/
3711 /* genChkZeroes :- greater or less than comparison                 */
3712 /*     For each byte in a literal that is zero, inclusive or the   */
3713 /*     the corresponding byte in the operand with W                */
3714 /*     returns true if any of the bytes are zero                   */
3715 /*-----------------------------------------------------------------*/
3716 static int genChkZeroes(operand *op, int lit,  int size)
3717 {
3718
3719   int i;
3720   int flag =1;
3721
3722   while(size--) {
3723     i = (lit >> (size*8)) & 0xff;
3724
3725     if(i==0) {
3726       if(flag) 
3727         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3728       else
3729         emitpcode(POC_IORFW, popGet(AOP(op),size));
3730       flag = 0;
3731     }
3732   }
3733
3734   return (flag==0);
3735 }
3736 #endif
3737
3738 /*-----------------------------------------------------------------*/
3739 /* genCmp :- greater or less than comparison                       */
3740 /*-----------------------------------------------------------------*/
3741 static void genCmp (operand *left,operand *right,
3742                     operand *result, iCode *ifx, int sign)
3743 {
3744   int size; //, offset = 0 ;
3745   unsigned long lit = 0L,i = 0;
3746   resolvedIfx rFalseIfx;
3747   //  resolvedIfx rTrueIfx;
3748   symbol *truelbl;
3749   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3750   if(ifx) {
3751     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3752     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3753   }
3754
3755
3756   resolveIfx(&rFalseIfx,ifx);
3757   truelbl  = newiTempLabel(NULL);
3758   size = max(AOP_SIZE(left),AOP_SIZE(right));
3759
3760 #define _swapp
3761
3762   /* if literal is on the right then swap with left */
3763   if ((AOP_TYPE(right) == AOP_LIT)) {
3764     operand *tmp = right ;
3765     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3766     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3767 #ifdef _swapp
3768     DEBUGpic14_emitcode ("; ***","%d swapping left&right, lit =0x%x",__LINE__,lit);
3769     lit = (lit - 1) & mask;
3770     DEBUGpic14_emitcode ("; ***","%d swapping left&right, lit =0x%x, mask 0x%x",__LINE__,lit,mask);
3771
3772     right = left;
3773     left = tmp;
3774     rFalseIfx.condition ^= 1;
3775 #endif
3776
3777   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3778     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3779   }
3780
3781
3782   //if(IC_TRUE(ifx) == NULL)
3783   /* if left & right are bit variables */
3784   if (AOP_TYPE(left) == AOP_CRY &&
3785       AOP_TYPE(right) == AOP_CRY ) {
3786     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3787     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3788   } else {
3789     /* subtract right from left if at the
3790        end the carry flag is set then we know that
3791        left is greater than right */
3792
3793     //    {
3794
3795     symbol *lbl  = newiTempLabel(NULL);
3796
3797 #ifndef _swapp
3798     if(AOP_TYPE(right) == AOP_LIT) {
3799
3800       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3801
3802       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3803
3804       /* special cases */
3805
3806       if(lit == 0) {
3807
3808         if(sign != 0) 
3809           genSkipCond(&rFalseIfx,left,size-1,7);
3810         else 
3811           /* no need to compare to 0...*/
3812           /* NOTE: this is a de-generate compare that most certainly 
3813            *       creates some dead code. */
3814           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3815
3816         if(ifx) ifx->generated = 1;
3817         return;
3818
3819       }
3820       size--;
3821
3822       if(size == 0) {
3823         //i = (lit >> (size*8)) & 0xff;
3824         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3825         
3826         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3827
3828         i = ((0-lit) & 0xff);
3829         if(sign) {
3830           if( i == 0x81) { 
3831             /* lit is 0x7f, all signed chars are less than
3832              * this except for 0x7f itself */
3833             emitpcode(POC_XORLW, popGetLit(0x7f));
3834             genSkipz2(&rFalseIfx,0);
3835           } else {
3836             emitpcode(POC_ADDLW, popGetLit(0x80));
3837             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3838             genSkipc(&rFalseIfx);
3839           }
3840
3841         } else {
3842           if(lit == 1) {
3843             genSkipz2(&rFalseIfx,1);
3844           } else {
3845             emitpcode(POC_ADDLW, popGetLit(i));
3846             genSkipc(&rFalseIfx);
3847           }
3848         }
3849
3850         if(ifx) ifx->generated = 1;
3851         return;
3852       }
3853
3854       /* chars are out of the way. now do ints and longs */
3855
3856
3857       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3858         
3859       /* special cases */
3860
3861       if(sign) {
3862
3863         if(lit == 0) {
3864           genSkipCond(&rFalseIfx,left,size,7);
3865           if(ifx) ifx->generated = 1;
3866           return;
3867         }
3868
3869         if(lit <0x100) {
3870           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3871
3872           //rFalseIfx.condition ^= 1;
3873           //genSkipCond(&rFalseIfx,left,size,7);
3874           //rFalseIfx.condition ^= 1;
3875
3876           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3877           if(rFalseIfx.condition)
3878             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3879           else
3880             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3881
3882           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3883           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3884           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3885
3886           while(size > 1)
3887             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3888
3889           if(rFalseIfx.condition) {
3890             emitSKPZ;
3891             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3892
3893           } else {
3894             emitSKPNZ;
3895           }
3896
3897           genSkipc(&rFalseIfx);
3898           emitpLabel(truelbl->key);
3899           if(ifx) ifx->generated = 1;
3900           return;
3901
3902         }
3903
3904         if(size == 1) {
3905
3906           if( (lit & 0xff) == 0) {
3907             /* lower byte is zero */
3908             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3909             i = ((lit >> 8) & 0xff) ^0x80;
3910             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3911             emitpcode(POC_ADDLW, popGetLit( 0x80));
3912             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3913             genSkipc(&rFalseIfx);
3914
3915
3916             if(ifx) ifx->generated = 1;
3917             return;
3918
3919           }
3920         } else {
3921           /* Special cases for signed longs */
3922           if( (lit & 0xffffff) == 0) {
3923             /* lower byte is zero */
3924             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3925             i = ((lit >> 8*3) & 0xff) ^0x80;
3926             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3927             emitpcode(POC_ADDLW, popGetLit( 0x80));
3928             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3929             genSkipc(&rFalseIfx);
3930
3931
3932             if(ifx) ifx->generated = 1;
3933             return;
3934
3935           }
3936
3937         }
3938
3939
3940         if(lit & (0x80 << (size*8))) {
3941           /* lit is negative */
3942           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3943
3944           //genSkipCond(&rFalseIfx,left,size,7);
3945
3946           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3947
3948           if(rFalseIfx.condition)
3949             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3950           else
3951             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3952
3953
3954         } else {
3955           /* lit is positive */
3956           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3957           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3958           if(rFalseIfx.condition)
3959             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3960           else
3961             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3962
3963         }
3964
3965         /*
3966           This works, but is only good for ints.
3967           It also requires a "known zero" register.
3968           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3969           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3970           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3971           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3972           emitpcode(POC_ADDFW, popGet(AOP(left),1));
3973           genSkipc(&rFalseIfx);
3974
3975           emitpLabel(truelbl->key);
3976           if(ifx) ifx->generated = 1;
3977           return;
3978         **/
3979           
3980         /* There are no more special cases, so perform a general compare */
3981   
3982         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3983         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3984
3985         while(size--) {
3986
3987           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3988           emitSKPNZ;
3989           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3990         }
3991         //rFalseIfx.condition ^= 1;
3992         genSkipc(&rFalseIfx);
3993
3994         emitpLabel(truelbl->key);
3995
3996         if(ifx) ifx->generated = 1;
3997         return;
3998
3999
4000       }
4001
4002
4003       /* sign is out of the way. So now do an unsigned compare */
4004       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4005
4006
4007       /* General case - compare to an unsigned literal on the right.*/
4008
4009       i = (lit >> (size*8)) & 0xff;
4010       emitpcode(POC_MOVLW, popGetLit(i));
4011       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4012       while(size--) {
4013         i = (lit >> (size*8)) & 0xff;
4014
4015         if(i) {
4016           emitpcode(POC_MOVLW, popGetLit(i));
4017           emitSKPNZ;
4018           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4019         } else {
4020           /* this byte of the lit is zero, 
4021            *if it's not the last then OR in the variable */
4022           if(size)
4023             emitpcode(POC_IORFW, popGet(AOP(left),size));
4024         }
4025       }
4026
4027
4028       emitpLabel(lbl->key);
4029       //if(emitFinalCheck)
4030       genSkipc(&rFalseIfx);
4031       if(sign)
4032         emitpLabel(truelbl->key);
4033
4034       if(ifx) ifx->generated = 1;
4035       return;
4036
4037
4038     }
4039 #endif
4040     if(AOP_TYPE(left) == AOP_LIT) {
4041       //symbol *lbl = newiTempLabel(NULL);
4042
4043       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4044
4045
4046       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4047
4048       /* Special cases */
4049       if((lit == 0) && (sign == 0)){
4050
4051         size--;
4052         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4053         while(size) 
4054           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4055
4056         genSkipz2(&rFalseIfx,0);
4057         if(ifx) ifx->generated = 1;
4058         return;
4059       }
4060
4061       if(size==1) {
4062         /* Special cases */
4063         lit &= 0xff;
4064         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4065           /* degenerate compare can never be true */
4066           if(rFalseIfx.condition == 0)
4067             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4068
4069           if(ifx) ifx->generated = 1;
4070           return;
4071         }
4072
4073         if(sign) {
4074           /* signed comparisons to a literal byte */
4075
4076           int lp1 = (lit+1) & 0xff;
4077
4078           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4079           switch (lp1) {
4080           case 0:
4081             rFalseIfx.condition ^= 1;
4082             genSkipCond(&rFalseIfx,right,0,7);
4083             break;
4084           case 0x7f:
4085             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4086             emitpcode(POC_XORLW, popGetLit(0x7f));
4087             genSkipz2(&rFalseIfx,1);
4088             break;
4089           default:
4090             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4091             emitpcode(POC_ADDLW, popGetLit(0x80));
4092             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4093             rFalseIfx.condition ^= 1;
4094             genSkipc(&rFalseIfx);
4095             break;
4096           }
4097         } else {
4098           /* unsigned comparisons to a literal byte */
4099
4100           switch(lit & 0xff ) {
4101           case 0:
4102             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4103             genSkipz2(&rFalseIfx,0);
4104             break;
4105           case 0x7f:
4106             rFalseIfx.condition ^= 1;
4107             genSkipCond(&rFalseIfx,right,0,7);
4108             break;
4109
4110           default:
4111             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4112             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4113             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4114             rFalseIfx.condition ^= 1;
4115             genSkipc(&rFalseIfx);
4116             break;
4117           }
4118         }
4119
4120         if(ifx) ifx->generated = 1;
4121         return;
4122
4123       } else {
4124
4125         /* Size is greater than 1 */
4126
4127         if(sign) {
4128           int lp1 = lit+1;
4129
4130           size--;
4131
4132           if(lp1 == 0) {
4133             /* this means lit = 0xffffffff, or -1 */
4134
4135
4136             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4137             rFalseIfx.condition ^= 1;
4138             genSkipCond(&rFalseIfx,right,size,7);
4139             if(ifx) ifx->generated = 1;
4140             return;
4141           }
4142
4143           if(lit == 0) {
4144             int s = size;
4145
4146             if(rFalseIfx.condition) {
4147               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4148               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4149             }
4150
4151             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4152             while(size--)
4153               emitpcode(POC_IORFW, popGet(AOP(right),size));
4154
4155
4156             emitSKPZ;
4157             if(rFalseIfx.condition) {
4158               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4159               emitpLabel(truelbl->key);
4160             }else {
4161               rFalseIfx.condition ^= 1;
4162               genSkipCond(&rFalseIfx,right,s,7);
4163             }
4164
4165             if(ifx) ifx->generated = 1;
4166             return;
4167           }
4168
4169           if((size == 1) &&  (0 == (lp1&0xff))) {
4170             /* lower byte of signed word is zero */
4171             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4172             i = ((lp1 >> 8) & 0xff) ^0x80;
4173             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4174             emitpcode(POC_ADDLW, popGetLit( 0x80));
4175             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4176             rFalseIfx.condition ^= 1;
4177             genSkipc(&rFalseIfx);
4178
4179
4180             if(ifx) ifx->generated = 1;
4181             return;
4182           }
4183
4184           if(lit & (0x80 << (size*8))) {
4185             /* Lit is less than zero */
4186             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4187             //rFalseIfx.condition ^= 1;
4188             //genSkipCond(&rFalseIfx,left,size,7);
4189             //rFalseIfx.condition ^= 1;
4190             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4191             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4192
4193             if(rFalseIfx.condition)
4194               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4195             else
4196               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4197
4198
4199           } else {
4200             /* Lit is greater than or equal to zero */
4201             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4202             //rFalseIfx.condition ^= 1;
4203             //genSkipCond(&rFalseIfx,right,size,7);
4204             //rFalseIfx.condition ^= 1;
4205
4206             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4207             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4208
4209             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4210             if(rFalseIfx.condition)
4211               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4212             else
4213               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4214
4215           }
4216
4217
4218           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4219           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4220
4221           while(size--) {
4222
4223             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4224             emitSKPNZ;
4225             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4226           }
4227           rFalseIfx.condition ^= 1;
4228           //rFalseIfx.condition = 1;
4229           genSkipc(&rFalseIfx);
4230
4231           emitpLabel(truelbl->key);
4232
4233           if(ifx) ifx->generated = 1;
4234           return;
4235           // end of if (sign)
4236         } else {
4237
4238           /* compare word or long to an unsigned literal on the right.*/
4239
4240
4241           size--;
4242           if(lit < 0xff) {
4243             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4244             switch (lit) {
4245             case 0:
4246               break; /* handled above */
4247 /*
4248             case 0xff:
4249               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4250               while(size--)
4251                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4252               genSkipz2(&rFalseIfx,0);
4253               break;
4254 */
4255             default:
4256               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4257               while(--size)
4258                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4259
4260               emitSKPZ;
4261               if(rFalseIfx.condition)
4262                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4263               else
4264                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4265
4266
4267               emitpcode(POC_MOVLW, popGetLit(lit+1));
4268               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4269
4270               rFalseIfx.condition ^= 1;
4271               genSkipc(&rFalseIfx);
4272             }
4273
4274             emitpLabel(truelbl->key);
4275
4276             if(ifx) ifx->generated = 1;
4277             return;
4278           }
4279
4280
4281           lit++;
4282           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4283           i = (lit >> (size*8)) & 0xff;
4284
4285           emitpcode(POC_MOVLW, popGetLit(i));
4286           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4287
4288           while(size--) {
4289             i = (lit >> (size*8)) & 0xff;
4290
4291             if(i) {
4292               emitpcode(POC_MOVLW, popGetLit(i));
4293               emitSKPNZ;
4294               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4295             } else {
4296               /* this byte of the lit is zero, 
4297                *if it's not the last then OR in the variable */
4298               if(size)
4299                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4300             }
4301           }
4302
4303
4304           emitpLabel(lbl->key);
4305
4306           rFalseIfx.condition ^= 1;
4307           genSkipc(&rFalseIfx);
4308         }
4309
4310         if(sign)
4311           emitpLabel(truelbl->key);
4312         if(ifx) ifx->generated = 1;
4313         return;
4314       }
4315     }
4316     /* Compare two variables */
4317
4318     DEBUGpic14_emitcode(";sign","%d",sign);
4319
4320     size--;
4321     if(sign) {
4322       /* Sigh. thus sucks... */
4323       if(size) {
4324         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4325         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4326         emitpcode(POC_MOVLW, popGetLit(0x80));
4327         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4328         emitpcode(POC_XORFW, popGet(AOP(right),size));
4329         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4330       } else {
4331         /* Signed char comparison */
4332         /* Special thanks to Nikolai Golovchenko for this snippet */
4333         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4334         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4335         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4336         emitpcode(POC_XORFW, popGet(AOP(left),0));
4337         emitpcode(POC_XORFW, popGet(AOP(right),0));
4338         emitpcode(POC_ADDLW, popGetLit(0x80));
4339
4340         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4341         genSkipc(&rFalseIfx);
4342           
4343         if(ifx) ifx->generated = 1;
4344         return;
4345       }
4346
4347     } else {
4348
4349       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4350       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4351     }
4352
4353
4354     /* The rest of the bytes of a multi-byte compare */
4355     while (size) {
4356
4357       emitSKPZ;
4358       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4359       size--;
4360
4361       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4362       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4363
4364
4365     }
4366
4367     emitpLabel(lbl->key);
4368
4369     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4370     genSkipc(&rFalseIfx);
4371     if(ifx) ifx->generated = 1;
4372     return;
4373
4374   }
4375
4376   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4377     pic14_outBitC(result);
4378   } else {
4379     /* if the result is used in the next
4380        ifx conditional branch then generate
4381        code a little differently */
4382     if (ifx )
4383       genIfxJump (ifx,"c");
4384     else
4385       pic14_outBitC(result);
4386     /* leave the result in acc */
4387   }
4388
4389 }
4390
4391 /*-----------------------------------------------------------------*/
4392 /* genCmpGt :- greater than comparison                             */
4393 /*-----------------------------------------------------------------*/
4394 static void genCmpGt (iCode *ic, iCode *ifx)
4395 {
4396     operand *left, *right, *result;
4397     sym_link *letype , *retype;
4398     int sign ;
4399
4400     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4401     left = IC_LEFT(ic);
4402     right= IC_RIGHT(ic);
4403     result = IC_RESULT(ic);
4404
4405     letype = getSpec(operandType(left));
4406     retype =getSpec(operandType(right));
4407     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4408     /* assign the amsops */
4409     aopOp (left,ic,FALSE);
4410     aopOp (right,ic,FALSE);
4411     aopOp (result,ic,TRUE);
4412
4413     genCmp(right, left, result, ifx, sign);
4414
4415     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4416     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4417     freeAsmop(result,NULL,ic,TRUE); 
4418 }
4419
4420 /*-----------------------------------------------------------------*/
4421 /* genCmpLt - less than comparisons                                */
4422 /*-----------------------------------------------------------------*/
4423 static void genCmpLt (iCode *ic, iCode *ifx)
4424 {
4425     operand *left, *right, *result;
4426     sym_link *letype , *retype;
4427     int sign ;
4428
4429     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4430     left = IC_LEFT(ic);
4431     right= IC_RIGHT(ic);
4432     result = IC_RESULT(ic);
4433
4434     letype = getSpec(operandType(left));
4435     retype =getSpec(operandType(right));
4436     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4437
4438     /* assign the amsops */
4439     aopOp (left,ic,FALSE);
4440     aopOp (right,ic,FALSE);
4441     aopOp (result,ic,TRUE);
4442
4443     genCmp(left, right, result, ifx, sign);
4444
4445     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4446     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4447     freeAsmop(result,NULL,ic,TRUE); 
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genc16bit2lit - compare a 16 bit value to a literal             */
4452 /*-----------------------------------------------------------------*/
4453 static void genc16bit2lit(operand *op, int lit, int offset)
4454 {
4455   int i;
4456
4457   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4458   if( (lit&0xff) == 0) 
4459     i=1;
4460   else
4461     i=0;
4462
4463   switch( BYTEofLONG(lit,i)) { 
4464   case 0:
4465     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4466     break;
4467   case 1:
4468     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4469     break;
4470   case 0xff:
4471     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4472     break;
4473   default:
4474     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4475     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4476   }
4477
4478   i ^= 1;
4479
4480   switch( BYTEofLONG(lit,i)) { 
4481   case 0:
4482     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4483     break;
4484   case 1:
4485     emitSKPNZ;
4486     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4487     break;
4488   case 0xff:
4489     emitSKPNZ;
4490     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4491     break;
4492   default:
4493     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4494     emitSKPNZ;
4495     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4496
4497   }
4498
4499 }
4500
4501 /*-----------------------------------------------------------------*/
4502 /* gencjneshort - compare and jump if not equal                    */
4503 /*-----------------------------------------------------------------*/
4504 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4505 {
4506   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4507   int offset = 0;
4508   resolvedIfx rIfx;
4509   symbol *lbl;
4510
4511   unsigned long lit = 0L;
4512   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4513   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4514
4515   resolveIfx(&rIfx,ifx);
4516   lbl =  newiTempLabel(NULL);
4517
4518
4519   /* if the left side is a literal or 
4520      if the right is in a pointer register and left 
4521      is not */
4522   if ((AOP_TYPE(left) == AOP_LIT) || 
4523       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4524     operand *t = right;
4525     right = left;
4526     left = t;
4527   }
4528   if(AOP_TYPE(right) == AOP_LIT)
4529     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4530
4531   /* if the right side is a literal then anything goes */
4532   if (AOP_TYPE(right) == AOP_LIT &&
4533       AOP_TYPE(left) != AOP_DIR ) {
4534     switch(size) {
4535     case 2:
4536       genc16bit2lit(left, lit, 0);
4537       emitSKPNZ;
4538       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4539       break;
4540     default:
4541       while (size--) {
4542         if(lit & 0xff) {
4543           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4544           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4545         } else {
4546           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4547         }
4548
4549         emitSKPNZ;
4550         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4551         offset++;
4552         lit >>= 8;
4553       }
4554       break;
4555     }
4556   }
4557
4558   /* if the right side is in a register or in direct space or
4559      if the left is a pointer register & right is not */    
4560   else if (AOP_TYPE(right) == AOP_REG ||
4561            AOP_TYPE(right) == AOP_DIR || 
4562            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4563            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4564     switch(size) {
4565     case 2:
4566       genc16bit2lit(left, lit, 0);
4567       emitSKPNZ;
4568       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4569       break;
4570     default:
4571       while (size--) {
4572         int emit_skip=1;
4573         if((AOP_TYPE(left) == AOP_DIR) && 
4574            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4575
4576           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4577           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4578
4579         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4580             
4581           switch (lit & 0xff) {
4582           case 0:
4583             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4584             break;
4585           case 1:
4586             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4587             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4588             emit_skip=0;
4589             break;
4590           case 0xff:
4591             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4592             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4593             emit_skip=0;
4594             break;
4595           default:
4596             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4597             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4598           }
4599           lit >>= 8;
4600
4601         } else {
4602           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4603         }
4604         if(emit_skip) {
4605           if(AOP_TYPE(result) == AOP_CRY) {
4606             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4607             if(rIfx.condition)
4608               emitSKPNZ;
4609             else
4610               emitSKPZ;
4611             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4612           } else {
4613             /* fix me. probably need to check result size too */
4614             emitpcode(POC_CLRF,popGet(AOP(result),0));
4615             if(rIfx.condition)
4616               emitSKPNZ;
4617             else
4618               emitSKPZ;
4619             emitpcode(POC_INCF,popGet(AOP(result),0));
4620           }
4621           if(ifx)
4622             ifx->generated=1;
4623         }
4624         emit_skip++;
4625         offset++;
4626       }
4627       break;
4628     }
4629   } else if(AOP_TYPE(right) == AOP_REG &&
4630             AOP_TYPE(left) != AOP_DIR){
4631
4632     while(size--) {
4633       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4634       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4635       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4636       if(rIfx.condition)
4637         emitSKPNZ;
4638       else
4639         emitSKPZ;
4640       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4641       offset++;
4642     }
4643       
4644   }else{
4645     /* right is a pointer reg need both a & b */
4646     while(size--) {
4647       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4648       if(strcmp(l,"b"))
4649         pic14_emitcode("mov","b,%s",l);
4650       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4651       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4652       offset++;
4653     }
4654   }
4655   emitpLabel(lbl->key);
4656
4657   if(ifx)
4658     ifx->generated = 1;
4659 }
4660
4661 #if 0
4662 /*-----------------------------------------------------------------*/
4663 /* gencjne - compare and jump if not equal                         */
4664 /*-----------------------------------------------------------------*/
4665 static void gencjne(operand *left, operand *right, iCode *ifx)
4666 {
4667     symbol *tlbl  = newiTempLabel(NULL);
4668
4669     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4670     gencjneshort(left, right, lbl);
4671
4672     pic14_emitcode("mov","a,%s",one);
4673     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4674     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4675     pic14_emitcode("clr","a");
4676     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4677
4678     emitpLabel(lbl->key);
4679     emitpLabel(tlbl->key);
4680
4681 }
4682 #endif
4683
4684 /*-----------------------------------------------------------------*/
4685 /* genCmpEq - generates code for equal to                          */
4686 /*-----------------------------------------------------------------*/
4687 static void genCmpEq (iCode *ic, iCode *ifx)
4688 {
4689     operand *left, *right, *result;
4690     unsigned long lit = 0L;
4691     int size,offset=0;
4692
4693     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4694
4695     if(ifx)
4696       DEBUGpic14_emitcode ("; ifx is non-null","");
4697     else
4698       DEBUGpic14_emitcode ("; ifx is null","");
4699
4700     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4701     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4702     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4703
4704     size = max(AOP_SIZE(left),AOP_SIZE(right));
4705
4706     DEBUGpic14_AopType(__LINE__,left,right,result);
4707
4708     /* if literal, literal on the right or 
4709     if the right is in a pointer register and left 
4710     is not */
4711     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4712         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4713       operand *tmp = right ;
4714       right = left;
4715       left = tmp;
4716     }
4717
4718
4719     if(ifx && !AOP_SIZE(result)){
4720         symbol *tlbl;
4721         /* if they are both bit variables */
4722         if (AOP_TYPE(left) == AOP_CRY &&
4723             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4724             if(AOP_TYPE(right) == AOP_LIT){
4725                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4726                 if(lit == 0L){
4727                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4728                     pic14_emitcode("cpl","c");
4729                 } else if(lit == 1L) {
4730                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4731                 } else {
4732                     pic14_emitcode("clr","c");
4733                 }
4734                 /* AOP_TYPE(right) == AOP_CRY */
4735             } else {
4736                 symbol *lbl = newiTempLabel(NULL);
4737                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4738                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4739                 pic14_emitcode("cpl","c");
4740                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4741             }
4742             /* if true label then we jump if condition
4743             supplied is true */
4744             tlbl = newiTempLabel(NULL);
4745             if ( IC_TRUE(ifx) ) {
4746                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4747                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4748             } else {
4749                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4750                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4751             }
4752             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4753
4754             {
4755               /* left and right are both bit variables, result is carry */
4756               resolvedIfx rIfx;
4757               
4758               resolveIfx(&rIfx,ifx);
4759
4760               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4761               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4762               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4763               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4764               genSkipz2(&rIfx,0);
4765             }
4766         } else {
4767
4768           /* They're not both bit variables. Is the right a literal? */
4769           if(AOP_TYPE(right) == AOP_LIT) {
4770             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4771             
4772             switch(size) {
4773
4774             case 1:
4775               switch(lit & 0xff) {
4776               case 1:
4777                 if ( IC_TRUE(ifx) ) {
4778                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4779                   emitSKPNZ;
4780                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4781                 } else {
4782                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4783                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4784                 }
4785                 break;
4786               case 0xff:
4787                 if ( IC_TRUE(ifx) ) {
4788                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4789                   emitSKPNZ;
4790                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4791                 } else {
4792                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4793                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4794                 }
4795                 break;
4796               default:
4797                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4798                 if(lit)
4799                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4800                 genSkip(ifx,'z');
4801               }
4802
4803
4804               /* end of size == 1 */
4805               break;
4806               
4807             case 2:
4808               genc16bit2lit(left,lit,offset);
4809               genSkip(ifx,'z');
4810               break;
4811               /* end of size == 2 */
4812
4813             default:
4814               /* size is 4 */
4815               if(lit==0) {
4816                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4817                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4818                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4819                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4820
4821               } else {
4822
4823                 /* search for patterns that can be optimized */
4824
4825                 genc16bit2lit(left,lit,0);
4826                 lit >>= 16;
4827                 if(lit) {
4828                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4829                   //genSkip(ifx,'z');
4830                   genc16bit2lit(left,lit,2);
4831                 } else {
4832                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4833                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4834
4835                 }
4836                 
4837               }
4838
4839               genSkip(ifx,'z');
4840             }
4841           
4842             ifx->generated = 1;
4843             goto release ;
4844             
4845
4846           } else if(AOP_TYPE(right) == AOP_CRY ) {
4847             /* we know the left is not a bit, but that the right is */
4848             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4849             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4850                       popGet(AOP(right),offset));
4851             emitpcode(POC_XORLW,popGetLit(1));
4852
4853             /* if the two are equal, then W will be 0 and the Z bit is set
4854              * we could test Z now, or go ahead and check the high order bytes if
4855              * the variable we're comparing is larger than a byte. */
4856
4857             while(--size)
4858               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4859
4860             if ( IC_TRUE(ifx) ) {
4861               emitSKPNZ;
4862               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4863               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4864             } else {
4865               emitSKPZ;
4866               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4867               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4868             }
4869
4870           } else {
4871             /* They're both variables that are larger than bits */
4872             int s = size;
4873
4874             tlbl = newiTempLabel(NULL);
4875
4876             while(size--) {
4877               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4878               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4879
4880               if ( IC_TRUE(ifx) ) {
4881                 if(size) {
4882                   emitSKPZ;
4883                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4884                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4885                 } else {
4886                   emitSKPNZ;
4887                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4888                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4889                 }
4890               } else {
4891                 emitSKPZ;
4892                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4893                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4894               }
4895               offset++;
4896             }
4897             if(s>1 && IC_TRUE(ifx)) {
4898               emitpLabel(tlbl->key);
4899               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4900             }
4901           }
4902         }
4903         /* mark the icode as generated */
4904         ifx->generated = 1;
4905         goto release ;
4906     }
4907
4908     /* if they are both bit variables */
4909     if (AOP_TYPE(left) == AOP_CRY &&
4910         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4911         if(AOP_TYPE(right) == AOP_LIT){
4912             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4913             if(lit == 0L){
4914                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4915                 pic14_emitcode("cpl","c");
4916             } else if(lit == 1L) {
4917                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4918             } else {
4919                 pic14_emitcode("clr","c");
4920             }
4921             /* AOP_TYPE(right) == AOP_CRY */
4922         } else {
4923             symbol *lbl = newiTempLabel(NULL);
4924             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4925             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4926             pic14_emitcode("cpl","c");
4927             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4928         }
4929         /* c = 1 if egal */
4930         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4931             pic14_outBitC(result);
4932             goto release ;
4933         }
4934         if (ifx) {
4935             genIfxJump (ifx,"c");
4936             goto release ;
4937         }
4938         /* if the result is used in an arithmetic operation
4939         then put the result in place */
4940         pic14_outBitC(result);
4941     } else {
4942       
4943       gencjne(left,right,result,ifx);
4944 /*
4945       if(ifx) 
4946         gencjne(left,right,newiTempLabel(NULL));
4947       else {
4948         if(IC_TRUE(ifx)->key)
4949           gencjne(left,right,IC_TRUE(ifx)->key);
4950         else
4951           gencjne(left,right,IC_FALSE(ifx)->key);
4952         ifx->generated = 1;
4953         goto release ;
4954       }
4955       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4956         aopPut(AOP(result),"a",0);
4957         goto release ;
4958       }
4959
4960       if (ifx) {
4961         genIfxJump (ifx,"a");
4962         goto release ;
4963       }
4964 */
4965       /* if the result is used in an arithmetic operation
4966          then put the result in place */
4967 /*
4968       if (AOP_TYPE(result) != AOP_CRY) 
4969         pic14_outAcc(result);
4970 */
4971       /* leave the result in acc */
4972     }
4973
4974 release:
4975     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4976     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4977     freeAsmop(result,NULL,ic,TRUE);
4978 }
4979
4980 /*-----------------------------------------------------------------*/
4981 /* ifxForOp - returns the icode containing the ifx for operand     */
4982 /*-----------------------------------------------------------------*/
4983 static iCode *ifxForOp ( operand *op, iCode *ic )
4984 {
4985     /* if true symbol then needs to be assigned */
4986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4987     if (IS_TRUE_SYMOP(op))
4988         return NULL ;
4989
4990     /* if this has register type condition and
4991     the next instruction is ifx with the same operand
4992     and live to of the operand is upto the ifx only then */
4993     if (ic->next &&
4994         ic->next->op == IFX &&
4995         IC_COND(ic->next)->key == op->key &&
4996         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4997         return ic->next;
4998
4999     if (ic->next &&
5000         ic->next->op == IFX &&
5001         IC_COND(ic->next)->key == op->key) {
5002       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5003       return ic->next;
5004     }
5005
5006     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5007     if (ic->next &&
5008         ic->next->op == IFX)
5009       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5010
5011     if (ic->next &&
5012         ic->next->op == IFX &&
5013         IC_COND(ic->next)->key == op->key) {
5014       DEBUGpic14_emitcode ("; "," key is okay");
5015       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5016                            OP_SYMBOL(op)->liveTo,
5017                            ic->next->seq);
5018     }
5019
5020
5021     return NULL;
5022 }
5023 /*-----------------------------------------------------------------*/
5024 /* genAndOp - for && operation                                     */
5025 /*-----------------------------------------------------------------*/
5026 static void genAndOp (iCode *ic)
5027 {
5028     operand *left,*right, *result;
5029     symbol *tlbl;
5030
5031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5032     /* note here that && operations that are in an
5033     if statement are taken away by backPatchLabels
5034     only those used in arthmetic operations remain */
5035     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5036     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5037     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5038
5039     /* if both are bit variables */
5040     if (AOP_TYPE(left) == AOP_CRY &&
5041         AOP_TYPE(right) == AOP_CRY ) {
5042         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5043         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
5044         pic14_outBitC(result);
5045     } else {
5046         tlbl = newiTempLabel(NULL);
5047         pic14_toBoolean(left);    
5048         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
5049         pic14_toBoolean(right);
5050         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5051         pic14_outBitAcc(result);
5052     }
5053
5054     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5055     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5056     freeAsmop(result,NULL,ic,TRUE);
5057 }
5058
5059
5060 /*-----------------------------------------------------------------*/
5061 /* genOrOp - for || operation                                      */
5062 /*-----------------------------------------------------------------*/
5063 /*
5064   tsd pic port -
5065   modified this code, but it doesn't appear to ever get called
5066 */
5067
5068 static void genOrOp (iCode *ic)
5069 {
5070     operand *left,*right, *result;
5071     symbol *tlbl;
5072
5073     /* note here that || operations that are in an
5074     if statement are taken away by backPatchLabels
5075     only those used in arthmetic operations remain */
5076     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5077     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5078     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5079     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5080
5081     DEBUGpic14_AopType(__LINE__,left,right,result);
5082
5083     /* if both are bit variables */
5084     if (AOP_TYPE(left) == AOP_CRY &&
5085         AOP_TYPE(right) == AOP_CRY ) {
5086       pic14_emitcode("clrc","");
5087       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5088                AOP(left)->aopu.aop_dir,
5089                AOP(left)->aopu.aop_dir);
5090       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5091                AOP(right)->aopu.aop_dir,
5092                AOP(right)->aopu.aop_dir);
5093       pic14_emitcode("setc","");
5094
5095     } else {
5096         tlbl = newiTempLabel(NULL);
5097         pic14_toBoolean(left);
5098         emitSKPZ;
5099         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5100         pic14_toBoolean(right);
5101         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5102
5103         pic14_outBitAcc(result);
5104     }
5105
5106     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5107     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5108     freeAsmop(result,NULL,ic,TRUE);            
5109 }
5110
5111 /*-----------------------------------------------------------------*/
5112 /* isLiteralBit - test if lit == 2^n                               */
5113 /*-----------------------------------------------------------------*/
5114 static int isLiteralBit(unsigned long lit)
5115 {
5116     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5117     0x100L,0x200L,0x400L,0x800L,
5118     0x1000L,0x2000L,0x4000L,0x8000L,
5119     0x10000L,0x20000L,0x40000L,0x80000L,
5120     0x100000L,0x200000L,0x400000L,0x800000L,
5121     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5122     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5123     int idx;
5124     
5125     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126     for(idx = 0; idx < 32; idx++)
5127         if(lit == pw[idx])
5128             return idx+1;
5129     return 0;
5130 }
5131
5132 /*-----------------------------------------------------------------*/
5133 /* continueIfTrue -                                                */
5134 /*-----------------------------------------------------------------*/
5135 static void continueIfTrue (iCode *ic)
5136 {
5137     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5138     if(IC_TRUE(ic))
5139         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5140     ic->generated = 1;
5141 }
5142
5143 /*-----------------------------------------------------------------*/
5144 /* jmpIfTrue -                                                     */
5145 /*-----------------------------------------------------------------*/
5146 static void jumpIfTrue (iCode *ic)
5147 {
5148     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5149     if(!IC_TRUE(ic))
5150         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5151     ic->generated = 1;
5152 }
5153
5154 /*-----------------------------------------------------------------*/
5155 /* jmpTrueOrFalse -                                                */
5156 /*-----------------------------------------------------------------*/
5157 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5158 {
5159     // ugly but optimized by peephole
5160     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5161     if(IC_TRUE(ic)){
5162         symbol *nlbl = newiTempLabel(NULL);
5163         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5164         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5165         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5166         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5167     }
5168     else{
5169         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5170         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5171     }
5172     ic->generated = 1;
5173 }
5174
5175 /*-----------------------------------------------------------------*/
5176 /* genAnd  - code for and                                          */
5177 /*-----------------------------------------------------------------*/
5178 static void genAnd (iCode *ic, iCode *ifx)
5179 {
5180   operand *left, *right, *result;
5181   int size, offset=0;  
5182   unsigned long lit = 0L;
5183   int bytelit = 0;
5184   resolvedIfx rIfx;
5185
5186
5187   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5188   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5189   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5190   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5191
5192   resolveIfx(&rIfx,ifx);
5193
5194   /* if left is a literal & right is not then exchange them */
5195   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5196       AOP_NEEDSACC(left)) {
5197     operand *tmp = right ;
5198     right = left;
5199     left = tmp;
5200   }
5201
5202   /* if result = right then exchange them */
5203   if(pic14_sameRegs(AOP(result),AOP(right))){
5204     operand *tmp = right ;
5205     right = left;
5206     left = tmp;
5207   }
5208
5209   /* if right is bit then exchange them */
5210   if (AOP_TYPE(right) == AOP_CRY &&
5211       AOP_TYPE(left) != AOP_CRY){
5212     operand *tmp = right ;
5213     right = left;
5214     left = tmp;
5215   }
5216   if(AOP_TYPE(right) == AOP_LIT)
5217     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5218
5219   size = AOP_SIZE(result);
5220
5221   DEBUGpic14_AopType(__LINE__,left,right,result);
5222
5223   // if(bit & yy)
5224   // result = bit & yy;
5225   if (AOP_TYPE(left) == AOP_CRY){
5226     // c = bit & literal;
5227     if(AOP_TYPE(right) == AOP_LIT){
5228       if(lit & 1) {
5229         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5230           // no change
5231           goto release;
5232         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5233       } else {
5234         // bit(result) = 0;
5235         if(size && (AOP_TYPE(result) == AOP_CRY)){
5236           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5237           goto release;
5238         }
5239         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5240           jumpIfTrue(ifx);
5241           goto release;
5242         }
5243         pic14_emitcode("clr","c");
5244       }
5245     } else {
5246       if (AOP_TYPE(right) == AOP_CRY){
5247         // c = bit & bit;
5248         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5249         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5250       } else {
5251         // c = bit & val;
5252         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5253         // c = lsb
5254         pic14_emitcode("rrc","a");
5255         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5256       }
5257     }
5258     // bit = c
5259     // val = c
5260     if(size)
5261       pic14_outBitC(result);
5262     // if(bit & ...)
5263     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5264       genIfxJump(ifx, "c");           
5265     goto release ;
5266   }
5267
5268   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5269   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5270   if((AOP_TYPE(right) == AOP_LIT) &&
5271      (AOP_TYPE(result) == AOP_CRY) &&
5272      (AOP_TYPE(left) != AOP_CRY)){
5273     int posbit = isLiteralBit(lit);
5274     /* left &  2^n */
5275     if(posbit){
5276       posbit--;
5277       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5278       // bit = left & 2^n
5279       if(size)
5280         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5281       // if(left &  2^n)
5282       else{
5283         if(ifx){
5284 /*
5285           if(IC_TRUE(ifx)) {
5286             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5287             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5288           } else {
5289             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5290             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5291           }
5292 */
5293           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5294                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5295           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5296           
5297           ifx->generated = 1;
5298         }
5299         goto release;
5300       }
5301     } else {
5302       symbol *tlbl = newiTempLabel(NULL);
5303       int sizel = AOP_SIZE(left);
5304       if(size)
5305         pic14_emitcode("setb","c");
5306       while(sizel--){
5307         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5308           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5309           // byte ==  2^n ?
5310           if((posbit = isLiteralBit(bytelit)) != 0)
5311             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5312           else{
5313             if(bytelit != 0x0FFL)
5314               pic14_emitcode("anl","a,%s",
5315                              aopGet(AOP(right),offset,FALSE,TRUE));
5316             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5317           }
5318         }
5319         offset++;
5320       }
5321       // bit = left & literal
5322       if(size){
5323         pic14_emitcode("clr","c");
5324         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5325       }
5326       // if(left & literal)
5327       else{
5328         if(ifx)
5329           jmpTrueOrFalse(ifx, tlbl);
5330         goto release ;
5331       }
5332     }
5333     pic14_outBitC(result);
5334     goto release ;
5335   }
5336
5337   /* if left is same as result */
5338   if(pic14_sameRegs(AOP(result),AOP(left))){
5339     int know_W = -1;
5340     for(;size--; offset++,lit>>=8) {
5341       if(AOP_TYPE(right) == AOP_LIT){
5342         switch(lit & 0xff) {
5343         case 0x00:
5344           /*  and'ing with 0 has clears the result */
5345           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5346           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5347           break;
5348         case 0xff:
5349           /* and'ing with 0xff is a nop when the result and left are the same */
5350           break;
5351
5352         default:
5353           {
5354             int p = my_powof2( (~lit) & 0xff );
5355             if(p>=0) {
5356               /* only one bit is set in the literal, so use a bcf instruction */
5357               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5358               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5359
5360             } else {
5361               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5362               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5363               if(know_W != (lit&0xff))
5364                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5365               know_W = lit &0xff;
5366               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5367             }
5368           }    
5369         }
5370       } else {
5371         if (AOP_TYPE(left) == AOP_ACC) {
5372           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5373         } else {                    
5374           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5375           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5376
5377         }
5378       }
5379     }
5380
5381   } else {
5382     // left & result in different registers
5383     if(AOP_TYPE(result) == AOP_CRY){
5384       // result = bit
5385       // if(size), result in bit
5386       // if(!size && ifx), conditional oper: if(left & right)
5387       symbol *tlbl = newiTempLabel(NULL);
5388       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5389       if(size)
5390         pic14_emitcode("setb","c");
5391       while(sizer--){
5392         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5393         pic14_emitcode("anl","a,%s",
5394                        aopGet(AOP(left),offset,FALSE,FALSE));
5395         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5396         offset++;
5397       }
5398       if(size){
5399         CLRC;
5400         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5401         pic14_outBitC(result);
5402       } else if(ifx)
5403         jmpTrueOrFalse(ifx, tlbl);
5404     } else {
5405       for(;(size--);offset++) {
5406         // normal case
5407         // result = left & right
5408         if(AOP_TYPE(right) == AOP_LIT){
5409           int t = (lit >> (offset*8)) & 0x0FFL;
5410           switch(t) { 
5411           case 0x00:
5412             pic14_emitcode("clrf","%s",
5413                            aopGet(AOP(result),offset,FALSE,FALSE));
5414             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5415             break;
5416           case 0xff:
5417             pic14_emitcode("movf","%s,w",
5418                            aopGet(AOP(left),offset,FALSE,FALSE));
5419             pic14_emitcode("movwf","%s",
5420                            aopGet(AOP(result),offset,FALSE,FALSE));
5421             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5422             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5423             break;
5424           default:
5425             pic14_emitcode("movlw","0x%x",t);
5426             pic14_emitcode("andwf","%s,w",
5427                            aopGet(AOP(left),offset,FALSE,FALSE));
5428             pic14_emitcode("movwf","%s",
5429                            aopGet(AOP(result),offset,FALSE,FALSE));
5430               
5431             emitpcode(POC_MOVLW, popGetLit(t));
5432             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5433             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5434           }
5435           continue;
5436         }
5437
5438         if (AOP_TYPE(left) == AOP_ACC) {
5439           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5440           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5441         } else {
5442           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5443           pic14_emitcode("andwf","%s,w",
5444                          aopGet(AOP(left),offset,FALSE,FALSE));
5445           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5446           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5447         }
5448         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5449         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5450       }
5451     }
5452   }
5453
5454   release :
5455     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457   freeAsmop(result,NULL,ic,TRUE);     
5458 }
5459
5460 /*-----------------------------------------------------------------*/
5461 /* genOr  - code for or                                            */
5462 /*-----------------------------------------------------------------*/
5463 static void genOr (iCode *ic, iCode *ifx)
5464 {
5465     operand *left, *right, *result;
5466     int size, offset=0;
5467     unsigned long lit = 0L;
5468
5469     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5470
5471     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5472     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5473     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5474
5475     DEBUGpic14_AopType(__LINE__,left,right,result);
5476
5477     /* if left is a literal & right is not then exchange them */
5478     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5479         AOP_NEEDSACC(left)) {
5480         operand *tmp = right ;
5481         right = left;
5482         left = tmp;
5483     }
5484
5485     /* if result = right then exchange them */
5486     if(pic14_sameRegs(AOP(result),AOP(right))){
5487         operand *tmp = right ;
5488         right = left;
5489         left = tmp;
5490     }
5491
5492     /* if right is bit then exchange them */
5493     if (AOP_TYPE(right) == AOP_CRY &&
5494         AOP_TYPE(left) != AOP_CRY){
5495         operand *tmp = right ;
5496         right = left;
5497         left = tmp;
5498     }
5499
5500     DEBUGpic14_AopType(__LINE__,left,right,result);
5501
5502     if(AOP_TYPE(right) == AOP_LIT)
5503         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5504
5505     size = AOP_SIZE(result);
5506
5507     // if(bit | yy)
5508     // xx = bit | yy;
5509     if (AOP_TYPE(left) == AOP_CRY){
5510         if(AOP_TYPE(right) == AOP_LIT){
5511             // c = bit & literal;
5512             if(lit){
5513                 // lit != 0 => result = 1
5514                 if(AOP_TYPE(result) == AOP_CRY){
5515                   if(size)
5516                     emitpcode(POC_BSF, popGet(AOP(result),0));
5517                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5518                   //     AOP(result)->aopu.aop_dir,
5519                   //     AOP(result)->aopu.aop_dir);
5520                     else if(ifx)
5521                         continueIfTrue(ifx);
5522                     goto release;
5523                 }
5524             } else {
5525                 // lit == 0 => result = left
5526                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5527                     goto release;
5528                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5529             }
5530         } else {
5531             if (AOP_TYPE(right) == AOP_CRY){
5532               if(pic14_sameRegs(AOP(result),AOP(left))){
5533                 // c = bit | bit;
5534                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5535                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5536                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5537
5538                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5539                          AOP(result)->aopu.aop_dir,
5540                          AOP(result)->aopu.aop_dir);
5541                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5542                          AOP(right)->aopu.aop_dir,
5543                          AOP(right)->aopu.aop_dir);
5544                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5545                          AOP(result)->aopu.aop_dir,
5546                          AOP(result)->aopu.aop_dir);
5547               } else {
5548                 if( AOP_TYPE(result) == AOP_ACC) {
5549                   emitpcode(POC_MOVLW, popGetLit(0));
5550                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5551                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5552                   emitpcode(POC_MOVLW, popGetLit(1));
5553
5554                 } else {
5555
5556                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5557                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5558                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5559                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5560
5561                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5562                                  AOP(result)->aopu.aop_dir,
5563                                  AOP(result)->aopu.aop_dir);
5564                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5565                                  AOP(right)->aopu.aop_dir,
5566                                  AOP(right)->aopu.aop_dir);
5567                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5568                                  AOP(left)->aopu.aop_dir,
5569                                  AOP(left)->aopu.aop_dir);
5570                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5571                                  AOP(result)->aopu.aop_dir,
5572                                  AOP(result)->aopu.aop_dir);
5573                 }
5574               }
5575             } else {
5576                 // c = bit | val;
5577                 symbol *tlbl = newiTempLabel(NULL);
5578                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5579
5580
5581                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5582                 if( AOP_TYPE(right) == AOP_ACC) {
5583                   emitpcode(POC_IORLW, popGetLit(0));
5584                   emitSKPNZ;
5585                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5586                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5587                 }
5588
5589
5590
5591                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5592                     pic14_emitcode(";XXX setb","c");
5593                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5594                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5595                 pic14_toBoolean(right);
5596                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5597                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5598                     jmpTrueOrFalse(ifx, tlbl);
5599                     goto release;
5600                 } else {
5601                     CLRC;
5602                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5603                 }
5604             }
5605         }
5606         // bit = c
5607         // val = c
5608         if(size)
5609             pic14_outBitC(result);
5610         // if(bit | ...)
5611         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5612             genIfxJump(ifx, "c");           
5613         goto release ;
5614     }
5615
5616     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5617     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5618     if((AOP_TYPE(right) == AOP_LIT) &&
5619        (AOP_TYPE(result) == AOP_CRY) &&
5620        (AOP_TYPE(left) != AOP_CRY)){
5621         if(lit){
5622           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5623             // result = 1
5624             if(size)
5625                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5626             else 
5627                 continueIfTrue(ifx);
5628             goto release;
5629         } else {
5630           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5631             // lit = 0, result = boolean(left)
5632             if(size)
5633                 pic14_emitcode(";XXX setb","c");
5634             pic14_toBoolean(right);
5635             if(size){
5636                 symbol *tlbl = newiTempLabel(NULL);
5637                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5638                 CLRC;
5639                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5640             } else {
5641                 genIfxJump (ifx,"a");
5642                 goto release;
5643             }
5644         }
5645         pic14_outBitC(result);
5646         goto release ;
5647     }
5648
5649     /* if left is same as result */
5650     if(pic14_sameRegs(AOP(result),AOP(left))){
5651       int know_W = -1;
5652       for(;size--; offset++,lit>>=8) {
5653         if(AOP_TYPE(right) == AOP_LIT){
5654           if((lit & 0xff) == 0)
5655             /*  or'ing with 0 has no effect */
5656             continue;
5657           else {
5658             int p = my_powof2(lit & 0xff);
5659             if(p>=0) {
5660               /* only one bit is set in the literal, so use a bsf instruction */
5661               emitpcode(POC_BSF,
5662                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5663             } else {
5664               if(know_W != (lit & 0xff))
5665                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5666               know_W = lit & 0xff;
5667               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5668             }
5669                     
5670           }
5671         } else {
5672           if (AOP_TYPE(left) == AOP_ACC) {
5673             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5674             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5675           } else {                  
5676             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5677             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5678
5679             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5680             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5681
5682           }
5683         }
5684       }
5685     } else {
5686         // left & result in different registers
5687         if(AOP_TYPE(result) == AOP_CRY){
5688             // result = bit
5689             // if(size), result in bit
5690             // if(!size && ifx), conditional oper: if(left | right)
5691             symbol *tlbl = newiTempLabel(NULL);
5692             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5693             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5694
5695
5696             if(size)
5697                 pic14_emitcode(";XXX setb","c");
5698             while(sizer--){
5699                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5700                 pic14_emitcode(";XXX orl","a,%s",
5701                          aopGet(AOP(left),offset,FALSE,FALSE));
5702                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5703                 offset++;
5704             }
5705             if(size){
5706                 CLRC;
5707                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5708                 pic14_outBitC(result);
5709             } else if(ifx)
5710                 jmpTrueOrFalse(ifx, tlbl);
5711         } else for(;(size--);offset++){
5712           // normal case
5713           // result = left & right
5714           if(AOP_TYPE(right) == AOP_LIT){
5715             int t = (lit >> (offset*8)) & 0x0FFL;
5716             switch(t) { 
5717             case 0x00:
5718               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5719               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5720
5721               pic14_emitcode("movf","%s,w",
5722                        aopGet(AOP(left),offset,FALSE,FALSE));
5723               pic14_emitcode("movwf","%s",
5724                        aopGet(AOP(result),offset,FALSE,FALSE));
5725               break;
5726             default:
5727               emitpcode(POC_MOVLW,  popGetLit(t));
5728               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5729               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5730
5731               pic14_emitcode("movlw","0x%x",t);
5732               pic14_emitcode("iorwf","%s,w",
5733                        aopGet(AOP(left),offset,FALSE,FALSE));
5734               pic14_emitcode("movwf","%s",
5735                        aopGet(AOP(result),offset,FALSE,FALSE));
5736               
5737             }
5738             continue;
5739           }
5740
5741           // faster than result <- left, anl result,right
5742           // and better if result is SFR
5743           if (AOP_TYPE(left) == AOP_ACC) {
5744             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5745             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5746           } else {
5747             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5748             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5749
5750             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5751             pic14_emitcode("iorwf","%s,w",
5752                      aopGet(AOP(left),offset,FALSE,FALSE));
5753           }
5754           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5755           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5756         }
5757     }
5758
5759 release :
5760     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5761     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5762     freeAsmop(result,NULL,ic,TRUE);     
5763 }
5764
5765 /*-----------------------------------------------------------------*/
5766 /* genXor - code for xclusive or                                   */
5767 /*-----------------------------------------------------------------*/
5768 static void genXor (iCode *ic, iCode *ifx)
5769 {
5770   operand *left, *right, *result;
5771   int size, offset=0;
5772   unsigned long lit = 0L;
5773
5774   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775
5776   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5777   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5778   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5779
5780   /* if left is a literal & right is not ||
5781      if left needs acc & right does not */
5782   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5783       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5784     operand *tmp = right ;
5785     right = left;
5786     left = tmp;
5787   }
5788
5789   /* if result = right then exchange them */
5790   if(pic14_sameRegs(AOP(result),AOP(right))){
5791     operand *tmp = right ;
5792     right = left;
5793     left = tmp;
5794   }
5795
5796   /* if right is bit then exchange them */
5797   if (AOP_TYPE(right) == AOP_CRY &&
5798       AOP_TYPE(left) != AOP_CRY){
5799     operand *tmp = right ;
5800     right = left;
5801     left = tmp;
5802   }
5803   if(AOP_TYPE(right) == AOP_LIT)
5804     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5805
5806   size = AOP_SIZE(result);
5807
5808   // if(bit ^ yy)
5809   // xx = bit ^ yy;
5810   if (AOP_TYPE(left) == AOP_CRY){
5811     if(AOP_TYPE(right) == AOP_LIT){
5812       // c = bit & literal;
5813       if(lit>>1){
5814         // lit>>1  != 0 => result = 1
5815         if(AOP_TYPE(result) == AOP_CRY){
5816           if(size)
5817             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5818             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5819           else if(ifx)
5820             continueIfTrue(ifx);
5821           goto release;
5822         }
5823         pic14_emitcode("setb","c");
5824       } else{
5825         // lit == (0 or 1)
5826         if(lit == 0){
5827           // lit == 0, result = left
5828           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5829             goto release;
5830           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5831         } else{
5832           // lit == 1, result = not(left)
5833           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5834             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5835             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5836             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5837             goto release;
5838           } else {
5839             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5840             pic14_emitcode("cpl","c");
5841           }
5842         }
5843       }
5844
5845     } else {
5846       // right != literal
5847       symbol *tlbl = newiTempLabel(NULL);
5848       if (AOP_TYPE(right) == AOP_CRY){
5849         // c = bit ^ bit;
5850         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5851       }
5852       else{
5853         int sizer = AOP_SIZE(right);
5854         // c = bit ^ val
5855         // if val>>1 != 0, result = 1
5856         pic14_emitcode("setb","c");
5857         while(sizer){
5858           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5859           if(sizer == 1)
5860             // test the msb of the lsb
5861             pic14_emitcode("anl","a,#0xfe");
5862           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5863           sizer--;
5864         }
5865         // val = (0,1)
5866         pic14_emitcode("rrc","a");
5867       }
5868       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5869       pic14_emitcode("cpl","c");
5870       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5871     }
5872     // bit = c
5873     // val = c
5874     if(size)
5875       pic14_outBitC(result);
5876     // if(bit | ...)
5877     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5878       genIfxJump(ifx, "c");           
5879     goto release ;
5880   }
5881
5882   if(pic14_sameRegs(AOP(result),AOP(left))){
5883     /* if left is same as result */
5884     for(;size--; offset++) {
5885       if(AOP_TYPE(right) == AOP_LIT){
5886         int t  = (lit >> (offset*8)) & 0x0FFL;
5887         if(t == 0x00L)
5888           continue;
5889         else
5890           if (IS_AOP_PREG(left)) {
5891             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5892             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5893             aopPut(AOP(result),"a",offset);
5894           } else {
5895             emitpcode(POC_MOVLW, popGetLit(t));
5896             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5897             pic14_emitcode("xrl","%s,%s",
5898                            aopGet(AOP(left),offset,FALSE,TRUE),
5899                            aopGet(AOP(right),offset,FALSE,FALSE));
5900           }
5901       } else {
5902         if (AOP_TYPE(left) == AOP_ACC)
5903           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5904         else {
5905           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5906           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5907 /*
5908           if (IS_AOP_PREG(left)) {
5909             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5910             aopPut(AOP(result),"a",offset);
5911           } else
5912             pic14_emitcode("xrl","%s,a",
5913                            aopGet(AOP(left),offset,FALSE,TRUE));
5914 */
5915         }
5916       }
5917     }
5918   } else {
5919     // left & result in different registers
5920     if(AOP_TYPE(result) == AOP_CRY){
5921       // result = bit
5922       // if(size), result in bit
5923       // if(!size && ifx), conditional oper: if(left ^ right)
5924       symbol *tlbl = newiTempLabel(NULL);
5925       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5926       if(size)
5927         pic14_emitcode("setb","c");
5928       while(sizer--){
5929         if((AOP_TYPE(right) == AOP_LIT) &&
5930            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5931           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5932         } else {
5933           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5934           pic14_emitcode("xrl","a,%s",
5935                          aopGet(AOP(left),offset,FALSE,FALSE));
5936         }
5937         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5938         offset++;
5939       }
5940       if(size){
5941         CLRC;
5942         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5943         pic14_outBitC(result);
5944       } else if(ifx)
5945         jmpTrueOrFalse(ifx, tlbl);
5946     } else for(;(size--);offset++){
5947       // normal case
5948       // result = left & right
5949       if(AOP_TYPE(right) == AOP_LIT){
5950         int t = (lit >> (offset*8)) & 0x0FFL;
5951         switch(t) { 
5952         case 0x00:
5953           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5954           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5955           pic14_emitcode("movf","%s,w",
5956                          aopGet(AOP(left),offset,FALSE,FALSE));
5957           pic14_emitcode("movwf","%s",
5958                          aopGet(AOP(result),offset,FALSE,FALSE));
5959           break;
5960         case 0xff:
5961           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5962           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5963           pic14_emitcode("comf","%s,w",
5964                          aopGet(AOP(left),offset,FALSE,FALSE));
5965           pic14_emitcode("movwf","%s",
5966                          aopGet(AOP(result),offset,FALSE,FALSE));
5967           break;
5968         default:
5969           emitpcode(POC_MOVLW, popGetLit(t));
5970           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5971           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5972           pic14_emitcode("movlw","0x%x",t);
5973           pic14_emitcode("xorwf","%s,w",
5974                          aopGet(AOP(left),offset,FALSE,FALSE));
5975           pic14_emitcode("movwf","%s",
5976                          aopGet(AOP(result),offset,FALSE,FALSE));
5977
5978         }
5979         continue;
5980       }
5981
5982       // faster than result <- left, anl result,right
5983       // and better if result is SFR
5984       if (AOP_TYPE(left) == AOP_ACC) {
5985         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5986         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5987       } else {
5988         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5989         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5990         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5991         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5992       }
5993       if ( AOP_TYPE(result) != AOP_ACC){
5994         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5995         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5996       }
5997     }
5998   }
5999
6000   release :
6001     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6002   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6003   freeAsmop(result,NULL,ic,TRUE);     
6004 }
6005
6006 /*-----------------------------------------------------------------*/
6007 /* genInline - write the inline code out                           */
6008 /*-----------------------------------------------------------------*/
6009 static void genInline (iCode *ic)
6010 {
6011     char *buffer, *bp, *bp1;
6012     
6013     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6014
6015     _G.inLine += (!options.asmpeep);
6016
6017     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6018     strcpy(buffer,IC_INLINE(ic));
6019
6020     /* emit each line as a code */
6021     while (*bp) {
6022         if (*bp == '\n') {
6023             *bp++ = '\0';
6024             pic14_emitcode(bp1,"");
6025             addpCode2pBlock(pb,newpCodeInlineP(bp1));
6026             bp1 = bp;
6027         } else {
6028             if (*bp == ':') {
6029                 bp++;
6030                 *bp = '\0';
6031                 bp++;
6032                 pic14_emitcode(bp1,"");
6033                 bp1 = bp;
6034             } else
6035                 bp++;
6036         }
6037     }
6038     if (bp1 != bp) {
6039         pic14_emitcode(bp1,"");
6040         addpCode2pBlock(pb,newpCodeInlineP(bp1));
6041     }
6042     /*     pic14_emitcode("",buffer); */
6043     _G.inLine -= (!options.asmpeep);
6044 }
6045
6046 /*-----------------------------------------------------------------*/
6047 /* genRRC - rotate right with carry                                */
6048 /*-----------------------------------------------------------------*/
6049 static void genRRC (iCode *ic)
6050 {
6051   operand *left , *result ;
6052   int size, offset = 0, same;
6053
6054   /* rotate right with carry */
6055   left = IC_LEFT(ic);
6056   result=IC_RESULT(ic);
6057   aopOp (left,ic,FALSE);
6058   aopOp (result,ic,FALSE);
6059
6060   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6061
6062   same = pic14_sameRegs(AOP(result),AOP(left));
6063
6064   size = AOP_SIZE(result);    
6065
6066   /* get the lsb and put it into the carry */
6067   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6068
6069   offset = 0 ;
6070
6071   while(size--) {
6072
6073     if(same) {
6074       emitpcode(POC_RRF, popGet(AOP(left),offset));
6075     } else {
6076       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6077       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6078     }
6079
6080     offset++;
6081   }
6082
6083   freeAsmop(left,NULL,ic,TRUE);
6084   freeAsmop(result,NULL,ic,TRUE);
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* genRLC - generate code for rotate left with carry               */
6089 /*-----------------------------------------------------------------*/
6090 static void genRLC (iCode *ic)
6091 {    
6092   operand *left , *result ;
6093   int size, offset = 0;
6094   int same;
6095
6096   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6097   /* rotate right with carry */
6098   left = IC_LEFT(ic);
6099   result=IC_RESULT(ic);
6100   aopOp (left,ic,FALSE);
6101   aopOp (result,ic,FALSE);
6102
6103   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6104
6105   same = pic14_sameRegs(AOP(result),AOP(left));
6106
6107   /* move it to the result */
6108   size = AOP_SIZE(result);    
6109
6110   /* get the msb and put it into the carry */
6111   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6112
6113   offset = 0 ;
6114
6115   while(size--) {
6116
6117     if(same) {
6118       emitpcode(POC_RLF, popGet(AOP(left),offset));
6119     } else {
6120       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6121       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6122     }
6123
6124     offset++;
6125   }
6126
6127
6128   freeAsmop(left,NULL,ic,TRUE);
6129   freeAsmop(result,NULL,ic,TRUE);
6130 }
6131
6132 /*-----------------------------------------------------------------*/
6133 /* genGetHbit - generates code get highest order bit               */
6134 /*-----------------------------------------------------------------*/
6135 static void genGetHbit (iCode *ic)
6136 {
6137     operand *left, *result;
6138     left = IC_LEFT(ic);
6139     result=IC_RESULT(ic);
6140     aopOp (left,ic,FALSE);
6141     aopOp (result,ic,FALSE);
6142
6143     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6144     /* get the highest order byte into a */
6145     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6146     if(AOP_TYPE(result) == AOP_CRY){
6147         pic14_emitcode("rlc","a");
6148         pic14_outBitC(result);
6149     }
6150     else{
6151         pic14_emitcode("rl","a");
6152         pic14_emitcode("anl","a,#0x01");
6153         pic14_outAcc(result);
6154     }
6155
6156
6157     freeAsmop(left,NULL,ic,TRUE);
6158     freeAsmop(result,NULL,ic,TRUE);
6159 }
6160
6161 /*-----------------------------------------------------------------*/
6162 /* AccRol - rotate left accumulator by known count                 */
6163 /*-----------------------------------------------------------------*/
6164 static void AccRol (int shCount)
6165 {
6166     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6167     shCount &= 0x0007;              // shCount : 0..7
6168     switch(shCount){
6169         case 0 :
6170             break;
6171         case 1 :
6172             pic14_emitcode("rl","a");
6173             break;
6174         case 2 :
6175             pic14_emitcode("rl","a");
6176             pic14_emitcode("rl","a");
6177             break;
6178         case 3 :
6179             pic14_emitcode("swap","a");
6180             pic14_emitcode("rr","a");
6181             break;
6182         case 4 :
6183             pic14_emitcode("swap","a");
6184             break;
6185         case 5 :
6186             pic14_emitcode("swap","a");
6187             pic14_emitcode("rl","a");
6188             break;
6189         case 6 :
6190             pic14_emitcode("rr","a");
6191             pic14_emitcode("rr","a");
6192             break;
6193         case 7 :
6194             pic14_emitcode("rr","a");
6195             break;
6196     }
6197 }
6198
6199 /*-----------------------------------------------------------------*/
6200 /* AccLsh - left shift accumulator by known count                  */
6201 /*-----------------------------------------------------------------*/
6202 static void AccLsh (int shCount)
6203 {
6204     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6205     if(shCount != 0){
6206         if(shCount == 1)
6207             pic14_emitcode("add","a,acc");
6208         else 
6209             if(shCount == 2) {
6210             pic14_emitcode("add","a,acc");
6211             pic14_emitcode("add","a,acc");
6212         } else {
6213             /* rotate left accumulator */
6214             AccRol(shCount);
6215             /* and kill the lower order bits */
6216             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6217         }
6218     }
6219 }
6220
6221 /*-----------------------------------------------------------------*/
6222 /* AccRsh - right shift accumulator by known count                 */
6223 /*-----------------------------------------------------------------*/
6224 static void AccRsh (int shCount)
6225 {
6226     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6227     if(shCount != 0){
6228         if(shCount == 1){
6229             CLRC;
6230             pic14_emitcode("rrc","a");
6231         } else {
6232             /* rotate right accumulator */
6233             AccRol(8 - shCount);
6234             /* and kill the higher order bits */
6235             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6236         }
6237     }
6238 }
6239
6240 #if 0
6241 /*-----------------------------------------------------------------*/
6242 /* AccSRsh - signed right shift accumulator by known count                 */
6243 /*-----------------------------------------------------------------*/
6244 static void AccSRsh (int shCount)
6245 {
6246     symbol *tlbl ;
6247     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6248     if(shCount != 0){
6249         if(shCount == 1){
6250             pic14_emitcode("mov","c,acc.7");
6251             pic14_emitcode("rrc","a");
6252         } else if(shCount == 2){
6253             pic14_emitcode("mov","c,acc.7");
6254             pic14_emitcode("rrc","a");
6255             pic14_emitcode("mov","c,acc.7");
6256             pic14_emitcode("rrc","a");
6257         } else {
6258             tlbl = newiTempLabel(NULL);
6259             /* rotate right accumulator */
6260             AccRol(8 - shCount);
6261             /* and kill the higher order bits */
6262             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6263             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6264             pic14_emitcode("orl","a,#0x%02x",
6265                      (unsigned char)~SRMask[shCount]);
6266             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6267         }
6268     }
6269 }
6270 #endif
6271 /*-----------------------------------------------------------------*/
6272 /* shiftR1Left2Result - shift right one byte from left to result   */
6273 /*-----------------------------------------------------------------*/
6274 static void shiftR1Left2ResultSigned (operand *left, int offl,
6275                                 operand *result, int offr,
6276                                 int shCount)
6277 {
6278   int same;
6279
6280   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6281
6282   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6283
6284   switch(shCount) {
6285   case 1:
6286     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6287     if(same) 
6288       emitpcode(POC_RRF, popGet(AOP(result),offr));
6289     else {
6290       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6291       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6292     }
6293
6294     break;
6295   case 2:
6296
6297     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6298     if(same) 
6299       emitpcode(POC_RRF, popGet(AOP(result),offr));
6300     else {
6301       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6302       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6303     }
6304     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6305     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6306
6307     break;
6308
6309   case 3:
6310     if(same)
6311       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6312     else {
6313       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6314       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6315     }
6316
6317     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6318     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6319     emitpcode(POC_ANDLW, popGetLit(0x1f));
6320
6321     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6322     emitpcode(POC_IORLW, popGetLit(0xe0));
6323
6324     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6325     break;
6326
6327   case 4:
6328     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6329     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6330     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6331     emitpcode(POC_IORLW,  popGetLit(0xf0));
6332     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6333     break;
6334   case 5:
6335     if(same) {
6336       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6337     } else {
6338       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6339       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6340     }
6341     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6342     emitpcode(POC_ANDLW,  popGetLit(0x07));
6343     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6344     emitpcode(POC_IORLW,  popGetLit(0xf8));
6345     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6346     break;
6347
6348   case 6:
6349     if(same) {
6350       emitpcode(POC_MOVLW, popGetLit(0x00));
6351       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6352       emitpcode(POC_MOVLW, popGetLit(0xfe));
6353       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6354       emitpcode(POC_IORLW, popGetLit(0x01));
6355       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6356     } else {
6357       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6358       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6359       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6360       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6361       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6362     }
6363     break;
6364
6365   case 7:
6366     if(same) {
6367       emitpcode(POC_MOVLW, popGetLit(0x00));
6368       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6369       emitpcode(POC_MOVLW, popGetLit(0xff));
6370       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6371     } else {
6372       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6373       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6374       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6375     }
6376
6377   default:
6378     break;
6379   }
6380 }
6381
6382 /*-----------------------------------------------------------------*/
6383 /* shiftR1Left2Result - shift right one byte from left to result   */
6384 /*-----------------------------------------------------------------*/
6385 static void shiftR1Left2Result (operand *left, int offl,
6386                                 operand *result, int offr,
6387                                 int shCount, int sign)
6388 {
6389   int same;
6390
6391   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6392
6393   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6394
6395   /* Copy the msb into the carry if signed. */
6396   if(sign) {
6397     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6398     return;
6399   }
6400
6401
6402
6403   switch(shCount) {
6404   case 1:
6405     emitCLRC;
6406     if(same) 
6407       emitpcode(POC_RRF, popGet(AOP(result),offr));
6408     else {
6409       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6410       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6411     }
6412     break;
6413   case 2:
6414     emitCLRC;
6415     if(same) {
6416       emitpcode(POC_RRF, popGet(AOP(result),offr));
6417     } else {
6418       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6419       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6420     }
6421     emitCLRC;
6422     emitpcode(POC_RRF, popGet(AOP(result),offr));
6423
6424     break;
6425   case 3:
6426     if(same)
6427       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6428     else {
6429       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6430       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6431     }
6432
6433     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6434     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6435     emitpcode(POC_ANDLW, popGetLit(0x1f));
6436     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6437     break;
6438       
6439   case 4:
6440     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6441     emitpcode(POC_ANDLW, popGetLit(0x0f));
6442     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6443     break;
6444
6445   case 5:
6446     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6447     emitpcode(POC_ANDLW, popGetLit(0x0f));
6448     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6449     emitCLRC;
6450     emitpcode(POC_RRF, popGet(AOP(result),offr));
6451
6452     break;
6453   case 6:
6454
6455     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6456     emitpcode(POC_ANDLW, popGetLit(0x80));
6457     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6458     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6459     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6460     break;
6461
6462   case 7:
6463
6464     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6465     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6466     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6467
6468     break;
6469
6470   default:
6471     break;
6472   }
6473 }
6474
6475 /*-----------------------------------------------------------------*/
6476 /* shiftL1Left2Result - shift left one byte from left to result    */
6477 /*-----------------------------------------------------------------*/
6478 static void shiftL1Left2Result (operand *left, int offl,
6479                                 operand *result, int offr, int shCount)
6480 {
6481   int same;
6482
6483   //    char *l;
6484   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6485
6486   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6487   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6488     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6489     //    MOVA(l);
6490     /* shift left accumulator */
6491     //AccLsh(shCount); // don't comment out just yet...
6492   //    aopPut(AOP(result),"a",offr);
6493
6494   switch(shCount) {
6495   case 1:
6496     /* Shift left 1 bit position */
6497     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6498     if(same) {
6499       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6500     } else {
6501       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6502       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6503     }
6504     break;
6505   case 2:
6506     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6507     emitpcode(POC_ANDLW,popGetLit(0x7e));
6508     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6509     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6510     break;
6511   case 3:
6512     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6513     emitpcode(POC_ANDLW,popGetLit(0x3e));
6514     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6515     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6516     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6517     break;
6518   case 4:
6519     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6520     emitpcode(POC_ANDLW, popGetLit(0xf0));
6521     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6522     break;
6523   case 5:
6524     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6525     emitpcode(POC_ANDLW, popGetLit(0xf0));
6526     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6527     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6528     break;
6529   case 6:
6530     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6531     emitpcode(POC_ANDLW, popGetLit(0x30));
6532     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6533     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6534     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6535     break;
6536   case 7:
6537     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6538     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6539     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6540     break;
6541
6542   default:
6543     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6544   }
6545
6546 }
6547
6548 /*-----------------------------------------------------------------*/
6549 /* movLeft2Result - move byte from left to result                  */
6550 /*-----------------------------------------------------------------*/
6551 static void movLeft2Result (operand *left, int offl,
6552                             operand *result, int offr)
6553 {
6554   char *l;
6555   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6556   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6557     l = aopGet(AOP(left),offl,FALSE,FALSE);
6558
6559     if (*l == '@' && (IS_AOP_PREG(result))) {
6560       pic14_emitcode("mov","a,%s",l);
6561       aopPut(AOP(result),"a",offr);
6562     } else {
6563       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6564       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6565     }
6566   }
6567 }
6568
6569 /*-----------------------------------------------------------------*/
6570 /* shiftL2Left2Result - shift left two bytes from left to result   */
6571 /*-----------------------------------------------------------------*/
6572 static void shiftL2Left2Result (operand *left, int offl,
6573                                 operand *result, int offr, int shCount)
6574 {
6575
6576
6577   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6578
6579   if(pic14_sameRegs(AOP(result), AOP(left))) {
6580     switch(shCount) {
6581     case 0:
6582       break;
6583     case 1:
6584     case 2:
6585     case 3:
6586
6587       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6588       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6589       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6590
6591       while(--shCount) {
6592         emitCLRC;
6593         emitpcode(POC_RLF, popGet(AOP(result),offr));
6594         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6595       }
6596
6597       break;
6598     case 4:
6599     case 5:
6600       emitpcode(POC_MOVLW, popGetLit(0x0f));
6601       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6602       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6603       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6604       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6605       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6606       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6607       if(shCount >=5) {
6608         emitpcode(POC_RLF, popGet(AOP(result),offr));
6609         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6610       }
6611       break;
6612     case 6:
6613       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6614       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6615       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6616       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6617       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6618       emitpcode(POC_ANDLW,popGetLit(0xc0));
6619       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6620       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6621       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6622       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6623       break;
6624     case 7:
6625       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6626       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6627       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6628       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6629       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6630     }
6631
6632   } else {
6633     switch(shCount) {
6634     case 0:
6635       break;
6636     case 1:
6637     case 2:
6638     case 3:
6639       /* note, use a mov/add for the shift since the mov has a
6640          chance of getting optimized out */
6641       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6642       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6643       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6644       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6645       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6646
6647       while(--shCount) {
6648         emitCLRC;
6649         emitpcode(POC_RLF, popGet(AOP(result),offr));
6650         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6651       }
6652       break;
6653
6654     case 4:
6655     case 5:
6656       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6657       emitpcode(POC_ANDLW, popGetLit(0xF0));
6658       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6659       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6660       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6661       emitpcode(POC_ANDLW, popGetLit(0xF0));
6662       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6663       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6664
6665
6666       if(shCount == 5) {
6667         emitpcode(POC_RLF, popGet(AOP(result),offr));
6668         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6669       }
6670       break;
6671     case 6:
6672       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6673       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6674       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6675       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6676
6677       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6678       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6679       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6680       emitpcode(POC_ANDLW,popGetLit(0xc0));
6681       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6682       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6683       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6684       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6685       break;
6686     case 7:
6687       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6688       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6689       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6690       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6691       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6692     }
6693   }
6694
6695 }
6696 /*-----------------------------------------------------------------*/
6697 /* shiftR2Left2Result - shift right two bytes from left to result  */
6698 /*-----------------------------------------------------------------*/
6699 static void shiftR2Left2Result (operand *left, int offl,
6700                                 operand *result, int offr,
6701                                 int shCount, int sign)
6702 {
6703   int same=0;
6704
6705   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6706   same = pic14_sameRegs(AOP(result), AOP(left));
6707
6708   if(same && ((offl + MSB16) == offr)){
6709     same=1;
6710     /* don't crash result[offr] */
6711     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6712     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6713   } else {
6714     movLeft2Result(left,offl, result, offr);
6715     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6716   }
6717   /* a:x >> shCount (x = lsb(result))*/
6718 /*
6719   if(sign)
6720     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6721   else {
6722     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6723 */
6724   switch(shCount) {
6725   case 0:
6726     break;
6727   case 1:
6728   case 2:
6729   case 3:
6730     if(sign)
6731       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6732     else
6733       emitCLRC;
6734
6735     if(same) {
6736       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6737       emitpcode(POC_RRF,popGet(AOP(result),offr));
6738     } else {
6739       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6740       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6741       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6742       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6743     }
6744
6745     while(--shCount) {
6746       if(sign)
6747         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6748       else
6749         emitCLRC;
6750       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6751       emitpcode(POC_RRF,popGet(AOP(result),offr));
6752     }
6753     break;
6754   case 4:
6755   case 5:
6756     if(same) {
6757
6758       emitpcode(POC_MOVLW, popGetLit(0xf0));
6759       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6760       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6761
6762       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6763       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6764       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6765       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6766     } else {
6767       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6768       emitpcode(POC_ANDLW, popGetLit(0x0f));
6769       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6770
6771       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6772       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6773       emitpcode(POC_ANDLW, popGetLit(0xf0));
6774       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6775       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6776     }
6777
6778     if(shCount >=5) {
6779       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6780       emitpcode(POC_RRF, popGet(AOP(result),offr));
6781     }
6782
6783     if(sign) {
6784       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6785       emitpcode(POC_BTFSC, 
6786                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6787       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6788     }
6789
6790     break;
6791
6792   case 6:
6793     if(same) {
6794
6795       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6796       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6797
6798       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6799       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6800       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6801       emitpcode(POC_ANDLW,popGetLit(0x03));
6802       if(sign) {
6803         emitpcode(POC_BTFSC, 
6804                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6805         emitpcode(POC_IORLW,popGetLit(0xfc));
6806       }
6807       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6809       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6810       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6811     } else {
6812       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6813       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6814       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6815       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6816       emitpcode(POC_RLFW,  popGet(AOP(result),offr+MSB16));
6817       emitpcode(POC_ANDLW,popGetLit(0x03));
6818       if(sign) {
6819         emitpcode(POC_BTFSC, 
6820                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6821         emitpcode(POC_IORLW,popGetLit(0xfc));
6822       }
6823       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6824       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6825
6826         
6827     }
6828
6829     break;
6830   case 7:
6831     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6832     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6833     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6834     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6835     if(sign) {
6836       emitSKPNC;
6837       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6838     } else 
6839       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6840   }
6841 }
6842
6843
6844 /*-----------------------------------------------------------------*/
6845 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6846 /*-----------------------------------------------------------------*/
6847 static void shiftLLeftOrResult (operand *left, int offl,
6848                                 operand *result, int offr, int shCount)
6849 {
6850     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6851     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6852     /* shift left accumulator */
6853     AccLsh(shCount);
6854     /* or with result */
6855     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6856     /* back to result */
6857     aopPut(AOP(result),"a",offr);
6858 }
6859
6860 /*-----------------------------------------------------------------*/
6861 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6862 /*-----------------------------------------------------------------*/
6863 static void shiftRLeftOrResult (operand *left, int offl,
6864                                 operand *result, int offr, int shCount)
6865 {
6866     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6867     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6868     /* shift right accumulator */
6869     AccRsh(shCount);
6870     /* or with result */
6871     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6872     /* back to result */
6873     aopPut(AOP(result),"a",offr);
6874 }
6875
6876 /*-----------------------------------------------------------------*/
6877 /* genlshOne - left shift a one byte quantity by known count       */
6878 /*-----------------------------------------------------------------*/
6879 static void genlshOne (operand *result, operand *left, int shCount)
6880 {       
6881     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6882     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6883 }
6884
6885 /*-----------------------------------------------------------------*/
6886 /* genlshTwo - left shift two bytes by known amount != 0           */
6887 /*-----------------------------------------------------------------*/
6888 static void genlshTwo (operand *result,operand *left, int shCount)
6889 {
6890     int size;
6891     
6892     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6893     size = pic14_getDataSize(result);
6894
6895     /* if shCount >= 8 */
6896     if (shCount >= 8) {
6897         shCount -= 8 ;
6898
6899         if (size > 1){
6900             if (shCount)
6901                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6902             else 
6903                 movLeft2Result(left, LSB, result, MSB16);
6904         }
6905         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6906     }
6907
6908     /*  1 <= shCount <= 7 */
6909     else {  
6910         if(size == 1)
6911             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6912         else 
6913             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6914     }
6915 }
6916
6917 /*-----------------------------------------------------------------*/
6918 /* shiftLLong - shift left one long from left to result            */
6919 /* offl = LSB or MSB16                                             */
6920 /*-----------------------------------------------------------------*/
6921 static void shiftLLong (operand *left, operand *result, int offr )
6922 {
6923     char *l;
6924     int size = AOP_SIZE(result);
6925
6926     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6927     if(size >= LSB+offr){
6928         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6929         MOVA(l);
6930         pic14_emitcode("add","a,acc");
6931         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6932             size >= MSB16+offr && offr != LSB )
6933             pic14_emitcode("xch","a,%s",
6934                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6935         else        
6936             aopPut(AOP(result),"a",LSB+offr);
6937     }
6938
6939     if(size >= MSB16+offr){
6940         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6941             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6942             MOVA(l);
6943         }
6944         pic14_emitcode("rlc","a");
6945         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6946             size >= MSB24+offr && offr != LSB)
6947             pic14_emitcode("xch","a,%s",
6948                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6949         else        
6950             aopPut(AOP(result),"a",MSB16+offr);
6951     }
6952
6953     if(size >= MSB24+offr){
6954         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6955             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6956             MOVA(l);
6957         }
6958         pic14_emitcode("rlc","a");
6959         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6960             size >= MSB32+offr && offr != LSB )
6961             pic14_emitcode("xch","a,%s",
6962                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6963         else        
6964             aopPut(AOP(result),"a",MSB24+offr);
6965     }
6966
6967     if(size > MSB32+offr){
6968         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6969             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6970             MOVA(l);    
6971         }
6972         pic14_emitcode("rlc","a");
6973         aopPut(AOP(result),"a",MSB32+offr);
6974     }
6975     if(offr != LSB)
6976         aopPut(AOP(result),zero,LSB);       
6977 }
6978
6979 /*-----------------------------------------------------------------*/
6980 /* genlshFour - shift four byte by a known amount != 0             */
6981 /*-----------------------------------------------------------------*/
6982 static void genlshFour (operand *result, operand *left, int shCount)
6983 {
6984     int size;
6985
6986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6987     size = AOP_SIZE(result);
6988
6989     /* if shifting more that 3 bytes */
6990     if (shCount >= 24 ) {
6991         shCount -= 24;
6992         if (shCount)
6993             /* lowest order of left goes to the highest
6994             order of the destination */
6995             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6996         else
6997             movLeft2Result(left, LSB, result, MSB32);
6998         aopPut(AOP(result),zero,LSB);
6999         aopPut(AOP(result),zero,MSB16);
7000         aopPut(AOP(result),zero,MSB32);
7001         return;
7002     }
7003
7004     /* more than two bytes */
7005     else if ( shCount >= 16 ) {
7006         /* lower order two bytes goes to higher order two bytes */
7007         shCount -= 16;
7008         /* if some more remaining */
7009         if (shCount)
7010             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7011         else {
7012             movLeft2Result(left, MSB16, result, MSB32);
7013             movLeft2Result(left, LSB, result, MSB24);
7014         }
7015         aopPut(AOP(result),zero,MSB16);
7016         aopPut(AOP(result),zero,LSB);
7017         return;
7018     }    
7019
7020     /* if more than 1 byte */
7021     else if ( shCount >= 8 ) {
7022         /* lower order three bytes goes to higher order  three bytes */
7023         shCount -= 8;
7024         if(size == 2){
7025             if(shCount)
7026                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7027             else
7028                 movLeft2Result(left, LSB, result, MSB16);
7029         }
7030         else{   /* size = 4 */
7031             if(shCount == 0){
7032                 movLeft2Result(left, MSB24, result, MSB32);
7033                 movLeft2Result(left, MSB16, result, MSB24);
7034                 movLeft2Result(left, LSB, result, MSB16);
7035                 aopPut(AOP(result),zero,LSB);
7036             }
7037             else if(shCount == 1)
7038                 shiftLLong(left, result, MSB16);
7039             else{
7040                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7041                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7042                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7043                 aopPut(AOP(result),zero,LSB);
7044             }
7045         }
7046     }
7047
7048     /* 1 <= shCount <= 7 */
7049     else if(shCount <= 2){
7050         shiftLLong(left, result, LSB);
7051         if(shCount == 2)
7052             shiftLLong(result, result, LSB);
7053     }
7054     /* 3 <= shCount <= 7, optimize */
7055     else{
7056         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7057         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7058         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7059     }
7060 }
7061
7062 /*-----------------------------------------------------------------*/
7063 /* genLeftShiftLiteral - left shifting by known count              */
7064 /*-----------------------------------------------------------------*/
7065 static void genLeftShiftLiteral (operand *left,
7066                                  operand *right,
7067                                  operand *result,
7068                                  iCode *ic)
7069 {    
7070     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7071     int size;
7072
7073     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7074     freeAsmop(right,NULL,ic,TRUE);
7075
7076     aopOp(left,ic,FALSE);
7077     aopOp(result,ic,FALSE);
7078
7079     size = getSize(operandType(result));
7080
7081 #if VIEW_SIZE
7082     pic14_emitcode("; shift left ","result %d, left %d",size,
7083              AOP_SIZE(left));
7084 #endif
7085
7086     /* I suppose that the left size >= result size */
7087     if(shCount == 0){
7088         while(size--){
7089             movLeft2Result(left, size, result, size);
7090         }
7091     }
7092
7093     else if(shCount >= (size * 8))
7094         while(size--)
7095             aopPut(AOP(result),zero,size);
7096     else{
7097         switch (size) {
7098             case 1:
7099                 genlshOne (result,left,shCount);
7100                 break;
7101
7102             case 2:
7103             case 3:
7104                 genlshTwo (result,left,shCount);
7105                 break;
7106
7107             case 4:
7108                 genlshFour (result,left,shCount);
7109                 break;
7110         }
7111     }
7112     freeAsmop(left,NULL,ic,TRUE);
7113     freeAsmop(result,NULL,ic,TRUE);
7114 }
7115
7116 /*-----------------------------------------------------------------*
7117  * genMultiAsm - repeat assembly instruction for size of register.
7118  * if endian == 1, then the high byte (i.e base address + size of 
7119  * register) is used first else the low byte is used first;
7120  *-----------------------------------------------------------------*/
7121 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7122 {
7123
7124   int offset = 0;
7125
7126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7127
7128   if(!reg)
7129     return;
7130
7131   if(!endian) {
7132     endian = 1;
7133   } else {
7134     endian = -1;
7135     offset = size-1;
7136   }
7137
7138   while(size--) {
7139     emitpcode(poc,    popGet(AOP(reg),offset));
7140     offset += endian;
7141   }
7142
7143 }
7144 /*-----------------------------------------------------------------*/
7145 /* genLeftShift - generates code for left shifting                 */
7146 /*-----------------------------------------------------------------*/
7147 static void genLeftShift (iCode *ic)
7148 {
7149   operand *left,*right, *result;
7150   int size, offset;
7151   char *l;
7152   symbol *tlbl , *tlbl1;
7153   pCodeOp *pctemp;
7154
7155   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7156
7157   right = IC_RIGHT(ic);
7158   left  = IC_LEFT(ic);
7159   result = IC_RESULT(ic);
7160
7161   aopOp(right,ic,FALSE);
7162
7163   /* if the shift count is known then do it 
7164      as efficiently as possible */
7165   if (AOP_TYPE(right) == AOP_LIT) {
7166     genLeftShiftLiteral (left,right,result,ic);
7167     return ;
7168   }
7169
7170   /* shift count is unknown then we have to form 
7171      a loop get the loop count in B : Note: we take
7172      only the lower order byte since shifting
7173      more that 32 bits make no sense anyway, ( the
7174      largest size of an object can be only 32 bits ) */  
7175
7176     
7177   aopOp(left,ic,FALSE);
7178   aopOp(result,ic,FALSE);
7179
7180   /* now move the left to the result if they are not the
7181      same */
7182   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7183       AOP_SIZE(result) > 1) {
7184
7185     size = AOP_SIZE(result);
7186     offset=0;
7187     while (size--) {
7188       l = aopGet(AOP(left),offset,FALSE,TRUE);
7189       if (*l == '@' && (IS_AOP_PREG(result))) {
7190
7191         pic14_emitcode("mov","a,%s",l);
7192         aopPut(AOP(result),"a",offset);
7193       } else {
7194         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7195         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7196         //aopPut(AOP(result),l,offset);
7197       }
7198       offset++;
7199     }
7200   }
7201
7202   size = AOP_SIZE(result);
7203
7204   /* if it is only one byte then */
7205   if (size == 1) {
7206     if(optimized_for_speed) {
7207       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7208       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7209       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7210       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7211       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7212       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7213       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7214       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7215       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7216       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7217       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7218       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7219     } else {
7220
7221       tlbl = newiTempLabel(NULL);
7222       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7223         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7224         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7225       }
7226
7227       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7228       emitpcode(POC_RRF,    popGet(AOP(result),0));
7229       emitpLabel(tlbl->key);
7230       emitpcode(POC_RLF,    popGet(AOP(result),0));
7231       emitpcode(POC_ADDLW,  popGetLit(1));
7232       emitSKPC;
7233       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7234     }
7235     goto release ;
7236   }
7237     
7238   if (pic14_sameRegs(AOP(left),AOP(result))) {
7239
7240     tlbl = newiTempLabel(NULL);
7241     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7242     genMultiAsm(POC_RRF, result, size,1);
7243     emitpLabel(tlbl->key);
7244     genMultiAsm(POC_RLF, result, size,0);
7245     emitpcode(POC_ADDLW,  popGetLit(1));
7246     emitSKPC;
7247     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7248     goto release;
7249   }
7250
7251   //tlbl = newiTempLabel(NULL);
7252   //offset = 0 ;   
7253   //tlbl1 = newiTempLabel(NULL);
7254
7255   //reAdjustPreg(AOP(result));    
7256     
7257   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7258   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7259   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7260   //MOVA(l);
7261   //pic14_emitcode("add","a,acc");         
7262   //aopPut(AOP(result),"a",offset++);
7263   //while (--size) {
7264   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7265   //  MOVA(l);
7266   //  pic14_emitcode("rlc","a");         
7267   //  aopPut(AOP(result),"a",offset++);
7268   //}
7269   //reAdjustPreg(AOP(result));
7270
7271   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7272   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7273
7274
7275   tlbl = newiTempLabel(NULL);
7276   tlbl1= newiTempLabel(NULL);
7277
7278   size = AOP_SIZE(result);
7279   offset = 1;
7280
7281   pctemp = popGetTempReg();  /* grab a temporary working register. */
7282
7283   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7284
7285   /* offset should be 0, 1 or 3 */
7286   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7287   emitSKPNZ;
7288   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7289
7290   emitpcode(POC_MOVWF, pctemp);
7291
7292
7293   emitpLabel(tlbl->key);
7294
7295   emitCLRC;
7296   emitpcode(POC_RLF,  popGet(AOP(result),0));
7297   while(--size)
7298     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7299
7300   emitpcode(POC_DECFSZ,  pctemp);
7301   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7302   emitpLabel(tlbl1->key);
7303
7304   popReleaseTempReg(pctemp);
7305
7306
7307  release:
7308   freeAsmop (right,NULL,ic,TRUE);
7309   freeAsmop(left,NULL,ic,TRUE);
7310   freeAsmop(result,NULL,ic,TRUE);
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* genrshOne - right shift a one byte quantity by known count      */
7315 /*-----------------------------------------------------------------*/
7316 static void genrshOne (operand *result, operand *left,
7317                        int shCount, int sign)
7318 {
7319     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7320     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7321 }
7322
7323 /*-----------------------------------------------------------------*/
7324 /* genrshTwo - right shift two bytes by known amount != 0          */
7325 /*-----------------------------------------------------------------*/
7326 static void genrshTwo (operand *result,operand *left,
7327                        int shCount, int sign)
7328 {
7329   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7330   /* if shCount >= 8 */
7331   if (shCount >= 8) {
7332     shCount -= 8 ;
7333     if (shCount)
7334       shiftR1Left2Result(left, MSB16, result, LSB,
7335                          shCount, sign);
7336     else
7337       movLeft2Result(left, MSB16, result, LSB);
7338
7339     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7340
7341     if(sign) {
7342       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7343       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7344     }
7345   }
7346
7347   /*  1 <= shCount <= 7 */
7348   else
7349     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* shiftRLong - shift right one long from left to result           */
7354 /* offl = LSB or MSB16                                             */
7355 /*-----------------------------------------------------------------*/
7356 static void shiftRLong (operand *left, int offl,
7357                         operand *result, int sign)
7358 {
7359     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7360     if(!sign)
7361         pic14_emitcode("clr","c");
7362     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7363     if(sign)
7364         pic14_emitcode("mov","c,acc.7");
7365     pic14_emitcode("rrc","a");
7366     aopPut(AOP(result),"a",MSB32-offl);
7367     if(offl == MSB16)
7368         /* add sign of "a" */
7369         addSign(result, MSB32, sign);
7370
7371     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7372     pic14_emitcode("rrc","a");
7373     aopPut(AOP(result),"a",MSB24-offl);
7374
7375     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7376     pic14_emitcode("rrc","a");
7377     aopPut(AOP(result),"a",MSB16-offl);
7378
7379     if(offl == LSB){
7380         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7381         pic14_emitcode("rrc","a");
7382         aopPut(AOP(result),"a",LSB);
7383     }
7384 }
7385
7386 /*-----------------------------------------------------------------*/
7387 /* genrshFour - shift four byte by a known amount != 0             */
7388 /*-----------------------------------------------------------------*/
7389 static void genrshFour (operand *result, operand *left,
7390                         int shCount, int sign)
7391 {
7392   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7393   /* if shifting more that 3 bytes */
7394   if(shCount >= 24 ) {
7395     shCount -= 24;
7396     if(shCount)
7397       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7398     else
7399       movLeft2Result(left, MSB32, result, LSB);
7400
7401     addSign(result, MSB16, sign);
7402   }
7403   else if(shCount >= 16){
7404     shCount -= 16;
7405     if(shCount)
7406       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7407     else{
7408       movLeft2Result(left, MSB24, result, LSB);
7409       movLeft2Result(left, MSB32, result, MSB16);
7410     }
7411     addSign(result, MSB24, sign);
7412   }
7413   else if(shCount >= 8){
7414     shCount -= 8;
7415     if(shCount == 1)
7416       shiftRLong(left, MSB16, result, sign);
7417     else if(shCount == 0){
7418       movLeft2Result(left, MSB16, result, LSB);
7419       movLeft2Result(left, MSB24, result, MSB16);
7420       movLeft2Result(left, MSB32, result, MSB24);
7421       addSign(result, MSB32, sign);
7422     }
7423     else{
7424       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7425       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7426       /* the last shift is signed */
7427       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7428       addSign(result, MSB32, sign);
7429     }
7430   }
7431   else{   /* 1 <= shCount <= 7 */
7432     if(shCount <= 2){
7433       shiftRLong(left, LSB, result, sign);
7434       if(shCount == 2)
7435         shiftRLong(result, LSB, result, sign);
7436     }
7437     else{
7438       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7439       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7440       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7441     }
7442   }
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genRightShiftLiteral - right shifting by known count            */
7447 /*-----------------------------------------------------------------*/
7448 static void genRightShiftLiteral (operand *left,
7449                                   operand *right,
7450                                   operand *result,
7451                                   iCode *ic,
7452                                   int sign)
7453 {    
7454   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7455   int lsize,res_size;
7456
7457   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458   freeAsmop(right,NULL,ic,TRUE);
7459
7460   aopOp(left,ic,FALSE);
7461   aopOp(result,ic,FALSE);
7462
7463 #if VIEW_SIZE
7464   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7465                  AOP_SIZE(left));
7466 #endif
7467
7468   lsize = pic14_getDataSize(left);
7469   res_size = pic14_getDataSize(result);
7470   /* test the LEFT size !!! */
7471
7472   /* I suppose that the left size >= result size */
7473   if(shCount == 0){
7474     while(res_size--)
7475       movLeft2Result(left, lsize, result, res_size);
7476   }
7477
7478   else if(shCount >= (lsize * 8)){
7479
7480     if(res_size == 1) {
7481       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7482       if(sign) {
7483         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7484         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7485       }
7486     } else {
7487
7488       if(sign) {
7489         emitpcode(POC_MOVLW, popGetLit(0));
7490         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7491         emitpcode(POC_MOVLW, popGetLit(0xff));
7492         while(res_size--)
7493           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7494
7495       } else {
7496
7497         while(res_size--)
7498           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7499       }
7500     }
7501   } else {
7502
7503     switch (res_size) {
7504     case 1:
7505       genrshOne (result,left,shCount,sign);
7506       break;
7507
7508     case 2:
7509       genrshTwo (result,left,shCount,sign);
7510       break;
7511
7512     case 4:
7513       genrshFour (result,left,shCount,sign);
7514       break;
7515     default :
7516       break;
7517     }
7518
7519   }
7520
7521   freeAsmop(left,NULL,ic,TRUE);
7522   freeAsmop(result,NULL,ic,TRUE);
7523 }
7524
7525 /*-----------------------------------------------------------------*/
7526 /* genSignedRightShift - right shift of signed number              */
7527 /*-----------------------------------------------------------------*/
7528 static void genSignedRightShift (iCode *ic)
7529 {
7530   operand *right, *left, *result;
7531   int size, offset;
7532   //  char *l;
7533   symbol *tlbl, *tlbl1 ;
7534   pCodeOp *pctemp;
7535
7536   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7537
7538   /* we do it the hard way put the shift count in b
7539      and loop thru preserving the sign */
7540   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7541
7542   right = IC_RIGHT(ic);
7543   left  = IC_LEFT(ic);
7544   result = IC_RESULT(ic);
7545
7546   aopOp(right,ic,FALSE);  
7547   aopOp(left,ic,FALSE);
7548   aopOp(result,ic,FALSE);
7549
7550
7551   if ( AOP_TYPE(right) == AOP_LIT) {
7552     genRightShiftLiteral (left,right,result,ic,1);
7553     return ;
7554   }
7555   /* shift count is unknown then we have to form 
7556      a loop get the loop count in B : Note: we take
7557      only the lower order byte since shifting
7558      more that 32 bits make no sense anyway, ( the
7559      largest size of an object can be only 32 bits ) */  
7560
7561   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7562   //pic14_emitcode("inc","b");
7563   //freeAsmop (right,NULL,ic,TRUE);
7564   //aopOp(left,ic,FALSE);
7565   //aopOp(result,ic,FALSE);
7566
7567   /* now move the left to the result if they are not the
7568      same */
7569   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7570       AOP_SIZE(result) > 1) {
7571
7572     size = AOP_SIZE(result);
7573     offset=0;
7574     while (size--) { 
7575       /*
7576         l = aopGet(AOP(left),offset,FALSE,TRUE);
7577         if (*l == '@' && IS_AOP_PREG(result)) {
7578
7579         pic14_emitcode("mov","a,%s",l);
7580         aopPut(AOP(result),"a",offset);
7581         } else
7582         aopPut(AOP(result),l,offset);
7583       */
7584       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7585       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7586
7587       offset++;
7588     }
7589   }
7590
7591   /* mov the highest order bit to OVR */    
7592   tlbl = newiTempLabel(NULL);
7593   tlbl1= newiTempLabel(NULL);
7594
7595   size = AOP_SIZE(result);
7596   offset = size - 1;
7597
7598   pctemp = popGetTempReg();  /* grab a temporary working register. */
7599
7600   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7601
7602   /* offset should be 0, 1 or 3 */
7603   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7604   emitSKPNZ;
7605   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7606
7607   emitpcode(POC_MOVWF, pctemp);
7608
7609
7610   emitpLabel(tlbl->key);
7611
7612   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7613   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7614
7615   while(--size) {
7616     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7617   }
7618
7619   emitpcode(POC_DECFSZ,  pctemp);
7620   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7621   emitpLabel(tlbl1->key);
7622
7623   popReleaseTempReg(pctemp);
7624 #if 0
7625   size = AOP_SIZE(result);
7626   offset = size - 1;
7627   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7628   pic14_emitcode("rlc","a");
7629   pic14_emitcode("mov","ov,c");
7630   /* if it is only one byte then */
7631   if (size == 1) {
7632     l = aopGet(AOP(left),0,FALSE,FALSE);
7633     MOVA(l);
7634     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7635     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7636     pic14_emitcode("mov","c,ov");
7637     pic14_emitcode("rrc","a");
7638     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7639     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7640     aopPut(AOP(result),"a",0);
7641     goto release ;
7642   }
7643
7644   reAdjustPreg(AOP(result));
7645   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7646   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7647   pic14_emitcode("mov","c,ov");
7648   while (size--) {
7649     l = aopGet(AOP(result),offset,FALSE,FALSE);
7650     MOVA(l);
7651     pic14_emitcode("rrc","a");         
7652     aopPut(AOP(result),"a",offset--);
7653   }
7654   reAdjustPreg(AOP(result));
7655   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7656   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7657
7658  release:
7659 #endif
7660
7661   freeAsmop(left,NULL,ic,TRUE);
7662   freeAsmop(result,NULL,ic,TRUE);
7663   freeAsmop(right,NULL,ic,TRUE);
7664 }
7665
7666 /*-----------------------------------------------------------------*/
7667 /* genRightShift - generate code for right shifting                */
7668 /*-----------------------------------------------------------------*/
7669 static void genRightShift (iCode *ic)
7670 {
7671     operand *right, *left, *result;
7672     sym_link *retype ;
7673     int size, offset;
7674     char *l;
7675     symbol *tlbl, *tlbl1 ;
7676
7677     /* if signed then we do it the hard way preserve the
7678     sign bit moving it inwards */
7679     retype = getSpec(operandType(IC_RESULT(ic)));
7680     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7681
7682     if (!SPEC_USIGN(retype)) {
7683         genSignedRightShift (ic);
7684         return ;
7685     }
7686
7687     /* signed & unsigned types are treated the same : i.e. the
7688     signed is NOT propagated inwards : quoting from the
7689     ANSI - standard : "for E1 >> E2, is equivalent to division
7690     by 2**E2 if unsigned or if it has a non-negative value,
7691     otherwise the result is implementation defined ", MY definition
7692     is that the sign does not get propagated */
7693
7694     right = IC_RIGHT(ic);
7695     left  = IC_LEFT(ic);
7696     result = IC_RESULT(ic);
7697
7698     aopOp(right,ic,FALSE);
7699
7700     /* if the shift count is known then do it 
7701     as efficiently as possible */
7702     if (AOP_TYPE(right) == AOP_LIT) {
7703         genRightShiftLiteral (left,right,result,ic, 0);
7704         return ;
7705     }
7706
7707     /* shift count is unknown then we have to form 
7708     a loop get the loop count in B : Note: we take
7709     only the lower order byte since shifting
7710     more that 32 bits make no sense anyway, ( the
7711     largest size of an object can be only 32 bits ) */  
7712
7713     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7714     pic14_emitcode("inc","b");
7715     aopOp(left,ic,FALSE);
7716     aopOp(result,ic,FALSE);
7717
7718     /* now move the left to the result if they are not the
7719     same */
7720     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7721         AOP_SIZE(result) > 1) {
7722
7723         size = AOP_SIZE(result);
7724         offset=0;
7725         while (size--) {
7726             l = aopGet(AOP(left),offset,FALSE,TRUE);
7727             if (*l == '@' && IS_AOP_PREG(result)) {
7728
7729                 pic14_emitcode("mov","a,%s",l);
7730                 aopPut(AOP(result),"a",offset);
7731             } else
7732                 aopPut(AOP(result),l,offset);
7733             offset++;
7734         }
7735     }
7736
7737     tlbl = newiTempLabel(NULL);
7738     tlbl1= newiTempLabel(NULL);
7739     size = AOP_SIZE(result);
7740     offset = size - 1;
7741
7742     /* if it is only one byte then */
7743     if (size == 1) {
7744
7745       tlbl = newiTempLabel(NULL);
7746       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7747         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7748         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7749       }
7750
7751       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7752       emitpcode(POC_RLF,    popGet(AOP(result),0));
7753       emitpLabel(tlbl->key);
7754       emitpcode(POC_RRF,    popGet(AOP(result),0));
7755       emitpcode(POC_ADDLW,  popGetLit(1));
7756       emitSKPC;
7757       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7758
7759       goto release ;
7760     }
7761
7762     reAdjustPreg(AOP(result));
7763     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7764     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7765     CLRC;
7766     while (size--) {
7767         l = aopGet(AOP(result),offset,FALSE,FALSE);
7768         MOVA(l);
7769         pic14_emitcode("rrc","a");         
7770         aopPut(AOP(result),"a",offset--);
7771     }
7772     reAdjustPreg(AOP(result));
7773
7774     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7775     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7776
7777 release:
7778     freeAsmop(left,NULL,ic,TRUE);
7779     freeAsmop (right,NULL,ic,TRUE);
7780     freeAsmop(result,NULL,ic,TRUE);
7781 }
7782
7783 /*-----------------------------------------------------------------*/
7784 /* genUnpackBits - generates code for unpacking bits               */
7785 /*-----------------------------------------------------------------*/
7786 static void genUnpackBits (operand *result, char *rname, int ptype)
7787 {    
7788     int shCnt ;
7789     int rlen = 0 ;
7790     sym_link *etype;
7791     int offset = 0 ;
7792
7793     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7794     etype = getSpec(operandType(result));
7795
7796     /* read the first byte  */
7797     switch (ptype) {
7798
7799     case POINTER:
7800     case IPOINTER:
7801         pic14_emitcode("mov","a,@%s",rname);
7802         break;
7803         
7804     case PPOINTER:
7805         pic14_emitcode("movx","a,@%s",rname);
7806         break;
7807         
7808     case FPOINTER:
7809         pic14_emitcode("movx","a,@dptr");
7810         break;
7811
7812     case CPOINTER:
7813         pic14_emitcode("clr","a");
7814         pic14_emitcode("movc","a","@a+dptr");
7815         break;
7816
7817     case GPOINTER:
7818         pic14_emitcode("lcall","__gptrget");
7819         break;
7820     }
7821
7822     /* if we have bitdisplacement then it fits   */
7823     /* into this byte completely or if length is */
7824     /* less than a byte                          */
7825     if ((shCnt = SPEC_BSTR(etype)) || 
7826         (SPEC_BLEN(etype) <= 8))  {
7827
7828         /* shift right acc */
7829         AccRsh(shCnt);
7830
7831         pic14_emitcode("anl","a,#0x%02x",
7832                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7833         aopPut(AOP(result),"a",offset);
7834         return ;
7835     }
7836
7837     /* bit field did not fit in a byte  */
7838     rlen = SPEC_BLEN(etype) - 8;
7839     aopPut(AOP(result),"a",offset++);
7840
7841     while (1)  {
7842
7843         switch (ptype) {
7844         case POINTER:
7845         case IPOINTER:
7846             pic14_emitcode("inc","%s",rname);
7847             pic14_emitcode("mov","a,@%s",rname);
7848             break;
7849             
7850         case PPOINTER:
7851             pic14_emitcode("inc","%s",rname);
7852             pic14_emitcode("movx","a,@%s",rname);
7853             break;
7854
7855         case FPOINTER:
7856             pic14_emitcode("inc","dptr");
7857             pic14_emitcode("movx","a,@dptr");
7858             break;
7859             
7860         case CPOINTER:
7861             pic14_emitcode("clr","a");
7862             pic14_emitcode("inc","dptr");
7863             pic14_emitcode("movc","a","@a+dptr");
7864             break;
7865             
7866         case GPOINTER:
7867             pic14_emitcode("inc","dptr");
7868             pic14_emitcode("lcall","__gptrget");
7869             break;
7870         }
7871
7872         rlen -= 8;            
7873         /* if we are done */
7874         if ( rlen <= 0 )
7875             break ;
7876         
7877         aopPut(AOP(result),"a",offset++);
7878                               
7879     }
7880     
7881     if (rlen) {
7882         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7883         aopPut(AOP(result),"a",offset);        
7884     }
7885     
7886     return ;
7887 }
7888
7889
7890 /*-----------------------------------------------------------------*/
7891 /* genDataPointerGet - generates code when ptr offset is known     */
7892 /*-----------------------------------------------------------------*/
7893 static void genDataPointerGet (operand *left, 
7894                                operand *result, 
7895                                iCode *ic)
7896 {
7897   int size , offset = 0;
7898
7899
7900   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7901
7902
7903   /* optimization - most of the time, left and result are the same
7904    * address, but different types. for the pic code, we could omit
7905    * the following
7906    */
7907
7908   aopOp(result,ic,TRUE);
7909
7910   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7911
7912   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7913
7914   size = AOP_SIZE(result);
7915
7916   while (size--) {
7917     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7918     offset++;
7919   }
7920
7921   freeAsmop(left,NULL,ic,TRUE);
7922   freeAsmop(result,NULL,ic,TRUE);
7923 }
7924
7925 /*-----------------------------------------------------------------*/
7926 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7927 /*-----------------------------------------------------------------*/
7928 static void genNearPointerGet (operand *left, 
7929                                operand *result, 
7930                                iCode *ic)
7931 {
7932     asmop *aop = NULL;
7933     regs *preg = NULL ;
7934     char *rname ;
7935     sym_link *rtype, *retype;
7936     sym_link *ltype = operandType(left);    
7937     char buffer[80];
7938
7939     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940
7941     rtype = operandType(result);
7942     retype= getSpec(rtype);
7943     
7944     aopOp(left,ic,FALSE);
7945     
7946     /* if left is rematerialisable and
7947        result is not bit variable type and
7948        the left is pointer to data space i.e
7949        lower 128 bytes of space */
7950     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7951         !IS_BITVAR(retype)         &&
7952         DCL_TYPE(ltype) == POINTER) {
7953       //genDataPointerGet (left,result,ic);
7954         return ;
7955     }
7956     
7957     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958
7959         /* if the value is already in a pointer register
7960        then don't need anything more */
7961     if (!AOP_INPREG(AOP(left))) {
7962         /* otherwise get a free pointer register */
7963     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964 /*
7965         aop = newAsmop(0);
7966         preg = getFreePtr(ic,&aop,FALSE);
7967         pic14_emitcode("mov","%s,%s",
7968                 preg->name,
7969                 aopGet(AOP(left),0,FALSE,TRUE));
7970         rname = preg->name ;
7971 */
7972     rname ="BAD";
7973     } else
7974         rname = aopGet(AOP(left),0,FALSE,FALSE);
7975     
7976     aopOp (result,ic,FALSE);
7977     
7978       /* if bitfield then unpack the bits */
7979     if (IS_BITVAR(retype)) 
7980         genUnpackBits (result,rname,POINTER);
7981     else {
7982         /* we have can just get the values */
7983       int size = AOP_SIZE(result);
7984       int offset = 0 ;  
7985         
7986       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7987
7988       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7989       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7990       while(size--) {
7991         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7992         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7993         if(size)
7994           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7995       }
7996 /*
7997         while (size--) {
7998             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7999
8000                 pic14_emitcode("mov","a,@%s",rname);
8001                 aopPut(AOP(result),"a",offset);
8002             } else {
8003                 sprintf(buffer,"@%s",rname);
8004                 aopPut(AOP(result),buffer,offset);
8005             }
8006             offset++ ;
8007             if (size)
8008                 pic14_emitcode("inc","%s",rname);
8009         }
8010 */
8011     }
8012
8013     /* now some housekeeping stuff */
8014     if (aop) {
8015         /* we had to allocate for this iCode */
8016     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8017         freeAsmop(NULL,aop,ic,TRUE);
8018     } else { 
8019         /* we did not allocate which means left
8020            already in a pointer register, then
8021            if size > 0 && this could be used again
8022            we have to point it back to where it 
8023            belongs */
8024     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8025         if (AOP_SIZE(result) > 1 &&
8026             !OP_SYMBOL(left)->remat &&
8027             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8028               ic->depth )) {
8029             int size = AOP_SIZE(result) - 1;
8030             while (size--)
8031                 pic14_emitcode("dec","%s",rname);
8032         }
8033     }
8034
8035     /* done */
8036     freeAsmop(left,NULL,ic,TRUE);
8037     freeAsmop(result,NULL,ic,TRUE);
8038      
8039 }
8040
8041 /*-----------------------------------------------------------------*/
8042 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8043 /*-----------------------------------------------------------------*/
8044 static void genPagedPointerGet (operand *left, 
8045                                operand *result, 
8046                                iCode *ic)
8047 {
8048     asmop *aop = NULL;
8049     regs *preg = NULL ;
8050     char *rname ;
8051     sym_link *rtype, *retype;    
8052
8053     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054
8055     rtype = operandType(result);
8056     retype= getSpec(rtype);
8057     
8058     aopOp(left,ic,FALSE);
8059
8060   /* if the value is already in a pointer register
8061        then don't need anything more */
8062     if (!AOP_INPREG(AOP(left))) {
8063         /* otherwise get a free pointer register */
8064         aop = newAsmop(0);
8065         preg = getFreePtr(ic,&aop,FALSE);
8066         pic14_emitcode("mov","%s,%s",
8067                 preg->name,
8068                 aopGet(AOP(left),0,FALSE,TRUE));
8069         rname = preg->name ;
8070     } else
8071         rname = aopGet(AOP(left),0,FALSE,FALSE);
8072     
8073     freeAsmop(left,NULL,ic,TRUE);
8074     aopOp (result,ic,FALSE);
8075
8076     /* if bitfield then unpack the bits */
8077     if (IS_BITVAR(retype)) 
8078         genUnpackBits (result,rname,PPOINTER);
8079     else {
8080         /* we have can just get the values */
8081         int size = AOP_SIZE(result);
8082         int offset = 0 ;        
8083         
8084         while (size--) {
8085             
8086             pic14_emitcode("movx","a,@%s",rname);
8087             aopPut(AOP(result),"a",offset);
8088             
8089             offset++ ;
8090             
8091             if (size)
8092                 pic14_emitcode("inc","%s",rname);
8093         }
8094     }
8095
8096     /* now some housekeeping stuff */
8097     if (aop) {
8098         /* we had to allocate for this iCode */
8099         freeAsmop(NULL,aop,ic,TRUE);
8100     } else { 
8101         /* we did not allocate which means left
8102            already in a pointer register, then
8103            if size > 0 && this could be used again
8104            we have to point it back to where it 
8105            belongs */
8106         if (AOP_SIZE(result) > 1 &&
8107             !OP_SYMBOL(left)->remat &&
8108             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8109               ic->depth )) {
8110             int size = AOP_SIZE(result) - 1;
8111             while (size--)
8112                 pic14_emitcode("dec","%s",rname);
8113         }
8114     }
8115
8116     /* done */
8117     freeAsmop(result,NULL,ic,TRUE);
8118     
8119         
8120 }
8121
8122 /*-----------------------------------------------------------------*/
8123 /* genFarPointerGet - gget value from far space                    */
8124 /*-----------------------------------------------------------------*/
8125 static void genFarPointerGet (operand *left,
8126                               operand *result, iCode *ic)
8127 {
8128     int size, offset ;
8129     sym_link *retype = getSpec(operandType(result));
8130
8131     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8132
8133     aopOp(left,ic,FALSE);
8134
8135     /* if the operand is already in dptr 
8136     then we do nothing else we move the value to dptr */
8137     if (AOP_TYPE(left) != AOP_STR) {
8138         /* if this is remateriazable */
8139         if (AOP_TYPE(left) == AOP_IMMD)
8140             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8141         else { /* we need to get it byte by byte */
8142             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8143             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8144             if (options.model == MODEL_FLAT24)
8145             {
8146                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8147             }
8148         }
8149     }
8150     /* so dptr know contains the address */
8151     freeAsmop(left,NULL,ic,TRUE);
8152     aopOp(result,ic,FALSE);
8153
8154     /* if bit then unpack */
8155     if (IS_BITVAR(retype)) 
8156         genUnpackBits(result,"dptr",FPOINTER);
8157     else {
8158         size = AOP_SIZE(result);
8159         offset = 0 ;
8160
8161         while (size--) {
8162             pic14_emitcode("movx","a,@dptr");
8163             aopPut(AOP(result),"a",offset++);
8164             if (size)
8165                 pic14_emitcode("inc","dptr");
8166         }
8167     }
8168
8169     freeAsmop(result,NULL,ic,TRUE);
8170 }
8171 #if 0
8172 /*-----------------------------------------------------------------*/
8173 /* genCodePointerGet - get value from code space                  */
8174 /*-----------------------------------------------------------------*/
8175 static void genCodePointerGet (operand *left,
8176                                 operand *result, iCode *ic)
8177 {
8178     int size, offset ;
8179     sym_link *retype = getSpec(operandType(result));
8180
8181     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8182
8183     aopOp(left,ic,FALSE);
8184
8185     /* if the operand is already in dptr 
8186     then we do nothing else we move the value to dptr */
8187     if (AOP_TYPE(left) != AOP_STR) {
8188         /* if this is remateriazable */
8189         if (AOP_TYPE(left) == AOP_IMMD)
8190             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8191         else { /* we need to get it byte by byte */
8192             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8193             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8194             if (options.model == MODEL_FLAT24)
8195             {
8196                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8197             }
8198         }
8199     }
8200     /* so dptr know contains the address */
8201     freeAsmop(left,NULL,ic,TRUE);
8202     aopOp(result,ic,FALSE);
8203
8204     /* if bit then unpack */
8205     if (IS_BITVAR(retype)) 
8206         genUnpackBits(result,"dptr",CPOINTER);
8207     else {
8208         size = AOP_SIZE(result);
8209         offset = 0 ;
8210
8211         while (size--) {
8212             pic14_emitcode("clr","a");
8213             pic14_emitcode("movc","a,@a+dptr");
8214             aopPut(AOP(result),"a",offset++);
8215             if (size)
8216                 pic14_emitcode("inc","dptr");
8217         }
8218     }
8219
8220     freeAsmop(result,NULL,ic,TRUE);
8221 }
8222 #endif
8223 /*-----------------------------------------------------------------*/
8224 /* genGenPointerGet - gget value from generic pointer space        */
8225 /*-----------------------------------------------------------------*/
8226 static void genGenPointerGet (operand *left,
8227                               operand *result, iCode *ic)
8228 {
8229   int size, offset ;
8230   sym_link *retype = getSpec(operandType(result));
8231
8232   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8233   aopOp(left,ic,FALSE);
8234   aopOp(result,ic,FALSE);
8235
8236
8237   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8238
8239   /* if the operand is already in dptr 
8240      then we do nothing else we move the value to dptr */
8241   //  if (AOP_TYPE(left) != AOP_STR) {
8242     /* if this is remateriazable */
8243     if (AOP_TYPE(left) == AOP_IMMD) {
8244       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8245       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8246     }
8247     else { /* we need to get it byte by byte */
8248
8249       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8250       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8251
8252       size = AOP_SIZE(result);
8253       offset = 0 ;
8254
8255       while(size--) {
8256         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8257         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8258         if(size)
8259           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8260       }
8261       goto release;
8262     }
8263     //}
8264   /* so dptr know contains the address */
8265
8266   /* if bit then unpack */
8267   //if (IS_BITVAR(retype)) 
8268   //  genUnpackBits(result,"dptr",GPOINTER);
8269
8270  release:
8271   freeAsmop(left,NULL,ic,TRUE);
8272   freeAsmop(result,NULL,ic,TRUE);
8273
8274 }
8275
8276 /*-----------------------------------------------------------------*/
8277 /* genConstPointerGet - get value from const generic pointer space */
8278 /*-----------------------------------------------------------------*/
8279 static void genConstPointerGet (operand *left,
8280                                 operand *result, iCode *ic)
8281 {
8282   //sym_link *retype = getSpec(operandType(result));
8283   symbol *albl = newiTempLabel(NULL);
8284   symbol *blbl = newiTempLabel(NULL);
8285   PIC_OPCODE poc;
8286
8287   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8288   aopOp(left,ic,FALSE);
8289   aopOp(result,ic,FALSE);
8290
8291
8292   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8293
8294   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8295
8296   emitpcode(POC_CALL,popGetLabel(albl->key));
8297   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8298   emitpLabel(albl->key);
8299
8300   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8301     
8302   emitpcode(poc,popGet(AOP(left),1));
8303   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8304   emitpcode(poc,popGet(AOP(left),0));
8305   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8306
8307   emitpLabel(blbl->key);
8308
8309   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8310
8311
8312   freeAsmop(left,NULL,ic,TRUE);
8313   freeAsmop(result,NULL,ic,TRUE);
8314
8315 }
8316 /*-----------------------------------------------------------------*/
8317 /* genPointerGet - generate code for pointer get                   */
8318 /*-----------------------------------------------------------------*/
8319 static void genPointerGet (iCode *ic)
8320 {
8321     operand *left, *result ;
8322     sym_link *type, *etype;
8323     int p_type;
8324
8325     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8326
8327     left = IC_LEFT(ic);
8328     result = IC_RESULT(ic) ;
8329
8330     /* depending on the type of pointer we need to
8331     move it to the correct pointer register */
8332     type = operandType(left);
8333     etype = getSpec(type);
8334
8335     if (IS_PTR_CONST(type))
8336       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8337
8338     /* if left is of type of pointer then it is simple */
8339     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8340         p_type = DCL_TYPE(type);
8341     else {
8342         /* we have to go by the storage class */
8343         p_type = PTR_TYPE(SPEC_OCLS(etype));
8344
8345         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8346
8347         if (SPEC_OCLS(etype)->codesp ) {
8348           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8349           //p_type = CPOINTER ; 
8350         }
8351         else
8352             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8353               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8354                /*p_type = FPOINTER ;*/ 
8355             else
8356                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8357                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8358 /*                  p_type = PPOINTER; */
8359                 else
8360                     if (SPEC_OCLS(etype) == idata )
8361                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8362 /*                      p_type = IPOINTER; */
8363                     else
8364                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8365 /*                      p_type = POINTER ; */
8366     }
8367
8368     /* now that we have the pointer type we assign
8369     the pointer values */
8370     switch (p_type) {
8371
8372     case POINTER:       
8373     case IPOINTER:
8374         genNearPointerGet (left,result,ic);
8375         break;
8376
8377     case PPOINTER:
8378         genPagedPointerGet(left,result,ic);
8379         break;
8380
8381     case FPOINTER:
8382         genFarPointerGet (left,result,ic);
8383         break;
8384
8385     case CPOINTER:
8386         genConstPointerGet (left,result,ic);
8387         //pic14_emitcodePointerGet (left,result,ic);
8388         break;
8389
8390     case GPOINTER:
8391       if (IS_PTR_CONST(type))
8392         genConstPointerGet (left,result,ic);
8393       else
8394         genGenPointerGet (left,result,ic);
8395       break;
8396     }
8397
8398 }
8399
8400 /*-----------------------------------------------------------------*/
8401 /* genPackBits - generates code for packed bit storage             */
8402 /*-----------------------------------------------------------------*/
8403 static void genPackBits (sym_link    *etype ,
8404                          operand *right ,
8405                          char *rname, int p_type)
8406 {
8407     int shCount = 0 ;
8408     int offset = 0  ;
8409     int rLen = 0 ;
8410     int blen, bstr ;   
8411     char *l ;
8412
8413     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8414     blen = SPEC_BLEN(etype);
8415     bstr = SPEC_BSTR(etype);
8416
8417     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8418     MOVA(l);   
8419
8420     /* if the bit lenth is less than or    */
8421     /* it exactly fits a byte then         */
8422     if (SPEC_BLEN(etype) <= 8 )  {
8423         shCount = SPEC_BSTR(etype) ;
8424
8425         /* shift left acc */
8426         AccLsh(shCount);
8427
8428         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8429
8430
8431             switch (p_type) {
8432                 case POINTER:
8433                     pic14_emitcode ("mov","b,a");
8434                     pic14_emitcode("mov","a,@%s",rname);
8435                     break;
8436
8437                 case FPOINTER:
8438                     pic14_emitcode ("mov","b,a");
8439                     pic14_emitcode("movx","a,@dptr");
8440                     break;
8441
8442                 case GPOINTER:
8443                     pic14_emitcode ("push","b");
8444                     pic14_emitcode ("push","acc");
8445                     pic14_emitcode ("lcall","__gptrget");
8446                     pic14_emitcode ("pop","b");
8447                     break;
8448             }
8449
8450             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8451                       ((unsigned char)(0xFF << (blen+bstr)) | 
8452                        (unsigned char)(0xFF >> (8-bstr)) ) );
8453             pic14_emitcode ("orl","a,b");
8454             if (p_type == GPOINTER)
8455                 pic14_emitcode("pop","b");
8456         }
8457     }
8458
8459     switch (p_type) {
8460         case POINTER:
8461             pic14_emitcode("mov","@%s,a",rname);
8462             break;
8463
8464         case FPOINTER:
8465             pic14_emitcode("movx","@dptr,a");
8466             break;
8467
8468         case GPOINTER:
8469             DEBUGpic14_emitcode(";lcall","__gptrput");
8470             break;
8471     }
8472
8473     /* if we r done */
8474     if ( SPEC_BLEN(etype) <= 8 )
8475         return ;
8476
8477     pic14_emitcode("inc","%s",rname);
8478     rLen = SPEC_BLEN(etype) ;     
8479
8480     /* now generate for lengths greater than one byte */
8481     while (1) {
8482
8483         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8484
8485         rLen -= 8 ;
8486         if (rLen <= 0 )
8487             break ;
8488
8489         switch (p_type) {
8490             case POINTER:
8491                 if (*l == '@') {
8492                     MOVA(l);
8493                     pic14_emitcode("mov","@%s,a",rname);
8494                 } else
8495                     pic14_emitcode("mov","@%s,%s",rname,l);
8496                 break;
8497
8498             case FPOINTER:
8499                 MOVA(l);
8500                 pic14_emitcode("movx","@dptr,a");
8501                 break;
8502
8503             case GPOINTER:
8504                 MOVA(l);
8505                 DEBUGpic14_emitcode(";lcall","__gptrput");
8506                 break;  
8507         }   
8508         pic14_emitcode ("inc","%s",rname);
8509     }
8510
8511     MOVA(l);
8512
8513     /* last last was not complete */
8514     if (rLen)   {
8515         /* save the byte & read byte */
8516         switch (p_type) {
8517             case POINTER:
8518                 pic14_emitcode ("mov","b,a");
8519                 pic14_emitcode("mov","a,@%s",rname);
8520                 break;
8521
8522             case FPOINTER:
8523                 pic14_emitcode ("mov","b,a");
8524                 pic14_emitcode("movx","a,@dptr");
8525                 break;
8526
8527             case GPOINTER:
8528                 pic14_emitcode ("push","b");
8529                 pic14_emitcode ("push","acc");
8530                 pic14_emitcode ("lcall","__gptrget");
8531                 pic14_emitcode ("pop","b");
8532                 break;
8533         }
8534
8535         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8536         pic14_emitcode ("orl","a,b");
8537     }
8538
8539     if (p_type == GPOINTER)
8540         pic14_emitcode("pop","b");
8541
8542     switch (p_type) {
8543
8544     case POINTER:
8545         pic14_emitcode("mov","@%s,a",rname);
8546         break;
8547         
8548     case FPOINTER:
8549         pic14_emitcode("movx","@dptr,a");
8550         break;
8551         
8552     case GPOINTER:
8553         DEBUGpic14_emitcode(";lcall","__gptrput");
8554         break;                  
8555     }
8556 }
8557 /*-----------------------------------------------------------------*/
8558 /* genDataPointerSet - remat pointer to data space                 */
8559 /*-----------------------------------------------------------------*/
8560 static void genDataPointerSet(operand *right,
8561                               operand *result,
8562                               iCode *ic)
8563 {
8564     int size, offset = 0 ;
8565     char *l, buffer[256];
8566
8567     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8568     aopOp(right,ic,FALSE);
8569     
8570     l = aopGet(AOP(result),0,FALSE,TRUE);
8571     size = AOP_SIZE(right);
8572 /*
8573     if ( AOP_TYPE(result) == AOP_PCODE) {
8574       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8575               AOP(result)->aopu.pcop->name,
8576               PCOI(AOP(result)->aopu.pcop)->offset);
8577     }
8578 */
8579
8580     // tsd, was l+1 - the underline `_' prefix was being stripped
8581     while (size--) {
8582       if (offset) {
8583         sprintf(buffer,"(%s + %d)",l,offset);
8584         fprintf(stderr,"oops  %s\n",buffer);
8585       } else
8586         sprintf(buffer,"%s",l);
8587
8588         if (AOP_TYPE(right) == AOP_LIT) {
8589           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8590           lit = lit >> (8*offset);
8591           if(lit&0xff) {
8592             pic14_emitcode("movlw","%d",lit);
8593             pic14_emitcode("movwf","%s",buffer);
8594
8595             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8596             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8597             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8598
8599           } else {
8600             pic14_emitcode("clrf","%s",buffer);
8601             //emitpcode(POC_CLRF, popRegFromString(buffer));
8602             emitpcode(POC_CLRF, popGet(AOP(result),0));
8603           }
8604         }else {
8605           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8606           pic14_emitcode("movwf","%s",buffer);
8607
8608           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8609           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8610           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8611
8612         }
8613
8614         offset++;
8615     }
8616
8617     freeAsmop(right,NULL,ic,TRUE);
8618     freeAsmop(result,NULL,ic,TRUE);
8619 }
8620
8621 /*-----------------------------------------------------------------*/
8622 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8623 /*-----------------------------------------------------------------*/
8624 static void genNearPointerSet (operand *right,
8625                                operand *result, 
8626                                iCode *ic)
8627 {
8628   asmop *aop = NULL;
8629   char *l;
8630   sym_link *retype;
8631   sym_link *ptype = operandType(result);
8632
8633     
8634   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635   retype= getSpec(operandType(right));
8636
8637   aopOp(result,ic,FALSE);
8638
8639     
8640   /* if the result is rematerializable &
8641      in data space & not a bit variable */
8642   //if (AOP_TYPE(result) == AOP_IMMD &&
8643   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8644       DCL_TYPE(ptype) == POINTER   &&
8645       !IS_BITVAR(retype)) {
8646     genDataPointerSet (right,result,ic);
8647     freeAsmop(result,NULL,ic,TRUE);
8648     return;
8649   }
8650
8651   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8652   aopOp(right,ic,FALSE);
8653   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8654
8655   /* if the value is already in a pointer register
8656      then don't need anything more */
8657   if (!AOP_INPREG(AOP(result))) {
8658     /* otherwise get a free pointer register */
8659     //aop = newAsmop(0);
8660     //preg = getFreePtr(ic,&aop,FALSE);
8661     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8662     //pic14_emitcode("mov","%s,%s",
8663     //         preg->name,
8664     //         aopGet(AOP(result),0,FALSE,TRUE));
8665     //rname = preg->name ;
8666     //pic14_emitcode("movwf","fsr");
8667     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8668     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8669     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8670     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8671     goto release;
8672
8673   }// else
8674   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8675
8676
8677   /* if bitfield then unpack the bits */
8678   if (IS_BITVAR(retype)) {
8679     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8680            "The programmer is obviously confused");
8681     //genPackBits (retype,right,rname,POINTER);
8682     exit(1);
8683   }
8684   else {
8685     /* we have can just get the values */
8686     int size = AOP_SIZE(right);
8687     int offset = 0 ;    
8688
8689     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8690     while (size--) {
8691       l = aopGet(AOP(right),offset,FALSE,TRUE);
8692       if (*l == '@' ) {
8693         //MOVA(l);
8694         //pic14_emitcode("mov","@%s,a",rname);
8695         pic14_emitcode("movf","indf,w ;1");
8696       } else {
8697
8698         if (AOP_TYPE(right) == AOP_LIT) {
8699           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8700           if(lit) {
8701             pic14_emitcode("movlw","%s",l);
8702             pic14_emitcode("movwf","indf ;2");
8703           } else 
8704             pic14_emitcode("clrf","indf");
8705         }else {
8706           pic14_emitcode("movf","%s,w",l);
8707           pic14_emitcode("movwf","indf ;2");
8708         }
8709         //pic14_emitcode("mov","@%s,%s",rname,l);
8710       }
8711       if (size)
8712         pic14_emitcode("incf","fsr,f ;3");
8713       //pic14_emitcode("inc","%s",rname);
8714       offset++;
8715     }
8716   }
8717
8718   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8719   /* now some housekeeping stuff */
8720   if (aop) {
8721     /* we had to allocate for this iCode */
8722     freeAsmop(NULL,aop,ic,TRUE);
8723   } else { 
8724     /* we did not allocate which means left
8725        already in a pointer register, then
8726        if size > 0 && this could be used again
8727        we have to point it back to where it 
8728        belongs */
8729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730     if (AOP_SIZE(right) > 1 &&
8731         !OP_SYMBOL(result)->remat &&
8732         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8733           ic->depth )) {
8734       int size = AOP_SIZE(right) - 1;
8735       while (size--)
8736         pic14_emitcode("decf","fsr,f");
8737       //pic14_emitcode("dec","%s",rname);
8738     }
8739   }
8740
8741   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8742   /* done */
8743  release:
8744   freeAsmop(right,NULL,ic,TRUE);
8745   freeAsmop(result,NULL,ic,TRUE);
8746 }
8747
8748 /*-----------------------------------------------------------------*/
8749 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8750 /*-----------------------------------------------------------------*/
8751 static void genPagedPointerSet (operand *right,
8752                                operand *result, 
8753                                iCode *ic)
8754 {
8755     asmop *aop = NULL;
8756     regs *preg = NULL ;
8757     char *rname , *l;
8758     sym_link *retype;
8759        
8760     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761
8762     retype= getSpec(operandType(right));
8763     
8764     aopOp(result,ic,FALSE);
8765     
8766     /* if the value is already in a pointer register
8767        then don't need anything more */
8768     if (!AOP_INPREG(AOP(result))) {
8769         /* otherwise get a free pointer register */
8770         aop = newAsmop(0);
8771         preg = getFreePtr(ic,&aop,FALSE);
8772         pic14_emitcode("mov","%s,%s",
8773                 preg->name,
8774                 aopGet(AOP(result),0,FALSE,TRUE));
8775         rname = preg->name ;
8776     } else
8777         rname = aopGet(AOP(result),0,FALSE,FALSE);
8778     
8779     freeAsmop(result,NULL,ic,TRUE);
8780     aopOp (right,ic,FALSE);
8781
8782     /* if bitfield then unpack the bits */
8783     if (IS_BITVAR(retype)) 
8784         genPackBits (retype,right,rname,PPOINTER);
8785     else {
8786         /* we have can just get the values */
8787         int size = AOP_SIZE(right);
8788         int offset = 0 ;        
8789         
8790         while (size--) {
8791             l = aopGet(AOP(right),offset,FALSE,TRUE);
8792             
8793             MOVA(l);
8794             pic14_emitcode("movx","@%s,a",rname);
8795
8796             if (size)
8797                 pic14_emitcode("inc","%s",rname);
8798
8799             offset++;
8800         }
8801     }
8802     
8803     /* now some housekeeping stuff */
8804     if (aop) {
8805         /* we had to allocate for this iCode */
8806         freeAsmop(NULL,aop,ic,TRUE);
8807     } else { 
8808         /* we did not allocate which means left
8809            already in a pointer register, then
8810            if size > 0 && this could be used again
8811            we have to point it back to where it 
8812            belongs */
8813         if (AOP_SIZE(right) > 1 &&
8814             !OP_SYMBOL(result)->remat &&
8815             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8816               ic->depth )) {
8817             int size = AOP_SIZE(right) - 1;
8818             while (size--)
8819                 pic14_emitcode("dec","%s",rname);
8820         }
8821     }
8822
8823     /* done */
8824     freeAsmop(right,NULL,ic,TRUE);
8825     
8826         
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* genFarPointerSet - set value from far space                     */
8831 /*-----------------------------------------------------------------*/
8832 static void genFarPointerSet (operand *right,
8833                               operand *result, iCode *ic)
8834 {
8835     int size, offset ;
8836     sym_link *retype = getSpec(operandType(right));
8837
8838     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839     aopOp(result,ic,FALSE);
8840
8841     /* if the operand is already in dptr 
8842     then we do nothing else we move the value to dptr */
8843     if (AOP_TYPE(result) != AOP_STR) {
8844         /* if this is remateriazable */
8845         if (AOP_TYPE(result) == AOP_IMMD)
8846             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8847         else { /* we need to get it byte by byte */
8848             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8849             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8850             if (options.model == MODEL_FLAT24)
8851             {
8852                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8853             }
8854         }
8855     }
8856     /* so dptr know contains the address */
8857     freeAsmop(result,NULL,ic,TRUE);
8858     aopOp(right,ic,FALSE);
8859
8860     /* if bit then unpack */
8861     if (IS_BITVAR(retype)) 
8862         genPackBits(retype,right,"dptr",FPOINTER);
8863     else {
8864         size = AOP_SIZE(right);
8865         offset = 0 ;
8866
8867         while (size--) {
8868             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8869             MOVA(l);
8870             pic14_emitcode("movx","@dptr,a");
8871             if (size)
8872                 pic14_emitcode("inc","dptr");
8873         }
8874     }
8875
8876     freeAsmop(right,NULL,ic,TRUE);
8877 }
8878
8879 /*-----------------------------------------------------------------*/
8880 /* genGenPointerSet - set value from generic pointer space         */
8881 /*-----------------------------------------------------------------*/
8882 static void genGenPointerSet (operand *right,
8883                               operand *result, iCode *ic)
8884 {
8885   int size, offset ;
8886   sym_link *retype = getSpec(operandType(right));
8887
8888   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889
8890   aopOp(result,ic,FALSE);
8891   aopOp(right,ic,FALSE);
8892   size = AOP_SIZE(right);
8893
8894   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8895
8896   /* if the operand is already in dptr 
8897      then we do nothing else we move the value to dptr */
8898   if (AOP_TYPE(result) != AOP_STR) {
8899     /* if this is remateriazable */
8900     if (AOP_TYPE(result) == AOP_IMMD) {
8901       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8902       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8903     }
8904     else { /* we need to get it byte by byte */
8905       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8906       size = AOP_SIZE(right);
8907       offset = 0 ;
8908
8909       /* hack hack! see if this the FSR. If so don't load W */
8910       if(AOP_TYPE(right) != AOP_ACC) {
8911
8912         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8913         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8914
8915         //if(size==2)
8916         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8917         //if(size==4) {
8918         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8919         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8920         //}
8921
8922         while(size--) {
8923           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8924           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8925           
8926           if(size)
8927             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8928         }
8929
8930
8931         goto release;
8932       } 
8933
8934       if(aopIdx(AOP(result),0) != 4) {
8935
8936         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8937         goto release;
8938       }
8939
8940       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8941       goto release;
8942
8943     }
8944   }
8945   /* so dptr know contains the address */
8946
8947
8948   /* if bit then unpack */
8949   if (IS_BITVAR(retype)) 
8950     genPackBits(retype,right,"dptr",GPOINTER);
8951   else {
8952     size = AOP_SIZE(right);
8953     offset = 0 ;
8954
8955   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8956
8957     while (size--) {
8958
8959       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8960       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8961
8962       if (AOP_TYPE(right) == AOP_LIT) 
8963         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8964       else
8965         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8966
8967       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8968
8969       offset++;
8970     }
8971   }
8972
8973  release:
8974   freeAsmop(right,NULL,ic,TRUE);
8975   freeAsmop(result,NULL,ic,TRUE);
8976 }
8977
8978 /*-----------------------------------------------------------------*/
8979 /* genPointerSet - stores the value into a pointer location        */
8980 /*-----------------------------------------------------------------*/
8981 static void genPointerSet (iCode *ic)
8982 {    
8983     operand *right, *result ;
8984     sym_link *type, *etype;
8985     int p_type;
8986
8987     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8988
8989     right = IC_RIGHT(ic);
8990     result = IC_RESULT(ic) ;
8991
8992     /* depending on the type of pointer we need to
8993     move it to the correct pointer register */
8994     type = operandType(result);
8995     etype = getSpec(type);
8996     /* if left is of type of pointer then it is simple */
8997     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8998         p_type = DCL_TYPE(type);
8999     }
9000     else {
9001         /* we have to go by the storage class */
9002         p_type = PTR_TYPE(SPEC_OCLS(etype));
9003
9004 /*      if (SPEC_OCLS(etype)->codesp ) { */
9005 /*          p_type = CPOINTER ;  */
9006 /*      } */
9007 /*      else */
9008 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9009 /*              p_type = FPOINTER ; */
9010 /*          else */
9011 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9012 /*                  p_type = PPOINTER ; */
9013 /*              else */
9014 /*                  if (SPEC_OCLS(etype) == idata ) */
9015 /*                      p_type = IPOINTER ; */
9016 /*                  else */
9017 /*                      p_type = POINTER ; */
9018     }
9019
9020     /* now that we have the pointer type we assign
9021     the pointer values */
9022     switch (p_type) {
9023
9024     case POINTER:
9025     case IPOINTER:
9026         genNearPointerSet (right,result,ic);
9027         break;
9028
9029     case PPOINTER:
9030         genPagedPointerSet (right,result,ic);
9031         break;
9032
9033     case FPOINTER:
9034         genFarPointerSet (right,result,ic);
9035         break;
9036
9037     case GPOINTER:
9038         genGenPointerSet (right,result,ic);
9039         break;
9040
9041     default:
9042       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9043               "genPointerSet: illegal pointer type");
9044     }
9045 }
9046
9047 /*-----------------------------------------------------------------*/
9048 /* genIfx - generate code for Ifx statement                        */
9049 /*-----------------------------------------------------------------*/
9050 static void genIfx (iCode *ic, iCode *popIc)
9051 {
9052   operand *cond = IC_COND(ic);
9053   int isbit =0;
9054
9055   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9056
9057   aopOp(cond,ic,FALSE);
9058
9059   /* get the value into acc */
9060   if (AOP_TYPE(cond) != AOP_CRY)
9061     pic14_toBoolean(cond);
9062   else
9063     isbit = 1;
9064   /* the result is now in the accumulator */
9065   freeAsmop(cond,NULL,ic,TRUE);
9066
9067   /* if there was something to be popped then do it */
9068   if (popIc)
9069     genIpop(popIc);
9070
9071   /* if the condition is  a bit variable */
9072   if (isbit && IS_ITEMP(cond) && 
9073       SPIL_LOC(cond)) {
9074     genIfxJump(ic,SPIL_LOC(cond)->rname);
9075     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9076   }
9077   else {
9078     if (isbit && !IS_ITEMP(cond))
9079       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9080     else
9081       genIfxJump(ic,"a");
9082   }
9083   ic->generated = 1;
9084
9085 }
9086
9087 /*-----------------------------------------------------------------*/
9088 /* genAddrOf - generates code for address of                       */
9089 /*-----------------------------------------------------------------*/
9090 static void genAddrOf (iCode *ic)
9091 {
9092   operand *right, *result, *left;
9093   int size, offset ;
9094
9095   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9096
9097
9098   //aopOp(IC_RESULT(ic),ic,FALSE);
9099
9100   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9101   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9102   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9103
9104   DEBUGpic14_AopType(__LINE__,left,right,result);
9105
9106   size = AOP_SIZE(IC_RESULT(ic));
9107   offset = 0;
9108
9109   while (size--) {
9110     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9111     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9112     offset++;
9113   }
9114
9115   freeAsmop(left,NULL,ic,FALSE);
9116   freeAsmop(result,NULL,ic,TRUE);
9117
9118 }
9119
9120 #if 0
9121 /*-----------------------------------------------------------------*/
9122 /* genFarFarAssign - assignment when both are in far space         */
9123 /*-----------------------------------------------------------------*/
9124 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9125 {
9126     int size = AOP_SIZE(right);
9127     int offset = 0;
9128     char *l ;
9129     /* first push the right side on to the stack */
9130     while (size--) {
9131         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9132         MOVA(l);
9133         pic14_emitcode ("push","acc");
9134     }
9135     
9136     freeAsmop(right,NULL,ic,FALSE);
9137     /* now assign DPTR to result */
9138     aopOp(result,ic,FALSE);
9139     size = AOP_SIZE(result);
9140     while (size--) {
9141         pic14_emitcode ("pop","acc");
9142         aopPut(AOP(result),"a",--offset);
9143     }
9144     freeAsmop(result,NULL,ic,FALSE);
9145         
9146 }
9147 #endif
9148
9149 /*-----------------------------------------------------------------*/
9150 /* genAssign - generate code for assignment                        */
9151 /*-----------------------------------------------------------------*/
9152 static void genAssign (iCode *ic)
9153 {
9154   operand *result, *right;
9155   int size, offset,know_W;
9156   unsigned long lit = 0L;
9157
9158   result = IC_RESULT(ic);
9159   right  = IC_RIGHT(ic) ;
9160
9161   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9162
9163   /* if they are the same */
9164   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9165     return ;
9166
9167   aopOp(right,ic,FALSE);
9168   aopOp(result,ic,TRUE);
9169
9170   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9171
9172   /* if they are the same registers */
9173   if (pic14_sameRegs(AOP(right),AOP(result)))
9174     goto release;
9175
9176   /* if the result is a bit */
9177   if (AOP_TYPE(result) == AOP_CRY) {
9178
9179     /* if the right size is a literal then
9180        we know what the value is */
9181     if (AOP_TYPE(right) == AOP_LIT) {
9182           
9183       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9184                   popGet(AOP(result),0));
9185
9186       if (((int) operandLitValue(right))) 
9187         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9188                        AOP(result)->aopu.aop_dir,
9189                        AOP(result)->aopu.aop_dir);
9190       else
9191         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9192                        AOP(result)->aopu.aop_dir,
9193                        AOP(result)->aopu.aop_dir);
9194       goto release;
9195     }
9196
9197     /* the right is also a bit variable */
9198     if (AOP_TYPE(right) == AOP_CRY) {
9199       emitpcode(POC_BCF,    popGet(AOP(result),0));
9200       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9201       emitpcode(POC_BSF,    popGet(AOP(result),0));
9202
9203       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9204                      AOP(result)->aopu.aop_dir,
9205                      AOP(result)->aopu.aop_dir);
9206       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9207                      AOP(right)->aopu.aop_dir,
9208                      AOP(right)->aopu.aop_dir);
9209       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9210                      AOP(result)->aopu.aop_dir,
9211                      AOP(result)->aopu.aop_dir);
9212       goto release ;
9213     }
9214
9215     /* we need to or */
9216     emitpcode(POC_BCF,    popGet(AOP(result),0));
9217     pic14_toBoolean(right);
9218     emitSKPZ;
9219     emitpcode(POC_BSF,    popGet(AOP(result),0));
9220     //aopPut(AOP(result),"a",0);
9221     goto release ;
9222   }
9223
9224   /* bit variables done */
9225   /* general case */
9226   size = AOP_SIZE(result);
9227   offset = 0 ;
9228   if(AOP_TYPE(right) == AOP_LIT)
9229     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9230
9231   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9232   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9233     if(aopIdx(AOP(result),0) == 4) {
9234   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9235       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9236       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9237       goto release;
9238     } else
9239       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9240   }
9241
9242   know_W=-1;
9243   while (size--) {
9244   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9245     if(AOP_TYPE(right) == AOP_LIT) {
9246       if(lit&0xff) {
9247         if(know_W != (lit&0xff))
9248           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9249         know_W = lit&0xff;
9250         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9251       } else
9252         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9253
9254       lit >>= 8;
9255
9256     } else if (AOP_TYPE(right) == AOP_CRY) {
9257       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9258       if(offset == 0) {
9259         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9260         emitpcode(POC_INCF, popGet(AOP(result),0));
9261       }
9262     } else {
9263   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9264       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9265       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9266     }
9267             
9268     offset++;
9269   }
9270
9271     
9272  release:
9273   freeAsmop (right,NULL,ic,FALSE);
9274   freeAsmop (result,NULL,ic,TRUE);
9275 }   
9276
9277 /*-----------------------------------------------------------------*/
9278 /* genJumpTab - genrates code for jump table                       */
9279 /*-----------------------------------------------------------------*/
9280 static void genJumpTab (iCode *ic)
9281 {
9282     symbol *jtab;
9283     char *l;
9284
9285     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9286
9287     aopOp(IC_JTCOND(ic),ic,FALSE);
9288     /* get the condition into accumulator */
9289     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9290     MOVA(l);
9291     /* multiply by three */
9292     pic14_emitcode("add","a,acc");
9293     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9294
9295     jtab = newiTempLabel(NULL);
9296     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9297     pic14_emitcode("jmp","@a+dptr");
9298     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9299
9300     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9301     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9302     emitSKPNC;
9303     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9304     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9305     emitpLabel(jtab->key);
9306
9307     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9308
9309     /* now generate the jump labels */
9310     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9311          jtab = setNextItem(IC_JTLABELS(ic))) {
9312         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9313         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9314         
9315     }
9316
9317 }
9318
9319 /*-----------------------------------------------------------------*/
9320 /* genMixedOperation - gen code for operators between mixed types  */
9321 /*-----------------------------------------------------------------*/
9322 /*
9323   TSD - Written for the PIC port - but this unfortunately is buggy.
9324   This routine is good in that it is able to efficiently promote 
9325   types to different (larger) sizes. Unfortunately, the temporary
9326   variables that are optimized out by this routine are sometimes
9327   used in other places. So until I know how to really parse the 
9328   iCode tree, I'm going to not be using this routine :(.
9329 */
9330 static int genMixedOperation (iCode *ic)
9331 {
9332 #if 0
9333   operand *result = IC_RESULT(ic);
9334   sym_link *ctype = operandType(IC_LEFT(ic));
9335   operand *right = IC_RIGHT(ic);
9336   int ret = 0;
9337   int big,small;
9338   int offset;
9339
9340   iCode *nextic;
9341   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9342
9343   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9344
9345   nextic = ic->next;
9346   if(!nextic)
9347     return 0;
9348
9349   nextright = IC_RIGHT(nextic);
9350   nextleft  = IC_LEFT(nextic);
9351   nextresult = IC_RESULT(nextic);
9352
9353   aopOp(right,ic,FALSE);
9354   aopOp(result,ic,FALSE);
9355   aopOp(nextright,  nextic, FALSE);
9356   aopOp(nextleft,   nextic, FALSE);
9357   aopOp(nextresult, nextic, FALSE);
9358
9359   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9360
9361     operand *t = right;
9362     right = nextright;
9363     nextright = t; 
9364
9365     pic14_emitcode(";remove right +","");
9366
9367   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9368 /*
9369     operand *t = right;
9370     right = nextleft;
9371     nextleft = t; 
9372 */
9373     pic14_emitcode(";remove left +","");
9374   } else
9375     return 0;
9376
9377   big = AOP_SIZE(nextleft);
9378   small = AOP_SIZE(nextright);
9379
9380   switch(nextic->op) {
9381
9382   case '+':
9383     pic14_emitcode(";optimize a +","");
9384     /* if unsigned or not an integral type */
9385     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9386       pic14_emitcode(";add a bit to something","");
9387     } else {
9388
9389       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9390
9391       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9392         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9393         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9394       } else
9395         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9396
9397       offset = 0;
9398       while(--big) {
9399
9400         offset++;
9401
9402         if(--small) {
9403           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9404             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9405             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9406           }
9407
9408           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9409           emitSKPNC;
9410           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9411                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9412                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9413           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9414           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9415
9416         } else {
9417           pic14_emitcode("rlf","known_zero,w");
9418
9419           /*
9420             if right is signed
9421               btfsc  right,7
9422                addlw ff
9423           */
9424           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9425             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9426             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9427           } else {
9428             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9429           }
9430         }
9431       }
9432       ret = 1;
9433     }
9434   }
9435   ret = 1;
9436
9437 release:
9438   freeAsmop(right,NULL,ic,TRUE);
9439   freeAsmop(result,NULL,ic,TRUE);
9440   freeAsmop(nextright,NULL,ic,TRUE);
9441   freeAsmop(nextleft,NULL,ic,TRUE);
9442   if(ret)
9443     nextic->generated = 1;
9444
9445   return ret;
9446 #else
9447   return 0;
9448 #endif
9449 }
9450 /*-----------------------------------------------------------------*/
9451 /* genCast - gen code for casting                                  */
9452 /*-----------------------------------------------------------------*/
9453 static void genCast (iCode *ic)
9454 {
9455     operand *result = IC_RESULT(ic);
9456     sym_link *ctype = operandType(IC_LEFT(ic));
9457     sym_link *rtype = operandType(IC_RIGHT(ic));
9458     operand *right = IC_RIGHT(ic);
9459     int size, offset ;
9460
9461     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9462     /* if they are equivalent then do nothing */
9463     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9464         return ;
9465
9466     aopOp(right,ic,FALSE) ;
9467     aopOp(result,ic,FALSE);
9468
9469     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9470
9471     /* if the result is a bit */
9472     if (AOP_TYPE(result) == AOP_CRY) {
9473         /* if the right size is a literal then
9474         we know what the value is */
9475       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9476         if (AOP_TYPE(right) == AOP_LIT) {
9477
9478           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9479                       popGet(AOP(result),0));
9480
9481             if (((int) operandLitValue(right))) 
9482               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9483                        AOP(result)->aopu.aop_dir,
9484                        AOP(result)->aopu.aop_dir);
9485             else
9486               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9487                        AOP(result)->aopu.aop_dir,
9488                        AOP(result)->aopu.aop_dir);
9489
9490             goto release;
9491         }
9492
9493         /* the right is also a bit variable */
9494         if (AOP_TYPE(right) == AOP_CRY) {
9495
9496           emitCLRC;
9497           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9498
9499           pic14_emitcode("clrc","");
9500           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9501                    AOP(right)->aopu.aop_dir,
9502                    AOP(right)->aopu.aop_dir);
9503             aopPut(AOP(result),"c",0);
9504             goto release ;
9505         }
9506
9507         /* we need to or */
9508         if (AOP_TYPE(right) == AOP_REG) {
9509           emitpcode(POC_BCF,    popGet(AOP(result),0));
9510           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9511           emitpcode(POC_BSF,    popGet(AOP(result),0));
9512         }
9513         pic14_toBoolean(right);
9514         aopPut(AOP(result),"a",0);
9515         goto release ;
9516     }
9517
9518     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9519       int offset = 1;
9520       size = AOP_SIZE(result);
9521
9522       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9523
9524       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9525       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9526       emitpcode(POC_INCF,   popGet(AOP(result),0));
9527
9528       while (size--)
9529         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9530
9531       goto release;
9532     }
9533
9534     /* if they are the same size : or less */
9535     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9536
9537         /* if they are in the same place */
9538       if (pic14_sameRegs(AOP(right),AOP(result)))
9539         goto release;
9540
9541       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9542       if (IS_PTR_CONST(rtype))
9543         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9544       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9545         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9546
9547       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9548         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9549         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9550         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9551         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9552         if(AOP_SIZE(result) <2)
9553           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9554
9555       } else {
9556
9557         /* if they in different places then copy */
9558         size = AOP_SIZE(result);
9559         offset = 0 ;
9560         while (size--) {
9561           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9562           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9563
9564           //aopPut(AOP(result),
9565           // aopGet(AOP(right),offset,FALSE,FALSE),
9566           // offset);
9567
9568           offset++;
9569         }
9570       }
9571       goto release;
9572     }
9573
9574
9575     /* if the result is of type pointer */
9576     if (IS_PTR(ctype)) {
9577
9578         int p_type;
9579         sym_link *type = operandType(right);
9580         sym_link *etype = getSpec(type);
9581       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9582
9583         /* pointer to generic pointer */
9584         if (IS_GENPTR(ctype)) {
9585             char *l = zero;
9586             
9587             if (IS_PTR(type)) 
9588                 p_type = DCL_TYPE(type);
9589             else {
9590                 /* we have to go by the storage class */
9591                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9592
9593 /*              if (SPEC_OCLS(etype)->codesp )  */
9594 /*                  p_type = CPOINTER ;  */
9595 /*              else */
9596 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9597 /*                      p_type = FPOINTER ; */
9598 /*                  else */
9599 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9600 /*                          p_type = PPOINTER; */
9601 /*                      else */
9602 /*                          if (SPEC_OCLS(etype) == idata ) */
9603 /*                              p_type = IPOINTER ; */
9604 /*                          else */
9605 /*                              p_type = POINTER ; */
9606             }
9607                 
9608             /* the first two bytes are known */
9609       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9610             size = GPTRSIZE - 1; 
9611             offset = 0 ;
9612             while (size--) {
9613               if(offset < AOP_SIZE(right)) {
9614       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9615                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9616                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9617                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9618                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9619                 } else { 
9620                   aopPut(AOP(result),
9621                          aopGet(AOP(right),offset,FALSE,FALSE),
9622                          offset);
9623                 }
9624               } else 
9625                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9626               offset++;
9627             }
9628             /* the last byte depending on type */
9629             switch (p_type) {
9630             case IPOINTER:
9631             case POINTER:
9632                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9633                 break;
9634             case FPOINTER:
9635               pic14_emitcode(";BUG!? ","%d",__LINE__);
9636                 l = one;
9637                 break;
9638             case CPOINTER:
9639               pic14_emitcode(";BUG!? ","%d",__LINE__);
9640                 l = "#0x02";
9641                 break;                          
9642             case PPOINTER:
9643               pic14_emitcode(";BUG!? ","%d",__LINE__);
9644                 l = "#0x03";
9645                 break;
9646                 
9647             default:
9648                 /* this should never happen */
9649                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9650                        "got unknown pointer type");
9651                 exit(1);
9652             }
9653             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9654             goto release ;
9655         }
9656         
9657         /* just copy the pointers */
9658         size = AOP_SIZE(result);
9659         offset = 0 ;
9660         while (size--) {
9661             aopPut(AOP(result),
9662                    aopGet(AOP(right),offset,FALSE,FALSE),
9663                    offset);
9664             offset++;
9665         }
9666         goto release ;
9667     }
9668     
9669
9670
9671     /* so we now know that the size of destination is greater
9672     than the size of the source.
9673     Now, if the next iCode is an operator then we might be
9674     able to optimize the operation without performing a cast.
9675     */
9676     if(genMixedOperation(ic))
9677       goto release;
9678
9679     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9680     
9681     /* we move to result for the size of source */
9682     size = AOP_SIZE(right);
9683     offset = 0 ;
9684     while (size--) {
9685       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9686       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9687       offset++;
9688     }
9689
9690     /* now depending on the sign of the destination */
9691     size = AOP_SIZE(result) - AOP_SIZE(right);
9692     /* if unsigned or not an integral type */
9693     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9694       while (size--)
9695         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9696     } else {
9697       /* we need to extend the sign :{ */
9698
9699       if(size == 1) {
9700         /* Save one instruction of casting char to int */
9701         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9702         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9703         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9704       } else {
9705         emitpcodeNULLop(POC_CLRW);
9706
9707         if(offset)
9708           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9709         else
9710           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9711         
9712         emitpcode(POC_MOVLW,   popGetLit(0xff));
9713
9714         while (size--)
9715           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9716       }
9717     }
9718
9719 release:
9720     freeAsmop(right,NULL,ic,TRUE);
9721     freeAsmop(result,NULL,ic,TRUE);
9722
9723 }
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genDjnz - generate decrement & jump if not zero instrucion      */
9727 /*-----------------------------------------------------------------*/
9728 static int genDjnz (iCode *ic, iCode *ifx)
9729 {
9730     symbol *lbl, *lbl1;
9731     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9732
9733     if (!ifx)
9734         return 0;
9735     
9736     /* if the if condition has a false label
9737        then we cannot save */
9738     if (IC_FALSE(ifx))
9739         return 0;
9740
9741     /* if the minus is not of the form 
9742        a = a - 1 */
9743     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9744         !IS_OP_LITERAL(IC_RIGHT(ic)))
9745         return 0;
9746
9747     if (operandLitValue(IC_RIGHT(ic)) != 1)
9748         return 0;
9749
9750     /* if the size of this greater than one then no
9751        saving */
9752     if (getSize(operandType(IC_RESULT(ic))) > 1)
9753         return 0;
9754
9755     /* otherwise we can save BIG */
9756     lbl = newiTempLabel(NULL);
9757     lbl1= newiTempLabel(NULL);
9758
9759     aopOp(IC_RESULT(ic),ic,FALSE);
9760     
9761     if (IS_AOP_PREG(IC_RESULT(ic))) {
9762         pic14_emitcode("dec","%s",
9763                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9764         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9765         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9766     } else {    
9767
9768
9769       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9770       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9771
9772       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9773       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9774
9775     }
9776 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9777 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9778 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9779 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9780
9781     
9782     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9783     ifx->generated = 1;
9784     return 1;
9785 }
9786
9787 /*-----------------------------------------------------------------*/
9788 /* genReceive - generate code for a receive iCode                  */
9789 /*-----------------------------------------------------------------*/
9790 static void genReceive (iCode *ic)
9791 {    
9792   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9793
9794   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9795       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9796         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9797
9798     int size = getSize(operandType(IC_RESULT(ic)));
9799     int offset =  fReturnSizePic - size;
9800     while (size--) {
9801       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9802                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9803       offset++;
9804     }
9805     aopOp(IC_RESULT(ic),ic,FALSE);  
9806     size = AOP_SIZE(IC_RESULT(ic));
9807     offset = 0;
9808     while (size--) {
9809       pic14_emitcode ("pop","acc");
9810       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9811     }
9812         
9813   } else {
9814     _G.accInUse++;
9815     aopOp(IC_RESULT(ic),ic,FALSE);  
9816     _G.accInUse--;
9817     assignResultValue(IC_RESULT(ic));   
9818   }
9819
9820   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9821 }
9822
9823 /*-----------------------------------------------------------------*/
9824 /* genpic14Code - generate code for pic14 based controllers        */
9825 /*-----------------------------------------------------------------*/
9826 /*
9827  * At this point, ralloc.c has gone through the iCode and attempted
9828  * to optimize in a way suitable for a PIC. Now we've got to generate
9829  * PIC instructions that correspond to the iCode.
9830  *
9831  * Once the instructions are generated, we'll pass through both the
9832  * peep hole optimizer and the pCode optimizer.
9833  *-----------------------------------------------------------------*/
9834
9835 void genpic14Code (iCode *lic)
9836 {
9837     iCode *ic;
9838     int cln = 0;
9839
9840     lineHead = lineCurr = NULL;
9841
9842     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9843     addpBlock(pb);
9844
9845     /* if debug information required */
9846     if (options.debug && currFunc) { 
9847       if (currFunc) {
9848         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9849         _G.debugLine = 1;
9850         if (IS_STATIC(currFunc->etype)) {
9851           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9852           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9853         } else {
9854           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9855           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9856         }
9857         _G.debugLine = 0;
9858       }
9859     }
9860
9861
9862     for (ic = lic ; ic ; ic = ic->next ) {
9863
9864       DEBUGpic14_emitcode(";ic","");
9865         if ( cln != ic->lineno ) {
9866             if ( options.debug ) {
9867                 _G.debugLine = 1;
9868                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9869                          FileBaseName(ic->filename),ic->lineno,
9870                          ic->level,ic->block);
9871                 _G.debugLine = 0;
9872             }
9873             /*
9874               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9875               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9876               printCLine(ic->filename, ic->lineno));
9877             */
9878             addpCode2pBlock(pb,
9879                             newpCodeCSource(ic->lineno, 
9880                                             ic->filename, 
9881                                             printCLine(ic->filename, ic->lineno)));
9882
9883             cln = ic->lineno ;
9884         }
9885         /* if the result is marked as
9886            spilt and rematerializable or code for
9887            this has already been generated then
9888            do nothing */
9889         if (resultRemat(ic) || ic->generated ) 
9890             continue ;
9891         
9892         /* depending on the operation */
9893         switch (ic->op) {
9894         case '!' :
9895             genNot(ic);
9896             break;
9897             
9898         case '~' :
9899             genCpl(ic);
9900             break;
9901             
9902         case UNARYMINUS:
9903             genUminus (ic);
9904             break;
9905             
9906         case IPUSH:
9907             genIpush (ic);
9908             break;
9909             
9910         case IPOP:
9911             /* IPOP happens only when trying to restore a 
9912                spilt live range, if there is an ifx statement
9913                following this pop then the if statement might
9914                be using some of the registers being popped which
9915                would destory the contents of the register so
9916                we need to check for this condition and handle it */
9917             if (ic->next            && 
9918                 ic->next->op == IFX &&
9919                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9920                 genIfx (ic->next,ic);
9921             else
9922                 genIpop (ic);
9923             break; 
9924             
9925         case CALL:
9926             genCall (ic);
9927             break;
9928             
9929         case PCALL:
9930             genPcall (ic);
9931             break;
9932             
9933         case FUNCTION:
9934             genFunction (ic);
9935             break;
9936             
9937         case ENDFUNCTION:
9938             genEndFunction (ic);
9939             break;
9940             
9941         case RETURN:
9942             genRet (ic);
9943             break;
9944             
9945         case LABEL:
9946             genLabel (ic);
9947             break;
9948             
9949         case GOTO:
9950             genGoto (ic);
9951             break;
9952             
9953         case '+' :
9954             genPlus (ic) ;
9955             break;
9956             
9957         case '-' :
9958             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9959                 genMinus (ic);
9960             break;
9961             
9962         case '*' :
9963             genMult (ic);
9964             break;
9965             
9966         case '/' :
9967             genDiv (ic) ;
9968             break;
9969             
9970         case '%' :
9971             genMod (ic);
9972             break;
9973             
9974         case '>' :
9975             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9976             break;
9977             
9978         case '<' :
9979             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9980             break;
9981             
9982         case LE_OP:
9983         case GE_OP:
9984         case NE_OP:
9985             
9986             /* note these two are xlated by algebraic equivalence
9987                during parsing SDCC.y */
9988             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9989                    "got '>=' or '<=' shouldn't have come here");
9990             break;      
9991             
9992         case EQ_OP:
9993             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9994             break;          
9995             
9996         case AND_OP:
9997             genAndOp (ic);
9998             break;
9999             
10000         case OR_OP:
10001             genOrOp (ic);
10002             break;
10003             
10004         case '^' :
10005             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10006             break;
10007             
10008         case '|' :
10009                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10010             break;
10011             
10012         case BITWISEAND:
10013             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10014             break;
10015             
10016         case INLINEASM:
10017             genInline (ic);
10018             break;
10019             
10020         case RRC:
10021             genRRC (ic);
10022             break;
10023             
10024         case RLC:
10025             genRLC (ic);
10026             break;
10027             
10028         case GETHBIT:
10029             genGetHbit (ic);
10030             break;
10031             
10032         case LEFT_OP:
10033             genLeftShift (ic);
10034             break;
10035             
10036         case RIGHT_OP:
10037             genRightShift (ic);
10038             break;
10039             
10040         case GET_VALUE_AT_ADDRESS:
10041             genPointerGet(ic);
10042             break;
10043             
10044         case '=' :
10045             if (POINTER_SET(ic))
10046                 genPointerSet(ic);
10047             else
10048                 genAssign(ic);
10049             break;
10050             
10051         case IFX:
10052             genIfx (ic,NULL);
10053             break;
10054             
10055         case ADDRESS_OF:
10056             genAddrOf (ic);
10057             break;
10058             
10059         case JUMPTABLE:
10060             genJumpTab (ic);
10061             break;
10062             
10063         case CAST:
10064             genCast (ic);
10065             break;
10066             
10067         case RECEIVE:
10068             genReceive(ic);
10069             break;
10070             
10071         case SEND:
10072             addSet(&_G.sendSet,ic);
10073             break;
10074
10075         default :
10076             ic = ic;
10077         }
10078     }
10079     
10080
10081     /* now we are ready to call the 
10082        peep hole optimizer */
10083     if (!options.nopeep) {
10084       peepHole (&lineHead);
10085     }
10086     /* now do the actual printing */
10087     printLine (lineHead,codeOutFile);
10088
10089 #ifdef PCODE_DEBUG
10090     DFPRINTF((stderr,"printing pBlock\n\n"));
10091     printpBlock(stdout,pb);
10092 #endif
10093
10094     return;
10095 }