* src/pic/gen.c (genInline),
[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 extern void printpBlock(FILE *of, pBlock *pb);
50
51 static int labelOffset=0;
52 extern int debug_verbose;
53 static int optimized_for_speed = 0;
54
55 /* max_key keeps track of the largest label number used in 
56 a function. This is then used to adjust the label offset
57 for the next function.
58 */
59 static int max_key=0;
60 static int GpsuedoStkPtr=0;
61
62 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
63 unsigned int pic14aopLiteral (value *val, int offset);
64 const char *AopType(short type);
65
66 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
67
68 /* this is the down and dirty file with all kinds of 
69 kludgy & hacky stuff. This is what it is all about
70 CODE GENERATION for a specific MCU . some of the
71 routines may be reusable, will have to see */
72
73 static char *zero = "#0x00";
74 static char *one  = "#0x01";
75 static char *spname = "sp";
76
77 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
78 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
79 static char **fReturn = fReturnpic14;
80
81 static char *accUse[] = {"a","b"};
82
83 //static short rbank = -1;
84
85 static struct {
86         short r0Pushed;
87         short r1Pushed;
88         short accInUse;
89         short inLine;
90         short debugLine;
91         short nRegsSaved;
92         set *sendSet;
93 } _G;
94
95 /* Resolved ifx structure. This structure stores information
96 about an iCode ifx that makes it easier to generate code.
97 */
98 typedef struct resolvedIfx {
99         symbol *lbl;     /* pointer to a label */
100         int condition;   /* true or false ifx */
101         int generated;   /* set true when the code associated with the ifx
102                           * is generated */
103 } resolvedIfx;
104
105 extern int pic14_ptrRegReq ;
106 extern int pic14_nRegs;
107 extern FILE *codeOutFile;
108 static void saverbank (int, iCode *,bool);
109
110 static lineNode *lineHead = NULL;
111 static lineNode *lineCurr = NULL;
112
113 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
114 0xE0, 0xC0, 0x80, 0x00};
115 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
117
118 static  pBlock *pb;
119
120 /*-----------------------------------------------------------------*/
121 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
122 /*                                 exponent of 2 is returned, otherwise -1 is      */
123 /*                                 returned.                                                                       */
124 /* note that this is similar to the function `powof2' in SDCCsymt  */
125 /* if(n == 2^y)                                                                                                    */
126 /*       return y;                                                                                                         */
127 /* return -1;                                                                                                      */
128 /*-----------------------------------------------------------------*/
129 static int my_powof2 (unsigned long num)
130 {
131         if(num) {
132                 if( (num & (num-1)) == 0) {
133                         int nshifts = -1;
134                         while(num) {
135                                 num>>=1;
136                                 nshifts++;
137                         }
138                         return nshifts;
139                 }
140         }
141         
142         return -1;
143 }
144
145 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
146 {
147         
148         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
149                 line_no,
150                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
151                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
152                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
153                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
154                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
155                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
156                 ((result) ? AOP_SIZE(result) : 0));
157         
158 }
159
160 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
161 {
162         
163         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
164                 line_no,
165                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
166                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
167                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
168                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
169                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
170                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
171         
172 }
173
174 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
175 {
176         va_list ap;
177         char lb[INITIAL_INLINEASM];  
178         char *lbp = lb;
179         
180         if(!debug_verbose)
181                 return;
182         
183         va_start(ap,fmt);   
184         
185         if (inst && *inst) {
186                 if (fmt && *fmt)
187                         sprintf(lb,"%s\t",inst);
188                 else
189                         sprintf(lb,"%s",inst);
190                 vsprintf(lb+(strlen(lb)),fmt,ap);
191         }  else
192                 vsprintf(lb,fmt,ap);
193         
194         while (isspace(*lbp)) lbp++;
195         
196         if (lbp && *lbp) 
197                 lineCurr = (lineCurr ?
198                 connectLine(lineCurr,newLineNode(lb)) :
199         (lineHead = newLineNode(lb)));
200         lineCurr->isInline = _G.inLine;
201         lineCurr->isDebug  = _G.debugLine;
202         
203         addpCode2pBlock(pb,newpCodeCharP(lb));
204         
205         va_end(ap);
206 }
207
208
209 void emitpLabel(int key)
210 {
211         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
212 }
213
214 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
215 {
216         if(pcop)
217                 addpCode2pBlock(pb,newpCode(poc,pcop));
218         else
219                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
220 }
221
222 void emitpcodeNULLop(PIC_OPCODE poc)
223 {
224         
225         addpCode2pBlock(pb,newpCode(poc,NULL));
226         
227 }
228
229
230 /*-----------------------------------------------------------------*/
231 /* pic14_emitcode - writes the code into a file : for now it is simple    */
232 /*-----------------------------------------------------------------*/
233 void pic14_emitcode (char *inst,char *fmt, ...)
234 {
235         va_list ap;
236         char lb[INITIAL_INLINEASM];  
237         char *lbp = lb;
238         
239         va_start(ap,fmt);   
240         
241         if (inst && *inst) {
242                 if (fmt && *fmt)
243                         sprintf(lb,"%s\t",inst);
244                 else
245                         sprintf(lb,"%s",inst);
246                 vsprintf(lb+(strlen(lb)),fmt,ap);
247         }  else
248                 vsprintf(lb,fmt,ap);
249         
250         while (isspace(*lbp)) lbp++;
251         
252         if (lbp && *lbp) 
253                 lineCurr = (lineCurr ?
254                 connectLine(lineCurr,newLineNode(lb)) :
255         (lineHead = newLineNode(lb)));
256         lineCurr->isInline = _G.inLine;
257         lineCurr->isDebug  = _G.debugLine;
258         
259         if(debug_verbose)
260                 addpCode2pBlock(pb,newpCodeCharP(lb));
261         
262         va_end(ap);
263 }
264
265 /*-----------------------------------------------------------------*/
266 /* pic14_emitDebuggerSymbol - associate the current code location  */
267 /*       with a debugger symbol                                                                            */
268 /*-----------------------------------------------------------------*/
269 void
270 pic14_emitDebuggerSymbol (char * debugSym)
271 {
272         _G.debugLine = 1;
273         pic14_emitcode ("", ";%s ==.", debugSym);
274         _G.debugLine = 0;
275 }
276
277
278 /*-----------------------------------------------------------------*/
279 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
280 /*-----------------------------------------------------------------*/
281 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
282 {
283         bool r0iu = FALSE , r1iu = FALSE;
284         bool r0ou = FALSE , r1ou = FALSE;
285         
286         /* the logic: if r0 & r1 used in the instruction
287         then we are in trouble otherwise */
288         
289         /* first check if r0 & r1 are used by this
290         instruction, in which case we are in trouble */
291         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
292                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
293         {
294                 goto endOfWorld;          
295         }
296         
297         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
298         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
299         
300         /* if no usage of r0 then return it */
301         if (!r0iu && !r0ou) {
302                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
303                 (*aopp)->type = AOP_R0;
304                 
305                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
306         }
307         
308         /* if no usage of r1 then return it */
309         if (!r1iu && !r1ou) {
310                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
311                 (*aopp)->type = AOP_R1;
312                 
313                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
314         }    
315         
316         /* now we know they both have usage */
317         /* if r0 not used in this instruction */
318         if (!r0iu) {
319                 /* push it if not already pushed */
320                 if (!_G.r0Pushed) {
321                         //pic14_emitcode ("push","%s",
322                         //                pic14_regWithIdx(R0_IDX)->dname);
323                         _G.r0Pushed++ ;
324                 }
325                 
326                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
327                 (*aopp)->type = AOP_R0;
328                 
329                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
330         }
331         
332         /* if r1 not used then */
333         
334         if (!r1iu) {
335                 /* push it if not already pushed */
336                 if (!_G.r1Pushed) {
337                         //pic14_emitcode ("push","%s",
338                         //                pic14_regWithIdx(R1_IDX)->dname);
339                         _G.r1Pushed++ ;
340                 }
341                 
342                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
343                 (*aopp)->type = AOP_R1;
344                 return pic14_regWithIdx(R1_IDX);
345         }
346         
347 endOfWorld :
348         /* I said end of world but not quite end of world yet */
349         /* if this is a result then we can push it on the stack*/
350         if (result) {
351                 (*aopp)->type = AOP_STK;        
352                 return NULL;
353         }
354         
355         /* other wise this is true end of the world */
356         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
357                 "getFreePtr should never reach here");
358         exit(0);
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* newAsmop - creates a new asmOp                                                                  */
363 /*-----------------------------------------------------------------*/
364 asmop *newAsmop (short type)
365 {
366         asmop *aop;
367         
368         aop = Safe_calloc(1,sizeof(asmop));
369         aop->type = type;
370         return aop;
371 }
372
373 static void genSetDPTR(int n)
374 {
375         if (!n)
376         {
377                 pic14_emitcode(";", "Select standard DPTR");
378                 pic14_emitcode("mov", "dps, #0x00");
379         }
380         else
381         {
382                 pic14_emitcode(";", "Select alternate DPTR");
383                 pic14_emitcode("mov", "dps, #0x01");
384         }
385 }
386
387 /*-----------------------------------------------------------------*/
388 /* resolveIfx - converts an iCode ifx into a form more useful for  */
389 /*                              generating code                                                                    */
390 /*-----------------------------------------------------------------*/
391 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
392 {
393         if(!resIfx) 
394                 return;
395         
396         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
397         
398         resIfx->condition = 1;  /* assume that the ifx is true */
399         resIfx->generated = 0;  /* indicate that the ifx has not been used */
400         
401         if(!ifx) {
402                 resIfx->lbl = newiTempLabel(NULL);      /* oops, there is no ifx. so create a label */
403                                                                                         /*
404                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
405                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
406                 */
407         } else {
408                 if(IC_TRUE(ifx)) {
409                         resIfx->lbl = IC_TRUE(ifx);
410                 } else {
411                         resIfx->lbl = IC_FALSE(ifx);
412                         resIfx->condition = 0;
413                 }
414                 /*
415                 if(IC_TRUE(ifx)) 
416                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
417                 if(IC_FALSE(ifx)) 
418                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
419                 */
420         }
421         
422         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
423         
424 }
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type                       */
427 /*-----------------------------------------------------------------*/
428 static int pointerCode (sym_link *etype)
429 {
430         
431         return PTR_TYPE(SPEC_OCLS(etype));
432         
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* aopForSym - for a true symbol                                                                   */
437 /*-----------------------------------------------------------------*/
438 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
439 {
440         asmop *aop;
441         memmap *space= SPEC_OCLS(sym->etype);
442         
443         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
444         /* if already has one */
445         if (sym->aop)
446                 return sym->aop;
447         
448         /* assign depending on the storage class */
449         /* if it is on the stack or indirectly addressable */
450         /* space we need to assign either r0 or r1 to it         */    
451         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
452                 sym->aop = aop = newAsmop(0);
453                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
454                 aop->size = getSize(sym->type);
455                 
456                 /* now assign the address of the variable to 
457                 the pointer register */
458                 if (aop->type != AOP_STK) {
459                         
460                         if (sym->onStack) {
461                                 if ( _G.accInUse )
462                                         pic14_emitcode("push","acc");
463                                 
464                                 pic14_emitcode("mov","a,_bp");
465                                 pic14_emitcode("add","a,#0x%02x",
466                                         ((sym->stack < 0) ?
467                                         ((char)(sym->stack - _G.nRegsSaved )) :
468                                 ((char)sym->stack)) & 0xff);
469                                 pic14_emitcode("mov","%s,a",
470                                         aop->aopu.aop_ptr->name);
471                                 
472                                 if ( _G.accInUse )
473                                         pic14_emitcode("pop","acc");
474                         } else
475                                 pic14_emitcode("mov","%s,#%s",
476                                 aop->aopu.aop_ptr->name,
477                                 sym->rname);
478                         aop->paged = space->paged;
479                 } else
480                         aop->aopu.aop_stk = sym->stack;
481                 return aop;
482         }
483         
484         if (sym->onStack && options.stack10bit)
485         {
486                 /* It's on the 10 bit stack, which is located in
487                 * far data space.
488                 */
489                 
490                 //DEBUGpic14_emitcode(";","%d",__LINE__);
491                 
492                 if ( _G.accInUse )
493                         pic14_emitcode("push","acc");
494                 
495                 pic14_emitcode("mov","a,_bp");
496                 pic14_emitcode("add","a,#0x%02x",
497                         ((sym->stack < 0) ?
498                         ((char)(sym->stack - _G.nRegsSaved )) :
499                 ((char)sym->stack)) & 0xff);
500                 
501                 genSetDPTR(1);
502                 pic14_emitcode ("mov","dpx1,#0x40");
503                 pic14_emitcode ("mov","dph1,#0x00");
504                 pic14_emitcode ("mov","dpl1, a");
505                 genSetDPTR(0);
506                 
507                 if ( _G.accInUse )
508                         pic14_emitcode("pop","acc");
509                 
510                 sym->aop = aop = newAsmop(AOP_DPTR2);
511                 aop->size = getSize(sym->type); 
512                 return aop;
513         }
514         
515         //DEBUGpic14_emitcode(";","%d",__LINE__);
516         /* if in bit space */
517         if (IN_BITSPACE(space)) {
518                 sym->aop = aop = newAsmop (AOP_CRY);
519                 aop->aopu.aop_dir = sym->rname ;
520                 aop->size = getSize(sym->type);
521                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
522                 return aop;
523         }
524         /* if it is in direct space */
525         if (IN_DIRSPACE(space)) {
526                 sym->aop = aop = newAsmop (AOP_DIR);
527                 aop->aopu.aop_dir = sym->rname ;
528                 aop->size = getSize(sym->type);
529                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
530                 return aop;
531         }
532         
533         /* special case for a function */
534         if (IS_FUNC(sym->type)) {   
535                 
536                 sym->aop = aop = newAsmop(AOP_PCODE);
537                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
538                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
539                 PCOI(aop->aopu.pcop)->_function = 1;
540                 PCOI(aop->aopu.pcop)->index = 0;
541                 aop->size = FPTRSIZE; 
542                 /*
543                 sym->aop = aop = newAsmop(AOP_IMMD);    
544                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
545                 strcpy(aop->aopu.aop_immd,sym->rname);
546                 aop->size = FPTRSIZE; 
547                 */
548                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
549                 return aop;
550         }
551         
552         
553         /* only remaining is far space */
554         /* in which case DPTR gets the address */
555         sym->aop = aop = newAsmop(AOP_PCODE);
556         
557         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
558         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
559         PCOI(aop->aopu.pcop)->index = 0;
560         
561         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
562                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
563         
564         allocDirReg (IC_LEFT(ic));
565         
566         aop->size = FPTRSIZE; 
567         /*
568         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
569         sym->aop = aop = newAsmop(AOP_DPTR);
570         pic14_emitcode ("mov","dptr,#%s", sym->rname);
571         aop->size = getSize(sym->type);
572         
573           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
574         */
575         
576         /* if it is in code space */
577         if (IN_CODESPACE(space))
578                 aop->code = 1;
579         
580         return aop;       
581 }
582
583 /*-----------------------------------------------------------------*/
584 /* aopForRemat - rematerialzes an object                                                   */
585 /*-----------------------------------------------------------------*/
586 static asmop *aopForRemat (operand *op) // x symbol *sym)
587 {
588         symbol *sym = OP_SYMBOL(op);
589         iCode *ic = NULL;
590         asmop *aop = newAsmop(AOP_PCODE);
591         int val = 0;
592         int offset = 0;
593         
594         ic = sym->rematiCode;
595         
596         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
597         if(IS_OP_POINTER(op)) {
598                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
599         }
600         for (;;) {
601                 if (ic->op == '+') {
602                         val += (int) operandLitValue(IC_RIGHT(ic));
603                 } else if (ic->op == '-') {
604                         val -= (int) operandLitValue(IC_RIGHT(ic));
605                 } else
606                         break;
607                 
608                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
609         }
610         
611         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
612         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
613         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
614         PCOI(aop->aopu.pcop)->index = val;
615         
616         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
617                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
618                 val, IS_PTR_CONST(operandType(op)));
619         
620         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
621         
622         allocDirReg (IC_LEFT(ic));
623         
624         return aop;              
625 }
626
627 int aopIdx (asmop *aop, int offset)
628 {
629         if(!aop)
630                 return -1;
631         
632         if(aop->type !=  AOP_REG)
633                 return -2;
634         
635         return aop->aopu.aop_reg[offset]->rIdx;
636         
637 }
638 /*-----------------------------------------------------------------*/
639 /* regsInCommon - two operands have some registers in common       */
640 /*-----------------------------------------------------------------*/
641 static bool regsInCommon (operand *op1, operand *op2)
642 {
643         symbol *sym1, *sym2;
644         int i;
645         
646         /* if they have registers in common */
647         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
648                 return FALSE ;
649         
650         sym1 = OP_SYMBOL(op1);
651         sym2 = OP_SYMBOL(op2);
652         
653         if (sym1->nRegs == 0 || sym2->nRegs == 0)
654                 return FALSE ;
655         
656         for (i = 0 ; i < sym1->nRegs ; i++) {
657                 int j;
658                 if (!sym1->regs[i])
659                         continue ;
660                 
661                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
662                         if (!sym2->regs[j])
663                                 continue ;
664                         
665                         if (sym2->regs[j] == sym1->regs[i])
666                                 return TRUE ;
667                 }
668         }
669         
670         return FALSE ;
671 }
672
673 /*-----------------------------------------------------------------*/
674 /* operandsEqu - equivalent                                                                        */
675 /*-----------------------------------------------------------------*/
676 static bool operandsEqu ( operand *op1, operand *op2)
677 {
678         symbol *sym1, *sym2;
679         
680         /* if they not symbols */
681         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
682                 return FALSE;
683         
684         sym1 = OP_SYMBOL(op1);
685         sym2 = OP_SYMBOL(op2);
686         
687         /* if both are itemps & one is spilt
688         and the other is not then false */
689         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
690                 sym1->isspilt != sym2->isspilt )
691                 return FALSE ;
692         
693         /* if they are the same */
694         if (sym1 == sym2)
695                 return TRUE ;
696         
697         if (sym1->rname[0] && sym2->rname[0]
698                 && strcmp (sym1->rname, sym2->rname) == 0)
699                 return TRUE;
700         
701         
702         /* if left is a tmp & right is not */
703         if (IS_ITEMP(op1)  && 
704                 !IS_ITEMP(op2) &&
705                 sym1->isspilt  &&
706                 (sym1->usl.spillLoc == sym2))
707                 return TRUE;
708         
709         if (IS_ITEMP(op2)  && 
710                 !IS_ITEMP(op1) &&
711                 sym2->isspilt  &&
712                 sym1->level > 0 &&
713                 (sym2->usl.spillLoc == sym1))
714                 return TRUE ;
715         
716         return FALSE ;
717 }
718
719 /*-----------------------------------------------------------------*/
720 /* pic14_sameRegs - two asmops have the same registers             */
721 /*-----------------------------------------------------------------*/
722 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
723 {
724         int i;
725         
726         if (aop1 == aop2)
727                 return TRUE ;
728         
729         if (aop1->type != AOP_REG ||
730                 aop2->type != AOP_REG )
731                 return FALSE ;
732         
733         if (aop1->size != aop2->size )
734                 return FALSE ;
735         
736         for (i = 0 ; i < aop1->size ; i++ )
737                 if (aop1->aopu.aop_reg[i] !=
738                         aop2->aopu.aop_reg[i] )
739                         return FALSE ;
740                 
741                 return TRUE ;
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* aopOp - allocates an asmop for an operand  :                    */
746 /*-----------------------------------------------------------------*/
747 void aopOp (operand *op, iCode *ic, bool result)
748 {
749         asmop *aop;
750         symbol *sym;
751         int i;
752         
753         if (!op)
754                 return ;
755         
756         /* if this a literal */
757         if (IS_OP_LITERAL(op)) {
758                 op->aop = aop = newAsmop(AOP_LIT);
759                 aop->aopu.aop_lit = op->operand.valOperand;
760                 aop->size = getSize(operandType(op));
761                 return;
762         }
763         
764         {
765                 sym_link *type = operandType(op);
766                 if(IS_PTR_CONST(type))
767                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
768         }
769         
770         /* if already has a asmop then continue */
771         if (op->aop)
772                 return ;
773         
774         /* if the underlying symbol has a aop */
775         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
776                 DEBUGpic14_emitcode(";","%d",__LINE__);
777                 op->aop = OP_SYMBOL(op)->aop;
778                 return;
779         }
780         
781         /* if this is a true symbol */
782         if (IS_TRUE_SYMOP(op)) {          
783                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
784                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
785                 return ;
786         }
787         
788         /* this is a temporary : this has
789         only four choices :
790         a) register
791         b) spillocation
792         c) rematerialize 
793         d) conditional   
794         e) can be a return use only */
795         
796         sym = OP_SYMBOL(op);
797         
798         
799         /* if the type is a conditional */
800         if (sym->regType == REG_CND) {
801                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
802                 aop->size = 0;
803                 return;
804         }
805         
806         /* if it is spilt then two situations
807         a) is rematerialize 
808         b) has a spill location */
809         if (sym->isspilt || sym->nRegs == 0) {
810                 
811                 DEBUGpic14_emitcode(";","%d",__LINE__);
812                 /* rematerialize it NOW */
813                 if (sym->remat) {
814                         
815                         sym->aop = op->aop = aop = aopForRemat (op);
816                         aop->size = getSize(sym->type);
817                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
818                         return;
819                 }
820                 
821                 if (sym->accuse) {
822                         int i;
823                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
824                         aop->size = getSize(sym->type);
825                         for ( i = 0 ; i < 2 ; i++ )
826                                 aop->aopu.aop_str[i] = accUse[i];
827                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
828                         return;  
829                 }
830                 
831                 if (sym->ruonly ) {
832                         if(sym->isptr) {        // && sym->uptr 
833                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
834                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
835                                 
836                                 //PCOI(aop->aopu.pcop)->_const = 0;
837                                 //PCOI(aop->aopu.pcop)->index = 0;
838                                 /*
839                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
840                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
841                                 */
842                                 //allocDirReg (IC_LEFT(ic));
843                                 
844                                 aop->size = getSize(sym->type);
845                                 DEBUGpic14_emitcode(";","%d",__LINE__);
846                                 return;
847                                 
848                         } else {
849                                 
850                                 unsigned i;
851                                 
852                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
853                                 aop->size = getSize(sym->type);
854                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
855                                         aop->aopu.aop_str[i] = fReturn[i];
856                                 
857                                 DEBUGpic14_emitcode(";","%d",__LINE__);
858                                 return;
859                         }
860                 }
861                 
862                 /* else spill location  */
863                 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
864                         /* force a new aop if sizes differ */
865                         sym->usl.spillLoc->aop = NULL;
866                 }
867                 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
868                         __FUNCTION__,__LINE__,
869                         sym->usl.spillLoc->rname,
870                         sym->rname, sym->usl.spillLoc->offset);
871                 
872                 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
873                 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
874                 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
875                         getSize(sym->type), 
876                         sym->usl.spillLoc->offset);
877                 aop->size = getSize(sym->type);
878                 
879                 return;
880         }
881         
882         {
883                 sym_link *type = operandType(op);
884                 if(IS_PTR_CONST(type)) 
885                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
886         }
887         
888         /* must be in a register */
889         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
890         sym->aop = op->aop = aop = newAsmop(AOP_REG);
891         aop->size = sym->nRegs;
892         for ( i = 0 ; i < sym->nRegs ;i++)
893                 aop->aopu.aop_reg[i] = sym->regs[i];
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* freeAsmop - free up the asmop given to an operand                       */
898 /*----------------------------------------------------------------*/
899 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
900 {       
901         asmop *aop ;
902         
903         if (!op)
904                 aop = aaop;
905         else 
906                 aop = op->aop;
907         
908         if (!aop)
909                 return ;
910         
911         if (aop->freed)
912                 goto dealloc; 
913         
914         aop->freed = 1;
915         
916         /* depending on the asmop type only three cases need work AOP_RO
917         , AOP_R1 && AOP_STK */
918 #if 0
919         switch (aop->type) {
920         case AOP_R0 :
921                 if (_G.r0Pushed ) {
922                         if (pop) {
923                                 pic14_emitcode ("pop","ar0");     
924                                 _G.r0Pushed--;
925                         }
926                 }
927                 bitVectUnSetBit(ic->rUsed,R0_IDX);
928                 break;
929                 
930         case AOP_R1 :
931                 if (_G.r1Pushed ) {
932                         if (pop) {
933                                 pic14_emitcode ("pop","ar1");
934                                 _G.r1Pushed--;
935                         }
936                 }
937                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
938                 break;
939                 
940         case AOP_STK :
941                 {
942                         int sz = aop->size;      
943                         int stk = aop->aopu.aop_stk + aop->size;
944                         bitVectUnSetBit(ic->rUsed,R0_IDX);
945                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
946                         
947                         getFreePtr(ic,&aop,FALSE);
948                         
949                         if (options.stack10bit)
950                         {
951                                 /* I'm not sure what to do here yet... */
952                                 /* #STUB */
953                                 fprintf(stderr, 
954                                         "*** Warning: probably generating bad code for "
955                                         "10 bit stack mode.\n");
956                         }
957                         
958                         if (stk) {
959                                 pic14_emitcode ("mov","a,_bp");
960                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
961                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
962                         } else {
963                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
964                         }
965                         
966                         while (sz--) {
967                                 pic14_emitcode("pop","acc");
968                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
969                                 if (!sz) break;
970                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
971                         }
972                         op->aop = aop;
973                         freeAsmop(op,NULL,ic,TRUE);
974                         if (_G.r0Pushed) {
975                                 pic14_emitcode("pop","ar0");
976                                 _G.r0Pushed--;
977                         }
978                         
979                         if (_G.r1Pushed) {
980                                 pic14_emitcode("pop","ar1");
981                                 _G.r1Pushed--;
982                         }         
983                 }
984         }
985 #endif
986         
987 dealloc:
988         /* all other cases just dealloc */
989         if (op ) {
990                 op->aop = NULL;
991                 if (IS_SYMOP(op)) {
992                         OP_SYMBOL(op)->aop = NULL;      
993                         /* if the symbol has a spill */
994                         if (SPIL_LOC(op))
995                                 SPIL_LOC(op)->aop = NULL;
996                 }
997         }
998 }
999
1000 /*-----------------------------------------------------------------*/
1001 /* aopGet - for fetching value of the aop                                                  */
1002 /*-----------------------------------------------------------------*/
1003 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1004 {
1005         char *s = buffer ;
1006         char *rs;
1007         
1008         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1009         /* offset is greater than
1010         size then zero */
1011         if (offset > (aop->size - 1) &&
1012                 aop->type != AOP_LIT)
1013                 return zero;
1014         
1015         /* depending on type */
1016         switch (aop->type) {
1017                 
1018         case AOP_R0:
1019         case AOP_R1:
1020                 DEBUGpic14_emitcode(";","%d",__LINE__);
1021                 /* if we need to increment it */           
1022                 while (offset > aop->coff) {            
1023                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1024                         aop->coff++;
1025                 }
1026                 
1027                 while (offset < aop->coff) {
1028                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1029                         aop->coff--;
1030                 }
1031                 
1032                 aop->coff = offset ;
1033                 if (aop->paged) {
1034                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1035                         return (dname ? "acc" : "a");
1036                 }               
1037                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1038                 rs = Safe_calloc(1,strlen(s)+1);
1039                 strcpy(rs,s);   
1040                 return rs;
1041                 
1042         case AOP_DPTR:
1043         case AOP_DPTR2:
1044                 DEBUGpic14_emitcode(";","%d",__LINE__);
1045                 if (aop->type == AOP_DPTR2)
1046                 {
1047                         genSetDPTR(1);
1048                 }
1049                 
1050                 while (offset > aop->coff) {
1051                         pic14_emitcode ("inc","dptr");
1052                         aop->coff++;
1053                 }
1054                 
1055                 while (offset < aop->coff) {            
1056                         pic14_emitcode("lcall","__decdptr");
1057                         aop->coff--;
1058                 }
1059                 
1060                 aop->coff = offset;
1061                 if (aop->code) {
1062                         pic14_emitcode("clr","a");
1063                         pic14_emitcode("movc","a,@a+dptr");
1064                 }
1065                 else {
1066                         pic14_emitcode("movx","a,@dptr");
1067                 }
1068                 
1069                 if (aop->type == AOP_DPTR2)
1070                 {
1071                         genSetDPTR(0);
1072                 }
1073                 
1074                 return (dname ? "acc" : "a");
1075                 
1076                 
1077         case AOP_IMMD:
1078                 if (bit16) 
1079                         sprintf (s,"%s",aop->aopu.aop_immd);
1080                 else
1081                         if (offset) 
1082                                 sprintf(s,"(%s >> %d)",
1083                                 aop->aopu.aop_immd,
1084                                 offset*8);
1085                         else
1086                                 sprintf(s,"%s",
1087                                 aop->aopu.aop_immd);
1088                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1089                         rs = Safe_calloc(1,strlen(s)+1);
1090                         strcpy(rs,s);   
1091                         return rs;
1092                         
1093         case AOP_DIR:
1094                 if (offset) {
1095                         sprintf(s,"(%s + %d)",
1096                                 aop->aopu.aop_dir,
1097                                 offset);
1098                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1099                 } else
1100                         sprintf(s,"%s",aop->aopu.aop_dir);
1101                 rs = Safe_calloc(1,strlen(s)+1);
1102                 strcpy(rs,s);   
1103                 return rs;
1104                 
1105         case AOP_REG:
1106                 //if (dname) 
1107                 //        return aop->aopu.aop_reg[offset]->dname;
1108                 //else
1109                 return aop->aopu.aop_reg[offset]->name;
1110                 
1111         case AOP_CRY:
1112                 //pic14_emitcode(";","%d",__LINE__);
1113                 return aop->aopu.aop_dir;
1114                 
1115         case AOP_ACC:
1116                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1117                 return "AOP_accumulator_bug";
1118                 
1119         case AOP_LIT:
1120                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1121                 rs = Safe_calloc(1,strlen(s)+1);
1122                 strcpy(rs,s);   
1123                 return rs;
1124                 
1125         case AOP_STR:
1126                 aop->coff = offset ;
1127                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1128                         dname)
1129                         return "acc";
1130                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1131                 
1132                 return aop->aopu.aop_str[offset];
1133                 
1134         case AOP_PCODE:
1135                 {
1136                         pCodeOp *pcop = aop->aopu.pcop;
1137                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1138                         if(pcop->name) {
1139                                 if (offset) {
1140                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1141                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1142                                 } else {
1143                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1144                                         sprintf(s,"%s", pcop->name);
1145                                 }
1146                         } else
1147                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1148                         
1149                 }
1150                 rs = Safe_calloc(1,strlen(s)+1);
1151                 strcpy(rs,s);   
1152                 return rs;
1153                 
1154   }
1155   
1156   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1157           "aopget got unsupported aop->type");
1158   exit(0);
1159 }
1160
1161
1162 /*-----------------------------------------------------------------*/
1163 /* popGetTempReg - create a new temporary pCodeOp                                  */
1164 /*-----------------------------------------------------------------*/
1165 pCodeOp *popGetTempReg(void)
1166 {
1167         
1168         pCodeOp *pcop;
1169         
1170         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1171         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1172                 PCOR(pcop)->r->wasUsed=1;
1173                 PCOR(pcop)->r->isFree=0;
1174         }
1175         
1176         return pcop;
1177 }
1178
1179 /*-----------------------------------------------------------------*/
1180 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1181 /*-----------------------------------------------------------------*/
1182 void popReleaseTempReg(pCodeOp *pcop)
1183 {
1184         
1185         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1186                 PCOR(pcop)->r->isFree = 1;
1187         
1188 }
1189 /*-----------------------------------------------------------------*/
1190 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1191 /*-----------------------------------------------------------------*/
1192 pCodeOp *popGetLabel(unsigned int key)
1193 {
1194         
1195         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1196         
1197         if(key>(unsigned int)max_key)
1198                 max_key = key;
1199         
1200         return newpCodeOpLabel(NULL,key+100+labelOffset);
1201 }
1202
1203 /*-------------------------------------------------------------------*/
1204 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1205 /*-------------------------------------------------------------------*/
1206 pCodeOp *popGetHighLabel(unsigned int key)
1207 {
1208         pCodeOp *pcop;
1209         pcop = popGetLabel(key);
1210         PCOLAB(pcop)->offset = 1;
1211         return pcop;
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* popGetLit - asm operator to pcode operator conversion                           */
1216 /*-----------------------------------------------------------------*/
1217 pCodeOp *popGetLit(unsigned int lit)
1218 {
1219         
1220         return newpCodeOpLit(lit);
1221 }
1222
1223 /*-----------------------------------------------------------------*/
1224 /* popGetImmd - asm operator to pcode immediate conversion                 */
1225 /*-----------------------------------------------------------------*/
1226 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1227 {
1228         
1229         return newpCodeOpImmd(name, offset,index, 0, is_func);
1230 }
1231
1232
1233 /*-----------------------------------------------------------------*/
1234 /* popGetWithString - asm operator to pcode operator conversion                    */
1235 /*-----------------------------------------------------------------*/
1236 pCodeOp *popGetWithString(char *str, int isExtern)
1237 {
1238         pCodeOp *pcop;
1239         
1240         
1241         if(!str) {
1242                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1243                 exit (1);
1244         }
1245         
1246         pcop = newpCodeOp(str,PO_STR);
1247         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1248         
1249         return pcop;
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* popRegFromString -                                                                                      */
1254 /*-----------------------------------------------------------------*/
1255 pCodeOp *popRegFromString(char *str, int size, int offset)
1256 {
1257         
1258         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1259         pcop->type = PO_DIR;
1260         
1261         DEBUGpic14_emitcode(";","%d",__LINE__);
1262         
1263         if(!str)
1264                 str = "BAD_STRING";
1265         
1266         pcop->name = Safe_calloc(1,strlen(str)+1);
1267         strcpy(pcop->name,str);
1268         
1269         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1270         
1271         PCOR(pcop)->r = dirregWithName(pcop->name);
1272         if(PCOR(pcop)->r == NULL) {
1273                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1274                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1275                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1276         } else {
1277                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1278         }
1279         PCOR(pcop)->instance = offset;
1280         
1281         return pcop;
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *popRegFromIdx(int rIdx)
1287 {
1288         pCodeOp *pcop;
1289         
1290         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1291                 __FUNCTION__,__LINE__,rIdx);
1292         
1293         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1294         
1295         PCOR(pcop)->rIdx = rIdx;
1296         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1297         PCOR(pcop)->r->isFree = 0;
1298         PCOR(pcop)->r->wasUsed = 1;
1299         
1300         pcop->type = PCOR(pcop)->r->pc_type;
1301         
1302         
1303         return pcop;
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* popGet - asm operator to pcode operator conversion                      */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1310 {
1311         //char *s = buffer ;
1312         //char *rs;
1313         
1314         pCodeOp *pcop;
1315         
1316         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1317         /* offset is greater than
1318         size then zero */
1319         
1320         if (offset > (aop->size - 1) &&
1321                 aop->type != AOP_LIT)
1322                 return NULL;  //zero;
1323         
1324         /* depending on type */
1325         switch (aop->type) {
1326                 
1327         case AOP_R0:
1328         case AOP_R1:
1329         case AOP_DPTR:
1330         case AOP_DPTR2:
1331         case AOP_ACC:
1332                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1333                 return NULL;
1334                 
1335         case AOP_IMMD:
1336                 DEBUGpic14_emitcode(";","%d",__LINE__);
1337                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1338                 
1339         case AOP_DIR:
1340                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1341 #if 0
1342                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1343                 pcop->type = PO_DIR;
1344                 
1345                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1346                 strcpy(pcop->name,aop->aopu.aop_dir);   
1347                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1348                 if(PCOR(pcop)->r == NULL) {
1349                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1350                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1351                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1352                 } else {
1353                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1354                 }
1355                 PCOR(pcop)->instance = offset;
1356                 
1357                 return pcop;
1358 #endif
1359                 
1360         case AOP_REG:
1361                 {
1362                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1363                         
1364                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1365                         PCOR(pcop)->rIdx = rIdx;
1366                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1367                         PCOR(pcop)->r->wasUsed=1;
1368                         PCOR(pcop)->r->isFree=0;
1369                         
1370                         PCOR(pcop)->instance = offset;
1371                         pcop->type = PCOR(pcop)->r->pc_type;
1372                         //rs = aop->aopu.aop_reg[offset]->name;
1373                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1374                         return pcop;
1375                 }
1376                 
1377         case AOP_CRY:
1378                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1379                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1380                 //if(PCOR(pcop)->r == NULL)
1381                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1382                 return pcop;
1383                 
1384         case AOP_LIT:
1385                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1386                 
1387         case AOP_STR:
1388                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1389                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1390                 /*
1391                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1392                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1393                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1394                 pcop->type = PCOR(pcop)->r->pc_type;
1395                 pcop->name = PCOR(pcop)->r->name;
1396                 
1397                   return pcop;
1398                 */
1399                 
1400         case AOP_PCODE:
1401                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1402                         __LINE__, 
1403                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1404                 pcop = pCodeOpCopy(aop->aopu.pcop);
1405                 PCOI(pcop)->offset = offset;
1406                 return pcop;
1407         }
1408         
1409         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1410                 "popGet got unsupported aop->type");
1411         exit(0);
1412 }
1413 /*-----------------------------------------------------------------*/
1414 /* aopPut - puts a string for a aop                                                        */
1415 /*-----------------------------------------------------------------*/
1416 void aopPut (asmop *aop, char *s, int offset)
1417 {
1418         char *d = buffer ;
1419         symbol *lbl ;
1420         
1421         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1422         
1423         if (aop->size && offset > ( aop->size - 1)) {
1424                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1425                         "aopPut got offset > aop->size");
1426                 exit(0);
1427         }
1428         
1429         /* will assign value to value */
1430         /* depending on where it is ofcourse */
1431         switch (aop->type) {
1432         case AOP_DIR:
1433                 if (offset) {
1434                         sprintf(d,"(%s + %d)",
1435                                 aop->aopu.aop_dir,offset);
1436                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1437                         
1438                 } else
1439                         sprintf(d,"%s",aop->aopu.aop_dir);
1440                 
1441                 if (strcmp(d,s)) {
1442                         DEBUGpic14_emitcode(";","%d",__LINE__);
1443                         if(strcmp(s,"W"))
1444                                 pic14_emitcode("movf","%s,w",s);
1445                         pic14_emitcode("movwf","%s",d);
1446                         
1447                         if(strcmp(s,"W")) {
1448                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1449                                 if(offset >= aop->size) {
1450                                         emitpcode(POC_CLRF,popGet(aop,offset));
1451                                         break;
1452                                 } else
1453                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1454                         }
1455                         
1456                         emitpcode(POC_MOVWF,popGet(aop,offset));
1457                         
1458                         
1459                 }
1460                 break;
1461                 
1462         case AOP_REG:
1463                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1464                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1465                         /*
1466                         if (*s == '@'             ||
1467                         strcmp(s,"r0") == 0 ||
1468                         strcmp(s,"r1") == 0 ||
1469                         strcmp(s,"r2") == 0 ||
1470                         strcmp(s,"r3") == 0 ||
1471                         strcmp(s,"r4") == 0 ||
1472                         strcmp(s,"r5") == 0 ||
1473                         strcmp(s,"r6") == 0 || 
1474                         strcmp(s,"r7") == 0 )
1475                         pic14_emitcode("mov","%s,%s  ; %d",
1476                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1477                         else
1478                         */
1479                         
1480                         if(strcmp(s,"W")==0 )
1481                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1482                         
1483                         pic14_emitcode("movwf","%s",
1484                                 aop->aopu.aop_reg[offset]->name);
1485                         
1486                         if(strcmp(s,zero)==0) {
1487                                 emitpcode(POC_CLRF,popGet(aop,offset));
1488                                 
1489                         } else if(strcmp(s,"W")==0) {
1490                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1491                                 pcop->type = PO_GPR_REGISTER;
1492                                 
1493                                 PCOR(pcop)->rIdx = -1;
1494                                 PCOR(pcop)->r = NULL;
1495                                 
1496                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1497                                 pcop->name = Safe_strdup(s);
1498                                 emitpcode(POC_MOVFW,pcop);
1499                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1500                         } else if(strcmp(s,one)==0) {
1501                                 emitpcode(POC_CLRF,popGet(aop,offset));
1502                                 emitpcode(POC_INCF,popGet(aop,offset));
1503                         } else {
1504                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1505                         }
1506                 }
1507                 break;
1508                 
1509         case AOP_DPTR:
1510         case AOP_DPTR2:
1511                 
1512                 if (aop->type == AOP_DPTR2)
1513                 {
1514                         genSetDPTR(1);
1515                 }
1516                 
1517                 if (aop->code) {
1518                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1519                                 "aopPut writting to code space");
1520                         exit(0);
1521                 }
1522                 
1523                 while (offset > aop->coff) {
1524                         aop->coff++;
1525                         pic14_emitcode ("inc","dptr");
1526                 }
1527                 
1528                 while (offset < aop->coff) {
1529                         aop->coff-- ;
1530                         pic14_emitcode("lcall","__decdptr");
1531                 }
1532                 
1533                 aop->coff = offset;
1534                 
1535                 /* if not in accumulater */
1536                 MOVA(s);
1537                 
1538                 pic14_emitcode ("movx","@dptr,a");
1539                 
1540                 if (aop->type == AOP_DPTR2)
1541                 {
1542                         genSetDPTR(0);
1543                 }
1544                 break;
1545                 
1546         case AOP_R0:
1547         case AOP_R1:
1548                 while (offset > aop->coff) {
1549                         aop->coff++;
1550                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1551                 }
1552                 while (offset < aop->coff) {
1553                         aop->coff-- ;
1554                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1555                 }
1556                 aop->coff = offset;
1557                 
1558                 if (aop->paged) {
1559                         MOVA(s);                         
1560                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1561                         
1562                 } else
1563                         if (*s == '@') {
1564                                 MOVA(s);
1565                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1566                         } else
1567                                 if (strcmp(s,"r0") == 0 ||
1568                                         strcmp(s,"r1") == 0 ||
1569                                         strcmp(s,"r2") == 0 ||
1570                                         strcmp(s,"r3") == 0 ||
1571                                         strcmp(s,"r4") == 0 ||
1572                                         strcmp(s,"r5") == 0 ||
1573                                         strcmp(s,"r6") == 0 || 
1574                                         strcmp(s,"r7") == 0 ) {
1575                                         char buffer[10];
1576                                         sprintf(buffer,"a%s",s);
1577                                         pic14_emitcode("mov","@%s,%s",
1578                                                 aop->aopu.aop_ptr->name,buffer);
1579                                 } else
1580                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1581                                 
1582                                 break;
1583                                 
1584         case AOP_STK:
1585                 if (strcmp(s,"a") == 0)
1586                         pic14_emitcode("push","acc");
1587                 else
1588                         pic14_emitcode("push","%s",s);
1589                 
1590                 break;
1591                 
1592         case AOP_CRY:
1593                 /* if bit variable */
1594                 if (!aop->aopu.aop_dir) {
1595                         pic14_emitcode("clr","a");
1596                         pic14_emitcode("rlc","a");
1597                 } else {
1598                         if (s == zero) 
1599                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1600                         else
1601                                 if (s == one)
1602                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1603                                 else
1604                                         if (!strcmp(s,"c"))
1605                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1606                                         else {
1607                                                 lbl = newiTempLabel(NULL);
1608                                                 
1609                                                 if (strcmp(s,"a")) {
1610                                                         MOVA(s);
1611                                                 }
1612                                                 pic14_emitcode("clr","c");
1613                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1614                                                 pic14_emitcode("cpl","c");
1615                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1616                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1617                                         }
1618                 }
1619                 break;
1620                 
1621         case AOP_STR:
1622                 aop->coff = offset;
1623                 if (strcmp(aop->aopu.aop_str[offset],s))
1624                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1625                 break;
1626                 
1627         case AOP_ACC:
1628                 aop->coff = offset;
1629                 if (!offset && (strcmp(s,"acc") == 0))
1630                         break;
1631                 
1632                 if (strcmp(aop->aopu.aop_str[offset],s))
1633                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1634                 break;
1635                 
1636         default :
1637                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1638                         "aopPut got unsupported aop->type");
1639                 exit(0);
1640         }
1641         
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1646 /*-----------------------------------------------------------------*/
1647 void mov2w (asmop *aop, int offset)
1648 {
1649         
1650         if(!aop)
1651                 return;
1652         
1653         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1654         
1655         if ( aop->type == AOP_PCODE ||
1656                 aop->type == AOP_LIT ||
1657                 aop->type == AOP_IMMD )
1658                 emitpcode(POC_MOVLW,popGet(aop,offset));
1659         else
1660                 emitpcode(POC_MOVFW,popGet(aop,offset));
1661         
1662 }
1663
1664 /*-----------------------------------------------------------------*/
1665 /* reAdjustPreg - points a register back to where it should        */
1666 /*-----------------------------------------------------------------*/
1667 static void reAdjustPreg (asmop *aop)
1668 {
1669         int size ;
1670         
1671         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1672         aop->coff = 0;
1673         if ((size = aop->size) <= 1)
1674                 return ;
1675         size-- ;
1676         switch (aop->type) {
1677         case AOP_R0 :
1678         case AOP_R1 :
1679                 while (size--)
1680                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1681                 break;                  
1682         case AOP_DPTR :
1683         case AOP_DPTR2:
1684                 if (aop->type == AOP_DPTR2)
1685                 {
1686                         genSetDPTR(1);
1687                 } 
1688                 while (size--)
1689                 {
1690                         pic14_emitcode("lcall","__decdptr");
1691                 }
1692                 
1693                 if (aop->type == AOP_DPTR2)
1694                 {
1695                         genSetDPTR(0);
1696                 }
1697                 break;
1698                 
1699         }
1700         
1701 }
1702
1703
1704 #if 0
1705 /*-----------------------------------------------------------------*/
1706 /* opIsGptr: returns non-zero if the passed operand is             */
1707 /* a generic pointer type.                                         */
1708 /*-----------------------------------------------------------------*/ 
1709 static int opIsGptr(operand *op)
1710 {
1711         sym_link *type = operandType(op);
1712         
1713         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1714         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1715         {
1716                 return 1;
1717         }
1718         return 0;          
1719 }
1720 #endif
1721
1722 /*-----------------------------------------------------------------*/
1723 /* pic14_getDataSize - get the operand data size                   */
1724 /*-----------------------------------------------------------------*/
1725 int pic14_getDataSize(operand *op)
1726 {
1727         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1728         
1729         
1730         return AOP_SIZE(op);
1731         
1732         // tsd- in the pic port, the genptr size is 1, so this code here
1733         // fails. ( in the 8051 port, the size was 4).
1734 #if 0
1735         int size;
1736         size = AOP_SIZE(op);
1737         if (size == GPTRSIZE)
1738         {
1739                 sym_link *type = operandType(op);
1740                 if (IS_GENPTR(type))
1741                 {
1742                         /* generic pointer; arithmetic operations
1743                         * should ignore the high byte (pointer type).
1744                         */
1745                         size--;
1746                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1747                 }
1748         }
1749         return size;
1750 #endif
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* pic14_outAcc - output Acc                                       */
1755 /*-----------------------------------------------------------------*/
1756 void pic14_outAcc(operand *result)
1757 {
1758         int size,offset;
1759         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1760         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1761         
1762         
1763         size = pic14_getDataSize(result);
1764         if(size){
1765                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1766                 size--;
1767                 offset = 1;
1768                 /* unsigned or positive */
1769                 while(size--)
1770                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1771         }
1772         
1773 }
1774
1775 /*-----------------------------------------------------------------*/
1776 /* pic14_outBitC - output a bit C                                  */
1777 /*-----------------------------------------------------------------*/
1778 void pic14_outBitC(operand *result)
1779 {
1780         
1781         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1782         /* if the result is bit */
1783         if (AOP_TYPE(result) == AOP_CRY) 
1784                 aopPut(AOP(result),"c",0);
1785         else {
1786                 pic14_emitcode("clr","a  ; %d", __LINE__);
1787                 pic14_emitcode("rlc","a");
1788                 pic14_outAcc(result);
1789         }
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1794 /*-----------------------------------------------------------------*/
1795 void pic14_toBoolean(operand *oper)
1796 {
1797         int size = AOP_SIZE(oper) - 1;
1798         int offset = 1;
1799         
1800         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1801         
1802         if ( AOP_TYPE(oper) != AOP_ACC) {
1803                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1804         }
1805         while (size--) {
1806                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1807         }
1808 }
1809
1810
1811 /*-----------------------------------------------------------------*/
1812 /* genNot - generate code for ! operation                          */
1813 /*-----------------------------------------------------------------*/
1814 static void genNot (iCode *ic)
1815 {
1816         symbol *tlbl;
1817         int size;
1818         
1819         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1820         /* assign asmOps to operand & result */
1821         aopOp (IC_LEFT(ic),ic,FALSE);
1822         aopOp (IC_RESULT(ic),ic,TRUE);
1823         
1824         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1825         /* if in bit space then a special case */
1826         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1827                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1828                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1829                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1830                 } else {
1831                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1832                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1833                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1834                 }
1835                 goto release;
1836         }
1837         
1838         size = AOP_SIZE(IC_LEFT(ic));
1839         if(size == 1) {
1840                 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1841                 emitpcode(POC_ANDLW,popGetLit(1));
1842                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1843                 goto release;
1844         }
1845         pic14_toBoolean(IC_LEFT(ic));
1846         
1847         tlbl = newiTempLabel(NULL);
1848         pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1849         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1850         pic14_outBitC(IC_RESULT(ic));
1851         
1852 release:        
1853         /* release the aops */
1854         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1855         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1856 }
1857
1858
1859 /*-----------------------------------------------------------------*/
1860 /* genCpl - generate code for complement                                                   */
1861 /*-----------------------------------------------------------------*/
1862 static void genCpl (iCode *ic)
1863 {
1864         operand *left, *result;
1865         int size, offset=0;  
1866         
1867         
1868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1869         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1870         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1871         
1872         /* if both are in bit space then 
1873         a special case */
1874         if (AOP_TYPE(result) == AOP_CRY &&
1875                 AOP_TYPE(left) == AOP_CRY ) { 
1876                 
1877                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1878                 pic14_emitcode("cpl","c"); 
1879                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1880                 goto release; 
1881         } 
1882         
1883         size = AOP_SIZE(result);
1884         while (size--) {
1885                 
1886                 if(AOP_TYPE(left) == AOP_ACC) 
1887                         emitpcode(POC_XORLW, popGetLit(0xff));
1888                 else
1889                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1890                 
1891                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1892                 offset++;
1893         }
1894         
1895         
1896 release:
1897         /* release the aops */
1898         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1899         freeAsmop(result,NULL,ic,TRUE);
1900 }
1901
1902 /*-----------------------------------------------------------------*/
1903 /* genUminusFloat - unary minus for floating points                        */
1904 /*-----------------------------------------------------------------*/
1905 static void genUminusFloat(operand *op,operand *result)
1906 {
1907         int size ,offset =0 ;
1908         char *l;
1909         
1910         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1911         /* for this we just need to flip the 
1912         first it then copy the rest in place */
1913         size = AOP_SIZE(op) - 1;
1914         l = aopGet(AOP(op),3,FALSE,FALSE);
1915         
1916         MOVA(l);          
1917         
1918         pic14_emitcode("cpl","acc.7");
1919         aopPut(AOP(result),"a",3);      
1920         
1921         while(size--) {
1922                 aopPut(AOP(result),
1923                         aopGet(AOP(op),offset,FALSE,FALSE),
1924                         offset);
1925                 offset++;
1926         }                
1927 }
1928
1929 /*-----------------------------------------------------------------*/
1930 /* genUminus - unary minus code generation                                                 */
1931 /*-----------------------------------------------------------------*/
1932 static void genUminus (iCode *ic)
1933 {
1934         int size, i;
1935         sym_link *optype, *rtype;
1936         
1937         
1938         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1939         /* assign asmops */
1940         aopOp(IC_LEFT(ic),ic,FALSE);
1941         aopOp(IC_RESULT(ic),ic,TRUE);
1942         
1943         /* if both in bit space then special
1944         case */
1945         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1946                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1947                 
1948                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
1949                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1950                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
1951                 
1952                 goto release; 
1953         } 
1954         
1955         optype = operandType(IC_LEFT(ic));
1956         rtype = operandType(IC_RESULT(ic));
1957         
1958         /* if float then do float stuff */
1959         if (IS_FLOAT(optype)) {
1960                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1961                 goto release;
1962         }
1963         
1964         /* otherwise subtract from zero by taking the 2's complement */
1965         size = AOP_SIZE(IC_LEFT(ic));
1966         
1967         for(i=0; i<size; i++) {
1968                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1969                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1970                 else {
1971                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1972                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1973                 }
1974         }
1975         
1976         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1977         for(i=1; i<size; i++) {
1978                 emitSKPNZ;
1979                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1980         }
1981         
1982 release:
1983         /* release the aops */
1984         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1985         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
1986 }
1987
1988 /*-----------------------------------------------------------------*/
1989 /* saveRegisters - will look for a call and save the registers     */
1990 /*-----------------------------------------------------------------*/
1991 static void saveRegisters(iCode *lic) 
1992 {
1993         int i;
1994         iCode *ic;
1995         bitVect *rsave;
1996         sym_link *dtype;
1997         
1998         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1999         /* look for call */
2000         for (ic = lic ; ic ; ic = ic->next) 
2001                 if (ic->op == CALL || ic->op == PCALL)
2002                         break;
2003                 
2004                 if (!ic) {
2005                         fprintf(stderr,"found parameter push with no function call\n");
2006                         return ;
2007                 }
2008                 
2009                 /* if the registers have been saved already then
2010                 do nothing */
2011                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2012                         return ;
2013                 
2014                         /* find the registers in use at this time 
2015                 and push them away to safety */
2016                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2017                         ic->rUsed);
2018                 
2019                 ic->regsSaved = 1;
2020                 if (options.useXstack) {
2021                         if (bitVectBitValue(rsave,R0_IDX))
2022                                 pic14_emitcode("mov","b,r0");
2023                         pic14_emitcode("mov","r0,%s",spname);
2024                         for (i = 0 ; i < pic14_nRegs ; i++) {
2025                                 if (bitVectBitValue(rsave,i)) {
2026                                         if (i == R0_IDX)
2027                                                 pic14_emitcode("mov","a,b");
2028                                         else
2029                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2030                                         pic14_emitcode("movx","@r0,a");
2031                                         pic14_emitcode("inc","r0");
2032                                 }
2033                         }
2034                         pic14_emitcode("mov","%s,r0",spname);
2035                         if (bitVectBitValue(rsave,R0_IDX))
2036                                 pic14_emitcode("mov","r0,b");     
2037                 }// else
2038                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2039                 //        if (bitVectBitValue(rsave,i))
2040                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2041                 //}
2042                 
2043                 dtype = operandType(IC_LEFT(ic));
2044                 if (currFunc && dtype && 
2045                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2046                         IFFUNC_ISISR(currFunc->type) &&
2047                         !ic->bankSaved) 
2048                         
2049                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2050                 
2051 }
2052 /*-----------------------------------------------------------------*/
2053 /* unsaveRegisters - pop the pushed registers                                      */
2054 /*-----------------------------------------------------------------*/
2055 static void unsaveRegisters (iCode *ic)
2056 {
2057         int i;
2058         bitVect *rsave;
2059         
2060         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2061         /* find the registers in use at this time 
2062         and push them away to safety */
2063         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2064                 ic->rUsed);
2065         
2066         if (options.useXstack) {
2067                 pic14_emitcode("mov","r0,%s",spname); 
2068                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2069                         if (bitVectBitValue(rsave,i)) {
2070                                 pic14_emitcode("dec","r0");
2071                                 pic14_emitcode("movx","a,@r0");
2072                                 if (i == R0_IDX)
2073                                         pic14_emitcode("mov","b,a");
2074                                 else
2075                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2076                         }       
2077                         
2078                 }
2079                 pic14_emitcode("mov","%s,r0",spname);
2080                 if (bitVectBitValue(rsave,R0_IDX))
2081                         pic14_emitcode("mov","r0,b");
2082         } //else
2083         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2084         //      if (bitVectBitValue(rsave,i))
2085         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2086         //}
2087         
2088 }  
2089
2090
2091 /*-----------------------------------------------------------------*/
2092 /* pushSide -                            */
2093 /*-----------------------------------------------------------------*/
2094 static void pushSide(operand * oper, int size)
2095 {
2096 #if 0
2097         int offset = 0;
2098         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2099         while (size--) {
2100                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2101                 if (AOP_TYPE(oper) != AOP_REG &&
2102                         AOP_TYPE(oper) != AOP_DIR &&
2103                         strcmp(l,"a") ) {
2104                         pic14_emitcode("mov","a,%s",l);
2105                         pic14_emitcode("push","acc");
2106                 } else
2107                         pic14_emitcode("push","%s",l);
2108         }
2109 #endif
2110 }
2111
2112 /*-----------------------------------------------------------------*/
2113 /* assignResultValue -                           */
2114 /*-----------------------------------------------------------------*/
2115 static void assignResultValue(operand * oper)
2116 {
2117         int size = AOP_SIZE(oper);
2118         
2119         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2120         
2121         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2122         
2123         while (size--) {
2124                 if (GpsuedoStkPtr++)
2125                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2126                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2127         }
2128 }
2129
2130
2131 /*-----------------------------------------------------------------*/
2132 /* genIpush - genrate code for pushing this gets a little complex  */
2133 /*-----------------------------------------------------------------*/
2134 static void genIpush (iCode *ic)
2135 {
2136         
2137         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2138 #if 0
2139         int size, offset = 0 ;
2140         char *l;
2141         
2142         
2143         /* if this is not a parm push : ie. it is spill push 
2144         and spill push is always done on the local stack */
2145         if (!ic->parmPush) {
2146                 
2147                 /* and the item is spilt then do nothing */
2148                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2149                         return ;
2150                 
2151                 aopOp(IC_LEFT(ic),ic,FALSE);
2152                 size = AOP_SIZE(IC_LEFT(ic));
2153                 /* push it on the stack */
2154                 while(size--) {
2155                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2156                         if (*l == '#') {
2157                                 MOVA(l);
2158                                 l = "acc";
2159                         }
2160                         pic14_emitcode("push","%s",l);
2161                 }
2162                 return ;                
2163         }
2164         
2165         /* this is a paramter push: in this case we call
2166         the routine to find the call and save those
2167         registers that need to be saved */   
2168         saveRegisters(ic);
2169         
2170         /* then do the push */
2171         aopOp(IC_LEFT(ic),ic,FALSE);
2172         
2173         
2174         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2175         size = AOP_SIZE(IC_LEFT(ic));
2176         
2177         while (size--) {
2178                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2179                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2180                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2181                         strcmp(l,"a") ) {
2182                         pic14_emitcode("mov","a,%s",l);
2183                         pic14_emitcode("push","acc");
2184                 } else
2185                         pic14_emitcode("push","%s",l);
2186         }         
2187         
2188         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2189 #endif
2190 }
2191
2192 /*-----------------------------------------------------------------*/
2193 /* genIpop - recover the registers: can happen only for spilling   */
2194 /*-----------------------------------------------------------------*/
2195 static void genIpop (iCode *ic)
2196 {
2197         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2198 #if 0
2199         int size,offset ;
2200         
2201         
2202         /* if the temp was not pushed then */
2203         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2204                 return ;
2205         
2206         aopOp(IC_LEFT(ic),ic,FALSE);
2207         size = AOP_SIZE(IC_LEFT(ic));
2208         offset = (size-1);
2209         while (size--) 
2210                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2211                 FALSE,TRUE));
2212         
2213         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2214 #endif
2215 }
2216
2217 /*-----------------------------------------------------------------*/
2218 /* unsaverbank - restores the resgister bank from stack                    */
2219 /*-----------------------------------------------------------------*/
2220 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2221 {
2222         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2223 #if 0
2224         int i;
2225         asmop *aop ;
2226         regs *r = NULL;
2227         
2228         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2229         if (popPsw) {
2230                 if (options.useXstack) {
2231                         aop = newAsmop(0);
2232                         r = getFreePtr(ic,&aop,FALSE);
2233                         
2234                         
2235                         pic14_emitcode("mov","%s,_spx",r->name);
2236                         pic14_emitcode("movx","a,@%s",r->name);
2237                         pic14_emitcode("mov","psw,a");
2238                         pic14_emitcode("dec","%s",r->name);
2239                         
2240                 }else
2241                         pic14_emitcode ("pop","psw");
2242         }
2243         
2244         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2245                 if (options.useXstack) {           
2246                         pic14_emitcode("movx","a,@%s",r->name);
2247                         //pic14_emitcode("mov","(%s+%d),a",
2248                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2249                         pic14_emitcode("dec","%s",r->name);
2250                         
2251                 } else 
2252                         pic14_emitcode("pop",""); //"(%s+%d)",
2253                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2254         }
2255         
2256         if (options.useXstack) {
2257                 
2258                 pic14_emitcode("mov","_spx,%s",r->name);
2259                 freeAsmop(NULL,aop,ic,TRUE);
2260                 
2261         }
2262 #endif 
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* saverbank - saves an entire register bank on the stack                  */
2267 /*-----------------------------------------------------------------*/
2268 static void saverbank (int bank, iCode *ic, bool pushPsw)
2269 {
2270         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2271 #if 0
2272         int i;
2273         asmop *aop ;
2274         regs *r = NULL;
2275         
2276         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2277         if (options.useXstack) {
2278                 
2279                 aop = newAsmop(0);
2280                 r = getFreePtr(ic,&aop,FALSE);  
2281                 pic14_emitcode("mov","%s,_spx",r->name);
2282                 
2283         }
2284         
2285         for (i = 0 ; i < pic14_nRegs ;i++) {
2286                 if (options.useXstack) {
2287                         pic14_emitcode("inc","%s",r->name);
2288                         //pic14_emitcode("mov","a,(%s+%d)",
2289                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2290                         pic14_emitcode("movx","@%s,a",r->name);                 
2291                 } else 
2292                         pic14_emitcode("push","");// "(%s+%d)",
2293                 //regspic14[i].base,8*bank+regspic14[i].offset);
2294         }
2295         
2296         if (pushPsw) {
2297                 if (options.useXstack) {
2298                         pic14_emitcode("mov","a,psw");
2299                         pic14_emitcode("movx","@%s,a",r->name); 
2300                         pic14_emitcode("inc","%s",r->name);
2301                         pic14_emitcode("mov","_spx,%s",r->name);                 
2302                         freeAsmop (NULL,aop,ic,TRUE);
2303                         
2304                 } else
2305                         pic14_emitcode("push","psw");
2306                 
2307                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2308         }
2309         ic->bankSaved = 1;
2310 #endif
2311 }
2312
2313 /*-----------------------------------------------------------------*/
2314 /* genCall - generates a call statement                                                    */
2315 /*-----------------------------------------------------------------*/
2316 static void genCall (iCode *ic)
2317 {
2318         sym_link *dtype;         
2319         symbol *sym;
2320         unsigned char *name;
2321         int isExtern;
2322         
2323         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2324         
2325         /* if caller saves & we have not saved then */
2326         if (!ic->regsSaved)
2327                 saveRegisters(ic);
2328         
2329                 /* if we are calling a function that is not using
2330                 the same register bank then we need to save the
2331         destination registers on the stack */
2332         dtype = operandType(IC_LEFT(ic));
2333         if (currFunc && dtype && 
2334                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2335                 IFFUNC_ISISR(currFunc->type) &&
2336                 !ic->bankSaved) 
2337                 
2338                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2339         
2340         /* if send set is not empty the assign */
2341         if (_G.sendSet) {
2342                 iCode *sic;
2343                 /* For the Pic port, there is no data stack.
2344                 * So parameters passed to functions are stored
2345                 * in registers. (The pCode optimizer will get
2346                 * rid of most of these :).
2347                 */
2348                 int psuedoStkPtr=-1;
2349                 int firstTimeThruLoop = 1;
2350                 
2351                 _G.sendSet = reverseSet(_G.sendSet);
2352                 
2353                 /* First figure how many parameters are getting passed */
2354                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2355                 sic = setNextItem(_G.sendSet)) {
2356                         
2357                         aopOp(IC_LEFT(sic),sic,FALSE);
2358                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2359                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2360                 }
2361                 
2362                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2363                 sic = setNextItem(_G.sendSet)) {
2364                         int size, offset = 0;
2365                         
2366                         aopOp(IC_LEFT(sic),sic,FALSE);
2367                         size = AOP_SIZE(IC_LEFT(sic));
2368                         
2369                         while (size--) {
2370                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2371                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2372                                 
2373                                 if(!firstTimeThruLoop) {
2374                                         /* If this is not the first time we've been through the loop
2375                                         * then we need to save the parameter in a temporary
2376                                         * register. The last byte of the last parameter is
2377                                         * passed in W. */
2378                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2379                                         
2380                                 }
2381                                 firstTimeThruLoop=0;
2382                                 
2383                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2384                                 offset++;
2385                         }
2386                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2387                 }
2388                 _G.sendSet = NULL;
2389         }
2390         /* make the call */
2391         sym = OP_SYMBOL(IC_LEFT(ic));
2392         name = sym->rname[0] ? sym->rname : sym->name;
2393         isExtern = IS_EXTERN(sym->etype);
2394         if (isExtern) {
2395                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2396         }
2397         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2398         if (isExtern) {
2399                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2400         }
2401         GpsuedoStkPtr=0;
2402         /* if we need assign a result value */
2403         if ((IS_ITEMP(IC_RESULT(ic)) && 
2404                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2405                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2406                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2407                 
2408                 _G.accInUse++;
2409                 aopOp(IC_RESULT(ic),ic,FALSE);
2410                 _G.accInUse--;
2411                 
2412                 assignResultValue(IC_RESULT(ic));
2413                 
2414                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2415                         AopType(AOP_TYPE(IC_RESULT(ic))));
2416                 
2417                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2418         }
2419         
2420         /* adjust the stack for parameters if 
2421         required */
2422         if (ic->parmBytes) {
2423                 int i;
2424                 if (ic->parmBytes > 3) {
2425                         pic14_emitcode("mov","a,%s",spname);
2426                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2427                         pic14_emitcode("mov","%s,a",spname);
2428                 } else 
2429                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2430                                 pic14_emitcode("dec","%s",spname);
2431                         
2432         }
2433         
2434         /* if register bank was saved then pop them */
2435         if (ic->bankSaved)
2436                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2437         
2438         /* if we hade saved some registers then unsave them */
2439         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2440                 unsaveRegisters (ic);
2441         
2442         
2443 }
2444
2445 /*-----------------------------------------------------------------*/
2446 /* genPcall - generates a call by pointer statement                        */
2447 /*-----------------------------------------------------------------*/
2448 static void genPcall (iCode *ic)
2449 {
2450         sym_link *dtype;
2451         symbol *albl = newiTempLabel(NULL);
2452         symbol *blbl = newiTempLabel(NULL);
2453         PIC_OPCODE poc;
2454         pCodeOp *pcop;
2455         operand *left;
2456         
2457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2458         /* if caller saves & we have not saved then */
2459         if (!ic->regsSaved)
2460                 saveRegisters(ic);
2461         
2462                 /* if we are calling a function that is not using
2463                 the same register bank then we need to save the
2464         destination registers on the stack */
2465         dtype = operandType(IC_LEFT(ic));
2466         if (currFunc && dtype && 
2467                 IFFUNC_ISISR(currFunc->type) &&
2468                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2469                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2470         
2471         left = IC_LEFT(ic);
2472         aopOp(left,ic,FALSE);
2473         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2474         
2475         pushSide(IC_LEFT(ic), FPTRSIZE);
2476         
2477         /* if send set is not empty, assign parameters */
2478         if (_G.sendSet) {
2479                 
2480                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2481                 /* no way to pass args - W always gets used to make the call */
2482         }
2483         /* first idea - factor out a common helper function and call it.
2484         But don't know how to get it generated only once in its own block
2485         
2486         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2487                 char *rname;
2488                 char *buffer;
2489                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2490                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2491                 buffer = Safe_calloc(1,strlen(rname)+16);
2492                 sprintf(buffer, "%s_goto_helper", rname);
2493                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2494                 free(buffer);
2495         }
2496         */
2497         emitpcode(POC_CALL,popGetLabel(albl->key));
2498         pcop = popGetLabel(blbl->key);
2499         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2500         emitpcode(POC_GOTO,pcop);
2501         emitpLabel(albl->key);
2502         
2503         poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2504         
2505         emitpcode(poc,popGet(AOP(left),1));
2506         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2507         emitpcode(poc,popGet(AOP(left),0));
2508         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2509         
2510         emitpLabel(blbl->key);
2511         
2512         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2513         
2514         /* if we need to assign a result value */
2515         if ((IS_ITEMP(IC_RESULT(ic)) &&
2516                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2517                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2518                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2519                 
2520                 _G.accInUse++;
2521                 aopOp(IC_RESULT(ic),ic,FALSE);
2522                 _G.accInUse--;
2523                 
2524                 assignResultValue(IC_RESULT(ic));
2525                 
2526                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2527         }
2528         
2529         /* if register bank was saved then unsave them */
2530         if (currFunc && dtype && 
2531                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2532                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2533         
2534                 /* if we hade saved some registers then
2535         unsave them */
2536         if (ic->regsSaved)
2537                 unsaveRegisters (ic);
2538         
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* resultRemat - result  is rematerializable                                       */
2543 /*-----------------------------------------------------------------*/
2544 static int resultRemat (iCode *ic)
2545 {
2546         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547         if (SKIP_IC(ic) || ic->op == IFX)
2548                 return 0;
2549         
2550         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2551                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2552                 if (sym->remat && !POINTER_SET(ic)) 
2553                         return 1;
2554         }
2555         
2556         return 0;
2557 }
2558
2559 #if defined(__BORLANDC__) || defined(_MSC_VER)
2560 #define STRCASECMP stricmp
2561 #else
2562 #define STRCASECMP strcasecmp
2563 #endif
2564
2565 #if 0
2566 /*-----------------------------------------------------------------*/
2567 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2568 /*-----------------------------------------------------------------*/
2569 static bool inExcludeList(char *s)
2570 {
2571         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2572         int i =0;
2573         
2574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575         if (options.excludeRegs[i] &&
2576                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2577                 return FALSE ;
2578         
2579         for ( i = 0 ; options.excludeRegs[i]; i++) {
2580                 if (options.excludeRegs[i] &&
2581                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2582                         return TRUE;
2583         }
2584         return FALSE ;
2585 }
2586 #endif
2587
2588 /*-----------------------------------------------------------------*/
2589 /* genFunction - generated code for function entry                                 */
2590 /*-----------------------------------------------------------------*/
2591 static void genFunction (iCode *ic)
2592 {
2593         symbol *sym;
2594         sym_link *ftype;
2595         
2596         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2597         
2598         labelOffset += (max_key+4);
2599         max_key=0;
2600         GpsuedoStkPtr=0;
2601         _G.nRegsSaved = 0;
2602         /* create the function header */
2603         pic14_emitcode(";","-----------------------------------------");
2604         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2605         pic14_emitcode(";","-----------------------------------------");
2606         
2607         pic14_emitcode("","%s:",sym->rname);
2608         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2609         
2610         ftype = operandType(IC_LEFT(ic));
2611         
2612         /* if critical function then turn interrupts off */
2613         if (IFFUNC_ISCRITICAL(ftype))
2614                 pic14_emitcode("clr","ea");
2615         
2616                 /* here we need to generate the equates for the
2617         register bank if required */
2618 #if 0
2619         if (FUNC_REGBANK(ftype) != rbank) {
2620                 int i ;
2621                 
2622                 rbank = FUNC_REGBANK(ftype);
2623                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2624                         if (strcmp(regspic14[i].base,"0") == 0)
2625                                 pic14_emitcode("","%s = 0x%02x",
2626                                 regspic14[i].dname,
2627                                 8*rbank+regspic14[i].offset);
2628                         else
2629                                 pic14_emitcode ("","%s = %s + 0x%02x",
2630                                 regspic14[i].dname,
2631                                 regspic14[i].base,
2632                                 8*rbank+regspic14[i].offset);
2633                 }
2634         }
2635 #endif
2636         
2637         /* if this is an interrupt service routine */
2638         if (IFFUNC_ISISR(sym->type)) {
2639         /*  already done in pic14createInterruptVect() - delete me
2640         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2641         emitpcodeNULLop(POC_NOP);
2642         emitpcodeNULLop(POC_NOP);
2643         emitpcodeNULLop(POC_NOP);
2644                 */
2645                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2646                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2647                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2648                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2649                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2650                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2651                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2652                 
2653                 pBlockConvert2ISR(pb);
2654 #if 0  
2655                 if (!inExcludeList("acc"))              
2656                         pic14_emitcode ("push","acc");  
2657                 if (!inExcludeList("b"))
2658                         pic14_emitcode ("push","b");
2659                 if (!inExcludeList("dpl"))
2660                         pic14_emitcode ("push","dpl");
2661                 if (!inExcludeList("dph"))
2662                         pic14_emitcode ("push","dph");
2663                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2664                 {
2665                         pic14_emitcode ("push", "dpx");
2666                         /* Make sure we're using standard DPTR */
2667                         pic14_emitcode ("push", "dps");
2668                         pic14_emitcode ("mov", "dps, #0x00");
2669                         if (options.stack10bit)
2670                         { 
2671                                 /* This ISR could conceivably use DPTR2. Better save it. */
2672                                 pic14_emitcode ("push", "dpl1");
2673                                 pic14_emitcode ("push", "dph1");
2674                                 pic14_emitcode ("push", "dpx1");
2675                         }
2676                 }
2677                 /* if this isr has no bank i.e. is going to
2678                 run with bank 0 , then we need to save more
2679                 registers :-) */
2680                 if (!FUNC_REGBANK(sym->type)) {
2681                         
2682                 /* if this function does not call any other
2683                 function then we can be economical and
2684                         save only those registers that are used */
2685                         if (! IFFUNC_HASFCALL(sym->type)) {
2686                                 int i;
2687                                 
2688                                 /* if any registers used */
2689                                 if (sym->regsUsed) {
2690                                         /* save the registers used */
2691                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2692                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2693                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2694                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2695                                         }
2696                                 }
2697                                 
2698                         } else {
2699                         /* this function has    a function call cannot
2700                         determines register usage so we will have the
2701                                 entire bank */
2702                                 saverbank(0,ic,FALSE);
2703                         }       
2704                 }
2705 #endif
2706         } else {
2707         /* if callee-save to be used for this function
2708                 then save the registers being used in this function */
2709                 if (IFFUNC_CALLEESAVES(sym->type)) {
2710                         int i;
2711                         
2712                         /* if any registers used */
2713                         if (sym->regsUsed) {
2714                                 /* save the registers used */
2715                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2716                                         if (bitVectBitValue(sym->regsUsed,i) ||
2717                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2718                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2719                                                 _G.nRegsSaved++;
2720                                         }
2721                                 }
2722                         }
2723                 }
2724         }
2725         
2726         /* set the register bank to the desired value */
2727         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2728                 pic14_emitcode("push","psw");
2729                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2730         }
2731         
2732         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2733                 
2734                 if (options.useXstack) {
2735                         pic14_emitcode("mov","r0,%s",spname);
2736                         pic14_emitcode("mov","a,_bp");
2737                         pic14_emitcode("movx","@r0,a");
2738                         pic14_emitcode("inc","%s",spname);
2739                 }
2740                 else
2741                 {
2742                         /* set up the stack */
2743                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2744                 }
2745                 pic14_emitcode ("mov","_bp,%s",spname);
2746         }
2747         
2748         /* adjust the stack for the function */
2749         if (sym->stack) {
2750                 
2751                 int i = sym->stack;
2752                 if (i > 256 ) 
2753                         werror(W_STACK_OVERFLOW,sym->name);
2754                 
2755                 if (i > 3 && sym->recvSize < 4) {                
2756                         
2757                         pic14_emitcode ("mov","a,sp");
2758                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2759                         pic14_emitcode ("mov","sp,a");
2760                         
2761                 }
2762                 else
2763                         while(i--)
2764                                 pic14_emitcode("inc","sp");
2765         }
2766         
2767         if (sym->xstack) {
2768                 
2769                 pic14_emitcode ("mov","a,_spx");
2770                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2771                 pic14_emitcode ("mov","_spx,a");
2772         }
2773         
2774 }
2775
2776 /*-----------------------------------------------------------------*/
2777 /* genEndFunction - generates epilogue for functions                       */
2778 /*-----------------------------------------------------------------*/
2779 static void genEndFunction (iCode *ic)
2780 {
2781         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2782         
2783         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2784         
2785         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2786         {
2787                 pic14_emitcode ("mov","%s,_bp",spname);
2788         }
2789         
2790         /* if use external stack but some variables were
2791         added to the local stack then decrement the
2792         local stack */
2793         if (options.useXstack && sym->stack) {    
2794                 pic14_emitcode("mov","a,sp");
2795                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2796                 pic14_emitcode("mov","sp,a");
2797         }
2798         
2799         
2800         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2801                 if (options.useXstack) {
2802                         pic14_emitcode("mov","r0,%s",spname);
2803                         pic14_emitcode("movx","a,@r0");
2804                         pic14_emitcode("mov","_bp,a");
2805                         pic14_emitcode("dec","%s",spname);
2806                 }
2807                 else
2808                 {
2809                         pic14_emitcode ("pop","_bp");
2810                 }
2811         }
2812         
2813         /* restore the register bank    */        
2814         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2815                 pic14_emitcode ("pop","psw");
2816         
2817         if (IFFUNC_ISISR(sym->type)) {
2818                 
2819                 /* now we need to restore the registers */
2820                 /* if this isr has no bank i.e. is going to
2821                 run with bank 0 , then we need to save more
2822 registers :-) */
2823                 if (!FUNC_REGBANK(sym->type)) {
2824                         
2825                 /* if this function does not call any other
2826                 function then we can be economical and
2827                         save only those registers that are used */
2828                         if (! IFFUNC_HASFCALL(sym->type)) {
2829                                 int i;
2830                                 
2831                                 /* if any registers used */
2832                                 if (sym->regsUsed) {
2833                                         /* save the registers used */
2834                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2835                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2836                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2837                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2838                                         }
2839                                 }
2840                                 
2841                         } else {
2842                         /* this function has    a function call cannot
2843                         determines register usage so we will have the
2844                                 entire bank */
2845                                 unsaverbank(0,ic,FALSE);
2846                         }       
2847                 }
2848 #if 0
2849                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2850                 {
2851                         if (options.stack10bit)
2852                         {
2853                                 pic14_emitcode ("pop", "dpx1");
2854                                 pic14_emitcode ("pop", "dph1");
2855                                 pic14_emitcode ("pop", "dpl1");
2856                         } 
2857                         pic14_emitcode ("pop", "dps");
2858                         pic14_emitcode ("pop", "dpx");
2859                 }
2860                 if (!inExcludeList("dph"))
2861                         pic14_emitcode ("pop","dph");
2862                 if (!inExcludeList("dpl"))
2863                         pic14_emitcode ("pop","dpl");
2864                 if (!inExcludeList("b"))
2865                         pic14_emitcode ("pop","b");
2866                 if (!inExcludeList("acc"))
2867                         pic14_emitcode ("pop","acc");
2868                 
2869                 if (IFFUNC_ISCRITICAL(sym->type))
2870                         pic14_emitcode("setb","ea");
2871 #endif
2872                 
2873                 /* if debug then send end of function */
2874                 /*      if (options.debug && currFunc) { */
2875                 if (currFunc) {
2876                         debugFile->writeEndFunction (currFunc, ic, 1);
2877                 }
2878                 
2879                 pic14_emitcode ("reti","");
2880                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2881                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2882                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2883                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2884                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2885                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2886                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2887                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2888                 emitpcodeNULLop(POC_RETFIE);
2889         }
2890         else {
2891                 if (IFFUNC_ISCRITICAL(sym->type))
2892                         pic14_emitcode("setb","ea");
2893                 
2894                 if (IFFUNC_CALLEESAVES(sym->type)) {
2895                         int i;
2896                         
2897                         /* if any registers used */
2898                         if (sym->regsUsed) {
2899                                 /* save the registers used */
2900                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2901                                         if (bitVectBitValue(sym->regsUsed,i) ||
2902                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2903                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2904                                 }
2905                         }
2906                         
2907                 }
2908                 
2909                 /* if debug then send end of function */
2910                 if (currFunc) {
2911                         debugFile->writeEndFunction (currFunc, ic, 1);
2912                 }
2913                 
2914                 pic14_emitcode ("return","");
2915                 emitpcodeNULLop(POC_RETURN);
2916                 
2917                 /* Mark the end of a function */
2918                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2919         }
2920         
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* genRet - generate code for return statement                                     */
2925 /*-----------------------------------------------------------------*/
2926 static void genRet (iCode *ic)
2927 {
2928         int size,offset = 0 , pushed = 0;
2929         
2930         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2931         /* if we have no return value then
2932         just generate the "ret" */
2933         if (!IC_LEFT(ic)) 
2934                 goto jumpret;           
2935         
2936                 /* we have something to return then
2937         move the return value into place */
2938         aopOp(IC_LEFT(ic),ic,FALSE);
2939         size = AOP_SIZE(IC_LEFT(ic));
2940         
2941         while (size--) {
2942                 char *l ;
2943                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2944                         /* #NOCHANGE */
2945                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
2946                                 FALSE,TRUE);
2947                         pic14_emitcode("push","%s",l);
2948                         pushed++;
2949                 } else {
2950                         l = aopGet(AOP(IC_LEFT(ic)),offset,
2951                                 FALSE,FALSE);
2952                         if (strcmp(fReturn[offset],l)) {
2953                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2954                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2955                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2956                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2957                                         emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2958                                 }else {
2959                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2960                                 }
2961                                 if(size) {
2962                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2963                                 }
2964                                 offset++;
2965                         }
2966                 }
2967         }
2968         
2969         if (pushed) {
2970                 while(pushed) {
2971                         pushed--;
2972                         if (strcmp(fReturn[pushed],"a"))
2973                                 pic14_emitcode("pop",fReturn[pushed]);
2974                         else
2975                                 pic14_emitcode("pop","acc");
2976                 }
2977         }
2978         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2979         
2980 jumpret:
2981         /* generate a jump to the return label
2982         if the next is not the return statement */
2983         if (!(ic->next && ic->next->op == LABEL &&
2984                 IC_LABEL(ic->next) == returnLabel)) {
2985                 
2986                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2987                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2988         }
2989         
2990 }
2991
2992 /*-----------------------------------------------------------------*/
2993 /* genLabel - generates a label                                                                    */
2994 /*-----------------------------------------------------------------*/
2995 static void genLabel (iCode *ic)
2996 {
2997         /* special case never generate */
2998         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2999         if (IC_LABEL(ic) == entryLabel)
3000                 return ;
3001         
3002         emitpLabel(IC_LABEL(ic)->key);
3003         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3004 }
3005
3006 /*-----------------------------------------------------------------*/
3007 /* genGoto - generates a goto                                                                      */
3008 /*-----------------------------------------------------------------*/
3009 //tsd
3010 static void genGoto (iCode *ic)
3011 {
3012         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3013         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3014 }
3015
3016
3017 /*-----------------------------------------------------------------*/
3018 /* genMultbits :- multiplication of bits                                                   */
3019 /*-----------------------------------------------------------------*/
3020 static void genMultbits (operand *left, 
3021                                                  operand *right, 
3022                                                  operand *result)
3023 {
3024         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3025         
3026         if(!pic14_sameRegs(AOP(result),AOP(right)))
3027                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3028         
3029         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3030         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3031         emitpcode(POC_BCF,  popGet(AOP(result),0));
3032         
3033 }
3034
3035
3036 /*-----------------------------------------------------------------*/
3037 /* genMultOneByte : 8 bit multiplication & division                        */
3038 /*-----------------------------------------------------------------*/
3039 static void genMultOneByte (operand *left,
3040                                                         operand *right,
3041                                                         operand *result)
3042 {
3043         sym_link *opetype = operandType(result);
3044         
3045         // symbol *lbl ;
3046         int size,offset;
3047         
3048         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3049         DEBUGpic14_AopType(__LINE__,left,right,result);
3050         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3051         
3052         /* (if two literals, the value is computed before) */
3053         /* if one literal, literal on the right */
3054         if (AOP_TYPE(left) == AOP_LIT){
3055                 operand *t = right;
3056                 right = left;
3057                 left = t;
3058         }
3059         
3060         size = AOP_SIZE(result);
3061         if(size == 1) {
3062                 
3063                 if (AOP_TYPE(right) == AOP_LIT){
3064                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3065                                 aopGet(AOP(right),0,FALSE,FALSE), 
3066                                 aopGet(AOP(left),0,FALSE,FALSE), 
3067                                 aopGet(AOP(result),0,FALSE,FALSE));
3068                         pic14_emitcode("call","genMultLit");
3069                 } else {
3070                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3071                                 aopGet(AOP(right),0,FALSE,FALSE), 
3072                                 aopGet(AOP(left),0,FALSE,FALSE), 
3073                                 aopGet(AOP(result),0,FALSE,FALSE));
3074                         pic14_emitcode("call","genMult8X8_8");
3075                         
3076                 }
3077                 genMult8X8_8 (left, right,result);
3078                 
3079                 
3080                 /* signed or unsigned */
3081                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3082                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3083                 //MOVA(l);               
3084                 //pic14_emitcode("mul","ab");
3085                 /* if result size = 1, mul signed = mul unsigned */
3086                 //aopPut(AOP(result),"a",0);
3087                 
3088         } else {        // (size > 1)
3089                 
3090                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3091                         aopGet(AOP(right),0,FALSE,FALSE), 
3092                         aopGet(AOP(left),0,FALSE,FALSE), 
3093                         aopGet(AOP(result),0,FALSE,FALSE));
3094                 
3095                 if (SPEC_USIGN(opetype)){
3096                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3097                         genUMult8X8_16 (left, right, result, NULL);
3098                         
3099                         if (size > 2) {
3100                                 /* for filling the MSBs */
3101                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3102                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3103                         }
3104                 }
3105                 else{
3106                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3107                         
3108                         pic14_emitcode("mov","a,b");
3109                         
3110                         /* adjust the MSB if left or right neg */
3111                         
3112                         /* if one literal */
3113                         if (AOP_TYPE(right) == AOP_LIT){
3114                                 pic14_emitcode("multiply ","right is a lit");
3115                                 /* AND literal negative */
3116                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3117                                         /* adjust MSB (c==0 after mul) */
3118                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3119                                 }
3120                         }
3121                         else{
3122                                 genSMult8X8_16 (left, right, result, NULL);
3123                         }
3124                         
3125                         if(size > 2){
3126                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3127                                 /* get the sign */
3128                                 pic14_emitcode("rlc","a");
3129                                 pic14_emitcode("subb","a,acc");
3130                         }
3131                 }
3132                 
3133                 size -= 2;
3134                 offset = 2;
3135                 if (size > 0)
3136                         while (size--)
3137                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3138                         //aopPut(AOP(result),"a",offset++);
3139         }
3140 }
3141
3142 /*-----------------------------------------------------------------*/
3143 /* genMult - generates code for multiplication                                     */
3144 /*-----------------------------------------------------------------*/
3145 static void genMult (iCode *ic)
3146 {
3147         operand *left = IC_LEFT(ic);
3148         operand *right = IC_RIGHT(ic);
3149         operand *result= IC_RESULT(ic); 
3150         
3151         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3152         /* assign the amsops */
3153         aopOp (left,ic,FALSE);
3154         aopOp (right,ic,FALSE);
3155         aopOp (result,ic,TRUE);
3156         
3157         DEBUGpic14_AopType(__LINE__,left,right,result);
3158         
3159         /* special cases first */
3160         /* both are bits */
3161         if (AOP_TYPE(left) == AOP_CRY &&
3162                 AOP_TYPE(right)== AOP_CRY) {
3163                 genMultbits(left,right,result);
3164                 goto release ;
3165         }
3166         
3167         /* if both are of size == 1 */
3168         if (AOP_SIZE(left) == 1 &&
3169                 AOP_SIZE(right) == 1 ) {
3170                 genMultOneByte(left,right,result);
3171                 goto release ;
3172         }
3173         
3174         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3175         
3176         /* should have been converted to function call */
3177         //assert(0) ;
3178         
3179 release :
3180         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3181         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3182         freeAsmop(result,NULL,ic,TRUE); 
3183 }
3184
3185 /*-----------------------------------------------------------------*/
3186 /* genDivbits :- division of bits                                                                  */
3187 /*-----------------------------------------------------------------*/
3188 static void genDivbits (operand *left, 
3189                                                 operand *right, 
3190                                                 operand *result)
3191 {
3192         
3193         char *l;
3194         
3195         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3196         /* the result must be bit */      
3197         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3198         l = aopGet(AOP(left),0,FALSE,FALSE);
3199         
3200         MOVA(l);          
3201         
3202         pic14_emitcode("div","ab");
3203         pic14_emitcode("rrc","a");
3204         aopPut(AOP(result),"c",0);
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208 /* genDivOneByte : 8 bit division                                                                  */
3209 /*-----------------------------------------------------------------*/
3210 static void genDivOneByte (operand *left,
3211                                                    operand *right,
3212                                                    operand *result)
3213 {
3214         sym_link *opetype = operandType(result);
3215         char *l ;
3216         symbol *lbl ;
3217         int size,offset;
3218         
3219         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3220         size = AOP_SIZE(result) - 1;
3221         offset = 1;
3222         /* signed or unsigned */
3223         if (SPEC_USIGN(opetype)) {
3224                 /* unsigned is easy */
3225                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3226                 l = aopGet(AOP(left),0,FALSE,FALSE);
3227                 MOVA(l);                
3228                 pic14_emitcode("div","ab");
3229                 aopPut(AOP(result),"a",0);
3230                 while (size--)
3231                         aopPut(AOP(result),zero,offset++);
3232                 return ;
3233         }
3234         
3235         /* signed is a little bit more difficult */
3236         
3237         /* save the signs of the operands */
3238         l = aopGet(AOP(left),0,FALSE,FALSE);      
3239         MOVA(l);          
3240         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3241         pic14_emitcode("push","acc"); /* save it on the stack */
3242         
3243         /* now sign adjust for both left & right */
3244         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3245         MOVA(l);                 
3246         lbl = newiTempLabel(NULL);
3247         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3248         pic14_emitcode("cpl","a");   
3249         pic14_emitcode("inc","a");
3250         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3251         pic14_emitcode("mov","b,a");
3252         
3253         /* sign adjust left side */
3254         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3255         MOVA(l);
3256         
3257         lbl = newiTempLabel(NULL);
3258         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3259         pic14_emitcode("cpl","a");
3260         pic14_emitcode("inc","a");
3261         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3262         
3263         /* now the division */
3264         pic14_emitcode("div","ab");
3265         /* we are interested in the lower order
3266         only */
3267         pic14_emitcode("mov","b,a");
3268         lbl = newiTempLabel(NULL);
3269         pic14_emitcode("pop","acc");     
3270         /* if there was an over flow we don't 
3271         adjust the sign of the result */
3272         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3273         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3274         CLRC;
3275         pic14_emitcode("clr","a");
3276         pic14_emitcode("subb","a,b");
3277         pic14_emitcode("mov","b,a");
3278         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3279         
3280         /* now we are done */
3281         aopPut(AOP(result),"b",0);
3282         if(size > 0){
3283                 pic14_emitcode("mov","c,b.7");
3284                 pic14_emitcode("subb","a,acc");   
3285         }
3286         while (size--)
3287                 aopPut(AOP(result),"a",offset++);
3288         
3289 }
3290
3291 /*-----------------------------------------------------------------*/
3292 /* genDiv - generates code for division                                                    */
3293 /*-----------------------------------------------------------------*/
3294 static void genDiv (iCode *ic)
3295 {
3296         operand *left = IC_LEFT(ic);
3297         operand *right = IC_RIGHT(ic);
3298         operand *result= IC_RESULT(ic); 
3299         
3300         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3301         /* assign the amsops */
3302         aopOp (left,ic,FALSE);
3303         aopOp (right,ic,FALSE);
3304         aopOp (result,ic,TRUE);
3305         
3306         /* special cases first */
3307         /* both are bits */
3308         if (AOP_TYPE(left) == AOP_CRY &&
3309                 AOP_TYPE(right)== AOP_CRY) {
3310                 genDivbits(left,right,result);
3311                 goto release ;
3312         }
3313         
3314         /* if both are of size == 1 */
3315         if (AOP_SIZE(left) == 1 &&
3316                 AOP_SIZE(right) == 1 ) {
3317                 genDivOneByte(left,right,result);
3318                 goto release ;
3319         }
3320         
3321         /* should have been converted to function call */
3322         assert(0);
3323 release :
3324         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3325         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3326         freeAsmop(result,NULL,ic,TRUE); 
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* genModbits :- modulus of bits                                                                   */
3331 /*-----------------------------------------------------------------*/
3332 static void genModbits (operand *left, 
3333                                                 operand *right, 
3334                                                 operand *result)
3335 {
3336         
3337         char *l;
3338         
3339         /* the result must be bit */      
3340         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3341         l = aopGet(AOP(left),0,FALSE,FALSE);
3342         
3343         MOVA(l);
3344         
3345         pic14_emitcode("div","ab");
3346         pic14_emitcode("mov","a,b");
3347         pic14_emitcode("rrc","a");
3348         aopPut(AOP(result),"c",0);
3349 }
3350
3351 /*-----------------------------------------------------------------*/
3352 /* genModOneByte : 8 bit modulus                                                                   */
3353 /*-----------------------------------------------------------------*/
3354 static void genModOneByte (operand *left,
3355                                                    operand *right,
3356                                                    operand *result)
3357 {
3358         sym_link *opetype = operandType(result);
3359         char *l ;
3360         symbol *lbl ;
3361         
3362         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3363         /* signed or unsigned */
3364         if (SPEC_USIGN(opetype)) {
3365                 /* unsigned is easy */
3366                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3367                 l = aopGet(AOP(left),0,FALSE,FALSE);
3368                 MOVA(l);        
3369                 pic14_emitcode("div","ab");
3370                 aopPut(AOP(result),"b",0);
3371                 return ;
3372         }
3373         
3374         /* signed is a little bit more difficult */
3375         
3376         /* save the signs of the operands */
3377         l = aopGet(AOP(left),0,FALSE,FALSE);      
3378         MOVA(l);
3379         
3380         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3381         pic14_emitcode("push","acc"); /* save it on the stack */
3382         
3383         /* now sign adjust for both left & right */
3384         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3385         MOVA(l);
3386         
3387         lbl = newiTempLabel(NULL);
3388         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3389         pic14_emitcode("cpl","a");   
3390         pic14_emitcode("inc","a");
3391         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3392         pic14_emitcode("mov","b,a"); 
3393         
3394         /* sign adjust left side */
3395         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3396         MOVA(l);
3397         
3398         lbl = newiTempLabel(NULL);
3399         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3400         pic14_emitcode("cpl","a");   
3401         pic14_emitcode("inc","a");
3402         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3403         
3404         /* now the multiplication */
3405         pic14_emitcode("div","ab");
3406         /* we are interested in the lower order
3407         only */
3408         lbl = newiTempLabel(NULL);
3409         pic14_emitcode("pop","acc");     
3410         /* if there was an over flow we don't 
3411         adjust the sign of the result */
3412         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3413         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3414         CLRC ;
3415         pic14_emitcode("clr","a");
3416         pic14_emitcode("subb","a,b");
3417         pic14_emitcode("mov","b,a");
3418         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3419         
3420         /* now we are done */
3421         aopPut(AOP(result),"b",0);
3422         
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genMod - generates code for division                                                    */
3427 /*-----------------------------------------------------------------*/
3428 static void genMod (iCode *ic)
3429 {
3430         operand *left = IC_LEFT(ic);
3431         operand *right = IC_RIGHT(ic);
3432         operand *result= IC_RESULT(ic);  
3433         
3434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3435         /* assign the amsops */
3436         aopOp (left,ic,FALSE);
3437         aopOp (right,ic,FALSE);
3438         aopOp (result,ic,TRUE);
3439         
3440         /* special cases first */
3441         /* both are bits */
3442         if (AOP_TYPE(left) == AOP_CRY &&
3443                 AOP_TYPE(right)== AOP_CRY) {
3444                 genModbits(left,right,result);
3445                 goto release ;
3446         }
3447         
3448         /* if both are of size == 1 */
3449         if (AOP_SIZE(left) == 1 &&
3450                 AOP_SIZE(right) == 1 ) {
3451                 genModOneByte(left,right,result);
3452                 goto release ;
3453         }
3454         
3455         /* should have been converted to function call */
3456         assert(0);
3457         
3458 release :
3459         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3460         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3461         freeAsmop(result,NULL,ic,TRUE); 
3462 }
3463
3464 /*-----------------------------------------------------------------*/
3465 /* genIfxJump :- will create a jump depending on the ifx                   */
3466 /*-----------------------------------------------------------------*/
3467 /*
3468 note: May need to add parameter to indicate when a variable is in bit space.
3469 */
3470 static void genIfxJump (iCode *ic, char *jval)
3471 {
3472         
3473         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3474         /* if true label then we jump if condition
3475         supplied is true */
3476         if ( IC_TRUE(ic) ) {
3477                 
3478                 if(strcmp(jval,"a") == 0)
3479                         emitSKPZ;
3480                 else if (strcmp(jval,"c") == 0)
3481                         emitSKPC;
3482                 else {
3483                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3484                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3485                 }
3486                 
3487                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3488                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3489                 
3490         }
3491         else {
3492                 /* false label is present */
3493                 if(strcmp(jval,"a") == 0)
3494                         emitSKPNZ;
3495                 else if (strcmp(jval,"c") == 0)
3496                         emitSKPNC;
3497                 else {
3498                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3499                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3500                 }
3501                 
3502                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3503                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3504                 
3505         }
3506         
3507         
3508         /* mark the icode as generated */
3509         ic->generated = 1;
3510 }
3511
3512 /*-----------------------------------------------------------------*/
3513 /* genSkip                                                                                                                 */
3514 /*-----------------------------------------------------------------*/
3515 static void genSkip(iCode *ifx,int status_bit)
3516 {
3517         if(!ifx)
3518                 return;
3519         
3520         if ( IC_TRUE(ifx) ) {
3521                 switch(status_bit) {
3522                 case 'z':
3523                         emitSKPNZ;
3524                         break;
3525                         
3526                 case 'c':
3527                         emitSKPNC;
3528                         break;
3529                         
3530                 case 'd':
3531                         emitSKPDC;
3532                         break;
3533                         
3534                 }
3535                 
3536                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3537                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3538                 
3539         } else {
3540                 
3541                 switch(status_bit) {
3542                         
3543                 case 'z':
3544                         emitSKPZ;
3545                         break;
3546                         
3547                 case 'c':
3548                         emitSKPC;
3549                         break;
3550                         
3551                 case 'd':
3552                         emitSKPDC;
3553                         break;
3554                 }
3555                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3556                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3557                 
3558         }
3559         
3560 }
3561
3562 /*-----------------------------------------------------------------*/
3563 /* genSkipc                                                                                                        */
3564 /*-----------------------------------------------------------------*/
3565 static void genSkipc(resolvedIfx *rifx)
3566 {
3567         if(!rifx)
3568                 return;
3569         
3570         if(rifx->condition)
3571                 emitSKPC;
3572         else
3573                 emitSKPNC;
3574         
3575         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3576         rifx->generated = 1;
3577 }
3578
3579 /*-----------------------------------------------------------------*/
3580 /* genSkipz2                                                                                                       */
3581 /*-----------------------------------------------------------------*/
3582 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3583 {
3584         if(!rifx)
3585                 return;
3586         
3587         if( (rifx->condition ^ invert_condition) & 1)
3588                 emitSKPZ;
3589         else
3590                 emitSKPNZ;
3591         
3592         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3593         rifx->generated = 1;
3594 }
3595
3596 /*-----------------------------------------------------------------*/
3597 /* genSkipz                                                        */
3598 /*-----------------------------------------------------------------*/
3599 static void genSkipz(iCode *ifx, int condition)
3600 {
3601         if(!ifx)
3602                 return;
3603         
3604         if(condition)
3605                 emitSKPNZ;
3606         else
3607                 emitSKPZ;
3608         
3609         if ( IC_TRUE(ifx) )
3610                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3611         else
3612                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3613         
3614         if ( IC_TRUE(ifx) )
3615                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3616         else
3617                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3618         
3619 }
3620 /*-----------------------------------------------------------------*/
3621 /* genSkipCond                                                     */
3622 /*-----------------------------------------------------------------*/
3623 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3624 {
3625         if(!rifx)
3626                 return;
3627         
3628         if(rifx->condition)
3629                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3630         else
3631                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3632         
3633         
3634         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3635         rifx->generated = 1;
3636 }
3637
3638 #if 0
3639 /*-----------------------------------------------------------------*/
3640 /* genChkZeroes :- greater or less than comparison                 */
3641 /*     For each byte in a literal that is zero, inclusive or the   */
3642 /*     the corresponding byte in the operand with W                */
3643 /*     returns true if any of the bytes are zero                   */
3644 /*-----------------------------------------------------------------*/
3645 static int genChkZeroes(operand *op, int lit,  int size)
3646 {
3647         
3648         int i;
3649         int flag =1;
3650         
3651         while(size--) {
3652                 i = (lit >> (size*8)) & 0xff;
3653                 
3654                 if(i==0) {
3655                         if(flag) 
3656                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3657                         else
3658                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3659                         flag = 0;
3660                 }
3661         }
3662         
3663         return (flag==0);
3664 }
3665 #endif
3666
3667 /*-----------------------------------------------------------------*/
3668 /* genCmp :- greater or less than comparison                       */
3669 /*-----------------------------------------------------------------*/
3670 static void genCmp (operand *left,operand *right,
3671                                         operand *result, iCode *ifx, int sign)
3672 {
3673         int size; //, offset = 0 ;
3674         unsigned long lit = 0L,i = 0;
3675         resolvedIfx rFalseIfx;
3676         //  resolvedIfx rTrueIfx;
3677         symbol *truelbl;
3678         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3679         /*
3680         if(ifx) {
3681         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3682         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3683         }
3684         */
3685         
3686         resolveIfx(&rFalseIfx,ifx);
3687         truelbl  = newiTempLabel(NULL);
3688         size = max(AOP_SIZE(left),AOP_SIZE(right));
3689         
3690         DEBUGpic14_AopType(__LINE__,left,right,result);
3691         
3692 #define _swapp
3693         
3694         /* if literal is on the right then swap with left */
3695         if ((AOP_TYPE(right) == AOP_LIT)) {
3696                 operand *tmp = right ;
3697                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3698                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3699 #ifdef _swapp
3700                 
3701                 lit = (lit - 1) & mask;
3702                 right = left;
3703                 left = tmp;
3704                 rFalseIfx.condition ^= 1;
3705 #endif
3706                 
3707         } else if ((AOP_TYPE(left) == AOP_LIT)) {
3708                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3709         }
3710         
3711         
3712         //if(IC_TRUE(ifx) == NULL)
3713         /* if left & right are bit variables */
3714         if (AOP_TYPE(left) == AOP_CRY &&
3715                 AOP_TYPE(right) == AOP_CRY ) {
3716                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3717                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3718         } else {
3719         /* subtract right from left if at the
3720         end the carry flag is set then we know that
3721                 left is greater than right */
3722                 
3723                 symbol *lbl  = newiTempLabel(NULL);
3724                 
3725 #ifndef _swapp
3726                 if(AOP_TYPE(right) == AOP_LIT) {
3727                         
3728                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3729                         
3730                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3731                         
3732                         /* special cases */
3733                         
3734                         if(lit == 0) {
3735                                 
3736                                 if(sign != 0) 
3737                                         genSkipCond(&rFalseIfx,left,size-1,7);
3738                                 else 
3739                                         /* no need to compare to 0...*/
3740                                         /* NOTE: this is a de-generate compare that most certainly 
3741                                         *       creates some dead code. */
3742                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3743                                 
3744                                 if(ifx) ifx->generated = 1;
3745                                 return;
3746                                 
3747                         }
3748                         size--;
3749                         
3750                         if(size == 0) {
3751                                 //i = (lit >> (size*8)) & 0xff;
3752                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3753                                 
3754                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3755                                 
3756                                 i = ((0-lit) & 0xff);
3757                                 if(sign) {
3758                                         if( i == 0x81) { 
3759                                         /* lit is 0x7f, all signed chars are less than
3760                                                 * this except for 0x7f itself */
3761                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
3762                                                 genSkipz2(&rFalseIfx,0);
3763                                         } else {
3764                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
3765                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3766                                                 genSkipc(&rFalseIfx);
3767                                         }
3768                                         
3769                                 } else {
3770                                         if(lit == 1) {
3771                                                 genSkipz2(&rFalseIfx,1);
3772                                         } else {
3773                                                 emitpcode(POC_ADDLW, popGetLit(i));
3774                                                 genSkipc(&rFalseIfx);
3775                                         }
3776                                 }
3777                                 
3778                                 if(ifx) ifx->generated = 1;
3779                                 return;
3780                         }
3781                         
3782                         /* chars are out of the way. now do ints and longs */
3783                         
3784                         
3785                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3786                         
3787                         /* special cases */
3788                         
3789                         if(sign) {
3790                                 
3791                                 if(lit == 0) {
3792                                         genSkipCond(&rFalseIfx,left,size,7);
3793                                         if(ifx) ifx->generated = 1;
3794                                         return;
3795                                 }
3796                                 
3797                                 if(lit <0x100) {
3798                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3799                                         
3800                                         //rFalseIfx.condition ^= 1;
3801                                         //genSkipCond(&rFalseIfx,left,size,7);
3802                                         //rFalseIfx.condition ^= 1;
3803                                         
3804                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3805                                         if(rFalseIfx.condition)
3806                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3807                                         else
3808                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3809                                         
3810                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3811                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
3812                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
3813                                         
3814                                         while(size > 1)
3815                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3816                                         
3817                                         if(rFalseIfx.condition) {
3818                                                 emitSKPZ;
3819                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3820                                                 
3821                                         } else {
3822                                                 emitSKPNZ;
3823                                         }
3824                                         
3825                                         genSkipc(&rFalseIfx);
3826                                         emitpLabel(truelbl->key);
3827                                         if(ifx) ifx->generated = 1;
3828                                         return;
3829                                         
3830                                 }
3831                                 
3832                                 if(size == 1) {
3833                                         
3834                                         if( (lit & 0xff) == 0) {
3835                                                 /* lower byte is zero */
3836                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3837                                                 i = ((lit >> 8) & 0xff) ^0x80;
3838                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3839                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3840                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3841                                                 genSkipc(&rFalseIfx);
3842                                                 
3843                                                 
3844                                                 if(ifx) ifx->generated = 1;
3845                                                 return;
3846                                                 
3847                                         }
3848                                 } else {
3849                                         /* Special cases for signed longs */
3850                                         if( (lit & 0xffffff) == 0) {
3851                                                 /* lower byte is zero */
3852                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3853                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
3854                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3855                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3856                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3857                                                 genSkipc(&rFalseIfx);
3858                                                 
3859                                                 
3860                                                 if(ifx) ifx->generated = 1;
3861                                                 return;
3862                                                 
3863                                         }
3864                                         
3865                                 }
3866                                 
3867                                 
3868                                 if(lit & (0x80 << (size*8))) {
3869                                         /* lit is negative */
3870                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3871                                         
3872                                         //genSkipCond(&rFalseIfx,left,size,7);
3873                                         
3874                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3875                                         
3876                                         if(rFalseIfx.condition)
3877                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3878                                         else
3879                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3880                                         
3881                                         
3882                                 } else {
3883                                         /* lit is positive */
3884                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3885                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3886                                         if(rFalseIfx.condition)
3887                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3888                                         else
3889                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3890                                         
3891                                 }
3892                                 
3893                                 /* There are no more special cases, so perform a general compare */
3894                                 
3895                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3896                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
3897                                 
3898                                 while(size--) {
3899                                         
3900                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3901                                         emitSKPNZ;
3902                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3903                                 }
3904                                 //rFalseIfx.condition ^= 1;
3905                                 genSkipc(&rFalseIfx);
3906                                 
3907                                 emitpLabel(truelbl->key);
3908                                 
3909                                 if(ifx) ifx->generated = 1;
3910                                 return;
3911                                 
3912                                 
3913                         }
3914
3915
3916                         /* sign is out of the way. So now do an unsigned compare */
3917                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3918
3919
3920                         /* General case - compare to an unsigned literal on the right.*/
3921
3922                         i = (lit >> (size*8)) & 0xff;
3923                         emitpcode(POC_MOVLW, popGetLit(i));
3924                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3925                         while(size--) {
3926                                 i = (lit >> (size*8)) & 0xff;
3927                                 
3928                                 if(i) {
3929                                         emitpcode(POC_MOVLW, popGetLit(i));
3930                                         emitSKPNZ;
3931                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3932                                 } else {
3933                                 /* this byte of the lit is zero, 
3934                                         *if it's not the last then OR in the variable */
3935                                         if(size)
3936                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
3937                                 }
3938                         }
3939
3940
3941                 emitpLabel(lbl->key);
3942                 //if(emitFinalCheck)
3943                 genSkipc(&rFalseIfx);
3944                 if(sign)
3945                         emitpLabel(truelbl->key);
3946
3947                 if(ifx) ifx->generated = 1;
3948                 return;
3949
3950
3951                 }
3952 #endif  // _swapp
3953
3954                 if(AOP_TYPE(left) == AOP_LIT) {
3955                         //symbol *lbl = newiTempLabel(NULL);
3956                         
3957                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3958                         
3959                         
3960                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3961                         
3962                         /* Special cases */
3963                         if((lit == 0) && (sign == 0)){
3964                                 
3965                                 size--;
3966                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3967                                 while(size) 
3968                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
3969                                 
3970                                 genSkipz2(&rFalseIfx,0);
3971                                 if(ifx) ifx->generated = 1;
3972                                 return;
3973                         }
3974                         
3975                         if(size==1) {
3976                                 /* Special cases */
3977                                 lit &= 0xff;
3978                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3979                                         /* degenerate compare can never be true */
3980                                         if(rFalseIfx.condition == 0)
3981                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3982                                         
3983                                         if(ifx) ifx->generated = 1;
3984                                         return;
3985                                 }
3986                                 
3987                                 if(sign) {
3988                                         /* signed comparisons to a literal byte */
3989                                         
3990                                         int lp1 = (lit+1) & 0xff;
3991                                         
3992                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
3993                                         switch (lp1) {
3994                                         case 0:
3995                                                 rFalseIfx.condition ^= 1;
3996                                                 genSkipCond(&rFalseIfx,right,0,7);
3997                                                 break;
3998                                         case 0x7f:
3999                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4000                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4001                                                 genSkipz2(&rFalseIfx,1);
4002                                                 break;
4003                                         default:
4004                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4005                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4006                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4007                                                 rFalseIfx.condition ^= 1;
4008                                                 genSkipc(&rFalseIfx);
4009                                                 break;
4010                                         }
4011                                         if(ifx) ifx->generated = 1;
4012                                 } else {
4013                                         /* unsigned comparisons to a literal byte */
4014                                         
4015                                         switch(lit & 0xff ) {
4016                                         case 0:
4017                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4018                                                 genSkipz2(&rFalseIfx,0);
4019                                                 if(ifx) ifx->generated = 1;
4020                                                 break;
4021                                         case 0x7f:
4022                                                 genSkipCond(&rFalseIfx,right,0,7);
4023                                                 if(ifx) ifx->generated = 1;
4024                                                 break;
4025                                                 
4026                                         default:
4027                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4028                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4029                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4030                                                 rFalseIfx.condition ^= 1;
4031                                                 if (AOP_TYPE(result) == AOP_CRY) {
4032                                                         genSkipc(&rFalseIfx);
4033                                                         if(ifx) ifx->generated = 1;
4034                                                 } else {
4035                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4036                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4037                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4038                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4039                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4040                                                 }       
4041                                                 break;
4042                                         }
4043                                 }
4044                                 
4045                                 //goto check_carry;
4046                                 return;
4047                                 
4048                         } else {
4049                                 
4050                                 /* Size is greater than 1 */
4051                                 
4052                                 if(sign) {
4053                                         int lp1 = lit+1;
4054                                         
4055                                         size--;
4056                                         
4057                                         if(lp1 == 0) {
4058                                                 /* this means lit = 0xffffffff, or -1 */
4059                                                 
4060                                                 
4061                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4062                                                 rFalseIfx.condition ^= 1;
4063                                                 genSkipCond(&rFalseIfx,right,size,7);
4064                                                 if(ifx) ifx->generated = 1;
4065                                                 return;
4066                                         }
4067                                         
4068                                         if(lit == 0) {
4069                                                 int s = size;
4070                                                 
4071                                                 if(rFalseIfx.condition) {
4072                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4073                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4074                                                 }
4075                                                 
4076                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4077                                                 while(size--)
4078                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4079                                                 
4080                                                 
4081                                                 emitSKPZ;
4082                                                 if(rFalseIfx.condition) {
4083                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4084                                                         emitpLabel(truelbl->key);
4085                                                 }else {
4086                                                         rFalseIfx.condition ^= 1;
4087                                                         genSkipCond(&rFalseIfx,right,s,7);
4088                                                 }
4089                                                 
4090                                                 if(ifx) ifx->generated = 1;
4091                                                 return;
4092                                         }
4093                                         
4094                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4095                                                 /* lower byte of signed word is zero */
4096                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4097                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4098                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4099                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4100                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4101                                                 rFalseIfx.condition ^= 1;
4102                                                 genSkipc(&rFalseIfx);
4103                                                 
4104                                                 
4105                                                 if(ifx) ifx->generated = 1;
4106                                                 return;
4107                                         }
4108                                         
4109                                         if(lit & (0x80 << (size*8))) {
4110                                                 /* Lit is less than zero */
4111                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4112                                                 //rFalseIfx.condition ^= 1;
4113                                                 //genSkipCond(&rFalseIfx,left,size,7);
4114                                                 //rFalseIfx.condition ^= 1;
4115                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4116                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4117                                                 
4118                                                 if(rFalseIfx.condition)
4119                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4120                                                 else
4121                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4122                                                 
4123                                                 
4124                                         } else {
4125                                                 /* Lit is greater than or equal to zero */
4126                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4127                                                 //rFalseIfx.condition ^= 1;
4128                                                 //genSkipCond(&rFalseIfx,right,size,7);
4129                                                 //rFalseIfx.condition ^= 1;
4130                                                 
4131                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4132                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4133                                                 
4134                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4135                                                 if(rFalseIfx.condition)
4136                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4137                                                 else
4138                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4139                                                 
4140                                         }
4141                                         
4142                                         
4143                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4144                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4145                                         
4146                                         while(size--) {
4147                                                 
4148                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4149                                                 emitSKPNZ;
4150                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4151                                         }
4152                                         rFalseIfx.condition ^= 1;
4153                                         //rFalseIfx.condition = 1;
4154                                         genSkipc(&rFalseIfx);
4155                                         
4156                                         emitpLabel(truelbl->key);
4157                                         
4158                                         if(ifx) ifx->generated = 1;
4159                                         return;
4160                                         // end of if (sign)
4161                                 } else {
4162                                         
4163                                         /* compare word or long to an unsigned literal on the right.*/
4164                                         
4165                                         
4166                                         size--;
4167                                         if(lit < 0xff) {
4168                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4169                                                 switch (lit) {
4170                                                 case 0:
4171                                                         break; /* handled above */
4172                                                 /*
4173                                                 case 0xff:
4174                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4175                                                         while(size--)
4176                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4177                                                         genSkipz2(&rFalseIfx,0);
4178                                                         break;
4179                                                 */
4180                                                 default:
4181                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4182                                                         while(--size)
4183                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4184                                                         
4185                                                         emitSKPZ;
4186                                                         if(rFalseIfx.condition)
4187                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4188                                                         else
4189                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4190                                                         
4191                                                         
4192                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4193                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4194                                                         
4195                                                         rFalseIfx.condition ^= 1;
4196                                                         genSkipc(&rFalseIfx);
4197                                                 }
4198                                                 
4199                                                 emitpLabel(truelbl->key);
4200                                                 
4201                                                 if(ifx) ifx->generated = 1;
4202                                                 return;
4203                                         }
4204                                         
4205                                         
4206                                         lit++;
4207                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4208                                         i = (lit >> (size*8)) & 0xff;
4209                                         
4210                                         emitpcode(POC_MOVLW, popGetLit(i));
4211                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4212                                         
4213                                         while(size--) {
4214                                                 i = (lit >> (size*8)) & 0xff;
4215                                                 
4216                                                 if(i) {
4217                                                         emitpcode(POC_MOVLW, popGetLit(i));
4218                                                         emitSKPNZ;
4219                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4220                                                 } else {
4221                                                 /* this byte of the lit is zero, 
4222                                                         *if it's not the last then OR in the variable */
4223                                                         if(size)
4224                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4225                                                 }
4226                                         }
4227                                         
4228                                         
4229                                         emitpLabel(lbl->key);
4230                                         
4231                                         rFalseIfx.condition ^= 1;
4232                                         genSkipc(&rFalseIfx);
4233                                 }
4234                                 
4235                                 if(sign)
4236                                         emitpLabel(truelbl->key);
4237                                 if(ifx) ifx->generated = 1;
4238                                 return;
4239                         }
4240                 }
4241                 /* Compare two variables */
4242                 
4243                 DEBUGpic14_emitcode(";sign","%d",sign);
4244                 
4245                 size--;
4246                 if(sign) {
4247                         /* Sigh. thus sucks... */
4248                         if(size) {
4249                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4250                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4251                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4252                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4253                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4254                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4255                         } else {
4256                                 /* Signed char comparison */
4257                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4258                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4259                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4260                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4261                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4262                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4263                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4264                                 
4265                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4266                                 genSkipc(&rFalseIfx);
4267                                 
4268                                 if(ifx) ifx->generated = 1;
4269                                 return;
4270                         }
4271                         
4272                 } else {
4273                         
4274                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4275                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4276                 }
4277                 
4278                 
4279                 /* The rest of the bytes of a multi-byte compare */
4280                 while (size) {
4281                         
4282                         emitSKPZ;
4283                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4284                         size--;
4285                         
4286                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4287                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4288                         
4289                         
4290                 }
4291                 
4292                 emitpLabel(lbl->key);
4293                 
4294                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4295                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4296                         (AOP_TYPE(result) == AOP_REG)) {
4297                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4298                         emitpcode(POC_RLF, popGet(AOP(result),0));
4299                 } else {
4300                         genSkipc(&rFalseIfx);
4301                 }       
4302                 //genSkipc(&rFalseIfx);
4303                 if(ifx) ifx->generated = 1;
4304                 
4305                 return;
4306                 
4307         }
4308         
4309         // check_carry:
4310         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4311                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4312                 pic14_outBitC(result);
4313         } else {
4314                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4315                 /* if the result is used in the next
4316                 ifx conditional branch then generate
4317                 code a little differently */
4318                 if (ifx )
4319                         genIfxJump (ifx,"c");
4320                 else
4321                         pic14_outBitC(result);
4322                 /* leave the result in acc */
4323         }
4324         
4325 }
4326
4327 /*-----------------------------------------------------------------*/
4328 /* genCmpGt :- greater than comparison                             */
4329 /*-----------------------------------------------------------------*/
4330 static void genCmpGt (iCode *ic, iCode *ifx)
4331 {
4332         operand *left, *right, *result;
4333         sym_link *letype , *retype;
4334         int sign ;
4335         
4336         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4337         left = IC_LEFT(ic);
4338         right= IC_RIGHT(ic);
4339         result = IC_RESULT(ic);
4340         
4341         letype = getSpec(operandType(left));
4342         retype =getSpec(operandType(right));
4343         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4344         /* assign the amsops */
4345         aopOp (left,ic,FALSE);
4346         aopOp (right,ic,FALSE);
4347         aopOp (result,ic,TRUE);
4348         
4349         genCmp(right, left, result, ifx, sign);
4350         
4351         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4352         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353         freeAsmop(result,NULL,ic,TRUE); 
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /* genCmpLt - less than comparisons                                */
4358 /*-----------------------------------------------------------------*/
4359 static void genCmpLt (iCode *ic, iCode *ifx)
4360 {
4361         operand *left, *right, *result;
4362         sym_link *letype , *retype;
4363         int sign ;
4364         
4365         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4366         left = IC_LEFT(ic);
4367         right= IC_RIGHT(ic);
4368         result = IC_RESULT(ic);
4369         
4370         letype = getSpec(operandType(left));
4371         retype =getSpec(operandType(right));
4372         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4373         
4374         /* assign the amsops */
4375         aopOp (left,ic,FALSE);
4376         aopOp (right,ic,FALSE);
4377         aopOp (result,ic,TRUE);
4378         
4379         genCmp(left, right, result, ifx, sign);
4380         
4381         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4382         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383         freeAsmop(result,NULL,ic,TRUE); 
4384 }
4385
4386 /*-----------------------------------------------------------------*/
4387 /* genc16bit2lit - compare a 16 bit value to a literal             */
4388 /*-----------------------------------------------------------------*/
4389 static void genc16bit2lit(operand *op, int lit, int offset)
4390 {
4391         int i;
4392         
4393         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4394         if( (lit&0xff) == 0) 
4395                 i=1;
4396         else
4397                 i=0;
4398         
4399         switch( BYTEofLONG(lit,i)) { 
4400         case 0:
4401                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4402                 break;
4403         case 1:
4404                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4405                 break;
4406         case 0xff:
4407                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4408                 break;
4409         default:
4410                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4411                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4412         }
4413         
4414         i ^= 1;
4415         
4416         switch( BYTEofLONG(lit,i)) { 
4417         case 0:
4418                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4419                 break;
4420         case 1:
4421                 emitSKPNZ;
4422                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4423                 break;
4424         case 0xff:
4425                 emitSKPNZ;
4426                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4427                 break;
4428         default:
4429                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4430                 emitSKPNZ;
4431                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4432                 
4433         }
4434         
4435 }
4436
4437 /*-----------------------------------------------------------------*/
4438 /* gencjneshort - compare and jump if not equal                    */
4439 /*-----------------------------------------------------------------*/
4440 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4441 {
4442         int size = max(AOP_SIZE(left),AOP_SIZE(right));
4443         int offset = 0;
4444         int res_offset = 0;  /* the result may be a different size then left or right */
4445         int res_size = AOP_SIZE(result);
4446         resolvedIfx rIfx;
4447         symbol *lbl;
4448         
4449         unsigned long lit = 0L;
4450         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4451         DEBUGpic14_AopType(__LINE__,left,right,result);
4452         if(result)
4453                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4454         resolveIfx(&rIfx,ifx);
4455         lbl =  newiTempLabel(NULL);
4456         
4457         
4458         /* if the left side is a literal or 
4459         if the right is in a pointer register and left 
4460         is not */
4461         if ((AOP_TYPE(left) == AOP_LIT) || 
4462                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4463                 operand *t = right;
4464                 right = left;
4465                 left = t;
4466         }
4467         if(AOP_TYPE(right) == AOP_LIT)
4468                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4469         
4470         /* if the right side is a literal then anything goes */
4471         if (AOP_TYPE(right) == AOP_LIT &&
4472                 AOP_TYPE(left) != AOP_DIR ) {
4473                 switch(size) {
4474                 case 2:
4475                         genc16bit2lit(left, lit, 0);
4476                         emitSKPNZ;
4477                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4478                         break;
4479                 default:
4480                         while (size--) {
4481                                 if(lit & 0xff) {
4482                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4483                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4484                                 } else {
4485                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4486                                 }
4487                                 
4488                                 emitSKPNZ;
4489                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4490                                 offset++;
4491                                 if(res_offset < res_size-1)
4492                                         res_offset++;
4493                                 lit >>= 8;
4494                         }
4495                         break;
4496                 }
4497         }
4498         
4499         /* if the right side is in a register or in direct space or
4500         if the left is a pointer register & right is not */    
4501         else if (AOP_TYPE(right) == AOP_REG ||
4502                 AOP_TYPE(right) == AOP_DIR || 
4503                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4504                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4505                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4506                 int lbl_key = lbl->key;
4507                 
4508                 if(result) {
4509                         emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4510                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4511                 }else {
4512                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4513                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4514                                 __FUNCTION__,__LINE__);
4515                         return;
4516                 }
4517                 
4518                 /*     switch(size) { */
4519                 /*     case 2: */
4520                 /*       genc16bit2lit(left, lit, 0); */
4521                 /*       emitSKPNZ; */
4522                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4523                 /*       break; */
4524                 /*     default: */
4525                 while (size--) {
4526                         int emit_skip=1;
4527                         if((AOP_TYPE(left) == AOP_DIR) && 
4528                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4529                                 
4530                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4531                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4532                                 
4533                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4534                                 
4535                                 switch (lit & 0xff) {
4536                                 case 0:
4537                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4538                                         break;
4539                                 case 1:
4540                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4541                                         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4542                                         //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4543                                         emit_skip=0;
4544                                         break;
4545                                 case 0xff:
4546                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4547                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4548                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4549                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4550                                         emit_skip=0;
4551                                         break;
4552                                 default:
4553                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4554                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4555                                 }
4556                                 lit >>= 8;
4557                                 
4558                         } else {
4559                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4560                         }
4561                         if(emit_skip) {
4562                                 if(AOP_TYPE(result) == AOP_CRY) {
4563                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4564                                         if(rIfx.condition)
4565                                                 emitSKPNZ;
4566                                         else
4567                                                 emitSKPZ;
4568                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4569                                 } else {
4570                                         /* fix me. probably need to check result size too */
4571                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4572                                         if(rIfx.condition)
4573                                                 emitSKPZ;
4574                                         else
4575                                                 emitSKPNZ;
4576                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4577                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4578                                 }
4579                                 if(ifx)
4580                                         ifx->generated=1;
4581                         }
4582                         emit_skip++;
4583                         offset++;
4584                         if(res_offset < res_size-1)
4585                                 res_offset++;
4586                 }
4587                 /*       break; */
4588                 /*     } */
4589         } else if(AOP_TYPE(right) == AOP_REG &&
4590                 AOP_TYPE(left) != AOP_DIR){
4591                 
4592                 while(size--) {
4593                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4594                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4595                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4596                         if(rIfx.condition)
4597                                 emitSKPNZ;
4598                         else
4599                                 emitSKPZ;
4600                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4601                         offset++;
4602                         if(res_offset < res_size-1)
4603                                 res_offset++;
4604                 }
4605                 
4606         }else{
4607                 /* right is a pointer reg need both a & b */
4608                 while(size--) {
4609                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4610                         if(strcmp(l,"b"))
4611                                 pic14_emitcode("mov","b,%s",l);
4612                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4613                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4614                         offset++;
4615                 }
4616         }
4617         
4618         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4619         if(!rIfx.condition)
4620                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4621         
4622         emitpLabel(lbl->key);
4623         
4624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4625         
4626         if(ifx)
4627                 ifx->generated = 1;
4628 }
4629
4630 #if 0
4631 /*-----------------------------------------------------------------*/
4632 /* gencjne - compare and jump if not equal                         */
4633 /*-----------------------------------------------------------------*/
4634 static void gencjne(operand *left, operand *right, iCode *ifx)
4635 {
4636         symbol *tlbl  = newiTempLabel(NULL);
4637         
4638         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4639         gencjneshort(left, right, lbl);
4640         
4641         pic14_emitcode("mov","a,%s",one);
4642         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4643         pic14_emitcode("","%05d_DS_:",lbl->key+100);
4644         pic14_emitcode("clr","a");
4645         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4646         
4647         emitpLabel(lbl->key);
4648         emitpLabel(tlbl->key);
4649         
4650 }
4651 #endif
4652
4653 /*-----------------------------------------------------------------*/
4654 /* genCmpEq - generates code for equal to                          */
4655 /*-----------------------------------------------------------------*/
4656 static void genCmpEq (iCode *ic, iCode *ifx)
4657 {
4658         operand *left, *right, *result;
4659         unsigned long lit = 0L;
4660         int size,offset=0;
4661         
4662         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4663         
4664         if(ifx)
4665                 DEBUGpic14_emitcode ("; ifx is non-null","");
4666         else
4667                 DEBUGpic14_emitcode ("; ifx is null","");
4668         
4669         aopOp((left=IC_LEFT(ic)),ic,FALSE);
4670         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4671         aopOp((result=IC_RESULT(ic)),ic,TRUE);
4672         
4673         size = max(AOP_SIZE(left),AOP_SIZE(right));
4674         
4675         DEBUGpic14_AopType(__LINE__,left,right,result);
4676         
4677         /* if literal, literal on the right or 
4678         if the right is in a pointer register and left 
4679         is not */
4680         if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4681                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4682                 operand *tmp = right ;
4683                 right = left;
4684                 left = tmp;
4685         }
4686         
4687         
4688         if(ifx && !AOP_SIZE(result)){
4689                 symbol *tlbl;
4690                 /* if they are both bit variables */
4691                 if (AOP_TYPE(left) == AOP_CRY &&
4692                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4693                         if(AOP_TYPE(right) == AOP_LIT){
4694                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4695                                 if(lit == 0L){
4696                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4697                                         pic14_emitcode("cpl","c");
4698                                 } else if(lit == 1L) {
4699                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4700                                 } else {
4701                                         pic14_emitcode("clr","c");
4702                                 }
4703                                 /* AOP_TYPE(right) == AOP_CRY */
4704                         } else {
4705                                 symbol *lbl = newiTempLabel(NULL);
4706                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4707                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4708                                 pic14_emitcode("cpl","c");
4709                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4710                         }
4711                         /* if true label then we jump if condition
4712                         supplied is true */
4713                         tlbl = newiTempLabel(NULL);
4714                         if ( IC_TRUE(ifx) ) {
4715                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4716                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4717                         } else {
4718                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4719                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4720                         }
4721                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4722                         
4723                         {
4724                                 /* left and right are both bit variables, result is carry */
4725                                 resolvedIfx rIfx;
4726                                 
4727                                 resolveIfx(&rIfx,ifx);
4728                                 
4729                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4730                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4731                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4732                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4733                                 genSkipz2(&rIfx,0);
4734                         }
4735                 } else {
4736                         
4737                         /* They're not both bit variables. Is the right a literal? */
4738                         if(AOP_TYPE(right) == AOP_LIT) {
4739                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4740                                 
4741                                 switch(size) {
4742                                         
4743                                 case 1:
4744                                         switch(lit & 0xff) {
4745                                         case 1:
4746                                                 if ( IC_TRUE(ifx) ) {
4747                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
4748                                                         emitSKPNZ;
4749                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4750                                                 } else {
4751                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4752                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4753                                                 }
4754                                                 break;
4755                                         case 0xff:
4756                                                 if ( IC_TRUE(ifx) ) {
4757                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
4758                                                         emitSKPNZ;
4759                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4760                                                 } else {
4761                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4762                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4763                                                 }
4764                                                 break;
4765                                         default:
4766                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4767                                                 if(lit)
4768                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4769                                                 genSkip(ifx,'z');
4770                                         }
4771                                         
4772                                         
4773                                         /* end of size == 1 */
4774                                         break;
4775                                         
4776                                         case 2:
4777                                                 genc16bit2lit(left,lit,offset);
4778                                                 genSkip(ifx,'z');
4779                                                 break;
4780                                                 /* end of size == 2 */
4781                                                 
4782                                         default:
4783                                                 /* size is 4 */
4784                                                 if(lit==0) {
4785                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
4786                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
4787                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
4788                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
4789                                                         
4790                                                 } else {
4791                                                         
4792                                                         /* search for patterns that can be optimized */
4793                                                         
4794                                                         genc16bit2lit(left,lit,0);
4795                                                         lit >>= 16;
4796                                                         if(lit) {
4797                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4798                                                                 //genSkip(ifx,'z');
4799                                                                 genc16bit2lit(left,lit,2);
4800                                                         } else {
4801                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4802                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4803                                                                 
4804                                                         }
4805                                                         
4806                                                 }
4807                                                 
4808                                                 genSkip(ifx,'z');
4809                                 }
4810                                 
4811                                 ifx->generated = 1;
4812                                 goto release ;
4813                                 
4814                                 
4815                         } else if(AOP_TYPE(right) == AOP_CRY ) {
4816                                 /* we know the left is not a bit, but that the right is */
4817                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4818                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4819                                         popGet(AOP(right),offset));
4820                                 emitpcode(POC_XORLW,popGetLit(1));
4821                                 
4822                                 /* if the two are equal, then W will be 0 and the Z bit is set
4823                                 * we could test Z now, or go ahead and check the high order bytes if
4824                                 * the variable we're comparing is larger than a byte. */
4825                                 
4826                                 while(--size)
4827                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
4828                                 
4829                                 if ( IC_TRUE(ifx) ) {
4830                                         emitSKPNZ;
4831                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4832                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4833                                 } else {
4834                                         emitSKPZ;
4835                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4836                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4837                                 }
4838                                 
4839                         } else {
4840                                 /* They're both variables that are larger than bits */
4841                                 int s = size;
4842                                 
4843                                 tlbl = newiTempLabel(NULL);
4844                                 
4845                                 while(size--) {
4846                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4847                                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4848                                         
4849                                         if ( IC_TRUE(ifx) ) {
4850                                                 if(size) {
4851                                                         emitSKPZ;
4852                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4853                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4854                                                 } else {
4855                                                         emitSKPNZ;
4856                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4857                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4858                                                 }
4859                                         } else {
4860                                                 emitSKPZ;
4861                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4862                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4863                                         }
4864                                         offset++;
4865                                 }
4866                                 if(s>1 && IC_TRUE(ifx)) {
4867                                         emitpLabel(tlbl->key);
4868                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4869                                 }
4870                         }
4871                 }
4872                 /* mark the icode as generated */
4873                 ifx->generated = 1;
4874                 goto release ;
4875         }
4876   
4877   /* if they are both bit variables */
4878   if (AOP_TYPE(left) == AOP_CRY &&
4879           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4880           if(AOP_TYPE(right) == AOP_LIT){
4881                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4882                   if(lit == 0L){
4883                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4884                           pic14_emitcode("cpl","c");
4885                   } else if(lit == 1L) {
4886                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4887                   } else {
4888                           pic14_emitcode("clr","c");
4889                   }
4890                   /* AOP_TYPE(right) == AOP_CRY */
4891           } else {
4892                   symbol *lbl = newiTempLabel(NULL);
4893                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4894                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4895                   pic14_emitcode("cpl","c");
4896                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4897           }
4898           /* c = 1 if egal */
4899           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4900                   pic14_outBitC(result);
4901                   goto release ;
4902           }
4903           if (ifx) {
4904                   genIfxJump (ifx,"c");
4905                   goto release ;
4906           }
4907           /* if the result is used in an arithmetic operation
4908           then put the result in place */
4909           pic14_outBitC(result);
4910   } else {
4911           
4912           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4913           gencjne(left,right,result,ifx);
4914           /*
4915           if(ifx) 
4916           gencjne(left,right,newiTempLabel(NULL));
4917           else {
4918           if(IC_TRUE(ifx)->key)
4919           gencjne(left,right,IC_TRUE(ifx)->key);
4920           else
4921           gencjne(left,right,IC_FALSE(ifx)->key);
4922           ifx->generated = 1;
4923           goto release ;
4924           }
4925           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4926           aopPut(AOP(result),"a",0);
4927           goto release ;
4928           }
4929           
4930                 if (ifx) {
4931                 genIfxJump (ifx,"a");
4932                 goto release ;
4933                 }
4934           */
4935           /* if the result is used in an arithmetic operation
4936           then put the result in place */
4937           /*
4938           if (AOP_TYPE(result) != AOP_CRY) 
4939           pic14_outAcc(result);
4940           */
4941           /* leave the result in acc */
4942   }
4943   
4944 release:
4945   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4946   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4947   freeAsmop(result,NULL,ic,TRUE);
4948 }
4949
4950 /*-----------------------------------------------------------------*/
4951 /* ifxForOp - returns the icode containing the ifx for operand     */
4952 /*-----------------------------------------------------------------*/
4953 static iCode *ifxForOp ( operand *op, iCode *ic )
4954 {
4955         /* if true symbol then needs to be assigned */
4956         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4957         if (IS_TRUE_SYMOP(op))
4958                 return NULL ;
4959         
4960         /* if this has register type condition and
4961         the next instruction is ifx with the same operand
4962         and live to of the operand is upto the ifx only then */
4963         if (ic->next &&
4964                 ic->next->op == IFX &&
4965                 IC_COND(ic->next)->key == op->key &&
4966                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4967                 return ic->next;
4968         
4969         if (ic->next &&
4970                 ic->next->op == IFX &&
4971                 IC_COND(ic->next)->key == op->key) {
4972                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4973                 return ic->next;
4974         }
4975         
4976         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4977         if (ic->next &&
4978                 ic->next->op == IFX)
4979                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4980         
4981         if (ic->next &&
4982                 ic->next->op == IFX &&
4983                 IC_COND(ic->next)->key == op->key) {
4984                 DEBUGpic14_emitcode ("; "," key is okay");
4985                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4986                         OP_SYMBOL(op)->liveTo,
4987                         ic->next->seq);
4988         }
4989         
4990         
4991         return NULL;
4992 }
4993 /*-----------------------------------------------------------------*/
4994 /* genAndOp - for && operation                                     */
4995 /*-----------------------------------------------------------------*/
4996 static void genAndOp (iCode *ic)
4997 {
4998         operand *left,*right, *result;
4999         /*     symbol *tlbl; */
5000         
5001         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5002         /* note here that && operations that are in an
5003         if statement are taken away by backPatchLabels
5004         only those used in arthmetic operations remain */
5005         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5006         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5007         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5008         
5009         DEBUGpic14_AopType(__LINE__,left,right,result);
5010         
5011         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5012         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5013         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5014         
5015         /* if both are bit variables */
5016         /*     if (AOP_TYPE(left) == AOP_CRY && */
5017         /*         AOP_TYPE(right) == AOP_CRY ) { */
5018         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5019         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5020         /*         pic14_outBitC(result); */
5021         /*     } else { */
5022         /*         tlbl = newiTempLabel(NULL); */
5023         /*         pic14_toBoolean(left);     */
5024         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5025         /*         pic14_toBoolean(right); */
5026         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5027         /*         pic14_outBitAcc(result); */
5028         /*     } */
5029         
5030         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5031         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5032         freeAsmop(result,NULL,ic,TRUE);
5033 }
5034
5035
5036 /*-----------------------------------------------------------------*/
5037 /* genOrOp - for || operation                                      */
5038 /*-----------------------------------------------------------------*/
5039 /*
5040 tsd pic port -
5041 modified this code, but it doesn't appear to ever get called
5042 */
5043
5044 static void genOrOp (iCode *ic)
5045 {
5046         operand *left,*right, *result;
5047         symbol *tlbl;
5048         
5049         /* note here that || operations that are in an
5050         if statement are taken away by backPatchLabels
5051         only those used in arthmetic operations remain */
5052         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5053         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5054         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5055         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5056         
5057         DEBUGpic14_AopType(__LINE__,left,right,result);
5058         
5059         /* if both are bit variables */
5060         if (AOP_TYPE(left) == AOP_CRY &&
5061                 AOP_TYPE(right) == AOP_CRY ) {
5062                 pic14_emitcode("clrc","");
5063                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5064                         AOP(left)->aopu.aop_dir,
5065                         AOP(left)->aopu.aop_dir);
5066                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5067                         AOP(right)->aopu.aop_dir,
5068                         AOP(right)->aopu.aop_dir);
5069                 pic14_emitcode("setc","");
5070                 
5071         } else {
5072                 tlbl = newiTempLabel(NULL);
5073                 pic14_toBoolean(left);
5074                 emitSKPZ;
5075                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5076                 pic14_toBoolean(right);
5077                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5078                 
5079                 pic14_outBitAcc(result);
5080         }
5081         
5082         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5083         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5084         freeAsmop(result,NULL,ic,TRUE);            
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* isLiteralBit - test if lit == 2^n                               */
5089 /*-----------------------------------------------------------------*/
5090 static int isLiteralBit(unsigned long lit)
5091 {
5092         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5093                 0x100L,0x200L,0x400L,0x800L,
5094                 0x1000L,0x2000L,0x4000L,0x8000L,
5095                 0x10000L,0x20000L,0x40000L,0x80000L,
5096                 0x100000L,0x200000L,0x400000L,0x800000L,
5097                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5098                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5099         int idx;
5100         
5101         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5102         for(idx = 0; idx < 32; idx++)
5103                 if(lit == pw[idx])
5104                         return idx+1;
5105                 return 0;
5106 }
5107
5108 /*-----------------------------------------------------------------*/
5109 /* continueIfTrue -                                                */
5110 /*-----------------------------------------------------------------*/
5111 static void continueIfTrue (iCode *ic)
5112 {
5113         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5114         if(IC_TRUE(ic))
5115                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5116         ic->generated = 1;
5117 }
5118
5119 /*-----------------------------------------------------------------*/
5120 /* jmpIfTrue -                                                     */
5121 /*-----------------------------------------------------------------*/
5122 static void jumpIfTrue (iCode *ic)
5123 {
5124         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5125         if(!IC_TRUE(ic))
5126                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5127         ic->generated = 1;
5128 }
5129
5130 /*-----------------------------------------------------------------*/
5131 /* jmpTrueOrFalse -                                                */
5132 /*-----------------------------------------------------------------*/
5133 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5134 {
5135         // ugly but optimized by peephole
5136         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137         if(IC_TRUE(ic)){
5138                 symbol *nlbl = newiTempLabel(NULL);
5139                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5140                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5141                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5142                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5143         }
5144         else{
5145                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5146                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5147         }
5148         ic->generated = 1;
5149 }
5150
5151 /*-----------------------------------------------------------------*/
5152 /* genAnd  - code for and                                          */
5153 /*-----------------------------------------------------------------*/
5154 static void genAnd (iCode *ic, iCode *ifx)
5155 {
5156         operand *left, *right, *result;
5157         int size, offset=0;  
5158         unsigned long lit = 0L;
5159         int bytelit = 0;
5160         resolvedIfx rIfx;
5161         
5162         
5163         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5164         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5165         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5166         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5167         
5168         resolveIfx(&rIfx,ifx);
5169         
5170         /* if left is a literal & right is not then exchange them */
5171         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5172                 AOP_NEEDSACC(left)) {
5173                 operand *tmp = right ;
5174                 right = left;
5175                 left = tmp;
5176         }
5177         
5178         /* if result = right then exchange them */
5179         if(pic14_sameRegs(AOP(result),AOP(right))){
5180                 operand *tmp = right ;
5181                 right = left;
5182                 left = tmp;
5183         }
5184         
5185         /* if right is bit then exchange them */
5186         if (AOP_TYPE(right) == AOP_CRY &&
5187                 AOP_TYPE(left) != AOP_CRY){
5188                 operand *tmp = right ;
5189                 right = left;
5190                 left = tmp;
5191         }
5192         if(AOP_TYPE(right) == AOP_LIT)
5193                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5194         
5195         size = AOP_SIZE(result);
5196         
5197         DEBUGpic14_AopType(__LINE__,left,right,result);
5198         
5199         // if(bit & yy)
5200         // result = bit & yy;
5201         if (AOP_TYPE(left) == AOP_CRY){
5202                 // c = bit & literal;
5203                 if(AOP_TYPE(right) == AOP_LIT){
5204                         if(lit & 1) {
5205                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5206                                         // no change
5207                                         goto release;
5208                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5209                         } else {
5210                                 // bit(result) = 0;
5211                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5212                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5213                                         goto release;
5214                                 }
5215                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5216                                         jumpIfTrue(ifx);
5217                                         goto release;
5218                                 }
5219                                 pic14_emitcode("clr","c");
5220                         }
5221                 } else {
5222                         if (AOP_TYPE(right) == AOP_CRY){
5223                                 // c = bit & bit;
5224                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5225                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5226                         } else {
5227                                 // c = bit & val;
5228                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5229                                 // c = lsb
5230                                 pic14_emitcode("rrc","a");
5231                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5232                         }
5233                 }
5234                 // bit = c
5235                 // val = c
5236                 if(size)
5237                         pic14_outBitC(result);
5238                 // if(bit & ...)
5239                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5240                         genIfxJump(ifx, "c");           
5241                 goto release ;
5242         }
5243         
5244         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5245         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5246         if((AOP_TYPE(right) == AOP_LIT) &&
5247                 (AOP_TYPE(result) == AOP_CRY) &&
5248                 (AOP_TYPE(left) != AOP_CRY)){
5249                 int posbit = isLiteralBit(lit);
5250                 /* left &  2^n */
5251                 if(posbit){
5252                         posbit--;
5253                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5254                         // bit = left & 2^n
5255                         if(size)
5256                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5257                         // if(left &  2^n)
5258                         else{
5259                                 if(ifx){
5260                                         int offset = 0;
5261                                         while (posbit > 7) {
5262                                                 posbit -= 8;
5263                                                 offset++;
5264                                         }
5265                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5266                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5267                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5268                                         
5269                                         ifx->generated = 1;
5270                                 }
5271                                 goto release;
5272                         }
5273                 } else {
5274                         symbol *tlbl = newiTempLabel(NULL);
5275                         int sizel = AOP_SIZE(left);
5276                         if(size)
5277                                 pic14_emitcode("setb","c");
5278                         while(sizel--){
5279                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5280                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5281                                         // byte ==  2^n ?
5282                                         if((posbit = isLiteralBit(bytelit)) != 0)
5283                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5284                                         else{
5285                                                 if(bytelit != 0x0FFL)
5286                                                         pic14_emitcode("anl","a,%s",
5287                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5288                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5289                                         }
5290                                 }
5291                                 offset++;
5292                         }
5293                         // bit = left & literal
5294                         if(size){
5295                                 pic14_emitcode("clr","c");
5296                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5297                         }
5298                         // if(left & literal)
5299                         else{
5300                                 if(ifx)
5301                                         jmpTrueOrFalse(ifx, tlbl);
5302                                 goto release ;
5303                         }
5304                 }
5305                 pic14_outBitC(result);
5306                 goto release ;
5307         }
5308         
5309         /* if left is same as result */
5310         if(pic14_sameRegs(AOP(result),AOP(left))){
5311                 int know_W = -1;
5312                 for(;size--; offset++,lit>>=8) {
5313                         if(AOP_TYPE(right) == AOP_LIT){
5314                                 switch(lit & 0xff) {
5315                                 case 0x00:
5316                                         /*  and'ing with 0 has clears the result */
5317                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5318                                         break;
5319                                 case 0xff:
5320                                         /* and'ing with 0xff is a nop when the result and left are the same */
5321                                         break;
5322                                         
5323                                 default:
5324                                         {
5325                                                 int p = my_powof2( (~lit) & 0xff );
5326                                                 if(p>=0) {
5327                                                         /* only one bit is set in the literal, so use a bcf instruction */
5328                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5329                                                         
5330                                                 } else {
5331                                                         if(know_W != (int)(lit&0xff))
5332                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5333                                                         know_W = lit &0xff;
5334                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5335                                                 }
5336                                         }    
5337                                 }
5338                         } else {
5339                                 if (AOP_TYPE(left) == AOP_ACC) {
5340                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5341                                 } else {        
5342                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5343                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5344                                         
5345                                 }
5346                         }
5347                 }
5348                 
5349         } else {
5350                 // left & result in different registers
5351                 if(AOP_TYPE(result) == AOP_CRY){
5352                         // result = bit
5353                         // if(size), result in bit
5354                         // if(!size && ifx), conditional oper: if(left & right)
5355                         symbol *tlbl = newiTempLabel(NULL);
5356                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5357                         if(size)
5358                                 pic14_emitcode("setb","c");
5359                         while(sizer--){
5360                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5361                                 pic14_emitcode("anl","a,%s",
5362                                         aopGet(AOP(left),offset,FALSE,FALSE));
5363                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5364                                 offset++;
5365                         }
5366                         if(size){
5367                                 CLRC;
5368                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5369                                 pic14_outBitC(result);
5370                         } else if(ifx)
5371                                 jmpTrueOrFalse(ifx, tlbl);
5372                 } else {
5373                         for(;(size--);offset++) {
5374                                 // normal case
5375                                 // result = left & right
5376                                 if(AOP_TYPE(right) == AOP_LIT){
5377                                         int t = (lit >> (offset*8)) & 0x0FFL;
5378                                         switch(t) { 
5379                                         case 0x00:
5380                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5381                                                 break;
5382                                         case 0xff:
5383                                                 if(AOP_TYPE(left) != AOP_ACC) {
5384                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5385                                                 }
5386                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5387                                                 break;
5388                                         default:
5389                                                 if(AOP_TYPE(left) == AOP_ACC) {
5390                                                         emitpcode(POC_ANDLW, popGetLit(t));
5391                                                 } else {
5392                                                         emitpcode(POC_MOVLW, popGetLit(t));
5393                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5394                                                 }
5395                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5396                                         }
5397                                         continue;
5398                                 }
5399                                 
5400                                 if (AOP_TYPE(left) == AOP_ACC) {
5401                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5402                                 } else {
5403                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5404                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5405                                 }
5406                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5407                         }
5408                 }
5409         }
5410         
5411 release :
5412         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5413         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5414         freeAsmop(result,NULL,ic,TRUE);     
5415 }
5416
5417 /*-----------------------------------------------------------------*/
5418 /* genOr  - code for or                                            */
5419 /*-----------------------------------------------------------------*/
5420 static void genOr (iCode *ic, iCode *ifx)
5421 {
5422         operand *left, *right, *result;
5423         int size, offset=0;
5424         unsigned long lit = 0L;
5425         
5426         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5427         
5428         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5429         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5430         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5431         
5432         DEBUGpic14_AopType(__LINE__,left,right,result);
5433         
5434         /* if left is a literal & right is not then exchange them */
5435         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5436                 AOP_NEEDSACC(left)) {
5437                 operand *tmp = right ;
5438                 right = left;
5439                 left = tmp;
5440         }
5441         
5442         /* if result = right then exchange them */
5443         if(pic14_sameRegs(AOP(result),AOP(right))){
5444                 operand *tmp = right ;
5445                 right = left;
5446                 left = tmp;
5447         }
5448         
5449         /* if right is bit then exchange them */
5450         if (AOP_TYPE(right) == AOP_CRY &&
5451                 AOP_TYPE(left) != AOP_CRY){
5452                 operand *tmp = right ;
5453                 right = left;
5454                 left = tmp;
5455         }
5456         
5457         DEBUGpic14_AopType(__LINE__,left,right,result);
5458         
5459         if(AOP_TYPE(right) == AOP_LIT)
5460                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5461         
5462         size = AOP_SIZE(result);
5463         
5464         // if(bit | yy)
5465         // xx = bit | yy;
5466         if (AOP_TYPE(left) == AOP_CRY){
5467                 if(AOP_TYPE(right) == AOP_LIT){
5468                         // c = bit & literal;
5469                         if(lit){
5470                                 // lit != 0 => result = 1
5471                                 if(AOP_TYPE(result) == AOP_CRY){
5472                                         if(size)
5473                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5474                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5475                                         //   AOP(result)->aopu.aop_dir,
5476                                         //   AOP(result)->aopu.aop_dir);
5477                                         else if(ifx)
5478                                                 continueIfTrue(ifx);
5479                                         goto release;
5480                                 }
5481                         } else {
5482                                 // lit == 0 => result = left
5483                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5484                                         goto release;
5485                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5486                         }
5487                 } else {
5488                         if (AOP_TYPE(right) == AOP_CRY){
5489                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5490                                         // c = bit | bit;
5491                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5492                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5493                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5494                                         
5495                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5496                                                 AOP(result)->aopu.aop_dir,
5497                                                 AOP(result)->aopu.aop_dir);
5498                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5499                                                 AOP(right)->aopu.aop_dir,
5500                                                 AOP(right)->aopu.aop_dir);
5501                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5502                                                 AOP(result)->aopu.aop_dir,
5503                                                 AOP(result)->aopu.aop_dir);
5504                                 } else {
5505                                         if( AOP_TYPE(result) == AOP_ACC) {
5506                                                 emitpcode(POC_MOVLW, popGetLit(0));
5507                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5508                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5509                                                 emitpcode(POC_MOVLW, popGetLit(1));
5510                                                 
5511                                         } else {
5512                                                 
5513                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5514                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5515                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5516                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5517                                                 
5518                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5519                                                         AOP(result)->aopu.aop_dir,
5520                                                         AOP(result)->aopu.aop_dir);
5521                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5522                                                         AOP(right)->aopu.aop_dir,
5523                                                         AOP(right)->aopu.aop_dir);
5524                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5525                                                         AOP(left)->aopu.aop_dir,
5526                                                         AOP(left)->aopu.aop_dir);
5527                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5528                                                         AOP(result)->aopu.aop_dir,
5529                                                         AOP(result)->aopu.aop_dir);
5530                                         }
5531                                 }
5532                         } else {
5533                                 // c = bit | val;
5534                                 symbol *tlbl = newiTempLabel(NULL);
5535                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5536                                 
5537                                 
5538                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5539                                 if( AOP_TYPE(right) == AOP_ACC) {
5540                                         emitpcode(POC_IORLW, popGetLit(0));
5541                                         emitSKPNZ;
5542                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5543                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5544                                 }
5545                                 
5546                                 
5547                                 
5548                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5549                                         pic14_emitcode(";XXX setb","c");
5550                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5551                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5552                                 pic14_toBoolean(right);
5553                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5554                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5555                                         jmpTrueOrFalse(ifx, tlbl);
5556                                         goto release;
5557                                 } else {
5558                                         CLRC;
5559                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5560                                 }
5561                         }
5562                 }
5563                 // bit = c
5564                 // val = c
5565                 if(size)
5566                         pic14_outBitC(result);
5567                 // if(bit | ...)
5568                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5569                         genIfxJump(ifx, "c");           
5570                 goto release ;
5571         }
5572
5573         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5574         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5575         if((AOP_TYPE(right) == AOP_LIT) &&
5576           (AOP_TYPE(result) == AOP_CRY) &&
5577           (AOP_TYPE(left) != AOP_CRY)){
5578                 if(lit){
5579                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5580                         // result = 1
5581                         if(size)
5582                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5583                         else 
5584                                 continueIfTrue(ifx);
5585                         goto release;
5586                 } else {
5587                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5588                         // lit = 0, result = boolean(left)
5589                         if(size)
5590                                 pic14_emitcode(";XXX setb","c");
5591                         pic14_toBoolean(right);
5592                         if(size){
5593                                 symbol *tlbl = newiTempLabel(NULL);
5594                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5595                                 CLRC;
5596                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5597                         } else {
5598                                 genIfxJump (ifx,"a");
5599                                 goto release;
5600                         }
5601                 }
5602                 pic14_outBitC(result);
5603                 goto release ;
5604         }
5605
5606         /* if left is same as result */
5607         if(pic14_sameRegs(AOP(result),AOP(left))){
5608                 int know_W = -1;
5609                 for(;size--; offset++,lit>>=8) {
5610                         if(AOP_TYPE(right) == AOP_LIT){
5611                                 if((lit & 0xff) == 0)
5612                                         /*  or'ing with 0 has no effect */
5613                                         continue;
5614                                 else {
5615                                         int p = my_powof2(lit & 0xff);
5616                                         if(p>=0) {
5617                                                 /* only one bit is set in the literal, so use a bsf instruction */
5618                                                 emitpcode(POC_BSF,
5619                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5620                                         } else {
5621                                                 if(know_W != (int)(lit & 0xff))
5622                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5623                                                 know_W = lit & 0xff;
5624                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5625                                         }
5626                                         
5627                                 }
5628                         } else {
5629                                 if (AOP_TYPE(left) == AOP_ACC) {
5630                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5631                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5632                                 } else {        
5633                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5634                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5635                                         
5636                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5637                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5638                                         
5639                                 }
5640                         }
5641                 }
5642         } else {
5643                 // left & result in different registers
5644                 if(AOP_TYPE(result) == AOP_CRY){
5645                         // result = bit
5646                         // if(size), result in bit
5647                         // if(!size && ifx), conditional oper: if(left | right)
5648                         symbol *tlbl = newiTempLabel(NULL);
5649                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5650                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5651                         
5652                         
5653                         if(size)
5654                                 pic14_emitcode(";XXX setb","c");
5655                         while(sizer--){
5656                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5657                                 pic14_emitcode(";XXX orl","a,%s",
5658                                         aopGet(AOP(left),offset,FALSE,FALSE));
5659                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5660                                 offset++;
5661                         }
5662                         if(size){
5663                                 CLRC;
5664                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5665                                 pic14_outBitC(result);
5666                         } else if(ifx)
5667                                 jmpTrueOrFalse(ifx, tlbl);
5668                 } else for(;(size--);offset++){
5669                         // normal case
5670                         // result = left | right
5671                         if(AOP_TYPE(right) == AOP_LIT){
5672                                 int t = (lit >> (offset*8)) & 0x0FFL;
5673                                 switch(t) { 
5674                                 case 0x00:
5675                                         if (AOP_TYPE(left) != AOP_ACC) {
5676                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5677                                         }
5678                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5679                                         
5680                                         break;
5681                                 default:
5682                                         if (AOP_TYPE(left) == AOP_ACC) {
5683                                                 emitpcode(POC_IORLW,  popGetLit(t));
5684                                         } else {
5685                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5686                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5687                                         }
5688                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5689                                 }
5690                                 continue;
5691                         }
5692                         
5693                         // faster than result <- left, anl result,right
5694                         // and better if result is SFR
5695                         if (AOP_TYPE(left) == AOP_ACC) {
5696                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5697                         } else {
5698                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5699                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5700                         }
5701                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5702                 }
5703         }
5704
5705 release :
5706         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5707         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5708         freeAsmop(result,NULL,ic,TRUE);     
5709 }
5710
5711 /*-----------------------------------------------------------------*/
5712 /* genXor - code for xclusive or                                   */
5713 /*-----------------------------------------------------------------*/
5714 static void genXor (iCode *ic, iCode *ifx)
5715 {
5716         operand *left, *right, *result;
5717         int size, offset=0;
5718         unsigned long lit = 0L;
5719         
5720         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5721         
5722         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5723         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5724         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5725         
5726         /* if left is a literal & right is not ||
5727         if left needs acc & right does not */
5728         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5729                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5730                 operand *tmp = right ;
5731                 right = left;
5732                 left = tmp;
5733         }
5734         
5735         /* if result = right then exchange them */
5736         if(pic14_sameRegs(AOP(result),AOP(right))){
5737                 operand *tmp = right ;
5738                 right = left;
5739                 left = tmp;
5740         }
5741         
5742         /* if right is bit then exchange them */
5743         if (AOP_TYPE(right) == AOP_CRY &&
5744                 AOP_TYPE(left) != AOP_CRY){
5745                 operand *tmp = right ;
5746                 right = left;
5747                 left = tmp;
5748         }
5749         if(AOP_TYPE(right) == AOP_LIT)
5750                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5751         
5752         size = AOP_SIZE(result);
5753         
5754         // if(bit ^ yy)
5755         // xx = bit ^ yy;
5756         if (AOP_TYPE(left) == AOP_CRY){
5757                 if(AOP_TYPE(right) == AOP_LIT){
5758                         // c = bit & literal;
5759                         if(lit>>1){
5760                                 // lit>>1  != 0 => result = 1
5761                                 if(AOP_TYPE(result) == AOP_CRY){
5762                                         if(size)
5763                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5764                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5765                                         else if(ifx)
5766                                                 continueIfTrue(ifx);
5767                                         goto release;
5768                                 }
5769                                 pic14_emitcode("setb","c");
5770                         } else{
5771                                 // lit == (0 or 1)
5772                                 if(lit == 0){
5773                                         // lit == 0, result = left
5774                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5775                                                 goto release;
5776                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5777                                 } else{
5778                                         // lit == 1, result = not(left)
5779                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
5780                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5781                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5782                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5783                                                 goto release;
5784                                         } else {
5785                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5786                                                 pic14_emitcode("cpl","c");
5787                                         }
5788                                 }
5789                         }
5790                         
5791                 } else {
5792                         // right != literal
5793                         symbol *tlbl = newiTempLabel(NULL);
5794                         if (AOP_TYPE(right) == AOP_CRY){
5795                                 // c = bit ^ bit;
5796                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5797                         }
5798                         else{
5799                                 int sizer = AOP_SIZE(right);
5800                                 // c = bit ^ val
5801                                 // if val>>1 != 0, result = 1
5802                                 pic14_emitcode("setb","c");
5803                                 while(sizer){
5804                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5805                                         if(sizer == 1)
5806                                                 // test the msb of the lsb
5807                                                 pic14_emitcode("anl","a,#0xfe");
5808                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5809                                         sizer--;
5810                                 }
5811                                 // val = (0,1)
5812                                 pic14_emitcode("rrc","a");
5813                         }
5814                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5815                         pic14_emitcode("cpl","c");
5816                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5817                 }
5818                 // bit = c
5819                 // val = c
5820                 if(size)
5821                         pic14_outBitC(result);
5822                 // if(bit | ...)
5823                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5824                         genIfxJump(ifx, "c");           
5825                 goto release ;
5826         }
5827         
5828         if(pic14_sameRegs(AOP(result),AOP(left))){
5829                 /* if left is same as result */
5830                 for(;size--; offset++) {
5831                         if(AOP_TYPE(right) == AOP_LIT){
5832                                 int t  = (lit >> (offset*8)) & 0x0FFL;
5833                                 if(t == 0x00L)
5834                                         continue;
5835                                 else
5836                                         if (IS_AOP_PREG(left)) {
5837                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5838                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5839                                                 aopPut(AOP(result),"a",offset);
5840                                         } else {
5841                                                 emitpcode(POC_MOVLW, popGetLit(t));
5842                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5843                                                 pic14_emitcode("xrl","%s,%s",
5844                                                         aopGet(AOP(left),offset,FALSE,TRUE),
5845                                                         aopGet(AOP(right),offset,FALSE,FALSE));
5846                                         }
5847                         } else {
5848                                 if (AOP_TYPE(left) == AOP_ACC)
5849                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5850                                 else {
5851                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5852                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
5853                                         /*
5854                                         if (IS_AOP_PREG(left)) {
5855                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5856                                         aopPut(AOP(result),"a",offset);
5857                                         } else
5858                                         pic14_emitcode("xrl","%s,a",
5859                                         aopGet(AOP(left),offset,FALSE,TRUE));
5860                                         */
5861                                 }
5862                         }
5863                 }
5864         } else {
5865                 // left & result in different registers
5866                 if(AOP_TYPE(result) == AOP_CRY){
5867                         // result = bit
5868                         // if(size), result in bit
5869                         // if(!size && ifx), conditional oper: if(left ^ right)
5870                         symbol *tlbl = newiTempLabel(NULL);
5871                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5872                         if(size)
5873                                 pic14_emitcode("setb","c");
5874                         while(sizer--){
5875                                 if((AOP_TYPE(right) == AOP_LIT) &&
5876                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5877                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5878                                 } else {
5879                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5880                                         pic14_emitcode("xrl","a,%s",
5881                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5882                                 }
5883                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5884                                 offset++;
5885                         }
5886                         if(size){
5887                                 CLRC;
5888                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5889                                 pic14_outBitC(result);
5890                         } else if(ifx)
5891                                 jmpTrueOrFalse(ifx, tlbl);
5892                 } else for(;(size--);offset++){
5893                         // normal case
5894                         // result = left & right
5895                         if(AOP_TYPE(right) == AOP_LIT){
5896                                 int t = (lit >> (offset*8)) & 0x0FFL;
5897                                 switch(t) { 
5898                                 case 0x00:
5899                                         if (AOP_TYPE(left) != AOP_ACC) {
5900                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5901                                         }
5902                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5903                                         pic14_emitcode("movf","%s,w",
5904                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5905                                         pic14_emitcode("movwf","%s",
5906                                                 aopGet(AOP(result),offset,FALSE,FALSE));
5907                                         break;
5908                                 case 0xff:
5909                                         if (AOP_TYPE(left) == AOP_ACC) {
5910                                                 emitpcode(POC_XORLW, popGetLit(t));
5911                                         } else {
5912                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
5913                                         }
5914                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5915                                         break;
5916                                 default:
5917                                         if (AOP_TYPE(left) == AOP_ACC) {
5918                                                 emitpcode(POC_XORLW, popGetLit(t));
5919                                         } else {
5920                                                 emitpcode(POC_MOVLW, popGetLit(t));
5921                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5922                                         }
5923                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5924                                         pic14_emitcode("movlw","0x%x",t);
5925                                         pic14_emitcode("xorwf","%s,w",
5926                                                 aopGet(AOP(left),offset,FALSE,FALSE));
5927                                         pic14_emitcode("movwf","%s",
5928                                                 aopGet(AOP(result),offset,FALSE,FALSE));
5929                                         
5930                                 }
5931                                 continue;
5932                         }
5933                         
5934                         // faster than result <- left, anl result,right
5935                         // and better if result is SFR
5936                         if (AOP_TYPE(left) == AOP_ACC) {
5937                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5938                         } else {
5939                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5940                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5941                         }
5942                         if ( AOP_TYPE(result) != AOP_ACC){
5943                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5944                         }
5945                 }
5946         }
5947         
5948 release :
5949         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5950         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5951         freeAsmop(result,NULL,ic,TRUE);     
5952 }
5953
5954 /*-----------------------------------------------------------------*/
5955 /* genInline - write the inline code out                           */
5956 /*-----------------------------------------------------------------*/
5957 static void genInline (iCode *ic)
5958 {
5959   char *buffer, *bp, *bp1;
5960
5961   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5962
5963   _G.inLine += (!options.asmpeep);
5964
5965   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5966   strcpy(buffer,IC_INLINE(ic));
5967
5968   /* emit each line as a code */
5969   while (*bp) {
5970     if (*bp == '\n') {
5971       *bp++ = '\0';
5972       
5973       if(*bp1)
5974         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5975       bp1 = bp;
5976     } else {
5977       if (*bp == ':') {
5978         bp++;
5979         *bp = '\0';
5980         bp++;
5981
5982         /* print label, use this special format with NULL directive
5983          * to denote that the argument should not be indented with tab */
5984         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
5985
5986         bp1 = bp;
5987       } else
5988         bp++;
5989     }
5990   }
5991   if ((bp1 != bp) && *bp1)
5992     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
5993
5994   Safe_free(buffer);
5995
5996   _G.inLine -= (!options.asmpeep);
5997 }
5998
5999 /*-----------------------------------------------------------------*/
6000 /* genRRC - rotate right with carry                                */
6001 /*-----------------------------------------------------------------*/
6002 static void genRRC (iCode *ic)
6003 {
6004         operand *left , *result ;
6005         int size, offset = 0, same;
6006         
6007         /* rotate right with carry */
6008         left = IC_LEFT(ic);
6009         result=IC_RESULT(ic);
6010         aopOp (left,ic,FALSE);
6011         aopOp (result,ic,FALSE);
6012         
6013         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6014         
6015         same = pic14_sameRegs(AOP(result),AOP(left));
6016         
6017         size = AOP_SIZE(result);    
6018         
6019         /* get the lsb and put it into the carry */
6020         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6021         
6022         offset = 0 ;
6023         
6024         while(size--) {
6025                 
6026                 if(same) {
6027                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6028                 } else {
6029                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6030                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6031                 }
6032                 
6033                 offset++;
6034         }
6035         
6036         freeAsmop(left,NULL,ic,TRUE);
6037         freeAsmop(result,NULL,ic,TRUE);
6038 }
6039
6040 /*-----------------------------------------------------------------*/
6041 /* genRLC - generate code for rotate left with carry               */
6042 /*-----------------------------------------------------------------*/
6043 static void genRLC (iCode *ic)
6044 {    
6045         operand *left , *result ;
6046         int size, offset = 0;
6047         int same;
6048         
6049         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6050         /* rotate right with carry */
6051         left = IC_LEFT(ic);
6052         result=IC_RESULT(ic);
6053         aopOp (left,ic,FALSE);
6054         aopOp (result,ic,FALSE);
6055         
6056         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6057         
6058         same = pic14_sameRegs(AOP(result),AOP(left));
6059         
6060         /* move it to the result */
6061         size = AOP_SIZE(result);    
6062         
6063         /* get the msb and put it into the carry */
6064         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6065         
6066         offset = 0 ;
6067         
6068         while(size--) {
6069                 
6070                 if(same) {
6071                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6072                 } else {
6073                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6074                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6075                 }
6076                 
6077                 offset++;
6078         }
6079         
6080         
6081         freeAsmop(left,NULL,ic,TRUE);
6082         freeAsmop(result,NULL,ic,TRUE);
6083 }
6084
6085 /*-----------------------------------------------------------------*/
6086 /* genGetHbit - generates code get highest order bit               */
6087 /*-----------------------------------------------------------------*/
6088 static void genGetHbit (iCode *ic)
6089 {
6090         operand *left, *result;
6091         left = IC_LEFT(ic);
6092         result=IC_RESULT(ic);
6093         aopOp (left,ic,FALSE);
6094         aopOp (result,ic,FALSE);
6095         
6096         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6097         /* get the highest order byte into a */
6098         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6099         if(AOP_TYPE(result) == AOP_CRY){
6100                 pic14_emitcode("rlc","a");
6101                 pic14_outBitC(result);
6102         }
6103         else{
6104                 pic14_emitcode("rl","a");
6105                 pic14_emitcode("anl","a,#0x01");
6106                 pic14_outAcc(result);
6107         }
6108         
6109         
6110         freeAsmop(left,NULL,ic,TRUE);
6111         freeAsmop(result,NULL,ic,TRUE);
6112 }
6113
6114 /*-----------------------------------------------------------------*/
6115 /* AccRol - rotate left accumulator by known count                 */
6116 /*-----------------------------------------------------------------*/
6117 static void AccRol (operand *op,int offset,int shCount)
6118 {
6119         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6120         shCount &= 0x0007;              // shCount : 0..7
6121         switch(shCount){
6122         case 0 :
6123                 break;
6124         case 1 :
6125                 pic14_emitcode("rl","a");
6126                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6127                 break;
6128         case 2 :
6129                 pic14_emitcode("rl","a");
6130                 pic14_emitcode("rl","a");
6131                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6132                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6133                 break;
6134         case 3 :
6135                 pic14_emitcode("swap","a");
6136                 pic14_emitcode("rr","a");
6137                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6138                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6139                 break;
6140         case 4 :
6141                 pic14_emitcode("swap","a");
6142                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6143                 break;
6144         case 5 :
6145                 pic14_emitcode("swap","a");
6146                 pic14_emitcode("rl","a");
6147                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6148                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6149                 break;
6150         case 6 :
6151                 pic14_emitcode("rr","a");
6152                 pic14_emitcode("rr","a");
6153                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6154                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6155                 break;
6156         case 7 :
6157                 pic14_emitcode("rr","a");
6158                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6159                 break;
6160         }
6161 }
6162
6163 /*-----------------------------------------------------------------*/
6164 /* AccLsh - left shift accumulator by known count                  */
6165 /*-----------------------------------------------------------------*/
6166 static void AccLsh (operand *op,int offset,int shCount)
6167 {
6168         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6169         if(shCount != 0){
6170                 /*
6171                 if(shCount == 1) {
6172                         pic14_emitcode("add","a,acc");
6173                         emitCLRC;
6174                         emitpcode(POC_RLF,popGet(AOP(op),offset));
6175                 } else {
6176                         if(shCount == 2) {
6177                                 pic14_emitcode("add","a,acc");
6178                                 emitCLRC;
6179                                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6180                                 pic14_emitcode("add","a,acc");
6181                                 emitCLRC;
6182                                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6183                         } else {
6184                 */
6185                 {
6186                         {
6187                                 /* rotate left accumulator */
6188                                 AccRol(op,offset,shCount);
6189                                 /* and kill the lower order bits */
6190                                 pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6191                                 emitpcode(POC_ANDLW,popGetLit(SLMask[shCount]));
6192                         }
6193                 }
6194         }
6195 }
6196
6197 /*-----------------------------------------------------------------*/
6198 /* AccRsh - right shift accumulator by known count                 */
6199 /*-----------------------------------------------------------------*/
6200 static void AccRsh (operand *op,int offset,int shCount)
6201 {
6202         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6203         if(shCount != 0){
6204                 if(shCount == 1){
6205                         CLRC;
6206                         pic14_emitcode("rrc","a");
6207                 } else {
6208                         /* rotate right accumulator */
6209                         AccRol(op,offset,8 - shCount);
6210                         /* and kill the higher order bits */
6211                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6212                 }
6213         }
6214 }
6215
6216 #if 0
6217 /*-----------------------------------------------------------------*/
6218 /* AccSRsh - signed right shift accumulator by known count                 */
6219 /*-----------------------------------------------------------------*/
6220 static void AccSRsh (int shCount)
6221 {
6222         symbol *tlbl ;
6223         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6224         if(shCount != 0){
6225                 if(shCount == 1){
6226                         pic14_emitcode("mov","c,acc.7");
6227                         pic14_emitcode("rrc","a");
6228                 } else if(shCount == 2){
6229                         pic14_emitcode("mov","c,acc.7");
6230                         pic14_emitcode("rrc","a");
6231                         pic14_emitcode("mov","c,acc.7");
6232                         pic14_emitcode("rrc","a");
6233                 } else {
6234                         tlbl = newiTempLabel(NULL);
6235                         /* rotate right accumulator */
6236                         AccRol(8 - shCount);
6237                         /* and kill the higher order bits */
6238                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6239                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6240                         pic14_emitcode("orl","a,#0x%02x",
6241                                 (unsigned char)~SRMask[shCount]);
6242                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6243                 }
6244         }
6245 }
6246 #endif
6247 /*-----------------------------------------------------------------*/
6248 /* shiftR1Left2Result - shift right one byte from left to result   */
6249 /*-----------------------------------------------------------------*/
6250 static void shiftR1Left2ResultSigned (operand *left, int offl,
6251                                                                           operand *result, int offr,
6252                                                                           int shCount)
6253 {
6254         int same;
6255         
6256         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6257         
6258         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6259         
6260         switch(shCount) {
6261         case 1:
6262                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6263                 if(same) 
6264                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6265                 else {
6266                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6267                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6268                 }
6269                 
6270                 break;
6271         case 2:
6272                 
6273                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6274                 if(same) 
6275                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6276                 else {
6277                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6278                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6279                 }
6280                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6281                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6282                 
6283                 break;
6284                 
6285         case 3:
6286                 if(same)
6287                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6288                 else {
6289                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6290                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6291                 }
6292                 
6293                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6294                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6295                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6296                 
6297                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6298                 emitpcode(POC_IORLW, popGetLit(0xe0));
6299                 
6300                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6301                 break;
6302                 
6303         case 4:
6304                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6305                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6306                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6307                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6308                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6309                 break;
6310         case 5:
6311                 if(same) {
6312                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6313                 } else {
6314                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6315                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6316                 }
6317                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6318                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6319                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6320                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6321                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6322                 break;
6323                 
6324         case 6:
6325                 if(same) {
6326                         emitpcode(POC_MOVLW, popGetLit(0x00));
6327                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6328                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6329                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6330                         emitpcode(POC_IORLW, popGetLit(0x01));
6331                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6332                 } else {
6333                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6334                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6335                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6336                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6337                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6338                 }
6339                 break;
6340                 
6341         case 7:
6342                 if(same) {
6343                         emitpcode(POC_MOVLW, popGetLit(0x00));
6344                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6345                         emitpcode(POC_MOVLW, popGetLit(0xff));
6346                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6347                 } else {
6348                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6349                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6350                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6351                 }
6352                 
6353         default:
6354                 break;
6355         }
6356 }
6357
6358 /*-----------------------------------------------------------------*/
6359 /* shiftR1Left2Result - shift right one byte from left to result   */
6360 /*-----------------------------------------------------------------*/
6361 static void shiftR1Left2Result (operand *left, int offl,
6362                                                                 operand *result, int offr,
6363                                                                 int shCount, int sign)
6364 {
6365         int same;
6366         
6367         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6368         
6369         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6370         
6371         /* Copy the msb into the carry if signed. */
6372         if(sign) {
6373                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6374                 return;
6375         }
6376         
6377         
6378         
6379         switch(shCount) {
6380         case 1:
6381                 emitCLRC;
6382                 if(same) 
6383                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6384                 else {
6385                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6386                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6387                 }
6388                 break;
6389         case 2:
6390                 emitCLRC;
6391                 if(same) {
6392                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6393                 } else {
6394                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6395                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6396                 }
6397                 emitCLRC;
6398                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6399                 
6400                 break;
6401         case 3:
6402                 if(same)
6403                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6404                 else {
6405                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6406                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6407                 }
6408                 
6409                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6410                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6411                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6412                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6413                 break;
6414                 
6415         case 4:
6416                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6417                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6418                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6419                 break;
6420                 
6421         case 5:
6422                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6423                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6424                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6425                 emitCLRC;
6426                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6427                 
6428                 break;
6429         case 6:
6430                 
6431                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6432                 emitpcode(POC_ANDLW, popGetLit(0x80));
6433                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6434                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6435                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6436                 break;
6437                 
6438         case 7:
6439                 
6440                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6441                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6442                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6443                 
6444                 break;
6445                 
6446         default:
6447                 break;
6448         }
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* shiftL1Left2Result - shift left one byte from left to result    */
6453 /*-----------------------------------------------------------------*/
6454 static void shiftL1Left2Result (operand *left, int offl,
6455                                                                 operand *result, int offr, int shCount)
6456 {
6457         int same;
6458         
6459         //    char *l;
6460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6461         
6462         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6463         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6464         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6465         //    MOVA(l);
6466         /* shift left accumulator */
6467         //AccLsh(shCount); // don't comment out just yet...
6468         //    aopPut(AOP(result),"a",offr);
6469         
6470         switch(shCount) {
6471         case 1:
6472                 /* Shift left 1 bit position */
6473                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6474                 if(same) {
6475                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6476                 } else {
6477                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6478                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6479                 }
6480                 break;
6481         case 2:
6482                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6483                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6484                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6485                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6486                 break;
6487         case 3:
6488                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6489                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6490                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6491                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6492                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6493                 break;
6494         case 4:
6495                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6496                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6497                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6498                 break;
6499         case 5:
6500                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6501                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6502                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6503                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6504                 break;
6505         case 6:
6506                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6507                 emitpcode(POC_ANDLW, popGetLit(0x30));
6508                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6509                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6510                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6511                 break;
6512         case 7:
6513                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6514                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6515                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6516                 break;
6517                 
6518         default:
6519                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6520         }
6521         
6522 }
6523
6524 /*-----------------------------------------------------------------*/
6525 /* movLeft2Result - move byte from left to result                  */
6526 /*-----------------------------------------------------------------*/
6527 static void movLeft2Result (operand *left, int offl,
6528                                                         operand *result, int offr)
6529 {
6530         char *l;
6531         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6532         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6533                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6534                 
6535                 if (*l == '@' && (IS_AOP_PREG(result))) {
6536                         pic14_emitcode("mov","a,%s",l);
6537                         aopPut(AOP(result),"a",offr);
6538                 } else {
6539                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6540                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6541                 }
6542         }
6543 }
6544
6545 /*-----------------------------------------------------------------*/
6546 /* shiftL2Left2Result - shift left two bytes from left to result   */
6547 /*-----------------------------------------------------------------*/
6548 static void shiftL2Left2Result (operand *left, int offl,
6549                                                                 operand *result, int offr, int shCount)
6550 {
6551         
6552         
6553         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6554         
6555         if(pic14_sameRegs(AOP(result), AOP(left))) {
6556                 switch(shCount) {
6557                 case 0:
6558                         break;
6559                 case 1:
6560                 case 2:
6561                 case 3:
6562                         
6563                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6564                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6565                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6566                         
6567                         while(--shCount) {
6568                                 emitCLRC;
6569                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6570                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6571                         }
6572                         
6573                         break;
6574                 case 4:
6575                 case 5:
6576                         emitpcode(POC_MOVLW, popGetLit(0x0f));
6577                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6578                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6579                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6580                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6581                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6582                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6583                         if(shCount >=5) {
6584                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6585                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6586                         }
6587                         break;
6588                 case 6:
6589                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6590                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6591                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6592                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6593                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6594                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6595                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6596                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6597                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6598                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6599                         break;
6600                 case 7:
6601                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6602                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
6603                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6604                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6605                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6606                 }
6607                 
6608         } else {
6609                 switch(shCount) {
6610                 case 0:
6611                         break;
6612                 case 1:
6613                 case 2:
6614                 case 3:
6615                 /* note, use a mov/add for the shift since the mov has a
6616                         chance of getting optimized out */
6617                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6618                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6619                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6620                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6621                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6622                         
6623                         while(--shCount) {
6624                                 emitCLRC;
6625                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6626                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6627                         }
6628                         break;
6629                         
6630                 case 4:
6631                 case 5:
6632                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6633                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6634                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6635                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6636                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6637                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6638                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6639                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6640                         
6641                         
6642                         if(shCount == 5) {
6643                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6644                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6645                         }
6646                         break;
6647                 case 6:
6648                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6649                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6650                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
6651                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6652                         
6653                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6654                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6655                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6656                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6657                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6658                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6659                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6660                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6661                         break;
6662                 case 7:
6663                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6664                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6665                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6666                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6667                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6668                 }
6669         }
6670         
6671 }
6672 /*-----------------------------------------------------------------*/
6673 /* shiftR2Left2Result - shift right two bytes from left to result  */
6674 /*-----------------------------------------------------------------*/
6675 static void shiftR2Left2Result (operand *left, int offl,
6676                                                                 operand *result, int offr,
6677                                                                 int shCount, int sign)
6678 {
6679         int same=0;
6680         
6681         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6682         same = pic14_sameRegs(AOP(result), AOP(left));
6683         
6684         if(same && ((offl + MSB16) == offr)){
6685                 same=1;
6686                 /* don't crash result[offr] */
6687                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6688                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6689         }
6690         /* else {
6691         movLeft2Result(left,offl, result, offr);
6692         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6693         }
6694         */
6695         /* a:x >> shCount (x = lsb(result))*/
6696         /*
6697         if(sign)
6698         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6699         else {
6700         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6701         */
6702         switch(shCount) {
6703         case 0:
6704                 break;
6705         case 1:
6706         case 2:
6707         case 3:
6708                 if(sign)
6709                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
6710                 else
6711                         emitCLRC;
6712                 
6713                 if(same) {
6714                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6715                         emitpcode(POC_RRF,popGet(AOP(result),offr));
6716                 } else {
6717                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6718                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6719                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6720                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6721                 }
6722                 
6723                 while(--shCount) {
6724                         if(sign)
6725                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6726                         else
6727                                 emitCLRC;
6728                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6729                         emitpcode(POC_RRF,popGet(AOP(result),offr));
6730                 }
6731                 break;
6732         case 4:
6733         case 5:
6734                 if(same) {
6735                         
6736                         emitpcode(POC_MOVLW, popGetLit(0xf0));
6737                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6738                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6739                         
6740                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6741                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6742                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6743                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6744                 } else {
6745                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6746                         emitpcode(POC_ANDLW, popGetLit(0x0f));
6747                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748                         
6749                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6750                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6751                         emitpcode(POC_ANDLW, popGetLit(0xf0));
6752                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6753                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6754                 }
6755                 
6756                 if(shCount >=5) {
6757                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6758                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6759                 }
6760                 
6761                 if(sign) {
6762                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6763                         emitpcode(POC_BTFSC, 
6764                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6765                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6766                 }
6767                 
6768                 break;
6769                 
6770         case 6:
6771                 if(same) {
6772                         
6773                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6774                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6775                         
6776                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6777                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6778                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
6779                         emitpcode(POC_ANDLW,popGetLit(0x03));
6780                         if(sign) {
6781                                 emitpcode(POC_BTFSC, 
6782                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6783                                 emitpcode(POC_IORLW,popGetLit(0xfc));
6784                         }
6785                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6786                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6787                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6788                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6789                 } else {
6790                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
6791                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6792                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6793                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6794                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6795                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
6796                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6797                         emitpcode(POC_ANDLW,popGetLit(0x03));
6798                         if(sign) {
6799                                 emitpcode(POC_BTFSC, 
6800                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6801                                 emitpcode(POC_IORLW,popGetLit(0xfc));
6802                         }
6803                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6804                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6805                         
6806                         
6807                 }
6808                 
6809                 break;
6810         case 7:
6811                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6812                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6813                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6814                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6815                 if(sign) {
6816                         emitSKPNC;
6817                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6818                 } else 
6819                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6820   }
6821 }
6822
6823
6824 /*-----------------------------------------------------------------*/
6825 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6826 /*-----------------------------------------------------------------*/
6827 static void shiftLLeftOrResult (operand *left, int offl,
6828                                                                 operand *result, int offr, int shCount)
6829 {
6830         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6831         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6832         /* shift left accumulator */
6833         AccLsh(left,offl,shCount);
6834         /* or with result */
6835         pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6836         /* back to result */
6837         aopPut(AOP(result),"a",offr);
6838 }
6839
6840 /*-----------------------------------------------------------------*/
6841 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6842 /*-----------------------------------------------------------------*/
6843 static void shiftRLeftOrResult (operand *left, int offl,
6844                                                                 operand *result, int offr, int shCount)
6845 {
6846         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6847         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6848         /* shift right accumulator */
6849         AccRsh(left,offl,shCount);
6850         /* or with result */
6851         pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6852         /* back to result */
6853         aopPut(AOP(result),"a",offr);
6854 }
6855
6856 /*-----------------------------------------------------------------*/
6857 /* genlshOne - left shift a one byte quantity by known count       */
6858 /*-----------------------------------------------------------------*/
6859 static void genlshOne (operand *result, operand *left, int shCount)
6860 {       
6861         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6862         shiftL1Left2Result(left, LSB, result, LSB, shCount);
6863 }
6864
6865 /*-----------------------------------------------------------------*/
6866 /* genlshTwo - left shift two bytes by known amount != 0           */
6867 /*-----------------------------------------------------------------*/
6868 static void genlshTwo (operand *result,operand *left, int shCount)
6869 {
6870         int size;
6871         
6872         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6873         size = pic14_getDataSize(result);
6874         
6875         /* if shCount >= 8 */
6876         if (shCount >= 8) {
6877                 shCount -= 8 ;
6878                 
6879                 if (size > 1){
6880                         if (shCount)
6881                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6882                         else 
6883                                 movLeft2Result(left, LSB, result, MSB16);
6884                 }
6885                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6886         }
6887         
6888         /*  1 <= shCount <= 7 */
6889         else {  
6890                 if(size == 1)
6891                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6892                 else 
6893                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6894         }
6895 }
6896
6897 /*-----------------------------------------------------------------*/
6898 /* shiftLLong - shift left one long from left to result            */
6899 /* offl = LSB or MSB16                                             */
6900 /*-----------------------------------------------------------------*/
6901 static void shiftLLong (operand *left, operand *result, int offr )
6902 {
6903         char *l;
6904         int size = AOP_SIZE(result);
6905         
6906         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6907         if(size >= LSB+offr){
6908                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6909                 MOVA(l);
6910                 pic14_emitcode("add","a,acc");
6911                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6912                         size >= MSB16+offr && offr != LSB )
6913                         pic14_emitcode("xch","a,%s",
6914                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6915                 else      
6916                         aopPut(AOP(result),"a",LSB+offr);
6917         }
6918         
6919         if(size >= MSB16+offr){
6920                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6921                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6922                         MOVA(l);
6923                 }
6924                 pic14_emitcode("rlc","a");
6925                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6926                         size >= MSB24+offr && offr != LSB)
6927                         pic14_emitcode("xch","a,%s",
6928                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6929                 else      
6930                         aopPut(AOP(result),"a",MSB16+offr);
6931         }
6932         
6933         if(size >= MSB24+offr){
6934                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6935                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6936                         MOVA(l);
6937                 }
6938                 pic14_emitcode("rlc","a");
6939                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
6940                         size >= MSB32+offr && offr != LSB )
6941                         pic14_emitcode("xch","a,%s",
6942                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6943                 else      
6944                         aopPut(AOP(result),"a",MSB24+offr);
6945         }
6946         
6947         if(size > MSB32+offr){
6948                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6949                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6950                         MOVA(l);  
6951                 }
6952                 pic14_emitcode("rlc","a");
6953                 aopPut(AOP(result),"a",MSB32+offr);
6954         }
6955         if(offr != LSB)
6956                 aopPut(AOP(result),zero,LSB);       
6957 }
6958
6959 /*-----------------------------------------------------------------*/
6960 /* genlshFour - shift four byte by a known amount != 0             */
6961 /*-----------------------------------------------------------------*/
6962 static void genlshFour (operand *result, operand *left, int shCount)
6963 {
6964         int size;
6965         
6966         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6967         size = AOP_SIZE(result);
6968         
6969         /* if shifting more that 3 bytes */
6970         if (shCount >= 24 ) {
6971                 shCount -= 24;
6972                 if (shCount)
6973                 /* lowest order of left goes to the highest
6974                 order of the destination */
6975                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6976                 else
6977                         movLeft2Result(left, LSB, result, MSB32);
6978                 aopPut(AOP(result),zero,LSB);
6979                 aopPut(AOP(result),zero,MSB16);
6980                 aopPut(AOP(result),zero,MSB32);
6981                 return;
6982         }
6983         
6984         /* more than two bytes */
6985         else if ( shCount >= 16 ) {
6986                 /* lower order two bytes goes to higher order two bytes */
6987                 shCount -= 16;
6988                 /* if some more remaining */
6989                 if (shCount)
6990                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6991                 else {
6992                         movLeft2Result(left, MSB16, result, MSB32);
6993                         movLeft2Result(left, LSB, result, MSB24);
6994                 }
6995                 aopPut(AOP(result),zero,MSB16);
6996                 aopPut(AOP(result),zero,LSB);
6997                 return;
6998         }    
6999         
7000         /* if more than 1 byte */
7001         else if ( shCount >= 8 ) {
7002                 /* lower order three bytes goes to higher order  three bytes */
7003                 shCount -= 8;
7004                 if(size == 2){
7005                         if(shCount)
7006                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7007                         else
7008                                 movLeft2Result(left, LSB, result, MSB16);
7009                 }
7010                 else{   /* size = 4 */
7011                         if(shCount == 0){
7012                                 movLeft2Result(left, MSB24, result, MSB32);
7013                                 movLeft2Result(left, MSB16, result, MSB24);
7014                                 movLeft2Result(left, LSB, result, MSB16);
7015                                 aopPut(AOP(result),zero,LSB);
7016                         }
7017                         else if(shCount == 1)
7018                                 shiftLLong(left, result, MSB16);
7019                         else{
7020                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7021                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7022                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7023                                 aopPut(AOP(result),zero,LSB);
7024                         }
7025                 }
7026         }
7027         
7028         /* 1 <= shCount <= 7 */
7029         else if(shCount <= 2){
7030                 shiftLLong(left, result, LSB);
7031                 if(shCount == 2)
7032                         shiftLLong(result, result, LSB);
7033         }
7034         /* 3 <= shCount <= 7, optimize */
7035         else{
7036                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7037                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7038                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7039         }
7040 }
7041
7042 /*-----------------------------------------------------------------*/
7043 /* genLeftShiftLiteral - left shifting by known count              */
7044 /*-----------------------------------------------------------------*/
7045 static void genLeftShiftLiteral (operand *left,
7046                                                                  operand *right,
7047                                                                  operand *result,
7048                                                                  iCode *ic)
7049 {    
7050         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7051         int size;
7052         
7053         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7054         freeAsmop(right,NULL,ic,TRUE);
7055         
7056         aopOp(left,ic,FALSE);
7057         aopOp(result,ic,FALSE);
7058         
7059         size = getSize(operandType(result));
7060         
7061 #if VIEW_SIZE
7062         pic14_emitcode("; shift left ","result %d, left %d",size,
7063                 AOP_SIZE(left));
7064 #endif
7065         
7066         /* I suppose that the left size >= result size */
7067         if(shCount == 0){
7068                 while(size--){
7069                         movLeft2Result(left, size, result, size);
7070                 }
7071         }
7072         
7073         else if(shCount >= (size * 8))
7074                 while(size--)
7075                         aopPut(AOP(result),zero,size);
7076                 else{
7077                         switch (size) {
7078                         case 1:
7079                                 genlshOne (result,left,shCount);
7080                                 break;
7081                                 
7082                         case 2:
7083                         case 3:
7084                                 genlshTwo (result,left,shCount);
7085                                 break;
7086                                 
7087                         case 4:
7088                                 genlshFour (result,left,shCount);
7089                                 break;
7090                         }
7091                 }
7092                 freeAsmop(left,NULL,ic,TRUE);
7093                 freeAsmop(result,NULL,ic,TRUE);
7094 }
7095
7096 /*-----------------------------------------------------------------*
7097 * genMultiAsm - repeat assembly instruction for size of register.
7098 * if endian == 1, then the high byte (i.e base address + size of 
7099 * register) is used first else the low byte is used first;
7100 *-----------------------------------------------------------------*/
7101 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7102 {
7103         
7104         int offset = 0;
7105         
7106         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7107         
7108         if(!reg)
7109                 return;
7110         
7111         if(!endian) {
7112                 endian = 1;
7113         } else {
7114                 endian = -1;
7115                 offset = size-1;
7116         }
7117         
7118         while(size--) {
7119                 emitpcode(poc,    popGet(AOP(reg),offset));
7120                 offset += endian;
7121         }
7122         
7123 }
7124 /*-----------------------------------------------------------------*/
7125 /* genLeftShift - generates code for left shifting                 */
7126 /*-----------------------------------------------------------------*/
7127 static void genLeftShift (iCode *ic)
7128 {
7129         operand *left,*right, *result;
7130         int size, offset;
7131         unsigned long lit = 0L;
7132         char *l;
7133         symbol *tlbl , *tlbl1;
7134         pCodeOp *pctemp;
7135         
7136         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7137         
7138         right = IC_RIGHT(ic);
7139         left  = IC_LEFT(ic);
7140         result = IC_RESULT(ic);
7141         
7142         aopOp(right,ic,FALSE);
7143         
7144         /* if the shift count is known then do it 
7145         as efficiently as possible */
7146         if (AOP_TYPE(right) == AOP_LIT) {
7147                 genLeftShiftLiteral (left,right,result,ic);
7148                 return ;
7149         }
7150         
7151         /* shift count is unknown then we have to form 
7152         a loop get the loop count in B : Note: we take
7153         only the lower order byte since shifting
7154         more that 32 bits make no sense anyway, ( the
7155         largest size of an object can be only 32 bits ) */  
7156         
7157         
7158         aopOp(left,ic,FALSE);
7159         aopOp(result,ic,FALSE);
7160         
7161         /* now move the left to the result if they are not the
7162         same */
7163         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7164                 AOP_SIZE(result) > 1) {
7165                 
7166                 size = AOP_SIZE(result);
7167                 offset=0;
7168                 while (size--) {
7169                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7170                         if (*l == '@' && (IS_AOP_PREG(result))) {
7171                                 
7172                                 pic14_emitcode("mov","a,%s",l);
7173                                 aopPut(AOP(result),"a",offset);
7174                         } else {
7175                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7176                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7177                                 //aopPut(AOP(result),l,offset);
7178                         }
7179                         offset++;
7180                 }
7181         }
7182         
7183         if(AOP_TYPE(left) == AOP_LIT)
7184                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7185
7186         size = AOP_SIZE(result);
7187         
7188         /* if it is only one byte then */
7189         if (size == 1) {
7190                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7191                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7192                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7193                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7194                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7195                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7196                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7197                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7198                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7199                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7200                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7201                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7202                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7203                 } else {
7204                         
7205                         tlbl = newiTempLabel(NULL);
7206                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7207                                 if (AOP_TYPE(left) == AOP_LIT)
7208                                         emitpcode(POC_MOVLW,  popGetLit(lit));
7209                                 else
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 }