Added support to generate code for struct bit fields.
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
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 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45
46 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 void genMult8X8_8 (operand *, operand *,operand *);
49 pCode *AssembleLine(char *line);
50 extern void printpBlock(FILE *of, pBlock *pb);
51
52 static int labelOffset=0;
53 extern int debug_verbose;
54 static int optimized_for_speed = 0;
55
56 /* max_key keeps track of the largest label number used in 
57 a function. This is then used to adjust the label offset
58 for the next function.
59 */
60 static int max_key=0;
61 static int GpsuedoStkPtr=0;
62
63 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
64 unsigned int pic14aopLiteral (value *val, int offset);
65 const char *AopType(short type);
66
67 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
68
69 /* this is the down and dirty file with all kinds of 
70 kludgy & hacky stuff. This is what it is all about
71 CODE GENERATION for a specific MCU . some of the
72 routines may be reusable, will have to see */
73
74 static char *zero = "#0x00";
75 static char *one  = "#0x01";
76 static char *spname = "sp";
77
78 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
79 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
80 static char **fReturn = fReturnpic14;
81
82 static char *accUse[] = {"a","b"};
83
84 //static short rbank = -1;
85
86 static struct {
87         short r0Pushed;
88         short r1Pushed;
89         short accInUse;
90         short inLine;
91         short debugLine;
92         short nRegsSaved;
93         set *sendSet;
94 } _G;
95
96 /* Resolved ifx structure. This structure stores information
97 about an iCode ifx that makes it easier to generate code.
98 */
99 typedef struct resolvedIfx {
100         symbol *lbl;     /* pointer to a label */
101         int condition;   /* true or false ifx */
102         int generated;   /* set true when the code associated with the ifx
103                           * is generated */
104 } resolvedIfx;
105
106 extern int pic14_ptrRegReq ;
107 extern int pic14_nRegs;
108 extern FILE *codeOutFile;
109 static void saverbank (int, iCode *,bool);
110
111 static lineNode *lineHead = NULL;
112 static lineNode *lineCurr = NULL;
113
114 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
115 0xE0, 0xC0, 0x80, 0x00};
116 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
117 0x07, 0x03, 0x01, 0x00};
118
119 static  pBlock *pb;
120
121 /*-----------------------------------------------------------------*/
122 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
123 /*                                 exponent of 2 is returned, otherwise -1 is      */
124 /*                                 returned.                                                                       */
125 /* note that this is similar to the function `powof2' in SDCCsymt  */
126 /* if(n == 2^y)                                                                                                    */
127 /*       return y;                                                                                                         */
128 /* return -1;                                                                                                      */
129 /*-----------------------------------------------------------------*/
130 static int my_powof2 (unsigned long num)
131 {
132         if(num) {
133                 if( (num & (num-1)) == 0) {
134                         int nshifts = -1;
135                         while(num) {
136                                 num>>=1;
137                                 nshifts++;
138                         }
139                         return nshifts;
140                 }
141         }
142         
143         return -1;
144 }
145
146 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
147 {
148         
149         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
150                 line_no,
151                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
152                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
153                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
154                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
155                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
156                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
157                 ((result) ? AOP_SIZE(result) : 0));
158         
159 }
160
161 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
162 {
163         
164         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
165                 line_no,
166                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
167                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
168                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
169                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
170                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
171                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
172         
173 }
174
175 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
176 {
177         va_list ap;
178         char lb[INITIAL_INLINEASM];  
179         char *lbp = lb;
180         
181         if(!debug_verbose)
182                 return;
183         
184         va_start(ap,fmt);   
185         
186         if (inst && *inst) {
187                 if (fmt && *fmt)
188                         sprintf(lb,"%s\t",inst);
189                 else
190                         sprintf(lb,"%s",inst);
191                 vsprintf(lb+(strlen(lb)),fmt,ap);
192         }  else
193                 vsprintf(lb,fmt,ap);
194         
195         while (isspace(*lbp)) lbp++;
196         
197         if (lbp && *lbp) 
198                 lineCurr = (lineCurr ?
199                 connectLine(lineCurr,newLineNode(lb)) :
200         (lineHead = newLineNode(lb)));
201         lineCurr->isInline = _G.inLine;
202         lineCurr->isDebug  = _G.debugLine;
203         
204         addpCode2pBlock(pb,newpCodeCharP(lb));
205         
206         va_end(ap);
207 }
208
209
210 void emitpLabel(int key)
211 {
212         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
213 }
214
215 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
216 {
217         if(pcop)
218                 addpCode2pBlock(pb,newpCode(poc,pcop));
219         else
220                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
221 }
222
223 void emitpcodeNULLop(PIC_OPCODE poc)
224 {
225         
226         addpCode2pBlock(pb,newpCode(poc,NULL));
227         
228 }
229
230
231 /*-----------------------------------------------------------------*/
232 /* pic14_emitcode - writes the code into a file : for now it is simple    */
233 /*-----------------------------------------------------------------*/
234 void pic14_emitcode (char *inst,char *fmt, ...)
235 {
236         va_list ap;
237         char lb[INITIAL_INLINEASM];  
238         char *lbp = lb;
239         
240         va_start(ap,fmt);   
241         
242         if (inst && *inst) {
243                 if (fmt && *fmt)
244                         sprintf(lb,"%s\t",inst);
245                 else
246                         sprintf(lb,"%s",inst);
247                 vsprintf(lb+(strlen(lb)),fmt,ap);
248         }  else
249                 vsprintf(lb,fmt,ap);
250         
251         while (isspace(*lbp)) lbp++;
252         
253         if (lbp && *lbp) 
254                 lineCurr = (lineCurr ?
255                 connectLine(lineCurr,newLineNode(lb)) :
256         (lineHead = newLineNode(lb)));
257         lineCurr->isInline = _G.inLine;
258         lineCurr->isDebug  = _G.debugLine;
259         
260         if(debug_verbose)
261                 addpCode2pBlock(pb,newpCodeCharP(lb));
262         
263         va_end(ap);
264 }
265
266 /*-----------------------------------------------------------------*/
267 /* pic14_emitDebuggerSymbol - associate the current code location  */
268 /*       with a debugger symbol                                                                            */
269 /*-----------------------------------------------------------------*/
270 void
271 pic14_emitDebuggerSymbol (char * debugSym)
272 {
273         _G.debugLine = 1;
274         pic14_emitcode ("", ";%s ==.", debugSym);
275         _G.debugLine = 0;
276 }
277
278
279 /*-----------------------------------------------------------------*/
280 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
281 /*-----------------------------------------------------------------*/
282 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
283 {
284         bool r0iu = FALSE , r1iu = FALSE;
285         bool r0ou = FALSE , r1ou = FALSE;
286         
287         /* the logic: if r0 & r1 used in the instruction
288         then we are in trouble otherwise */
289         
290         /* first check if r0 & r1 are used by this
291         instruction, in which case we are in trouble */
292         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
293                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
294         {
295                 goto endOfWorld;          
296         }
297         
298         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
299         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
300         
301         /* if no usage of r0 then return it */
302         if (!r0iu && !r0ou) {
303                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
304                 (*aopp)->type = AOP_R0;
305                 
306                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
307         }
308         
309         /* if no usage of r1 then return it */
310         if (!r1iu && !r1ou) {
311                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
312                 (*aopp)->type = AOP_R1;
313                 
314                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
315         }    
316         
317         /* now we know they both have usage */
318         /* if r0 not used in this instruction */
319         if (!r0iu) {
320                 /* push it if not already pushed */
321                 if (!_G.r0Pushed) {
322                         //pic14_emitcode ("push","%s",
323                         //                pic14_regWithIdx(R0_IDX)->dname);
324                         _G.r0Pushed++ ;
325                 }
326                 
327                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
328                 (*aopp)->type = AOP_R0;
329                 
330                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
331         }
332         
333         /* if r1 not used then */
334         
335         if (!r1iu) {
336                 /* push it if not already pushed */
337                 if (!_G.r1Pushed) {
338                         //pic14_emitcode ("push","%s",
339                         //                pic14_regWithIdx(R1_IDX)->dname);
340                         _G.r1Pushed++ ;
341                 }
342                 
343                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
344                 (*aopp)->type = AOP_R1;
345                 return pic14_regWithIdx(R1_IDX);
346         }
347         
348 endOfWorld :
349         /* I said end of world but not quite end of world yet */
350         /* if this is a result then we can push it on the stack*/
351         if (result) {
352                 (*aopp)->type = AOP_STK;        
353                 return NULL;
354         }
355         
356         /* other wise this is true end of the world */
357         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
358                 "getFreePtr should never reach here");
359         exit(0);
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* newAsmop - creates a new asmOp                                                                  */
364 /*-----------------------------------------------------------------*/
365 asmop *newAsmop (short type)
366 {
367         asmop *aop;
368         
369         aop = Safe_calloc(1,sizeof(asmop));
370         aop->type = type;
371         return aop;
372 }
373
374 static void genSetDPTR(int n)
375 {
376         if (!n)
377         {
378                 pic14_emitcode(";", "Select standard DPTR");
379                 pic14_emitcode("mov", "dps, #0x00");
380         }
381         else
382         {
383                 pic14_emitcode(";", "Select alternate DPTR");
384                 pic14_emitcode("mov", "dps, #0x01");
385         }
386 }
387
388 /*-----------------------------------------------------------------*/
389 /* resolveIfx - converts an iCode ifx into a form more useful for  */
390 /*                              generating code                                                                    */
391 /*-----------------------------------------------------------------*/
392 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
393 {
394         if(!resIfx) 
395                 return;
396         
397         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
398         
399         resIfx->condition = 1;  /* assume that the ifx is true */
400         resIfx->generated = 0;  /* indicate that the ifx has not been used */
401         
402         if(!ifx) {
403                 resIfx->lbl = newiTempLabel(NULL);      /* oops, there is no ifx. so create a label */
404                                                                                         /*
405                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
406                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
407                 */
408         } else {
409                 if(IC_TRUE(ifx)) {
410                         resIfx->lbl = IC_TRUE(ifx);
411                 } else {
412                         resIfx->lbl = IC_FALSE(ifx);
413                         resIfx->condition = 0;
414                 }
415                 /*
416                 if(IC_TRUE(ifx)) 
417                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
418                 if(IC_FALSE(ifx)) 
419                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
420                 */
421         }
422         
423         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
424         
425 }
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type                       */
428 /*-----------------------------------------------------------------*/
429 static int pointerCode (sym_link *etype)
430 {
431         
432         return PTR_TYPE(SPEC_OCLS(etype));
433         
434 }
435
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol                                                                   */
438 /*-----------------------------------------------------------------*/
439 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
440 {
441         asmop *aop;
442         memmap *space= SPEC_OCLS(sym->etype);
443         
444         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
445         /* if already has one */
446         if (sym->aop)
447                 return sym->aop;
448         
449         /* assign depending on the storage class */
450         /* if it is on the stack or indirectly addressable */
451         /* space we need to assign either r0 or r1 to it         */    
452         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
453                 sym->aop = aop = newAsmop(0);
454                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
455                 aop->size = getSize(sym->type);
456                 
457                 /* now assign the address of the variable to 
458                 the pointer register */
459                 if (aop->type != AOP_STK) {
460                         
461                         if (sym->onStack) {
462                                 if ( _G.accInUse )
463                                         pic14_emitcode("push","acc");
464                                 
465                                 pic14_emitcode("mov","a,_bp");
466                                 pic14_emitcode("add","a,#0x%02x",
467                                         ((sym->stack < 0) ?
468                                         ((char)(sym->stack - _G.nRegsSaved )) :
469                                 ((char)sym->stack)) & 0xff);
470                                 pic14_emitcode("mov","%s,a",
471                                         aop->aopu.aop_ptr->name);
472                                 
473                                 if ( _G.accInUse )
474                                         pic14_emitcode("pop","acc");
475                         } else
476                                 pic14_emitcode("mov","%s,#%s",
477                                 aop->aopu.aop_ptr->name,
478                                 sym->rname);
479                         aop->paged = space->paged;
480                 } else
481                         aop->aopu.aop_stk = sym->stack;
482                 return aop;
483         }
484         
485         if (sym->onStack && options.stack10bit)
486         {
487                 /* It's on the 10 bit stack, which is located in
488                 * far data space.
489                 */
490                 
491                 //DEBUGpic14_emitcode(";","%d",__LINE__);
492                 
493                 if ( _G.accInUse )
494                         pic14_emitcode("push","acc");
495                 
496                 pic14_emitcode("mov","a,_bp");
497                 pic14_emitcode("add","a,#0x%02x",
498                         ((sym->stack < 0) ?
499                         ((char)(sym->stack - _G.nRegsSaved )) :
500                 ((char)sym->stack)) & 0xff);
501                 
502                 genSetDPTR(1);
503                 pic14_emitcode ("mov","dpx1,#0x40");
504                 pic14_emitcode ("mov","dph1,#0x00");
505                 pic14_emitcode ("mov","dpl1, a");
506                 genSetDPTR(0);
507                 
508                 if ( _G.accInUse )
509                         pic14_emitcode("pop","acc");
510                 
511                 sym->aop = aop = newAsmop(AOP_DPTR2);
512                 aop->size = getSize(sym->type); 
513                 return aop;
514         }
515         
516         //DEBUGpic14_emitcode(";","%d",__LINE__);
517         /* if in bit space */
518         if (IN_BITSPACE(space)) {
519                 sym->aop = aop = newAsmop (AOP_CRY);
520                 aop->aopu.aop_dir = sym->rname ;
521                 aop->size = getSize(sym->type);
522                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
523                 return aop;
524         }
525         /* if it is in direct space */
526         if (IN_DIRSPACE(space)) {
527                 sym->aop = aop = newAsmop (AOP_DIR);
528                 aop->aopu.aop_dir = sym->rname ;
529                 aop->size = getSize(sym->type);
530                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
531                 return aop;
532         }
533         
534         /* special case for a function */
535         if (IS_FUNC(sym->type)) {   
536                 
537                 sym->aop = aop = newAsmop(AOP_PCODE);
538                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
539                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
540                 PCOI(aop->aopu.pcop)->_function = 1;
541                 PCOI(aop->aopu.pcop)->index = 0;
542                 aop->size = FPTRSIZE; 
543                 /*
544                 sym->aop = aop = newAsmop(AOP_IMMD);    
545                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
546                 strcpy(aop->aopu.aop_immd,sym->rname);
547                 aop->size = FPTRSIZE; 
548                 */
549                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
550                 return aop;
551         }
552         
553         
554         /* only remaining is far space */
555         /* in which case DPTR gets the address */
556         sym->aop = aop = newAsmop(AOP_PCODE);
557         
558         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
559         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
560         PCOI(aop->aopu.pcop)->index = 0;
561         
562         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
563                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
564         
565         allocDirReg (IC_LEFT(ic));
566         
567         aop->size = FPTRSIZE; 
568         /*
569         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
570         sym->aop = aop = newAsmop(AOP_DPTR);
571         pic14_emitcode ("mov","dptr,#%s", sym->rname);
572         aop->size = getSize(sym->type);
573         
574           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
575         */
576         
577         /* if it is in code space */
578         if (IN_CODESPACE(space))
579                 aop->code = 1;
580         
581         return aop;       
582 }
583
584 /*-----------------------------------------------------------------*/
585 /* aopForRemat - rematerialzes an object                                                   */
586 /*-----------------------------------------------------------------*/
587 static asmop *aopForRemat (operand *op) // x symbol *sym)
588 {
589         symbol *sym = OP_SYMBOL(op);
590         iCode *ic = NULL;
591         asmop *aop = newAsmop(AOP_PCODE);
592         int val = 0;
593         int offset = 0;
594         
595         ic = sym->rematiCode;
596         
597         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
598         if(IS_OP_POINTER(op)) {
599                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
600         }
601         for (;;) {
602                 if (ic->op == '+') {
603                         val += (int) operandLitValue(IC_RIGHT(ic));
604                 } else if (ic->op == '-') {
605                         val -= (int) operandLitValue(IC_RIGHT(ic));
606                 } else
607                         break;
608                 
609                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
610         }
611         
612         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
613         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
614         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
615         PCOI(aop->aopu.pcop)->index = val;
616         
617         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
618                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
619                 val, IS_PTR_CONST(operandType(op)));
620         
621         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
622         
623         allocDirReg (IC_LEFT(ic));
624         
625         return aop;              
626 }
627
628 int aopIdx (asmop *aop, int offset)
629 {
630         if(!aop)
631                 return -1;
632         
633         if(aop->type !=  AOP_REG)
634                 return -2;
635         
636         return aop->aopu.aop_reg[offset]->rIdx;
637         
638 }
639 /*-----------------------------------------------------------------*/
640 /* regsInCommon - two operands have some registers in common       */
641 /*-----------------------------------------------------------------*/
642 static bool regsInCommon (operand *op1, operand *op2)
643 {
644         symbol *sym1, *sym2;
645         int i;
646         
647         /* if they have registers in common */
648         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
649                 return FALSE ;
650         
651         sym1 = OP_SYMBOL(op1);
652         sym2 = OP_SYMBOL(op2);
653         
654         if (sym1->nRegs == 0 || sym2->nRegs == 0)
655                 return FALSE ;
656         
657         for (i = 0 ; i < sym1->nRegs ; i++) {
658                 int j;
659                 if (!sym1->regs[i])
660                         continue ;
661                 
662                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
663                         if (!sym2->regs[j])
664                                 continue ;
665                         
666                         if (sym2->regs[j] == sym1->regs[i])
667                                 return TRUE ;
668                 }
669         }
670         
671         return FALSE ;
672 }
673
674 /*-----------------------------------------------------------------*/
675 /* operandsEqu - equivalent                                                                        */
676 /*-----------------------------------------------------------------*/
677 static bool operandsEqu ( operand *op1, operand *op2)
678 {
679         symbol *sym1, *sym2;
680         
681         /* if they not symbols */
682         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
683                 return FALSE;
684         
685         sym1 = OP_SYMBOL(op1);
686         sym2 = OP_SYMBOL(op2);
687         
688         /* if both are itemps & one is spilt
689         and the other is not then false */
690         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
691                 sym1->isspilt != sym2->isspilt )
692                 return FALSE ;
693         
694         /* if they are the same */
695         if (sym1 == sym2)
696                 return TRUE ;
697         
698         if (sym1->rname[0] && sym2->rname[0]
699                 && strcmp (sym1->rname, sym2->rname) == 0)
700                 return TRUE;
701         
702         
703         /* if left is a tmp & right is not */
704         if (IS_ITEMP(op1)  && 
705                 !IS_ITEMP(op2) &&
706                 sym1->isspilt  &&
707                 (sym1->usl.spillLoc == sym2))
708                 return TRUE;
709         
710         if (IS_ITEMP(op2)  && 
711                 !IS_ITEMP(op1) &&
712                 sym2->isspilt  &&
713                 sym1->level > 0 &&
714                 (sym2->usl.spillLoc == sym1))
715                 return TRUE ;
716         
717         return FALSE ;
718 }
719
720 /*-----------------------------------------------------------------*/
721 /* pic14_sameRegs - two asmops have the same registers             */
722 /*-----------------------------------------------------------------*/
723 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
724 {
725         int i;
726         
727         if (aop1 == aop2)
728                 return TRUE ;
729         
730         if (aop1->type != AOP_REG ||
731                 aop2->type != AOP_REG )
732                 return FALSE ;
733         
734         if (aop1->size != aop2->size )
735                 return FALSE ;
736         
737         for (i = 0 ; i < aop1->size ; i++ )
738                 if (aop1->aopu.aop_reg[i] !=
739                         aop2->aopu.aop_reg[i] )
740                         return FALSE ;
741                 
742                 return TRUE ;
743 }
744
745 /*-----------------------------------------------------------------*/
746 /* aopOp - allocates an asmop for an operand  :                    */
747 /*-----------------------------------------------------------------*/
748 void aopOp (operand *op, iCode *ic, bool result)
749 {
750         asmop *aop;
751         symbol *sym;
752         int i;
753         
754         if (!op)
755                 return ;
756         
757         /* if this a literal */
758         if (IS_OP_LITERAL(op)) {
759                 op->aop = aop = newAsmop(AOP_LIT);
760                 aop->aopu.aop_lit = op->operand.valOperand;
761                 aop->size = getSize(operandType(op));
762                 return;
763         }
764         
765         {
766                 sym_link *type = operandType(op);
767                 if(IS_PTR_CONST(type))
768                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
769         }
770         
771         /* if already has a asmop then continue */
772         if (op->aop)
773                 return ;
774         
775         /* if the underlying symbol has a aop */
776         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
777                 DEBUGpic14_emitcode(";","%d",__LINE__);
778                 op->aop = OP_SYMBOL(op)->aop;
779                 return;
780         }
781         
782         /* if this is a true symbol */
783         if (IS_TRUE_SYMOP(op)) {          
784                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
785                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
786                 return ;
787         }
788         
789         /* this is a temporary : this has
790         only four choices :
791         a) register
792         b) spillocation
793         c) rematerialize 
794         d) conditional   
795         e) can be a return use only */
796         
797         sym = OP_SYMBOL(op);
798         
799         
800         /* if the type is a conditional */
801         if (sym->regType == REG_CND) {
802                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
803                 aop->size = 0;
804                 return;
805         }
806         
807         /* if it is spilt then two situations
808         a) is rematerialize 
809         b) has a spill location */
810         if (sym->isspilt || sym->nRegs == 0) {
811                 
812                 DEBUGpic14_emitcode(";","%d",__LINE__);
813                 /* rematerialize it NOW */
814                 if (sym->remat) {
815                         
816                         sym->aop = op->aop = aop = aopForRemat (op);
817                         aop->size = getSize(sym->type);
818                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
819                         return;
820                 }
821                 
822                 if (sym->accuse) {
823                         int i;
824                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
825                         aop->size = getSize(sym->type);
826                         for ( i = 0 ; i < 2 ; i++ )
827                                 aop->aopu.aop_str[i] = accUse[i];
828                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
829                         return;  
830                 }
831                 
832                 if (sym->ruonly ) {
833                         if(sym->isptr) {        // && sym->uptr 
834                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
835                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
836                                 
837                                 //PCOI(aop->aopu.pcop)->_const = 0;
838                                 //PCOI(aop->aopu.pcop)->index = 0;
839                                 /*
840                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
841                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
842                                 */
843                                 //allocDirReg (IC_LEFT(ic));
844                                 
845                                 aop->size = getSize(sym->type);
846                                 DEBUGpic14_emitcode(";","%d",__LINE__);
847                                 return;
848                                 
849                         } else {
850                                 
851                                 unsigned i;
852                                 
853                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
854                                 aop->size = getSize(sym->type);
855                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
856                                         aop->aopu.aop_str[i] = fReturn[i];
857                                 
858                                 DEBUGpic14_emitcode(";","%d",__LINE__);
859                                 return;
860                         }
861                 }
862                 
863                 /* else spill location  */
864                 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
865                         /* force a new aop if sizes differ */
866                         sym->usl.spillLoc->aop = NULL;
867                 }
868                 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
869                         __FUNCTION__,__LINE__,
870                         sym->usl.spillLoc->rname,
871                         sym->rname, sym->usl.spillLoc->offset);
872                 
873                 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
874                 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
875                 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
876                         getSize(sym->type), 
877                         sym->usl.spillLoc->offset);
878                 aop->size = getSize(sym->type);
879                 
880                 return;
881         }
882         
883         {
884                 sym_link *type = operandType(op);
885                 if(IS_PTR_CONST(type)) 
886                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
887         }
888         
889         /* must be in a register */
890         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
891         sym->aop = op->aop = aop = newAsmop(AOP_REG);
892         aop->size = sym->nRegs;
893         for ( i = 0 ; i < sym->nRegs ;i++)
894                 aop->aopu.aop_reg[i] = sym->regs[i];
895 }
896
897 /*-----------------------------------------------------------------*/
898 /* freeAsmop - free up the asmop given to an operand                       */
899 /*----------------------------------------------------------------*/
900 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
901 {       
902         asmop *aop ;
903         
904         if (!op)
905                 aop = aaop;
906         else 
907                 aop = op->aop;
908         
909         if (!aop)
910                 return ;
911         
912         if (aop->freed)
913                 goto dealloc; 
914         
915         aop->freed = 1;
916         
917         /* depending on the asmop type only three cases need work AOP_RO
918         , AOP_R1 && AOP_STK */
919 #if 0
920         switch (aop->type) {
921         case AOP_R0 :
922                 if (_G.r0Pushed ) {
923                         if (pop) {
924                                 pic14_emitcode ("pop","ar0");     
925                                 _G.r0Pushed--;
926                         }
927                 }
928                 bitVectUnSetBit(ic->rUsed,R0_IDX);
929                 break;
930                 
931         case AOP_R1 :
932                 if (_G.r1Pushed ) {
933                         if (pop) {
934                                 pic14_emitcode ("pop","ar1");
935                                 _G.r1Pushed--;
936                         }
937                 }
938                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
939                 break;
940                 
941         case AOP_STK :
942                 {
943                         int sz = aop->size;      
944                         int stk = aop->aopu.aop_stk + aop->size;
945                         bitVectUnSetBit(ic->rUsed,R0_IDX);
946                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
947                         
948                         getFreePtr(ic,&aop,FALSE);
949                         
950                         if (options.stack10bit)
951                         {
952                                 /* I'm not sure what to do here yet... */
953                                 /* #STUB */
954                                 fprintf(stderr, 
955                                         "*** Warning: probably generating bad code for "
956                                         "10 bit stack mode.\n");
957                         }
958                         
959                         if (stk) {
960                                 pic14_emitcode ("mov","a,_bp");
961                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
962                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
963                         } else {
964                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
965                         }
966                         
967                         while (sz--) {
968                                 pic14_emitcode("pop","acc");
969                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
970                                 if (!sz) break;
971                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
972                         }
973                         op->aop = aop;
974                         freeAsmop(op,NULL,ic,TRUE);
975                         if (_G.r0Pushed) {
976                                 pic14_emitcode("pop","ar0");
977                                 _G.r0Pushed--;
978                         }
979                         
980                         if (_G.r1Pushed) {
981                                 pic14_emitcode("pop","ar1");
982                                 _G.r1Pushed--;
983                         }         
984                 }
985         }
986 #endif
987         
988 dealloc:
989         /* all other cases just dealloc */
990         if (op ) {
991                 op->aop = NULL;
992                 if (IS_SYMOP(op)) {
993                         OP_SYMBOL(op)->aop = NULL;      
994                         /* if the symbol has a spill */
995                         if (SPIL_LOC(op))
996                                 SPIL_LOC(op)->aop = NULL;
997                 }
998         }
999 }
1000
1001 /*-----------------------------------------------------------------*/
1002 /* aopGet - for fetching value of the aop                                                  */
1003 /*-----------------------------------------------------------------*/
1004 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1005 {
1006         char *s = buffer ;
1007         char *rs;
1008         
1009         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1010         /* offset is greater than
1011         size then zero */
1012         if (offset > (aop->size - 1) &&
1013                 aop->type != AOP_LIT)
1014                 return zero;
1015         
1016         /* depending on type */
1017         switch (aop->type) {
1018                 
1019         case AOP_R0:
1020         case AOP_R1:
1021                 DEBUGpic14_emitcode(";","%d",__LINE__);
1022                 /* if we need to increment it */           
1023                 while (offset > aop->coff) {            
1024                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1025                         aop->coff++;
1026                 }
1027                 
1028                 while (offset < aop->coff) {
1029                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1030                         aop->coff--;
1031                 }
1032                 
1033                 aop->coff = offset ;
1034                 if (aop->paged) {
1035                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1036                         return (dname ? "acc" : "a");
1037                 }               
1038                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1039                 rs = Safe_calloc(1,strlen(s)+1);
1040                 strcpy(rs,s);   
1041                 return rs;
1042                 
1043         case AOP_DPTR:
1044         case AOP_DPTR2:
1045                 DEBUGpic14_emitcode(";","%d",__LINE__);
1046                 if (aop->type == AOP_DPTR2)
1047                 {
1048                         genSetDPTR(1);
1049                 }
1050                 
1051                 while (offset > aop->coff) {
1052                         pic14_emitcode ("inc","dptr");
1053                         aop->coff++;
1054                 }
1055                 
1056                 while (offset < aop->coff) {            
1057                         pic14_emitcode("lcall","__decdptr");
1058                         aop->coff--;
1059                 }
1060                 
1061                 aop->coff = offset;
1062                 if (aop->code) {
1063                         pic14_emitcode("clr","a");
1064                         pic14_emitcode("movc","a,@a+dptr");
1065                 }
1066                 else {
1067                         pic14_emitcode("movx","a,@dptr");
1068                 }
1069                 
1070                 if (aop->type == AOP_DPTR2)
1071                 {
1072                         genSetDPTR(0);
1073                 }
1074                 
1075                 return (dname ? "acc" : "a");
1076                 
1077                 
1078         case AOP_IMMD:
1079                 if (bit16) 
1080                         sprintf (s,"%s",aop->aopu.aop_immd);
1081                 else
1082                         if (offset) 
1083                                 sprintf(s,"(%s >> %d)",
1084                                 aop->aopu.aop_immd,
1085                                 offset*8);
1086                         else
1087                                 sprintf(s,"%s",
1088                                 aop->aopu.aop_immd);
1089                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1090                         rs = Safe_calloc(1,strlen(s)+1);
1091                         strcpy(rs,s);   
1092                         return rs;
1093                         
1094         case AOP_DIR:
1095                 if (offset) {
1096                         sprintf(s,"(%s + %d)",
1097                                 aop->aopu.aop_dir,
1098                                 offset);
1099                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1100                 } else
1101                         sprintf(s,"%s",aop->aopu.aop_dir);
1102                 rs = Safe_calloc(1,strlen(s)+1);
1103                 strcpy(rs,s);   
1104                 return rs;
1105                 
1106         case AOP_REG:
1107                 //if (dname) 
1108                 //        return aop->aopu.aop_reg[offset]->dname;
1109                 //else
1110                 return aop->aopu.aop_reg[offset]->name;
1111                 
1112         case AOP_CRY:
1113                 //pic14_emitcode(";","%d",__LINE__);
1114                 return aop->aopu.aop_dir;
1115                 
1116         case AOP_ACC:
1117                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1118                 return "AOP_accumulator_bug";
1119                 
1120         case AOP_LIT:
1121                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1122                 rs = Safe_calloc(1,strlen(s)+1);
1123                 strcpy(rs,s);   
1124                 return rs;
1125                 
1126         case AOP_STR:
1127                 aop->coff = offset ;
1128                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1129                         dname)
1130                         return "acc";
1131                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1132                 
1133                 return aop->aopu.aop_str[offset];
1134                 
1135         case AOP_PCODE:
1136                 {
1137                         pCodeOp *pcop = aop->aopu.pcop;
1138                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1139                         if(pcop->name) {
1140                                 if (offset) {
1141                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1142                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1143                                 } else {
1144                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1145                                         sprintf(s,"%s", pcop->name);
1146                                 }
1147                         } else
1148                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1149                         
1150                 }
1151                 rs = Safe_calloc(1,strlen(s)+1);
1152                 strcpy(rs,s);   
1153                 return rs;
1154                 
1155   }
1156   
1157   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1158           "aopget got unsupported aop->type");
1159   exit(0);
1160 }
1161
1162
1163 /*-----------------------------------------------------------------*/
1164 /* popGetTempReg - create a new temporary pCodeOp                                  */
1165 /*-----------------------------------------------------------------*/
1166 pCodeOp *popGetTempReg(void)
1167 {
1168         
1169         pCodeOp *pcop;
1170         
1171         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1172         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1173                 PCOR(pcop)->r->wasUsed=1;
1174                 PCOR(pcop)->r->isFree=0;
1175         }
1176         
1177         return pcop;
1178 }
1179
1180 /*-----------------------------------------------------------------*/
1181 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1182 /*-----------------------------------------------------------------*/
1183 void popReleaseTempReg(pCodeOp *pcop)
1184 {
1185         
1186         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1187                 PCOR(pcop)->r->isFree = 1;
1188         
1189 }
1190 /*-----------------------------------------------------------------*/
1191 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1192 /*-----------------------------------------------------------------*/
1193 pCodeOp *popGetLabel(unsigned int key)
1194 {
1195         
1196         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1197         
1198         if(key>(unsigned int)max_key)
1199                 max_key = key;
1200         
1201         return newpCodeOpLabel(NULL,key+100+labelOffset);
1202 }
1203
1204 /*-------------------------------------------------------------------*/
1205 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1206 /*-------------------------------------------------------------------*/
1207 pCodeOp *popGetHighLabel(unsigned int key)
1208 {
1209         pCodeOp *pcop;
1210         pcop = popGetLabel(key);
1211         PCOLAB(pcop)->offset = 1;
1212         return pcop;
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* popGetLit - asm operator to pcode operator conversion                           */
1217 /*-----------------------------------------------------------------*/
1218 pCodeOp *popGetLit(unsigned int lit)
1219 {
1220         
1221         return newpCodeOpLit(lit);
1222 }
1223
1224 /*-----------------------------------------------------------------*/
1225 /* popGetImmd - asm operator to pcode immediate conversion                 */
1226 /*-----------------------------------------------------------------*/
1227 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1228 {
1229         
1230         return newpCodeOpImmd(name, offset,index, 0, is_func);
1231 }
1232
1233
1234 /*-----------------------------------------------------------------*/
1235 /* popGetWithString - asm operator to pcode operator conversion                    */
1236 /*-----------------------------------------------------------------*/
1237 pCodeOp *popGetWithString(char *str, int isExtern)
1238 {
1239         pCodeOp *pcop;
1240         
1241         
1242         if(!str) {
1243                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1244                 exit (1);
1245         }
1246         
1247         pcop = newpCodeOp(str,PO_STR);
1248         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1249         
1250         return pcop;
1251 }
1252
1253 /*-----------------------------------------------------------------*/
1254 /* popRegFromString -                                                                                      */
1255 /*-----------------------------------------------------------------*/
1256 pCodeOp *popRegFromString(char *str, int size, int offset)
1257 {
1258         
1259         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1260         pcop->type = PO_DIR;
1261         
1262         DEBUGpic14_emitcode(";","%d",__LINE__);
1263         
1264         if(!str)
1265                 str = "BAD_STRING";
1266         
1267         pcop->name = Safe_calloc(1,strlen(str)+1);
1268         strcpy(pcop->name,str);
1269         
1270         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1271         
1272         PCOR(pcop)->r = dirregWithName(pcop->name);
1273         if(PCOR(pcop)->r == NULL) {
1274                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1275                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1276                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1277         } else {
1278                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1279         }
1280         PCOR(pcop)->instance = offset;
1281         
1282         return pcop;
1283 }
1284
1285 /*-----------------------------------------------------------------*/
1286 /*-----------------------------------------------------------------*/
1287 pCodeOp *popRegFromIdx(int rIdx)
1288 {
1289         pCodeOp *pcop;
1290         
1291         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1292                 __FUNCTION__,__LINE__,rIdx);
1293         
1294         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1295         
1296         PCOR(pcop)->rIdx = rIdx;
1297         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1298         PCOR(pcop)->r->isFree = 0;
1299         PCOR(pcop)->r->wasUsed = 1;
1300         
1301         pcop->type = PCOR(pcop)->r->pc_type;
1302         
1303         
1304         return pcop;
1305 }
1306
1307 /*-----------------------------------------------------------------*/
1308 /* popGet - asm operator to pcode operator conversion                      */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1311 {
1312         //char *s = buffer ;
1313         //char *rs;
1314         
1315         pCodeOp *pcop;
1316         
1317         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1318         /* offset is greater than
1319         size then zero */
1320         
1321         if (offset > (aop->size - 1) &&
1322                 aop->type != AOP_LIT)
1323                 return NULL;  //zero;
1324         
1325         /* depending on type */
1326         switch (aop->type) {
1327                 
1328         case AOP_R0:
1329         case AOP_R1:
1330         case AOP_DPTR:
1331         case AOP_DPTR2:
1332         case AOP_ACC:
1333                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1334                 return NULL;
1335                 
1336         case AOP_IMMD:
1337                 DEBUGpic14_emitcode(";","%d",__LINE__);
1338                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1339                 
1340         case AOP_DIR:
1341                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1342 #if 0
1343                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1344                 pcop->type = PO_DIR;
1345                 
1346                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1347                 strcpy(pcop->name,aop->aopu.aop_dir);   
1348                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1349                 if(PCOR(pcop)->r == NULL) {
1350                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1351                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1352                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1353                 } else {
1354                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1355                 }
1356                 PCOR(pcop)->instance = offset;
1357                 
1358                 return pcop;
1359 #endif
1360                 
1361         case AOP_REG:
1362                 {
1363                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1364                         
1365                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1366                         PCOR(pcop)->rIdx = rIdx;
1367                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1368                         PCOR(pcop)->r->wasUsed=1;
1369                         PCOR(pcop)->r->isFree=0;
1370                         
1371                         PCOR(pcop)->instance = offset;
1372                         pcop->type = PCOR(pcop)->r->pc_type;
1373                         //rs = aop->aopu.aop_reg[offset]->name;
1374                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1375                         return pcop;
1376                 }
1377                 
1378         case AOP_CRY:
1379                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1380                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1381                 //if(PCOR(pcop)->r == NULL)
1382                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1383                 return pcop;
1384                 
1385         case AOP_LIT:
1386                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1387                 
1388         case AOP_STR:
1389                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1390                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1391                 /*
1392                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1393                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1394                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1395                 pcop->type = PCOR(pcop)->r->pc_type;
1396                 pcop->name = PCOR(pcop)->r->name;
1397                 
1398                   return pcop;
1399                 */
1400                 
1401         case AOP_PCODE:
1402                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1403                         __LINE__, 
1404                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1405                 pcop = pCodeOpCopy(aop->aopu.pcop);
1406                 PCOI(pcop)->offset = offset;
1407                 return pcop;
1408         }
1409         
1410         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1411                 "popGet got unsupported aop->type");
1412         exit(0);
1413 }
1414 /*-----------------------------------------------------------------*/
1415 /* aopPut - puts a string for a aop                                                        */
1416 /*-----------------------------------------------------------------*/
1417 void aopPut (asmop *aop, char *s, int offset)
1418 {
1419         char *d = buffer ;
1420         symbol *lbl ;
1421         
1422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1423         
1424         if (aop->size && offset > ( aop->size - 1)) {
1425                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1426                         "aopPut got offset > aop->size");
1427                 exit(0);
1428         }
1429         
1430         /* will assign value to value */
1431         /* depending on where it is ofcourse */
1432         switch (aop->type) {
1433         case AOP_DIR:
1434                 if (offset) {
1435                         sprintf(d,"(%s + %d)",
1436                                 aop->aopu.aop_dir,offset);
1437                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1438                         
1439                 } else
1440                         sprintf(d,"%s",aop->aopu.aop_dir);
1441                 
1442                 if (strcmp(d,s)) {
1443                         DEBUGpic14_emitcode(";","%d",__LINE__);
1444                         if(strcmp(s,"W"))
1445                                 pic14_emitcode("movf","%s,w",s);
1446                         pic14_emitcode("movwf","%s",d);
1447                         
1448                         if(strcmp(s,"W")) {
1449                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1450                                 if(offset >= aop->size) {
1451                                         emitpcode(POC_CLRF,popGet(aop,offset));
1452                                         break;
1453                                 } else
1454                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1455                         }
1456                         
1457                         emitpcode(POC_MOVWF,popGet(aop,offset));
1458                         
1459                         
1460                 }
1461                 break;
1462                 
1463         case AOP_REG:
1464                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1465                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1466                         /*
1467                         if (*s == '@'             ||
1468                         strcmp(s,"r0") == 0 ||
1469                         strcmp(s,"r1") == 0 ||
1470                         strcmp(s,"r2") == 0 ||
1471                         strcmp(s,"r3") == 0 ||
1472                         strcmp(s,"r4") == 0 ||
1473                         strcmp(s,"r5") == 0 ||
1474                         strcmp(s,"r6") == 0 || 
1475                         strcmp(s,"r7") == 0 )
1476                         pic14_emitcode("mov","%s,%s  ; %d",
1477                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1478                         else
1479                         */
1480                         
1481                         if(strcmp(s,"W")==0 )
1482                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1483                         
1484                         pic14_emitcode("movwf","%s",
1485                                 aop->aopu.aop_reg[offset]->name);
1486                         
1487                         if(strcmp(s,zero)==0) {
1488                                 emitpcode(POC_CLRF,popGet(aop,offset));
1489                                 
1490                         } else if(strcmp(s,"W")==0) {
1491                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1492                                 pcop->type = PO_GPR_REGISTER;
1493                                 
1494                                 PCOR(pcop)->rIdx = -1;
1495                                 PCOR(pcop)->r = NULL;
1496                                 
1497                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1498                                 pcop->name = Safe_strdup(s);
1499                                 emitpcode(POC_MOVFW,pcop);
1500                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1501                         } else if(strcmp(s,one)==0) {
1502                                 emitpcode(POC_CLRF,popGet(aop,offset));
1503                                 emitpcode(POC_INCF,popGet(aop,offset));
1504                         } else {
1505                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1506                         }
1507                 }
1508                 break;
1509                 
1510         case AOP_DPTR:
1511         case AOP_DPTR2:
1512                 
1513                 if (aop->type == AOP_DPTR2)
1514                 {
1515                         genSetDPTR(1);
1516                 }
1517                 
1518                 if (aop->code) {
1519                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1520                                 "aopPut writting to code space");
1521                         exit(0);
1522                 }
1523                 
1524                 while (offset > aop->coff) {
1525                         aop->coff++;
1526                         pic14_emitcode ("inc","dptr");
1527                 }
1528                 
1529                 while (offset < aop->coff) {
1530                         aop->coff-- ;
1531                         pic14_emitcode("lcall","__decdptr");
1532                 }
1533                 
1534                 aop->coff = offset;
1535                 
1536                 /* if not in accumulater */
1537                 MOVA(s);
1538                 
1539                 pic14_emitcode ("movx","@dptr,a");
1540                 
1541                 if (aop->type == AOP_DPTR2)
1542                 {
1543                         genSetDPTR(0);
1544                 }
1545                 break;
1546                 
1547         case AOP_R0:
1548         case AOP_R1:
1549                 while (offset > aop->coff) {
1550                         aop->coff++;
1551                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1552                 }
1553                 while (offset < aop->coff) {
1554                         aop->coff-- ;
1555                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1556                 }
1557                 aop->coff = offset;
1558                 
1559                 if (aop->paged) {
1560                         MOVA(s);                         
1561                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1562                         
1563                 } else
1564                         if (*s == '@') {
1565                                 MOVA(s);
1566                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1567                         } else
1568                                 if (strcmp(s,"r0") == 0 ||
1569                                         strcmp(s,"r1") == 0 ||
1570                                         strcmp(s,"r2") == 0 ||
1571                                         strcmp(s,"r3") == 0 ||
1572                                         strcmp(s,"r4") == 0 ||
1573                                         strcmp(s,"r5") == 0 ||
1574                                         strcmp(s,"r6") == 0 || 
1575                                         strcmp(s,"r7") == 0 ) {
1576                                         char buffer[10];
1577                                         sprintf(buffer,"a%s",s);
1578                                         pic14_emitcode("mov","@%s,%s",
1579                                                 aop->aopu.aop_ptr->name,buffer);
1580                                 } else
1581                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1582                                 
1583                                 break;
1584                                 
1585         case AOP_STK:
1586                 if (strcmp(s,"a") == 0)
1587                         pic14_emitcode("push","acc");
1588                 else
1589                         pic14_emitcode("push","%s",s);
1590                 
1591                 break;
1592                 
1593         case AOP_CRY:
1594                 /* if bit variable */
1595                 if (!aop->aopu.aop_dir) {
1596                         pic14_emitcode("clr","a");
1597                         pic14_emitcode("rlc","a");
1598                 } else {
1599                         if (s == zero) 
1600                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1601                         else
1602                                 if (s == one)
1603                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1604                                 else
1605                                         if (!strcmp(s,"c"))
1606                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1607                                         else {
1608                                                 lbl = newiTempLabel(NULL);
1609                                                 
1610                                                 if (strcmp(s,"a")) {
1611                                                         MOVA(s);
1612                                                 }
1613                                                 pic14_emitcode("clr","c");
1614                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1615                                                 pic14_emitcode("cpl","c");
1616                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1617                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1618                                         }
1619                 }
1620                 break;
1621                 
1622         case AOP_STR:
1623                 aop->coff = offset;
1624                 if (strcmp(aop->aopu.aop_str[offset],s))
1625                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1626                 break;
1627                 
1628         case AOP_ACC:
1629                 aop->coff = offset;
1630                 if (!offset && (strcmp(s,"acc") == 0))
1631                         break;
1632                 
1633                 if (strcmp(aop->aopu.aop_str[offset],s))
1634                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1635                 break;
1636                 
1637         default :
1638                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1639                         "aopPut got unsupported aop->type");
1640                 exit(0);
1641         }
1642         
1643 }
1644
1645 /*-----------------------------------------------------------------*/
1646 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1647 /*-----------------------------------------------------------------*/
1648 void mov2w (asmop *aop, int offset)
1649 {
1650         
1651         if(!aop)
1652                 return;
1653         
1654         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1655         
1656         if ( aop->type == AOP_PCODE ||
1657                 aop->type == AOP_LIT ||
1658                 aop->type == AOP_IMMD )
1659                 emitpcode(POC_MOVLW,popGet(aop,offset));
1660         else
1661                 emitpcode(POC_MOVFW,popGet(aop,offset));
1662         
1663 }
1664
1665 /*-----------------------------------------------------------------*/
1666 /* reAdjustPreg - points a register back to where it should        */
1667 /*-----------------------------------------------------------------*/
1668 static void reAdjustPreg (asmop *aop)
1669 {
1670         int size ;
1671         
1672         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1673         aop->coff = 0;
1674         if ((size = aop->size) <= 1)
1675                 return ;
1676         size-- ;
1677         switch (aop->type) {
1678         case AOP_R0 :
1679         case AOP_R1 :
1680                 while (size--)
1681                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1682                 break;                  
1683         case AOP_DPTR :
1684         case AOP_DPTR2:
1685                 if (aop->type == AOP_DPTR2)
1686                 {
1687                         genSetDPTR(1);
1688                 } 
1689                 while (size--)
1690                 {
1691                         pic14_emitcode("lcall","__decdptr");
1692                 }
1693                 
1694                 if (aop->type == AOP_DPTR2)
1695                 {
1696                         genSetDPTR(0);
1697                 }
1698                 break;
1699                 
1700         }
1701         
1702 }
1703
1704
1705 #if 0
1706 /*-----------------------------------------------------------------*/
1707 /* opIsGptr: returns non-zero if the passed operand is             */
1708 /* a generic pointer type.                                         */
1709 /*-----------------------------------------------------------------*/ 
1710 static int opIsGptr(operand *op)
1711 {
1712         sym_link *type = operandType(op);
1713         
1714         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1715         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1716         {
1717                 return 1;
1718         }
1719         return 0;          
1720 }
1721 #endif
1722
1723 /*-----------------------------------------------------------------*/
1724 /* pic14_getDataSize - get the operand data size                   */
1725 /*-----------------------------------------------------------------*/
1726 int pic14_getDataSize(operand *op)
1727 {
1728         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1729         
1730         
1731         return AOP_SIZE(op);
1732         
1733         // tsd- in the pic port, the genptr size is 1, so this code here
1734         // fails. ( in the 8051 port, the size was 4).
1735 #if 0
1736         int size;
1737         size = AOP_SIZE(op);
1738         if (size == GPTRSIZE)
1739         {
1740                 sym_link *type = operandType(op);
1741                 if (IS_GENPTR(type))
1742                 {
1743                         /* generic pointer; arithmetic operations
1744                         * should ignore the high byte (pointer type).
1745                         */
1746                         size--;
1747                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1748                 }
1749         }
1750         return size;
1751 #endif
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* pic14_outAcc - output Acc                                       */
1756 /*-----------------------------------------------------------------*/
1757 void pic14_outAcc(operand *result)
1758 {
1759         int size,offset;
1760         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1761         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1762         
1763         
1764         size = pic14_getDataSize(result);
1765         if(size){
1766                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1767                 size--;
1768                 offset = 1;
1769                 /* unsigned or positive */
1770                 while(size--)
1771                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1772         }
1773         
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* pic14_outBitC - output a bit C                                  */
1778 /*-----------------------------------------------------------------*/
1779 void pic14_outBitC(operand *result)
1780 {
1781         
1782         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1783         /* if the result is bit */
1784         if (AOP_TYPE(result) == AOP_CRY) 
1785                 aopPut(AOP(result),"c",0);
1786         else {
1787                 pic14_emitcode("clr","a  ; %d", __LINE__);
1788                 pic14_emitcode("rlc","a");
1789                 pic14_outAcc(result);
1790         }
1791 }
1792
1793 /*-----------------------------------------------------------------*/
1794 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1795 /*-----------------------------------------------------------------*/
1796 void pic14_toBoolean(operand *oper)
1797 {
1798         int size = AOP_SIZE(oper) - 1;
1799         int offset = 1;
1800         
1801         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1802         
1803         if ( AOP_TYPE(oper) != AOP_ACC) {
1804                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1805         }
1806         while (size--) {
1807                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1808         }
1809 }
1810
1811
1812 /*-----------------------------------------------------------------*/
1813 /* genNot - generate code for ! operation                          */
1814 /*-----------------------------------------------------------------*/
1815 static void genNot (iCode *ic)
1816 {
1817         symbol *tlbl;
1818         int size;
1819         
1820         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1821         /* assign asmOps to operand & result */
1822         aopOp (IC_LEFT(ic),ic,FALSE);
1823         aopOp (IC_RESULT(ic),ic,TRUE);
1824         
1825         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1826         /* if in bit space then a special case */
1827         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1828                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1829                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1830                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1831                 } else {
1832                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1833                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1834                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1835                 }
1836                 goto release;
1837         }
1838         
1839         size = AOP_SIZE(IC_LEFT(ic));
1840         if(size == 1) {
1841                 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1842                 emitpcode(POC_ANDLW,popGetLit(1));
1843                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1844                 goto release;
1845         }
1846         pic14_toBoolean(IC_LEFT(ic));
1847         
1848         tlbl = newiTempLabel(NULL);
1849         pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1850         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1851         pic14_outBitC(IC_RESULT(ic));
1852         
1853 release:        
1854         /* release the aops */
1855         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1856         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1857 }
1858
1859
1860 /*-----------------------------------------------------------------*/
1861 /* genCpl - generate code for complement                                                   */
1862 /*-----------------------------------------------------------------*/
1863 static void genCpl (iCode *ic)
1864 {
1865         operand *left, *result;
1866         int size, offset=0;  
1867         
1868         
1869         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1870         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1871         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1872         
1873         /* if both are in bit space then 
1874         a special case */
1875         if (AOP_TYPE(result) == AOP_CRY &&
1876                 AOP_TYPE(left) == AOP_CRY ) { 
1877                 
1878                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1879                 pic14_emitcode("cpl","c"); 
1880                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1881                 goto release; 
1882         } 
1883         
1884         size = AOP_SIZE(result);
1885         while (size--) {
1886                 
1887                 if(AOP_TYPE(left) == AOP_ACC) 
1888                         emitpcode(POC_XORLW, popGetLit(0xff));
1889                 else
1890                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1891                 
1892                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1893                 offset++;
1894         }
1895         
1896         
1897 release:
1898         /* release the aops */
1899         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1900         freeAsmop(result,NULL,ic,TRUE);
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* genUminusFloat - unary minus for floating points                        */
1905 /*-----------------------------------------------------------------*/
1906 static void genUminusFloat(operand *op,operand *result)
1907 {
1908         int size ,offset =0 ;
1909         char *l;
1910         
1911         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1912         /* for this we just need to flip the 
1913         first it then copy the rest in place */
1914         size = AOP_SIZE(op) - 1;
1915         l = aopGet(AOP(op),3,FALSE,FALSE);
1916         
1917         MOVA(l);          
1918         
1919         pic14_emitcode("cpl","acc.7");
1920         aopPut(AOP(result),"a",3);      
1921         
1922         while(size--) {
1923                 aopPut(AOP(result),
1924                         aopGet(AOP(op),offset,FALSE,FALSE),
1925                         offset);
1926                 offset++;
1927         }                
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* genUminus - unary minus code generation                                                 */
1932 /*-----------------------------------------------------------------*/
1933 static void genUminus (iCode *ic)
1934 {
1935         int size, i;
1936         sym_link *optype, *rtype;
1937         
1938         
1939         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1940         /* assign asmops */
1941         aopOp(IC_LEFT(ic),ic,FALSE);
1942         aopOp(IC_RESULT(ic),ic,TRUE);
1943         
1944         /* if both in bit space then special
1945         case */
1946         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1947                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1948                 
1949                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
1950                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1951                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
1952                 
1953                 goto release; 
1954         } 
1955         
1956         optype = operandType(IC_LEFT(ic));
1957         rtype = operandType(IC_RESULT(ic));
1958         
1959         /* if float then do float stuff */
1960         if (IS_FLOAT(optype)) {
1961                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1962                 goto release;
1963         }
1964         
1965         /* otherwise subtract from zero by taking the 2's complement */
1966         size = AOP_SIZE(IC_LEFT(ic));
1967         
1968         for(i=0; i<size; i++) {
1969                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1970                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1971                 else {
1972                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1973                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1974                 }
1975         }
1976         
1977         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1978         for(i=1; i<size; i++) {
1979                 emitSKPNZ;
1980                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1981         }
1982         
1983 release:
1984         /* release the aops */
1985         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1986         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
1987 }
1988
1989 /*-----------------------------------------------------------------*/
1990 /* saveRegisters - will look for a call and save the registers     */
1991 /*-----------------------------------------------------------------*/
1992 static void saveRegisters(iCode *lic) 
1993 {
1994         int i;
1995         iCode *ic;
1996         bitVect *rsave;
1997         sym_link *dtype;
1998         
1999         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2000         /* look for call */
2001         for (ic = lic ; ic ; ic = ic->next) 
2002                 if (ic->op == CALL || ic->op == PCALL)
2003                         break;
2004                 
2005                 if (!ic) {
2006                         fprintf(stderr,"found parameter push with no function call\n");
2007                         return ;
2008                 }
2009                 
2010                 /* if the registers have been saved already then
2011                 do nothing */
2012                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2013                         return ;
2014                 
2015                         /* find the registers in use at this time 
2016                 and push them away to safety */
2017                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2018                         ic->rUsed);
2019                 
2020                 ic->regsSaved = 1;
2021                 if (options.useXstack) {
2022                         if (bitVectBitValue(rsave,R0_IDX))
2023                                 pic14_emitcode("mov","b,r0");
2024                         pic14_emitcode("mov","r0,%s",spname);
2025                         for (i = 0 ; i < pic14_nRegs ; i++) {
2026                                 if (bitVectBitValue(rsave,i)) {
2027                                         if (i == R0_IDX)
2028                                                 pic14_emitcode("mov","a,b");
2029                                         else
2030                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2031                                         pic14_emitcode("movx","@r0,a");
2032                                         pic14_emitcode("inc","r0");
2033                                 }
2034                         }
2035                         pic14_emitcode("mov","%s,r0",spname);
2036                         if (bitVectBitValue(rsave,R0_IDX))
2037                                 pic14_emitcode("mov","r0,b");     
2038                 }// else
2039                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2040                 //        if (bitVectBitValue(rsave,i))
2041                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2042                 //}
2043                 
2044                 dtype = operandType(IC_LEFT(ic));
2045                 if (currFunc && dtype && 
2046                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2047                         IFFUNC_ISISR(currFunc->type) &&
2048                         !ic->bankSaved) 
2049                         
2050                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2051                 
2052 }
2053 /*-----------------------------------------------------------------*/
2054 /* unsaveRegisters - pop the pushed registers                                      */
2055 /*-----------------------------------------------------------------*/
2056 static void unsaveRegisters (iCode *ic)
2057 {
2058         int i;
2059         bitVect *rsave;
2060         
2061         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2062         /* find the registers in use at this time 
2063         and push them away to safety */
2064         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2065                 ic->rUsed);
2066         
2067         if (options.useXstack) {
2068                 pic14_emitcode("mov","r0,%s",spname); 
2069                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2070                         if (bitVectBitValue(rsave,i)) {
2071                                 pic14_emitcode("dec","r0");
2072                                 pic14_emitcode("movx","a,@r0");
2073                                 if (i == R0_IDX)
2074                                         pic14_emitcode("mov","b,a");
2075                                 else
2076                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2077                         }       
2078                         
2079                 }
2080                 pic14_emitcode("mov","%s,r0",spname);
2081                 if (bitVectBitValue(rsave,R0_IDX))
2082                         pic14_emitcode("mov","r0,b");
2083         } //else
2084         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2085         //      if (bitVectBitValue(rsave,i))
2086         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2087         //}
2088         
2089 }  
2090
2091
2092 /*-----------------------------------------------------------------*/
2093 /* pushSide -                            */
2094 /*-----------------------------------------------------------------*/
2095 static void pushSide(operand * oper, int size)
2096 {
2097 #if 0
2098         int offset = 0;
2099         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2100         while (size--) {
2101                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2102                 if (AOP_TYPE(oper) != AOP_REG &&
2103                         AOP_TYPE(oper) != AOP_DIR &&
2104                         strcmp(l,"a") ) {
2105                         pic14_emitcode("mov","a,%s",l);
2106                         pic14_emitcode("push","acc");
2107                 } else
2108                         pic14_emitcode("push","%s",l);
2109         }
2110 #endif
2111 }
2112
2113 /*-----------------------------------------------------------------*/
2114 /* assignResultValue -                           */
2115 /*-----------------------------------------------------------------*/
2116 static void assignResultValue(operand * oper)
2117 {
2118         int size = AOP_SIZE(oper);
2119         
2120         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2121         
2122         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2123         
2124         while (size--) {
2125                 if (GpsuedoStkPtr++)
2126                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2127                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2128         }
2129 }
2130
2131
2132 /*-----------------------------------------------------------------*/
2133 /* genIpush - genrate code for pushing this gets a little complex  */
2134 /*-----------------------------------------------------------------*/
2135 static void genIpush (iCode *ic)
2136 {
2137         
2138         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2139 #if 0
2140         int size, offset = 0 ;
2141         char *l;
2142         
2143         
2144         /* if this is not a parm push : ie. it is spill push 
2145         and spill push is always done on the local stack */
2146         if (!ic->parmPush) {
2147                 
2148                 /* and the item is spilt then do nothing */
2149                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2150                         return ;
2151                 
2152                 aopOp(IC_LEFT(ic),ic,FALSE);
2153                 size = AOP_SIZE(IC_LEFT(ic));
2154                 /* push it on the stack */
2155                 while(size--) {
2156                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2157                         if (*l == '#') {
2158                                 MOVA(l);
2159                                 l = "acc";
2160                         }
2161                         pic14_emitcode("push","%s",l);
2162                 }
2163                 return ;                
2164         }
2165         
2166         /* this is a paramter push: in this case we call
2167         the routine to find the call and save those
2168         registers that need to be saved */   
2169         saveRegisters(ic);
2170         
2171         /* then do the push */
2172         aopOp(IC_LEFT(ic),ic,FALSE);
2173         
2174         
2175         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2176         size = AOP_SIZE(IC_LEFT(ic));
2177         
2178         while (size--) {
2179                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2180                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2181                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2182                         strcmp(l,"a") ) {
2183                         pic14_emitcode("mov","a,%s",l);
2184                         pic14_emitcode("push","acc");
2185                 } else
2186                         pic14_emitcode("push","%s",l);
2187         }         
2188         
2189         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2190 #endif
2191 }
2192
2193 /*-----------------------------------------------------------------*/
2194 /* genIpop - recover the registers: can happen only for spilling   */
2195 /*-----------------------------------------------------------------*/
2196 static void genIpop (iCode *ic)
2197 {
2198         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2199 #if 0
2200         int size,offset ;
2201         
2202         
2203         /* if the temp was not pushed then */
2204         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2205                 return ;
2206         
2207         aopOp(IC_LEFT(ic),ic,FALSE);
2208         size = AOP_SIZE(IC_LEFT(ic));
2209         offset = (size-1);
2210         while (size--) 
2211                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2212                 FALSE,TRUE));
2213         
2214         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2215 #endif
2216 }
2217
2218 /*-----------------------------------------------------------------*/
2219 /* unsaverbank - restores the resgister bank from stack                    */
2220 /*-----------------------------------------------------------------*/
2221 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2222 {
2223         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2224 #if 0
2225         int i;
2226         asmop *aop ;
2227         regs *r = NULL;
2228         
2229         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2230         if (popPsw) {
2231                 if (options.useXstack) {
2232                         aop = newAsmop(0);
2233                         r = getFreePtr(ic,&aop,FALSE);
2234                         
2235                         
2236                         pic14_emitcode("mov","%s,_spx",r->name);
2237                         pic14_emitcode("movx","a,@%s",r->name);
2238                         pic14_emitcode("mov","psw,a");
2239                         pic14_emitcode("dec","%s",r->name);
2240                         
2241                 }else
2242                         pic14_emitcode ("pop","psw");
2243         }
2244         
2245         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2246                 if (options.useXstack) {           
2247                         pic14_emitcode("movx","a,@%s",r->name);
2248                         //pic14_emitcode("mov","(%s+%d),a",
2249                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2250                         pic14_emitcode("dec","%s",r->name);
2251                         
2252                 } else 
2253                         pic14_emitcode("pop",""); //"(%s+%d)",
2254                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2255         }
2256         
2257         if (options.useXstack) {
2258                 
2259                 pic14_emitcode("mov","_spx,%s",r->name);
2260                 freeAsmop(NULL,aop,ic,TRUE);
2261                 
2262         }
2263 #endif 
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* saverbank - saves an entire register bank on the stack                  */
2268 /*-----------------------------------------------------------------*/
2269 static void saverbank (int bank, iCode *ic, bool pushPsw)
2270 {
2271         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2272 #if 0
2273         int i;
2274         asmop *aop ;
2275         regs *r = NULL;
2276         
2277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2278         if (options.useXstack) {
2279                 
2280                 aop = newAsmop(0);
2281                 r = getFreePtr(ic,&aop,FALSE);  
2282                 pic14_emitcode("mov","%s,_spx",r->name);
2283                 
2284         }
2285         
2286         for (i = 0 ; i < pic14_nRegs ;i++) {
2287                 if (options.useXstack) {
2288                         pic14_emitcode("inc","%s",r->name);
2289                         //pic14_emitcode("mov","a,(%s+%d)",
2290                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2291                         pic14_emitcode("movx","@%s,a",r->name);                 
2292                 } else 
2293                         pic14_emitcode("push","");// "(%s+%d)",
2294                 //regspic14[i].base,8*bank+regspic14[i].offset);
2295         }
2296         
2297         if (pushPsw) {
2298                 if (options.useXstack) {
2299                         pic14_emitcode("mov","a,psw");
2300                         pic14_emitcode("movx","@%s,a",r->name); 
2301                         pic14_emitcode("inc","%s",r->name);
2302                         pic14_emitcode("mov","_spx,%s",r->name);                 
2303                         freeAsmop (NULL,aop,ic,TRUE);
2304                         
2305                 } else
2306                         pic14_emitcode("push","psw");
2307                 
2308                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2309         }
2310         ic->bankSaved = 1;
2311 #endif
2312 }
2313
2314 /*-----------------------------------------------------------------*/
2315 /* genCall - generates a call statement                                                    */
2316 /*-----------------------------------------------------------------*/
2317 static void genCall (iCode *ic)
2318 {
2319         sym_link *dtype;         
2320         symbol *sym;
2321         unsigned char *name;
2322         int isExtern;
2323         
2324         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2325         
2326         /* if caller saves & we have not saved then */
2327         if (!ic->regsSaved)
2328                 saveRegisters(ic);
2329         
2330                 /* if we are calling a function that is not using
2331                 the same register bank then we need to save the
2332         destination registers on the stack */
2333         dtype = operandType(IC_LEFT(ic));
2334         if (currFunc && dtype && 
2335                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2336                 IFFUNC_ISISR(currFunc->type) &&
2337                 !ic->bankSaved) 
2338                 
2339                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2340         
2341         /* if send set is not empty the assign */
2342         if (_G.sendSet) {
2343                 iCode *sic;
2344                 /* For the Pic port, there is no data stack.
2345                 * So parameters passed to functions are stored
2346                 * in registers. (The pCode optimizer will get
2347                 * rid of most of these :).
2348                 */
2349                 int psuedoStkPtr=-1;
2350                 int firstTimeThruLoop = 1;
2351                 
2352                 _G.sendSet = reverseSet(_G.sendSet);
2353                 
2354                 /* First figure how many parameters are getting passed */
2355                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2356                 sic = setNextItem(_G.sendSet)) {
2357                         
2358                         aopOp(IC_LEFT(sic),sic,FALSE);
2359                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2360                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2361                 }
2362                 
2363                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2364                 sic = setNextItem(_G.sendSet)) {
2365                         int size, offset = 0;
2366                         
2367                         aopOp(IC_LEFT(sic),sic,FALSE);
2368                         size = AOP_SIZE(IC_LEFT(sic));
2369                         
2370                         while (size--) {
2371                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2372                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2373                                 
2374                                 if(!firstTimeThruLoop) {
2375                                         /* If this is not the first time we've been through the loop
2376                                         * then we need to save the parameter in a temporary
2377                                         * register. The last byte of the last parameter is
2378                                         * passed in W. */
2379                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2380                                         
2381                                 }
2382                                 firstTimeThruLoop=0;
2383                                 
2384                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2385                                 offset++;
2386                         }
2387                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2388                 }
2389                 _G.sendSet = NULL;
2390         }
2391         /* make the call */
2392         sym = OP_SYMBOL(IC_LEFT(ic));
2393         name = sym->rname[0] ? sym->rname : sym->name;
2394         isExtern = IS_EXTERN(sym->etype);
2395         if (isExtern) {
2396                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2397         }
2398         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2399         if (isExtern) {
2400                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2401         }
2402         GpsuedoStkPtr=0;
2403         /* if we need assign a result value */
2404         if ((IS_ITEMP(IC_RESULT(ic)) && 
2405                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2406                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2407                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2408                 
2409                 _G.accInUse++;
2410                 aopOp(IC_RESULT(ic),ic,FALSE);
2411                 _G.accInUse--;
2412                 
2413                 assignResultValue(IC_RESULT(ic));
2414                 
2415                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2416                         AopType(AOP_TYPE(IC_RESULT(ic))));
2417                 
2418                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2419         }
2420         
2421         /* adjust the stack for parameters if 
2422         required */
2423         if (ic->parmBytes) {
2424                 int i;
2425                 if (ic->parmBytes > 3) {
2426                         pic14_emitcode("mov","a,%s",spname);
2427                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2428                         pic14_emitcode("mov","%s,a",spname);
2429                 } else 
2430                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2431                                 pic14_emitcode("dec","%s",spname);
2432                         
2433         }
2434         
2435         /* if register bank was saved then pop them */
2436         if (ic->bankSaved)
2437                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2438         
2439         /* if we hade saved some registers then unsave them */
2440         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2441                 unsaveRegisters (ic);
2442         
2443         
2444 }
2445
2446 /*-----------------------------------------------------------------*/
2447 /* genPcall - generates a call by pointer statement                        */
2448 /*-----------------------------------------------------------------*/
2449 static void genPcall (iCode *ic)
2450 {
2451         sym_link *dtype;
2452         symbol *albl = newiTempLabel(NULL);
2453         symbol *blbl = newiTempLabel(NULL);
2454         PIC_OPCODE poc;
2455         pCodeOp *pcop;
2456         operand *left;
2457         
2458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2459         /* if caller saves & we have not saved then */
2460         if (!ic->regsSaved)
2461                 saveRegisters(ic);
2462         
2463                 /* if we are calling a function that is not using
2464                 the same register bank then we need to save the
2465         destination registers on the stack */
2466         dtype = operandType(IC_LEFT(ic));
2467         if (currFunc && dtype && 
2468                 IFFUNC_ISISR(currFunc->type) &&
2469                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2470                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2471         
2472         left = IC_LEFT(ic);
2473         aopOp(left,ic,FALSE);
2474         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2475         
2476         pushSide(IC_LEFT(ic), FPTRSIZE);
2477         
2478         /* if send set is not empty, assign parameters */
2479         if (_G.sendSet) {
2480                 
2481                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2482                 /* no way to pass args - W always gets used to make the call */
2483         }
2484         /* first idea - factor out a common helper function and call it.
2485         But don't know how to get it generated only once in its own block
2486         
2487         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2488                 char *rname;
2489                 char *buffer;
2490                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2491                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2492                 buffer = Safe_calloc(1,strlen(rname)+16);
2493                 sprintf(buffer, "%s_goto_helper", rname);
2494                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2495                 free(buffer);
2496         }
2497         */
2498         emitpcode(POC_CALL,popGetLabel(albl->key));
2499         pcop = popGetLabel(blbl->key);
2500         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2501         emitpcode(POC_GOTO,pcop);
2502         emitpLabel(albl->key);
2503         
2504         poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2505         
2506         emitpcode(poc,popGet(AOP(left),1));
2507         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2508         emitpcode(poc,popGet(AOP(left),0));
2509         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2510         
2511         emitpLabel(blbl->key);
2512         
2513         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2514         
2515         /* if we need to assign a result value */
2516         if ((IS_ITEMP(IC_RESULT(ic)) &&
2517                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2518                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2519                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2520                 
2521                 _G.accInUse++;
2522                 aopOp(IC_RESULT(ic),ic,FALSE);
2523                 _G.accInUse--;
2524                 
2525                 assignResultValue(IC_RESULT(ic));
2526                 
2527                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2528         }
2529         
2530         /* if register bank was saved then unsave them */
2531         if (currFunc && dtype && 
2532                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2533                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2534         
2535                 /* if we hade saved some registers then
2536         unsave them */
2537         if (ic->regsSaved)
2538                 unsaveRegisters (ic);
2539         
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* resultRemat - result  is rematerializable                                       */
2544 /*-----------------------------------------------------------------*/
2545 static int resultRemat (iCode *ic)
2546 {
2547         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548         if (SKIP_IC(ic) || ic->op == IFX)
2549                 return 0;
2550         
2551         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2552                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2553                 if (sym->remat && !POINTER_SET(ic)) 
2554                         return 1;
2555         }
2556         
2557         return 0;
2558 }
2559
2560 #if defined(__BORLANDC__) || defined(_MSC_VER)
2561 #define STRCASECMP stricmp
2562 #else
2563 #define STRCASECMP strcasecmp
2564 #endif
2565
2566 #if 0
2567 /*-----------------------------------------------------------------*/
2568 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2569 /*-----------------------------------------------------------------*/
2570 static bool inExcludeList(char *s)
2571 {
2572         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2573         int i =0;
2574         
2575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2576         if (options.excludeRegs[i] &&
2577                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2578                 return FALSE ;
2579         
2580         for ( i = 0 ; options.excludeRegs[i]; i++) {
2581                 if (options.excludeRegs[i] &&
2582                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2583                         return TRUE;
2584         }
2585         return FALSE ;
2586 }
2587 #endif
2588
2589 /*-----------------------------------------------------------------*/
2590 /* genFunction - generated code for function entry                                 */
2591 /*-----------------------------------------------------------------*/
2592 static void genFunction (iCode *ic)
2593 {
2594         symbol *sym;
2595         sym_link *ftype;
2596         
2597         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2598         
2599         labelOffset += (max_key+4);
2600         max_key=0;
2601         GpsuedoStkPtr=0;
2602         _G.nRegsSaved = 0;
2603         /* create the function header */
2604         pic14_emitcode(";","-----------------------------------------");
2605         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2606         pic14_emitcode(";","-----------------------------------------");
2607         
2608         pic14_emitcode("","%s:",sym->rname);
2609         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2610         
2611         ftype = operandType(IC_LEFT(ic));
2612         
2613         /* if critical function then turn interrupts off */
2614         if (IFFUNC_ISCRITICAL(ftype))
2615                 pic14_emitcode("clr","ea");
2616         
2617                 /* here we need to generate the equates for the
2618         register bank if required */
2619 #if 0
2620         if (FUNC_REGBANK(ftype) != rbank) {
2621                 int i ;
2622                 
2623                 rbank = FUNC_REGBANK(ftype);
2624                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2625                         if (strcmp(regspic14[i].base,"0") == 0)
2626                                 pic14_emitcode("","%s = 0x%02x",
2627                                 regspic14[i].dname,
2628                                 8*rbank+regspic14[i].offset);
2629                         else
2630                                 pic14_emitcode ("","%s = %s + 0x%02x",
2631                                 regspic14[i].dname,
2632                                 regspic14[i].base,
2633                                 8*rbank+regspic14[i].offset);
2634                 }
2635         }
2636 #endif
2637         
2638         /* if this is an interrupt service routine */
2639         if (IFFUNC_ISISR(sym->type)) {
2640         /*  already done in pic14createInterruptVect() - delete me
2641         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2642         emitpcodeNULLop(POC_NOP);
2643         emitpcodeNULLop(POC_NOP);
2644         emitpcodeNULLop(POC_NOP);
2645                 */
2646                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2647                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2648                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2649                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2650                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2651                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2652                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2653                 
2654                 pBlockConvert2ISR(pb);
2655 #if 0  
2656                 if (!inExcludeList("acc"))              
2657                         pic14_emitcode ("push","acc");  
2658                 if (!inExcludeList("b"))
2659                         pic14_emitcode ("push","b");
2660                 if (!inExcludeList("dpl"))
2661                         pic14_emitcode ("push","dpl");
2662                 if (!inExcludeList("dph"))
2663                         pic14_emitcode ("push","dph");
2664                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2665                 {
2666                         pic14_emitcode ("push", "dpx");
2667                         /* Make sure we're using standard DPTR */
2668                         pic14_emitcode ("push", "dps");
2669                         pic14_emitcode ("mov", "dps, #0x00");
2670                         if (options.stack10bit)
2671                         { 
2672                                 /* This ISR could conceivably use DPTR2. Better save it. */
2673                                 pic14_emitcode ("push", "dpl1");
2674                                 pic14_emitcode ("push", "dph1");
2675                                 pic14_emitcode ("push", "dpx1");
2676                         }
2677                 }
2678                 /* if this isr has no bank i.e. is going to
2679                 run with bank 0 , then we need to save more
2680                 registers :-) */
2681                 if (!FUNC_REGBANK(sym->type)) {
2682                         
2683                 /* if this function does not call any other
2684                 function then we can be economical and
2685                         save only those registers that are used */
2686                         if (! IFFUNC_HASFCALL(sym->type)) {
2687                                 int i;
2688                                 
2689                                 /* if any registers used */
2690                                 if (sym->regsUsed) {
2691                                         /* save the registers used */
2692                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2693                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2694                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2695                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2696                                         }
2697                                 }
2698                                 
2699                         } else {
2700                         /* this function has    a function call cannot
2701                         determines register usage so we will have the
2702                                 entire bank */
2703                                 saverbank(0,ic,FALSE);
2704                         }       
2705                 }
2706 #endif
2707         } else {
2708         /* if callee-save to be used for this function
2709                 then save the registers being used in this function */
2710                 if (IFFUNC_CALLEESAVES(sym->type)) {
2711                         int i;
2712                         
2713                         /* if any registers used */
2714                         if (sym->regsUsed) {
2715                                 /* save the registers used */
2716                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2717                                         if (bitVectBitValue(sym->regsUsed,i) ||
2718                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2719                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2720                                                 _G.nRegsSaved++;
2721                                         }
2722                                 }
2723                         }
2724                 }
2725         }
2726         
2727         /* set the register bank to the desired value */
2728         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2729                 pic14_emitcode("push","psw");
2730                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2731         }
2732         
2733         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2734                 
2735                 if (options.useXstack) {
2736                         pic14_emitcode("mov","r0,%s",spname);
2737                         pic14_emitcode("mov","a,_bp");
2738                         pic14_emitcode("movx","@r0,a");
2739                         pic14_emitcode("inc","%s",spname);
2740                 }
2741                 else
2742                 {
2743                         /* set up the stack */
2744                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2745                 }
2746                 pic14_emitcode ("mov","_bp,%s",spname);
2747         }
2748         
2749         /* adjust the stack for the function */
2750         if (sym->stack) {
2751                 
2752                 int i = sym->stack;
2753                 if (i > 256 ) 
2754                         werror(W_STACK_OVERFLOW,sym->name);
2755                 
2756                 if (i > 3 && sym->recvSize < 4) {                
2757                         
2758                         pic14_emitcode ("mov","a,sp");
2759                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2760                         pic14_emitcode ("mov","sp,a");
2761                         
2762                 }
2763                 else
2764                         while(i--)
2765                                 pic14_emitcode("inc","sp");
2766         }
2767         
2768         if (sym->xstack) {
2769                 
2770                 pic14_emitcode ("mov","a,_spx");
2771                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2772                 pic14_emitcode ("mov","_spx,a");
2773         }
2774         
2775 }
2776
2777 /*-----------------------------------------------------------------*/
2778 /* genEndFunction - generates epilogue for functions                       */
2779 /*-----------------------------------------------------------------*/
2780 static void genEndFunction (iCode *ic)
2781 {
2782         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2783         
2784         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2785         
2786         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2787         {
2788                 pic14_emitcode ("mov","%s,_bp",spname);
2789         }
2790         
2791         /* if use external stack but some variables were
2792         added to the local stack then decrement the
2793         local stack */
2794         if (options.useXstack && sym->stack) {    
2795                 pic14_emitcode("mov","a,sp");
2796                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2797                 pic14_emitcode("mov","sp,a");
2798         }
2799         
2800         
2801         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2802                 if (options.useXstack) {
2803                         pic14_emitcode("mov","r0,%s",spname);
2804                         pic14_emitcode("movx","a,@r0");
2805                         pic14_emitcode("mov","_bp,a");
2806                         pic14_emitcode("dec","%s",spname);
2807                 }
2808                 else
2809                 {
2810                         pic14_emitcode ("pop","_bp");
2811                 }
2812         }
2813         
2814         /* restore the register bank    */        
2815         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2816                 pic14_emitcode ("pop","psw");
2817         
2818         if (IFFUNC_ISISR(sym->type)) {
2819                 
2820                 /* now we need to restore the registers */
2821                 /* if this isr has no bank i.e. is going to
2822                 run with bank 0 , then we need to save more
2823 registers :-) */
2824                 if (!FUNC_REGBANK(sym->type)) {
2825                         
2826                 /* if this function does not call any other
2827                 function then we can be economical and
2828                         save only those registers that are used */
2829                         if (! IFFUNC_HASFCALL(sym->type)) {
2830                                 int i;
2831                                 
2832                                 /* if any registers used */
2833                                 if (sym->regsUsed) {
2834                                         /* save the registers used */
2835                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2836                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2837                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2838                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2839                                         }
2840                                 }
2841                                 
2842                         } else {
2843                         /* this function has    a function call cannot
2844                         determines register usage so we will have the
2845                                 entire bank */
2846                                 unsaverbank(0,ic,FALSE);
2847                         }       
2848                 }
2849 #if 0
2850                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2851                 {
2852                         if (options.stack10bit)
2853                         {
2854                                 pic14_emitcode ("pop", "dpx1");
2855                                 pic14_emitcode ("pop", "dph1");
2856                                 pic14_emitcode ("pop", "dpl1");
2857                         } 
2858                         pic14_emitcode ("pop", "dps");
2859                         pic14_emitcode ("pop", "dpx");
2860                 }
2861                 if (!inExcludeList("dph"))
2862                         pic14_emitcode ("pop","dph");
2863                 if (!inExcludeList("dpl"))
2864                         pic14_emitcode ("pop","dpl");
2865                 if (!inExcludeList("b"))
2866                         pic14_emitcode ("pop","b");
2867                 if (!inExcludeList("acc"))
2868                         pic14_emitcode ("pop","acc");
2869                 
2870                 if (IFFUNC_ISCRITICAL(sym->type))
2871                         pic14_emitcode("setb","ea");
2872 #endif
2873                 
2874                 /* if debug then send end of function */
2875                 /*      if (options.debug && currFunc) { */
2876                 if (currFunc) {
2877                         debugFile->writeEndFunction (currFunc, ic, 1);
2878                 }
2879                 
2880                 pic14_emitcode ("reti","");
2881                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2882                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2883                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2884                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2885                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2886                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2887                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2888                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2889                 emitpcodeNULLop(POC_RETFIE);
2890         }
2891         else {
2892                 if (IFFUNC_ISCRITICAL(sym->type))
2893                         pic14_emitcode("setb","ea");
2894                 
2895                 if (IFFUNC_CALLEESAVES(sym->type)) {
2896                         int i;
2897                         
2898                         /* if any registers used */
2899                         if (sym->regsUsed) {
2900                                 /* save the registers used */
2901                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2902                                         if (bitVectBitValue(sym->regsUsed,i) ||
2903                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2904                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2905                                 }
2906                         }
2907                         
2908                 }
2909                 
2910                 /* if debug then send end of function */
2911                 if (currFunc) {
2912                         debugFile->writeEndFunction (currFunc, ic, 1);
2913                 }
2914                 
2915                 pic14_emitcode ("return","");
2916                 emitpcodeNULLop(POC_RETURN);
2917                 
2918                 /* Mark the end of a function */
2919                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2920         }
2921         
2922 }
2923
2924 /*-----------------------------------------------------------------*/
2925 /* genRet - generate code for return statement                                     */
2926 /*-----------------------------------------------------------------*/
2927 static void genRet (iCode *ic)
2928 {
2929         int size,offset = 0 , pushed = 0;
2930         
2931         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2932         /* if we have no return value then
2933         just generate the "ret" */
2934         if (!IC_LEFT(ic)) 
2935                 goto jumpret;           
2936         
2937                 /* we have something to return then
2938         move the return value into place */
2939         aopOp(IC_LEFT(ic),ic,FALSE);
2940         size = AOP_SIZE(IC_LEFT(ic));
2941         
2942         while (size--) {
2943                 char *l ;
2944                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2945                         /* #NOCHANGE */
2946                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
2947                                 FALSE,TRUE);
2948                         pic14_emitcode("push","%s",l);
2949                         pushed++;
2950                 } else {
2951                         l = aopGet(AOP(IC_LEFT(ic)),offset,
2952                                 FALSE,FALSE);
2953                         if (strcmp(fReturn[offset],l)) {
2954                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2955                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2956                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2957                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2958                                         emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2959                                 }else {
2960                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2961                                 }
2962                                 if(size) {
2963                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2964                                 }
2965                                 offset++;
2966                         }
2967                 }
2968         }
2969         
2970         if (pushed) {
2971                 while(pushed) {
2972                         pushed--;
2973                         if (strcmp(fReturn[pushed],"a"))
2974                                 pic14_emitcode("pop",fReturn[pushed]);
2975                         else
2976                                 pic14_emitcode("pop","acc");
2977                 }
2978         }
2979         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2980         
2981 jumpret:
2982         /* generate a jump to the return label
2983         if the next is not the return statement */
2984         if (!(ic->next && ic->next->op == LABEL &&
2985                 IC_LABEL(ic->next) == returnLabel)) {
2986                 
2987                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2988                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2989         }
2990         
2991 }
2992
2993 /*-----------------------------------------------------------------*/
2994 /* genLabel - generates a label                                                                    */
2995 /*-----------------------------------------------------------------*/
2996 static void genLabel (iCode *ic)
2997 {
2998         /* special case never generate */
2999         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3000         if (IC_LABEL(ic) == entryLabel)
3001                 return ;
3002         
3003         emitpLabel(IC_LABEL(ic)->key);
3004         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3005 }
3006
3007 /*-----------------------------------------------------------------*/
3008 /* genGoto - generates a goto                                                                      */
3009 /*-----------------------------------------------------------------*/
3010 //tsd
3011 static void genGoto (iCode *ic)
3012 {
3013         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3014         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3015 }
3016
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genMultbits :- multiplication of bits                                                   */
3020 /*-----------------------------------------------------------------*/
3021 static void genMultbits (operand *left, 
3022                                                  operand *right, 
3023                                                  operand *result)
3024 {
3025         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026         
3027         if(!pic14_sameRegs(AOP(result),AOP(right)))
3028                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3029         
3030         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3031         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3032         emitpcode(POC_BCF,  popGet(AOP(result),0));
3033         
3034 }
3035
3036
3037 /*-----------------------------------------------------------------*/
3038 /* genMultOneByte : 8 bit multiplication & division                        */
3039 /*-----------------------------------------------------------------*/
3040 static void genMultOneByte (operand *left,
3041                                                         operand *right,
3042                                                         operand *result)
3043 {
3044         sym_link *opetype = operandType(result);
3045         
3046         // symbol *lbl ;
3047         int size,offset;
3048         
3049         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3050         DEBUGpic14_AopType(__LINE__,left,right,result);
3051         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3052         
3053         /* (if two literals, the value is computed before) */
3054         /* if one literal, literal on the right */
3055         if (AOP_TYPE(left) == AOP_LIT){
3056                 operand *t = right;
3057                 right = left;
3058                 left = t;
3059         }
3060         
3061         size = AOP_SIZE(result);
3062         if(size == 1) {
3063                 
3064                 if (AOP_TYPE(right) == AOP_LIT){
3065                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3066                                 aopGet(AOP(right),0,FALSE,FALSE), 
3067                                 aopGet(AOP(left),0,FALSE,FALSE), 
3068                                 aopGet(AOP(result),0,FALSE,FALSE));
3069                         pic14_emitcode("call","genMultLit");
3070                 } else {
3071                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3072                                 aopGet(AOP(right),0,FALSE,FALSE), 
3073                                 aopGet(AOP(left),0,FALSE,FALSE), 
3074                                 aopGet(AOP(result),0,FALSE,FALSE));
3075                         pic14_emitcode("call","genMult8X8_8");
3076                         
3077                 }
3078                 genMult8X8_8 (left, right,result);
3079                 
3080                 
3081                 /* signed or unsigned */
3082                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3083                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3084                 //MOVA(l);               
3085                 //pic14_emitcode("mul","ab");
3086                 /* if result size = 1, mul signed = mul unsigned */
3087                 //aopPut(AOP(result),"a",0);
3088                 
3089         } else {        // (size > 1)
3090                 
3091                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3092                         aopGet(AOP(right),0,FALSE,FALSE), 
3093                         aopGet(AOP(left),0,FALSE,FALSE), 
3094                         aopGet(AOP(result),0,FALSE,FALSE));
3095                 
3096                 if (SPEC_USIGN(opetype)){
3097                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3098                         genUMult8X8_16 (left, right, result, NULL);
3099                         
3100                         if (size > 2) {
3101                                 /* for filling the MSBs */
3102                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3103                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3104                         }
3105                 }
3106                 else{
3107                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3108                         
3109                         pic14_emitcode("mov","a,b");
3110                         
3111                         /* adjust the MSB if left or right neg */
3112                         
3113                         /* if one literal */
3114                         if (AOP_TYPE(right) == AOP_LIT){
3115                                 pic14_emitcode("multiply ","right is a lit");
3116                                 /* AND literal negative */
3117                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3118                                         /* adjust MSB (c==0 after mul) */
3119                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3120                                 }
3121                         }
3122                         else{
3123                                 genSMult8X8_16 (left, right, result, NULL);
3124                         }
3125                         
3126                         if(size > 2){
3127                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3128                                 /* get the sign */
3129                                 pic14_emitcode("rlc","a");
3130                                 pic14_emitcode("subb","a,acc");
3131                         }
3132                 }
3133                 
3134                 size -= 2;
3135                 offset = 2;
3136                 if (size > 0)
3137                         while (size--)
3138                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3139                         //aopPut(AOP(result),"a",offset++);
3140         }
3141 }
3142
3143 /*-----------------------------------------------------------------*/
3144 /* genMult - generates code for multiplication                                     */
3145 /*-----------------------------------------------------------------*/
3146 static void genMult (iCode *ic)
3147 {
3148         operand *left = IC_LEFT(ic);
3149         operand *right = IC_RIGHT(ic);
3150         operand *result= IC_RESULT(ic); 
3151         
3152         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3153         /* assign the amsops */
3154         aopOp (left,ic,FALSE);
3155         aopOp (right,ic,FALSE);
3156         aopOp (result,ic,TRUE);
3157         
3158         DEBUGpic14_AopType(__LINE__,left,right,result);
3159         
3160         /* special cases first */
3161         /* both are bits */
3162         if (AOP_TYPE(left) == AOP_CRY &&
3163                 AOP_TYPE(right)== AOP_CRY) {
3164                 genMultbits(left,right,result);
3165                 goto release ;
3166         }
3167         
3168         /* if both are of size == 1 */
3169         if (AOP_SIZE(left) == 1 &&
3170                 AOP_SIZE(right) == 1 ) {
3171                 genMultOneByte(left,right,result);
3172                 goto release ;
3173         }
3174         
3175         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3176         
3177         /* should have been converted to function call */
3178         //assert(0) ;
3179         
3180 release :
3181         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3182         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3183         freeAsmop(result,NULL,ic,TRUE); 
3184 }
3185
3186 /*-----------------------------------------------------------------*/
3187 /* genDivbits :- division of bits                                                                  */
3188 /*-----------------------------------------------------------------*/
3189 static void genDivbits (operand *left, 
3190                                                 operand *right, 
3191                                                 operand *result)
3192 {
3193         
3194         char *l;
3195         
3196         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3197         /* the result must be bit */      
3198         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3199         l = aopGet(AOP(left),0,FALSE,FALSE);
3200         
3201         MOVA(l);          
3202         
3203         pic14_emitcode("div","ab");
3204         pic14_emitcode("rrc","a");
3205         aopPut(AOP(result),"c",0);
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genDivOneByte : 8 bit division                                                                  */
3210 /*-----------------------------------------------------------------*/
3211 static void genDivOneByte (operand *left,
3212                                                    operand *right,
3213                                                    operand *result)
3214 {
3215         sym_link *opetype = operandType(result);
3216         char *l ;
3217         symbol *lbl ;
3218         int size,offset;
3219         
3220         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3221         size = AOP_SIZE(result) - 1;
3222         offset = 1;
3223         /* signed or unsigned */
3224         if (SPEC_USIGN(opetype)) {
3225                 /* unsigned is easy */
3226                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3227                 l = aopGet(AOP(left),0,FALSE,FALSE);
3228                 MOVA(l);                
3229                 pic14_emitcode("div","ab");
3230                 aopPut(AOP(result),"a",0);
3231                 while (size--)
3232                         aopPut(AOP(result),zero,offset++);
3233                 return ;
3234         }
3235         
3236         /* signed is a little bit more difficult */
3237         
3238         /* save the signs of the operands */
3239         l = aopGet(AOP(left),0,FALSE,FALSE);      
3240         MOVA(l);          
3241         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3242         pic14_emitcode("push","acc"); /* save it on the stack */
3243         
3244         /* now sign adjust for both left & right */
3245         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3246         MOVA(l);                 
3247         lbl = newiTempLabel(NULL);
3248         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3249         pic14_emitcode("cpl","a");   
3250         pic14_emitcode("inc","a");
3251         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3252         pic14_emitcode("mov","b,a");
3253         
3254         /* sign adjust left side */
3255         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3256         MOVA(l);
3257         
3258         lbl = newiTempLabel(NULL);
3259         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3260         pic14_emitcode("cpl","a");
3261         pic14_emitcode("inc","a");
3262         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3263         
3264         /* now the division */
3265         pic14_emitcode("div","ab");
3266         /* we are interested in the lower order
3267         only */
3268         pic14_emitcode("mov","b,a");
3269         lbl = newiTempLabel(NULL);
3270         pic14_emitcode("pop","acc");     
3271         /* if there was an over flow we don't 
3272         adjust the sign of the result */
3273         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3274         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3275         CLRC;
3276         pic14_emitcode("clr","a");
3277         pic14_emitcode("subb","a,b");
3278         pic14_emitcode("mov","b,a");
3279         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3280         
3281         /* now we are done */
3282         aopPut(AOP(result),"b",0);
3283         if(size > 0){
3284                 pic14_emitcode("mov","c,b.7");
3285                 pic14_emitcode("subb","a,acc");   
3286         }
3287         while (size--)
3288                 aopPut(AOP(result),"a",offset++);
3289         
3290 }
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genDiv - generates code for division                                                    */
3294 /*-----------------------------------------------------------------*/
3295 static void genDiv (iCode *ic)
3296 {
3297         operand *left = IC_LEFT(ic);
3298         operand *right = IC_RIGHT(ic);
3299         operand *result= IC_RESULT(ic); 
3300         
3301         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3302         /* assign the amsops */
3303         aopOp (left,ic,FALSE);
3304         aopOp (right,ic,FALSE);
3305         aopOp (result,ic,TRUE);
3306         
3307         /* special cases first */
3308         /* both are bits */
3309         if (AOP_TYPE(left) == AOP_CRY &&
3310                 AOP_TYPE(right)== AOP_CRY) {
3311                 genDivbits(left,right,result);
3312                 goto release ;
3313         }
3314         
3315         /* if both are of size == 1 */
3316         if (AOP_SIZE(left) == 1 &&
3317                 AOP_SIZE(right) == 1 ) {
3318                 genDivOneByte(left,right,result);
3319                 goto release ;
3320         }
3321         
3322         /* should have been converted to function call */
3323         assert(0);
3324 release :
3325         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3326         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3327         freeAsmop(result,NULL,ic,TRUE); 
3328 }
3329
3330 /*-----------------------------------------------------------------*/
3331 /* genModbits :- modulus of bits                                                                   */
3332 /*-----------------------------------------------------------------*/
3333 static void genModbits (operand *left, 
3334                                                 operand *right, 
3335                                                 operand *result)
3336 {
3337         
3338         char *l;
3339         
3340         /* the result must be bit */      
3341         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3342         l = aopGet(AOP(left),0,FALSE,FALSE);
3343         
3344         MOVA(l);
3345         
3346         pic14_emitcode("div","ab");
3347         pic14_emitcode("mov","a,b");
3348         pic14_emitcode("rrc","a");
3349         aopPut(AOP(result),"c",0);
3350 }
3351
3352 /*-----------------------------------------------------------------*/
3353 /* genModOneByte : 8 bit modulus                                                                   */
3354 /*-----------------------------------------------------------------*/
3355 static void genModOneByte (operand *left,
3356                                                    operand *right,
3357                                                    operand *result)
3358 {
3359         sym_link *opetype = operandType(result);
3360         char *l ;
3361         symbol *lbl ;
3362         
3363         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3364         /* signed or unsigned */
3365         if (SPEC_USIGN(opetype)) {
3366                 /* unsigned is easy */
3367                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3368                 l = aopGet(AOP(left),0,FALSE,FALSE);
3369                 MOVA(l);        
3370                 pic14_emitcode("div","ab");
3371                 aopPut(AOP(result),"b",0);
3372                 return ;
3373         }
3374         
3375         /* signed is a little bit more difficult */
3376         
3377         /* save the signs of the operands */
3378         l = aopGet(AOP(left),0,FALSE,FALSE);      
3379         MOVA(l);
3380         
3381         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3382         pic14_emitcode("push","acc"); /* save it on the stack */
3383         
3384         /* now sign adjust for both left & right */
3385         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3386         MOVA(l);
3387         
3388         lbl = newiTempLabel(NULL);
3389         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3390         pic14_emitcode("cpl","a");   
3391         pic14_emitcode("inc","a");
3392         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3393         pic14_emitcode("mov","b,a"); 
3394         
3395         /* sign adjust left side */
3396         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3397         MOVA(l);
3398         
3399         lbl = newiTempLabel(NULL);
3400         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3401         pic14_emitcode("cpl","a");   
3402         pic14_emitcode("inc","a");
3403         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3404         
3405         /* now the multiplication */
3406         pic14_emitcode("div","ab");
3407         /* we are interested in the lower order
3408         only */
3409         lbl = newiTempLabel(NULL);
3410         pic14_emitcode("pop","acc");     
3411         /* if there was an over flow we don't 
3412         adjust the sign of the result */
3413         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3414         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3415         CLRC ;
3416         pic14_emitcode("clr","a");
3417         pic14_emitcode("subb","a,b");
3418         pic14_emitcode("mov","b,a");
3419         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3420         
3421         /* now we are done */
3422         aopPut(AOP(result),"b",0);
3423         
3424 }
3425
3426 /*-----------------------------------------------------------------*/
3427 /* genMod - generates code for division                                                    */
3428 /*-----------------------------------------------------------------*/
3429 static void genMod (iCode *ic)
3430 {
3431         operand *left = IC_LEFT(ic);
3432         operand *right = IC_RIGHT(ic);
3433         operand *result= IC_RESULT(ic);  
3434         
3435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3436         /* assign the amsops */
3437         aopOp (left,ic,FALSE);
3438         aopOp (right,ic,FALSE);
3439         aopOp (result,ic,TRUE);
3440         
3441         /* special cases first */
3442         /* both are bits */
3443         if (AOP_TYPE(left) == AOP_CRY &&
3444                 AOP_TYPE(right)== AOP_CRY) {
3445                 genModbits(left,right,result);
3446                 goto release ;
3447         }
3448         
3449         /* if both are of size == 1 */
3450         if (AOP_SIZE(left) == 1 &&
3451                 AOP_SIZE(right) == 1 ) {
3452                 genModOneByte(left,right,result);
3453                 goto release ;
3454         }
3455         
3456         /* should have been converted to function call */
3457         assert(0);
3458         
3459 release :
3460         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3461         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3462         freeAsmop(result,NULL,ic,TRUE); 
3463 }
3464
3465 /*-----------------------------------------------------------------*/
3466 /* genIfxJump :- will create a jump depending on the ifx                   */
3467 /*-----------------------------------------------------------------*/
3468 /*
3469 note: May need to add parameter to indicate when a variable is in bit space.
3470 */
3471 static void genIfxJump (iCode *ic, char *jval)
3472 {
3473         
3474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3475         /* if true label then we jump if condition
3476         supplied is true */
3477         if ( IC_TRUE(ic) ) {
3478                 
3479                 if(strcmp(jval,"a") == 0)
3480                         emitSKPZ;
3481                 else if (strcmp(jval,"c") == 0)
3482                         emitSKPC;
3483                 else {
3484                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3485                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3486                 }
3487                 
3488                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3489                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3490                 
3491         }
3492         else {
3493                 /* false label is present */
3494                 if(strcmp(jval,"a") == 0)
3495                         emitSKPNZ;
3496                 else if (strcmp(jval,"c") == 0)
3497                         emitSKPNC;
3498                 else {
3499                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3500                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3501                 }
3502                 
3503                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3504                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3505                 
3506         }
3507         
3508         
3509         /* mark the icode as generated */
3510         ic->generated = 1;
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* genSkip                                                                                                                 */
3515 /*-----------------------------------------------------------------*/
3516 static void genSkip(iCode *ifx,int status_bit)
3517 {
3518         if(!ifx)
3519                 return;
3520         
3521         if ( IC_TRUE(ifx) ) {
3522                 switch(status_bit) {
3523                 case 'z':
3524                         emitSKPNZ;
3525                         break;
3526                         
3527                 case 'c':
3528                         emitSKPNC;
3529                         break;
3530                         
3531                 case 'd':
3532                         emitSKPDC;
3533                         break;
3534                         
3535                 }
3536                 
3537                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3538                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3539                 
3540         } else {
3541                 
3542                 switch(status_bit) {
3543                         
3544                 case 'z':
3545                         emitSKPZ;
3546                         break;
3547                         
3548                 case 'c':
3549                         emitSKPC;
3550                         break;
3551                         
3552                 case 'd':
3553                         emitSKPDC;
3554                         break;
3555                 }
3556                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3557                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3558                 
3559         }
3560         
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genSkipc                                                                                                        */
3565 /*-----------------------------------------------------------------*/
3566 static void genSkipc(resolvedIfx *rifx)
3567 {
3568         if(!rifx)
3569                 return;
3570         
3571         if(rifx->condition)
3572                 emitSKPC;
3573         else
3574                 emitSKPNC;
3575         
3576         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3577         rifx->generated = 1;
3578 }
3579
3580 /*-----------------------------------------------------------------*/
3581 /* genSkipz2                                                                                                       */
3582 /*-----------------------------------------------------------------*/
3583 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3584 {
3585         if(!rifx)
3586                 return;
3587         
3588         if( (rifx->condition ^ invert_condition) & 1)
3589                 emitSKPZ;
3590         else
3591                 emitSKPNZ;
3592         
3593         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3594         rifx->generated = 1;
3595 }
3596
3597 /*-----------------------------------------------------------------*/
3598 /* genSkipz                                                        */
3599 /*-----------------------------------------------------------------*/
3600 static void genSkipz(iCode *ifx, int condition)
3601 {
3602         if(!ifx)
3603                 return;
3604         
3605         if(condition)
3606                 emitSKPNZ;
3607         else
3608                 emitSKPZ;
3609         
3610         if ( IC_TRUE(ifx) )
3611                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3612         else
3613                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3614         
3615         if ( IC_TRUE(ifx) )
3616                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3617         else
3618                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3619         
3620 }
3621 /*-----------------------------------------------------------------*/
3622 /* genSkipCond                                                     */
3623 /*-----------------------------------------------------------------*/
3624 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3625 {
3626         if(!rifx)
3627                 return;
3628         
3629         if(rifx->condition)
3630                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3631         else
3632                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3633         
3634         
3635         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3636         rifx->generated = 1;
3637 }
3638
3639 #if 0
3640 /*-----------------------------------------------------------------*/
3641 /* genChkZeroes :- greater or less than comparison                 */
3642 /*     For each byte in a literal that is zero, inclusive or the   */
3643 /*     the corresponding byte in the operand with W                */
3644 /*     returns true if any of the bytes are zero                   */
3645 /*-----------------------------------------------------------------*/
3646 static int genChkZeroes(operand *op, int lit,  int size)
3647 {
3648         
3649         int i;
3650         int flag =1;
3651         
3652         while(size--) {
3653                 i = (lit >> (size*8)) & 0xff;
3654                 
3655                 if(i==0) {
3656                         if(flag) 
3657                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3658                         else
3659                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3660                         flag = 0;
3661                 }
3662         }
3663         
3664         return (flag==0);
3665 }
3666 #endif
3667
3668 /*-----------------------------------------------------------------*/
3669 /* genCmp :- greater or less than comparison                       */
3670 /*-----------------------------------------------------------------*/
3671 static void genCmp (operand *left,operand *right,
3672                                         operand *result, iCode *ifx, int sign)
3673 {
3674         int size; //, offset = 0 ;
3675         unsigned long lit = 0L,i = 0;
3676         resolvedIfx rFalseIfx;
3677         //  resolvedIfx rTrueIfx;
3678         symbol *truelbl;
3679         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3680         /*
3681         if(ifx) {
3682         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3683         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3684         }
3685         */
3686         
3687         resolveIfx(&rFalseIfx,ifx);
3688         truelbl  = newiTempLabel(NULL);
3689         size = max(AOP_SIZE(left),AOP_SIZE(right));
3690         
3691         DEBUGpic14_AopType(__LINE__,left,right,result);
3692         
3693 #define _swapp
3694         
3695         /* if literal is on the right then swap with left */
3696         if ((AOP_TYPE(right) == AOP_LIT)) {
3697                 operand *tmp = right ;
3698                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3699                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3700 #ifdef _swapp
3701                 
3702                 lit = (lit - 1) & mask;
3703                 right = left;
3704                 left = tmp;
3705                 rFalseIfx.condition ^= 1;
3706 #endif
3707                 
3708         } else if ((AOP_TYPE(left) == AOP_LIT)) {
3709                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3710         }
3711         
3712         
3713         //if(IC_TRUE(ifx) == NULL)
3714         /* if left & right are bit variables */
3715         if (AOP_TYPE(left) == AOP_CRY &&
3716                 AOP_TYPE(right) == AOP_CRY ) {
3717                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3718                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3719         } else {
3720         /* subtract right from left if at the
3721         end the carry flag is set then we know that
3722                 left is greater than right */
3723                 
3724                 symbol *lbl  = newiTempLabel(NULL);
3725                 
3726 #ifndef _swapp
3727                 if(AOP_TYPE(right) == AOP_LIT) {
3728                         
3729                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3730                         
3731                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3732                         
3733                         /* special cases */
3734                         
3735                         if(lit == 0) {
3736                                 
3737                                 if(sign != 0) 
3738                                         genSkipCond(&rFalseIfx,left,size-1,7);
3739                                 else 
3740                                         /* no need to compare to 0...*/
3741                                         /* NOTE: this is a de-generate compare that most certainly 
3742                                         *       creates some dead code. */
3743                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3744                                 
3745                                 if(ifx) ifx->generated = 1;
3746                                 return;
3747                                 
3748                         }
3749                         size--;
3750                         
3751                         if(size == 0) {
3752                                 //i = (lit >> (size*8)) & 0xff;
3753                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3754                                 
3755                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3756                                 
3757                                 i = ((0-lit) & 0xff);
3758                                 if(sign) {
3759                                         if( i == 0x81) { 
3760                                         /* lit is 0x7f, all signed chars are less than
3761                                                 * this except for 0x7f itself */
3762                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
3763                                                 genSkipz2(&rFalseIfx,0);
3764                                         } else {
3765                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
3766                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3767                                                 genSkipc(&rFalseIfx);
3768                                         }
3769                                         
3770                                 } else {
3771                                         if(lit == 1) {
3772                                                 genSkipz2(&rFalseIfx,1);
3773                                         } else {
3774                                                 emitpcode(POC_ADDLW, popGetLit(i));
3775                                                 genSkipc(&rFalseIfx);
3776                                         }
3777                                 }
3778                                 
3779                                 if(ifx) ifx->generated = 1;
3780                                 return;
3781                         }
3782                         
3783                         /* chars are out of the way. now do ints and longs */
3784                         
3785                         
3786                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3787                         
3788                         /* special cases */
3789                         
3790                         if(sign) {
3791                                 
3792                                 if(lit == 0) {
3793                                         genSkipCond(&rFalseIfx,left,size,7);
3794                                         if(ifx) ifx->generated = 1;
3795                                         return;
3796                                 }
3797                                 
3798                                 if(lit <0x100) {
3799                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3800                                         
3801                                         //rFalseIfx.condition ^= 1;
3802                                         //genSkipCond(&rFalseIfx,left,size,7);
3803                                         //rFalseIfx.condition ^= 1;
3804                                         
3805                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3806                                         if(rFalseIfx.condition)
3807                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3808                                         else
3809                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3810                                         
3811                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3812                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
3813                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
3814                                         
3815                                         while(size > 1)
3816                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3817                                         
3818                                         if(rFalseIfx.condition) {
3819                                                 emitSKPZ;
3820                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3821                                                 
3822                                         } else {
3823                                                 emitSKPNZ;
3824                                         }
3825                                         
3826                                         genSkipc(&rFalseIfx);
3827                                         emitpLabel(truelbl->key);
3828                                         if(ifx) ifx->generated = 1;
3829                                         return;
3830                                         
3831                                 }
3832                                 
3833                                 if(size == 1) {
3834                                         
3835                                         if( (lit & 0xff) == 0) {
3836                                                 /* lower byte is zero */
3837                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3838                                                 i = ((lit >> 8) & 0xff) ^0x80;
3839                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3840                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3841                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3842                                                 genSkipc(&rFalseIfx);
3843                                                 
3844                                                 
3845                                                 if(ifx) ifx->generated = 1;
3846                                                 return;
3847                                                 
3848                                         }
3849                                 } else {
3850                                         /* Special cases for signed longs */
3851                                         if( (lit & 0xffffff) == 0) {
3852                                                 /* lower byte is zero */
3853                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3854                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
3855                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3856                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3857                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3858                                                 genSkipc(&rFalseIfx);
3859                                                 
3860                                                 
3861                                                 if(ifx) ifx->generated = 1;
3862                                                 return;
3863                                                 
3864                                         }
3865                                         
3866                                 }
3867                                 
3868                                 
3869                                 if(lit & (0x80 << (size*8))) {
3870                                         /* lit is negative */
3871                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3872                                         
3873                                         //genSkipCond(&rFalseIfx,left,size,7);
3874                                         
3875                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3876                                         
3877                                         if(rFalseIfx.condition)
3878                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3879                                         else
3880                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3881                                         
3882                                         
3883                                 } else {
3884                                         /* lit is positive */
3885                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3886                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3887                                         if(rFalseIfx.condition)
3888                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3889                                         else
3890                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3891                                         
3892                                 }
3893                                 
3894                                 /* There are no more special cases, so perform a general compare */
3895                                 
3896                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3897                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3898                                 
3899                                 while(size--) {
3900                                         
3901                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3902                                         emitSKPNZ;
3903                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3904                                 }
3905                                 //rFalseIfx.condition ^= 1;
3906                                 genSkipc(&rFalseIfx);
3907                                 
3908                                 emitpLabel(truelbl->key);
3909                                 
3910                                 if(ifx) ifx->generated = 1;
3911                                 return;
3912                                 
3913                                 
3914                         }
3915
3916
3917                         /* sign is out of the way. So now do an unsigned compare */
3918                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3919
3920
3921                         /* General case - compare to an unsigned literal on the right.*/
3922
3923                         i = (lit >> (size*8)) & 0xff;
3924                         emitpcode(POC_MOVLW, popGetLit(i));
3925                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3926                         while(size--) {
3927                                 i = (lit >> (size*8)) & 0xff;
3928                                 
3929                                 if(i) {
3930                                         emitpcode(POC_MOVLW, popGetLit(i));
3931                                         emitSKPNZ;
3932                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3933                                 } else {
3934                                 /* this byte of the lit is zero, 
3935                                         *if it's not the last then OR in the variable */
3936                                         if(size)
3937                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
3938                                 }
3939                         }
3940
3941
3942                 emitpLabel(lbl->key);
3943                 //if(emitFinalCheck)
3944                 genSkipc(&rFalseIfx);
3945                 if(sign)
3946                         emitpLabel(truelbl->key);
3947
3948                 if(ifx) ifx->generated = 1;
3949                 return;
3950
3951
3952                 }
3953 #endif  // _swapp
3954
3955                 if(AOP_TYPE(left) == AOP_LIT) {
3956                         //symbol *lbl = newiTempLabel(NULL);
3957                         
3958                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3959                         
3960                         
3961                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3962                         
3963                         /* Special cases */
3964                         if((lit == 0) && (sign == 0)){
3965                                 
3966                                 size--;
3967                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3968                                 while(size) 
3969                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
3970                                 
3971                                 genSkipz2(&rFalseIfx,0);
3972                                 if(ifx) ifx->generated = 1;
3973                                 return;
3974                         }
3975                         
3976                         if(size==1) {
3977                                 /* Special cases */
3978                                 lit &= 0xff;
3979                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3980                                         /* degenerate compare can never be true */
3981                                         if(rFalseIfx.condition == 0)
3982                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3983                                         
3984                                         if(ifx) ifx->generated = 1;
3985                                         return;
3986                                 }
3987                                 
3988                                 if(sign) {
3989                                         /* signed comparisons to a literal byte */
3990                                         
3991                                         int lp1 = (lit+1) & 0xff;
3992                                         
3993                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3994                                         switch (lp1) {
3995                                         case 0:
3996                                                 rFalseIfx.condition ^= 1;
3997                                                 genSkipCond(&rFalseIfx,right,0,7);
3998                                                 break;
3999                                         case 0x7f:
4000                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4001                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4002                                                 genSkipz2(&rFalseIfx,1);
4003                                                 break;
4004                                         default:
4005                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4006                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4007                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4008                                                 rFalseIfx.condition ^= 1;
4009                                                 genSkipc(&rFalseIfx);
4010                                                 break;
4011                                         }
4012                                         if(ifx) ifx->generated = 1;
4013                                 } else {
4014                                         /* unsigned comparisons to a literal byte */
4015                                         
4016                                         switch(lit & 0xff ) {
4017                                         case 0:
4018                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4019                                                 genSkipz2(&rFalseIfx,0);
4020                                                 if(ifx) ifx->generated = 1;
4021                                                 break;
4022                                         case 0x7f:
4023                                                 genSkipCond(&rFalseIfx,right,0,7);
4024                                                 if(ifx) ifx->generated = 1;
4025                                                 break;
4026                                                 
4027                                         default:
4028                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4029                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4030                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4031                                                 rFalseIfx.condition ^= 1;
4032                                                 if (AOP_TYPE(result) == AOP_CRY) {
4033                                                         genSkipc(&rFalseIfx);
4034                                                         if(ifx) ifx->generated = 1;
4035                                                 } else {
4036                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4037                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4038                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4039                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4040                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4041                                                 }       
4042                                                 break;
4043                                         }
4044                                 }
4045                                 
4046                                 //goto check_carry;
4047                                 return;
4048                                 
4049                         } else {
4050                                 
4051                                 /* Size is greater than 1 */
4052                                 
4053                                 if(sign) {
4054                                         int lp1 = lit+1;
4055                                         
4056                                         size--;
4057                                         
4058                                         if(lp1 == 0) {
4059                                                 /* this means lit = 0xffffffff, or -1 */
4060                                                 
4061                                                 
4062                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4063                                                 rFalseIfx.condition ^= 1;
4064                                                 genSkipCond(&rFalseIfx,right,size,7);
4065                                                 if(ifx) ifx->generated = 1;
4066                                                 return;
4067                                         }
4068                                         
4069                                         if(lit == 0) {
4070                                                 int s = size;
4071                                                 
4072                                                 if(rFalseIfx.condition) {
4073                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4074                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4075                                                 }
4076                                                 
4077                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4078                                                 while(size--)
4079                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4080                                                 
4081                                                 
4082                                                 emitSKPZ;
4083                                                 if(rFalseIfx.condition) {
4084                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4085                                                         emitpLabel(truelbl->key);
4086                                                 }else {
4087                                                         rFalseIfx.condition ^= 1;
4088                                                         genSkipCond(&rFalseIfx,right,s,7);
4089                                                 }
4090                                                 
4091                                                 if(ifx) ifx->generated = 1;
4092                                                 return;
4093                                         }
4094                                         
4095                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4096                                                 /* lower byte of signed word is zero */
4097                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4098                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4099                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4100                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4101                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4102                                                 rFalseIfx.condition ^= 1;
4103                                                 genSkipc(&rFalseIfx);
4104                                                 
4105                                                 
4106                                                 if(ifx) ifx->generated = 1;
4107                                                 return;
4108                                         }
4109                                         
4110                                         if(lit & (0x80 << (size*8))) {
4111                                                 /* Lit is less than zero */
4112                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4113                                                 //rFalseIfx.condition ^= 1;
4114                                                 //genSkipCond(&rFalseIfx,left,size,7);
4115                                                 //rFalseIfx.condition ^= 1;
4116                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4117                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4118                                                 
4119                                                 if(rFalseIfx.condition)
4120                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4121                                                 else
4122                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4123                                                 
4124                                                 
4125                                         } else {
4126                                                 /* Lit is greater than or equal to zero */
4127                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4128                                                 //rFalseIfx.condition ^= 1;
4129                                                 //genSkipCond(&rFalseIfx,right,size,7);
4130                                                 //rFalseIfx.condition ^= 1;
4131                                                 
4132                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4133                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4134                                                 
4135                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4136                                                 if(rFalseIfx.condition)
4137                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4138                                                 else
4139                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4140                                                 
4141                                         }
4142                                         
4143                                         
4144                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4145                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4146                                         
4147                                         while(size--) {
4148                                                 
4149                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4150                                                 emitSKPNZ;
4151                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4152                                         }
4153                                         rFalseIfx.condition ^= 1;
4154                                         //rFalseIfx.condition = 1;
4155                                         genSkipc(&rFalseIfx);
4156                                         
4157                                         emitpLabel(truelbl->key);
4158                                         
4159                                         if(ifx) ifx->generated = 1;
4160                                         return;
4161                                         // end of if (sign)
4162                                 } else {
4163                                         
4164                                         /* compare word or long to an unsigned literal on the right.*/
4165                                         
4166                                         
4167                                         size--;
4168                                         if(lit < 0xff) {
4169                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4170                                                 switch (lit) {
4171                                                 case 0:
4172                                                         break; /* handled above */
4173                                                 /*
4174                                                 case 0xff:
4175                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4176                                                         while(size--)
4177                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4178                                                         genSkipz2(&rFalseIfx,0);
4179                                                         break;
4180                                                 */
4181                                                 default:
4182                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4183                                                         while(--size)
4184                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4185                                                         
4186                                                         emitSKPZ;
4187                                                         if(rFalseIfx.condition)
4188                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4189                                                         else
4190                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4191                                                         
4192                                                         
4193                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4194                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4195                                                         
4196                                                         rFalseIfx.condition ^= 1;
4197                                                         genSkipc(&rFalseIfx);
4198                                                 }
4199                                                 
4200                                                 emitpLabel(truelbl->key);
4201                                                 
4202                                                 if(ifx) ifx->generated = 1;
4203                                                 return;
4204                                         }
4205                                         
4206                                         
4207                                         lit++;
4208                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4209                                         i = (lit >> (size*8)) & 0xff;
4210                                         
4211                                         emitpcode(POC_MOVLW, popGetLit(i));
4212                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4213                                         
4214                                         while(size--) {
4215                                                 i = (lit >> (size*8)) & 0xff;
4216                                                 
4217                                                 if(i) {
4218                                                         emitpcode(POC_MOVLW, popGetLit(i));
4219                                                         emitSKPNZ;
4220                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4221                                                 } else {
4222                                                 /* this byte of the lit is zero, 
4223                                                         *if it's not the last then OR in the variable */
4224                                                         if(size)
4225                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4226                                                 }
4227                                         }
4228                                         
4229                                         
4230                                         emitpLabel(lbl->key);
4231                                         
4232                                         rFalseIfx.condition ^= 1;
4233                                         genSkipc(&rFalseIfx);
4234                                 }
4235                                 
4236                                 if(sign)
4237                                         emitpLabel(truelbl->key);
4238                                 if(ifx) ifx->generated = 1;
4239                                 return;
4240                         }
4241                 }
4242                 /* Compare two variables */
4243                 
4244                 DEBUGpic14_emitcode(";sign","%d",sign);
4245                 
4246                 size--;
4247                 if(sign) {
4248                         /* Sigh. thus sucks... */
4249                         if(size) {
4250                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4251                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4252                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4253                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4254                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4255                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4256                         } else {
4257                                 /* Signed char comparison */
4258                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4259                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4260                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4261                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4262                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4263                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4264                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4265                                 
4266                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4267                                 genSkipc(&rFalseIfx);
4268                                 
4269                                 if(ifx) ifx->generated = 1;
4270                                 return;
4271                         }
4272                         
4273                 } else {
4274                         
4275                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4276                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4277                 }
4278                 
4279                 
4280                 /* The rest of the bytes of a multi-byte compare */
4281                 while (size) {
4282                         
4283                         emitSKPZ;
4284                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4285                         size--;
4286                         
4287                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4288                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4289                         
4290                         
4291                 }
4292                 
4293                 emitpLabel(lbl->key);
4294                 
4295                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4296                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4297                         (AOP_TYPE(result) == AOP_REG)) {
4298                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4299                         emitpcode(POC_RLF, popGet(AOP(result),0));
4300                 } else {
4301                         genSkipc(&rFalseIfx);
4302                 }       
4303                 //genSkipc(&rFalseIfx);
4304                 if(ifx) ifx->generated = 1;
4305                 
4306                 return;
4307                 
4308         }
4309         
4310         // check_carry:
4311         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4312                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4313                 pic14_outBitC(result);
4314         } else {
4315                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4316                 /* if the result is used in the next
4317                 ifx conditional branch then generate
4318                 code a little differently */
4319                 if (ifx )
4320                         genIfxJump (ifx,"c");
4321                 else
4322                         pic14_outBitC(result);
4323                 /* leave the result in acc */
4324         }
4325         
4326 }
4327
4328 /*-----------------------------------------------------------------*/
4329 /* genCmpGt :- greater than comparison                             */
4330 /*-----------------------------------------------------------------*/
4331 static void genCmpGt (iCode *ic, iCode *ifx)
4332 {
4333         operand *left, *right, *result;
4334         sym_link *letype , *retype;
4335         int sign ;
4336         
4337         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4338         left = IC_LEFT(ic);
4339         right= IC_RIGHT(ic);
4340         result = IC_RESULT(ic);
4341         
4342         letype = getSpec(operandType(left));
4343         retype =getSpec(operandType(right));
4344         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4345         /* assign the amsops */
4346         aopOp (left,ic,FALSE);
4347         aopOp (right,ic,FALSE);
4348         aopOp (result,ic,TRUE);
4349         
4350         genCmp(right, left, result, ifx, sign);
4351         
4352         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354         freeAsmop(result,NULL,ic,TRUE); 
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genCmpLt - less than comparisons                                */
4359 /*-----------------------------------------------------------------*/
4360 static void genCmpLt (iCode *ic, iCode *ifx)
4361 {
4362         operand *left, *right, *result;
4363         sym_link *letype , *retype;
4364         int sign ;
4365         
4366         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4367         left = IC_LEFT(ic);
4368         right= IC_RIGHT(ic);
4369         result = IC_RESULT(ic);
4370         
4371         letype = getSpec(operandType(left));
4372         retype =getSpec(operandType(right));
4373         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4374         
4375         /* assign the amsops */
4376         aopOp (left,ic,FALSE);
4377         aopOp (right,ic,FALSE);
4378         aopOp (result,ic,TRUE);
4379         
4380         genCmp(left, right, result, ifx, sign);
4381         
4382         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384         freeAsmop(result,NULL,ic,TRUE); 
4385 }
4386
4387 /*-----------------------------------------------------------------*/
4388 /* genc16bit2lit - compare a 16 bit value to a literal             */
4389 /*-----------------------------------------------------------------*/
4390 static void genc16bit2lit(operand *op, int lit, int offset)
4391 {
4392         int i;
4393         
4394         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4395         if( (lit&0xff) == 0) 
4396                 i=1;
4397         else
4398                 i=0;
4399         
4400         switch( BYTEofLONG(lit,i)) { 
4401         case 0:
4402                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4403                 break;
4404         case 1:
4405                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4406                 break;
4407         case 0xff:
4408                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4409                 break;
4410         default:
4411                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4412                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4413         }
4414         
4415         i ^= 1;
4416         
4417         switch( BYTEofLONG(lit,i)) { 
4418         case 0:
4419                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4420                 break;
4421         case 1:
4422                 emitSKPNZ;
4423                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4424                 break;
4425         case 0xff:
4426                 emitSKPNZ;
4427                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4428                 break;
4429         default:
4430                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4431                 emitSKPNZ;
4432                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4433                 
4434         }
4435         
4436 }
4437
4438 /*-----------------------------------------------------------------*/
4439 /* gencjneshort - compare and jump if not equal                    */
4440 /*-----------------------------------------------------------------*/
4441 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4442 {
4443         int size = max(AOP_SIZE(left),AOP_SIZE(right));
4444         int offset = 0;
4445         int res_offset = 0;  /* the result may be a different size then left or right */
4446         int res_size = AOP_SIZE(result);
4447         resolvedIfx rIfx;
4448         symbol *lbl;
4449         
4450         unsigned long lit = 0L;
4451         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4452         DEBUGpic14_AopType(__LINE__,left,right,result);
4453         if(result)
4454                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4455         resolveIfx(&rIfx,ifx);
4456         lbl =  newiTempLabel(NULL);
4457         
4458         
4459         /* if the left side is a literal or 
4460         if the right is in a pointer register and left 
4461         is not */
4462         if ((AOP_TYPE(left) == AOP_LIT) || 
4463                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4464                 operand *t = right;
4465                 right = left;
4466                 left = t;
4467         }
4468         if(AOP_TYPE(right) == AOP_LIT)
4469                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4470         
4471         /* if the right side is a literal then anything goes */
4472         if (AOP_TYPE(right) == AOP_LIT &&
4473                 AOP_TYPE(left) != AOP_DIR ) {
4474                 switch(size) {
4475                 case 2:
4476                         genc16bit2lit(left, lit, 0);
4477                         emitSKPNZ;
4478                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4479                         break;
4480                 default:
4481                         while (size--) {
4482                                 if(lit & 0xff) {
4483                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4484                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4485                                 } else {
4486                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4487                                 }
4488                                 
4489                                 emitSKPNZ;
4490                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4491                                 offset++;
4492                                 if(res_offset < res_size-1)
4493                                         res_offset++;
4494                                 lit >>= 8;
4495                         }
4496                         break;
4497                 }
4498         }
4499         
4500         /* if the right side is in a register or in direct space or
4501         if the left is a pointer register & right is not */    
4502         else if (AOP_TYPE(right) == AOP_REG ||
4503                 AOP_TYPE(right) == AOP_DIR || 
4504                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4505                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4506                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4507                 int lbl_key = lbl->key;
4508                 
4509                 if(result) {
4510                         emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4511                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4512                 }else {
4513                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4514                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4515                                 __FUNCTION__,__LINE__);
4516                         return;
4517                 }
4518                 
4519                 /*     switch(size) { */
4520                 /*     case 2: */
4521                 /*       genc16bit2lit(left, lit, 0); */
4522                 /*       emitSKPNZ; */
4523                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4524                 /*       break; */
4525                 /*     default: */
4526                 while (size--) {
4527                         int emit_skip=1;
4528                         if((AOP_TYPE(left) == AOP_DIR) && 
4529                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4530                                 
4531                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4532                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4533                                 
4534                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4535                                 
4536                                 switch (lit & 0xff) {
4537                                 case 0:
4538                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4539                                         break;
4540                                 case 1:
4541                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4542                                         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4543                                         //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4544                                         emit_skip=0;
4545                                         break;
4546                                 case 0xff:
4547                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4548                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4549                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4550                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4551                                         emit_skip=0;
4552                                         break;
4553                                 default:
4554                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4555                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4556                                 }
4557                                 lit >>= 8;
4558                                 
4559                         } else {
4560                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4561                         }
4562                         if(emit_skip) {
4563                                 if(AOP_TYPE(result) == AOP_CRY) {
4564                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4565                                         if(rIfx.condition)
4566                                                 emitSKPNZ;
4567                                         else
4568                                                 emitSKPZ;
4569                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4570                                 } else {
4571                                         /* fix me. probably need to check result size too */
4572                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4573                                         if(rIfx.condition)
4574                                                 emitSKPZ;
4575                                         else
4576                                                 emitSKPNZ;
4577                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4578                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4579                                 }
4580                                 if(ifx)
4581                                         ifx->generated=1;
4582                         }
4583                         emit_skip++;
4584                         offset++;
4585                         if(res_offset < res_size-1)
4586                                 res_offset++;
4587                 }
4588                 /*       break; */
4589                 /*     } */
4590         } else if(AOP_TYPE(right) == AOP_REG &&
4591                 AOP_TYPE(left) != AOP_DIR){
4592                 
4593                 while(size--) {
4594                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4595                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4596                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4597                         if(rIfx.condition)
4598                                 emitSKPNZ;
4599                         else
4600                                 emitSKPZ;
4601                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4602                         offset++;
4603                         if(res_offset < res_size-1)
4604                                 res_offset++;
4605                 }
4606                 
4607         }else{
4608                 /* right is a pointer reg need both a & b */
4609                 while(size--) {
4610                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4611                         if(strcmp(l,"b"))
4612                                 pic14_emitcode("mov","b,%s",l);
4613                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4614                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4615                         offset++;
4616                 }
4617         }
4618         
4619         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4620         if(!rIfx.condition)
4621                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4622         
4623         emitpLabel(lbl->key);
4624         
4625         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4626         
4627         if(ifx)
4628                 ifx->generated = 1;
4629 }
4630
4631 #if 0
4632 /*-----------------------------------------------------------------*/
4633 /* gencjne - compare and jump if not equal                         */
4634 /*-----------------------------------------------------------------*/
4635 static void gencjne(operand *left, operand *right, iCode *ifx)
4636 {
4637         symbol *tlbl  = newiTempLabel(NULL);
4638         
4639         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4640         gencjneshort(left, right, lbl);
4641         
4642         pic14_emitcode("mov","a,%s",one);
4643         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4644         pic14_emitcode("","%05d_DS_:",lbl->key+100);
4645         pic14_emitcode("clr","a");
4646         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4647         
4648         emitpLabel(lbl->key);
4649         emitpLabel(tlbl->key);
4650         
4651 }
4652 #endif
4653
4654 /*-----------------------------------------------------------------*/
4655 /* genCmpEq - generates code for equal to                          */
4656 /*-----------------------------------------------------------------*/
4657 static void genCmpEq (iCode *ic, iCode *ifx)
4658 {
4659         operand *left, *right, *result;
4660         unsigned long lit = 0L;
4661         int size,offset=0;
4662         
4663         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4664         
4665         if(ifx)
4666                 DEBUGpic14_emitcode ("; ifx is non-null","");
4667         else
4668                 DEBUGpic14_emitcode ("; ifx is null","");
4669         
4670         aopOp((left=IC_LEFT(ic)),ic,FALSE);
4671         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4672         aopOp((result=IC_RESULT(ic)),ic,TRUE);
4673         
4674         size = max(AOP_SIZE(left),AOP_SIZE(right));
4675         
4676         DEBUGpic14_AopType(__LINE__,left,right,result);
4677         
4678         /* if literal, literal on the right or 
4679         if the right is in a pointer register and left 
4680         is not */
4681         if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4682                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4683                 operand *tmp = right ;
4684                 right = left;
4685                 left = tmp;
4686         }
4687         
4688         
4689         if(ifx && !AOP_SIZE(result)){
4690                 symbol *tlbl;
4691                 /* if they are both bit variables */
4692                 if (AOP_TYPE(left) == AOP_CRY &&
4693                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4694                         if(AOP_TYPE(right) == AOP_LIT){
4695                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4696                                 if(lit == 0L){
4697                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4698                                         pic14_emitcode("cpl","c");
4699                                 } else if(lit == 1L) {
4700                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4701                                 } else {
4702                                         pic14_emitcode("clr","c");
4703                                 }
4704                                 /* AOP_TYPE(right) == AOP_CRY */
4705                         } else {
4706                                 symbol *lbl = newiTempLabel(NULL);
4707                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4708                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4709                                 pic14_emitcode("cpl","c");
4710                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4711                         }
4712                         /* if true label then we jump if condition
4713                         supplied is true */
4714                         tlbl = newiTempLabel(NULL);
4715                         if ( IC_TRUE(ifx) ) {
4716                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4717                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4718                         } else {
4719                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4720                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4721                         }
4722                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4723                         
4724                         {
4725                                 /* left and right are both bit variables, result is carry */
4726                                 resolvedIfx rIfx;
4727                                 
4728                                 resolveIfx(&rIfx,ifx);
4729                                 
4730                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4731                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4732                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4733                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4734                                 genSkipz2(&rIfx,0);
4735                         }
4736                 } else {
4737                         
4738                         /* They're not both bit variables. Is the right a literal? */
4739                         if(AOP_TYPE(right) == AOP_LIT) {
4740                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4741                                 
4742                                 switch(size) {
4743                                         
4744                                 case 1:
4745                                         switch(lit & 0xff) {
4746                                         case 1:
4747                                                 if ( IC_TRUE(ifx) ) {
4748                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
4749                                                         emitSKPNZ;
4750                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4751                                                 } else {
4752                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4753                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4754                                                 }
4755                                                 break;
4756                                         case 0xff:
4757                                                 if ( IC_TRUE(ifx) ) {
4758                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
4759                                                         emitSKPNZ;
4760                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4761                                                 } else {
4762                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4763                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4764                                                 }
4765                                                 break;
4766                                         default:
4767                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4768                                                 if(lit)
4769                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4770                                                 genSkip(ifx,'z');
4771                                         }
4772                                         
4773                                         
4774                                         /* end of size == 1 */
4775                                         break;
4776                                         
4777                                         case 2:
4778                                                 genc16bit2lit(left,lit,offset);
4779                                                 genSkip(ifx,'z');
4780                                                 break;
4781                                                 /* end of size == 2 */
4782                                                 
4783                                         default:
4784                                                 /* size is 4 */
4785                                                 if(lit==0) {
4786                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
4787                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
4788                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
4789                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
4790                                                         
4791                                                 } else {
4792                                                         
4793                                                         /* search for patterns that can be optimized */
4794                                                         
4795                                                         genc16bit2lit(left,lit,0);
4796                                                         lit >>= 16;
4797                                                         if(lit) {
4798                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4799                                                                 //genSkip(ifx,'z');
4800                                                                 genc16bit2lit(left,lit,2);
4801                                                         } else {
4802                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4803                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4804                                                                 
4805                                                         }
4806                                                         
4807                                                 }
4808                                                 
4809                                                 genSkip(ifx,'z');
4810                                 }
4811                                 
4812                                 ifx->generated = 1;
4813                                 goto release ;
4814                                 
4815                                 
4816                         } else if(AOP_TYPE(right) == AOP_CRY ) {
4817                                 /* we know the left is not a bit, but that the right is */
4818                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4819                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4820                                         popGet(AOP(right),offset));
4821                                 emitpcode(POC_XORLW,popGetLit(1));
4822                                 
4823                                 /* if the two are equal, then W will be 0 and the Z bit is set
4824                                 * we could test Z now, or go ahead and check the high order bytes if
4825                                 * the variable we're comparing is larger than a byte. */
4826                                 
4827                                 while(--size)
4828                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
4829                                 
4830                                 if ( IC_TRUE(ifx) ) {
4831                                         emitSKPNZ;
4832                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4833                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4834                                 } else {
4835                                         emitSKPZ;
4836                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4837                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4838                                 }
4839                                 
4840                         } else {
4841                                 /* They're both variables that are larger than bits */
4842                                 int s = size;
4843                                 
4844                                 tlbl = newiTempLabel(NULL);
4845                                 
4846                                 while(size--) {
4847                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4848                                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4849                                         
4850                                         if ( IC_TRUE(ifx) ) {
4851                                                 if(size) {
4852                                                         emitSKPZ;
4853                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4854                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4855                                                 } else {
4856                                                         emitSKPNZ;
4857                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4858                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4859                                                 }
4860                                         } else {
4861                                                 emitSKPZ;
4862                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4863                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4864                                         }
4865                                         offset++;
4866                                 }
4867                                 if(s>1 && IC_TRUE(ifx)) {
4868                                         emitpLabel(tlbl->key);
4869                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4870                                 }
4871                         }
4872                 }
4873                 /* mark the icode as generated */
4874                 ifx->generated = 1;
4875                 goto release ;
4876         }
4877   
4878   /* if they are both bit variables */
4879   if (AOP_TYPE(left) == AOP_CRY &&
4880           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4881           if(AOP_TYPE(right) == AOP_LIT){
4882                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4883                   if(lit == 0L){
4884                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4885                           pic14_emitcode("cpl","c");
4886                   } else if(lit == 1L) {
4887                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4888                   } else {
4889                           pic14_emitcode("clr","c");
4890                   }
4891                   /* AOP_TYPE(right) == AOP_CRY */
4892           } else {
4893                   symbol *lbl = newiTempLabel(NULL);
4894                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4895                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4896                   pic14_emitcode("cpl","c");
4897                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4898           }
4899           /* c = 1 if egal */
4900           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4901                   pic14_outBitC(result);
4902                   goto release ;
4903           }
4904           if (ifx) {
4905                   genIfxJump (ifx,"c");
4906                   goto release ;
4907           }
4908           /* if the result is used in an arithmetic operation
4909           then put the result in place */
4910           pic14_outBitC(result);
4911   } else {
4912           
4913           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4914           gencjne(left,right,result,ifx);
4915           /*
4916           if(ifx) 
4917           gencjne(left,right,newiTempLabel(NULL));
4918           else {
4919           if(IC_TRUE(ifx)->key)
4920           gencjne(left,right,IC_TRUE(ifx)->key);
4921           else
4922           gencjne(left,right,IC_FALSE(ifx)->key);
4923           ifx->generated = 1;
4924           goto release ;
4925           }
4926           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4927           aopPut(AOP(result),"a",0);
4928           goto release ;
4929           }
4930           
4931                 if (ifx) {
4932                 genIfxJump (ifx,"a");
4933                 goto release ;
4934                 }
4935           */
4936           /* if the result is used in an arithmetic operation
4937           then put the result in place */
4938           /*
4939           if (AOP_TYPE(result) != AOP_CRY) 
4940           pic14_outAcc(result);
4941           */
4942           /* leave the result in acc */
4943   }
4944   
4945 release:
4946   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4947   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4948   freeAsmop(result,NULL,ic,TRUE);
4949 }
4950
4951 /*-----------------------------------------------------------------*/
4952 /* ifxForOp - returns the icode containing the ifx for operand     */
4953 /*-----------------------------------------------------------------*/
4954 static iCode *ifxForOp ( operand *op, iCode *ic )
4955 {
4956         /* if true symbol then needs to be assigned */
4957         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4958         if (IS_TRUE_SYMOP(op))
4959                 return NULL ;
4960         
4961         /* if this has register type condition and
4962         the next instruction is ifx with the same operand
4963         and live to of the operand is upto the ifx only then */
4964         if (ic->next &&
4965                 ic->next->op == IFX &&
4966                 IC_COND(ic->next)->key == op->key &&
4967                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4968                 return ic->next;
4969         
4970         if (ic->next &&
4971                 ic->next->op == IFX &&
4972                 IC_COND(ic->next)->key == op->key) {
4973                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4974                 return ic->next;
4975         }
4976         
4977         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4978         if (ic->next &&
4979                 ic->next->op == IFX)
4980                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4981         
4982         if (ic->next &&
4983                 ic->next->op == IFX &&
4984                 IC_COND(ic->next)->key == op->key) {
4985                 DEBUGpic14_emitcode ("; "," key is okay");
4986                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4987                         OP_SYMBOL(op)->liveTo,
4988                         ic->next->seq);
4989         }
4990         
4991         
4992         return NULL;
4993 }
4994 /*-----------------------------------------------------------------*/
4995 /* genAndOp - for && operation                                     */
4996 /*-----------------------------------------------------------------*/
4997 static void genAndOp (iCode *ic)
4998 {
4999         operand *left,*right, *result;
5000         /*     symbol *tlbl; */
5001         
5002         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5003         /* note here that && operations that are in an
5004         if statement are taken away by backPatchLabels
5005         only those used in arthmetic operations remain */
5006         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5007         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5008         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5009         
5010         DEBUGpic14_AopType(__LINE__,left,right,result);
5011         
5012         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5013         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5014         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5015         
5016         /* if both are bit variables */
5017         /*     if (AOP_TYPE(left) == AOP_CRY && */
5018         /*         AOP_TYPE(right) == AOP_CRY ) { */
5019         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5020         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5021         /*         pic14_outBitC(result); */
5022         /*     } else { */
5023         /*         tlbl = newiTempLabel(NULL); */
5024         /*         pic14_toBoolean(left);     */
5025         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5026         /*         pic14_toBoolean(right); */
5027         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5028         /*         pic14_outBitAcc(result); */
5029         /*     } */
5030         
5031         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5032         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5033         freeAsmop(result,NULL,ic,TRUE);
5034 }
5035
5036
5037 /*-----------------------------------------------------------------*/
5038 /* genOrOp - for || operation                                      */
5039 /*-----------------------------------------------------------------*/
5040 /*
5041 tsd pic port -
5042 modified this code, but it doesn't appear to ever get called
5043 */
5044
5045 static void genOrOp (iCode *ic)
5046 {
5047         operand *left,*right, *result;
5048         symbol *tlbl;
5049         
5050         /* note here that || operations that are in an
5051         if statement are taken away by backPatchLabels
5052         only those used in arthmetic operations remain */
5053         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5054         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5055         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5056         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5057         
5058         DEBUGpic14_AopType(__LINE__,left,right,result);
5059         
5060         /* if both are bit variables */
5061         if (AOP_TYPE(left) == AOP_CRY &&
5062                 AOP_TYPE(right) == AOP_CRY ) {
5063                 pic14_emitcode("clrc","");
5064                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5065                         AOP(left)->aopu.aop_dir,
5066                         AOP(left)->aopu.aop_dir);
5067                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5068                         AOP(right)->aopu.aop_dir,
5069                         AOP(right)->aopu.aop_dir);
5070                 pic14_emitcode("setc","");
5071                 
5072         } else {
5073                 tlbl = newiTempLabel(NULL);
5074                 pic14_toBoolean(left);
5075                 emitSKPZ;
5076                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5077                 pic14_toBoolean(right);
5078                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5079                 
5080                 pic14_outBitAcc(result);
5081         }
5082         
5083         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5084         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5085         freeAsmop(result,NULL,ic,TRUE);            
5086 }
5087
5088 /*-----------------------------------------------------------------*/
5089 /* isLiteralBit - test if lit == 2^n                               */
5090 /*-----------------------------------------------------------------*/
5091 static int isLiteralBit(unsigned long lit)
5092 {
5093         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5094                 0x100L,0x200L,0x400L,0x800L,
5095                 0x1000L,0x2000L,0x4000L,0x8000L,
5096                 0x10000L,0x20000L,0x40000L,0x80000L,
5097                 0x100000L,0x200000L,0x400000L,0x800000L,
5098                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5099                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5100         int idx;
5101         
5102         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5103         for(idx = 0; idx < 32; idx++)
5104                 if(lit == pw[idx])
5105                         return idx+1;
5106                 return 0;
5107 }
5108
5109 /*-----------------------------------------------------------------*/
5110 /* continueIfTrue -                                                */
5111 /*-----------------------------------------------------------------*/
5112 static void continueIfTrue (iCode *ic)
5113 {
5114         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5115         if(IC_TRUE(ic))
5116                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5117         ic->generated = 1;
5118 }
5119
5120 /*-----------------------------------------------------------------*/
5121 /* jmpIfTrue -                                                     */
5122 /*-----------------------------------------------------------------*/
5123 static void jumpIfTrue (iCode *ic)
5124 {
5125         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126         if(!IC_TRUE(ic))
5127                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5128         ic->generated = 1;
5129 }
5130
5131 /*-----------------------------------------------------------------*/
5132 /* jmpTrueOrFalse -                                                */
5133 /*-----------------------------------------------------------------*/
5134 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5135 {
5136         // ugly but optimized by peephole
5137         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5138         if(IC_TRUE(ic)){
5139                 symbol *nlbl = newiTempLabel(NULL);
5140                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5141                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5142                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5143                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5144         }
5145         else{
5146                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5147                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5148         }
5149         ic->generated = 1;
5150 }
5151
5152 /*-----------------------------------------------------------------*/
5153 /* genAnd  - code for and                                          */
5154 /*-----------------------------------------------------------------*/
5155 static void genAnd (iCode *ic, iCode *ifx)
5156 {
5157         operand *left, *right, *result;
5158         int size, offset=0;  
5159         unsigned long lit = 0L;
5160         int bytelit = 0;
5161         resolvedIfx rIfx;
5162         
5163         
5164         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5165         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5166         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5167         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5168         
5169         resolveIfx(&rIfx,ifx);
5170         
5171         /* if left is a literal & right is not then exchange them */
5172         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5173                 AOP_NEEDSACC(left)) {
5174                 operand *tmp = right ;
5175                 right = left;
5176                 left = tmp;
5177         }
5178         
5179         /* if result = right then exchange them */
5180         if(pic14_sameRegs(AOP(result),AOP(right))){
5181                 operand *tmp = right ;
5182                 right = left;
5183                 left = tmp;
5184         }
5185         
5186         /* if right is bit then exchange them */
5187         if (AOP_TYPE(right) == AOP_CRY &&
5188                 AOP_TYPE(left) != AOP_CRY){
5189                 operand *tmp = right ;
5190                 right = left;
5191                 left = tmp;
5192         }
5193         if(AOP_TYPE(right) == AOP_LIT)
5194                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5195         
5196         size = AOP_SIZE(result);
5197         
5198         DEBUGpic14_AopType(__LINE__,left,right,result);
5199         
5200         // if(bit & yy)
5201         // result = bit & yy;
5202         if (AOP_TYPE(left) == AOP_CRY){
5203                 // c = bit & literal;
5204                 if(AOP_TYPE(right) == AOP_LIT){
5205                         if(lit & 1) {
5206                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5207                                         // no change
5208                                         goto release;
5209                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5210                         } else {
5211                                 // bit(result) = 0;
5212                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5213                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5214                                         goto release;
5215                                 }
5216                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5217                                         jumpIfTrue(ifx);
5218                                         goto release;
5219                                 }
5220                                 pic14_emitcode("clr","c");
5221                         }
5222                 } else {
5223                         if (AOP_TYPE(right) == AOP_CRY){
5224                                 // c = bit & bit;
5225                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5226                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5227                         } else {
5228                                 // c = bit & val;
5229                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5230                                 // c = lsb
5231                                 pic14_emitcode("rrc","a");
5232                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5233                         }
5234                 }
5235                 // bit = c
5236                 // val = c
5237                 if(size)
5238                         pic14_outBitC(result);
5239                 // if(bit & ...)
5240                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5241                         genIfxJump(ifx, "c");           
5242                 goto release ;
5243         }
5244         
5245         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5246         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5247         if((AOP_TYPE(right) == AOP_LIT) &&
5248                 (AOP_TYPE(result) == AOP_CRY) &&
5249                 (AOP_TYPE(left) != AOP_CRY)){
5250                 int posbit = isLiteralBit(lit);
5251                 /* left &  2^n */
5252                 if(posbit){
5253                         posbit--;
5254                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5255                         // bit = left & 2^n
5256                         if(size)
5257                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5258                         // if(left &  2^n)
5259                         else{
5260                                 if(ifx){
5261                                         int offset = 0;
5262                                         while (posbit > 7) {
5263                                                 posbit -= 8;
5264                                                 offset++;
5265                                         }
5266                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5267                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5268                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5269                                         
5270                                         ifx->generated = 1;
5271                                 }
5272                                 goto release;
5273                         }
5274                 } else {
5275                         symbol *tlbl = newiTempLabel(NULL);
5276                         int sizel = AOP_SIZE(left);
5277                         if(size)
5278                                 pic14_emitcode("setb","c");
5279                         while(sizel--){
5280                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5281                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5282                                         // byte ==  2^n ?
5283                                         if((posbit = isLiteralBit(bytelit)) != 0)
5284                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5285                                         else{
5286                                                 if(bytelit != 0x0FFL)
5287                                                         pic14_emitcode("anl","a,%s",
5288                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5289                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5290                                         }
5291                                 }
5292                                 offset++;
5293                         }
5294                         // bit = left & literal
5295                         if(size){
5296                                 pic14_emitcode("clr","c");
5297                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5298                         }
5299                         // if(left & literal)
5300                         else{
5301                                 if(ifx)
5302                                         jmpTrueOrFalse(ifx, tlbl);
5303                                 goto release ;
5304                         }
5305                 }
5306                 pic14_outBitC(result);
5307                 goto release ;
5308         }
5309         
5310         /* if left is same as result */
5311         if(pic14_sameRegs(AOP(result),AOP(left))){
5312                 int know_W = -1;
5313                 for(;size--; offset++,lit>>=8) {
5314                         if(AOP_TYPE(right) == AOP_LIT){
5315                                 switch(lit & 0xff) {
5316                                 case 0x00:
5317                                         /*  and'ing with 0 has clears the result */
5318                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5319                                         break;
5320                                 case 0xff:
5321                                         /* and'ing with 0xff is a nop when the result and left are the same */
5322                                         break;
5323                                         
5324                                 default:
5325                                         {
5326                                                 int p = my_powof2( (~lit) & 0xff );
5327                                                 if(p>=0) {
5328                                                         /* only one bit is set in the literal, so use a bcf instruction */
5329                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5330                                                         
5331                                                 } else {
5332                                                         if(know_W != (int)(lit&0xff))
5333                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5334                                                         know_W = lit &0xff;
5335                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5336                                                 }
5337                                         }    
5338                                 }
5339                         } else {
5340                                 if (AOP_TYPE(left) == AOP_ACC) {
5341                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5342                                 } else {        
5343                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5344                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5345                                         
5346                                 }
5347                         }
5348                 }
5349                 
5350         } else {
5351                 // left & result in different registers
5352                 if(AOP_TYPE(result) == AOP_CRY){
5353                         // result = bit
5354                         // if(size), result in bit
5355                         // if(!size && ifx), conditional oper: if(left & right)
5356                         symbol *tlbl = newiTempLabel(NULL);
5357                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5358                         if(size)
5359                                 pic14_emitcode("setb","c");
5360                         while(sizer--){
5361                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5362                                 pic14_emitcode("anl","a,%s",
5363                                         aopGet(AOP(left),offset,FALSE,FALSE));
5364                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5365                                 offset++;
5366                         }
5367                         if(size){
5368                                 CLRC;
5369                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5370                                 pic14_outBitC(result);
5371                         } else if(ifx)
5372                                 jmpTrueOrFalse(ifx, tlbl);
5373                 } else {
5374                         for(;(size--);offset++) {
5375                                 // normal case
5376                                 // result = left & right
5377                                 if(AOP_TYPE(right) == AOP_LIT){
5378                                         int t = (lit >> (offset*8)) & 0x0FFL;
5379                                         switch(t) { 
5380                                         case 0x00:
5381                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5382                                                 break;
5383                                         case 0xff:
5384                                                 if(AOP_TYPE(left) != AOP_ACC) {
5385                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5386                                                 }
5387                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5388                                                 break;
5389                                         default:
5390                                                 if(AOP_TYPE(left) == AOP_ACC) {
5391                                                         emitpcode(POC_ANDLW, popGetLit(t));
5392                                                 } else {
5393                                                         emitpcode(POC_MOVLW, popGetLit(t));
5394                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5395                                                 }
5396                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5397                                         }
5398                                         continue;
5399                                 }
5400                                 
5401                                 if (AOP_TYPE(left) == AOP_ACC) {
5402                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5403                                 } else {
5404                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5405                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5406                                 }
5407                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5408                         }
5409                 }
5410         }
5411         
5412 release :
5413         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5414         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5415         freeAsmop(result,NULL,ic,TRUE);     
5416 }
5417
5418 /*-----------------------------------------------------------------*/
5419 /* genOr  - code for or                                            */
5420 /*-----------------------------------------------------------------*/
5421 static void genOr (iCode *ic, iCode *ifx)
5422 {
5423         operand *left, *right, *result;
5424         int size, offset=0;
5425         unsigned long lit = 0L;
5426         
5427         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5428         
5429         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5430         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5431         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5432         
5433         DEBUGpic14_AopType(__LINE__,left,right,result);
5434         
5435         /* if left is a literal & right is not then exchange them */
5436         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5437                 AOP_NEEDSACC(left)) {
5438                 operand *tmp = right ;
5439                 right = left;
5440                 left = tmp;
5441         }
5442         
5443         /* if result = right then exchange them */
5444         if(pic14_sameRegs(AOP(result),AOP(right))){
5445                 operand *tmp = right ;
5446                 right = left;
5447                 left = tmp;
5448         }
5449         
5450         /* if right is bit then exchange them */
5451         if (AOP_TYPE(right) == AOP_CRY &&
5452                 AOP_TYPE(left) != AOP_CRY){
5453                 operand *tmp = right ;
5454                 right = left;
5455                 left = tmp;
5456         }
5457         
5458         DEBUGpic14_AopType(__LINE__,left,right,result);
5459         
5460         if(AOP_TYPE(right) == AOP_LIT)
5461                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5462         
5463         size = AOP_SIZE(result);
5464         
5465         // if(bit | yy)
5466         // xx = bit | yy;
5467         if (AOP_TYPE(left) == AOP_CRY){
5468                 if(AOP_TYPE(right) == AOP_LIT){
5469                         // c = bit & literal;
5470                         if(lit){
5471                                 // lit != 0 => result = 1
5472                                 if(AOP_TYPE(result) == AOP_CRY){
5473                                         if(size)
5474                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5475                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5476                                         //   AOP(result)->aopu.aop_dir,
5477                                         //   AOP(result)->aopu.aop_dir);
5478                                         else if(ifx)
5479                                                 continueIfTrue(ifx);
5480                                         goto release;
5481                                 }
5482                         } else {
5483                                 // lit == 0 => result = left
5484                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5485                                         goto release;
5486                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5487                         }
5488                 } else {
5489                         if (AOP_TYPE(right) == AOP_CRY){
5490                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5491                                         // c = bit | bit;
5492                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5493                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5494                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5495                                         
5496                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5497                                                 AOP(result)->aopu.aop_dir,
5498                                                 AOP(result)->aopu.aop_dir);
5499                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5500                                                 AOP(right)->aopu.aop_dir,
5501                                                 AOP(right)->aopu.aop_dir);
5502                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5503                                                 AOP(result)->aopu.aop_dir,
5504                                                 AOP(result)->aopu.aop_dir);
5505                                 } else {
5506                                         if( AOP_TYPE(result) == AOP_ACC) {
5507                                                 emitpcode(POC_MOVLW, popGetLit(0));
5508                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5509                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5510                                                 emitpcode(POC_MOVLW, popGetLit(1));
5511                                                 
5512                                         } else {
5513                                                 
5514                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5515                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5516                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5517                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5518                                                 
5519                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5520                                                         AOP(result)->aopu.aop_dir,
5521                                                         AOP(result)->aopu.aop_dir);
5522                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5523                                                         AOP(right)->aopu.aop_dir,
5524                                                         AOP(right)->aopu.aop_dir);
5525                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5526                                                         AOP(left)->aopu.aop_dir,
5527                                                         AOP(left)->aopu.aop_dir);
5528                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5529                                                         AOP(result)->aopu.aop_dir,
5530                                                         AOP(result)->aopu.aop_dir);
5531                                         }
5532                                 }
5533                         } else {
5534                                 // c = bit | val;
5535                                 symbol *tlbl = newiTempLabel(NULL);
5536                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5537                                 
5538                                 
5539                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5540                                 if( AOP_TYPE(right) == AOP_ACC) {
5541                                         emitpcode(POC_IORLW, popGetLit(0));
5542                                         emitSKPNZ;
5543                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5544                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5545                                 }
5546                                 
5547                                 
5548                                 
5549                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5550                                         pic14_emitcode(";XXX setb","c");
5551                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5552                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5553                                 pic14_toBoolean(right);
5554                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5555                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5556                                         jmpTrueOrFalse(ifx, tlbl);
5557                                         goto release;
5558                                 } else {
5559                                         CLRC;
5560                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5561                                 }
5562                         }
5563                 }
5564                 // bit = c
5565                 // val = c
5566                 if(size)
5567                         pic14_outBitC(result);
5568                 // if(bit | ...)
5569                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5570                         genIfxJump(ifx, "c");           
5571                 goto release ;
5572   }
5573   
5574   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5575   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5576   if((AOP_TYPE(right) == AOP_LIT) &&
5577           (AOP_TYPE(result) == AOP_CRY) &&
5578           (AOP_TYPE(left) != AOP_CRY)){
5579           if(lit){
5580                   pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5581                   // result = 1
5582                   if(size)
5583                           pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5584                   else 
5585                           continueIfTrue(ifx);
5586                   goto release;
5587           } else {
5588                   pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5589                   // lit = 0, result = boolean(left)
5590                   if(size)
5591                           pic14_emitcode(";XXX setb","c");
5592                   pic14_toBoolean(right);
5593                   if(size){
5594                           symbol *tlbl = newiTempLabel(NULL);
5595                           pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5596                           CLRC;
5597                           pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5598                   } else {
5599                           genIfxJump (ifx,"a");
5600                           goto release;
5601                   }
5602           }
5603           pic14_outBitC(result);
5604           goto release ;
5605   }
5606   
5607   /* if left is same as result */
5608   if(pic14_sameRegs(AOP(result),AOP(left))){
5609           int know_W = -1;
5610           for(;size--; offset++,lit>>=8) {
5611                   if(AOP_TYPE(right) == AOP_LIT){
5612                           if((lit & 0xff) == 0)
5613                                   /*  or'ing with 0 has no effect */
5614                                   continue;
5615                           else {
5616                                   int p = my_powof2(lit & 0xff);
5617                                   if(p>=0) {
5618                                           /* only one bit is set in the literal, so use a bsf instruction */
5619                                           emitpcode(POC_BSF,
5620                                                   newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5621                                   } else {
5622                                           if(know_W != (int)(lit & 0xff))
5623                                                   emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5624                                           know_W = lit & 0xff;
5625                                           emitpcode(POC_IORWF, popGet(AOP(left),offset));
5626                                   }
5627                                   
5628                           }
5629                   } else {
5630                           if (AOP_TYPE(left) == AOP_ACC) {
5631                                   emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5632                                   pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5633                           } else {        
5634                                   emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5635                                   emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5636                                   
5637                                   pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5638                                   pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5639                                   
5640                           }
5641                   }
5642           }
5643   } else {
5644           // left & result in different registers
5645           if(AOP_TYPE(result) == AOP_CRY){
5646                   // result = bit
5647                   // if(size), result in bit
5648                   // if(!size && ifx), conditional oper: if(left | right)
5649                   symbol *tlbl = newiTempLabel(NULL);
5650                   int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5651                   pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5652                   
5653                   
5654                   if(size)
5655                           pic14_emitcode(";XXX setb","c");
5656                   while(sizer--){
5657                           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5658                           pic14_emitcode(";XXX orl","a,%s",
5659                                   aopGet(AOP(left),offset,FALSE,FALSE));
5660                           pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5661                           offset++;
5662                   }
5663                   if(size){
5664                           CLRC;
5665                           pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5666                           pic14_outBitC(result);
5667                   } else if(ifx)
5668                           jmpTrueOrFalse(ifx, tlbl);
5669           } else for(;(size--);offset++){
5670                   // normal case
5671                   // result = left & right
5672                   if(AOP_TYPE(right) == AOP_LIT){
5673                           int t = (lit >> (offset*8)) & 0x0FFL;
5674                           switch(t) { 
5675                           case 0x00:
5676                                   if (AOP_TYPE(left) != AOP_ACC) {
5677                                           emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5678                                   }
5679                                   emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5680                                   
5681                                   break;
5682                           default:
5683                                   if (AOP_TYPE(left) == AOP_ACC) {
5684                                           emitpcode(POC_IORLW,  popGetLit(t));
5685                                   } else {
5686                                           emitpcode(POC_MOVLW,  popGetLit(t));
5687                                           emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5688                                   }
5689                                   emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5690                           }
5691                           continue;
5692                   }
5693                   
5694                   // faster than result <- left, anl result,right
5695                   // and better if result is SFR
5696                   if (AOP_TYPE(left) == AOP_ACC) {
5697                           emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5698                           pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5699                   } else {
5700                           emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5701                           emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5702                           
5703                           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5704                           pic14_emitcode("iorwf","%s,w",
5705                                   aopGet(AOP(left),offset,FALSE,FALSE));
5706                   }
5707                   emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5708                   pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5709           }
5710   }
5711   
5712 release :
5713   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5714   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5715   freeAsmop(result,NULL,ic,TRUE);     
5716 }
5717
5718 /*-----------------------------------------------------------------*/
5719 /* genXor - code for xclusive or                                   */
5720 /*-----------------------------------------------------------------*/
5721 static void genXor (iCode *ic, iCode *ifx)
5722 {
5723         operand *left, *right, *result;
5724         int size, offset=0;
5725         unsigned long lit = 0L;
5726         
5727         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5728         
5729         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5730         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5731         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5732         
5733         /* if left is a literal & right is not ||
5734         if left needs acc & right does not */
5735         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5736                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5737                 operand *tmp = right ;
5738                 right = left;
5739                 left = tmp;
5740         }
5741         
5742         /* if result = right then exchange them */
5743         if(pic14_sameRegs(AOP(result),AOP(right))){
5744                 operand *tmp = right ;
5745                 right = left;
5746                 left = tmp;
5747         }
5748         
5749         /* if right is bit then exchange them */
5750         if (AOP_TYPE(right) == AOP_CRY &&
5751                 AOP_TYPE(left) != AOP_CRY){
5752                 operand *tmp = right ;
5753                 right = left;
5754                 left = tmp;
5755         }
5756         if(AOP_TYPE(right) == AOP_LIT)
5757                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5758         
5759         size = AOP_SIZE(result);
5760         
5761         // if(bit ^ yy)
5762         // xx = bit ^ yy;
5763         if (AOP_TYPE(left) == AOP_CRY){
5764                 if(AOP_TYPE(right) == AOP_LIT){
5765                         // c = bit & literal;
5766                         if(lit>>1){
5767                                 // lit>>1  != 0 => result = 1
5768                                 if(AOP_TYPE(result) == AOP_CRY){
5769                                         if(size)
5770                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5771                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5772                                         else if(ifx)
5773                                                 continueIfTrue(ifx);
5774                                         goto release;
5775                                 }
5776                                 pic14_emitcode("setb","c");
5777                         } else{
5778                                 // lit == (0 or 1)
5779                                 if(lit == 0){
5780                                         // lit == 0, result = left
5781                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5782                                                 goto release;
5783                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5784                                 } else{
5785                                         // lit == 1, result = not(left)
5786                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
5787                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5788                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5789                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5790                                                 goto release;
5791                                         } else {
5792                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5793                                                 pic14_emitcode("cpl","c");
5794                                         }
5795                                 }
5796                         }
5797                         
5798                 } else {
5799                         // right != literal
5800                         symbol *tlbl = newiTempLabel(NULL);
5801                         if (AOP_TYPE(right) == AOP_CRY){
5802                                 // c = bit ^ bit;
5803                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5804                         }
5805                         else{
5806                                 int sizer = AOP_SIZE(right);
5807                                 // c = bit ^ val
5808                                 // if val>>1 != 0, result = 1
5809                                 pic14_emitcode("setb","c");
5810                                 while(sizer){
5811                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5812                                         if(sizer == 1)
5813                                                 // test the msb of the lsb
5814                                                 pic14_emitcode("anl","a,#0xfe");
5815                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5816                                         sizer--;
5817                                 }
5818                                 // val = (0,1)
5819                                 pic14_emitcode("rrc","a");
5820                         }
5821                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5822                         pic14_emitcode("cpl","c");
5823                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5824                 }
5825                 // bit = c
5826                 // val = c
5827                 if(size)
5828                         pic14_outBitC(result);
5829                 // if(bit | ...)
5830                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5831                         genIfxJump(ifx, "c");           
5832                 goto release ;
5833         }
5834         
5835         if(pic14_sameRegs(AOP(result),AOP(left))){
5836                 /* if left is same as result */
5837                 for(;size--; offset++) {
5838                         if(AOP_TYPE(right) == AOP_LIT){
5839                                 int t  = (lit >> (offset*8)) & 0x0FFL;
5840                                 if(t == 0x00L)
5841                                         continue;
5842                                 else
5843                                         if (IS_AOP_PREG(left)) {
5844                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5845                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5846                                                 aopPut(AOP(result),"a",offset);
5847                                         } else {
5848                                                 emitpcode(POC_MOVLW, popGetLit(t));
5849                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5850                                                 pic14_emitcode("xrl","%s,%s",
5851                                                         aopGet(AOP(left),offset,FALSE,TRUE),
5852                                                         aopGet(AOP(right),offset,FALSE,FALSE));
5853                                         }
5854                         } else {
5855                                 if (AOP_TYPE(left) == AOP_ACC)
5856                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5857                                 else {
5858                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5859                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
5860                                         /*
5861                                         if (IS_AOP_PREG(left)) {
5862                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5863                                         aopPut(AOP(result),"a",offset);
5864                                         } else
5865                                         pic14_emitcode("xrl","%s,a",
5866                                         aopGet(AOP(left),offset,FALSE,TRUE));
5867                                         */
5868                                 }
5869                         }
5870                 }
5871         } else {
5872                 // left & result in different registers
5873                 if(AOP_TYPE(result) == AOP_CRY){
5874                         // result = bit
5875                         // if(size), result in bit
5876                         // if(!size && ifx), conditional oper: if(left ^ right)
5877                         symbol *tlbl = newiTempLabel(NULL);
5878                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5879                         if(size)
5880                                 pic14_emitcode("setb","c");
5881                         while(sizer--){
5882                                 if((AOP_TYPE(right) == AOP_LIT) &&
5883                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5884                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5885                                 } else {
5886                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5887                                         pic14_emitcode("xrl","a,%s",
5888                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5889                                 }
5890                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5891                                 offset++;
5892                         }
5893                         if(size){
5894                                 CLRC;
5895                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5896                                 pic14_outBitC(result);
5897                         } else if(ifx)
5898                                 jmpTrueOrFalse(ifx, tlbl);
5899                 } else for(;(size--);offset++){
5900                         // normal case
5901                         // result = left & right
5902                         if(AOP_TYPE(right) == AOP_LIT){
5903                                 int t = (lit >> (offset*8)) & 0x0FFL;
5904                                 switch(t) { 
5905                                 case 0x00:
5906                                         if (AOP_TYPE(left) != AOP_ACC) {
5907                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5908                                         }
5909                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5910                                         pic14_emitcode("movf","%s,w",
5911                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5912                                         pic14_emitcode("movwf","%s",
5913                                                 aopGet(AOP(result),offset,FALSE,FALSE));
5914                                         break;
5915                                 case 0xff:
5916                                         if (AOP_TYPE(left) == AOP_ACC) {
5917                                                 emitpcode(POC_XORLW, popGetLit(t));
5918                                         } else {
5919                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5920                                         }
5921                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5922                                         break;
5923                                 default:
5924                                         if (AOP_TYPE(left) == AOP_ACC) {
5925                                                 emitpcode(POC_XORLW, popGetLit(t));
5926                                         } else {
5927                                                 emitpcode(POC_MOVLW, popGetLit(t));
5928                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5929                                         }
5930                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5931                                         pic14_emitcode("movlw","0x%x",t);
5932                                         pic14_emitcode("xorwf","%s,w",
5933                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5934                                         pic14_emitcode("movwf","%s",
5935                                                 aopGet(AOP(result),offset,FALSE,FALSE));
5936                                         
5937                                 }
5938                                 continue;
5939                         }
5940                         
5941                         // faster than result <- left, anl result,right
5942                         // and better if result is SFR
5943                         if (AOP_TYPE(left) == AOP_ACC) {
5944                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5945                                 pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5946                         } else {
5947                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5948                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5949                                 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5950                                 pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5951                         }
5952                         if ( AOP_TYPE(result) != AOP_ACC){
5953                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5954                                 pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5955                         }
5956                 }
5957         }
5958         
5959 release :
5960         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5961         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5962         freeAsmop(result,NULL,ic,TRUE);     
5963 }
5964
5965 /*-----------------------------------------------------------------*/
5966 /* genInline - write the inline code out                           */
5967 /*-----------------------------------------------------------------*/
5968 static void genInline (iCode *ic)
5969 {
5970         char *buffer, *bp, *bp1;
5971         
5972         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5973         
5974         _G.inLine += (!options.asmpeep);
5975         
5976         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5977         strcpy(buffer,IC_INLINE(ic));
5978         
5979         /* emit each line as a code */
5980         while (*bp) {
5981                 if (*bp == '\n') {
5982                         *bp++ = '\0';
5983                         
5984                         if(*bp1)
5985                                 addpCode2pBlock(pb,AssembleLine(bp1));
5986                         bp1 = bp;
5987                 } else {
5988                         if (*bp == ':') {
5989                                 bp++;
5990                                 *bp = '\0';
5991                                 bp++;
5992                                 pic14_emitcode(bp1,"");
5993                                 bp1 = bp;
5994                         } else
5995                                 bp++;
5996                 }
5997         }
5998         if ((bp1 != bp) && *bp1)
5999                 addpCode2pBlock(pb,AssembleLine(bp1));
6000         
6001         Safe_free(buffer);
6002         
6003         _G.inLine -= (!options.asmpeep);
6004 }
6005
6006 /*-----------------------------------------------------------------*/
6007 /* genRRC - rotate right with carry                                */
6008 /*-----------------------------------------------------------------*/
6009 static void genRRC (iCode *ic)
6010 {
6011         operand *left , *result ;
6012         int size, offset = 0, same;
6013         
6014         /* rotate right with carry */
6015         left = IC_LEFT(ic);
6016         result=IC_RESULT(ic);
6017         aopOp (left,ic,FALSE);
6018         aopOp (result,ic,FALSE);
6019         
6020         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6021         
6022         same = pic14_sameRegs(AOP(result),AOP(left));
6023         
6024         size = AOP_SIZE(result);    
6025         
6026         /* get the lsb and put it into the carry */
6027         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6028         
6029         offset = 0 ;
6030         
6031         while(size--) {
6032                 
6033                 if(same) {
6034                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6035                 } else {
6036                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6037                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6038                 }
6039                 
6040                 offset++;
6041         }
6042         
6043         freeAsmop(left,NULL,ic,TRUE);
6044         freeAsmop(result,NULL,ic,TRUE);
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* genRLC - generate code for rotate left with carry               */
6049 /*-----------------------------------------------------------------*/
6050 static void genRLC (iCode *ic)
6051 {    
6052         operand *left , *result ;
6053         int size, offset = 0;
6054         int same;
6055         
6056         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6057         /* rotate right with carry */
6058         left = IC_LEFT(ic);
6059         result=IC_RESULT(ic);
6060         aopOp (left,ic,FALSE);
6061         aopOp (result,ic,FALSE);
6062         
6063         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6064         
6065         same = pic14_sameRegs(AOP(result),AOP(left));
6066         
6067         /* move it to the result */
6068         size = AOP_SIZE(result);    
6069         
6070         /* get the msb and put it into the carry */
6071         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6072         
6073         offset = 0 ;
6074         
6075         while(size--) {
6076                 
6077                 if(same) {
6078                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6079                 } else {
6080                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6081                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6082                 }
6083                 
6084                 offset++;
6085         }
6086         
6087         
6088         freeAsmop(left,NULL,ic,TRUE);
6089         freeAsmop(result,NULL,ic,TRUE);
6090 }
6091
6092 /*-----------------------------------------------------------------*/
6093 /* genGetHbit - generates code get highest order bit               */
6094 /*-----------------------------------------------------------------*/
6095 static void genGetHbit (iCode *ic)
6096 {
6097         operand *left, *result;
6098         left = IC_LEFT(ic);
6099         result=IC_RESULT(ic);
6100         aopOp (left,ic,FALSE);
6101         aopOp (result,ic,FALSE);
6102         
6103         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6104         /* get the highest order byte into a */
6105         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6106         if(AOP_TYPE(result) == AOP_CRY){
6107                 pic14_emitcode("rlc","a");
6108                 pic14_outBitC(result);
6109         }
6110         else{
6111                 pic14_emitcode("rl","a");
6112                 pic14_emitcode("anl","a,#0x01");
6113                 pic14_outAcc(result);
6114         }
6115         
6116         
6117         freeAsmop(left,NULL,ic,TRUE);
6118         freeAsmop(result,NULL,ic,TRUE);
6119 }
6120
6121 /*-----------------------------------------------------------------*/
6122 /* AccRol - rotate left accumulator by known count                 */
6123 /*-----------------------------------------------------------------*/
6124 static void AccRol (operand *op,int offset,int shCount)
6125 {
6126         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6127         shCount &= 0x0007;              // shCount : 0..7
6128         switch(shCount){
6129         case 0 :
6130                 break;
6131         case 1 :
6132                 pic14_emitcode("rl","a");
6133                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6134                 break;
6135         case 2 :
6136                 pic14_emitcode("rl","a");
6137                 pic14_emitcode("rl","a");
6138                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6139                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6140                 break;
6141         case 3 :
6142                 pic14_emitcode("swap","a");
6143                 pic14_emitcode("rr","a");
6144                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6145                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6146                 break;
6147         case 4 :
6148                 pic14_emitcode("swap","a");
6149                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6150                 break;
6151         case 5 :
6152                 pic14_emitcode("swap","a");
6153                 pic14_emitcode("rl","a");
6154                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6155                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6156                 break;
6157         case 6 :
6158                 pic14_emitcode("rr","a");
6159                 pic14_emitcode("rr","a");
6160                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6161                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6162                 break;
6163         case 7 :
6164                 pic14_emitcode("rr","a");
6165                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6166                 break;
6167         }
6168 }
6169
6170 /*-----------------------------------------------------------------*/
6171 /* AccLsh - left shift accumulator by known count                  */
6172 /*-----------------------------------------------------------------*/
6173 static void AccLsh (operand *op,int offset,int shCount)
6174 {
6175         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6176         if(shCount != 0){
6177                 /*
6178                 if(shCount == 1) {
6179                         pic14_emitcode("add","a,acc");
6180                         emitCLRC;
6181                         emitpcode(POC_RLF,popGet(AOP(op),offset));
6182                 } else {
6183                         if(shCount == 2) {
6184                                 pic14_emitcode("add","a,acc");
6185                                 emitCLRC;
6186                                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6187                                 pic14_emitcode("add","a,acc");
6188                                 emitCLRC;
6189                                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6190                         } else {
6191                 */
6192                 {
6193                         {
6194                                 /* rotate left accumulator */
6195                                 AccRol(op,offset,shCount);
6196                                 /* and kill the lower order bits */
6197                                 pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6198                                 emitpcode(POC_ANDLW,popGetLit(SLMask[shCount]));
6199                         }
6200                 }
6201         }
6202 }
6203
6204 /*-----------------------------------------------------------------*/
6205 /* AccRsh - right shift accumulator by known count                 */
6206 /*-----------------------------------------------------------------*/
6207 static void AccRsh (operand *op,int offset,int shCount)
6208 {
6209         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6210         if(shCount != 0){
6211                 if(shCount == 1){
6212                         CLRC;
6213                         pic14_emitcode("rrc","a");
6214                 } else {
6215                         /* rotate right accumulator */
6216                         AccRol(op,offset,8 - shCount);
6217                         /* and kill the higher order bits */
6218                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6219                 }
6220         }
6221 }
6222
6223 #if 0
6224 /*-----------------------------------------------------------------*/
6225 /* AccSRsh - signed right shift accumulator by known count                 */
6226 /*-----------------------------------------------------------------*/
6227 static void AccSRsh (int shCount)
6228 {
6229         symbol *tlbl ;
6230         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6231         if(shCount != 0){
6232                 if(shCount == 1){
6233                         pic14_emitcode("mov","c,acc.7");
6234                         pic14_emitcode("rrc","a");
6235                 } else if(shCount == 2){
6236                         pic14_emitcode("mov","c,acc.7");
6237                         pic14_emitcode("rrc","a");
6238                         pic14_emitcode("mov","c,acc.7");
6239                         pic14_emitcode("rrc","a");
6240                 } else {
6241                         tlbl = newiTempLabel(NULL);
6242                         /* rotate right accumulator */
6243                         AccRol(8 - shCount);
6244                         /* and kill the higher order bits */
6245                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6246                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6247                         pic14_emitcode("orl","a,#0x%02x",
6248                                 (unsigned char)~SRMask[shCount]);
6249                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6250                 }
6251         }
6252 }
6253 #endif
6254 /*-----------------------------------------------------------------*/
6255 /* shiftR1Left2Result - shift right one byte from left to result   */
6256 /*-----------------------------------------------------------------*/
6257 static void shiftR1Left2ResultSigned (operand *left, int offl,
6258                                                                           operand *result, int offr,
6259                                                                           int shCount)
6260 {
6261         int same;
6262         
6263         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6264         
6265         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6266         
6267         switch(shCount) {
6268         case 1:
6269                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6270                 if(same) 
6271                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6272                 else {
6273                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6274                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6275                 }
6276                 
6277                 break;
6278         case 2:
6279                 
6280                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6281                 if(same) 
6282                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6283                 else {
6284                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6285                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6286                 }
6287                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6288                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6289                 
6290                 break;
6291                 
6292         case 3:
6293                 if(same)
6294                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6295                 else {
6296                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6297                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6298                 }
6299                 
6300                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6301                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6302                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6303                 
6304                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6305                 emitpcode(POC_IORLW, popGetLit(0xe0));
6306                 
6307                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6308                 break;
6309                 
6310         case 4:
6311                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6312                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6313                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6314                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6315                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6316                 break;
6317         case 5:
6318                 if(same) {
6319                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6320                 } else {
6321                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6322                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6323                 }
6324                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6325                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6326                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6327                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6328                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6329                 break;
6330                 
6331         case 6:
6332                 if(same) {
6333                         emitpcode(POC_MOVLW, popGetLit(0x00));
6334                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6335                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6336                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6337                         emitpcode(POC_IORLW, popGetLit(0x01));
6338                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6339                 } else {
6340                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6341                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6342                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6343                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6344                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6345                 }
6346                 break;
6347                 
6348         case 7:
6349                 if(same) {
6350                         emitpcode(POC_MOVLW, popGetLit(0x00));
6351                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6352                         emitpcode(POC_MOVLW, popGetLit(0xff));
6353                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6354                 } else {
6355                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6356                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6357                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6358                 }
6359                 
6360         default:
6361                 break;
6362         }
6363 }
6364
6365 /*-----------------------------------------------------------------*/
6366 /* shiftR1Left2Result - shift right one byte from left to result   */
6367 /*-----------------------------------------------------------------*/
6368 static void shiftR1Left2Result (operand *left, int offl,
6369                                                                 operand *result, int offr,
6370                                                                 int shCount, int sign)
6371 {
6372         int same;
6373         
6374         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6375         
6376         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6377         
6378         /* Copy the msb into the carry if signed. */
6379         if(sign) {
6380                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6381                 return;
6382         }
6383         
6384         
6385         
6386         switch(shCount) {
6387         case 1:
6388                 emitCLRC;
6389                 if(same) 
6390                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6391                 else {
6392                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6393                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6394                 }
6395                 break;
6396         case 2:
6397                 emitCLRC;
6398                 if(same) {
6399                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6400                 } else {
6401                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6402                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6403                 }
6404                 emitCLRC;
6405                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6406                 
6407                 break;
6408         case 3:
6409                 if(same)
6410                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6411                 else {
6412                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6413                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6414                 }
6415                 
6416                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6417                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6418                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6419                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6420                 break;
6421                 
6422         case 4:
6423                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6424                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6425                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6426                 break;
6427                 
6428         case 5:
6429                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6430                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6431                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6432                 emitCLRC;
6433                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6434                 
6435                 break;
6436         case 6:
6437                 
6438                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6439                 emitpcode(POC_ANDLW, popGetLit(0x80));
6440                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6441                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6442                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6443                 break;
6444                 
6445         case 7:
6446                 
6447                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6448                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6449                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6450                 
6451                 break;
6452                 
6453         default:
6454                 break;
6455         }
6456 }
6457
6458 /*-----------------------------------------------------------------*/
6459 /* shiftL1Left2Result - shift left one byte from left to result    */
6460 /*-----------------------------------------------------------------*/
6461 static void shiftL1Left2Result (operand *left, int offl,
6462                                                                 operand *result, int offr, int shCount)
6463 {
6464         int same;
6465         
6466         //    char *l;
6467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6468         
6469         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6470         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6471         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6472         //    MOVA(l);
6473         /* shift left accumulator */
6474         //AccLsh(shCount); // don't comment out just yet...
6475         //    aopPut(AOP(result),"a",offr);
6476         
6477         switch(shCount) {
6478         case 1:
6479                 /* Shift left 1 bit position */
6480                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6481                 if(same) {
6482                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6483                 } else {
6484                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6485                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6486                 }
6487                 break;
6488         case 2:
6489                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6490                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6491                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6492                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6493                 break;
6494         case 3:
6495                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6496                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6497                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6498                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6499                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6500                 break;
6501         case 4:
6502                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6503                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6504                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6505                 break;
6506         case 5:
6507                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6508                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6509                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6510                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6511                 break;
6512         case 6:
6513                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6514                 emitpcode(POC_ANDLW, popGetLit(0x30));
6515                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6516                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6517                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6518                 break;
6519         case 7:
6520                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6521                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6522                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6523                 break;
6524                 
6525         default:
6526                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6527         }
6528         
6529 }
6530
6531 /*-----------------------------------------------------------------*/
6532 /* movLeft2Result - move byte from left to result                  */
6533 /*-----------------------------------------------------------------*/
6534 static void movLeft2Result (operand *left, int offl,
6535                                                         operand *result, int offr)
6536 {
6537         char *l;
6538         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6539         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6540                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6541                 
6542                 if (*l == '@' && (IS_AOP_PREG(result))) {
6543                         pic14_emitcode("mov","a,%s",l);
6544                         aopPut(AOP(result),"a",offr);
6545                 } else {
6546                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6547                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6548                 }
6549         }
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* shiftL2Left2Result - shift left two bytes from left to result   */
6554 /*-----------------------------------------------------------------*/
6555 static void shiftL2Left2Result (operand *left, int offl,
6556                                                                 operand *result, int offr, int shCount)
6557 {
6558         
6559         
6560         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6561         
6562         if(pic14_sameRegs(AOP(result), AOP(left))) {
6563                 switch(shCount) {
6564                 case 0:
6565                         break;
6566                 case 1:
6567                 case 2:
6568                 case 3:
6569                         
6570                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6571                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6572                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6573                         
6574                         while(--shCount) {
6575                                 emitCLRC;
6576                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6577                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6578                         }
6579                         
6580                         break;
6581                 case 4:
6582                 case 5:
6583                         emitpcode(POC_MOVLW, popGetLit(0x0f));
6584                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6585                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6586                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6587                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6588                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6589                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6590                         if(shCount >=5) {
6591                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6592                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6593                         }
6594                         break;
6595                 case 6:
6596                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6597                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6598                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6599                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6600                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6601                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6602                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6603                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6604                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6605                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6606                         break;
6607                 case 7:
6608                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6609                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
6610                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6611                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6612                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6613                 }
6614                 
6615         } else {
6616                 switch(shCount) {
6617                 case 0:
6618                         break;
6619                 case 1:
6620                 case 2:
6621                 case 3:
6622                 /* note, use a mov/add for the shift since the mov has a
6623                         chance of getting optimized out */
6624                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6625                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6626                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6627                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6628                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6629                         
6630                         while(--shCount) {
6631                                 emitCLRC;
6632                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6633                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6634                         }
6635                         break;
6636                         
6637                 case 4:
6638                 case 5:
6639                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6640                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6641                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6642                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6643                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6644                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6645                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6646                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6647                         
6648                         
6649                         if(shCount == 5) {
6650                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6651                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6652                         }
6653                         break;
6654                 case 6:
6655                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6656                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6657                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
6658                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6659                         
6660                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6661                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6662                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6663                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6664                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6665                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6666                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6667                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6668                         break;
6669                 case 7:
6670                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6671                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6672                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6673                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6674                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6675                 }
6676         }
6677         
6678 }
6679 /*-----------------------------------------------------------------*/
6680 /* shiftR2Left2Result - shift right two bytes from left to result  */
6681 /*-----------------------------------------------------------------*/
6682 static void shiftR2Left2Result (operand *left, int offl,
6683                                                                 operand *result, int offr,
6684                                                                 int shCount, int sign)
6685 {
6686         int same=0;
6687         
6688         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6689         same = pic14_sameRegs(AOP(result), AOP(left));
6690         
6691         if(same && ((offl + MSB16) == offr)){
6692                 same=1;
6693                 /* don't crash result[offr] */
6694                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6695                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6696         }
6697         /* else {
6698         movLeft2Result(left,offl, result, offr);
6699         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6700         }
6701         */
6702         /* a:x >> shCount (x = lsb(result))*/
6703         /*
6704         if(sign)
6705         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6706         else {
6707         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6708         */
6709         switch(shCount) {
6710         case 0:
6711                 break;
6712         case 1:
6713         case 2:
6714         case 3:
6715                 if(sign)
6716                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6717                 else
6718                         emitCLRC;
6719                 
6720                 if(same) {
6721                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6722                         emitpcode(POC_RRF,popGet(AOP(result),offr));
6723                 } else {
6724                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6725                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6726                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6727                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6728                 }
6729                 
6730                 while(--shCount) {
6731                         if(sign)
6732                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6733                         else
6734                                 emitCLRC;
6735                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6736                         emitpcode(POC_RRF,popGet(AOP(result),offr));
6737                 }
6738                 break;
6739         case 4:
6740         case 5:
6741                 if(same) {
6742                         
6743                         emitpcode(POC_MOVLW, popGetLit(0xf0));
6744                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6745                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6746                         
6747                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6748                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6749                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6750                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6751                 } else {
6752                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6753                         emitpcode(POC_ANDLW, popGetLit(0x0f));
6754                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6755                         
6756                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6757                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6758                         emitpcode(POC_ANDLW, popGetLit(0xf0));
6759                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6760                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6761                 }
6762                 
6763                 if(shCount >=5) {
6764                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6765                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6766                 }
6767                 
6768                 if(sign) {
6769                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6770                         emitpcode(POC_BTFSC, 
6771                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6772                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6773                 }
6774                 
6775                 break;
6776                 
6777         case 6:
6778                 if(same) {
6779                         
6780                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6781                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6782                         
6783                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6784                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6785                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
6786                         emitpcode(POC_ANDLW,popGetLit(0x03));
6787                         if(sign) {
6788                                 emitpcode(POC_BTFSC, 
6789                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6790                                 emitpcode(POC_IORLW,popGetLit(0xfc));
6791                         }
6792                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6793                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6794                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6795                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6796                 } else {
6797                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6798                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6799                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6800                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6801                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6802                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6803                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6804                         emitpcode(POC_ANDLW,popGetLit(0x03));
6805                         if(sign) {
6806                                 emitpcode(POC_BTFSC, 
6807                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6808                                 emitpcode(POC_IORLW,popGetLit(0xfc));
6809                         }
6810                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6811                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6812                         
6813                         
6814                 }
6815                 
6816                 break;
6817         case 7:
6818                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6819                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6820                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6821                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6822                 if(sign) {
6823                         emitSKPNC;
6824                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6825                 } else 
6826                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6827   }
6828 }
6829
6830
6831 /*-----------------------------------------------------------------*/
6832 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6833 /*-----------------------------------------------------------------*/
6834 static void shiftLLeftOrResult (operand *left, int offl,
6835                                                                 operand *result, int offr, int shCount)
6836 {
6837         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6838         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6839         /* shift left accumulator */
6840         AccLsh(left,offl,shCount);
6841         /* or with result */
6842         pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6843         /* back to result */
6844         aopPut(AOP(result),"a",offr);
6845 }
6846
6847 /*-----------------------------------------------------------------*/
6848 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6849 /*-----------------------------------------------------------------*/
6850 static void shiftRLeftOrResult (operand *left, int offl,
6851                                                                 operand *result, int offr, int shCount)
6852 {
6853         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6854         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6855         /* shift right accumulator */
6856         AccRsh(left,offl,shCount);
6857         /* or with result */
6858         pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6859         /* back to result */
6860         aopPut(AOP(result),"a",offr);
6861 }
6862
6863 /*-----------------------------------------------------------------*/
6864 /* genlshOne - left shift a one byte quantity by known count       */
6865 /*-----------------------------------------------------------------*/
6866 static void genlshOne (operand *result, operand *left, int shCount)
6867 {       
6868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6869         shiftL1Left2Result(left, LSB, result, LSB, shCount);
6870 }
6871
6872 /*-----------------------------------------------------------------*/
6873 /* genlshTwo - left shift two bytes by known amount != 0           */
6874 /*-----------------------------------------------------------------*/
6875 static void genlshTwo (operand *result,operand *left, int shCount)
6876 {
6877         int size;
6878         
6879         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6880         size = pic14_getDataSize(result);
6881         
6882         /* if shCount >= 8 */
6883         if (shCount >= 8) {
6884                 shCount -= 8 ;
6885                 
6886                 if (size > 1){
6887                         if (shCount)
6888                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6889                         else 
6890                                 movLeft2Result(left, LSB, result, MSB16);
6891                 }
6892                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6893         }
6894         
6895         /*  1 <= shCount <= 7 */
6896         else {  
6897                 if(size == 1)
6898                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6899                 else 
6900                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6901         }
6902 }
6903
6904 /*-----------------------------------------------------------------*/
6905 /* shiftLLong - shift left one long from left to result            */
6906 /* offl = LSB or MSB16                                             */
6907 /*-----------------------------------------------------------------*/
6908 static void shiftLLong (operand *left, operand *result, int offr )
6909 {
6910         char *l;
6911         int size = AOP_SIZE(result);
6912         
6913         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6914         if(size >= LSB+offr){
6915                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6916                 MOVA(l);
6917                 pic14_emitcode("add","a,acc");
6918                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6919                         size >= MSB16+offr && offr != LSB )
6920                         pic14_emitcode("xch","a,%s",
6921                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6922                 else      
6923                         aopPut(AOP(result),"a",LSB+offr);
6924         }
6925         
6926         if(size >= MSB16+offr){
6927                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6928                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6929                         MOVA(l);
6930                 }
6931                 pic14_emitcode("rlc","a");
6932                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6933                         size >= MSB24+offr && offr != LSB)
6934                         pic14_emitcode("xch","a,%s",
6935                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6936                 else      
6937                         aopPut(AOP(result),"a",MSB16+offr);
6938         }
6939         
6940         if(size >= MSB24+offr){
6941                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6942                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6943                         MOVA(l);
6944                 }
6945                 pic14_emitcode("rlc","a");
6946                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6947                         size >= MSB32+offr && offr != LSB )
6948                         pic14_emitcode("xch","a,%s",
6949                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6950                 else      
6951                         aopPut(AOP(result),"a",MSB24+offr);
6952         }
6953         
6954         if(size > MSB32+offr){
6955                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6956                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6957                         MOVA(l);  
6958                 }
6959                 pic14_emitcode("rlc","a");
6960                 aopPut(AOP(result),"a",MSB32+offr);
6961         }
6962         if(offr != LSB)
6963                 aopPut(AOP(result),zero,LSB);       
6964 }
6965
6966 /*-----------------------------------------------------------------*/
6967 /* genlshFour - shift four byte by a known amount != 0             */
6968 /*-----------------------------------------------------------------*/
6969 static void genlshFour (operand *result, operand *left, int shCount)
6970 {
6971         int size;
6972         
6973         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6974         size = AOP_SIZE(result);
6975         
6976         /* if shifting more that 3 bytes */
6977         if (shCount >= 24 ) {
6978                 shCount -= 24;
6979                 if (shCount)
6980                 /* lowest order of left goes to the highest
6981                 order of the destination */
6982                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6983                 else
6984                         movLeft2Result(left, LSB, result, MSB32);
6985                 aopPut(AOP(result),zero,LSB);
6986                 aopPut(AOP(result),zero,MSB16);
6987                 aopPut(AOP(result),zero,MSB32);
6988                 return;
6989         }
6990         
6991         /* more than two bytes */
6992         else if ( shCount >= 16 ) {
6993                 /* lower order two bytes goes to higher order two bytes */
6994                 shCount -= 16;
6995                 /* if some more remaining */
6996                 if (shCount)
6997                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6998                 else {
6999                         movLeft2Result(left, MSB16, result, MSB32);
7000                         movLeft2Result(left, LSB, result, MSB24);
7001                 }
7002                 aopPut(AOP(result),zero,MSB16);
7003                 aopPut(AOP(result),zero,LSB);
7004                 return;
7005         }    
7006         
7007         /* if more than 1 byte */
7008         else if ( shCount >= 8 ) {
7009                 /* lower order three bytes goes to higher order  three bytes */
7010                 shCount -= 8;
7011                 if(size == 2){
7012                         if(shCount)
7013                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7014                         else
7015                                 movLeft2Result(left, LSB, result, MSB16);
7016                 }
7017                 else{   /* size = 4 */
7018                         if(shCount == 0){
7019                                 movLeft2Result(left, MSB24, result, MSB32);
7020                                 movLeft2Result(left, MSB16, result, MSB24);
7021                                 movLeft2Result(left, LSB, result, MSB16);
7022                                 aopPut(AOP(result),zero,LSB);
7023                         }
7024                         else if(shCount == 1)
7025                                 shiftLLong(left, result, MSB16);
7026                         else{
7027                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7028                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7029                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7030                                 aopPut(AOP(result),zero,LSB);
7031                         }
7032                 }
7033         }
7034         
7035         /* 1 <= shCount <= 7 */
7036         else if(shCount <= 2){
7037                 shiftLLong(left, result, LSB);
7038                 if(shCount == 2)
7039                         shiftLLong(result, result, LSB);
7040         }
7041         /* 3 <= shCount <= 7, optimize */
7042         else{
7043                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7044                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7045                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7046         }
7047 }
7048
7049 /*-----------------------------------------------------------------*/
7050 /* genLeftShiftLiteral - left shifting by known count              */
7051 /*-----------------------------------------------------------------*/
7052 static void genLeftShiftLiteral (operand *left,
7053                                                                  operand *right,
7054                                                                  operand *result,
7055                                                                  iCode *ic)
7056 {    
7057         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7058         int size;
7059         
7060         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7061         freeAsmop(right,NULL,ic,TRUE);
7062         
7063         aopOp(left,ic,FALSE);
7064         aopOp(result,ic,FALSE);
7065         
7066         size = getSize(operandType(result));
7067         
7068 #if VIEW_SIZE
7069         pic14_emitcode("; shift left ","result %d, left %d",size,
7070                 AOP_SIZE(left));
7071 #endif
7072         
7073         /* I suppose that the left size >= result size */
7074         if(shCount == 0){
7075                 while(size--){
7076                         movLeft2Result(left, size, result, size);
7077                 }
7078         }
7079         
7080         else if(shCount >= (size * 8))
7081                 while(size--)
7082                         aopPut(AOP(result),zero,size);
7083                 else{
7084                         switch (size) {
7085                         case 1:
7086                                 genlshOne (result,left,shCount);
7087                                 break;
7088                                 
7089                         case 2:
7090                         case 3:
7091                                 genlshTwo (result,left,shCount);
7092                                 break;
7093                                 
7094                         case 4:
7095                                 genlshFour (result,left,shCount);
7096                                 break;
7097                         }
7098                 }
7099                 freeAsmop(left,NULL,ic,TRUE);
7100                 freeAsmop(result,NULL,ic,TRUE);
7101 }
7102
7103 /*-----------------------------------------------------------------*
7104 * genMultiAsm - repeat assembly instruction for size of register.
7105 * if endian == 1, then the high byte (i.e base address + size of 
7106 * register) is used first else the low byte is used first;
7107 *-----------------------------------------------------------------*/
7108 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7109 {
7110         
7111         int offset = 0;
7112         
7113         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7114         
7115         if(!reg)
7116                 return;
7117         
7118         if(!endian) {
7119                 endian = 1;
7120         } else {
7121                 endian = -1;
7122                 offset = size-1;
7123         }
7124         
7125         while(size--) {
7126                 emitpcode(poc,    popGet(AOP(reg),offset));
7127                 offset += endian;
7128         }
7129         
7130 }
7131 /*-----------------------------------------------------------------*/
7132 /* genLeftShift - generates code for left shifting                 */
7133 /*-----------------------------------------------------------------*/
7134 static void genLeftShift (iCode *ic)
7135 {
7136         operand *left,*right, *result;
7137         int size, offset;
7138         char *l;
7139         symbol *tlbl , *tlbl1;
7140         pCodeOp *pctemp;
7141         
7142         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7143         
7144         right = IC_RIGHT(ic);
7145         left  = IC_LEFT(ic);
7146         result = IC_RESULT(ic);
7147         
7148         aopOp(right,ic,FALSE);
7149         
7150         /* if the shift count is known then do it 
7151         as efficiently as possible */
7152         if (AOP_TYPE(right) == AOP_LIT) {
7153                 genLeftShiftLiteral (left,right,result,ic);
7154                 return ;
7155         }
7156         
7157         /* shift count is unknown then we have to form 
7158         a loop get the loop count in B : Note: we take
7159         only the lower order byte since shifting
7160         more that 32 bits make no sense anyway, ( the
7161         largest size of an object can be only 32 bits ) */  
7162         
7163         
7164         aopOp(left,ic,FALSE);
7165         aopOp(result,ic,FALSE);
7166         
7167         /* now move the left to the result if they are not the
7168         same */
7169         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7170                 AOP_SIZE(result) > 1) {
7171                 
7172                 size = AOP_SIZE(result);
7173                 offset=0;
7174                 while (size--) {
7175                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7176                         if (*l == '@' && (IS_AOP_PREG(result))) {
7177                                 
7178                                 pic14_emitcode("mov","a,%s",l);
7179                                 aopPut(AOP(result),"a",offset);
7180                         } else {
7181                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7182                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7183                                 //aopPut(AOP(result),l,offset);
7184                         }
7185                         offset++;
7186                 }
7187         }
7188         
7189         size = AOP_SIZE(result);
7190         
7191         /* if it is only one byte then */
7192         if (size == 1) {
7193                 if(optimized_for_speed) {
7194                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7195                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7196                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7197                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7198                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7199                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7200                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7201                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7202                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7203                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7204                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7205                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7206                 } else {
7207                         
7208                         tlbl = newiTempLabel(NULL);
7209                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7210                                 emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7211                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7212                         }
7213                         
7214                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7215                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7216                         emitpLabel(tlbl->key);
7217                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7218                         emitpcode(POC_ADDLW,  popGetLit(1));
7219                         emitSKPC;
7220                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7221                 }
7222                 goto release ;
7223         }
7224         
7225         if (pic14_sameRegs(AOP(left),AOP(result))) {
7226                 
7227                 tlbl = newiTempLabel(NULL);
7228                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7229                 genMultiAsm(POC_RRF, result, size,1);
7230                 emitpLabel(tlbl->key);
7231                 genMultiAsm(POC_RLF, result, size,0);
7232                 emitpcode(POC_ADDLW,  popGetLit(1));
7233                 emitSKPC;
7234                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7235                 goto release;
7236         }
7237         
7238         //tlbl = newiTempLabel(NULL);
7239         //offset = 0 ;   
7240         //tlbl1 = newiTempLabel(NULL);
7241         
7242         //reAdjustPreg(AOP(result));    
7243         
7244         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7245         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7246         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7247         //MOVA(l);
7248         //pic14_emitcode("add","a,acc");         
7249         //aopPut(AOP(result),"a",offset++);
7250         //while (--size) {
7251         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7252         //  MOVA(l);
7253         //  pic14_emitcode("rlc","a");         
7254         //  aopPut(AOP(result),"a",offset++);
7255         //}
7256         //reAdjustPreg(AOP(result));
7257         
7258         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7259         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7260         
7261         
7262         tlbl = newiTempLabel(NULL);
7263         tlbl1= newiTempLabel(NULL);
7264         
7265         size = AOP_SIZE(result);
7266         offset = 1;
7267         
7268         pctemp = popGetTempReg();  /* grab a temporary working register. */
7269         
7270         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7271         
7272         /* offset should be 0, 1 or 3 */
7273         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7274         emitSKPNZ;
7275         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7276         
7277         emitpcode(POC_MOVWF, pctemp);
7278         
7279         
7280         emitpLabel(tlbl->key);
7281         
7282         emitCLRC;
7283         emitpcode(POC_RLF,  popGet(AOP(result),0));
7284         while(--size)
7285                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7286         
7287         emitpcode(POC_DECFSZ,  pctemp);
7288         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7289         emitpLabel(tlbl1->key);
7290         
7291         popReleaseTempReg(pctemp);
7292         
7293         
7294 release:
7295         freeAsmop (right,NULL,ic,TRUE);
7296         freeAsmop(left,NULL,ic,TRUE);
7297         freeAsmop(result,NULL,ic,TRUE);
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* genrshOne - right shift a one byte quantity by known count      */
7302 /*-----------------------------------------------------------------*/
7303 static void genrshOne (operand *result, operand *left,
7304                                            int shCount, int sign)
7305 {
7306         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7307         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* genrshTwo - right shift two bytes by known amount != 0          */
7312 /*-----------------------------------------------------------------*/
7313 static void genrshTwo (operand *result,operand *left,
7314                                            int shCount, int sign)
7315 {
7316         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7317         /* if shCount >= 8 */
7318         if (shCount >= 8) {
7319                 shCount -= 8 ;
7320                 if (shCount)
7321                         shiftR1Left2Result(left, MSB16, result, LSB,
7322                         shCount, sign);
7323                 else
7324                         movLeft2Result(left, MSB16, result, LSB);
7325                 
7326                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7327                 
7328                 if(sign) {
7329                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7330                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7331                 }
7332         }
7333         
7334         /*  1 <= shCount <= 7 */
7335         else
7336                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7337 }
7338
7339 /*-----------------------------------------------------------------*/
7340 /* shiftRLong - shift right one long from left to result           */
7341 /* offl = LSB or MSB16                                             */
7342 /*-----------------------------------------------------------------*/
7343 static void shiftRLong (operand *left, int offl,
7344                                                 operand *result, int sign)
7345 {
7346         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7347         if(!sign)
7348                 pic14_emitcode("clr","c");
7349         MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7350         if(sign)
7351                 pic14_emitcode("mov","c,acc.7");
7352         pic14_emitcode("rrc","a");
7353         aopPut(AOP(result),"a",MSB32-offl);
7354         if(offl == MSB16)
7355                 /* add sign of "a" */
7356                 addSign(result, MSB32, sign);
7357         
7358         MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7359         pic14_emitcode("rrc","a");
7360         aopPut(AOP(result),"a",MSB24-offl);
7361         
7362         MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7363         pic14_emitcode("rrc","a");
7364         aopPut(AOP(result),"a",MSB16-offl);
7365         
7366         if(offl == LSB){
7367                 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7368                 pic14_emitcode("rrc","a");
7369                 aopPut(AOP(result),"a",LSB);
7370         }
7371 }
7372
7373 /*-----------------------------------------------------------------*/
7374 /* genrshFour - shift four byte by a known amount != 0             */
7375 /*-----------------------------------------------------------------*/
7376 static void genrshFour (operand *result, operand *left,
7377                                                 int shCount, int sign)
7378 {
7379         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7380         /* if shifting more that 3 bytes */
7381         if(shCount >= 24 ) {
7382                 shCount -= 24;
7383                 if(shCount)
7384                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7385                 else
7386                         movLeft2Result(left, MSB32, result, LSB);
7387                 
7388                 addSign(result, MSB16, sign);
7389         }
7390         else if(shCount >= 16){
7391                 shCount -= 16;
7392                 if(shCount)
7393                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7394                 else{
7395                         movLeft2Result(left, MSB24, result, LSB);
7396                         movLeft2Result(left, MSB32, result, MSB16);
7397                 }
7398                 addSign(result, MSB24, sign);
7399         }
7400         else if(shCount >= 8){
7401                 shCount -= 8;
7402                 if(shCount == 1)
7403                         shiftRLong(left, MSB16, result, sign);
7404                 else if(shCount == 0){
7405                         movLeft2Result(left, MSB16, result, LSB);
7406                         movLeft2Result(left, MSB24, result, MSB16);
7407                         movLeft2Result(left, MSB32, result, MSB24);
7408                         addSign(result, MSB32, sign);
7409                 }
7410                 else{
7411                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7412                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7413                         /* the last shift is signed */
7414                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7415                         addSign(result, MSB32, sign);
7416                 }
7417         }
7418         else{   /* 1 <= shCount <= 7 */
7419                 if(shCount <= 2){
7420                         shiftRLong(left, LSB, result, sign);
7421                         if(shCount == 2)
7422                                 shiftRLong(result, LSB, result, sign);
7423                 }
7424                 else{
7425                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7426                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7427                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7428                 }
7429         }
7430 }
7431
7432 /*-----------------------------------------------------------------*/
7433 /* genRightShiftLiteral - right shifting by known count            */
7434 /*-----------------------------------------------------------------*/
7435 static void genRightShiftLiteral (operand *left,
7436                                                                   operand *right,
7437                                                                   operand *result,
7438                                                                   iCode *ic,
7439                                                                   int sign)
7440 {    
7441         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7442         int lsize,res_size;
7443         
7444         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7445         freeAsmop(right,NULL,ic,TRUE);
7446         
7447         aopOp(left,ic,FALSE);
7448         aopOp(result,ic,FALSE);
7449         
7450 #if VIEW_SIZE
7451         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7452                 AOP_SIZE(left));
7453 #endif
7454         
7455         lsize = pic14_getDataSize(left);
7456         res_size = pic14_getDataSize(result);
7457         /* test the LEFT size !!! */
7458         
7459         /* I suppose that the left size >= result size */
7460         if(shCount == 0){
7461                 while(res_size--)
7462                         movLeft2Result(left, lsize, result, res_size);
7463         }
7464         
7465         else if(shCount >= (lsize * 8)){
7466                 
7467                 if(res_size == 1) {
7468                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7469                         if(sign) {
7470                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7471                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7472                         }
7473                 } else {
7474                         
7475                         if(sign) {
7476                                 emitpcode(POC_MOVLW, popGetLit(0));
7477                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7478                                 emitpcode(POC_MOVLW, popGetLit(0xff));
7479                                 while(res_size--)
7480                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7481                                 
7482                         } else {
7483                                 
7484                                 while(res_size--)
7485                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7486                         }
7487                 }
7488         } else {
7489                 
7490                 switch (res_size) {
7491                 case 1:
7492                         genrshOne (result,left,shCount,sign);
7493                         break;
7494                         
7495                 case 2:
7496                         genrshTwo (result,left,shCount,sign);
7497                         break;
7498                         
7499                 case 4:
7500                         genrshFour (result,left,shCount,sign);
7501                         break;
7502                 default :
7503                         break;
7504                 }
7505                 
7506         }
7507         
7508         freeAsmop(left,NULL,ic,TRUE);
7509         freeAsmop(result,NULL,ic,TRUE);
7510 }
7511
7512 /*-----------------------------------------------------------------*/
7513 /* genSignedRightShift - right shift of signed number              */
7514 /*-----------------------------------------------------------------*/
7515 static void genSignedRightShift (iCode *ic)
7516 {
7517         operand *right, *left, *result;
7518         int size, offset;
7519         //  char *l;
7520         symbol *tlbl, *tlbl1 ;
7521         pCodeOp *pctemp;
7522         
7523         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7524         
7525         /* we do it the hard way put the shift count in b
7526         and loop thru preserving the sign */
7527         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7528         
7529         right = IC_RIGHT(ic);
7530         left  = IC_LEFT(ic);
7531         result = IC_RESULT(ic);
7532         
7533         aopOp(right,ic,FALSE);  
7534         aopOp(left,ic,FALSE);
7535         aopOp(result,ic,FALSE);
7536         
7537         
7538         if ( AOP_TYPE(right) == AOP_LIT) {
7539                 genRightShiftLiteral (left,right,result,ic,1);
7540                 return ;
7541         }
7542         /* shift count is unknown then we have to form 
7543         a loop get the loop count in B : Note: we take
7544         only the lower order byte since shifting
7545         more that 32 bits make no sense anyway, ( the
7546         largest size of an object can be only 32 bits ) */  
7547         
7548         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7549         //pic14_emitcode("inc","b");
7550         //freeAsmop (right,NULL,ic,TRUE);
7551         //aopOp(left,ic,FALSE);
7552         //aopOp(result,ic,FALSE);
7553         
7554         /* now move the left to the result if they are not the
7555         same */
7556         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7557                 AOP_SIZE(result) > 1) {
7558                 
7559                 size = AOP_SIZE(result);
7560                 offset=0;
7561                 while (size--) { 
7562                         /*
7563                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7564                         if (*l == '@' && IS_AOP_PREG(result)) {
7565                                 pic14_emitcode("mov","a,%s",l);
7566                                 aopPut(AOP(result),"a",offset);
7567                         } else
7568                         aopPut(AOP(result),l,offset);
7569                         */
7570                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7571                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7572                         
7573                         offset++;
7574                 }
7575         }
7576         
7577         /* mov the highest order bit to OVR */    
7578         tlbl = newiTempLabel(NULL);
7579         tlbl1= newiTempLabel(NULL);
7580         
7581         size = AOP_SIZE(result);
7582         offset = size - 1;
7583         
7584         pctemp = popGetTempReg();  /* grab a temporary working register. */
7585         
7586         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7587         
7588         /* offset should be 0, 1 or 3 */
7589         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7590         emitSKPNZ;
7591         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7592         
7593         emitpcode(POC_MOVWF, pctemp);
7594         
7595         
7596         emitpLabel(tlbl->key);
7597         
7598         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7599         emitpcode(POC_RRF,   popGet(AOP(result),offset));
7600         
7601         while(--size) {
7602                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7603         }
7604         
7605         emitpcode(POC_DECFSZ,  pctemp);
7606         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7607         emitpLabel(tlbl1->key);
7608         
7609         popReleaseTempReg(pctemp);
7610 #if 0
7611         size = AOP_SIZE(result);
7612         offset = size - 1;
7613         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7614         pic14_emitcode("rlc","a");
7615         pic14_emitcode("mov","ov,c");
7616         /* if it is only one byte then */
7617         if (size == 1) {
7618                 l = aopGet(AOP(left),0,FALSE,FALSE);
7619                 MOVA(l);
7620                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7621                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7622                 pic14_emitcode("mov","c,ov");
7623                 pic14_emitcode("rrc","a");
7624                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7625                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7626                 aopPut(AOP(result),"a",0);
7627                 goto release ;
7628         }
7629         
7630         reAdjustPreg(AOP(result));
7631         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7632         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7633         pic14_emitcode("mov","c,ov");
7634         while (size--) {
7635                 l = aopGet(AOP(result),offset,FALSE,FALSE);
7636                 MOVA(l);
7637                 pic14_emitcode("rrc","a");         
7638                 aopPut(AOP(result),"a",offset--);
7639         }
7640         reAdjustPreg(AOP(result));
7641         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7642         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7643         
7644 release:
7645 #endif
7646         
7647         freeAsmop(left,NULL,ic,TRUE);
7648         freeAsmop(result,NULL,ic,TRUE);
7649         freeAsmop(right,NULL,ic,TRUE);
7650 }
7651
7652 /*-----------------------------------------------------------------*/
7653 /* genRightShift - generate code for right shifting                */
7654 /*-----------------------------------------------------------------*/
7655 static void genRightShift (iCode *ic)
7656 {
7657         operand *right, *left, *result;
7658         sym_link *retype ;
7659         int size, offset;
7660         char *l;
7661         symbol *tlbl, *tlbl1 ;
7662         
7663         /* if signed then we do it the hard way preserve the
7664         sign bit moving it inwards */
7665         retype = getSpec(operandType(IC_RESULT(ic)));
7666         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7667         
7668         if (!SPEC_USIGN(retype)) {
7669                 genSignedRightShift (ic);
7670                 return ;
7671         }
7672         
7673         /* signed & unsigned types are treated the same : i.e. the
7674         signed is NOT propagated inwards : quoting from the
7675         ANSI - standard : "for E1 >> E2, is equivalent to division
7676         by 2**E2 if unsigned or if it has a non-negative value,
7677         otherwise the result is implementation defined ", MY definition
7678         is that the sign does not get propagated */
7679         
7680         right = IC_RIGHT(ic);
7681         left  = IC_LEFT(ic);
7682         result = IC_RESULT(ic);
7683         
7684         aopOp(right,ic,FALSE);
7685         
7686         /* if the shift count is known then do it 
7687         as efficiently as possible */
7688         if (AOP_TYPE(right) == AOP_LIT) {
7689                 genRightShiftLiteral (left,right,result,ic, 0);
7690                 return ;
7691         }
7692         
7693         /* shift count is unknown then we have to form 
7694         a loop get the loop count in B : Note: we take
7695         only the lower order byte since shifting
7696         more that 32 bits make no sense anyway, ( the
7697         largest size of an object can be only 32 bits ) */  
7698         
7699         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7700         pic14_emitcode("inc","b");
7701         aopOp(left,ic,FALSE);
7702         aopOp(result,ic,FALSE);
7703         
7704         /* now move the left to the result if they are not the
7705         same */
7706         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7707                 AOP_SIZE(result) > 1) {
7708                 
7709                 size = AOP_SIZE(result);
7710                 offset=0;
7711                 while (size--) {
7712                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7713                         if (*l == '@' && IS_AOP_PREG(result)) {
7714                                 
7715                                 pic14_emitcode("mov","a,%s",l);
7716                                 aopPut(AOP(result),"a",offset);
7717                         } else
7718                                 aopPut(AOP(result),l,offset);
7719                         offset++;
7720                 }
7721         }
7722         
7723         tlbl = newiTempLabel(NULL);
7724         tlbl1= newiTempLabel(NULL);
7725         size = AOP_SIZE(result);
7726         offset = size - 1;
7727         
7728         /* if it is only one byte then */
7729         if (size == 1) {
7730                 
7731                 tlbl = newiTempLabel(NULL);
7732                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7733                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7734                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7735                 }
7736                 
7737                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7738                 emitpcode(POC_RLF,    popGet(AOP(result),0));
7739                 emitpLabel(tlbl->key);
7740                 emitpcode(POC_RRF,    popGet(AOP(result),0));
7741                 emitpcode(POC_ADDLW,  popGetLit(1));
7742                 emitSKPC;
7743                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7744                 
7745                 goto release ;
7746         }
7747         
7748         reAdjustPreg(AOP(result));
7749         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7750         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7751         CLRC;
7752         while (size--) {
7753                 l = aopGet(AOP(result),offset,FALSE,FALSE);
7754                 MOVA(l);
7755                 pic14_emitcode("rrc","a");         
7756                 aopPut(AOP(result),"a",offset--);
7757         }
7758         reAdjustPreg(AOP(result));
7759         
7760         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7761         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7762         
7763 release:
7764         freeAsmop(left,NULL,ic,TRUE);
7765         freeAsmop (right,NULL,ic,TRUE);
7766         freeAsmop(result,NULL,ic,TRUE);
7767 }
7768
7769 /*-----------------------------------------------------------------*/
7770 /* genUnpackBits - generates code for unpacking bits               */
7771 /*-----------------------------------------------------------------*/
7772 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
7773 {    
7774         int shCnt;
7775         int offset = 0;       /* result byte offset */
7776         int rsize;            /* result size */
7777         int rlen = 0;         /* remaining bitfield length */
7778         sym_link *etype;      /* bitfield type information */
7779         int blen;             /* bitfield length */
7780         int bstr;             /* bitfield starting bit within byte */
7781
7782         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7783         etype = getSpec(operandType(result));
7784         rsize = getSize (operandType (result));
7785         blen = SPEC_BLEN (etype);
7786         bstr = SPEC_BSTR (etype);
7787         
7788         /* single bit field case */
7789         if (blen == 1) {
7790                 if (ifx) { /* that is for an if statement */
7791                         pCodeOp *pcop;
7792                         resolvedIfx rIfx;
7793                         resolveIfx(&rIfx,ifx);
7794                         if (ptype == -1) /* direct */
7795                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
7796                         else
7797                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7798                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
7799                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
7800                         ifx->generated=1;
7801                 } else {
7802                         pCodeOp *pcop;
7803                         if (ptype == -1) /* direct */
7804                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
7805                         else
7806                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7807                         emitpcode(POC_BTFSC,pcop);
7808                         emitpcode(POC_BSF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
7809
7810                         if (ptype == -1) /* direct */
7811                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
7812                         else
7813                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
7814                         emitpcode(POC_BTFSS,pcop);
7815                         emitpcode(POC_BCF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
7816                 }
7817                 return;
7818         }
7819
7820         /* read the first byte  */
7821         switch (ptype) {
7822                 
7823         case POINTER:
7824         case IPOINTER:
7825 //              pic14_emitcode("mov","a,@%s",rname);
7826                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
7827                 break;
7828                 
7829         case PPOINTER:
7830                 pic14_emitcode("movx","a,@%s",rname);
7831                 break;
7832                 
7833         case FPOINTER:
7834                 pic14_emitcode("movx","a,@dptr");
7835                 break;
7836                 
7837         case CPOINTER:
7838                 pic14_emitcode("clr","a");
7839                 pic14_emitcode("movc","a","@a+dptr");
7840                 break;
7841                 
7842         case GPOINTER:
7843                 pic14_emitcode("lcall","__gptrget");
7844                 break;
7845         }
7846
7847         /* if we have bitdisplacement then it fits   */
7848         /* into this byte completely or if length is */
7849         /* less than a byte                          */
7850         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
7851                 
7852                 /* shift right acc */
7853                 AccRsh(left,0,shCnt);
7854                 
7855                 pic14_emitcode("anl","a,#0x%02x",
7856                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7857                 aopPut(AOP(result),"a",offset);
7858                 return ;
7859         }
7860         
7861         /* bit field did not fit in a byte  */
7862         rlen = SPEC_BLEN(etype) - 8;
7863         aopPut(AOP(result),"a",offset++);
7864         
7865         while (1)  {
7866                 
7867                 switch (ptype) {
7868                 case POINTER:
7869                 case IPOINTER:
7870                         pic14_emitcode("inc","%s",rname);
7871                         pic14_emitcode("mov","a,@%s",rname);
7872                         break;
7873                         
7874                 case PPOINTER:
7875                         pic14_emitcode("inc","%s",rname);
7876                         pic14_emitcode("movx","a,@%s",rname);
7877                         break;
7878                         
7879                 case FPOINTER:
7880                         pic14_emitcode("inc","dptr");
7881                         pic14_emitcode("movx","a,@dptr");
7882                         break;
7883                         
7884                 case CPOINTER:
7885                         pic14_emitcode("clr","a");
7886                         pic14_emitcode("inc","dptr");
7887                         pic14_emitcode("movc","a","@a+dptr");
7888                         break;
7889                         
7890                 case GPOINTER:
7891                         pic14_emitcode("inc","dptr");
7892                         pic14_emitcode("lcall","__gptrget");
7893                         break;
7894                 }
7895                 
7896                 rlen -= 8;            
7897                 /* if we are done */
7898                 if ( rlen <= 0 )
7899                         break ;
7900                 
7901                 aopPut(AOP(result),"a",offset++);
7902                 
7903         }
7904         
7905         if (rlen) {
7906                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7907                 aopPut(AOP(result),"a",offset);        
7908         }
7909         
7910         return ;
7911 }
7912
7913 #if 0
7914 /*-----------------------------------------------------------------*/
7915 /* genDataPointerGet - generates code when ptr offset is known     */
7916 /*-----------------------------------------------------------------*/
7917 static void genDataPointerGet (operand *left, 
7918                                                            operand *result, 
7919                                                            iCode *ic)
7920 {
7921         int size , offset = 0;
7922         
7923         
7924         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7925         
7926         
7927         /* optimization - most of the time, left and result are the same
7928         * address, but different types. for the pic code, we could omit
7929         * the following
7930         */
7931         
7932         aopOp(result,ic,TRUE);
7933         
7934         DEBUGpic14_AopType(__LINE__,left,NULL,result);
7935         
7936         emitpcode(POC_MOVFW, popGet(AOP(left),0));
7937         
7938         size = AOP_SIZE(result);
7939         
7940         while (size--) {
7941                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7942                 offset++;
7943         }
7944         
7945         freeAsmop(left,NULL,ic,TRUE);
7946         freeAsmop(result,NULL,ic,TRUE);
7947 }
7948 #endif
7949 /*-----------------------------------------------------------------*/
7950 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
7951 /*-----------------------------------------------------------------*/
7952 static void genNearPointerGet (operand *left, 
7953                                                            operand *result, 
7954                                                            iCode *ic)
7955 {
7956         asmop *aop = NULL;
7957         sym_link *ltype = operandType(left);
7958         sym_link *rtype = operandType(result);
7959         sym_link *retype= getSpec(rtype);      /* bitfield type information */
7960         int direct = 0;
7961
7962         
7963         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964         
7965         
7966         aopOp(left,ic,FALSE);
7967         
7968         /* if left is rematerialisable and
7969         result is not bit variable type and
7970         the left is pointer to data space i.e
7971         lower 128 bytes of space */
7972         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7973                 !IS_BITVAR(retype)         &&
7974                 DCL_TYPE(ltype) == POINTER) {
7975                 //genDataPointerGet (left,result,ic);
7976                 return ;
7977         }
7978         
7979         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7980         aopOp (result,ic,FALSE);
7981         
7982         /* Check if can access directly instead of via a pointer */
7983         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
7984                 direct = 1;
7985         }
7986
7987         /* If the pointer value is not in a the FSR then need to put it in */
7988         if (!AOP_INPREG(AOP(left)) && !direct) {
7989                 /* otherwise get a free pointer register */
7990                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7991                 if (PCOP(AOP(result))->type == PO_LITERAL) 
7992                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
7993                 else
7994                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
7995                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
7996         }
7997         
7998         
7999 //      sym_link *etype;
8000         /* if bitfield then unpack the bits */
8001         if (IS_BITFIELD(retype)) 
8002                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8003         else {
8004                 /* we have can just get the values */
8005                 int size = AOP_SIZE(result);
8006                 int offset = 0 ;  
8007                 
8008                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8009                 
8010                 while(size--) {
8011                         if (direct)
8012                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8013                         else
8014                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8015                         if (AOP_TYPE(result) == AOP_LIT) {
8016                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8017                         } else {
8018                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8019                         }
8020                         if (size && !direct)
8021                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8022                         offset++;
8023                 }
8024         }
8025         
8026         /* now some housekeeping stuff */
8027         if (aop) {
8028                 /* we had to allocate for this iCode */
8029                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8030                 freeAsmop(NULL,aop,ic,TRUE);
8031         } else { 
8032                 /* we did not allocate which means left
8033                 already in a pointer register, then
8034                 if size > 0 && this could be used again
8035                 we have to point it back to where it 
8036                 belongs */
8037                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8038                 if (AOP_SIZE(result) > 1 &&
8039                         !OP_SYMBOL(left)->remat &&
8040                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8041                         ic->depth )) {
8042                         int size = AOP_SIZE(result) - 1;
8043                         while (size--)
8044                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8045                 }
8046         }
8047         
8048         /* done */
8049         freeAsmop(left,NULL,ic,TRUE);
8050         freeAsmop(result,NULL,ic,TRUE);
8051
8052 }
8053
8054 /*-----------------------------------------------------------------*/
8055 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8056 /*-----------------------------------------------------------------*/
8057 static void genPagedPointerGet (operand *left, 
8058                                                                 operand *result, 
8059                                                                 iCode *ic)
8060 {
8061         asmop *aop = NULL;
8062         regs *preg = NULL ;
8063         char *rname ;
8064         sym_link *rtype, *retype;    
8065         
8066         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8067         
8068         rtype = operandType(result);
8069         retype= getSpec(rtype);
8070         
8071         aopOp(left,ic,FALSE);
8072         
8073         /* if the value is already in a pointer register
8074         then don't need anything more */
8075         if (!AOP_INPREG(AOP(left))) {
8076                 /* otherwise get a free pointer register */
8077                 aop = newAsmop(0);
8078                 preg = getFreePtr(ic,&aop,FALSE);
8079                 pic14_emitcode("mov","%s,%s",
8080                         preg->name,
8081                         aopGet(AOP(left),0,FALSE,TRUE));
8082                 rname = preg->name ;
8083         } else
8084                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8085         
8086         freeAsmop(left,NULL,ic,TRUE);
8087         aopOp (result,ic,FALSE);
8088         
8089         /* if bitfield then unpack the bits */
8090         if (IS_BITFIELD(retype)) 
8091                 genUnpackBits (result,left,rname,PPOINTER,0);
8092         else {
8093                 /* we have can just get the values */
8094                 int size = AOP_SIZE(result);
8095                 int offset = 0 ;  
8096                 
8097                 while (size--) {
8098                         
8099                         pic14_emitcode("movx","a,@%s",rname);
8100                         aopPut(AOP(result),"a",offset);
8101                         
8102                         offset++ ;
8103                         
8104                         if (size)
8105                                 pic14_emitcode("inc","%s",rname);
8106                 }
8107         }
8108         
8109         /* now some housekeeping stuff */
8110         if (aop) {
8111                 /* we had to allocate for this iCode */
8112                 freeAsmop(NULL,aop,ic,TRUE);
8113         } else { 
8114         /* we did not allocate which means left
8115         already in a pointer register, then
8116         if size > 0 && this could be used again
8117         we have to point it back to where it 
8118                 belongs */
8119                 if (AOP_SIZE(result) > 1 &&
8120                         !OP_SYMBOL(left)->remat &&
8121                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8122                         ic->depth )) {
8123                         int size = AOP_SIZE(result) - 1;
8124                         while (size--)
8125                                 pic14_emitcode("dec","%s",rname);
8126                 }
8127         }
8128         
8129         /* done */
8130         freeAsmop(result,NULL,ic,TRUE);
8131         
8132         
8133 }
8134
8135 /*-----------------------------------------------------------------*/
8136 /* genFarPointerGet - gget value from far space                    */
8137 /*-----------------------------------------------------------------*/
8138 static void genFarPointerGet (operand *left,
8139                                                           operand *result, iCode *ic)
8140 {
8141         int size, offset ;
8142         sym_link *retype = getSpec(operandType(result));
8143         
8144         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8145         
8146         aopOp(left,ic,FALSE);
8147         
8148         /* if the operand is already in dptr 
8149         then we do nothing else we move the value to dptr */
8150         if (AOP_TYPE(left) != AOP_STR) {
8151                 /* if this is remateriazable */
8152                 if (AOP_TYPE(left) == AOP_IMMD)
8153                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8154                 else { /* we need to get it byte by byte */
8155                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8156                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8157                         if (options.model == MODEL_FLAT24)
8158                         {
8159                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8160                         }
8161                 }
8162         }
8163         /* so dptr know contains the address */
8164         freeAsmop(left,NULL,ic,TRUE);
8165         aopOp(result,ic,FALSE);
8166         
8167         /* if bit then unpack */
8168         if (IS_BITFIELD(retype)) 
8169                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8170         else {
8171                 size = AOP_SIZE(result);
8172                 offset = 0 ;
8173                 
8174                 while (size--) {
8175                         pic14_emitcode("movx","a,@dptr");
8176                         aopPut(AOP(result),"a",offset++);
8177                         if (size)
8178                                 pic14_emitcode("inc","dptr");
8179                 }
8180         }
8181         
8182         freeAsmop(result,NULL,ic,TRUE);
8183 }
8184 #if 0
8185 /*-----------------------------------------------------------------*/
8186 /* genCodePointerGet - get value from code space                  */
8187 /*-----------------------------------------------------------------*/
8188 static void genCodePointerGet (operand *left,
8189                                                            operand *result, iCode *ic)
8190 {
8191         int size, offset ;
8192         sym_link *retype = getSpec(operandType(result));
8193         
8194         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8195         
8196         aopOp(left,ic,FALSE);
8197         
8198         /* if the operand is already in dptr 
8199         then we do nothing else we move the value to dptr */
8200         if (AOP_TYPE(left) != AOP_STR) {
8201                 /* if this is remateriazable */
8202                 if (AOP_TYPE(left) == AOP_IMMD)
8203                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8204                 else { /* we need to get it byte by byte */
8205                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8206                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8207                         if (options.model == MODEL_FLAT24)
8208                         {
8209                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8210                         }
8211                 }
8212         }
8213         /* so dptr know contains the address */
8214         freeAsmop(left,NULL,ic,TRUE);
8215         aopOp(result,ic,FALSE);
8216         
8217         /* if bit then unpack */
8218         if (IS_BITFIELD(retype)) 
8219                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8220         else {
8221                 size = AOP_SIZE(result);
8222                 offset = 0 ;
8223                 
8224                 while (size--) {
8225                         pic14_emitcode("clr","a");
8226                         pic14_emitcode("movc","a,@a+dptr");
8227                         aopPut(AOP(result),"a",offset++);
8228                         if (size)
8229                                 pic14_emitcode("inc","dptr");
8230                 }
8231         }
8232         
8233         freeAsmop(result,NULL,ic,TRUE);
8234 }
8235 #endif
8236 /*-----------------------------------------------------------------*/
8237 /* genGenPointerGet - gget value from generic pointer space        */
8238 /*-----------------------------------------------------------------*/
8239 static void genGenPointerGet (operand *left,
8240                                                           operand *result, iCode *ic)
8241 {
8242         int size, offset ;
8243         sym_link *retype = getSpec(operandType(result));
8244         
8245         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8246         aopOp(left,ic,FALSE);
8247         aopOp(result,ic,FALSE);
8248         
8249         
8250         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8251         
8252         /* if the operand is already in dptr 
8253         then we do nothing else we move the value to dptr */
8254         //  if (AOP_TYPE(left) != AOP_STR) {
8255         /* if this is remateriazable */
8256         if (AOP_TYPE(left) == AOP_IMMD) {
8257                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8258                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8259         }
8260         else { /* we need to get it byte by byte */
8261                 
8262                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8263                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8264                 
8265                 size = AOP_SIZE(result);
8266                 offset = 0 ;
8267                 
8268                 while(size--) {
8269                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8270                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8271                         if(size)
8272                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8273                 }
8274                 goto release;
8275         }
8276         //}
8277         /* so dptr know contains the address */
8278         
8279         /* if bit then unpack */
8280         //if (IS_BITFIELD(retype)) 
8281         //  genUnpackBits(result,"dptr",GPOINTER);
8282         
8283 release:
8284         freeAsmop(left,NULL,ic,TRUE);
8285         freeAsmop(result,NULL,ic,TRUE);
8286         
8287 }
8288
8289 /*-----------------------------------------------------------------*/
8290 /* genConstPointerGet - get value from const generic pointer space */
8291 /*-----------------------------------------------------------------*/
8292 static void genConstPointerGet (operand *left,
8293                                                                 operand *result, iCode *ic)
8294 {
8295         //sym_link *retype = getSpec(operandType(result));
8296         symbol *albl = newiTempLabel(NULL);
8297         symbol *blbl = newiTempLabel(NULL);
8298         PIC_OPCODE poc;
8299         pCodeOp *pcop;
8300         
8301         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8302         aopOp(left,ic,FALSE);
8303         aopOp(result,ic,FALSE);
8304         
8305         
8306         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8307         
8308         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8309         
8310         emitpcode(POC_CALL,popGetLabel(albl->key));
8311         pcop = popGetLabel(blbl->key);
8312         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8313         emitpcode(POC_GOTO,pcop);
8314         emitpLabel(albl->key);
8315         
8316         poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8317         
8318         emitpcode(poc,popGet(AOP(left),1));
8319         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8320         emitpcode(poc,popGet(AOP(left),0));
8321         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8322         
8323         emitpLabel(blbl->key);
8324         
8325         emitpcode(POC_MOVWF,popGet(AOP(result),0));
8326         
8327         
8328         freeAsmop(left,NULL,ic,TRUE);
8329         freeAsmop(result,NULL,ic,TRUE);
8330         
8331 }
8332 /*-----------------------------------------------------------------*/
8333 /* genPointerGet - generate code for pointer get                   */
8334 /*-----------------------------------------------------------------*/
8335 static void genPointerGet (iCode *ic)
8336 {
8337         operand *left, *result ;
8338         sym_link *type, *etype;
8339         int p_type;
8340         
8341         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342         
8343         left = IC_LEFT(ic);
8344         result = IC_RESULT(ic) ;
8345         
8346         /* depending on the type of pointer we need to
8347         move it to the correct pointer register */
8348         type = operandType(left);
8349         etype = getSpec(type);
8350         
8351         if (IS_PTR_CONST(type))
8352                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8353         
8354         /* if left is of type of pointer then it is simple */
8355         if (IS_PTR(type) && !IS_FUNC(type->next)) 
8356                 p_type = DCL_TYPE(type);
8357         else {
8358                 /* we have to go by the storage class */
8359                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8360                 
8361                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8362                 
8363                 if (SPEC_OCLS(etype)->codesp ) {
8364                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8365                         //p_type = CPOINTER ; 
8366                 }
8367                 else
8368                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8369                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8370                         /*p_type = FPOINTER ;*/ 
8371                         else
8372                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8373                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8374                                 /*        p_type = PPOINTER; */
8375                                 else
8376                                         if (SPEC_OCLS(etype) == idata )
8377                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8378                                         /*      p_type = IPOINTER; */
8379                                         else
8380                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8381                                         /*      p_type = POINTER ; */
8382         }
8383         
8384         /* now that we have the pointer type we assign
8385         the pointer values */
8386         switch (p_type) {
8387                 
8388         case POINTER: 
8389         case IPOINTER:
8390                 genNearPointerGet (left,result,ic);
8391                 break;
8392                 
8393         case PPOINTER:
8394                 genPagedPointerGet(left,result,ic);
8395                 break;
8396                 
8397         case FPOINTER:
8398                 genFarPointerGet (left,result,ic);
8399                 break;
8400                 
8401         case CPOINTER:
8402                 genConstPointerGet (left,result,ic);
8403                 //pic14_emitcodePointerGet (left,result,ic);
8404                 break;
8405                 
8406         case GPOINTER:
8407                 if (IS_PTR_CONST(type))
8408                         genConstPointerGet (left,result,ic);
8409                 else
8410                         genGenPointerGet (left,result,ic);
8411                 break;
8412         }
8413         
8414 }
8415
8416 /*-----------------------------------------------------------------*/
8417 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
8418 /* A through a pointer register (R0, R1, or DPTR). The original    */
8419 /* value of A can be preserved in B.                               */
8420 /* PIC has to use INDF register.                                   */
8421 /*-----------------------------------------------------------------*/
8422 static void
8423 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8424 {
8425         switch (p_type)
8426     {
8427     case IPOINTER:
8428     case POINTER:
8429                 if (preserveAinB)
8430                         pic14_emitcode ("mov", "b,a");
8431 //              pic14_emitcode ("mov", "a,@%s", rname);
8432                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8433                 break;
8434                 
8435     case PPOINTER:
8436                 if (preserveAinB)
8437                         pic14_emitcode ("mov", "b,a");
8438                 pic14_emitcode ("movx", "a,@%s", rname);
8439                 break;
8440                 
8441     case FPOINTER:
8442                 if (preserveAinB)
8443                         pic14_emitcode ("mov", "b,a");
8444                 pic14_emitcode ("movx", "a,@dptr");
8445                 break;
8446                 
8447     case CPOINTER:
8448                 if (preserveAinB)
8449                         pic14_emitcode ("mov", "b,a");
8450                 pic14_emitcode ("clr", "a");
8451                 pic14_emitcode ("movc", "a,@a+dptr");
8452                 break;
8453                 
8454     case GPOINTER:
8455                 if (preserveAinB)
8456         {
8457                         pic14_emitcode ("push", "b");
8458                         pic14_emitcode ("push", "acc");
8459         }
8460                 pic14_emitcode ("lcall", "__gptrget");
8461                 if (preserveAinB)
8462                         pic14_emitcode ("pop", "b");
8463                 break;
8464     }
8465 }
8466
8467 /*-----------------------------------------------------------------*/
8468 /* emitPtrByteSet - emits code to set a byte from src through a    */
8469 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8470 /*-----------------------------------------------------------------*/
8471 static void
8472 emitPtrByteSet (char *rname, int p_type, char *src)
8473 {
8474         switch (p_type)
8475     {
8476     case IPOINTER:
8477     case POINTER:
8478                 if (*src=='@')
8479         {
8480                         MOVA (src);
8481                         pic14_emitcode ("mov", "@%s,a", rname);
8482         }
8483                 else
8484 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
8485                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8486                 break;
8487                 
8488     case PPOINTER:
8489                 MOVA (src);
8490                 pic14_emitcode ("movx", "@%s,a", rname);
8491                 break;
8492                 
8493     case FPOINTER:
8494                 MOVA (src);
8495                 pic14_emitcode ("movx", "@dptr,a");
8496                 break;
8497                 
8498     case GPOINTER:
8499                 MOVA (src);
8500                 pic14_emitcode ("lcall", "__gptrput");
8501                 break;
8502     }
8503 }
8504
8505 /*-----------------------------------------------------------------*/
8506 /* genPackBits - generates code for packed bit storage             */
8507 /*-----------------------------------------------------------------*/
8508 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8509 {
8510         int offset = 0;       /* source byte offset */
8511         int rlen = 0;         /* remaining bitfield length */
8512         int blen;             /* bitfield length */
8513         int bstr;             /* bitfield starting bit within byte */
8514         int litval;           /* source literal value (if AOP_LIT) */
8515         unsigned char mask;   /* bitmask within current byte */
8516         
8517         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8518         
8519         blen = SPEC_BLEN (etype);
8520         bstr = SPEC_BSTR (etype);
8521         
8522         /* If the bitfield length is less than a byte */
8523         if (blen < 8)
8524     {
8525                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8526                         (unsigned char) (0xFF >> (8 - bstr)));
8527                 
8528                 if (AOP_TYPE (right) == AOP_LIT)
8529         {
8530                         /* Case with a bitfield length <8 and literal source
8531                         */
8532                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8533                         if (blen == 1) {
8534                                 if (p_type == -1) {
8535                                         pCodeOp *pcop;
8536                                         if (AOP(result)->type == AOP_PCODE)
8537                                                 pcop = newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0);
8538                                         else
8539                                                 pcop = popGet(AOP(result),0);
8540                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
8541                                 } else {
8542                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8543                                 }
8544                                 return;
8545                         } else {
8546                                 litval = lit << bstr;
8547                                 litval &= (~mask) & 0xff;
8548                                 if (p_type == -1)
8549                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8550                                 else
8551                                         emitPtrByteGet (rname, p_type, FALSE);
8552                                 if ((mask|litval)!=0xff)
8553                                         emitpcode(POC_ANDLW,popGetLit(mask));
8554                                 if (litval)
8555                                         emitpcode(POC_IORLW,popGetLit(litval));
8556                         }
8557         }
8558                 else
8559         {
8560                         if (blen==1) {
8561                                 if (p_type == -1) {
8562                                         /* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
8563                                         emitpcode(POC_RLF,popGet(AOP(right),0));
8564                                         emitSKPC;
8565                                         emitpcode(POC_BCF,popGet(AOP(result),0));
8566                                         emitSKPNC;
8567                                         emitpcode(POC_BSF,popGet(AOP(result),0));
8568                                 } else if (p_type!=GPOINTER) {
8569                                         /* Case with a bitfield length == 1 and no generic pointer
8570                                         */
8571                                         if (AOP_TYPE (right) == AOP_CRY)
8572                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8573                                         else
8574                                         {
8575                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8576                                                 pic14_emitcode ("rrc","a");
8577                                         }
8578                                         emitPtrByteGet (rname, p_type, FALSE);
8579                                         pic14_emitcode ("mov","acc.%d,c",bstr);
8580                                 }
8581             }
8582                         else
8583             {
8584                                 //bool pushedB;
8585                                 /* Case with a bitfield length < 8 and arbitrary source
8586                                 */
8587                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8588                                 /* shift and mask source value */
8589                                 AccLsh (right,0,bstr);
8590                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8591                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
8592                                 
8593                                 //pushedB = pushB ();
8594                                 if (p_type == -1)
8595                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8596                                 else
8597                                         emitPtrByteGet (rname, p_type, TRUE);
8598                                 
8599                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
8600                                 pic14_emitcode ("orl", "a,b");
8601                                 emitpcode(POC_ANDLW,popGetLit(mask));
8602                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
8603                                 if (p_type == GPOINTER)
8604                                         pic14_emitcode ("pop", "b");
8605                                 
8606                                 //popB (pushedB);
8607                         }
8608         }
8609                 
8610                 if (p_type == -1)
8611                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
8612                 else
8613                         emitPtrByteSet (rname, p_type, "a");
8614                 return;
8615     }
8616         
8617         /* Bit length is greater than 7 bits. In this case, copy  */
8618         /* all except the partial byte at the end                 */
8619         for (rlen=blen;rlen>=8;rlen-=8)
8620     {
8621                 emitPtrByteSet (rname, p_type,
8622                         aopGet (AOP (right), offset++, FALSE, TRUE) );
8623                 if (rlen>8)
8624                         pic14_emitcode ("inc", "%s", rname);
8625     }
8626         
8627         /* If there was a partial byte at the end */
8628         if (rlen)
8629     {
8630                 mask = (((unsigned char) -1 << rlen) & 0xff);
8631                 
8632                 if (AOP_TYPE (right) == AOP_LIT)
8633         {
8634                 /* Case with partial byte and literal source
8635                         */
8636                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8637                         litval >>= (blen-rlen);
8638                         litval &= (~mask) & 0xff;
8639                         emitPtrByteGet (rname, p_type, FALSE);
8640                         if ((mask|litval)!=0xff)
8641                                 pic14_emitcode ("anl","a,#0x%02x", mask);
8642                         if (litval)
8643                                 pic14_emitcode ("orl","a,#0x%02x", litval);
8644         }
8645                 else
8646         {
8647                         //bool pushedB;
8648                         /* Case with partial byte and arbitrary source
8649                         */
8650                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8651                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8652                         
8653                         //pushedB = pushB ();
8654                         /* transfer A to B and get next byte */
8655                         emitPtrByteGet (rname, p_type, TRUE);
8656                         
8657                         pic14_emitcode ("anl", "a,#0x%02x", mask);
8658                         pic14_emitcode ("orl", "a,b");
8659                         if (p_type == GPOINTER)
8660                                 pic14_emitcode ("pop", "b");
8661                         
8662                         //popB (pushedB);
8663         }
8664                 emitPtrByteSet (rname, p_type, "a");
8665     }
8666         
8667 }
8668
8669 /*-----------------------------------------------------------------*/
8670 /* SetIrp - Set IRP bit                                            */
8671 /*-----------------------------------------------------------------*/
8672 void SetIrp(operand *result) {
8673         if (AOP_TYPE(result) == AOP_LIT) {
8674                 unsigned lit = (unsigned)operandLitValue(result);
8675                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8676         } else {
8677                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8678                         int addrs = PCOL(AOP(result))->lit;
8679                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8680                 } else {
8681                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
8682                         if(AOP_SIZE(result) > 1) {
8683                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8684                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8685                         }
8686                 }
8687         }
8688 }
8689
8690 /*-----------------------------------------------------------------*/
8691 /* genDataPointerSet - remat pointer to data space                 */
8692 /*-----------------------------------------------------------------*/
8693 static void genDataPointerSet(operand *right,
8694                                                           operand *result,
8695                                                           iCode *ic)
8696 {
8697         int size, offset = 0 ;
8698         char *l, buffer[256];
8699         
8700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701         aopOp(right,ic,FALSE);
8702         
8703         l = aopGet(AOP(result),0,FALSE,TRUE);
8704         size = AOP_SIZE(right);
8705         /*
8706         if ( AOP_TYPE(result) == AOP_PCODE) {
8707         fprintf(stderr,"genDataPointerSet   %s, %d\n",
8708         AOP(result)->aopu.pcop->name,
8709         PCOI(AOP(result)->aopu.pcop)->offset);
8710         }
8711         */
8712         
8713         // tsd, was l+1 - the underline `_' prefix was being stripped
8714         while (size--) {
8715                 if (offset) {
8716                         sprintf(buffer,"(%s + %d)",l,offset);
8717                         fprintf(stderr,"oops  %s\n",buffer);
8718                 } else
8719                         sprintf(buffer,"%s",l);
8720                 
8721                 if (AOP_TYPE(right) == AOP_LIT) {
8722                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8723                         lit = lit >> (8*offset);
8724                         if(lit&0xff) {
8725                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8726                                 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8727                         } else {
8728                                 emitpcode(POC_CLRF, popGet(AOP(result),0));
8729                         }
8730                 } else {
8731                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8732                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
8733                 }
8734                 
8735                 offset++;
8736         }
8737         
8738         freeAsmop(right,NULL,ic,TRUE);
8739         freeAsmop(result,NULL,ic,TRUE);
8740 }
8741
8742 /*-----------------------------------------------------------------*/
8743 /* genNearPointerSet - pic14_emitcode for near pointer put         */
8744 /*-----------------------------------------------------------------*/
8745 static void genNearPointerSet (operand *right,
8746                                                            operand *result, 
8747                                                            iCode *ic)
8748 {
8749         asmop *aop = NULL;
8750         sym_link *ptype = operandType(result);
8751         sym_link *retype = getSpec(operandType(right));
8752         sym_link *letype = getSpec(ptype);
8753         int direct = 0;
8754         
8755         
8756         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8757         aopOp(result,ic,FALSE);
8758         
8759         
8760         /* if the result is rematerializable &
8761         in data space & not a bit variable */
8762         //if (AOP_TYPE(result) == AOP_IMMD &&
8763         if (AOP_TYPE(result) == AOP_PCODE &&
8764                 DCL_TYPE(ptype) == POINTER   &&
8765                 !IS_BITVAR (retype) &&
8766                 !IS_BITVAR (letype)) {
8767                 genDataPointerSet (right,result,ic);
8768                 freeAsmop(result,NULL,ic,TRUE);
8769                 return;
8770         }
8771
8772         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8773         aopOp(right,ic,FALSE);
8774         DEBUGpic14_AopType(__LINE__,NULL,right,result);
8775         
8776         /* Check if can access directly instead of via a pointer */
8777         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
8778                 direct = 1;
8779         }
8780
8781         /* If the pointer value is not in a the FSR then need to put it in */
8782         if (!AOP_INPREG(AOP(result)) && !direct) {
8783                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8784                 if (PCOP(AOP(result))->type == PO_LITERAL) 
8785                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
8786                 else
8787                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
8788                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8789         }
8790
8791         /* Must set/reset IRP bit for use with FSR. */
8792         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
8793         if (!direct)
8794                 SetIrp(result);
8795
8796         /* if bitfield then unpack the bits */
8797         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
8798                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
8799         } else {
8800                 /* we have can just get the values */
8801                 int size = AOP_SIZE(right);
8802                 int offset = 0 ;    
8803                 
8804                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8805                 while (size--) {
8806                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
8807                         if (*l == '@' ) {
8808                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8809                         } else {
8810                                 if (AOP_TYPE(right) == AOP_LIT) {
8811                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
8812                                 } else {
8813                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
8814                                 }
8815                                 if (direct)
8816                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
8817                                 else
8818                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8819                         }
8820                         if (size && !direct)
8821                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8822                         offset++;
8823                 }
8824         }
8825         
8826         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8827         /* now some housekeeping stuff */
8828         if (aop) {
8829                 /* we had to allocate for this iCode */
8830                 freeAsmop(NULL,aop,ic,TRUE);
8831         } else { 
8832                 /* we did not allocate which means left
8833                 already in a pointer register, then
8834                 if size > 0 && this could be used again
8835                 we have to point it back to where it 
8836                 belongs */
8837                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838                 if (AOP_SIZE(right) > 1 &&
8839                         !OP_SYMBOL(result)->remat &&
8840                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8841                         ic->depth )) {
8842                         int size = AOP_SIZE(right) - 1;
8843                         while (size--)
8844                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8845                 }
8846         }
8847         
8848         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8849         /* done */
8850
8851         freeAsmop(right,NULL,ic,TRUE);
8852         freeAsmop(result,NULL,ic,TRUE);
8853 }
8854
8855 /*-----------------------------------------------------------------*/
8856 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8857 /*-----------------------------------------------------------------*/
8858 static void genPagedPointerSet (operand *right,
8859                                                                 operand *result, 
8860                                                                 iCode *ic)
8861 {
8862         asmop *aop = NULL;
8863         regs *preg = NULL ;
8864         char *rname , *l;
8865         sym_link *retype;
8866         
8867         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8868         
8869         retype= getSpec(operandType(right));
8870         
8871         aopOp(result,ic,FALSE);
8872         
8873         /* if the value is already in a pointer register
8874         then don't need anything more */
8875         if (!AOP_INPREG(AOP(result))) {
8876                 /* otherwise get a free pointer register */
8877                 aop = newAsmop(0);
8878                 preg = getFreePtr(ic,&aop,FALSE);
8879                 pic14_emitcode("mov","%s,%s",
8880                         preg->name,
8881                         aopGet(AOP(result),0,FALSE,TRUE));
8882                 rname = preg->name ;
8883         } else
8884                 rname = aopGet(AOP(result),0,FALSE,FALSE);
8885         
8886         freeAsmop(result,NULL,ic,TRUE);
8887         aopOp (right,ic,FALSE);
8888         
8889         /* if bitfield then unpack the bits */
8890         if (IS_BITFIELD(retype)) 
8891                 genPackBits (retype,result,right,rname,PPOINTER);
8892         else {
8893                 /* we have can just get the values */
8894                 int size = AOP_SIZE(right);
8895                 int offset = 0 ;  
8896                 
8897                 while (size--) {
8898                         l = aopGet(AOP(right),offset,FALSE,TRUE);
8899                         
8900                         MOVA(l);
8901                         pic14_emitcode("movx","@%s,a",rname);
8902                         
8903                         if (size)
8904                                 pic14_emitcode("inc","%s",rname);
8905                         
8906                         offset++;
8907                 }
8908         }
8909         
8910         /* now some housekeeping stuff */
8911         if (aop) {
8912                 /* we had to allocate for this iCode */
8913                 freeAsmop(NULL,aop,ic,TRUE);
8914         } else { 
8915         /* we did not allocate which means left
8916         already in a pointer register, then
8917         if size > 0 && this could be used again
8918         we have to point it back to where it 
8919                 belongs */
8920                 if (AOP_SIZE(right) > 1 &&
8921                         !OP_SYMBOL(result)->remat &&
8922                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8923                         ic->depth )) {
8924                         int size = AOP_SIZE(right) - 1;
8925                         while (size--)
8926                                 pic14_emitcode("dec","%s",rname);
8927                 }
8928         }
8929         
8930         /* done */
8931         freeAsmop(right,NULL,ic,TRUE);
8932         
8933         
8934 }
8935
8936 /*-----------------------------------------------------------------*/
8937 /* genFarPointerSet - set value from far space                     */
8938 /*-----------------------------------------------------------------*/
8939 static void genFarPointerSet (operand *right,
8940                                                           operand *result, iCode *ic)
8941 {
8942         int size, offset ;
8943         sym_link *retype = getSpec(operandType(right));
8944         
8945         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8946         aopOp(result,ic,FALSE);
8947         
8948         /* if the operand is already in dptr 
8949         then we do nothing else we move the value to dptr */
8950         if (AOP_TYPE(result) != AOP_STR) {
8951                 /* if this is remateriazable */
8952                 if (AOP_TYPE(result) == AOP_IMMD)
8953                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8954                 else { /* we need to get it byte by byte */
8955                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8956                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8957                         if (options.model == MODEL_FLAT24)
8958                         {
8959                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8960                         }
8961                 }
8962         }
8963         /* so dptr know contains the address */
8964         freeAsmop(result,NULL,ic,TRUE);
8965         aopOp(right,ic,FALSE);
8966         
8967         /* if bit then unpack */
8968         if (IS_BITFIELD(retype)) 
8969                 genPackBits(retype,result,right,"dptr",FPOINTER);
8970         else {
8971                 size = AOP_SIZE(right);
8972                 offset = 0 ;
8973                 
8974                 while (size--) {
8975                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8976                         MOVA(l);
8977                         pic14_emitcode("movx","@dptr,a");
8978                         if (size)
8979                                 pic14_emitcode("inc","dptr");
8980                 }
8981         }
8982         
8983         freeAsmop(right,NULL,ic,TRUE);
8984 }
8985
8986 /*-----------------------------------------------------------------*/
8987 /* genGenPointerSet - set value from generic pointer space         */
8988 /*-----------------------------------------------------------------*/
8989 static void genGenPointerSet (operand *right,
8990                                                           operand *result, iCode *ic)
8991 {
8992         sym_link *ptype = operandType(result);
8993         sym_link *retype = getSpec(operandType(right));
8994         sym_link *letype = getSpec (ptype);
8995         
8996         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8997         
8998         aopOp(result,ic,FALSE);
8999         aopOp(right,ic,FALSE);
9000         
9001         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9002         
9003         /* if the operand is already in dptr 
9004         then we do nothing else we move the value to dptr */
9005         if (AOP_TYPE(result) != AOP_STR) {
9006                 /* if this is remateriazable */
9007                 if (AOP_TYPE(result) == AOP_IMMD) {
9008                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9009                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9010                 }
9011                 else {
9012                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9013                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9014
9015                         /* Must set/reset IRP bit for use with FSR. */
9016                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9017                         SetIrp(result);
9018                 }
9019         }
9020
9021         /* if bitfield then unpack the bits */
9022         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9023                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9024         } else {
9025                 /* we have can just get the values */
9026                 int size = AOP_SIZE(right);
9027                 int offset = 0 ;    
9028                 
9029                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9030                 while (size--) {
9031                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9032                         if (*l == '@' ) {
9033                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9034                         } else {
9035                                 if (AOP_TYPE(right) == AOP_LIT) {
9036                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9037                                 } else {
9038                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9039                                 }
9040                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9041                         }
9042                         if (size)
9043                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9044                         offset++;
9045                 }
9046         }
9047         
9048         freeAsmop(right,NULL,ic,TRUE);
9049         freeAsmop(result,NULL,ic,TRUE);
9050 }
9051
9052 /*-----------------------------------------------------------------*/
9053 /* genPointerSet - stores the value into a pointer location        */
9054 /*-----------------------------------------------------------------*/
9055 static void genPointerSet (iCode *ic)
9056 {    
9057         operand *right, *result ;
9058         sym_link *type, *etype;
9059         int p_type;
9060         
9061         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9062         
9063         right = IC_RIGHT(ic);
9064         result = IC_RESULT(ic) ;
9065         
9066         /* depending on the type of pointer we need to
9067         move it to the correct pointer register */
9068         type = operandType(result);
9069         etype = getSpec(type);
9070         /* if left is of type of pointer then it is simple */
9071         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9072                 p_type = DCL_TYPE(type);
9073         }
9074         else {
9075                 /* we have to go by the storage class */
9076                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9077                 
9078                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9079                 /*      p_type = CPOINTER ;  */
9080                 /*  } */
9081                 /*  else */
9082                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9083                 /*    p_type = FPOINTER ; */
9084                 /*      else */
9085                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9086                 /*        p_type = PPOINTER ; */
9087                 /*    else */
9088                 /*        if (SPEC_OCLS(etype) == idata ) */
9089                 /*      p_type = IPOINTER ; */
9090                 /*        else */
9091                 /*      p_type = POINTER ; */
9092         }
9093         
9094         /* now that we have the pointer type we assign
9095         the pointer values */
9096         switch (p_type) {
9097                 
9098         case POINTER:
9099         case IPOINTER:
9100                 genNearPointerSet (right,result,ic);
9101                 break;
9102                 
9103         case PPOINTER:
9104                 genPagedPointerSet (right,result,ic);
9105                 break;
9106                 
9107         case FPOINTER:
9108                 genFarPointerSet (right,result,ic);
9109                 break;
9110                 
9111         case GPOINTER:
9112                 genGenPointerSet (right,result,ic);
9113                 break;
9114                 
9115         default:
9116                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9117                         "genPointerSet: illegal pointer type");
9118         }
9119 }
9120
9121 /*-----------------------------------------------------------------*/
9122 /* genIfx - generate code for Ifx statement                        */
9123 /*-----------------------------------------------------------------*/
9124 static void genIfx (iCode *ic, iCode *popIc)
9125 {
9126         operand *cond = IC_COND(ic);
9127         int isbit =0;
9128         
9129         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9130         
9131         aopOp(cond,ic,FALSE);
9132         
9133         /* get the value into acc */
9134         if (AOP_TYPE(cond) != AOP_CRY)
9135                 pic14_toBoolean(cond);
9136         else
9137                 isbit = 1;
9138         /* the result is now in the accumulator */
9139         freeAsmop(cond,NULL,ic,TRUE);
9140         
9141         /* if there was something to be popped then do it */
9142         if (popIc)
9143                 genIpop(popIc);
9144         
9145         /* if the condition is  a bit variable */
9146         if (isbit && IS_ITEMP(cond) && 
9147                 SPIL_LOC(cond)) {
9148                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9149                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9150         }
9151         else {
9152                 if (isbit && !IS_ITEMP(cond))
9153                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9154                 else
9155                         genIfxJump(ic,"a");
9156         }
9157         ic->generated = 1;
9158         
9159 }
9160
9161 /*-----------------------------------------------------------------*/
9162 /* genAddrOf - generates code for address of                       */
9163 /*-----------------------------------------------------------------*/
9164 static void genAddrOf (iCode *ic)
9165 {
9166         operand *right, *result, *left;
9167         int size, offset ;
9168         
9169         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9170         
9171         
9172         //aopOp(IC_RESULT(ic),ic,FALSE);
9173         
9174         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9175         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9176         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9177         
9178         DEBUGpic14_AopType(__LINE__,left,right,result);
9179         
9180         size = AOP_SIZE(IC_RESULT(ic));
9181         offset = 0;
9182         
9183         while (size--) {
9184                 /* fixing bug #863624, reported from (errolv) */
9185                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9186                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9187                 
9188 #if 0
9189                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9190                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9191 #endif
9192                 offset++;
9193         }
9194         
9195         freeAsmop(left,NULL,ic,FALSE);
9196         freeAsmop(result,NULL,ic,TRUE);
9197         
9198 }
9199
9200 #if 0
9201 /*-----------------------------------------------------------------*/
9202 /* genFarFarAssign - assignment when both are in far space         */
9203 /*-----------------------------------------------------------------*/
9204 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9205 {
9206         int size = AOP_SIZE(right);
9207         int offset = 0;
9208         char *l ;
9209         /* first push the right side on to the stack */
9210         while (size--) {
9211                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9212                 MOVA(l);
9213                 pic14_emitcode ("push","acc");
9214         }
9215         
9216         freeAsmop(right,NULL,ic,FALSE);
9217         /* now assign DPTR to result */
9218         aopOp(result,ic,FALSE);
9219         size = AOP_SIZE(result);
9220         while (size--) {
9221                 pic14_emitcode ("pop","acc");
9222                 aopPut(AOP(result),"a",--offset);
9223         }
9224         freeAsmop(result,NULL,ic,FALSE);
9225         
9226 }
9227 #endif
9228
9229 /*-----------------------------------------------------------------*/
9230 /* genAssign - generate code for assignment                        */
9231 /*-----------------------------------------------------------------*/
9232 static void genAssign (iCode *ic)
9233 {
9234         operand *result, *right;
9235         int size, offset,know_W;
9236         unsigned long lit = 0L;
9237         
9238         result = IC_RESULT(ic);
9239         right  = IC_RIGHT(ic) ;
9240         
9241         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9242         
9243         /* if they are the same */
9244         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9245                 return ;
9246         
9247         aopOp(right,ic,FALSE);
9248         aopOp(result,ic,TRUE);
9249         
9250         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9251         
9252         /* if they are the same registers */
9253         if (pic14_sameRegs(AOP(right),AOP(result)))
9254                 goto release;
9255         
9256         /* if the result is a bit */
9257         if (AOP_TYPE(result) == AOP_CRY) {
9258                 
9259         /* if the right size is a literal then
9260                 we know what the value is */
9261                 if (AOP_TYPE(right) == AOP_LIT) {
9262                         
9263                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9264                                 popGet(AOP(result),0));
9265                         
9266                         if (((int) operandLitValue(right))) 
9267                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9268                                 AOP(result)->aopu.aop_dir,
9269                                 AOP(result)->aopu.aop_dir);
9270                         else
9271                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9272                                 AOP(result)->aopu.aop_dir,
9273                                 AOP(result)->aopu.aop_dir);
9274                         goto release;
9275                 }
9276                 
9277                 /* the right is also a bit variable */
9278                 if (AOP_TYPE(right) == AOP_CRY) {
9279                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9280                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9281                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9282                         
9283                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9284                                 AOP(result)->aopu.aop_dir,
9285                                 AOP(result)->aopu.aop_dir);
9286                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9287                                 AOP(right)->aopu.aop_dir,
9288                                 AOP(right)->aopu.aop_dir);
9289                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9290                                 AOP(result)->aopu.aop_dir,
9291                                 AOP(result)->aopu.aop_dir);
9292                         goto release ;
9293                 }
9294                 
9295                 /* we need to or */
9296                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9297                 pic14_toBoolean(right);
9298                 emitSKPZ;
9299                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9300                 //aopPut(AOP(result),"a",0);
9301                 goto release ;
9302         }
9303         
9304         /* bit variables done */
9305         /* general case */
9306         size = AOP_SIZE(result);
9307         offset = 0 ;
9308         if(AOP_TYPE(right) == AOP_LIT)
9309                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9310         
9311         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9312                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9313                 if(aopIdx(AOP(result),0) == 4) {
9314                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9315                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9316                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9317                         goto release;
9318                 } else
9319                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9320         }
9321         
9322         know_W=-1;
9323         while (size--) {
9324                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9325                 if(AOP_TYPE(right) == AOP_LIT) {
9326                         if(lit&0xff) {
9327                                 if(know_W != (int)(lit&0xff))
9328                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9329                                 know_W = lit&0xff;
9330                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9331                         } else
9332                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9333                         
9334                         lit >>= 8;
9335                         
9336                 } else if (AOP_TYPE(right) == AOP_CRY) {
9337                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9338                         if(offset == 0) {
9339                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9340                                 emitpcode(POC_INCF, popGet(AOP(result),0));
9341                         }
9342                 } else {
9343                         mov2w (AOP(right), offset);
9344                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9345                 }
9346                 
9347                 offset++;
9348         }
9349         
9350         
9351 release:
9352         freeAsmop (right,NULL,ic,FALSE);
9353         freeAsmop (result,NULL,ic,TRUE);
9354 }   
9355
9356 /*-----------------------------------------------------------------*/
9357 /* genJumpTab - genrates code for jump table                       */
9358 /*-----------------------------------------------------------------*/
9359 static void genJumpTab (iCode *ic)
9360 {
9361         symbol *jtab;
9362         char *l;
9363         
9364         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9365         
9366         aopOp(IC_JTCOND(ic),ic,FALSE);
9367         /* get the condition into accumulator */
9368         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9369         MOVA(l);
9370         /* multiply by three */
9371         pic14_emitcode("add","a,acc");
9372         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9373         
9374         jtab = newiTempLabel(NULL);
9375         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9376         pic14_emitcode("jmp","@a+dptr");
9377         pic14_emitcode("","%05d_DS_:",jtab->key+100);
9378         
9379         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9380         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9381         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9382         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9383         emitSKPNC;
9384         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9385         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9386         emitpLabel(jtab->key);
9387         
9388         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9389         
9390         /* now generate the jump labels */
9391         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9392         jtab = setNextItem(IC_JTLABELS(ic))) {
9393                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9394                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9395                 
9396         }
9397         
9398 }
9399
9400 /*-----------------------------------------------------------------*/
9401 /* genMixedOperation - gen code for operators between mixed types  */
9402 /*-----------------------------------------------------------------*/
9403 /*
9404 TSD - Written for the PIC port - but this unfortunately is buggy.
9405 This routine is good in that it is able to efficiently promote 
9406 types to different (larger) sizes. Unfortunately, the temporary
9407 variables that are optimized out by this routine are sometimes
9408 used in other places. So until I know how to really parse the 
9409 iCode tree, I'm going to not be using this routine :(.
9410 */
9411 static int genMixedOperation (iCode *ic)
9412 {
9413 #if 0
9414         operand *result = IC_RESULT(ic);
9415         sym_link *ctype = operandType(IC_LEFT(ic));
9416         operand *right = IC_RIGHT(ic);
9417         int ret = 0;
9418         int big,small;
9419         int offset;
9420         
9421         iCode *nextic;
9422         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9423         
9424         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9425         
9426         nextic = ic->next;
9427         if(!nextic)
9428                 return 0;
9429         
9430         nextright = IC_RIGHT(nextic);
9431         nextleft  = IC_LEFT(nextic);
9432         nextresult = IC_RESULT(nextic);
9433         
9434         aopOp(right,ic,FALSE);
9435         aopOp(result,ic,FALSE);
9436         aopOp(nextright,  nextic, FALSE);
9437         aopOp(nextleft,   nextic, FALSE);
9438         aopOp(nextresult, nextic, FALSE);
9439         
9440         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9441                 
9442                 operand *t = right;
9443                 right = nextright;
9444                 nextright = t; 
9445                 
9446                 pic14_emitcode(";remove right +","");
9447                 
9448         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9449         /*
9450         operand *t = right;
9451         right = nextleft;
9452         nextleft = t; 
9453                 */
9454                 pic14_emitcode(";remove left +","");
9455         } else
9456                 return 0;
9457         
9458         big = AOP_SIZE(nextleft);
9459         small = AOP_SIZE(nextright);
9460         
9461         switch(nextic->op) {
9462                 
9463         case '+':
9464                 pic14_emitcode(";optimize a +","");
9465                 /* if unsigned or not an integral type */
9466                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9467                         pic14_emitcode(";add a bit to something","");
9468                 } else {
9469                         
9470                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9471                         
9472                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9473                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9474                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9475                         } else
9476                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9477                         
9478                         offset = 0;
9479                         while(--big) {
9480                                 
9481                                 offset++;
9482                                 
9483                                 if(--small) {
9484                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9485                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9486                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9487                                         }
9488                                         
9489                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9490                                         emitSKPNC;
9491                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9492                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9493                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9494                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9495                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9496                                         
9497                                 } else {
9498                                         pic14_emitcode("rlf","known_zero,w");
9499                                         
9500                                         /*
9501                                         if right is signed
9502                                         btfsc  right,7
9503                                         addlw ff
9504                                         */
9505                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9506                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9507                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9508                                         } else {
9509                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9510                                         }
9511                                 }
9512                         }
9513                         ret = 1;
9514                 }
9515         }
9516         ret = 1;
9517         
9518 release:
9519         freeAsmop(right,NULL,ic,TRUE);
9520         freeAsmop(result,NULL,ic,TRUE);
9521         freeAsmop(nextright,NULL,ic,TRUE);
9522         freeAsmop(nextleft,NULL,ic,TRUE);
9523         if(ret)
9524                 nextic->generated = 1;
9525         
9526         return ret;
9527 #else
9528         return 0;
9529 #endif
9530 }
9531 /*-----------------------------------------------------------------*/
9532 /* genCast - gen code for casting                                  */
9533 /*-----------------------------------------------------------------*/
9534 static void genCast (iCode *ic)
9535 {
9536         operand *result = IC_RESULT(ic);
9537         sym_link *ctype = operandType(IC_LEFT(ic));
9538         sym_link *rtype = operandType(IC_RIGHT(ic));
9539         operand *right = IC_RIGHT(ic);
9540         int size, offset ;
9541         
9542         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9543         /* if they are equivalent then do nothing */
9544         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9545                 return ;
9546         
9547         aopOp(right,ic,FALSE) ;
9548         aopOp(result,ic,FALSE);
9549         
9550         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9551         
9552         /* if the result is a bit */
9553         if (AOP_TYPE(result) == AOP_CRY) {
9554         /* if the right size is a literal then
9555                 we know what the value is */
9556                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9557                 if (AOP_TYPE(right) == AOP_LIT) {
9558                         
9559                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9560                                 popGet(AOP(result),0));
9561                         
9562                         if (((int) operandLitValue(right))) 
9563                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9564                                 AOP(result)->aopu.aop_dir,
9565                                 AOP(result)->aopu.aop_dir);
9566                         else
9567                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9568                                 AOP(result)->aopu.aop_dir,
9569                                 AOP(result)->aopu.aop_dir);
9570                         
9571                         goto release;
9572                 }
9573                 
9574                 /* the right is also a bit variable */
9575                 if (AOP_TYPE(right) == AOP_CRY) {
9576                         
9577                         emitCLRC;
9578                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9579                         
9580                         pic14_emitcode("clrc","");
9581                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9582                                 AOP(right)->aopu.aop_dir,
9583                                 AOP(right)->aopu.aop_dir);
9584                         aopPut(AOP(result),"c",0);
9585                         goto release ;
9586                 }
9587                 
9588                 /* we need to or */
9589                 if (AOP_TYPE(right) == AOP_REG) {
9590                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9591                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9592                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9593                 }
9594                 pic14_toBoolean(right);
9595                 aopPut(AOP(result),"a",0);
9596                 goto release ;
9597         }
9598         
9599         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9600                 int offset = 1;
9601                 size = AOP_SIZE(result);
9602                 
9603                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9604                 
9605                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
9606                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9607                 emitpcode(POC_INCF,   popGet(AOP(result),0));
9608                 
9609                 while (size--)
9610                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9611                 
9612                 goto release;
9613         }
9614         
9615         /* if they are the same size : or less */
9616         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9617                 
9618                 /* if they are in the same place */
9619                 if (pic14_sameRegs(AOP(right),AOP(result)))
9620                         goto release;
9621                 
9622                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9623                 if (IS_PTR_CONST(rtype))
9624                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9625                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9626                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9627                 
9628                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9629                         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9630                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9631                         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9632                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9633                         if(AOP_SIZE(result) <2)
9634                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9635                         
9636                 } else {
9637                         
9638                         /* if they in different places then copy */
9639                         size = AOP_SIZE(result);
9640                         offset = 0 ;
9641                         while (size--) {
9642                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9643                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9644                                 
9645                                 //aopPut(AOP(result),
9646                                 // aopGet(AOP(right),offset,FALSE,FALSE),
9647                                 // offset);
9648                                 
9649                                 offset++;
9650                         }
9651                 }
9652                 goto release;
9653         }
9654         
9655         
9656         /* if the result is of type pointer */
9657         if (IS_PTR(ctype)) {
9658                 
9659                 int p_type;
9660                 sym_link *type = operandType(right);
9661                 sym_link *etype = getSpec(type);
9662                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9663                 
9664                 /* pointer to generic pointer */
9665                 if (IS_GENPTR(ctype)) {
9666                         char *l = zero;
9667                         
9668                         if (IS_PTR(type)) 
9669                                 p_type = DCL_TYPE(type);
9670                         else {
9671                                 /* we have to go by the storage class */
9672                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9673                                 
9674                                 /*    if (SPEC_OCLS(etype)->codesp )  */
9675                                 /*        p_type = CPOINTER ;  */
9676                                 /*    else */
9677                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9678                                 /*      p_type = FPOINTER ; */
9679                                 /*        else */
9680                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9681                                 /*          p_type = PPOINTER; */
9682                                 /*      else */
9683                                 /*          if (SPEC_OCLS(etype) == idata ) */
9684                                 /*        p_type = IPOINTER ; */
9685                                 /*          else */
9686                                 /*        p_type = POINTER ; */
9687                         }
9688                         
9689                         /* the first two bytes are known */
9690                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9691                         size = GPTRSIZE - 1; 
9692                         offset = 0 ;
9693                         while (size--) {
9694                                 if(offset < AOP_SIZE(right)) {
9695                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9696                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
9697                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9698                                                 emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9699                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9700                                         } else { 
9701                                                 aopPut(AOP(result),
9702                                                         aopGet(AOP(right),offset,FALSE,FALSE),
9703                                                         offset);
9704                                         }
9705                                 } else 
9706                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
9707                                 offset++;
9708                         }
9709                         /* the last byte depending on type */
9710                         switch (p_type) {
9711                         case IPOINTER:
9712                         case POINTER:
9713                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9714                                 break;
9715                         case FPOINTER:
9716                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
9717                                 l = one;
9718                                 break;
9719                         case CPOINTER:
9720                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
9721                                 l = "#0x02";
9722                                 break;        
9723                         case PPOINTER:
9724                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
9725                                 l = "#0x03";
9726                                 break;
9727                                 
9728                         default:
9729                                 /* this should never happen */
9730                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9731                                         "got unknown pointer type");
9732                                 exit(1);
9733                         }
9734                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
9735                         goto release ;
9736                 }
9737                 
9738                 /* just copy the pointers */
9739                 size = AOP_SIZE(result);
9740                 offset = 0 ;
9741                 while (size--) {
9742                         aopPut(AOP(result),
9743                                 aopGet(AOP(right),offset,FALSE,FALSE),
9744                                 offset);
9745                         offset++;
9746                 }
9747                 goto release ;
9748         }
9749         
9750         
9751         
9752         /* so we now know that the size of destination is greater
9753         than the size of the source.
9754         Now, if the next iCode is an operator then we might be
9755         able to optimize the operation without performing a cast.
9756         */
9757         if(genMixedOperation(ic))
9758                 goto release;
9759         
9760         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9761         
9762         /* we move to result for the size of source */
9763         size = AOP_SIZE(right);
9764         offset = 0 ;
9765         while (size--) {
9766                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9767                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9768                 offset++;
9769         }
9770         
9771         /* now depending on the sign of the destination */
9772         size = AOP_SIZE(result) - AOP_SIZE(right);
9773         /* if unsigned or not an integral type */
9774         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9775                 while (size--)
9776                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9777         } else {
9778                 /* we need to extend the sign :{ */
9779                 
9780                 if(size == 1) {
9781                         /* Save one instruction of casting char to int */
9782                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9783                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9784                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9785                 } else {
9786                         emitpcodeNULLop(POC_CLRW);
9787                         
9788                         if(offset)
9789                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9790                         else
9791                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9792                         
9793                         emitpcode(POC_MOVLW,   popGetLit(0xff));
9794                         
9795                         while (size--)
9796                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9797                 }
9798         }
9799         
9800 release:
9801         freeAsmop(right,NULL,ic,TRUE);
9802         freeAsmop(result,NULL,ic,TRUE);
9803         
9804 }
9805
9806 /*-----------------------------------------------------------------*/
9807 /* genDjnz - generate decrement & jump if not zero instrucion      */
9808 /*-----------------------------------------------------------------*/
9809 static int genDjnz (iCode *ic, iCode *ifx)
9810 {
9811         symbol *lbl, *lbl1;
9812         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9813         
9814         if (!ifx)
9815                 return 0;
9816         
9817                 /* if the if condition has a false label
9818         then we cannot save */
9819         if (IC_FALSE(ifx))
9820                 return 0;
9821         
9822                 /* if the minus is not of the form 
9823         a = a - 1 */
9824         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9825                 !IS_OP_LITERAL(IC_RIGHT(ic)))
9826                 return 0;
9827         
9828         if (operandLitValue(IC_RIGHT(ic)) != 1)
9829                 return 0;
9830         
9831                 /* if the size of this greater than one then no
9832         saving */
9833         if (getSize(operandType(IC_RESULT(ic))) > 1)
9834                 return 0;
9835         
9836         /* otherwise we can save BIG */
9837         lbl = newiTempLabel(NULL);
9838         lbl1= newiTempLabel(NULL);
9839         
9840         aopOp(IC_RESULT(ic),ic,FALSE);
9841         
9842         if (IS_AOP_PREG(IC_RESULT(ic))) {
9843                 pic14_emitcode("dec","%s",
9844                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9845                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9846                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9847         } else {  
9848                 
9849                 
9850                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9851                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9852                 
9853                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9854                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9855                 
9856         }
9857         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9858         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9859         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9860         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9861         
9862         
9863         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9864         ifx->generated = 1;
9865         return 1;
9866 }
9867
9868 /*-----------------------------------------------------------------*/
9869 /* genReceive - generate code for a receive iCode                  */
9870 /*-----------------------------------------------------------------*/
9871 static void genReceive (iCode *ic)
9872 {
9873         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9874         
9875         if (isOperandInFarSpace(IC_RESULT(ic)) &&
9876                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9877                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9878                 
9879                 int size = getSize(operandType(IC_RESULT(ic)));
9880                 int offset =  fReturnSizePic - size;
9881                 while (size--) {
9882                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9883                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
9884                         offset++;
9885                 }
9886                 aopOp(IC_RESULT(ic),ic,FALSE);
9887                 size = AOP_SIZE(IC_RESULT(ic));
9888                 offset = 0;
9889                 while (size--) {
9890                         pic14_emitcode ("pop","acc");
9891                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9892                 }
9893                 
9894         } else {
9895                 _G.accInUse++;
9896                 aopOp(IC_RESULT(ic),ic,FALSE);
9897                 _G.accInUse--;
9898                 assignResultValue(IC_RESULT(ic));
9899         }
9900         
9901         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9902 }
9903
9904 /*-----------------------------------------------------------------*/
9905 /* genDummyRead - generate code for dummy read of volatiles        */
9906 /*-----------------------------------------------------------------*/
9907 static void
9908 genDummyRead (iCode * ic)
9909 {
9910         pic14_emitcode ("; genDummyRead","");
9911         pic14_emitcode ("; not implemented","");
9912         
9913         ic = ic;
9914 }
9915
9916 /*-----------------------------------------------------------------*/
9917 /* genpic14Code - generate code for pic14 based controllers        */
9918 /*-----------------------------------------------------------------*/
9919 /*
9920 * At this point, ralloc.c has gone through the iCode and attempted
9921 * to optimize in a way suitable for a PIC. Now we've got to generate
9922 * PIC instructions that correspond to the iCode.
9923 *
9924 * Once the instructions are generated, we'll pass through both the
9925 * peep hole optimizer and the pCode optimizer.
9926 *-----------------------------------------------------------------*/
9927
9928 void genpic14Code (iCode *lic)
9929 {
9930         iCode *ic;
9931         int cln = 0;
9932         
9933         lineHead = lineCurr = NULL;
9934         
9935         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9936         addpBlock(pb);
9937         
9938         /* if debug information required */
9939         if (options.debug && currFunc) { 
9940                 if (currFunc) {
9941                         debugFile->writeFunction (currFunc, lic);
9942                 }
9943         }
9944         
9945         
9946         for (ic = lic ; ic ; ic = ic->next ) {
9947                 
9948                 DEBUGpic14_emitcode(";ic","");
9949                 if ( cln != ic->lineno ) {
9950                         if ( options.debug ) {
9951                                 debugFile->writeCLine (ic);
9952                         }
9953                         /*
9954                         pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9955                         pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9956                         printCLine(ic->filename, ic->lineno));
9957                         */
9958                         if (!options.noCcodeInAsm) {
9959                                 addpCode2pBlock(pb,
9960                                         newpCodeCSource(ic->lineno, 
9961                                         ic->filename, 
9962                                         printCLine(ic->filename, ic->lineno)));
9963                         }
9964                         
9965                         cln = ic->lineno ;
9966                 }
9967                 
9968                 // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9969                 
9970                 /* if the result is marked as
9971                 spilt and rematerializable or code for
9972                 this has already been generated then
9973                 do nothing */
9974                 if (resultRemat(ic) || ic->generated ) 
9975                         continue ;
9976                 
9977                 /* depending on the operation */
9978                 switch (ic->op) {
9979                 case '!' :
9980                         genNot(ic);
9981                         break;
9982                         
9983                 case '~' :
9984                         genCpl(ic);
9985                         break;
9986                         
9987                 case UNARYMINUS:
9988                         genUminus (ic);
9989                         break;
9990                         
9991                 case IPUSH:
9992                         genIpush (ic);
9993                         break;
9994                         
9995                 case IPOP:
9996                         /* IPOP happens only when trying to restore a 
9997                         spilt live range, if there is an ifx statement
9998                         following this pop then the if statement might
9999                         be using some of the registers being popped which
10000                         would destory the contents of the register so
10001                         we need to check for this condition and handle it */
10002                         if (ic->next            && 
10003                                 ic->next->op == IFX &&
10004                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10005                                 genIfx (ic->next,ic);
10006                         else
10007                                 genIpop (ic);
10008                         break; 
10009                         
10010                 case CALL:
10011                         genCall (ic);
10012                         break;
10013                         
10014                 case PCALL:
10015                         genPcall (ic);
10016                         break;
10017                         
10018                 case FUNCTION:
10019                         genFunction (ic);
10020                         break;
10021                         
10022                 case ENDFUNCTION:
10023                         genEndFunction (ic);
10024                         break;
10025                         
10026                 case RETURN:
10027                         genRet (ic);
10028                         break;
10029                         
10030                 case LABEL:
10031                         genLabel (ic);
10032                         break;
10033                         
10034                 case GOTO:
10035                         genGoto (ic);
10036                         break;
10037                         
10038                 case '+' :
10039                         genPlus (ic) ;
10040                         break;
10041                         
10042                 case '-' :
10043                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10044                                 genMinus (ic);
10045                         break;
10046                         
10047                 case '*' :
10048                         genMult (ic);
10049                         break;
10050                         
10051                 case '/' :
10052                         genDiv (ic) ;
10053                         break;
10054                         
10055                 case '%' :
10056                         genMod (ic);
10057                         break;
10058                         
10059                 case '>' :
10060                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10061                         break;
10062                         
10063                 case '<' :
10064                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10065                         break;
10066                         
10067                 case LE_OP:
10068                 case GE_OP:
10069                 case NE_OP:
10070                         
10071                         /* note these two are xlated by algebraic equivalence
10072                         during parsing SDCC.y */
10073                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10074                                 "got '>=' or '<=' shouldn't have come here");
10075                         break;  
10076                         
10077                 case EQ_OP:
10078                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10079                         break;      
10080                         
10081                 case AND_OP:
10082                         genAndOp (ic);
10083                         break;
10084                         
10085                 case OR_OP:
10086                         genOrOp (ic);
10087                         break;
10088                         
10089                 case '^' :
10090                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10091                         break;
10092                         
10093                 case '|' :
10094                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10095                         break;
10096                         
10097                 case BITWISEAND:
10098                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10099                         break;
10100                         
10101                 case INLINEASM:
10102                         genInline (ic);
10103                         break;
10104                         
10105                 case RRC:
10106                         genRRC (ic);
10107                         break;
10108                         
10109                 case RLC:
10110                         genRLC (ic);
10111                         break;
10112                         
10113                 case GETHBIT:
10114                         genGetHbit (ic);
10115                         break;
10116                         
10117                 case LEFT_OP:
10118                         genLeftShift (ic);
10119                         break;
10120                         
10121                 case RIGHT_OP:
10122                         genRightShift (ic);
10123                         break;
10124                         
10125                 case GET_VALUE_AT_ADDRESS:
10126                         genPointerGet(ic);
10127                         break;
10128                         
10129                 case '=' :
10130                         if (POINTER_SET(ic))
10131                                 genPointerSet(ic);
10132                         else
10133                                 genAssign(ic);
10134                         break;
10135                         
10136                 case IFX:
10137                         genIfx (ic,NULL);
10138                         break;
10139                         
10140                 case ADDRESS_OF:
10141                         genAddrOf (ic);
10142                         break;
10143                         
10144                 case JUMPTABLE:
10145                         genJumpTab (ic);
10146                         break;
10147                         
10148                 case CAST:
10149                         genCast (ic);
10150                         break;
10151                         
10152                 case RECEIVE:
10153                         genReceive(ic);
10154                         break;
10155                         
10156                 case SEND:
10157                         addSet(&_G.sendSet,ic);
10158                         break;
10159                         
10160                 case DUMMY_READ_VOLATILE:
10161                         genDummyRead (ic);
10162                         break;
10163                         
10164                 default :
10165                         ic = ic;
10166                 }
10167         }
10168
10169         
10170         /* now we are ready to call the
10171         peep hole optimizer */
10172         if (!options.nopeep) {
10173                 peepHole (&lineHead);
10174         }
10175         /* now do the actual printing */
10176         printLine (lineHead,codeOutFile);
10177         
10178 #ifdef PCODE_DEBUG
10179         DFPRINTF((stderr,"printing pBlock\n\n"));
10180         printpBlock(stdout,pb);
10181 #endif
10182         
10183         return;
10184 }