* .version: changed version to 2.5.4
[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     cont'd   -  Raphael Neider rneider@web.de (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45
46 /* When changing these, you must also update the assembler template
47  * in device/lib/libsdcc/macros.inc */
48 #define GPTRTAG_DATA    0x00
49 #define GPTRTAG_CODE    0x80
50
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
55
56 static int labelOffset=0;
57 extern int debug_verbose;
58 //static int optimized_for_speed = 0;
59
60 /* max_key keeps track of the largest label number used in 
61 a function. This is then used to adjust the label offset
62 for the next function.
63 */
64 static int max_key=0;
65 static int GpsuedoStkPtr=0;
66
67 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
68 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
69 unsigned int pic14aopLiteral (value *val, int offset);
70 const char *AopType(short type);
71
72 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
73
74 /* this is the down and dirty file with all kinds of 
75 kludgy & hacky stuff. This is what it is all about
76 CODE GENERATION for a specific MCU . some of the
77 routines may be reusable, will have to see */
78
79 static char *zero = "#0x00";
80 static char *one  = "#0x01";
81 static char *spname = "sp";
82
83 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
84 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
85 static char **fReturn = fReturnpic14;
86
87 //static char *accUse[] = {"a","b"};
88
89 //static short rbank = -1;
90
91 static struct {
92         short r0Pushed;
93         short r1Pushed;
94         short accInUse;
95         short inLine;
96         short debugLine;
97         short nRegsSaved;
98         set *sendSet;
99 } _G;
100
101 /* Resolved ifx structure. This structure stores information
102 about an iCode ifx that makes it easier to generate code.
103 */
104 typedef struct resolvedIfx {
105         symbol *lbl;     /* pointer to a label */
106         int condition;   /* true or false ifx */
107         int generated;   /* set true when the code associated with the ifx
108                           * is generated */
109 } resolvedIfx;
110
111 extern int pic14_ptrRegReq ;
112 extern int pic14_nRegs;
113 extern FILE *codeOutFile;
114 static void saverbank (int, iCode *,bool);
115
116 static lineNode *lineHead = NULL;
117 static lineNode *lineCurr = NULL;
118
119 #if 0
120 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
121 0xE0, 0xC0, 0x80, 0x00};
122 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
123 0x07, 0x03, 0x01, 0x00};
124 #endif
125
126 static  pBlock *pb;
127
128 /*-----------------------------------------------------------------*/
129 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
130 /*                                 exponent of 2 is returned, otherwise -1 is      */
131 /*                                 returned.                                                                       */
132 /* note that this is similar to the function `powof2' in SDCCsymt  */
133 /* if(n == 2^y)                                                                                                    */
134 /*       return y;                                                                                                         */
135 /* return -1;                                                                                                      */
136 /*-----------------------------------------------------------------*/
137 static int my_powof2 (unsigned long num)
138 {
139         if(num) {
140                 if( (num & (num-1)) == 0) {
141                         int nshifts = -1;
142                         while(num) {
143                                 num>>=1;
144                                 nshifts++;
145                         }
146                         return nshifts;
147                 }
148         }
149         
150         return -1;
151 }
152
153 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
154 {
155         
156         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
157                 line_no,
158                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
159                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
160                 ((result) ? AOP_SIZE(result) : 0),
161                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
162                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
163                 ((left)   ? AOP_SIZE(left) : 0),
164                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
165                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
166                 ((right)  ? AOP_SIZE(right) : 0));
167         
168 }
169
170 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
171 {
172         
173         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
174                 line_no,
175                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
176                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
177                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
178                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
179                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
180                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
181         
182 }
183
184 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
185 {
186         va_list ap;
187         char lb[INITIAL_INLINEASM];  
188         unsigned char *lbp = lb;
189         
190         if(!debug_verbose && !options.debug)
191                 return;
192         
193         va_start(ap,fmt);   
194         
195         if (inst && *inst) {
196                 if (fmt && *fmt)
197                         sprintf(lb,"%s\t",inst);
198                 else
199                         sprintf(lb,"%s",inst);
200                 vsprintf(lb+(strlen(lb)),fmt,ap);
201         }  else
202                 vsprintf(lb,fmt,ap);
203         
204         while (isspace(*lbp)) lbp++;
205         
206         if (lbp && *lbp) 
207                 lineCurr = (lineCurr ?
208                 connectLine(lineCurr,newLineNode(lb)) :
209         (lineHead = newLineNode(lb)));
210         lineCurr->isInline = _G.inLine;
211         lineCurr->isDebug  = _G.debugLine;
212         
213         addpCode2pBlock(pb,newpCodeCharP(lb));
214         
215         va_end(ap);
216 }
217
218 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
219 {
220 #if defined (HAVE_VSNPRINTF)
221   vsnprintf (buf, size, fmt, ap);
222 #elif defined (HAVE_VSPRINTF)
223   vsprintf (buf, size, fmt, ap);
224   if (strlen (buf) >= size)
225   {
226     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
227   }
228 #elif defined (HAVE_SNPRINTF)
229   snprintf (buf, size, "vs(n)printf required");
230 #elif defined (HAVE_SRINTF)
231   sprintf (buf, "vs(n)printf required");
232   if (strlen (buf) >= size)
233   {
234     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
235   }
236 #else
237   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
238 #endif
239 }
240
241 void emitpComment (const char *fmt, ...)
242 {
243   va_list va;
244   char buffer[4096];
245   
246   va_start (va, fmt);
247   if (pb) {
248     Safe_vsnprintf (buffer, 4096, fmt, va);
249     //fprintf (stderr, "%s\n" ,buffer);
250     addpCode2pBlock (pb, newpCodeCharP (buffer));
251 #if 0
252   } else {
253     Safe_vsnprintf (buffer, 4096, fmt, va);
254     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
255 #endif
256   }
257   va_end (va);
258 }
259
260 void emitpLabel(int key)
261 {
262         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
263 }
264
265 /* gen.h defines a macro emitpcode that should be used to call emitpcode
266  * as this allows for easy debugging (ever asked the question: where was
267  * this instruction geenrated? Here is the answer... */
268 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
269 {
270         if(pcop)
271                 addpCode2pBlock(pb,newpCode(poc,pcop));
272         else
273                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
274 }
275
276 void emitpcodeNULLop(PIC_OPCODE poc)
277 {
278         
279         addpCode2pBlock(pb,newpCode(poc,NULL));
280         
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* pic14_emitcode - writes the code into a file : for now it is simple    */
286 /*-----------------------------------------------------------------*/
287 void pic14_emitcode (char *inst,char *fmt, ...)
288 {
289         va_list ap;
290         char lb[INITIAL_INLINEASM];  
291         unsigned char *lbp = lb;
292         
293         va_start(ap,fmt);   
294         
295         if (inst && *inst) {
296                 if (fmt && *fmt)
297                         sprintf(lb,"%s\t",inst);
298                 else
299                         sprintf(lb,"%s",inst);
300                 vsprintf(lb+(strlen(lb)),fmt,ap);
301         }  else
302                 vsprintf(lb,fmt,ap);
303         
304         while (isspace(*lbp)) lbp++;
305         
306         if (lbp && *lbp) 
307                 lineCurr = (lineCurr ?
308                 connectLine(lineCurr,newLineNode(lb)) :
309         (lineHead = newLineNode(lb)));
310         lineCurr->isInline = _G.inLine;
311         lineCurr->isDebug  = _G.debugLine;
312         
313         if(debug_verbose)
314                 addpCode2pBlock(pb,newpCodeCharP(lb));
315         
316         va_end(ap);
317 }
318
319 /*-----------------------------------------------------------------*/
320 /* pic14_emitDebuggerSymbol - associate the current code location  */
321 /*       with a debugger symbol                                                                            */
322 /*-----------------------------------------------------------------*/
323 void
324 pic14_emitDebuggerSymbol (char * debugSym)
325 {
326         _G.debugLine = 1;
327         pic14_emitcode ("", ";%s ==.", debugSym);
328         _G.debugLine = 0;
329 }
330
331 #if 0
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
334 /*-----------------------------------------------------------------*/
335 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
336 {
337         bool r0iu = FALSE , r1iu = FALSE;
338         bool r0ou = FALSE , r1ou = FALSE;
339         
340         /* the logic: if r0 & r1 used in the instruction
341         then we are in trouble otherwise */
342         
343         /* first check if r0 & r1 are used by this
344         instruction, in which case we are in trouble */
345         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
346                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
347         {
348                 goto endOfWorld;          
349         }
350         
351         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
352         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
353         
354         /* if no usage of r0 then return it */
355         if (!r0iu && !r0ou) {
356                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
357                 (*aopp)->type = AOP_R0;
358                 
359                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
360         }
361         
362         /* if no usage of r1 then return it */
363         if (!r1iu && !r1ou) {
364                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
365                 (*aopp)->type = AOP_R1;
366                 
367                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
368         }    
369         
370         /* now we know they both have usage */
371         /* if r0 not used in this instruction */
372         if (!r0iu) {
373                 /* push it if not already pushed */
374                 if (!_G.r0Pushed) {
375                         //pic14_emitcode ("push","%s",
376                         //                pic14_regWithIdx(R0_IDX)->dname);
377                         _G.r0Pushed++ ;
378                 }
379                 
380                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
381                 (*aopp)->type = AOP_R0;
382                 
383                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
384         }
385         
386         /* if r1 not used then */
387         
388         if (!r1iu) {
389                 /* push it if not already pushed */
390                 if (!_G.r1Pushed) {
391                         //pic14_emitcode ("push","%s",
392                         //                pic14_regWithIdx(R1_IDX)->dname);
393                         _G.r1Pushed++ ;
394                 }
395                 
396                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
397                 (*aopp)->type = AOP_R1;
398                 return pic14_regWithIdx(R1_IDX);
399         }
400         
401 endOfWorld :
402         /* I said end of world but not quite end of world yet */
403         /* if this is a result then we can push it on the stack*/
404         if (result) {
405                 (*aopp)->type = AOP_STK;        
406                 return NULL;
407         }
408         
409         /* other wise this is true end of the world */
410         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
411                 "getFreePtr should never reach here");
412         exit(0);
413 }
414 #endif
415
416 /*-----------------------------------------------------------------*/
417 /* newAsmop - creates a new asmOp                                                                  */
418 /*-----------------------------------------------------------------*/
419 asmop *newAsmop (short type)
420 {
421         asmop *aop;
422         
423         aop = Safe_calloc(1,sizeof(asmop));
424         aop->type = type;
425         return aop;
426 }
427
428 static void genSetDPTR(int n)
429 {
430         if (!n)
431         {
432                 pic14_emitcode(";", "Select standard DPTR");
433                 pic14_emitcode("mov", "dps, #0x00");
434         }
435         else
436         {
437                 pic14_emitcode(";", "Select alternate DPTR");
438                 pic14_emitcode("mov", "dps, #0x01");
439         }
440 }
441
442 /*-----------------------------------------------------------------*/
443 /* resolveIfx - converts an iCode ifx into a form more useful for  */
444 /*                              generating code                                                                    */
445 /*-----------------------------------------------------------------*/
446 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
447 {
448         if(!resIfx) 
449                 return;
450         
451         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
452         
453         resIfx->condition = 1;  /* assume that the ifx is true */
454         resIfx->generated = 0;  /* indicate that the ifx has not been used */
455         
456         if(!ifx) {
457                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
458                                                                                         /*
459                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
460                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
461                 */
462         } else {
463                 if(IC_TRUE(ifx)) {
464                         resIfx->lbl = IC_TRUE(ifx);
465                 } else {
466                         resIfx->lbl = IC_FALSE(ifx);
467                         resIfx->condition = 0;
468                 }
469                 /*
470                 if(IC_TRUE(ifx)) 
471                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
472                 if(IC_FALSE(ifx)) 
473                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
474                 */
475         }
476         
477         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
478         
479 }
480 /*-----------------------------------------------------------------*/
481 /* pointerCode - returns the code for a pointer type                       */
482 /*-----------------------------------------------------------------*/
483 #if 0
484 static int pointerCode (sym_link *etype)
485 {
486         
487         return PTR_TYPE(SPEC_OCLS(etype));
488         
489 }
490 #endif
491
492 /*-----------------------------------------------------------------*/
493 /* aopForSym - for a true symbol                                                                   */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
496 {
497         asmop *aop;
498         memmap *space= SPEC_OCLS(sym->etype);
499         
500         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
501         /* if already has one */
502         if (sym->aop)
503                 return sym->aop;
504         
505 #if 0
506         /* assign depending on the storage class */
507         /* if it is on the stack or indirectly addressable */
508         /* space we need to assign either r0 or r1 to it         */    
509         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
510                 sym->aop = aop = newAsmop(0);
511                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
512                 aop->size = getSize(sym->type);
513                 
514                 /* now assign the address of the variable to 
515                 the pointer register */
516                 if (aop->type != AOP_STK) {
517                         
518                         if (sym->onStack) {
519                                 if ( _G.accInUse )
520                                         pic14_emitcode("push","acc");
521                                 
522                                 pic14_emitcode("mov","a,_bp");
523                                 pic14_emitcode("add","a,#0x%02x",
524                                         ((sym->stack < 0) ?
525                                         ((char)(sym->stack - _G.nRegsSaved )) :
526                                 ((char)sym->stack)) & 0xff);
527                                 pic14_emitcode("mov","%s,a",
528                                         aop->aopu.aop_ptr->name);
529                                 
530                                 if ( _G.accInUse )
531                                         pic14_emitcode("pop","acc");
532                         } else
533                                 pic14_emitcode("mov","%s,#%s",
534                                 aop->aopu.aop_ptr->name,
535                                 sym->rname);
536                         aop->paged = space->paged;
537                 } else
538                         aop->aopu.aop_stk = sym->stack;
539                 return aop;
540         }
541         
542         if (sym->onStack && options.stack10bit)
543         {
544                 /* It's on the 10 bit stack, which is located in
545                 * far data space.
546                 */
547                 
548                 //DEBUGpic14_emitcode(";","%d",__LINE__);
549                 
550                 if ( _G.accInUse )
551                         pic14_emitcode("push","acc");
552                 
553                 pic14_emitcode("mov","a,_bp");
554                 pic14_emitcode("add","a,#0x%02x",
555                         ((sym->stack < 0) ?
556                         ((char)(sym->stack - _G.nRegsSaved )) :
557                 ((char)sym->stack)) & 0xff);
558                 
559                 genSetDPTR(1);
560                 pic14_emitcode ("mov","dpx1,#0x40");
561                 pic14_emitcode ("mov","dph1,#0x00");
562                 pic14_emitcode ("mov","dpl1, a");
563                 genSetDPTR(0);
564                 
565                 if ( _G.accInUse )
566                         pic14_emitcode("pop","acc");
567                 
568                 sym->aop = aop = newAsmop(AOP_DPTR2);
569                 aop->size = getSize(sym->type); 
570                 return aop;
571         }
572 #endif
573
574         //DEBUGpic14_emitcode(";","%d",__LINE__);
575         /* if in bit space */
576         if (IN_BITSPACE(space)) {
577                 sym->aop = aop = newAsmop (AOP_CRY);
578                 aop->aopu.aop_dir = sym->rname ;
579                 aop->size = getSize(sym->type);
580                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
581                 return aop;
582         }
583         /* if it is in direct space */
584         if (IN_DIRSPACE(space)) {
585                 sym->aop = aop = newAsmop (AOP_DIR);
586                 aop->aopu.aop_dir = sym->rname ;
587                 aop->size = getSize(sym->type);
588                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
589                 return aop;
590         }
591         
592         /* special case for a function */
593         if (IS_FUNC(sym->type)) {   
594                 
595                 sym->aop = aop = newAsmop(AOP_PCODE);
596                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
597                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
598                 PCOI(aop->aopu.pcop)->_function = 1;
599                 PCOI(aop->aopu.pcop)->index = 0;
600                 aop->size = FPTRSIZE; 
601                 /*
602                 sym->aop = aop = newAsmop(AOP_IMMD);    
603                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
604                 strcpy(aop->aopu.aop_immd,sym->rname);
605                 aop->size = FPTRSIZE; 
606                 */
607                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
608                 return aop;
609         }
610         
611         if (IS_ARRAY(sym->type)) {
612                 sym->aop = aop = newAsmop(AOP_PCODE);
613                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
614                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
615                 PCOI(aop->aopu.pcop)->_function = 0;
616                 PCOI(aop->aopu.pcop)->index = 0;
617                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
618                 
619                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
620                 return aop;
621         }
622         
623         /* only remaining is far space */
624         /* in which case DPTR gets the address */
625         sym->aop = aop = newAsmop(AOP_PCODE);
626         
627         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
628         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
629         PCOI(aop->aopu.pcop)->index = 0;
630         
631         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
632                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
633         
634         allocDirReg (IC_LEFT(ic));
635         
636         aop->size = FPTRSIZE;
637         /*
638         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
639         sym->aop = aop = newAsmop(AOP_DPTR);
640         pic14_emitcode ("mov","dptr,#%s", sym->rname);
641         aop->size = getSize(sym->type);
642         
643           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
644         */
645         
646         /* if it is in code space */
647         if (IN_CODESPACE(space))
648                 aop->code = 1;
649         
650         return aop;       
651 }
652
653 /*-----------------------------------------------------------------*/
654 /* aopForRemat - rematerialzes an object                                                   */
655 /*-----------------------------------------------------------------*/
656 static asmop *aopForRemat (operand *op) // x symbol *sym)
657 {
658         symbol *sym = OP_SYMBOL(op);
659         iCode *ic = NULL;
660         asmop *aop = newAsmop(AOP_PCODE);
661         int val = 0;
662         int offset = 0;
663         
664         ic = sym->rematiCode;
665
666         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
667         if(IS_OP_POINTER(op)) {
668                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
669         }
670         for (;;) {
671                 if (ic->op == '+') {
672                         val += (int) operandLitValue(IC_RIGHT(ic));
673                 } else if (ic->op == '-') {
674                         val -= (int) operandLitValue(IC_RIGHT(ic));
675                 } else
676                         break;
677                 
678                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
679         }
680         
681         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
682         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
683         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
684         PCOI(aop->aopu.pcop)->index = val;
685         
686         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
687                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
688                 val, IS_PTR_CONST(operandType(op)));
689         
690         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
691         
692         allocDirReg (IC_LEFT(ic));
693         
694         return aop;              
695 }
696
697 int aopIdx (asmop *aop, int offset)
698 {
699         if(!aop)
700                 return -1;
701         
702         if(aop->type !=  AOP_REG)
703                 return -2;
704         
705         return aop->aopu.aop_reg[offset]->rIdx;
706         
707 }
708 /*-----------------------------------------------------------------*/
709 /* regsInCommon - two operands have some registers in common       */
710 /*-----------------------------------------------------------------*/
711 static bool regsInCommon (operand *op1, operand *op2)
712 {
713         symbol *sym1, *sym2;
714         int i;
715         
716         /* if they have registers in common */
717         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
718                 return FALSE ;
719         
720         sym1 = OP_SYMBOL(op1);
721         sym2 = OP_SYMBOL(op2);
722         
723         if (sym1->nRegs == 0 || sym2->nRegs == 0)
724                 return FALSE ;
725         
726         for (i = 0 ; i < sym1->nRegs ; i++) {
727                 int j;
728                 if (!sym1->regs[i])
729                         continue ;
730                 
731                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
732                         if (!sym2->regs[j])
733                                 continue ;
734                         
735                         if (sym2->regs[j] == sym1->regs[i])
736                                 return TRUE ;
737                 }
738         }
739         
740         return FALSE ;
741 }
742
743 /*-----------------------------------------------------------------*/
744 /* operandsEqu - equivalent                                                                        */
745 /*-----------------------------------------------------------------*/
746 static bool operandsEqu ( operand *op1, operand *op2)
747 {
748         symbol *sym1, *sym2;
749         
750         /* if they not symbols */
751         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
752                 return FALSE;
753         
754         sym1 = OP_SYMBOL(op1);
755         sym2 = OP_SYMBOL(op2);
756         
757         /* if both are itemps & one is spilt
758         and the other is not then false */
759         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
760                 sym1->isspilt != sym2->isspilt )
761                 return FALSE ;
762         
763         /* if they are the same */
764         if (sym1 == sym2)
765                 return TRUE ;
766         
767         if (sym1->rname[0] && sym2->rname[0]
768                 && strcmp (sym1->rname, sym2->rname) == 0)
769                 return TRUE;
770         
771         
772         /* if left is a tmp & right is not */
773         if (IS_ITEMP(op1)  && 
774                 !IS_ITEMP(op2) &&
775                 sym1->isspilt  &&
776                 (sym1->usl.spillLoc == sym2))
777                 return TRUE;
778         
779         if (IS_ITEMP(op2)  && 
780                 !IS_ITEMP(op1) &&
781                 sym2->isspilt  &&
782                 sym1->level > 0 &&
783                 (sym2->usl.spillLoc == sym1))
784                 return TRUE ;
785         
786         return FALSE ;
787 }
788
789 /*-----------------------------------------------------------------*/
790 /* pic14_sameRegs - two asmops have the same registers             */
791 /*-----------------------------------------------------------------*/
792 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
793 {
794         int i;
795         
796         if (aop1 == aop2)
797                 return TRUE ;
798         
799         if (aop1->type != AOP_REG ||
800                 aop2->type != AOP_REG )
801                 return FALSE ;
802         
803         if (aop1->size != aop2->size )
804                 return FALSE ;
805         
806         for (i = 0 ; i < aop1->size ; i++ )
807                 if (aop1->aopu.aop_reg[i] !=
808                         aop2->aopu.aop_reg[i] )
809                         return FALSE ;
810                 
811                 return TRUE ;
812 }
813
814 /*-----------------------------------------------------------------*/
815 /* aopOp - allocates an asmop for an operand  :                    */
816 /*-----------------------------------------------------------------*/
817 void aopOp (operand *op, iCode *ic, bool result)
818 {
819         asmop *aop;
820         symbol *sym;
821         int i;
822         
823         if (!op)
824                 return ;
825         
826         /* if this a literal */
827         if (IS_OP_LITERAL(op)) {
828                 op->aop = aop = newAsmop(AOP_LIT);
829                 aop->aopu.aop_lit = op->operand.valOperand;
830                 aop->size = getSize(operandType(op));
831                 return;
832         }
833         
834         {
835                 sym_link *type = operandType(op);
836                 if(IS_PTR_CONST(type))
837                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
838         }
839         
840         /* if already has a asmop then continue */
841         if (op->aop)
842                 return ;
843         
844         /* if the underlying symbol has a aop */
845         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
846                 DEBUGpic14_emitcode(";","%d",__LINE__);
847                 op->aop = OP_SYMBOL(op)->aop;
848                 return;
849         }
850         
851         /* if this is a true symbol */
852         if (IS_TRUE_SYMOP(op)) {          
853                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
854                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
855                 return ;
856         }
857         
858         /* this is a temporary : this has
859         only four choices :
860         a) register
861         b) spillocation
862         c) rematerialize 
863         d) conditional   
864         e) can be a return use only */
865         
866         sym = OP_SYMBOL(op);
867         
868         
869         /* if the type is a conditional */
870         if (sym->regType == REG_CND) {
871                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
872                 aop->size = 0;
873                 return;
874         }
875         
876         /* if it is spilt then two situations
877         a) is rematerialize 
878         b) has a spill location */
879         if (sym->isspilt || sym->nRegs == 0) {
880                 
881                 DEBUGpic14_emitcode(";","%d",__LINE__);
882                 /* rematerialize it NOW */
883                 if (sym->remat) {
884                         
885                         sym->aop = op->aop = aop = aopForRemat (op);
886                         aop->size = getSize(sym->type);
887                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
888                         return;
889                 }
890                 
891 #if 0
892                 /* WREG is not usable as an ordinary operand with PIC architecture,
893                  * one might introduce a scratch register that can be used to make
894                  * WREG accesible as an operand... disable WREG for now */
895                 if (sym->accuse) {
896                         int i;
897                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
898                         aop->size = getSize(sym->type);
899                         for ( i = 0 ; i < 2 ; i++ )
900                                 aop->aopu.aop_str[i] = accUse[i];
901                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
902                         return;  
903                 }
904 #endif
905                 
906                 if (sym->ruonly ) {
907                         if(sym->isptr) {        // && sym->uptr 
908                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
909                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
910                                 
911                                 //PCOI(aop->aopu.pcop)->_const = 0;
912                                 //PCOI(aop->aopu.pcop)->index = 0;
913                                 /*
914                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
915                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
916                                 */
917                                 //allocDirReg (IC_LEFT(ic));
918                                 
919                                 aop->size = getSize(sym->type);
920                                 DEBUGpic14_emitcode(";","%d",__LINE__);
921                                 return;
922                                 
923                         } else {
924                                 
925                                 unsigned i;
926                                 
927                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
928                                 aop->size = getSize(sym->type);
929                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
930                                         aop->aopu.aop_str[i] = fReturn[i];
931                                 
932                                 DEBUGpic14_emitcode(";","%d",__LINE__);
933                                 return;
934                         }
935                 }
936                 
937                 /* else spill location  */
938                 if (sym->usl.spillLoc)
939                 {
940                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
941                         {
942                                 /* force a new aop if sizes differ */
943                                 sym->usl.spillLoc->aop = NULL;
944                         }
945                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
946                                 __FUNCTION__,__LINE__,
947                                 sym->usl.spillLoc->rname,
948                                 sym->rname, sym->usl.spillLoc->offset);
949                 
950                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
951                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
952                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
953                                 getSize(sym->type), 
954                                 sym->usl.spillLoc->offset);
955                         aop->size = getSize(sym->type);
956                 
957                         return;
958                 }
959         }
960         
961         {
962                 sym_link *type = operandType(op);
963                 if(IS_PTR_CONST(type)) 
964                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
965         }
966         
967         /* must be in a register */
968         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
969         sym->aop = op->aop = aop = newAsmop(AOP_REG);
970         aop->size = sym->nRegs;
971         for ( i = 0 ; i < sym->nRegs ;i++)
972                 aop->aopu.aop_reg[i] = sym->regs[i];
973 }
974
975 /*-----------------------------------------------------------------*/
976 /* freeAsmop - free up the asmop given to an operand                       */
977 /*----------------------------------------------------------------*/
978 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
979 {       
980         asmop *aop ;
981         
982         if (!op)
983                 aop = aaop;
984         else 
985                 aop = op->aop;
986         
987         if (!aop)
988                 return ;
989         
990         if (aop->freed)
991                 goto dealloc; 
992         
993         aop->freed = 1;
994         
995         /* depending on the asmop type only three cases need work AOP_RO
996         , AOP_R1 && AOP_STK */
997 #if 0
998         switch (aop->type) {
999         case AOP_R0 :
1000                 if (_G.r0Pushed ) {
1001                         if (pop) {
1002                                 pic14_emitcode ("pop","ar0");     
1003                                 _G.r0Pushed--;
1004                         }
1005                 }
1006                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1007                 break;
1008                 
1009         case AOP_R1 :
1010                 if (_G.r1Pushed ) {
1011                         if (pop) {
1012                                 pic14_emitcode ("pop","ar1");
1013                                 _G.r1Pushed--;
1014                         }
1015                 }
1016                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1017                 break;
1018                 
1019         case AOP_STK :
1020                 {
1021                         int sz = aop->size;      
1022                         int stk = aop->aopu.aop_stk + aop->size;
1023                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1024                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1025                         
1026                         getFreePtr(ic,&aop,FALSE);
1027                         
1028                         if (options.stack10bit)
1029                         {
1030                                 /* I'm not sure what to do here yet... */
1031                                 /* #STUB */
1032                                 fprintf(stderr, 
1033                                         "*** Warning: probably generating bad code for "
1034                                         "10 bit stack mode.\n");
1035                         }
1036                         
1037                         if (stk) {
1038                                 pic14_emitcode ("mov","a,_bp");
1039                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1040                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1041                         } else {
1042                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1043                         }
1044                         
1045                         while (sz--) {
1046                                 pic14_emitcode("pop","acc");
1047                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1048                                 if (!sz) break;
1049                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1050                         }
1051                         op->aop = aop;
1052                         freeAsmop(op,NULL,ic,TRUE);
1053                         if (_G.r0Pushed) {
1054                                 pic14_emitcode("pop","ar0");
1055                                 _G.r0Pushed--;
1056                         }
1057                         
1058                         if (_G.r1Pushed) {
1059                                 pic14_emitcode("pop","ar1");
1060                                 _G.r1Pushed--;
1061                         }         
1062                 }
1063         }
1064 #endif
1065         
1066 dealloc:
1067         /* all other cases just dealloc */
1068         if (op ) {
1069                 op->aop = NULL;
1070                 if (IS_SYMOP(op)) {
1071                         OP_SYMBOL(op)->aop = NULL;      
1072                         /* if the symbol has a spill */
1073                         if (SPIL_LOC(op))
1074                                 SPIL_LOC(op)->aop = NULL;
1075                 }
1076         }
1077 }
1078
1079 /*-----------------------------------------------------------------*/
1080 /* aopGet - for fetching value of the aop                                                  */
1081 /*-----------------------------------------------------------------*/
1082 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1083 {
1084         char *s = buffer ;
1085         char *rs;
1086         
1087         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1088         /* offset is greater than
1089         size then zero */
1090         if (offset > (aop->size - 1) &&
1091                 aop->type != AOP_LIT)
1092                 return zero;
1093         
1094         /* depending on type */
1095         switch (aop->type) {
1096                 
1097         case AOP_R0:
1098         case AOP_R1:
1099                 DEBUGpic14_emitcode(";","%d",__LINE__);
1100                 /* if we need to increment it */           
1101                 while (offset > aop->coff) {            
1102                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1103                         aop->coff++;
1104                 }
1105                 
1106                 while (offset < aop->coff) {
1107                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1108                         aop->coff--;
1109                 }
1110                 
1111                 aop->coff = offset ;
1112                 if (aop->paged) {
1113                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1114                         return (dname ? "acc" : "a");
1115                 }               
1116                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1117                 rs = Safe_calloc(1,strlen(s)+1);
1118                 strcpy(rs,s);   
1119                 return rs;
1120                 
1121         case AOP_DPTR:
1122         case AOP_DPTR2:
1123                 DEBUGpic14_emitcode(";","%d",__LINE__);
1124                 if (aop->type == AOP_DPTR2)
1125                 {
1126                         genSetDPTR(1);
1127                 }
1128                 
1129                 while (offset > aop->coff) {
1130                         pic14_emitcode ("inc","dptr");
1131                         aop->coff++;
1132                 }
1133                 
1134                 while (offset < aop->coff) {            
1135                         pic14_emitcode("lcall","__decdptr");
1136                         aop->coff--;
1137                 }
1138                 
1139                 aop->coff = offset;
1140                 if (aop->code) {
1141                         pic14_emitcode("clr","a");
1142                         pic14_emitcode("movc","a,@a+dptr");
1143                 }
1144                 else {
1145                         pic14_emitcode("movx","a,@dptr");
1146                 }
1147                 
1148                 if (aop->type == AOP_DPTR2)
1149                 {
1150                         genSetDPTR(0);
1151                 }
1152                 
1153                 return (dname ? "acc" : "a");
1154                 
1155                 
1156         case AOP_IMMD:
1157                 if (bit16) 
1158                         sprintf (s,"%s",aop->aopu.aop_immd);
1159                 else
1160                         if (offset) 
1161                                 sprintf(s,"(%s >> %d)",
1162                                 aop->aopu.aop_immd,
1163                                 offset*8);
1164                         else
1165                                 sprintf(s,"%s",
1166                                 aop->aopu.aop_immd);
1167                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1168                         rs = Safe_calloc(1,strlen(s)+1);
1169                         strcpy(rs,s);   
1170                         return rs;
1171                         
1172         case AOP_DIR:
1173                 if (offset) {
1174                         sprintf(s,"(%s + %d)",
1175                                 aop->aopu.aop_dir,
1176                                 offset);
1177                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1178                 } else
1179                         sprintf(s,"%s",aop->aopu.aop_dir);
1180                 rs = Safe_calloc(1,strlen(s)+1);
1181                 strcpy(rs,s);   
1182                 return rs;
1183                 
1184         case AOP_REG:
1185                 //if (dname) 
1186                 //        return aop->aopu.aop_reg[offset]->dname;
1187                 //else
1188                 return aop->aopu.aop_reg[offset]->name;
1189                 
1190         case AOP_CRY:
1191                 //pic14_emitcode(";","%d",__LINE__);
1192                 return aop->aopu.aop_dir;
1193                 
1194         case AOP_ACC:
1195                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1196                 return "AOP_accumulator_bug";
1197                 
1198         case AOP_LIT:
1199                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1200                 rs = Safe_calloc(1,strlen(s)+1);
1201                 strcpy(rs,s);   
1202                 return rs;
1203                 
1204         case AOP_STR:
1205                 aop->coff = offset ;
1206                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1207                         dname)
1208                         return "acc";
1209                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1210                 
1211                 return aop->aopu.aop_str[offset];
1212                 
1213         case AOP_PCODE:
1214                 {
1215                         pCodeOp *pcop = aop->aopu.pcop;
1216                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1217                         if(pcop->name) {
1218                                 if (offset) {
1219                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1220                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1221                                 } else {
1222                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1223                                         sprintf(s,"%s", pcop->name);
1224                                 }
1225                         } else
1226                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1227                         
1228                 }
1229                 rs = Safe_calloc(1,strlen(s)+1);
1230                 strcpy(rs,s);   
1231                 return rs;
1232                 
1233   }
1234   
1235   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1236           "aopget got unsupported aop->type");
1237   exit(0);
1238 }
1239
1240
1241 /*-----------------------------------------------------------------*/
1242 /* popGetTempReg - create a new temporary pCodeOp                                  */
1243 /*-----------------------------------------------------------------*/
1244 pCodeOp *popGetTempReg(void)
1245 {
1246         
1247         pCodeOp *pcop;
1248         
1249         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1250         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1251                 PCOR(pcop)->r->wasUsed=1;
1252                 PCOR(pcop)->r->isFree=0;
1253         }
1254         
1255         return pcop;
1256 }
1257
1258 /*-----------------------------------------------------------------*/
1259 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1260 /*-----------------------------------------------------------------*/
1261 void popReleaseTempReg(pCodeOp *pcop)
1262 {
1263         
1264         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1265                 PCOR(pcop)->r->isFree = 1;
1266         
1267 }
1268 /*-----------------------------------------------------------------*/
1269 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1270 /*-----------------------------------------------------------------*/
1271 pCodeOp *popGetLabel(unsigned int key)
1272 {
1273         
1274         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1275         
1276         if(key>(unsigned int)max_key)
1277                 max_key = key;
1278         
1279         return newpCodeOpLabel(NULL,key+100+labelOffset);
1280 }
1281
1282 /*-------------------------------------------------------------------*/
1283 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1284 /*-------------------------------------------------------------------*/
1285 pCodeOp *popGetHighLabel(unsigned int key)
1286 {
1287         pCodeOp *pcop;
1288         pcop = popGetLabel(key);
1289         PCOLAB(pcop)->offset = 1;
1290         return pcop;
1291 }
1292
1293 /*-----------------------------------------------------------------*/
1294 /* popGetLit - asm operator to pcode operator conversion                           */
1295 /*-----------------------------------------------------------------*/
1296 pCodeOp *popGetLit(unsigned int lit)
1297 {
1298         
1299         return newpCodeOpLit((unsigned char)lit);
1300 }
1301
1302 /*-----------------------------------------------------------------*/
1303 /* popGetImmd - asm operator to pcode immediate conversion                 */
1304 /*-----------------------------------------------------------------*/
1305 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1306 {
1307         
1308         return newpCodeOpImmd(name, offset,index, 0, is_func);
1309 }
1310
1311 extern set *externs;
1312
1313 /*-----------------------------------------------------------------*/
1314 /* popGetWithString - asm operator to pcode operator conversion                    */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *popGetWithString(char *str, int isExtern)
1317 {
1318         pCodeOp *pcop;
1319         
1320         
1321         if(!str) {
1322                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1323                 exit (1);
1324         }
1325         
1326         pcop = newpCodeOp(str,PO_STR);
1327         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1328
1329         return pcop;
1330 }
1331
1332 pCodeOp *popGetExternal (char *str)
1333 {
1334         pCodeOp *pcop = popGetWithString (str, 1);
1335         
1336         if (str) {
1337           symbol *sym;
1338           bool found = 0;
1339
1340           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1341           {
1342             if (!strcmp (str, sym->rname))
1343               found = 1;
1344           }
1345           
1346           if (!found)
1347           {
1348             sym = newSymbol(str, 0);
1349             strncpy(sym->rname, str, SDCC_NAME_MAX);
1350             addSet (&externs, sym);
1351           } // if
1352         }
1353         return pcop;
1354 }
1355
1356 /*-----------------------------------------------------------------*/
1357 /* popRegFromString -                                                                                      */
1358 /*-----------------------------------------------------------------*/
1359 pCodeOp *popRegFromString(char *str, int size, int offset)
1360 {
1361         
1362         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1363         pcop->type = PO_DIR;
1364         
1365         DEBUGpic14_emitcode(";","%d",__LINE__);
1366         
1367         if(!str)
1368                 str = "BAD_STRING";
1369         
1370         pcop->name = Safe_calloc(1,strlen(str)+1);
1371         strcpy(pcop->name,str);
1372         
1373         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1374         
1375         PCOR(pcop)->r = dirregWithName(pcop->name);
1376         if(PCOR(pcop)->r == NULL) {
1377                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1378                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1379                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1380         } else {
1381                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1382         }
1383         PCOR(pcop)->instance = offset;
1384         
1385         return pcop;
1386 }
1387
1388 /*-----------------------------------------------------------------*/
1389 /*-----------------------------------------------------------------*/
1390 pCodeOp *popRegFromIdx(int rIdx)
1391 {
1392         pCodeOp *pcop;
1393         
1394         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1395                 __FUNCTION__,__LINE__,rIdx);
1396         
1397         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1398         
1399         PCOR(pcop)->rIdx = rIdx;
1400         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1401         PCOR(pcop)->r->isFree = 0;
1402         PCOR(pcop)->r->wasUsed = 1;
1403         
1404         pcop->type = PCOR(pcop)->r->pc_type;
1405         
1406         
1407         return pcop;
1408 }
1409
1410 /*-----------------------------------------------------------------*/
1411 /* popGet - asm operator to pcode operator conversion                      */
1412 /*-----------------------------------------------------------------*/
1413 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1414 {
1415         //char *s = buffer ;
1416         //char *rs;
1417         
1418         pCodeOp *pcop;
1419         
1420         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1421         /* offset is greater than
1422         size then zero */
1423
1424         assert (aop);
1425
1426         /* XXX: still needed for BIT operands (AOP_CRY) */
1427         if (offset > (aop->size - 1) &&
1428                 aop->type != AOP_LIT)
1429                 return NULL;  //zero;
1430         
1431         /* depending on type */
1432         switch (aop->type) {
1433                 
1434         case AOP_R0:
1435         case AOP_R1:
1436         case AOP_DPTR:
1437         case AOP_DPTR2:
1438         case AOP_ACC:
1439                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1440                 return NULL;
1441                 
1442         case AOP_IMMD:
1443                 DEBUGpic14_emitcode(";","%d",__LINE__);
1444                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1445                 
1446         case AOP_DIR:
1447                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1448 #if 0
1449                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1450                 pcop->type = PO_DIR;
1451                 
1452                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1453                 strcpy(pcop->name,aop->aopu.aop_dir);   
1454                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1455                 if(PCOR(pcop)->r == NULL) {
1456                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1457                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1458                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1459                 } else {
1460                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1461                 }
1462                 PCOR(pcop)->instance = offset;
1463                 
1464                 return pcop;
1465 #endif
1466                 
1467         case AOP_REG:
1468                 {
1469                         int rIdx;
1470                         assert (offset < aop->size);
1471                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1472                         
1473                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1474                         PCOR(pcop)->rIdx = rIdx;
1475                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1476                         PCOR(pcop)->r->wasUsed=1;
1477                         PCOR(pcop)->r->isFree=0;
1478                         
1479                         PCOR(pcop)->instance = offset;
1480                         pcop->type = PCOR(pcop)->r->pc_type;
1481                         //rs = aop->aopu.aop_reg[offset]->name;
1482                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1483                         return pcop;
1484                 }
1485                 
1486         case AOP_CRY:
1487                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1488                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1489                 //if(PCOR(pcop)->r == NULL)
1490                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1491                 return pcop;
1492                 
1493         case AOP_LIT:
1494                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1495                 
1496         case AOP_STR:
1497                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1498                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1499                 /*
1500                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1501                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1502                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1503                 pcop->type = PCOR(pcop)->r->pc_type;
1504                 pcop->name = PCOR(pcop)->r->name;
1505                 
1506                   return pcop;
1507                 */
1508                 
1509         case AOP_PCODE:
1510                 pcop = NULL;
1511                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1512                         __LINE__, 
1513                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1514                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1515                 switch (aop->aopu.pcop->type)
1516                 {
1517                 case PO_IMMEDIATE:
1518                   pcop = pCodeOpCopy (aop->aopu.pcop);
1519                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1520                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1521                   PCOI(pcop)->index += offset;
1522                   //PCOI(pcop)->offset = 0;
1523                   break;
1524                 case PO_DIR:
1525                   pcop = pCodeOpCopy (aop->aopu.pcop);
1526                   PCOR(pcop)->instance = offset;
1527                   break;
1528                 default:
1529                   assert ( !"unhandled pCode type" );
1530                   break;
1531                 } // switch
1532                 return pcop;
1533         }
1534         
1535         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1536                 "popGet got unsupported aop->type");
1537         exit(0);
1538 }
1539
1540 /*-----------------------------------------------------------------*/
1541 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1542 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1543 /*-----------------------------------------------------------------*/
1544 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1545 {
1546   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1547   {
1548     pCodeOp *pcop = aop->aopu.pcop;
1549     assert (offset <= GPTRSIZE);
1550
1551     /* special case: index >= 2 should return GPOINTER-style values */
1552     if (offset == 2)
1553     {
1554       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1555       return pcop;
1556     }
1557     
1558     pcop = pCodeOpCopy (pcop);
1559     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1560      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1561     PCOI(pcop)->offset += offset;
1562     PCOI(pcop)->index += index;
1563     //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1564     return pcop;
1565   } else {
1566     return popGet (aop, offset + index);
1567   }
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* aopPut - puts a string for a aop                                                        */
1572 /*-----------------------------------------------------------------*/
1573 void aopPut (asmop *aop, char *s, int offset)
1574 {
1575         char *d = buffer ;
1576         symbol *lbl ;
1577         
1578         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1579         
1580         if (aop->size && offset > ( aop->size - 1)) {
1581                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1582                         "aopPut got offset > aop->size");
1583                 exit(0);
1584         }
1585         
1586         /* will assign value to value */
1587         /* depending on where it is ofcourse */
1588         switch (aop->type) {
1589         case AOP_DIR:
1590                 if (offset) {
1591                         sprintf(d,"(%s + %d)",
1592                                 aop->aopu.aop_dir,offset);
1593                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1594                         
1595                 } else
1596                         sprintf(d,"%s",aop->aopu.aop_dir);
1597                 
1598                 if (strcmp(d,s)) {
1599                         DEBUGpic14_emitcode(";","%d",__LINE__);
1600                         if(strcmp(s,"W"))
1601                                 pic14_emitcode("movf","%s,w",s);
1602                         pic14_emitcode("movwf","%s",d);
1603                         
1604                         if(strcmp(s,"W")) {
1605                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1606                                 if(offset >= aop->size) {
1607                                         emitpcode(POC_CLRF,popGet(aop,offset));
1608                                         break;
1609                                 } else {
1610                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1611                                 }
1612                         }
1613                         emitpcode(POC_MOVWF,popGet(aop,offset));
1614                 
1615                 }
1616                 break;
1617                 
1618         case AOP_REG:
1619                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1620                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1621                         /*
1622                         if (*s == '@'             ||
1623                         strcmp(s,"r0") == 0 ||
1624                         strcmp(s,"r1") == 0 ||
1625                         strcmp(s,"r2") == 0 ||
1626                         strcmp(s,"r3") == 0 ||
1627                         strcmp(s,"r4") == 0 ||
1628                         strcmp(s,"r5") == 0 ||
1629                         strcmp(s,"r6") == 0 || 
1630                         strcmp(s,"r7") == 0 )
1631                         pic14_emitcode("mov","%s,%s  ; %d",
1632                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1633                         else
1634                         */
1635                         
1636                         if(strcmp(s,"W")==0 )
1637                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1638                         
1639                         pic14_emitcode("movwf","%s",
1640                                 aop->aopu.aop_reg[offset]->name);
1641                         
1642                         if(strcmp(s,zero)==0) {
1643                                 emitpcode(POC_CLRF,popGet(aop,offset));
1644                                 
1645                         } else if(strcmp(s,"W")==0) {
1646                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1647                                 pcop->type = PO_GPR_REGISTER;
1648                                 
1649                                 PCOR(pcop)->rIdx = -1;
1650                                 PCOR(pcop)->r = NULL;
1651                                 
1652                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1653                                 pcop->name = Safe_strdup(s);
1654                                 emitpcode(POC_MOVFW,pcop);
1655                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1656                         } else if(strcmp(s,one)==0) {
1657                                 emitpcode(POC_CLRF,popGet(aop,offset));
1658                                 emitpcode(POC_INCF,popGet(aop,offset));
1659                         } else {
1660                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1661                         }
1662                 }
1663                 break;
1664                 
1665         case AOP_DPTR:
1666         case AOP_DPTR2:
1667                 
1668                 if (aop->type == AOP_DPTR2)
1669                 {
1670                         genSetDPTR(1);
1671                 }
1672                 
1673                 if (aop->code) {
1674                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1675                                 "aopPut writting to code space");
1676                         exit(0);
1677                 }
1678                 
1679                 while (offset > aop->coff) {
1680                         aop->coff++;
1681                         pic14_emitcode ("inc","dptr");
1682                 }
1683                 
1684                 while (offset < aop->coff) {
1685                         aop->coff-- ;
1686                         pic14_emitcode("lcall","__decdptr");
1687                 }
1688                 
1689                 aop->coff = offset;
1690                 
1691                 /* if not in accumulater */
1692                 MOVA(s);
1693                 
1694                 pic14_emitcode ("movx","@dptr,a");
1695                 
1696                 if (aop->type == AOP_DPTR2)
1697                 {
1698                         genSetDPTR(0);
1699                 }
1700                 break;
1701                 
1702         case AOP_R0:
1703         case AOP_R1:
1704                 while (offset > aop->coff) {
1705                         aop->coff++;
1706                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1707                 }
1708                 while (offset < aop->coff) {
1709                         aop->coff-- ;
1710                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1711                 }
1712                 aop->coff = offset;
1713                 
1714                 if (aop->paged) {
1715                         MOVA(s);                         
1716                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1717                         
1718                 } else
1719                         if (*s == '@') {
1720                                 MOVA(s);
1721                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1722                         } else
1723                                 if (strcmp(s,"r0") == 0 ||
1724                                         strcmp(s,"r1") == 0 ||
1725                                         strcmp(s,"r2") == 0 ||
1726                                         strcmp(s,"r3") == 0 ||
1727                                         strcmp(s,"r4") == 0 ||
1728                                         strcmp(s,"r5") == 0 ||
1729                                         strcmp(s,"r6") == 0 || 
1730                                         strcmp(s,"r7") == 0 ) {
1731                                         char buffer[10];
1732                                         sprintf(buffer,"a%s",s);
1733                                         pic14_emitcode("mov","@%s,%s",
1734                                                 aop->aopu.aop_ptr->name,buffer);
1735                                 } else
1736                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1737                                 
1738                                 break;
1739                                 
1740         case AOP_STK:
1741                 if (strcmp(s,"a") == 0)
1742                         pic14_emitcode("push","acc");
1743                 else
1744                         pic14_emitcode("push","%s",s);
1745                 
1746                 break;
1747                 
1748         case AOP_CRY:
1749                 /* if bit variable */
1750                 if (!aop->aopu.aop_dir) {
1751                         pic14_emitcode("clr","a");
1752                         pic14_emitcode("rlc","a");
1753                 } else {
1754                         if (s == zero) 
1755                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1756                         else
1757                                 if (s == one)
1758                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1759                                 else
1760                                         if (!strcmp(s,"c"))
1761                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1762                                         else {
1763                                                 lbl = newiTempLabel(NULL);
1764                                                 
1765                                                 if (strcmp(s,"a")) {
1766                                                         MOVA(s);
1767                                                 }
1768                                                 pic14_emitcode("clr","c");
1769                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1770                                                 pic14_emitcode("cpl","c");
1771                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1772                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1773                                         }
1774                 }
1775                 break;
1776                 
1777         case AOP_STR:
1778                 aop->coff = offset;
1779                 if (strcmp(aop->aopu.aop_str[offset],s))
1780                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1781                 break;
1782                 
1783         case AOP_ACC:
1784                 aop->coff = offset;
1785                 if (!offset && (strcmp(s,"acc") == 0))
1786                         break;
1787                 
1788                 if (strcmp(aop->aopu.aop_str[offset],s))
1789                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1790                 break;
1791                 
1792         default :
1793                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1794                         "aopPut got unsupported aop->type");
1795                 exit(0);
1796         }
1797         
1798 }
1799
1800 /*-----------------------------------------------------------------*/
1801 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1802 /*-----------------------------------------------------------------*/
1803 static void mov2w_op (operand *op, int offset)
1804 {
1805         assert (op);
1806         FENTRY;
1807
1808         /* for PO_IMMEDIATEs: use address or value? */
1809         if (op_isLitLike (op))
1810         {
1811                 /* access address of op */
1812                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1813                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1814                 {
1815                         if (offset == GPTRSIZE-1)
1816                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1817                         else
1818                                 emitpcode (POC_MOVLW, popGetLit (0));
1819                 }
1820                 else
1821                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1822         } else {
1823                 /* access value stored in op */
1824                 mov2w (AOP(op), offset);
1825         }
1826 }
1827
1828
1829 /*-----------------------------------------------------------------*/
1830 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1831 /*-----------------------------------------------------------------*/
1832 void mov2w (asmop *aop, int offset)
1833 {
1834         
1835         if(!aop)
1836                 return;
1837         
1838         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1839         
1840         if ( aop_isLitLike (aop) )
1841                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1842         else
1843                 emitpcode(POC_MOVFW,popGet(aop,offset));
1844         
1845 }
1846
1847 static void movwf (asmop *op, int offset)
1848 {
1849         emitpcode (POC_MOVWF, popGet(op, offset));
1850 }
1851
1852 static pCodeOp *get_argument_pcop (int idx)
1853 {
1854         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1855         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1856 }
1857
1858 static pCodeOp *get_return_val_pcop (int offset)
1859 {
1860         assert (offset > 0 && "the most significant byte is returned via WREG");
1861         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1862 }
1863
1864 static void pass_argument (operand *op, int offset, int idx)
1865 {
1866         if (op)
1867                 mov2w_op (op, offset);
1868         if (idx != 0)
1869                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1870 }
1871
1872 static void get_returnvalue (operand *op, int offset, int idx)
1873 {
1874         if (idx != 0)
1875                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1876         movwf(AOP(op), offset);
1877 }
1878
1879 static void call_libraryfunc (char *name)
1880 {
1881   /* library code might reside in different page... */
1882   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1883   /* call the library function */
1884   emitpcode (POC_CALL, popGetExternal (name));
1885   /* might return from different page... */
1886   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1887 }
1888 #if 0
1889 /*-----------------------------------------------------------------*/
1890 /* reAdjustPreg - points a register back to where it should        */
1891 /*-----------------------------------------------------------------*/
1892 static void reAdjustPreg (asmop *aop)
1893 {
1894         int size ;
1895         
1896         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1897         aop->coff = 0;
1898         if ((size = aop->size) <= 1)
1899                 return ;
1900         size-- ;
1901         switch (aop->type) {
1902         case AOP_R0 :
1903         case AOP_R1 :
1904                 while (size--)
1905                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1906                 break;                  
1907         case AOP_DPTR :
1908         case AOP_DPTR2:
1909                 if (aop->type == AOP_DPTR2)
1910                 {
1911                         genSetDPTR(1);
1912                 } 
1913                 while (size--)
1914                 {
1915                         pic14_emitcode("lcall","__decdptr");
1916                 }
1917                 
1918                 if (aop->type == AOP_DPTR2)
1919                 {
1920                         genSetDPTR(0);
1921                 }
1922                 break;
1923                 
1924         }
1925         
1926 }
1927 #endif
1928
1929
1930 #if 0
1931 /*-----------------------------------------------------------------*/
1932 /* opIsGptr: returns non-zero if the passed operand is             */
1933 /* a generic pointer type.                                         */
1934 /*-----------------------------------------------------------------*/ 
1935 static int opIsGptr(operand *op)
1936 {
1937         sym_link *type = operandType(op);
1938         
1939         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1940         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1941         {
1942                 return 1;
1943         }
1944         return 0;          
1945 }
1946 #endif
1947
1948 /*-----------------------------------------------------------------*/
1949 /* pic14_getDataSize - get the operand data size                   */
1950 /*-----------------------------------------------------------------*/
1951 int pic14_getDataSize(operand *op)
1952 {
1953         int size;
1954         
1955         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1956         
1957 #if 0
1958         size = getSize(OP_SYM_ETYPE(op));
1959         return size;
1960         //return AOP_SIZE(op);
1961         
1962         // tsd- in the pic port, the genptr size is 1, so this code here
1963         // fails. ( in the 8051 port, the size was 4).
1964 #else
1965         size = AOP_SIZE(op);
1966         if (IS_GENPTR(OP_SYM_TYPE(op)))
1967         {
1968                 sym_link *type = operandType(op);
1969                 if (IS_GENPTR(type))
1970                 {
1971                         /* generic pointer; arithmetic operations
1972                         * should ignore the high byte (pointer type).
1973                         */
1974                         size--;
1975                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1976                 }
1977         }
1978         return size;
1979 #endif
1980 }
1981
1982 /*-----------------------------------------------------------------*/
1983 /* pic14_outAcc - output Acc                                       */
1984 /*-----------------------------------------------------------------*/
1985 void pic14_outAcc(operand *result)
1986 {
1987         int size,offset;
1988         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1989         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1990         
1991         
1992         size = pic14_getDataSize(result);
1993         if(size){
1994                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1995                 size--;
1996                 offset = 1;
1997                 /* unsigned or positive */
1998                 while(size--)
1999                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2000         }
2001         
2002 }
2003
2004 /*-----------------------------------------------------------------*/
2005 /* pic14_outBitC - output a bit C                                  */
2006 /*-----------------------------------------------------------------*/
2007 void pic14_outBitC(operand *result)
2008 {
2009         
2010         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2011         /* if the result is bit */
2012         if (AOP_TYPE(result) == AOP_CRY) 
2013                 aopPut(AOP(result),"c",0);
2014         else {
2015                 pic14_emitcode("clr","a  ; %d", __LINE__);
2016                 pic14_emitcode("rlc","a");
2017                 pic14_outAcc(result);
2018         }
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2023 /*-----------------------------------------------------------------*/
2024 void pic14_toBoolean(operand *oper)
2025 {
2026         int size = AOP_SIZE(oper);
2027         int offset = 0;
2028         
2029         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2030
2031         assert (size > 0);
2032
2033         if (size == 1) {
2034                 /* MOVFW does not load the flags... */
2035                 if (AOP_TYPE(oper) == AOP_ACC) {
2036                         emitpcode(POC_IORLW, popGetLit(0));
2037                         offset = 1;
2038                 } else {
2039                         emitpcode(POC_MOVLW, popGetLit(0));
2040                         offset = 0;
2041                 }
2042         } else {
2043                 if ( AOP_TYPE(oper) != AOP_ACC) {
2044                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2045                         offset = 1;
2046                 }
2047         }
2048         
2049         while (offset < size) {
2050                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2051         }
2052         /* Z is set iff (oper == 0) */
2053 }
2054
2055
2056 /*-----------------------------------------------------------------*/
2057 /* genNot - generate code for ! operation                          */
2058 /*-----------------------------------------------------------------*/
2059 static void genNot (iCode *ic)
2060 {
2061         //symbol *tlbl;
2062         int size;
2063
2064         FENTRY;
2065         
2066         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2067         /* assign asmOps to operand & result */
2068         aopOp (IC_LEFT(ic),ic,FALSE);
2069         aopOp (IC_RESULT(ic),ic,TRUE);
2070         
2071         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2072         /* if in bit space then a special case */
2073         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2074                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2075                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2076                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2077                 } else {
2078                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2079                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2080                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2081                 }
2082                 goto release;
2083         }
2084         
2085         size = AOP_SIZE(IC_LEFT(ic));
2086         mov2w (AOP(IC_LEFT(ic)),0);
2087         while (--size > 0)
2088         {
2089           if (op_isLitLike (IC_LEFT(ic)))
2090             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2091           else
2092             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2093         }
2094         emitpcode(POC_MOVLW, popGetLit (0));
2095         emitSKPNZ;
2096         emitpcode(POC_MOVLW, popGetLit (1));
2097         movwf(AOP(IC_RESULT(ic)), 0);
2098
2099         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2100         {
2101           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2102         }
2103         goto release;
2104         
2105 release:        
2106         /* release the aops */
2107         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2108         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2109 }
2110
2111
2112 /*-----------------------------------------------------------------*/
2113 /* genCpl - generate code for complement                                                   */
2114 /*-----------------------------------------------------------------*/
2115 static void genCpl (iCode *ic)
2116 {
2117         operand *left, *result;
2118         int size, offset=0;  
2119         
2120         FENTRY;
2121         
2122         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2123         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2124         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2125         
2126         /* if both are in bit space then 
2127         a special case */
2128         if (AOP_TYPE(result) == AOP_CRY &&
2129                 AOP_TYPE(left) == AOP_CRY ) { 
2130                 
2131                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2132                 pic14_emitcode("cpl","c"); 
2133                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2134                 goto release; 
2135         } 
2136         
2137         size = AOP_SIZE(result);
2138         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2139         while (size--) {
2140                 
2141                 if(AOP_TYPE(left) == AOP_ACC) 
2142                         emitpcode(POC_XORLW, popGetLit(0xff));
2143                 else
2144                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2145                 
2146                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2147                 offset++;
2148         }
2149         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2150         
2151         
2152 release:
2153         /* release the aops */
2154         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2155         freeAsmop(result,NULL,ic,TRUE);
2156 }
2157
2158 /*-----------------------------------------------------------------*/
2159 /* genUminusFloat - unary minus for floating points                        */
2160 /*-----------------------------------------------------------------*/
2161 static void genUminusFloat(operand *op,operand *result)
2162 {
2163         int size ,offset =0 ;
2164         char *l;
2165         
2166         FENTRY;
2167
2168         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2169         /* for this we just need to flip the 
2170         first it then copy the rest in place */
2171         size = AOP_SIZE(op) - 1;
2172         l = aopGet(AOP(op),3,FALSE,FALSE);
2173         
2174         MOVA(l);          
2175         
2176         pic14_emitcode("cpl","acc.7");
2177         aopPut(AOP(result),"a",3);      
2178         
2179         while(size--) {
2180                 aopPut(AOP(result),
2181                         aopGet(AOP(op),offset,FALSE,FALSE),
2182                         offset);
2183                 offset++;
2184         }                
2185 }
2186
2187 /*-----------------------------------------------------------------*/
2188 /* genUminus - unary minus code generation                                                 */
2189 /*-----------------------------------------------------------------*/
2190 static void genUminus (iCode *ic)
2191 {
2192         int size, i;
2193         sym_link *optype, *rtype;
2194         
2195         FENTRY;
2196         
2197         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2198         /* assign asmops */
2199         aopOp(IC_LEFT(ic),ic,FALSE);
2200         aopOp(IC_RESULT(ic),ic,TRUE);
2201         
2202         /* if both in bit space then special
2203         case */
2204         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2205                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2206                 
2207                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2208                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2209                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2210                 
2211                 goto release; 
2212         } 
2213         
2214         optype = operandType(IC_LEFT(ic));
2215         rtype = operandType(IC_RESULT(ic));
2216         
2217         /* if float then do float stuff */
2218         if (IS_FLOAT(optype)) {
2219                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2220                 goto release;
2221         }
2222         
2223         /* otherwise subtract from zero by taking the 2's complement */
2224         size = AOP_SIZE(IC_LEFT(ic));
2225         
2226         for(i=0; i<size; i++) {
2227                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2228                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2229                 else {
2230                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2231                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2232                 }
2233         }
2234         
2235         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2236         for(i=1; i<size; i++) {
2237                 emitSKPNZ;
2238                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2239         }
2240         
2241 release:
2242         /* release the aops */
2243         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2244         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2245 }
2246
2247 /*-----------------------------------------------------------------*/
2248 /* saveRegisters - will look for a call and save the registers     */
2249 /*-----------------------------------------------------------------*/
2250 static void saveRegisters(iCode *lic) 
2251 {
2252         int i;
2253         iCode *ic;
2254         bitVect *rsave;
2255         sym_link *dtype;
2256         
2257         FENTRY;
2258
2259         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2260         /* look for call */
2261         for (ic = lic ; ic ; ic = ic->next) 
2262                 if (ic->op == CALL || ic->op == PCALL)
2263                         break;
2264                 
2265                 if (!ic) {
2266                         fprintf(stderr,"found parameter push with no function call\n");
2267                         return ;
2268                 }
2269                 
2270                 /* if the registers have been saved already then
2271                 do nothing */
2272                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2273                         return ;
2274                 
2275                         /* find the registers in use at this time 
2276                 and push them away to safety */
2277                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2278                         ic->rUsed);
2279                 
2280                 ic->regsSaved = 1;
2281                 if (options.useXstack) {
2282                         if (bitVectBitValue(rsave,R0_IDX))
2283                                 pic14_emitcode("mov","b,r0");
2284                         pic14_emitcode("mov","r0,%s",spname);
2285                         for (i = 0 ; i < pic14_nRegs ; i++) {
2286                                 if (bitVectBitValue(rsave,i)) {
2287                                         if (i == R0_IDX)
2288                                                 pic14_emitcode("mov","a,b");
2289                                         else
2290                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2291                                         pic14_emitcode("movx","@r0,a");
2292                                         pic14_emitcode("inc","r0");
2293                                 }
2294                         }
2295                         pic14_emitcode("mov","%s,r0",spname);
2296                         if (bitVectBitValue(rsave,R0_IDX))
2297                                 pic14_emitcode("mov","r0,b");     
2298                 }// else
2299                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2300                 //        if (bitVectBitValue(rsave,i))
2301                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2302                 //}
2303                 
2304                 dtype = operandType(IC_LEFT(ic));
2305                 if (currFunc && dtype && 
2306                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2307                         IFFUNC_ISISR(currFunc->type) &&
2308                         !ic->bankSaved) 
2309                         
2310                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2311                 
2312 }
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRegisters - pop the pushed registers                                      */
2315 /*-----------------------------------------------------------------*/
2316 static void unsaveRegisters (iCode *ic)
2317 {
2318         int i;
2319         bitVect *rsave;
2320         
2321         FENTRY;
2322
2323         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2324         /* find the registers in use at this time 
2325         and push them away to safety */
2326         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2327                 ic->rUsed);
2328         
2329         if (options.useXstack) {
2330                 pic14_emitcode("mov","r0,%s",spname); 
2331                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2332                         if (bitVectBitValue(rsave,i)) {
2333                                 pic14_emitcode("dec","r0");
2334                                 pic14_emitcode("movx","a,@r0");
2335                                 if (i == R0_IDX)
2336                                         pic14_emitcode("mov","b,a");
2337                                 else
2338                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2339                         }       
2340                         
2341                 }
2342                 pic14_emitcode("mov","%s,r0",spname);
2343                 if (bitVectBitValue(rsave,R0_IDX))
2344                         pic14_emitcode("mov","r0,b");
2345         } //else
2346         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2347         //      if (bitVectBitValue(rsave,i))
2348         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2349         //}
2350         
2351 }  
2352
2353
2354 /*-----------------------------------------------------------------*/
2355 /* pushSide -                            */
2356 /*-----------------------------------------------------------------*/
2357 static void pushSide(operand * oper, int size)
2358 {
2359 #if 0
2360         int offset = 0;
2361         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2362         while (size--) {
2363                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2364                 if (AOP_TYPE(oper) != AOP_REG &&
2365                         AOP_TYPE(oper) != AOP_DIR &&
2366                         strcmp(l,"a") ) {
2367                         pic14_emitcode("mov","a,%s",l);
2368                         pic14_emitcode("push","acc");
2369                 } else
2370                         pic14_emitcode("push","%s",l);
2371         }
2372 #endif
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* assignResultValue -                           */
2377 /*-----------------------------------------------------------------*/
2378 static void assignResultValue(operand * oper)
2379 {
2380         int size = AOP_SIZE(oper);
2381         int offset = 0;
2382         
2383         FENTRY;
2384
2385         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2386         
2387         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2388         
2389         /* assign MSB first (passed via WREG) */
2390         while (size--) {
2391                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2392                 GpsuedoStkPtr++;
2393         }
2394 }
2395
2396
2397 /*-----------------------------------------------------------------*/
2398 /* genIpush - genrate code for pushing this gets a little complex  */
2399 /*-----------------------------------------------------------------*/
2400 static void genIpush (iCode *ic)
2401 {
2402         FENTRY;
2403         
2404         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2405 #if 0
2406         int size, offset = 0 ;
2407         char *l;
2408         
2409         
2410         /* if this is not a parm push : ie. it is spill push 
2411         and spill push is always done on the local stack */
2412         if (!ic->parmPush) {
2413                 
2414                 /* and the item is spilt then do nothing */
2415                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2416                         return ;
2417                 
2418                 aopOp(IC_LEFT(ic),ic,FALSE);
2419                 size = AOP_SIZE(IC_LEFT(ic));
2420                 /* push it on the stack */
2421                 while(size--) {
2422                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2423                         if (*l == '#') {
2424                                 MOVA(l);
2425                                 l = "acc";
2426                         }
2427                         pic14_emitcode("push","%s",l);
2428                 }
2429                 return ;                
2430         }
2431         
2432         /* this is a paramter push: in this case we call
2433         the routine to find the call and save those
2434         registers that need to be saved */   
2435         saveRegisters(ic);
2436         
2437         /* then do the push */
2438         aopOp(IC_LEFT(ic),ic,FALSE);
2439         
2440         
2441         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2442         size = AOP_SIZE(IC_LEFT(ic));
2443         
2444         while (size--) {
2445                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2446                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2447                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2448                         strcmp(l,"a") ) {
2449                         pic14_emitcode("mov","a,%s",l);
2450                         pic14_emitcode("push","acc");
2451                 } else
2452                         pic14_emitcode("push","%s",l);
2453         }         
2454         
2455         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2456 #endif
2457 }
2458
2459 /*-----------------------------------------------------------------*/
2460 /* genIpop - recover the registers: can happen only for spilling   */
2461 /*-----------------------------------------------------------------*/
2462 static void genIpop (iCode *ic)
2463 {
2464         FENTRY;
2465
2466         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2467         assert (!"genIpop -- unimplemented");
2468 #if 0
2469         int size,offset ;
2470         
2471         
2472         /* if the temp was not pushed then */
2473         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2474                 return ;
2475         
2476         aopOp(IC_LEFT(ic),ic,FALSE);
2477         size = AOP_SIZE(IC_LEFT(ic));
2478         offset = (size-1);
2479         while (size--) 
2480                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2481                 FALSE,TRUE));
2482         
2483         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2484 #endif
2485 }
2486
2487 /*-----------------------------------------------------------------*/
2488 /* unsaverbank - restores the resgister bank from stack                    */
2489 /*-----------------------------------------------------------------*/
2490 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2491 {
2492         FENTRY;
2493
2494         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2495 #if 0
2496         int i;
2497         asmop *aop ;
2498         regs *r = NULL;
2499         
2500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2501         if (popPsw) {
2502                 if (options.useXstack) {
2503                         aop = newAsmop(0);
2504                         r = getFreePtr(ic,&aop,FALSE);
2505                         
2506                         
2507                         pic14_emitcode("mov","%s,_spx",r->name);
2508                         pic14_emitcode("movx","a,@%s",r->name);
2509                         pic14_emitcode("mov","psw,a");
2510                         pic14_emitcode("dec","%s",r->name);
2511                         
2512                 }else
2513                         pic14_emitcode ("pop","psw");
2514         }
2515         
2516         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2517                 if (options.useXstack) {           
2518                         pic14_emitcode("movx","a,@%s",r->name);
2519                         //pic14_emitcode("mov","(%s+%d),a",
2520                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2521                         pic14_emitcode("dec","%s",r->name);
2522                         
2523                 } else 
2524                         pic14_emitcode("pop",""); //"(%s+%d)",
2525                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2526         }
2527         
2528         if (options.useXstack) {
2529                 
2530                 pic14_emitcode("mov","_spx,%s",r->name);
2531                 freeAsmop(NULL,aop,ic,TRUE);
2532                 
2533         }
2534 #endif 
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* saverbank - saves an entire register bank on the stack                  */
2539 /*-----------------------------------------------------------------*/
2540 static void saverbank (int bank, iCode *ic, bool pushPsw)
2541 {
2542         FENTRY;
2543
2544         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2545 #if 0
2546         int i;
2547         asmop *aop ;
2548         regs *r = NULL;
2549         
2550         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2551         if (options.useXstack) {
2552                 
2553                 aop = newAsmop(0);
2554                 r = getFreePtr(ic,&aop,FALSE);  
2555                 pic14_emitcode("mov","%s,_spx",r->name);
2556                 
2557         }
2558         
2559         for (i = 0 ; i < pic14_nRegs ;i++) {
2560                 if (options.useXstack) {
2561                         pic14_emitcode("inc","%s",r->name);
2562                         //pic14_emitcode("mov","a,(%s+%d)",
2563                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2564                         pic14_emitcode("movx","@%s,a",r->name);                 
2565                 } else 
2566                         pic14_emitcode("push","");// "(%s+%d)",
2567                 //regspic14[i].base,8*bank+regspic14[i].offset);
2568         }
2569         
2570         if (pushPsw) {
2571                 if (options.useXstack) {
2572                         pic14_emitcode("mov","a,psw");
2573                         pic14_emitcode("movx","@%s,a",r->name); 
2574                         pic14_emitcode("inc","%s",r->name);
2575                         pic14_emitcode("mov","_spx,%s",r->name);                 
2576                         freeAsmop (NULL,aop,ic,TRUE);
2577                         
2578                 } else
2579                         pic14_emitcode("push","psw");
2580                 
2581                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2582         }
2583         ic->bankSaved = 1;
2584 #endif
2585 }
2586
2587 /*-----------------------------------------------------------------*/
2588 /* genCall - generates a call statement                                                    */
2589 /*-----------------------------------------------------------------*/
2590 static void genCall (iCode *ic)
2591 {
2592         sym_link *dtype;         
2593         symbol *sym;
2594         unsigned char *name;
2595         int isExtern;
2596         
2597         FENTRY;
2598
2599         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2600         
2601         /* if caller saves & we have not saved then */
2602         if (!ic->regsSaved)
2603                 saveRegisters(ic);
2604         
2605                 /* if we are calling a function that is not using
2606                 the same register bank then we need to save the
2607         destination registers on the stack */
2608         dtype = operandType(IC_LEFT(ic));
2609         if (currFunc && dtype && 
2610                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2611                 IFFUNC_ISISR(currFunc->type) &&
2612                 !ic->bankSaved) 
2613                 
2614                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2615         
2616         /* if send set is not empty the assign */
2617         if (_G.sendSet) {
2618                 iCode *sic;
2619                 /* For the Pic port, there is no data stack.
2620                 * So parameters passed to functions are stored
2621                 * in registers. (The pCode optimizer will get
2622                 * rid of most of these :).
2623                 */
2624                 int psuedoStkPtr=-1;
2625                 int firstTimeThruLoop = 1;
2626                 
2627                 _G.sendSet = reverseSet(_G.sendSet);
2628                 
2629                 /* First figure how many parameters are getting passed */
2630                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2631                 sic = setNextItem(_G.sendSet)) {
2632                         
2633                         aopOp(IC_LEFT(sic),sic,FALSE);
2634                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2635                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2636                 }
2637                 
2638                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2639                 sic = setNextItem(_G.sendSet)) {
2640                         int size, offset = 0;
2641                         
2642                         aopOp(IC_LEFT(sic),sic,FALSE);
2643                         size = AOP_SIZE(IC_LEFT(sic));
2644                         
2645                         while (size--) {
2646                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2647                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2648                                 
2649                                 if(!firstTimeThruLoop) {
2650                                         /* If this is not the first time we've been through the loop
2651                                         * then we need to save the parameter in a temporary
2652                                         * register. The last byte of the last parameter is
2653                                         * passed in W. */
2654                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2655                                         
2656                                 }
2657                                 firstTimeThruLoop=0;
2658                                 
2659                                 mov2w_op (IC_LEFT(sic),  offset);
2660                                 offset++;
2661                         }
2662                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2663                 }
2664                 _G.sendSet = NULL;
2665         }
2666         /* make the call */
2667         sym = OP_SYMBOL(IC_LEFT(ic));
2668         name = sym->rname[0] ? sym->rname : sym->name;
2669         isExtern = IS_EXTERN(sym->etype);
2670         if (isExtern) {
2671                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2672         }
2673         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2674         if (isExtern) {
2675                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2676         }
2677         GpsuedoStkPtr=0;
2678         /* if we need assign a result value */
2679         if ((IS_ITEMP(IC_RESULT(ic)) && 
2680                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2681                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2682                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2683                 
2684                 _G.accInUse++;
2685                 aopOp(IC_RESULT(ic),ic,FALSE);
2686                 _G.accInUse--;
2687                 
2688                 assignResultValue(IC_RESULT(ic));
2689                 
2690                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2691                         AopType(AOP_TYPE(IC_RESULT(ic))));
2692                 
2693                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2694         }
2695         
2696         /* if register bank was saved then pop them */
2697         if (ic->bankSaved)
2698                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2699         
2700         /* if we hade saved some registers then unsave them */
2701         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2702                 unsaveRegisters (ic);
2703         
2704         
2705 }
2706
2707 /*-----------------------------------------------------------------*/
2708 /* genPcall - generates a call by pointer statement                        */
2709 /*-----------------------------------------------------------------*/
2710 static void genPcall (iCode *ic)
2711 {
2712         sym_link *dtype;
2713         symbol *albl = newiTempLabel(NULL);
2714         symbol *blbl = newiTempLabel(NULL);
2715         PIC_OPCODE poc;
2716         pCodeOp *pcop;
2717         operand *left;
2718         
2719         FENTRY;
2720
2721         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2722         /* if caller saves & we have not saved then */
2723         if (!ic->regsSaved)
2724                 saveRegisters(ic);
2725         
2726                 /* if we are calling a function that is not using
2727                 the same register bank then we need to save the
2728         destination registers on the stack */
2729         dtype = operandType(IC_LEFT(ic));
2730         if (currFunc && dtype && 
2731                 IFFUNC_ISISR(currFunc->type) &&
2732                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2733                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2734         
2735         left = IC_LEFT(ic);
2736         aopOp(left,ic,FALSE);
2737         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2738         
2739         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2740         
2741         pushSide(IC_LEFT(ic), FPTRSIZE);
2742         
2743         /* if send set is not empty, assign parameters */
2744         if (_G.sendSet) {
2745                 
2746                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2747                 /* no way to pass args - W always gets used to make the call */
2748         }
2749         /* first idea - factor out a common helper function and call it.
2750         But don't know how to get it generated only once in its own block
2751         
2752         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2753                 char *rname;
2754                 char *buffer;
2755                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2756                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2757                 buffer = Safe_calloc(1,strlen(rname)+16);
2758                 sprintf(buffer, "%s_goto_helper", rname);
2759                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2760                 free(buffer);
2761         }
2762         */
2763         emitpcode(POC_CALL,popGetLabel(albl->key));
2764         pcop = popGetLabel(blbl->key);
2765         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2766         emitpcode(POC_GOTO,pcop);
2767         emitpLabel(albl->key);
2768         
2769         emitpcode(poc,popGetAddr(AOP(left),1,0));
2770         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2771         emitpcode(poc,popGetAddr(AOP(left),0,0));
2772         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2773         
2774         emitpLabel(blbl->key);
2775         
2776         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2777         
2778         /* if we need to assign a result value */
2779         if ((IS_ITEMP(IC_RESULT(ic)) &&
2780                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2781                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2782                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2783                 
2784                 _G.accInUse++;
2785                 aopOp(IC_RESULT(ic),ic,FALSE);
2786                 _G.accInUse--;
2787
2788                 GpsuedoStkPtr = 0;
2789                 
2790                 assignResultValue(IC_RESULT(ic));
2791                 
2792                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2793         }
2794         
2795         /* if register bank was saved then unsave them */
2796         if (currFunc && dtype && 
2797                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2798                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2799         
2800                 /* if we hade saved some registers then
2801         unsave them */
2802         if (ic->regsSaved)
2803                 unsaveRegisters (ic);
2804         
2805 }
2806
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result  is rematerializable                                       */
2809 /*-----------------------------------------------------------------*/
2810 static int resultRemat (iCode *ic)
2811 {
2812         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2813         FENTRY;
2814
2815         if (SKIP_IC(ic) || ic->op == IFX)
2816                 return 0;
2817         
2818         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2819                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2820                 if (sym->remat && !POINTER_SET(ic)) 
2821                         return 1;
2822         }
2823         
2824         return 0;
2825 }
2826
2827 #if defined(__BORLANDC__) || defined(_MSC_VER)
2828 #define STRCASECMP stricmp
2829 #else
2830 #define STRCASECMP strcasecmp
2831 #endif
2832
2833 #if 0
2834 /*-----------------------------------------------------------------*/
2835 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2836 /*-----------------------------------------------------------------*/
2837 static bool inExcludeList(char *s)
2838 {
2839         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2840         int i =0;
2841         
2842         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2843         if (options.excludeRegs[i] &&
2844                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2845                 return FALSE ;
2846         
2847         for ( i = 0 ; options.excludeRegs[i]; i++) {
2848                 if (options.excludeRegs[i] &&
2849                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2850                         return TRUE;
2851         }
2852         return FALSE ;
2853 }
2854 #endif
2855
2856 /*-----------------------------------------------------------------*/
2857 /* genFunction - generated code for function entry                                 */
2858 /*-----------------------------------------------------------------*/
2859 static void genFunction (iCode *ic)
2860 {
2861         symbol *sym;
2862         sym_link *ftype;
2863         
2864         FENTRY;
2865
2866         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2867         
2868         labelOffset += (max_key+4);
2869         max_key=0;
2870         GpsuedoStkPtr=0;
2871         _G.nRegsSaved = 0;
2872         /* create the function header */
2873         pic14_emitcode(";","-----------------------------------------");
2874         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2875         pic14_emitcode(";","-----------------------------------------");
2876         
2877         pic14_emitcode("","%s:",sym->rname);
2878         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2879         
2880         ftype = operandType(IC_LEFT(ic));
2881         
2882         /* if critical function then turn interrupts off */
2883         if (IFFUNC_ISCRITICAL(ftype))
2884                 pic14_emitcode("clr","ea");
2885         
2886                 /* here we need to generate the equates for the
2887         register bank if required */
2888 #if 0
2889         if (FUNC_REGBANK(ftype) != rbank) {
2890                 int i ;
2891                 
2892                 rbank = FUNC_REGBANK(ftype);
2893                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2894                         if (strcmp(regspic14[i].base,"0") == 0)
2895                                 pic14_emitcode("","%s = 0x%02x",
2896                                 regspic14[i].dname,
2897                                 8*rbank+regspic14[i].offset);
2898                         else
2899                                 pic14_emitcode ("","%s = %s + 0x%02x",
2900                                 regspic14[i].dname,
2901                                 regspic14[i].base,
2902                                 8*rbank+regspic14[i].offset);
2903                 }
2904         }
2905 #endif
2906         
2907         /* if this is an interrupt service routine */
2908         if (IFFUNC_ISISR(sym->type)) {
2909         /*  already done in pic14createInterruptVect() - delete me
2910         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2911         emitpcodeNULLop(POC_NOP);
2912         emitpcodeNULLop(POC_NOP);
2913         emitpcodeNULLop(POC_NOP);
2914                 */
2915                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2916                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2917                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2918                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2919                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2920                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2921                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2922                 
2923                 pBlockConvert2ISR(pb);
2924 #if 0  
2925                 if (!inExcludeList("acc"))              
2926                         pic14_emitcode ("push","acc");  
2927                 if (!inExcludeList("b"))
2928                         pic14_emitcode ("push","b");
2929                 if (!inExcludeList("dpl"))
2930                         pic14_emitcode ("push","dpl");
2931                 if (!inExcludeList("dph"))
2932                         pic14_emitcode ("push","dph");
2933                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2934                 {
2935                         pic14_emitcode ("push", "dpx");
2936                         /* Make sure we're using standard DPTR */
2937                         pic14_emitcode ("push", "dps");
2938                         pic14_emitcode ("mov", "dps, #0x00");
2939                         if (options.stack10bit)
2940                         { 
2941                                 /* This ISR could conceivably use DPTR2. Better save it. */
2942                                 pic14_emitcode ("push", "dpl1");
2943                                 pic14_emitcode ("push", "dph1");
2944                                 pic14_emitcode ("push", "dpx1");
2945                         }
2946                 }
2947                 /* if this isr has no bank i.e. is going to
2948                 run with bank 0 , then we need to save more
2949                 registers :-) */
2950                 if (!FUNC_REGBANK(sym->type)) {
2951                         
2952                 /* if this function does not call any other
2953                 function then we can be economical and
2954                         save only those registers that are used */
2955                         if (! IFFUNC_HASFCALL(sym->type)) {
2956                                 int i;
2957                                 
2958                                 /* if any registers used */
2959                                 if (sym->regsUsed) {
2960                                         /* save the registers used */
2961                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2962                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2963                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2964                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2965                                         }
2966                                 }
2967                                 
2968                         } else {
2969                         /* this function has    a function call cannot
2970                         determines register usage so we will have the
2971                                 entire bank */
2972                                 saverbank(0,ic,FALSE);
2973                         }       
2974                 }
2975 #endif
2976         } else {
2977         /* if callee-save to be used for this function
2978                 then save the registers being used in this function */
2979                 if (IFFUNC_CALLEESAVES(sym->type)) {
2980                         int i;
2981                         
2982                         /* if any registers used */
2983                         if (sym->regsUsed) {
2984                                 /* save the registers used */
2985                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2986                                         if (bitVectBitValue(sym->regsUsed,i) ||
2987                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2988                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2989                                                 _G.nRegsSaved++;
2990                                         }
2991                                 }
2992                         }
2993                 }
2994         }
2995         
2996         /* set the register bank to the desired value */
2997         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2998                 pic14_emitcode("push","psw");
2999                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3000         }
3001         
3002         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3003                 
3004                 if (options.useXstack) {
3005                         pic14_emitcode("mov","r0,%s",spname);
3006                         pic14_emitcode("mov","a,_bp");
3007                         pic14_emitcode("movx","@r0,a");
3008                         pic14_emitcode("inc","%s",spname);
3009                 }
3010                 else
3011                 {
3012                         /* set up the stack */
3013                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3014                 }
3015                 pic14_emitcode ("mov","_bp,%s",spname);
3016         }
3017         
3018         /* adjust the stack for the function */
3019         if (sym->stack) {
3020                 
3021                 int i = sym->stack;
3022                 if (i > 256 ) 
3023                         werror(W_STACK_OVERFLOW,sym->name);
3024                 
3025                 if (i > 3 && sym->recvSize < 4) {                
3026                         
3027                         pic14_emitcode ("mov","a,sp");
3028                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3029                         pic14_emitcode ("mov","sp,a");
3030                         
3031                 }
3032                 else
3033                         while(i--)
3034                                 pic14_emitcode("inc","sp");
3035         }
3036         
3037         if (sym->xstack) {
3038                 
3039                 pic14_emitcode ("mov","a,_spx");
3040                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3041                 pic14_emitcode ("mov","_spx,a");
3042         }
3043         
3044 }
3045
3046 /*-----------------------------------------------------------------*/
3047 /* genEndFunction - generates epilogue for functions                       */
3048 /*-----------------------------------------------------------------*/
3049 static void genEndFunction (iCode *ic)
3050 {
3051         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3052         
3053         FENTRY;
3054
3055         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3056         
3057         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3058         {
3059                 pic14_emitcode ("mov","%s,_bp",spname);
3060         }
3061         
3062         /* if use external stack but some variables were
3063         added to the local stack then decrement the
3064         local stack */
3065         if (options.useXstack && sym->stack) {    
3066                 pic14_emitcode("mov","a,sp");
3067                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3068                 pic14_emitcode("mov","sp,a");
3069         }
3070         
3071         
3072         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3073                 if (options.useXstack) {
3074                         pic14_emitcode("mov","r0,%s",spname);
3075                         pic14_emitcode("movx","a,@r0");
3076                         pic14_emitcode("mov","_bp,a");
3077                         pic14_emitcode("dec","%s",spname);
3078                 }
3079                 else
3080                 {
3081                         pic14_emitcode ("pop","_bp");
3082                 }
3083         }
3084         
3085         /* restore the register bank    */        
3086         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3087                 pic14_emitcode ("pop","psw");
3088         
3089         if (IFFUNC_ISISR(sym->type)) {
3090                 
3091                 /* now we need to restore the registers */
3092                 /* if this isr has no bank i.e. is going to
3093                 run with bank 0 , then we need to save more
3094 registers :-) */
3095                 if (!FUNC_REGBANK(sym->type)) {
3096                         
3097                 /* if this function does not call any other
3098                 function then we can be economical and
3099                         save only those registers that are used */
3100                         if (! IFFUNC_HASFCALL(sym->type)) {
3101                                 int i;
3102                                 
3103                                 /* if any registers used */
3104                                 if (sym->regsUsed) {
3105                                         /* save the registers used */
3106                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3107                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3108                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3109                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3110                                         }
3111                                 }
3112                                 
3113                         } else {
3114                         /* this function has    a function call cannot
3115                         determines register usage so we will have the
3116                                 entire bank */
3117                                 unsaverbank(0,ic,FALSE);
3118                         }       
3119                 }
3120 #if 0
3121                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3122                 {
3123                         if (options.stack10bit)
3124                         {
3125                                 pic14_emitcode ("pop", "dpx1");
3126                                 pic14_emitcode ("pop", "dph1");
3127                                 pic14_emitcode ("pop", "dpl1");
3128                         } 
3129                         pic14_emitcode ("pop", "dps");
3130                         pic14_emitcode ("pop", "dpx");
3131                 }
3132                 if (!inExcludeList("dph"))
3133                         pic14_emitcode ("pop","dph");
3134                 if (!inExcludeList("dpl"))
3135                         pic14_emitcode ("pop","dpl");
3136                 if (!inExcludeList("b"))
3137                         pic14_emitcode ("pop","b");
3138                 if (!inExcludeList("acc"))
3139                         pic14_emitcode ("pop","acc");
3140                 
3141                 if (IFFUNC_ISCRITICAL(sym->type))
3142                         pic14_emitcode("setb","ea");
3143 #endif
3144                 
3145                 /* if debug then send end of function */
3146                 /*      if (options.debug && currFunc) { */
3147                 if (currFunc) {
3148                         debugFile->writeEndFunction (currFunc, ic, 1);
3149                 }
3150                 
3151                 pic14_emitcode ("reti","");
3152                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3153                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3154                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3155                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3156                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3157                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3158                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3159                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3160                 emitpcodeNULLop(POC_RETFIE);
3161         }
3162         else {
3163                 if (IFFUNC_ISCRITICAL(sym->type))
3164                         pic14_emitcode("setb","ea");
3165                 
3166                 if (IFFUNC_CALLEESAVES(sym->type)) {
3167                         int i;
3168                         
3169                         /* if any registers used */
3170                         if (sym->regsUsed) {
3171                                 /* save the registers used */
3172                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3173                                         if (bitVectBitValue(sym->regsUsed,i) ||
3174                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3175                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3176                                 }
3177                         }
3178                         
3179                 }
3180                 
3181                 /* if debug then send end of function */
3182                 if (currFunc) {
3183                         debugFile->writeEndFunction (currFunc, ic, 1);
3184                 }
3185                 
3186                 pic14_emitcode ("return","");
3187                 emitpcodeNULLop(POC_RETURN);
3188                 
3189                 /* Mark the end of a function */
3190                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3191         }
3192         
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement                                     */
3197 /*-----------------------------------------------------------------*/
3198 static void genRet (iCode *ic)
3199 {
3200         int size,offset = 0;
3201         
3202         FENTRY;
3203
3204         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3205         /* if we have no return value then
3206         just generate the "ret" */
3207         if (!IC_LEFT(ic)) 
3208                 goto jumpret;           
3209         
3210                 /* we have something to return then
3211         move the return value into place */
3212         aopOp(IC_LEFT(ic),ic,FALSE);
3213         size = AOP_SIZE(IC_LEFT(ic));
3214
3215         for (offset = 0; offset < size; offset++)
3216         {
3217                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3218         }
3219         
3220         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3221         
3222 jumpret:
3223         /* generate a jump to the return label
3224         if the next is not the return statement */
3225         if (!(ic->next && ic->next->op == LABEL &&
3226                 IC_LABEL(ic->next) == returnLabel)) {
3227                 
3228                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3229         }
3230         
3231 }
3232
3233 /*-----------------------------------------------------------------*/
3234 /* genLabel - generates a label                                                                    */
3235 /*-----------------------------------------------------------------*/
3236 static void genLabel (iCode *ic)
3237 {
3238         FENTRY;
3239
3240         /* special case never generate */
3241         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3242         if (IC_LABEL(ic) == entryLabel)
3243                 return ;
3244         
3245         emitpLabel(IC_LABEL(ic)->key);
3246         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3247 }
3248
3249 /*-----------------------------------------------------------------*/
3250 /* genGoto - generates a goto                                                                      */
3251 /*-----------------------------------------------------------------*/
3252 //tsd
3253 static void genGoto (iCode *ic)
3254 {
3255         FENTRY;
3256
3257         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3258         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3259 }
3260
3261
3262 /*-----------------------------------------------------------------*/
3263 /* genMultbits :- multiplication of bits                                                   */
3264 /*-----------------------------------------------------------------*/
3265 static void genMultbits (operand *left, 
3266                                                  operand *right, 
3267                                                  operand *result)
3268 {
3269         FENTRY;
3270         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3271         
3272         if(!pic14_sameRegs(AOP(result),AOP(right)))
3273                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3274         
3275         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3276         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3277         emitpcode(POC_BCF,  popGet(AOP(result),0));
3278         
3279 }
3280
3281
3282 /*-----------------------------------------------------------------*/
3283 /* genMultOneByte : 8 bit multiplication & division                        */
3284 /*-----------------------------------------------------------------*/
3285 static void genMultOneByte (operand *left,
3286                                                         operand *right,
3287                                                         operand *result)
3288 {
3289         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3290         
3291         // symbol *lbl ;
3292         int size,offset,i;
3293         
3294         
3295         FENTRY;
3296         
3297         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3298         DEBUGpic14_AopType(__LINE__,left,right,result);
3299         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3300         
3301         /* (if two literals, the value is computed before) */
3302         /* if one literal, literal on the right */
3303         if (AOP_TYPE(left) == AOP_LIT){
3304                 operand *t = right;
3305                 right = left;
3306                 left = t;
3307         }
3308
3309         assert (AOP_SIZE(left) == AOP_SIZE(right));
3310         
3311         size = min(AOP_SIZE(result),AOP_SIZE(left));
3312         offset = Gstack_base_addr - (2*size - 1);
3313
3314         /* pass right operand as argument */
3315         for (i=0; i < size; i++)
3316         {
3317                 mov2w (AOP(right), i);
3318                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3319         } // for
3320         
3321         /* pass left operand as argument */
3322         for (i=0; i < size; i++)
3323         {
3324                 mov2w (AOP(left), i);
3325                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3326         } // for
3327         assert (offset == Gstack_base_addr);
3328         
3329         /* call library routine */
3330         assert (size > 0 && size <= 4);
3331         call_libraryfunc (func[size]);
3332         
3333         /* assign result */
3334         movwf (AOP(result), size-1);
3335         for (i=0; i < size - 1; i++)
3336         {
3337                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3338                 movwf (AOP(result), size - 2 - i);
3339         } // for
3340
3341         /* now (zero-/sign) extend the result to its size */
3342         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3343 }
3344
3345 /*-----------------------------------------------------------------*/
3346 /* genMult - generates code for multiplication                                     */
3347 /*-----------------------------------------------------------------*/
3348 static void genMult (iCode *ic)
3349 {
3350         operand *left = IC_LEFT(ic);
3351         operand *right = IC_RIGHT(ic);
3352         operand *result= IC_RESULT(ic); 
3353         
3354         FENTRY;
3355
3356         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3357         /* assign the amsops */
3358         aopOp (left,ic,FALSE);
3359         aopOp (right,ic,FALSE);
3360         aopOp (result,ic,TRUE);
3361         
3362         DEBUGpic14_AopType(__LINE__,left,right,result);
3363         
3364         /* special cases first */
3365         /* both are bits */
3366         if (AOP_TYPE(left) == AOP_CRY &&
3367                 AOP_TYPE(right)== AOP_CRY) {
3368                 genMultbits(left,right,result);
3369                 goto release ;
3370         }
3371         
3372         /* if both are of size == 1 */
3373         if (AOP_SIZE(left) == 1 &&
3374                 AOP_SIZE(right) == 1 ) {
3375                 genMultOneByte(left,right,result);
3376                 goto release ;
3377         }
3378         
3379         /* should have been converted to function call */
3380         assert(0) ;
3381         
3382 release :
3383         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3384         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3385         freeAsmop(result,NULL,ic,TRUE); 
3386 }
3387
3388 /*-----------------------------------------------------------------*/
3389 /* genDivbits :- division of bits                                                                  */
3390 /*-----------------------------------------------------------------*/
3391 static void genDivbits (operand *left, 
3392                                                 operand *right, 
3393                                                 operand *result)
3394 {
3395         
3396         char *l;
3397         
3398         FENTRY;
3399
3400         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3401         /* the result must be bit */      
3402         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3403         l = aopGet(AOP(left),0,FALSE,FALSE);
3404         
3405         MOVA(l);          
3406         
3407         pic14_emitcode("div","ab");
3408         pic14_emitcode("rrc","a");
3409         aopPut(AOP(result),"c",0);
3410 }
3411
3412 /*-----------------------------------------------------------------*/
3413 /* genDivOneByte : 8 bit division                                                                  */
3414 /*-----------------------------------------------------------------*/
3415 static void genDivOneByte (operand *left,
3416                                                    operand *right,
3417                                                    operand *result)
3418 {
3419         int size;
3420         
3421         FENTRY;
3422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3423         
3424         assert (AOP_SIZE(result) == 1);
3425         assert (AOP_SIZE(right) == 1);
3426         assert (AOP_SIZE(left) == 1);
3427
3428         size = min(AOP_SIZE(result),AOP_SIZE(left));
3429
3430         if (AOP_TYPE(right) == AOP_LIT)
3431         {
3432                 /* XXX: might add specialized code */
3433         }
3434
3435         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3436         {
3437                 /* unsigned division */
3438         #if 1
3439                 mov2w(AOP(right),0);
3440                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3441                 mov2w(AOP(left),0);
3442                 call_libraryfunc("__divuchar");
3443                 movwf(AOP(result),0);
3444         #else
3445                 pCodeOp *temp;
3446                 symbol *lbl;
3447
3448                 temp = popGetTempReg();
3449                 lbl = newiTempLabel(NULL);
3450                 
3451                 /* XXX: improve this naive approach:
3452                    [result] = [a] / [b]
3453                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3454
3455                    In PIC assembler:
3456                    movf  left,W
3457                    movwf temp           // temp <-- left
3458                    movf  right,W        // W <-- right
3459                    clrf  result
3460                    label1:
3461                    incf  result
3462                    subwf temp,F         // temp <-- temp - W
3463                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3464                    goto  label1
3465                    decf result          // we just subtract once too often
3466                  */
3467
3468                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3469                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3470                 
3471                 mov2w(AOP(left),0);
3472                 emitpcode(POC_MOVWF, temp);
3473                 mov2w(AOP(right),0);
3474                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3475
3476                 emitpLabel(lbl->key);
3477                 emitpcode(POC_INCF, popGet(AOP(result),0));
3478                 emitpcode(POC_SUBWF, temp);
3479                 emitSKPNC;
3480                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3481                 emitpcode(POC_DECF, popGet(AOP(result),0));
3482         #endif
3483         }
3484         else
3485         {
3486                 /* signed division */
3487                 mov2w(AOP(right),0);
3488                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3489                 mov2w(AOP(left),0);
3490                 call_libraryfunc("__divschar");
3491                 movwf(AOP(result),0);
3492         }
3493
3494         /* now performed the signed/unsigned division -- extend result */
3495         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3496 }
3497
3498 /*-----------------------------------------------------------------*/
3499 /* genDiv - generates code for division                            */
3500 /*-----------------------------------------------------------------*/
3501 static void genDiv (iCode *ic)
3502 {
3503         operand *left = IC_LEFT(ic);
3504         operand *right = IC_RIGHT(ic);
3505         operand *result= IC_RESULT(ic); 
3506         
3507         FENTRY;
3508         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3509         /* assign the amsops */
3510         aopOp (left,ic,FALSE);
3511         aopOp (right,ic,FALSE);
3512         aopOp (result,ic,TRUE);
3513         
3514         /* special cases first */
3515         /* both are bits */
3516         if (AOP_TYPE(left) == AOP_CRY &&
3517                 AOP_TYPE(right)== AOP_CRY) {
3518                 genDivbits(left,right,result);
3519                 goto release ;
3520         }
3521         
3522         /* if both are of size == 1 */
3523         if (AOP_SIZE(left) == 1 &&
3524                 AOP_SIZE(right) == 1 ) {
3525                 genDivOneByte(left,right,result);
3526                 goto release ;
3527         }
3528         
3529         /* should have been converted to function call */
3530         assert(0);
3531 release :
3532         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3533         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3534         freeAsmop(result,NULL,ic,TRUE); 
3535 }
3536
3537 /*-----------------------------------------------------------------*/
3538 /* genModbits :- modulus of bits                                                                   */
3539 /*-----------------------------------------------------------------*/
3540 static void genModbits (operand *left, 
3541                                                 operand *right, 
3542                                                 operand *result)
3543 {
3544         
3545         char *l;
3546         
3547         FENTRY;
3548         /* the result must be bit */      
3549         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3550         l = aopGet(AOP(left),0,FALSE,FALSE);
3551         
3552         MOVA(l);
3553         
3554         pic14_emitcode("div","ab");
3555         pic14_emitcode("mov","a,b");
3556         pic14_emitcode("rrc","a");
3557         aopPut(AOP(result),"c",0);
3558 }
3559
3560 /*-----------------------------------------------------------------*/
3561 /* genModOneByte : 8 bit modulus                                                                   */
3562 /*-----------------------------------------------------------------*/
3563 static void genModOneByte (operand *left,
3564                                                    operand *right,
3565                                                    operand *result)
3566 {
3567         int size;
3568         
3569         FENTRY;
3570         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3571         
3572         assert (AOP_SIZE(result) == 1);
3573         assert (AOP_SIZE(right) == 1);
3574         assert (AOP_SIZE(left) == 1);
3575
3576         size = min(AOP_SIZE(result),AOP_SIZE(left));
3577
3578         if (AOP_TYPE(right) == AOP_LIT)
3579         {
3580                 /* XXX: might add specialized code */
3581         }
3582
3583         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3584         {
3585                 /* unsigned division */
3586         #if 1
3587                 mov2w(AOP(right),0);
3588                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3589                 mov2w(AOP(left),0);
3590                 call_libraryfunc("__moduchar");
3591                 movwf(AOP(result),0);
3592         #else
3593                 pCodeOp *temp;
3594                 symbol *lbl;
3595
3596                 lbl = newiTempLabel(NULL);
3597                 
3598                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3599
3600                 /* XXX: improve this naive approach:
3601                    [result] = [a] % [b]
3602                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3603
3604                    In PIC assembler:
3605                    movf  left,W
3606                    movwf result         // result <-- left
3607                    movf  right,W        // W <-- right
3608                    label1:
3609                    subwf result,F       // result <-- result - W
3610                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3611                    goto  label1
3612                    addwf result, F      // we just subtract once too often
3613                  */
3614
3615                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3616                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3617                 
3618                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3619                 {
3620                         mov2w(AOP(left),0);
3621                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3622                 }
3623                 mov2w(AOP(right),0);
3624
3625                 emitpLabel(lbl->key);
3626                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3627                 emitSKPNC;
3628                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3629                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3630         #endif
3631         }
3632         else
3633         {
3634                 /* signed division */
3635                 mov2w(AOP(right),0);
3636                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3637                 mov2w(AOP(left),0);
3638                 call_libraryfunc("__modschar");
3639                 movwf(AOP(result),0);
3640         }
3641
3642         /* now we performed the signed/unsigned modulus -- extend result */
3643         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genMod - generates code for division                                                    */
3648 /*-----------------------------------------------------------------*/
3649 static void genMod (iCode *ic)
3650 {
3651         operand *left = IC_LEFT(ic);
3652         operand *right = IC_RIGHT(ic);
3653         operand *result= IC_RESULT(ic);  
3654         
3655         FENTRY;
3656         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3657         /* assign the amsops */
3658         aopOp (left,ic,FALSE);
3659         aopOp (right,ic,FALSE);
3660         aopOp (result,ic,TRUE);
3661         
3662         /* special cases first */
3663         /* both are bits */
3664         if (AOP_TYPE(left) == AOP_CRY &&
3665                 AOP_TYPE(right)== AOP_CRY) {
3666                 genModbits(left,right,result);
3667                 goto release ;
3668         }
3669         
3670         /* if both are of size == 1 */
3671         if (AOP_SIZE(left) == 1 &&
3672                 AOP_SIZE(right) == 1 ) {
3673                 genModOneByte(left,right,result);
3674                 goto release ;
3675         }
3676         
3677         /* should have been converted to function call */
3678         assert(0);
3679         
3680 release :
3681         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3682         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3683         freeAsmop(result,NULL,ic,TRUE); 
3684 }
3685
3686 /*-----------------------------------------------------------------*/
3687 /* genIfxJump :- will create a jump depending on the ifx                   */
3688 /*-----------------------------------------------------------------*/
3689 /*
3690 note: May need to add parameter to indicate when a variable is in bit space.
3691 */
3692 static void genIfxJump (iCode *ic, char *jval)
3693 {
3694         
3695         FENTRY;
3696         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3697         /* if true label then we jump if condition
3698         supplied is true */
3699         if ( IC_TRUE(ic) ) {
3700                 
3701                 if(strcmp(jval,"a") == 0)
3702                         emitSKPZ;
3703                 else if (strcmp(jval,"c") == 0)
3704                         emitSKPC;
3705                 else {
3706                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3707                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3708                 }
3709                 
3710                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3711                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3712                 
3713         }
3714         else {
3715                 /* false label is present */
3716                 if(strcmp(jval,"a") == 0)
3717                         emitSKPNZ;
3718                 else if (strcmp(jval,"c") == 0)
3719                         emitSKPNC;
3720                 else {
3721                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3722                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3723                 }
3724                 
3725                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3726                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3727                 
3728         }
3729         
3730         
3731         /* mark the icode as generated */
3732         ic->generated = 1;
3733 }
3734
3735 #if 0
3736 /*-----------------------------------------------------------------*/
3737 /* genSkip                                                                                                                 */
3738 /*-----------------------------------------------------------------*/
3739 static void genSkip(iCode *ifx,int status_bit)
3740 {
3741         FENTRY;
3742         if(!ifx)
3743                 return;
3744         
3745         if ( IC_TRUE(ifx) ) {
3746                 switch(status_bit) {
3747                 case 'z':
3748                         emitSKPNZ;
3749                         break;
3750                         
3751                 case 'c':
3752                         emitSKPNC;
3753                         break;
3754                         
3755                 case 'd':
3756                         emitSKPDC;
3757                         break;
3758                         
3759                 }
3760                 
3761                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3762                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3763                 
3764         } else {
3765                 
3766                 switch(status_bit) {
3767                         
3768                 case 'z':
3769                         emitSKPZ;
3770                         break;
3771                         
3772                 case 'c':
3773                         emitSKPC;
3774                         break;
3775                         
3776                 case 'd':
3777                         emitSKPDC;
3778                         break;
3779                 }
3780                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3781                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3782                 
3783         }
3784         
3785 }
3786 #endif
3787
3788 /*-----------------------------------------------------------------*/
3789 /* genSkipc                                                                                                        */
3790 /*-----------------------------------------------------------------*/
3791 static void genSkipc(resolvedIfx *rifx)
3792 {
3793         FENTRY;
3794         if(!rifx)
3795                 return;
3796         
3797         if(rifx->condition)
3798                 emitSKPNC;
3799         else
3800                 emitSKPC;
3801         
3802         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3803         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3804         rifx->generated = 1;
3805 }
3806
3807 #if 0
3808 /*-----------------------------------------------------------------*/
3809 /* genSkipz2                                                                                                       */
3810 /*-----------------------------------------------------------------*/
3811 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3812 {
3813         FENTRY;
3814         if(!rifx)
3815                 return;
3816         
3817         if( (rifx->condition ^ invert_condition) & 1)
3818                 emitSKPZ;
3819         else
3820                 emitSKPNZ;
3821         
3822         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3823         rifx->generated = 1;
3824 }
3825 #endif
3826
3827 #if 0
3828 /*-----------------------------------------------------------------*/
3829 /* genSkipz                                                        */
3830 /*-----------------------------------------------------------------*/
3831 static void genSkipz(iCode *ifx, int condition)
3832 {
3833         FENTRY;
3834         assert (ifx != NULL);
3835         
3836         if(condition)
3837                 emitSKPNZ;
3838         else
3839                 emitSKPZ;
3840         
3841         if ( IC_TRUE(ifx) )
3842                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3843         else
3844                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3845         
3846         if ( IC_TRUE(ifx) )
3847                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3848         else
3849                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3850         
3851 }
3852 #endif
3853
3854 #if 0
3855 /*-----------------------------------------------------------------*/
3856 /* genSkipCond                                                     */
3857 /*-----------------------------------------------------------------*/
3858 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3859 {
3860         FENTRY;
3861         if(!rifx)
3862                 return;
3863         
3864         if(rifx->condition)
3865                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3866         else
3867                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3868         
3869         
3870         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3871         rifx->generated = 1;
3872 }
3873 #endif
3874
3875 #if 0
3876 /*-----------------------------------------------------------------*/
3877 /* genChkZeroes :- greater or less than comparison                 */
3878 /*     For each byte in a literal that is zero, inclusive or the   */
3879 /*     the corresponding byte in the operand with W                */
3880 /*     returns true if any of the bytes are zero                   */
3881 /*-----------------------------------------------------------------*/
3882 static int genChkZeroes(operand *op, int lit,  int size)
3883 {
3884         
3885         int i;
3886         int flag =1;
3887         
3888         while(size--) {
3889                 i = (lit >> (size*8)) & 0xff;
3890                 
3891                 if(i==0) {
3892                         if(flag) 
3893                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3894                         else
3895                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3896                         flag = 0;
3897                 }
3898         }
3899         
3900         return (flag==0);
3901 }
3902 #endif
3903
3904
3905 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3906 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3907 #define DEBUGpc           emitpComment
3908
3909 /*-----------------------------------------------------------------*/
3910 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3911 /*                  aop (if it's NOT a literal) or from lit (if    */
3912 /*                  aop is a literal)                              */
3913 /*-----------------------------------------------------------------*/
3914 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3915   if (aop->type == AOP_LIT) {
3916     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3917   } else {
3918     emitpcode (POC_MOVFW, popGet (aop, offset));
3919   }
3920 }
3921
3922 /* genCmp performs a left < right comparison, stores
3923  * the outcome in result (if != NULL) and generates
3924  * control flow code for the ifx (if != NULL).
3925  *
3926  * This version leaves in sequences like
3927  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3928  * which should be optmized by the peephole
3929  * optimizer - RN 2005-01-01 */
3930 static void genCmp (operand *left,operand *right,
3931                     operand *result, iCode *ifx, int sign)
3932 {
3933   resolvedIfx rIfx;
3934   int size;
3935   int offs;
3936   symbol *templbl;
3937   operand *dummy;
3938   unsigned long lit;
3939   unsigned long mask;
3940   int performedLt;
3941   int invert_result = 0;
3942
3943   FENTRY;
3944   
3945   assert (AOP_SIZE(left) == AOP_SIZE(right));
3946   assert (left && right);
3947
3948   size = AOP_SIZE(right) - 1;
3949   mask = (0x100UL << (size*8)) - 1;
3950   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3951   performedLt = 1;
3952   templbl = NULL;
3953   lit = 0;
3954   
3955   resolveIfx (&rIfx, ifx);
3956
3957   /**********************************************************************
3958    * handle bits - bit compares are promoted to int compares seemingly! *
3959    **********************************************************************/
3960 #if 0
3961   // THIS IS COMPLETELY UNTESTED!
3962   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3963     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3964     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3965     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3966
3967     emitSETC;
3968     // 1 < {0,1} is false --> clear C by skipping the next instruction
3969     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3970     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3971     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3972     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3973     emitCLRC; // only skipped for left=0 && right=1
3974
3975     goto correct_result_in_carry;
3976   } // if
3977 #endif
3978
3979   /*************************************************
3980    * make sure that left is register (or the like) *
3981    *************************************************/
3982   if (!isAOP_REGlike(left)) {
3983     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3984     assert (isAOP_LIT(left));
3985     assert (isAOP_REGlike(right));
3986     // swap left and right
3987     // left < right <==> right > left <==> (right >= left + 1)
3988     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3989
3990     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3991       // MAXVALUE < right? always false
3992       if (performedLt) emitCLRC; else emitSETC;
3993       goto correct_result_in_carry;
3994     } // if
3995
3996     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3997     // that's why we handled it above.
3998     lit++;
3999
4000     dummy = left;
4001     left = right;
4002     right = dummy;
4003
4004     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4005   } else if (isAOP_LIT(right)) {
4006     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4007   } // if
4008
4009   assert (isAOP_REGlike(left)); // left must be register or the like
4010   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4011
4012   /*************************************************
4013    * special cases go here                         *
4014    *************************************************/
4015
4016   if (isAOP_LIT(right)) {
4017     if (!sign) {
4018       // unsigned comparison to a literal
4019       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4020       if (lit == 0) {
4021         // unsigned left < 0? always false
4022         if (performedLt) emitCLRC; else emitSETC;
4023         goto correct_result_in_carry;
4024       }
4025     } else {
4026       // signed comparison to a literal
4027       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4028       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4029         // signed left < 0x80000000? always false
4030         if (performedLt) emitCLRC; else emitSETC;
4031         goto correct_result_in_carry;
4032       } else if (lit == 0) {
4033         // compare left < 0; set CARRY if SIGNBIT(left) is set
4034         if (performedLt) emitSETC; else emitCLRC;
4035         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4036         if (performedLt) emitCLRC; else emitSETC;
4037         goto correct_result_in_carry;
4038       }
4039     } // if (!sign)
4040   } // right is literal
4041
4042   /*************************************************
4043    * perform a general case comparison             *
4044    * make sure we get CARRY==1 <==> left >= right  *
4045    *************************************************/
4046   // compare most significant bytes
4047   //DEBUGpc ("comparing bytes at offset %d", size);
4048   if (!sign) {
4049     // unsigned comparison
4050     pic14_mov2w_regOrLit (AOP(right), lit, size);
4051     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4052   } else {
4053     // signed comparison
4054     // (add 2^n to both operands then perform an unsigned comparison)
4055     if (isAOP_LIT(right)) {
4056       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4057       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4058
4059       if (litbyte == 0x80) {
4060         // left >= 0x80 -- always true, but more bytes to come
4061         mov2w (AOP(left), size);
4062         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4063         emitSETC;
4064       } else {
4065         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4066         mov2w (AOP(left), size);
4067         emitpcode (POC_ADDLW, popGetLit (0x80));
4068         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4069       } // if
4070     } else {
4071       pCodeOp *pctemp = popGetTempReg();
4072       mov2w (AOP(left), size);
4073       emitpcode (POC_ADDLW, popGetLit (0x80));
4074       emitpcode (POC_MOVWF, pctemp);
4075       mov2w (AOP(right), size);
4076       emitpcode (POC_ADDLW, popGetLit (0x80));
4077       emitpcode (POC_SUBFW, pctemp);
4078       popReleaseTempReg(pctemp);
4079     }
4080   } // if (!sign)
4081
4082   // compare remaining bytes (treat as unsigned case from above)
4083   templbl = newiTempLabel ( NULL );
4084   offs = size;
4085   while (offs--) {
4086     //DEBUGpc ("comparing bytes at offset %d", offs);
4087     emitSKPZ;
4088     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4089     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4090     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4091   } // while (offs)
4092   emitpLabel (templbl->key);
4093   goto result_in_carry;
4094
4095 result_in_carry:
4096   
4097   /****************************************************
4098    * now CARRY contains the result of the comparison: *
4099    * SUBWF sets CARRY iff                             *
4100    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4101    * (F=left, W=right)                                *
4102    ****************************************************/
4103
4104   if (performedLt) {
4105     invert_result = 1;
4106     // value will be used in the following genSkipc()
4107     rIfx.condition ^= 1;
4108   } // if
4109
4110 correct_result_in_carry:
4111
4112   // assign result to variable (if neccessary)
4113   if (result && AOP_TYPE(result) != AOP_CRY) {
4114     //DEBUGpc ("assign result");
4115     size = AOP_SIZE(result);
4116     while (size--) {
4117       emitpcode (POC_CLRF, popGet (AOP(result), size));
4118     } // while
4119     if (invert_result) {
4120       emitSKPC;
4121       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4122     } else {
4123       emitpcode (POC_RLF, popGet (AOP(result), 0));
4124     }
4125   } // if (result)
4126
4127   // perform conditional jump
4128   if (ifx) {
4129     //DEBUGpc ("generate control flow");
4130     genSkipc (&rIfx);
4131     ifx->generated = 1;
4132   } // if
4133 }
4134
4135
4136 #if 0
4137 /* OLD VERSION -- BUGGY, DO NOT USE */
4138
4139 /*-----------------------------------------------------------------*/
4140 /* genCmp :- greater or less than comparison                       */
4141 /*-----------------------------------------------------------------*/
4142 static void genCmp (operand *left,operand *right,
4143                                         operand *result, iCode *ifx, int sign)
4144 {
4145         int size; //, offset = 0 ;
4146         unsigned long lit = 0L,i = 0;
4147         resolvedIfx rFalseIfx;
4148         //  resolvedIfx rTrueIfx;
4149         symbol *truelbl;
4150
4151         FENTRY;
4152         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4153         /*
4154         if(ifx) {
4155         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4156         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4157         }
4158         */
4159         
4160         resolveIfx(&rFalseIfx,ifx);
4161         truelbl  = newiTempLabel(NULL);
4162         size = max(AOP_SIZE(left),AOP_SIZE(right));
4163         
4164         DEBUGpic14_AopType(__LINE__,left,right,result);
4165         
4166 #define _swapp
4167         
4168         /* if literal is on the right then swap with left */
4169         if ((AOP_TYPE(right) == AOP_LIT)) {
4170                 operand *tmp = right ;
4171                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4172                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4173 #ifdef _swapp
4174                 
4175                 lit = (lit - 1) & mask;
4176                 right = left;
4177                 left = tmp;
4178                 rFalseIfx.condition ^= 1;
4179 #endif
4180                 
4181         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4182                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4183         }
4184         
4185         
4186         //if(IC_TRUE(ifx) == NULL)
4187         /* if left & right are bit variables */
4188         if (AOP_TYPE(left) == AOP_CRY &&
4189                 AOP_TYPE(right) == AOP_CRY ) {
4190                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4191                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4192         } else {
4193         /* subtract right from left if at the
4194         end the carry flag is set then we know that
4195                 left is greater than right */
4196                 
4197                 symbol *lbl  = newiTempLabel(NULL);
4198                 
4199 #ifndef _swapp
4200                 if(AOP_TYPE(right) == AOP_LIT) {
4201                         
4202                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4203                         
4204                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4205                         
4206                         /* special cases */
4207                         
4208                         if(lit == 0) {
4209                                 
4210                                 if(sign != 0) 
4211                                         genSkipCond(&rFalseIfx,left,size-1,7);
4212                                 else 
4213                                         /* no need to compare to 0...*/
4214                                         /* NOTE: this is a de-generate compare that most certainly 
4215                                         *       creates some dead code. */
4216                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4217                                 
4218                                 if(ifx) ifx->generated = 1;
4219                                 return;
4220                                 
4221                         }
4222                         size--;
4223                         
4224                         if(size == 0) {
4225                                 //i = (lit >> (size*8)) & 0xff;
4226                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4227                                 
4228                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4229                                 
4230                                 i = ((0-lit) & 0xff);
4231                                 if(sign) {
4232                                         if( i == 0x81) { 
4233                                         /* lit is 0x7f, all signed chars are less than
4234                                                 * this except for 0x7f itself */
4235                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4236                                                 genSkipz2(&rFalseIfx,0);
4237                                         } else {
4238                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4239                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4240                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4241                                         }
4242                                         
4243                                 } else {
4244                                         if(lit == 1) {
4245                                                 genSkipz2(&rFalseIfx,1);
4246                                         } else {
4247                                                 emitpcode(POC_ADDLW, popGetLit(i));
4248                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4249                                         }
4250                                 }
4251                                 
4252                                 if(ifx) ifx->generated = 1;
4253                                 return;
4254                         }
4255                         
4256                         /* chars are out of the way. now do ints and longs */
4257                         
4258                         
4259                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4260                         
4261                         /* special cases */
4262                         
4263                         if(sign) {
4264                                 
4265                                 if(lit == 0) {
4266                                         genSkipCond(&rFalseIfx,left,size,7);
4267                                         if(ifx) ifx->generated = 1;
4268                                         return;
4269                                 }
4270                                 
4271                                 if(lit <0x100) {
4272                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4273                                         
4274                                         //rFalseIfx.condition ^= 1;
4275                                         //genSkipCond(&rFalseIfx,left,size,7);
4276                                         //rFalseIfx.condition ^= 1;
4277                                         
4278                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4279                                         if(rFalseIfx.condition)
4280                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4281                                         else
4282                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4283                                         
4284                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4285                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4286                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4287                                         
4288                                         while(size > 1)
4289                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4290                                         
4291                                         if(rFalseIfx.condition) {
4292                                                 emitSKPZ;
4293                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4294                                                 
4295                                         } else {
4296                                                 emitSKPNZ;
4297                                         }
4298                                         
4299                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4300                                         emitpLabel(truelbl->key);
4301                                         if(ifx) ifx->generated = 1;
4302                                         return;
4303                                         
4304                                 }
4305                                 
4306                                 if(size == 1) {
4307                                         
4308                                         if( (lit & 0xff) == 0) {
4309                                                 /* lower byte is zero */
4310                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4311                                                 i = ((lit >> 8) & 0xff) ^0x80;
4312                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4313                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4314                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4315                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4316                                                 
4317                                                 
4318                                                 if(ifx) ifx->generated = 1;
4319                                                 return;
4320                                                 
4321                                         }
4322                                 } else {
4323                                         /* Special cases for signed longs */
4324                                         if( (lit & 0xffffff) == 0) {
4325                                                 /* lower byte is zero */
4326                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4327                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4328                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4329                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4330                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4331                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4332                                                 
4333                                                 
4334                                                 if(ifx) ifx->generated = 1;
4335                                                 return;
4336                                                 
4337                                         }
4338                                         
4339                                 }
4340                                 
4341                                 
4342                                 if(lit & (0x80 << (size*8))) {
4343                                         /* lit is negative */
4344                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4345                                         
4346                                         //genSkipCond(&rFalseIfx,left,size,7);
4347                                         
4348                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4349                                         
4350                                         if(rFalseIfx.condition)
4351                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4352                                         else
4353                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4354                                         
4355                                         
4356                                 } else {
4357                                         /* lit is positive */
4358                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4359                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4360                                         if(rFalseIfx.condition)
4361                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4362                                         else
4363                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4364                                         
4365                                 }
4366                                 
4367                                 /* There are no more special cases, so perform a general compare */
4368                                 
4369                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4370                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4371                                 
4372                                 while(size--) {
4373                                         
4374                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4375                                         emitSKPNZ;
4376                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4377                                 }
4378                                 //rFalseIfx.condition ^= 1;
4379                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4380                                 
4381                                 emitpLabel(truelbl->key);
4382                                 
4383                                 if(ifx) ifx->generated = 1;
4384                                 return;
4385                                 
4386                                 
4387                         }
4388
4389
4390                         /* sign is out of the way. So now do an unsigned compare */
4391                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4392
4393
4394                         /* General case - compare to an unsigned literal on the right.*/
4395
4396                         i = (lit >> (size*8)) & 0xff;
4397                         emitpcode(POC_MOVLW, popGetLit(i));
4398                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4399                         while(size--) {
4400                                 i = (lit >> (size*8)) & 0xff;
4401                                 
4402                                 if(i) {
4403                                         emitpcode(POC_MOVLW, popGetLit(i));
4404                                         emitSKPNZ;
4405                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4406                                 } else {
4407                                 /* this byte of the lit is zero, 
4408                                         *if it's not the last then OR in the variable */
4409                                         if(size)
4410                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4411                                 }
4412                         }
4413
4414
4415                 emitpLabel(lbl->key);
4416                 //if(emitFinalCheck)
4417                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4418                 if(sign)
4419                         emitpLabel(truelbl->key);
4420
4421                 if(ifx) ifx->generated = 1;
4422                 return;
4423
4424
4425                 }
4426 #endif  // _swapp
4427
4428                 if(AOP_TYPE(left) == AOP_LIT) {
4429                         //symbol *lbl = newiTempLabel(NULL);
4430                         
4431                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4432                         
4433                         
4434                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4435                         
4436                         /* Special cases */
4437                         if((lit == 0) && (sign == 0)){
4438                                 
4439                                 size--;
4440                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4441                                 while(size) 
4442                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4443                                 
4444                                 genSkipz2(&rFalseIfx,0);
4445                                 if(ifx) ifx->generated = 1;
4446                                 return;
4447                         }
4448                         
4449                         if(size==1) {
4450                                 /* Special cases */
4451                                 lit &= 0xff;
4452                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4453                                         /* degenerate compare can never be true */
4454                                         if(rFalseIfx.condition == 0)
4455                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4456                                         
4457                                         if(ifx) ifx->generated = 1;
4458                                         return;
4459                                 }
4460                                 
4461                                 if(sign) {
4462                                         /* signed comparisons to a literal byte */
4463                                         
4464                                         int lp1 = (lit+1) & 0xff;
4465                                         
4466                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4467                                         switch (lp1) {
4468                                         case 0:
4469                                                 rFalseIfx.condition ^= 1;
4470                                                 genSkipCond(&rFalseIfx,right,0,7);
4471                                                 break;
4472                                         case 0x7f:
4473                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4474                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4475                                                 genSkipz2(&rFalseIfx,1);
4476                                                 break;
4477                                         default:
4478                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4479                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4480                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4481                                                 rFalseIfx.condition ^= 1;
4482                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4483                                                 break;
4484                                         }
4485                                         if(ifx) ifx->generated = 1;
4486                                 } else {
4487                                         /* unsigned comparisons to a literal byte */
4488                                         
4489                                         switch(lit & 0xff ) {
4490                                         case 0:
4491                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4492                                                 genSkipz2(&rFalseIfx,0);
4493                                                 if(ifx) ifx->generated = 1;
4494                                                 break;
4495                                         case 0x7f:
4496                                                 genSkipCond(&rFalseIfx,right,0,7);
4497                                                 if(ifx) ifx->generated = 1;
4498                                                 break;
4499                                                 
4500                                         default:
4501                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4502                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4503                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4504                                                 rFalseIfx.condition ^= 1;
4505                                                 if (AOP_TYPE(result) == AOP_CRY) {
4506                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4507                                                         if(ifx) ifx->generated = 1;
4508                                                 } else {
4509                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4510                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4511                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4512                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4513                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4514                                                 }       
4515                                                 break;
4516                                         }
4517                                 }
4518                                 
4519                                 //goto check_carry;
4520                                 return;
4521                                 
4522                         } else {
4523                                 
4524                                 /* Size is greater than 1 */
4525                                 
4526                                 if(sign) {
4527                                         int lp1 = lit+1;
4528                                         
4529                                         size--;
4530                                         
4531                                         if(lp1 == 0) {
4532                                                 /* this means lit = 0xffffffff, or -1 */
4533                                                 
4534                                                 
4535                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4536                                                 rFalseIfx.condition ^= 1;
4537                                                 genSkipCond(&rFalseIfx,right,size,7);
4538                                                 if(ifx) ifx->generated = 1;
4539                                                 return;
4540                                         }
4541                                         
4542                                         if(lit == 0) {
4543                                                 int s = size;
4544                                                 
4545                                                 if(rFalseIfx.condition) {
4546                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4547                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4548                                                 }
4549                                                 
4550                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4551                                                 while(size--)
4552                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4553                                                 
4554                                                 
4555                                                 emitSKPZ;
4556                                                 if(rFalseIfx.condition) {
4557                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4558                                                         emitpLabel(truelbl->key);
4559                                                 }else {
4560                                                         rFalseIfx.condition ^= 1;
4561                                                         genSkipCond(&rFalseIfx,right,s,7);
4562                                                 }
4563                                                 
4564                                                 if(ifx) ifx->generated = 1;
4565                                                 return;
4566                                         }
4567                                         
4568                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4569                                                 /* lower byte of signed word is zero */
4570                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4571                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4572                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4573                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4574                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4575                                                 rFalseIfx.condition ^= 1;
4576                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4577                                                 
4578                                                 
4579                                                 if(ifx) ifx->generated = 1;
4580                                                 return;
4581                                         }
4582                                         
4583                                         if(lit & (0x80 << (size*8))) {
4584                                                 /* Lit is less than zero */
4585                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4586                                                 //rFalseIfx.condition ^= 1;
4587                                                 //genSkipCond(&rFalseIfx,left,size,7);
4588                                                 //rFalseIfx.condition ^= 1;
4589                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4590                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4591                                                 
4592                                                 if(rFalseIfx.condition)
4593                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4594                                                 else
4595                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4596                                                 
4597                                                 
4598                                         } else {
4599                                                 /* Lit is greater than or equal to zero */
4600                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4601                                                 //rFalseIfx.condition ^= 1;
4602                                                 //genSkipCond(&rFalseIfx,right,size,7);
4603                                                 //rFalseIfx.condition ^= 1;
4604                                                 
4605                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4606                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4607                                                 
4608                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4609                                                 if(rFalseIfx.condition)
4610                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4611                                                 else
4612                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4613                                                 
4614                                         }
4615                                         
4616                                         
4617                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4618                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4619                                         
4620                                         while(size--) {
4621                                                 
4622                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4623                                                 emitSKPNZ;
4624                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4625                                         }
4626                                         rFalseIfx.condition ^= 1;
4627                                         //rFalseIfx.condition = 1;
4628                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4629                                         
4630                                         emitpLabel(truelbl->key);
4631                                         
4632                                         if(ifx) ifx->generated = 1;
4633                                         return;
4634                                         // end of if (sign)
4635                                 } else {
4636                                         
4637                                         /* compare word or long to an unsigned literal on the right.*/
4638                                         
4639                                         
4640                                         size--;
4641                                         if(lit < 0xff) {
4642                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4643                                                 switch (lit) {
4644                                                 case 0:
4645                                                         break; /* handled above */
4646                                                 /*
4647                                                 case 0xff:
4648                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4649                                                         while(size--)
4650                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4651                                                         genSkipz2(&rFalseIfx,0);
4652                                                         break;
4653                                                 */
4654                                                 default:
4655                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4656                                                         while(--size)
4657                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4658                                                         
4659                                                         emitSKPZ;
4660                                                         if(rFalseIfx.condition)
4661                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4662                                                         else
4663                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4664                                                         
4665                                                         
4666                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4667                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4668                                                         
4669                                                         rFalseIfx.condition ^= 1;
4670                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4671                                                 }
4672                                                 
4673                                                 emitpLabel(truelbl->key);
4674                                                 
4675                                                 if(ifx) ifx->generated = 1;
4676                                                 return;
4677                                         }
4678                                         
4679                                         
4680                                         lit++;
4681                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4682                                         i = (lit >> (size*8)) & 0xff;
4683                                         
4684                                         emitpcode(POC_MOVLW, popGetLit(i));
4685                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4686                                         
4687                                         while(size--) {
4688                                                 i = (lit >> (size*8)) & 0xff;
4689                                                 
4690                                                 if(i) {
4691                                                         emitpcode(POC_MOVLW, popGetLit(i));
4692                                                         emitSKPNZ;
4693                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4694                                                 } else {
4695                                                 /* this byte of the lit is zero, 
4696                                                         *if it's not the last then OR in the variable */
4697                                                         if(size)
4698                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4699                                                 }
4700                                         }
4701                                         
4702                                         
4703                                         emitpLabel(lbl->key);
4704                                         
4705                                         rFalseIfx.condition ^= 1;
4706                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4707                                 }
4708                                 
4709                                 if(sign)
4710                                         emitpLabel(truelbl->key);
4711                                 if(ifx) ifx->generated = 1;
4712                                 return;
4713                         }
4714                 }
4715                 /* Compare two variables */
4716                 
4717                 DEBUGpic14_emitcode(";sign","%d",sign);
4718                 
4719                 size--;
4720                 if(sign) {
4721                         /* Sigh. thus sucks... */
4722                         if(size) {
4723                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4724                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4725                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4726                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4727                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4728                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4729                         } else {
4730                                 /* Signed char comparison */
4731                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4732                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4733                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4734                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4735                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4736                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4737                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4738                                 
4739                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4740                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4741                                 
4742                                 if(ifx) ifx->generated = 1;
4743                                 return;
4744                         }
4745                         
4746                 } else {
4747                         
4748                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4749                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4750                 }
4751                 
4752                 
4753                 /* The rest of the bytes of a multi-byte compare */
4754                 while (size) {
4755                         
4756                         emitSKPZ;
4757                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4758                         size--;
4759                         
4760                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4761                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4762                         
4763                         
4764                 }
4765                 
4766                 emitpLabel(lbl->key);
4767                 
4768                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4769                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4770                         (AOP_TYPE(result) == AOP_REG)) {
4771                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4772                         emitpcode(POC_RLF, popGet(AOP(result),0));
4773                 } else {
4774                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4775                 }       
4776                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4777                 if(ifx) ifx->generated = 1;
4778                 
4779                 return;
4780                 
4781         }
4782         
4783         // check_carry:
4784         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4785                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4786                 pic14_outBitC(result);
4787         } else {
4788                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4789                 /* if the result is used in the next
4790                 ifx conditional branch then generate
4791                 code a little differently */
4792                 if (ifx )
4793                         genIfxJump (ifx,"c");
4794                 else
4795                         pic14_outBitC(result);
4796                 /* leave the result in acc */
4797         }
4798         
4799 }
4800 #endif
4801
4802 /*-----------------------------------------------------------------*/
4803 /* genCmpGt :- greater than comparison                             */
4804 /*-----------------------------------------------------------------*/
4805 static void genCmpGt (iCode *ic, iCode *ifx)
4806 {
4807         operand *left, *right, *result;
4808         sym_link *letype , *retype;
4809         int sign ;
4810         
4811         FENTRY;
4812         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4813         left = IC_LEFT(ic);
4814         right= IC_RIGHT(ic);
4815         result = IC_RESULT(ic);
4816         
4817         letype = getSpec(operandType(left));
4818         retype =getSpec(operandType(right));
4819         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4820         /* assign the amsops */
4821         aopOp (left,ic,FALSE);
4822         aopOp (right,ic,FALSE);
4823         aopOp (result,ic,TRUE);
4824         
4825         genCmp(right, left, result, ifx, sign);
4826         
4827         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4828         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4829         freeAsmop(result,NULL,ic,TRUE); 
4830 }
4831
4832 /*-----------------------------------------------------------------*/
4833 /* genCmpLt - less than comparisons                                */
4834 /*-----------------------------------------------------------------*/
4835 static void genCmpLt (iCode *ic, iCode *ifx)
4836 {
4837         operand *left, *right, *result;
4838         sym_link *letype , *retype;
4839         int sign ;
4840         
4841         FENTRY;
4842         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4843         left = IC_LEFT(ic);
4844         right= IC_RIGHT(ic);
4845         result = IC_RESULT(ic);
4846         
4847         letype = getSpec(operandType(left));
4848         retype =getSpec(operandType(right));
4849         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4850         
4851         /* assign the amsops */
4852         aopOp (left,ic,FALSE);
4853         aopOp (right,ic,FALSE);
4854         aopOp (result,ic,TRUE);
4855         
4856         genCmp(left, right, result, ifx, sign);
4857         
4858         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4859         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4860         freeAsmop(result,NULL,ic,TRUE); 
4861 }
4862
4863 #if 0
4864 /*-----------------------------------------------------------------*/
4865 /* genc16bit2lit - compare a 16 bit value to a literal             */
4866 /*-----------------------------------------------------------------*/
4867 static void genc16bit2lit(operand *op, int lit, int offset)
4868 {
4869         int i;
4870         
4871         FENTRY;
4872         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4873         if( (lit&0xff) == 0) 
4874                 i=1;
4875         else
4876                 i=0;
4877         
4878         switch( BYTEofLONG(lit,i)) { 
4879         case 0:
4880                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4881                 break;
4882         case 1:
4883                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4884                 break;
4885         case 0xff:
4886                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4887                 break;
4888         default:
4889                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4890                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4891         }
4892         
4893         i ^= 1;
4894         
4895         switch( BYTEofLONG(lit,i)) { 
4896         case 0:
4897                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4898                 break;
4899         case 1:
4900                 emitSKPNZ;
4901                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4902                 break;
4903         case 0xff:
4904                 emitSKPNZ;
4905                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4906                 break;
4907         default:
4908                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4909                 emitSKPNZ;
4910                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4911                 
4912         }
4913         
4914 }
4915 #endif
4916
4917 #if 0
4918 /*-----------------------------------------------------------------*/
4919 /* gencjneshort - compare and jump if not equal                    */
4920 /*-----------------------------------------------------------------*/
4921 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4922 {
4923         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4924         int offset = 0;
4925         //resolvedIfx rIfx;
4926         symbol *lbl;
4927         
4928         //unsigned long lit = 0L;
4929         FENTRY;
4930         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4931           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4932           return;
4933         }
4934         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4935         DEBUGpic14_AopType(__LINE__,left,right,result);
4936         
4937         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4938         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4939         if (AOP_SIZE(result)) {
4940           for (offset = 0; offset < AOP_SIZE(result); offset++)
4941             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4942         }
4943         
4944         assert (AOP_SIZE(left) == AOP_SIZE(right));
4945         //resolveIfx(&rIfx,ifx);
4946         lbl = newiTempLabel (NULL);
4947         while (size--)
4948         {
4949           mov2w (AOP(right),size);
4950           emitpcode (POC_XORFW, popGet (AOP(left), size));
4951           if (size)
4952           {
4953             emitSKPZ;
4954             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4955           }
4956         } // while
4957         emitpLabel (lbl->key);
4958         if (AOP_SIZE(result)) {
4959           emitSKPNZ;
4960           emitpcode (POC_INCF, popGet (AOP(result), 0));
4961         } else {
4962           assert (ifx);
4963           genSkipz (ifx, NULL != IC_TRUE(ifx));
4964           ifx->generated = 1;
4965         }
4966         return;
4967 #if 0   
4968         if(result)
4969         {
4970                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4971                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4972                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4973                 for (offset=0; offset < AOP_SIZE(result); offset++)
4974                 {
4975                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4976                 } // for offset
4977         }
4978         
4979         
4980         /* if the left side is a literal or 
4981         if the right is in a pointer register and left 
4982         is not */
4983         if ((AOP_TYPE(left) == AOP_LIT) || 
4984                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4985                 operand *t = right;
4986                 right = left;
4987                 left = t;
4988         }
4989         if(AOP_TYPE(right) == AOP_LIT)
4990                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4991         
4992         /* if the right side is a literal then anything goes */
4993         if (AOP_TYPE(right) == AOP_LIT &&
4994                 AOP_TYPE(left) != AOP_DIR ) {
4995                 switch(size) {
4996                 case 2:
4997                         genc16bit2lit(left, lit, 0);
4998                         emitSKPNZ;
4999                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5000                         break;
5001                 default:
5002                         offset = 0;
5003                         while (size--) {
5004                                 if(lit & 0xff) {
5005                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5006                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5007                                 } else {
5008                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5009                                 }
5010                                 
5011                                 emitSKPNZ;
5012                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5013                                 offset++;
5014                                 lit >>= 8;
5015                         }
5016                         break;
5017                 }
5018         }
5019         
5020         /* if the right side is in a register or in direct space or
5021         if the left is a pointer register & right is not */    
5022         else if (AOP_TYPE(right) == AOP_REG ||
5023                 AOP_TYPE(right) == AOP_DIR || 
5024                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5025                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5026                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5027                 int lbl_key = lbl->key;
5028                 
5029                 if(!result) {
5030                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5031                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5032                                 __FUNCTION__,__LINE__);
5033                         return;
5034                 }
5035                 
5036                 /*     switch(size) { */
5037                 /*     case 2: */
5038                 /*       genc16bit2lit(left, lit, 0); */
5039                 /*       emitSKPNZ; */
5040                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5041                 /*       break; */
5042                 /*     default: */
5043                 offset = 0;
5044                 while (size--) {
5045                         int emit_skip=1;
5046                         if((AOP_TYPE(left) == AOP_DIR) && 
5047                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5048                                 
5049                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5050                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5051                                 
5052                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5053                                 
5054                                 switch (lit & 0xff) {
5055                                 case 0:
5056                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5057                                         break;
5058                                 case 1:
5059                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5060                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5061                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5062                                         emit_skip=0;
5063                                         break;
5064                                 case 0xff:
5065                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5066                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5067                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5068                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5069                                         emit_skip=0;
5070                                         break;
5071                                 default:
5072                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5073                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5074                                 }
5075                                 lit >>= 8;
5076                                 
5077                         } else {
5078                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5079                         }
5080                         if(emit_skip) {
5081                                 if(AOP_TYPE(result) == AOP_CRY) {
5082                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5083                                         if(rIfx.condition)
5084                                                 emitSKPNZ;
5085                                         else
5086                                                 emitSKPZ;
5087                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5088                                 } else {
5089                                         /* fix me. probably need to check result size too */
5090                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5091                                         if(rIfx.condition)
5092                                                 emitSKPZ;
5093                                         else
5094                                                 emitSKPNZ;
5095                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5096                                 }
5097                                 if(ifx)
5098                                         ifx->generated=1;
5099                         }
5100                         emit_skip++;
5101                         offset++;
5102                 }
5103                 /*       break; */
5104                 /*     } */
5105         } else if(AOP_TYPE(right) == AOP_REG &&
5106                 AOP_TYPE(left) != AOP_DIR){
5107
5108                 offset = 0;
5109                 while(size--) {
5110                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5111                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5112                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5113                         if(rIfx.condition)
5114                                 emitSKPNZ;
5115                         else
5116                                 emitSKPZ;
5117                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5118                         offset++;
5119                 }
5120                 
5121         }else{
5122                 /* right is a pointer reg need both a & b */
5123                 offset = 0;
5124                 while(size--) {
5125                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5126                         if(strcmp(l,"b"))
5127                                 pic14_emitcode("mov","b,%s",l);
5128                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5129                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5130                         offset++;
5131                 }
5132         }
5133         
5134         emitpcode(POC_INCF,popGet(AOP(result),0));
5135         if(!rIfx.condition)
5136                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5137         
5138         emitpLabel(lbl->key);
5139         
5140         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5141         
5142         if(ifx)
5143                 ifx->generated = 1;
5144 #endif
5145 }
5146 #endif
5147
5148 #if 0
5149 /*-----------------------------------------------------------------*/
5150 /* gencjne - compare and jump if not equal                         */
5151 /*-----------------------------------------------------------------*/
5152 static void gencjne(operand *left, operand *right, iCode *ifx)
5153 {
5154         symbol *tlbl  = newiTempLabel(NULL);
5155         
5156         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5157         gencjneshort(left, right, lbl);
5158         
5159         pic14_emitcode("mov","a,%s",one);
5160         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5161         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5162         pic14_emitcode("clr","a");
5163         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5164         
5165         emitpLabel(lbl->key);
5166         emitpLabel(tlbl->key);
5167         
5168 }
5169 #endif
5170
5171 /*-----------------------------------------------------------------*/
5172 /* genCmpEq - generates code for equal to                          */
5173 /*-----------------------------------------------------------------*/
5174 static void genCmpEq (iCode *ic, iCode *ifx)
5175 {
5176   operand *left, *right, *result;
5177   int size;
5178   symbol *false_label;
5179
5180   FENTRY;
5181   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5182
5183   if(ifx)
5184     DEBUGpic14_emitcode ("; ifx is non-null","");
5185   else
5186     DEBUGpic14_emitcode ("; ifx is null","");
5187
5188   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5189   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5190   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5191
5192   DEBUGpic14_AopType(__LINE__,left,right,result);
5193
5194   /* if literal, move literal to right */ 
5195   if (op_isLitLike (IC_LEFT(ic))) {
5196     operand *tmp = right ;
5197     right = left;
5198     left = tmp;
5199   }
5200
5201   false_label = NULL;
5202   if (ifx && !IC_TRUE(ifx))
5203   {
5204     assert (IC_FALSE(ifx));
5205     false_label = IC_FALSE(ifx);
5206   }
5207
5208   size = min(AOP_SIZE(left),AOP_SIZE(right));
5209   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5210   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5211
5212   /* assume left != right */
5213   {
5214     int i;
5215     for (i=0; i < AOP_SIZE(result); i++)
5216     {
5217       emitpcode(POC_CLRF, popGet(AOP(result),i));
5218     }
5219   }
5220
5221   if (AOP_TYPE(right) == AOP_LIT)
5222   {
5223     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5224     int i;
5225     size = AOP_SIZE(left);
5226     assert(!op_isLitLike(left));
5227
5228     switch (lit)
5229     {
5230       case 0:
5231         mov2w(AOP(left), 0);
5232         for (i=1; i < size; i++)
5233           emitpcode(POC_IORFW,popGet(AOP(left),i));
5234         /* now Z is set iff `left == right' */
5235         emitSKPZ;
5236         if (!false_label) false_label = newiTempLabel(NULL);
5237         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5238         break;
5239
5240       default:
5241         for (i=0; i < size; i++)
5242         {
5243           mov2w(AOP(left),i);
5244           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5245           /* now Z is cleared if `left != right' */
5246           emitSKPZ;
5247           if (!false_label) false_label = newiTempLabel(NULL);
5248           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5249         } // for i
5250         break;
5251     } // switch (lit)
5252   }
5253   else
5254   {
5255     /* right is no literal */
5256     int i;
5257
5258     for (i=0; i < size; i++)
5259     {
5260       mov2w(AOP(right),i);
5261       emitpcode(POC_XORFW,popGet(AOP(left),i));
5262       /* now Z is cleared if `left != right' */
5263       emitSKPZ;
5264       if (!false_label) false_label = newiTempLabel(NULL);
5265       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5266     } // for i
5267   }
5268
5269   /* if we reach here, left == right */
5270
5271   if (AOP_SIZE(result) > 0)
5272   {
5273     emitpcode(POC_INCF, popGet(AOP(result),0));
5274   }
5275
5276   if (ifx && IC_TRUE(ifx))
5277   {
5278     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5279   }
5280
5281   if (false_label && (!ifx || IC_TRUE(ifx)))
5282     emitpLabel(false_label->key);
5283
5284   if (ifx) ifx->generated = 1;
5285
5286   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5287   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5288   freeAsmop(result,NULL,ic,TRUE);
5289 }
5290
5291 /*-----------------------------------------------------------------*/
5292 /* ifxForOp - returns the icode containing the ifx for operand     */
5293 /*-----------------------------------------------------------------*/
5294 static iCode *ifxForOp ( operand *op, iCode *ic )
5295 {
5296         FENTRY;
5297         /* if true symbol then needs to be assigned */
5298         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5299         if (IS_TRUE_SYMOP(op))
5300                 return NULL ;
5301         
5302         /* if this has register type condition and
5303         the next instruction is ifx with the same operand
5304         and live to of the operand is upto the ifx only then */
5305         if (ic->next &&
5306                 ic->next->op == IFX &&
5307                 IC_COND(ic->next)->key == op->key &&
5308                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5309                 return ic->next;
5310         
5311         if (ic->next &&
5312                 ic->next->op == IFX &&
5313                 IC_COND(ic->next)->key == op->key) {
5314                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5315                 return ic->next;
5316         }
5317         
5318         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5319         if (ic->next &&
5320                 ic->next->op == IFX)
5321                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5322         
5323         if (ic->next &&
5324                 ic->next->op == IFX &&
5325                 IC_COND(ic->next)->key == op->key) {
5326                 DEBUGpic14_emitcode ("; "," key is okay");
5327                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5328                         OP_SYMBOL(op)->liveTo,
5329                         ic->next->seq);
5330         }
5331         
5332         
5333         return NULL;
5334 }
5335 /*-----------------------------------------------------------------*/
5336 /* genAndOp - for && operation                                     */
5337 /*-----------------------------------------------------------------*/
5338 static void genAndOp (iCode *ic)
5339 {
5340         operand *left,*right, *result;
5341         /*     symbol *tlbl; */
5342         
5343         FENTRY;
5344         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5345         /* note here that && operations that are in an
5346         if statement are taken away by backPatchLabels
5347         only those used in arthmetic operations remain */
5348         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5349         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5350         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5351         
5352         DEBUGpic14_AopType(__LINE__,left,right,result);
5353         
5354         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5355         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5356         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5357         
5358         /* if both are bit variables */
5359         /*     if (AOP_TYPE(left) == AOP_CRY && */
5360         /*         AOP_TYPE(right) == AOP_CRY ) { */
5361         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5362         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5363         /*         pic14_outBitC(result); */
5364         /*     } else { */
5365         /*         tlbl = newiTempLabel(NULL); */
5366         /*         pic14_toBoolean(left);     */
5367         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5368         /*         pic14_toBoolean(right); */
5369         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5370         /*         pic14_outBitAcc(result); */
5371         /*     } */
5372         
5373         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5374         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5375         freeAsmop(result,NULL,ic,TRUE);
5376 }
5377
5378
5379 /*-----------------------------------------------------------------*/
5380 /* genOrOp - for || operation                                      */
5381 /*-----------------------------------------------------------------*/
5382 /*
5383 tsd pic port -
5384 modified this code, but it doesn't appear to ever get called
5385 */
5386
5387 static void genOrOp (iCode *ic)
5388 {
5389         operand *left,*right, *result;
5390         symbol *tlbl;
5391         int i;
5392         
5393         /* note here that || operations that are in an
5394         if statement are taken away by backPatchLabels
5395         only those used in arthmetic operations remain */
5396         FENTRY;
5397         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5398         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5399         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5400         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5401         
5402         DEBUGpic14_AopType(__LINE__,left,right,result);
5403
5404         for (i=0; i < AOP_SIZE(result); i++)
5405         {
5406                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5407         } // for i
5408
5409         tlbl = newiTempLabel(NULL);
5410         pic14_toBoolean(left);
5411         emitSKPZ;
5412         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5413         pic14_toBoolean(right);
5414         emitpLabel(tlbl->key);
5415         /* here Z is clear IFF `left || right' */
5416         emitSKPZ;
5417         emitpcode(POC_INCF, popGet(AOP(result), 0));
5418         
5419         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5420         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5421         freeAsmop(result,NULL,ic,TRUE);            
5422 }
5423
5424 /*-----------------------------------------------------------------*/
5425 /* isLiteralBit - test if lit == 2^n                               */
5426 /*-----------------------------------------------------------------*/
5427 static int isLiteralBit(unsigned long lit)
5428 {
5429         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5430                 0x100L,0x200L,0x400L,0x800L,
5431                 0x1000L,0x2000L,0x4000L,0x8000L,
5432                 0x10000L,0x20000L,0x40000L,0x80000L,
5433                 0x100000L,0x200000L,0x400000L,0x800000L,
5434                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5435                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5436         int idx;
5437         
5438         FENTRY;
5439         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5440         for(idx = 0; idx < 32; idx++)
5441                 if(lit == pw[idx])
5442                         return idx+1;
5443                 return 0;
5444 }
5445
5446 /*-----------------------------------------------------------------*/
5447 /* continueIfTrue -                                                */
5448 /*-----------------------------------------------------------------*/
5449 static void continueIfTrue (iCode *ic)
5450 {
5451         FENTRY;
5452         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5453         if(IC_TRUE(ic))
5454                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5455         ic->generated = 1;
5456 }
5457
5458 /*-----------------------------------------------------------------*/
5459 /* jmpIfTrue -                                                     */
5460 /*-----------------------------------------------------------------*/
5461 static void jumpIfTrue (iCode *ic)
5462 {
5463         FENTRY;
5464         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5465         if(!IC_TRUE(ic))
5466                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5467         ic->generated = 1;
5468 }
5469
5470 /*-----------------------------------------------------------------*/
5471 /* jmpTrueOrFalse -                                                */
5472 /*-----------------------------------------------------------------*/
5473 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5474 {
5475         FENTRY;
5476         // ugly but optimized by peephole
5477         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5478         if(IC_TRUE(ic)){
5479                 symbol *nlbl = newiTempLabel(NULL);
5480                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5481                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5482                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5483                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5484         }
5485         else{
5486                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5487                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5488         }
5489         ic->generated = 1;
5490 }
5491
5492 /*-----------------------------------------------------------------*/
5493 /* genAnd  - code for and                                          */
5494 /*-----------------------------------------------------------------*/
5495 static void genAnd (iCode *ic, iCode *ifx)
5496 {
5497         operand *left, *right, *result;
5498         int size, offset=0;  
5499         unsigned long lit = 0L;
5500         int bytelit = 0;
5501         resolvedIfx rIfx;
5502         
5503         FENTRY;
5504         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5505         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5506         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5507         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5508         
5509         resolveIfx(&rIfx,ifx);
5510         
5511         /* if left is a literal & right is not then exchange them */
5512         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5513                 AOP_NEEDSACC(left)) {
5514                 operand *tmp = right ;
5515                 right = left;
5516                 left = tmp;
5517         }
5518         
5519         /* if result = right then exchange them */
5520         if(pic14_sameRegs(AOP(result),AOP(right))){
5521                 operand *tmp = right ;
5522                 right = left;
5523                 left = tmp;
5524         }
5525         
5526         /* if right is bit then exchange them */
5527         if (AOP_TYPE(right) == AOP_CRY &&
5528                 AOP_TYPE(left) != AOP_CRY){
5529                 operand *tmp = right ;
5530                 right = left;
5531                 left = tmp;
5532         }
5533         if(AOP_TYPE(right) == AOP_LIT)
5534                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5535         
5536         size = AOP_SIZE(result);
5537         
5538         DEBUGpic14_AopType(__LINE__,left,right,result);
5539         
5540         // if(bit & yy)
5541         // result = bit & yy;
5542         if (AOP_TYPE(left) == AOP_CRY){
5543                 // c = bit & literal;
5544                 if(AOP_TYPE(right) == AOP_LIT){
5545                         if(lit & 1) {
5546                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5547                                         // no change
5548                                         goto release;
5549                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5550                         } else {
5551                                 // bit(result) = 0;
5552                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5553                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5554                                         goto release;
5555                                 }
5556                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5557                                         jumpIfTrue(ifx);
5558                                         goto release;
5559                                 }
5560                                 pic14_emitcode("clr","c");
5561                         }
5562                 } else {
5563                         if (AOP_TYPE(right) == AOP_CRY){
5564                                 // c = bit & bit;
5565                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5566                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5567                         } else {
5568                                 // c = bit & val;
5569                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5570                                 // c = lsb
5571                                 pic14_emitcode("rrc","a");
5572                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5573                         }
5574                 }
5575                 // bit = c
5576                 // val = c
5577                 if(size)
5578                         pic14_outBitC(result);
5579                 // if(bit & ...)
5580                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5581                         genIfxJump(ifx, "c");           
5582                 goto release ;
5583         }
5584         
5585         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5586         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5587         if((AOP_TYPE(right) == AOP_LIT) &&
5588                 (AOP_TYPE(result) == AOP_CRY) &&
5589                 (AOP_TYPE(left) != AOP_CRY)){
5590                 int posbit = isLiteralBit(lit);
5591                 /* left &  2^n */
5592                 if(posbit){
5593                         posbit--;
5594                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5595                         // bit = left & 2^n
5596                         if(size)
5597                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5598                         // if(left &  2^n)
5599                         else{
5600                                 if(ifx){
5601                                         int offset = 0;
5602                                         while (posbit > 7) {
5603                                                 posbit -= 8;
5604                                                 offset++;
5605                                         }
5606                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5607                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5608                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5609                                         
5610                                         ifx->generated = 1;
5611                                 }
5612                                 goto release;
5613                         }
5614                 } else {
5615                         symbol *tlbl = newiTempLabel(NULL);
5616                         int sizel = AOP_SIZE(left);
5617                         if(size)
5618                                 pic14_emitcode("setb","c");
5619                         while(sizel--){
5620                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5621                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5622                                         // byte ==  2^n ?
5623                                         if((posbit = isLiteralBit(bytelit)) != 0)
5624                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5625                                         else{
5626                                                 if(bytelit != 0x0FFL)
5627                                                         pic14_emitcode("anl","a,%s",
5628                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5629                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5630                                         }
5631                                 }
5632                                 offset++;
5633                         }
5634                         // bit = left & literal
5635                         if(size){
5636                                 pic14_emitcode("clr","c");
5637                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5638                         }
5639                         // if(left & literal)
5640                         else{
5641                                 if(ifx)
5642                                         jmpTrueOrFalse(ifx, tlbl);
5643                                 goto release ;
5644                         }
5645                 }
5646                 pic14_outBitC(result);
5647                 goto release ;
5648         }
5649         
5650         /* if left is same as result */
5651         if(pic14_sameRegs(AOP(result),AOP(left))){
5652                 int know_W = -1;
5653                 for(;size--; offset++,lit>>=8) {
5654                         if(AOP_TYPE(right) == AOP_LIT){
5655                                 switch(lit & 0xff) {
5656                                 case 0x00:
5657                                         /*  and'ing with 0 has clears the result */
5658                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5659                                         break;
5660                                 case 0xff:
5661                                         /* and'ing with 0xff is a nop when the result and left are the same */
5662                                         break;
5663                                         
5664                                 default:
5665                                         {
5666                                                 int p = my_powof2( (~lit) & 0xff );
5667                                                 if(p>=0) {
5668                                                         /* only one bit is set in the literal, so use a bcf instruction */
5669                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5670                                                         
5671                                                 } else {
5672                                                         if(know_W != (int)(lit&0xff))
5673                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5674                                                         know_W = lit &0xff;
5675                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5676                                                 }
5677                                         }    
5678                                 }
5679                         } else {
5680                                 if (AOP_TYPE(left) == AOP_ACC) {
5681                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5682                                 } else {        
5683                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5684                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5685                                         
5686                                 }
5687                         }
5688                 }
5689                 
5690         } else {
5691                 // left & result in different registers
5692                 if(AOP_TYPE(result) == AOP_CRY){
5693                         // result = bit
5694                         // if(size), result in bit
5695                         // if(!size && ifx), conditional oper: if(left & right)
5696                         symbol *tlbl = newiTempLabel(NULL);
5697                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5698                         if(size)
5699                                 pic14_emitcode("setb","c");
5700                         while(sizer--){
5701                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5702                                 pic14_emitcode("anl","a,%s",
5703                                         aopGet(AOP(left),offset,FALSE,FALSE));
5704                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5705                                 offset++;
5706                         }
5707                         if(size){
5708                                 CLRC;
5709                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5710                                 pic14_outBitC(result);
5711                         } else if(ifx)
5712                                 jmpTrueOrFalse(ifx, tlbl);
5713                 } else {
5714                         for(;(size--);offset++) {
5715                                 // normal case
5716                                 // result = left & right
5717                                 if(AOP_TYPE(right) == AOP_LIT){
5718                                         int t = (lit >> (offset*8)) & 0x0FFL;
5719                                         switch(t) { 
5720                                         case 0x00:
5721                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5722                                                 break;
5723                                         case 0xff:
5724                                                 if(AOP_TYPE(left) != AOP_ACC) {
5725                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5726                                                 }
5727                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5728                                                 break;
5729                                         default:
5730                                                 if(AOP_TYPE(left) == AOP_ACC) {
5731                                                         emitpcode(POC_ANDLW, popGetLit(t));
5732                                                 } else {
5733                                                         emitpcode(POC_MOVLW, popGetLit(t));
5734                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5735                                                 }
5736                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5737                                         }
5738                                         continue;
5739                                 }
5740                                 
5741                                 if (AOP_TYPE(left) == AOP_ACC) {
5742                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5743                                 } else {
5744                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5745                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5746                                 }
5747                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5748                         }
5749                 }
5750         }
5751         
5752 release :
5753         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5754         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5755         freeAsmop(result,NULL,ic,TRUE);     
5756 }
5757
5758 /*-----------------------------------------------------------------*/
5759 /* genOr  - code for or                                            */
5760 /*-----------------------------------------------------------------*/
5761 static void genOr (iCode *ic, iCode *ifx)
5762 {
5763         operand *left, *right, *result;
5764         int size, offset=0;
5765         unsigned long lit = 0L;
5766         
5767         FENTRY;
5768         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5769         
5770         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5771         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5772         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5773         
5774         DEBUGpic14_AopType(__LINE__,left,right,result);
5775         
5776         /* if left is a literal & right is not then exchange them */
5777         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5778                 AOP_NEEDSACC(left)) {
5779                 operand *tmp = right ;
5780                 right = left;
5781                 left = tmp;
5782         }
5783         
5784         /* if result = right then exchange them */
5785         if(pic14_sameRegs(AOP(result),AOP(right))){
5786                 operand *tmp = right ;
5787                 right = left;
5788                 left = tmp;
5789         }
5790         
5791         /* if right is bit then exchange them */
5792         if (AOP_TYPE(right) == AOP_CRY &&
5793                 AOP_TYPE(left) != AOP_CRY){
5794                 operand *tmp = right ;
5795                 right = left;
5796                 left = tmp;
5797         }
5798         
5799         DEBUGpic14_AopType(__LINE__,left,right,result);
5800         
5801         if(AOP_TYPE(right) == AOP_LIT)
5802                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5803         
5804         size = AOP_SIZE(result);
5805         
5806         // if(bit | yy)
5807         // xx = bit | yy;
5808         if (AOP_TYPE(left) == AOP_CRY){
5809                 if(AOP_TYPE(right) == AOP_LIT){
5810                         // c = bit & literal;
5811                         if(lit){
5812                                 // lit != 0 => result = 1
5813                                 if(AOP_TYPE(result) == AOP_CRY){
5814                                         if(size)
5815                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5816                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5817                                         //   AOP(result)->aopu.aop_dir,
5818                                         //   AOP(result)->aopu.aop_dir);
5819                                         else if(ifx)
5820                                                 continueIfTrue(ifx);
5821                                         goto release;
5822                                 }
5823                         } else {
5824                                 // lit == 0 => result = left
5825                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5826                                         goto release;
5827                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5828                         }
5829                 } else {
5830                         if (AOP_TYPE(right) == AOP_CRY){
5831                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5832                                         // c = bit | bit;
5833                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5834                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5835                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5836                                         
5837                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5838                                                 AOP(result)->aopu.aop_dir,
5839                                                 AOP(result)->aopu.aop_dir);
5840                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5841                                                 AOP(right)->aopu.aop_dir,
5842                                                 AOP(right)->aopu.aop_dir);
5843                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5844                                                 AOP(result)->aopu.aop_dir,
5845                                                 AOP(result)->aopu.aop_dir);
5846                                 } else {
5847                                         if( AOP_TYPE(result) == AOP_ACC) {
5848                                                 emitpcode(POC_MOVLW, popGetLit(0));
5849                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5850                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5851                                                 emitpcode(POC_MOVLW, popGetLit(1));
5852                                                 
5853                                         } else {
5854                                                 
5855                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5856                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5857                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5858                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5859                                                 
5860                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5861                                                         AOP(result)->aopu.aop_dir,
5862                                                         AOP(result)->aopu.aop_dir);
5863                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5864                                                         AOP(right)->aopu.aop_dir,
5865                                                         AOP(right)->aopu.aop_dir);
5866                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5867                                                         AOP(left)->aopu.aop_dir,
5868                                                         AOP(left)->aopu.aop_dir);
5869                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5870                                                         AOP(result)->aopu.aop_dir,
5871                                                         AOP(result)->aopu.aop_dir);
5872                                         }
5873                                 }
5874                         } else {
5875                                 // c = bit | val;
5876                                 symbol *tlbl = newiTempLabel(NULL);
5877                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5878                                 
5879                                 
5880                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5881                                 if( AOP_TYPE(right) == AOP_ACC) {
5882                                         emitpcode(POC_IORLW, popGetLit(0));
5883                                         emitSKPNZ;
5884                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5885                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5886                                 }
5887                                 
5888                                 
5889                                 
5890                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5891                                         pic14_emitcode(";XXX setb","c");
5892                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5893                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5894                                 pic14_toBoolean(right);
5895                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5896                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5897                                         jmpTrueOrFalse(ifx, tlbl);
5898                                         goto release;
5899                                 } else {
5900                                         CLRC;
5901                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5902                                 }
5903                         }
5904                 }
5905                 // bit = c
5906                 // val = c
5907                 if(size)
5908                         pic14_outBitC(result);
5909                 // if(bit | ...)
5910                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5911                         genIfxJump(ifx, "c");           
5912                 goto release ;
5913         }
5914
5915         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5916         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5917         if((AOP_TYPE(right) == AOP_LIT) &&
5918           (AOP_TYPE(result) == AOP_CRY) &&
5919           (AOP_TYPE(left) != AOP_CRY)){
5920                 if(lit){
5921                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5922                         // result = 1
5923                         if(size)
5924                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5925                         else 
5926                                 continueIfTrue(ifx);
5927                         goto release;
5928                 } else {
5929                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5930                         // lit = 0, result = boolean(left)
5931                         if(size)
5932                                 pic14_emitcode(";XXX setb","c");
5933                         pic14_toBoolean(right);
5934                         if(size){
5935                                 symbol *tlbl = newiTempLabel(NULL);
5936                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5937                                 CLRC;
5938                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5939                         } else {
5940                                 genIfxJump (ifx,"a");
5941                                 goto release;
5942                         }
5943                 }
5944                 pic14_outBitC(result);
5945                 goto release ;
5946         }
5947
5948         /* if left is same as result */
5949         if(pic14_sameRegs(AOP(result),AOP(left))){
5950                 int know_W = -1;
5951                 for(;size--; offset++,lit>>=8) {
5952                         if(AOP_TYPE(right) == AOP_LIT){
5953                                 if((lit & 0xff) == 0)
5954                                         /*  or'ing with 0 has no effect */
5955                                         continue;
5956                                 else {
5957                                         int p = my_powof2(lit & 0xff);
5958                                         if(p>=0) {
5959                                                 /* only one bit is set in the literal, so use a bsf instruction */
5960                                                 emitpcode(POC_BSF,
5961                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5962                                         } else {
5963                                                 if(know_W != (int)(lit & 0xff))
5964                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5965                                                 know_W = lit & 0xff;
5966                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5967                                         }
5968                                         
5969                                 }
5970                         } else {
5971                                 if (AOP_TYPE(left) == AOP_ACC) {
5972                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5973                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5974                                 } else {        
5975                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5976                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5977                                         
5978                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5979                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5980                                         
5981                                 }
5982                         }
5983                 }
5984         } else {
5985                 // left & result in different registers
5986                 if(AOP_TYPE(result) == AOP_CRY){
5987                         // result = bit
5988                         // if(size), result in bit
5989                         // if(!size && ifx), conditional oper: if(left | right)
5990                         symbol *tlbl = newiTempLabel(NULL);
5991                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5992                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5993                         
5994                         
5995                         if(size)
5996                                 pic14_emitcode(";XXX setb","c");
5997                         while(sizer--){
5998                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5999                                 pic14_emitcode(";XXX orl","a,%s",
6000                                         aopGet(AOP(left),offset,FALSE,FALSE));
6001                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6002                                 offset++;
6003                         }
6004                         if(size){
6005                                 CLRC;
6006                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6007                                 pic14_outBitC(result);
6008                         } else if(ifx)
6009                                 jmpTrueOrFalse(ifx, tlbl);
6010                 } else for(;(size--);offset++){
6011                         // normal case
6012                         // result = left | right
6013                         if(AOP_TYPE(right) == AOP_LIT){
6014                                 int t = (lit >> (offset*8)) & 0x0FFL;
6015                                 switch(t) { 
6016                                 case 0x00:
6017                                         if (AOP_TYPE(left) != AOP_ACC) {
6018                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6019                                         }
6020                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6021                                         
6022                                         break;
6023                                 default:
6024                                         if (AOP_TYPE(left) == AOP_ACC) {
6025                                                 emitpcode(POC_IORLW,  popGetLit(t));
6026                                         } else {
6027                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6028                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6029                                         }
6030                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6031                                 }
6032                                 continue;
6033                         }
6034                         
6035                         // faster than result <- left, anl result,right
6036                         // and better if result is SFR
6037                         if (AOP_TYPE(left) == AOP_ACC) {
6038                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6039                         } else {
6040                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6041                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6042                         }
6043                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6044                 }
6045         }
6046
6047 release :
6048         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6049         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6050         freeAsmop(result,NULL,ic,TRUE);     
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* genXor - code for xclusive or                                   */
6055 /*-----------------------------------------------------------------*/
6056 static void genXor (iCode *ic, iCode *ifx)
6057 {
6058         operand *left, *right, *result;
6059         int size, offset=0;
6060         unsigned long lit = 0L;
6061         
6062         FENTRY;
6063         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6064         
6065         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6066         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6067         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6068         
6069         /* if left is a literal & right is not ||
6070         if left needs acc & right does not */
6071         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6072                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6073                 operand *tmp = right ;
6074                 right = left;
6075                 left = tmp;
6076         }
6077         
6078         /* if result = right then exchange them */
6079         if(pic14_sameRegs(AOP(result),AOP(right))){
6080                 operand *tmp = right ;
6081                 right = left;
6082                 left = tmp;
6083         }
6084         
6085         /* if right is bit then exchange them */
6086         if (AOP_TYPE(right) == AOP_CRY &&
6087                 AOP_TYPE(left) != AOP_CRY){
6088                 operand *tmp = right ;
6089                 right = left;
6090                 left = tmp;
6091         }
6092         if(AOP_TYPE(right) == AOP_LIT)
6093                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6094         
6095         size = AOP_SIZE(result);
6096         
6097         // if(bit ^ yy)
6098         // xx = bit ^ yy;
6099         if (AOP_TYPE(left) == AOP_CRY){
6100                 if(AOP_TYPE(right) == AOP_LIT){
6101                         // c = bit & literal;
6102                         if(lit>>1){
6103                                 // lit>>1  != 0 => result = 1
6104                                 if(AOP_TYPE(result) == AOP_CRY){
6105                                         if(size)
6106                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6107                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6108                                         else if(ifx)
6109                                                 continueIfTrue(ifx);
6110                                         goto release;
6111                                 }
6112                                 pic14_emitcode("setb","c");
6113                         } else{
6114                                 // lit == (0 or 1)
6115                                 if(lit == 0){
6116                                         // lit == 0, result = left
6117                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6118                                                 goto release;
6119                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6120                                 } else{
6121                                         // lit == 1, result = not(left)
6122                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6123                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6124                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6125                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6126                                                 goto release;
6127                                         } else {
6128                                                 assert ( !"incomplete genXor" );
6129                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6130                                                 pic14_emitcode("cpl","c");
6131                                         }
6132                                 }
6133                         }
6134                         
6135                 } else {
6136                         // right != literal
6137                         symbol *tlbl = newiTempLabel(NULL);
6138                         if (AOP_TYPE(right) == AOP_CRY){
6139                                 // c = bit ^ bit;
6140                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6141                         }
6142                         else{
6143                                 int sizer = AOP_SIZE(right);
6144                                 // c = bit ^ val
6145                                 // if val>>1 != 0, result = 1
6146                                 pic14_emitcode("setb","c");
6147                                 while(sizer){
6148                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6149                                         if(sizer == 1)
6150                                                 // test the msb of the lsb
6151                                                 pic14_emitcode("anl","a,#0xfe");
6152                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6153                                         sizer--;
6154                                 }
6155                                 // val = (0,1)
6156                                 pic14_emitcode("rrc","a");
6157                         }
6158                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6159                         pic14_emitcode("cpl","c");
6160                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6161                 }
6162                 // bit = c
6163                 // val = c
6164                 if(size)
6165                         pic14_outBitC(result);
6166                 // if(bit | ...)
6167                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6168                         genIfxJump(ifx, "c");           
6169                 goto release ;
6170         }
6171         
6172         if(pic14_sameRegs(AOP(result),AOP(left))){
6173                 /* if left is same as result */
6174                 for(;size--; offset++) {
6175                         if(AOP_TYPE(right) == AOP_LIT){
6176                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6177                                 if(t == 0x00L)
6178                                         continue;
6179                                 else
6180                                         if (IS_AOP_PREG(left)) {
6181                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6182                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6183                                                 aopPut(AOP(result),"a",offset);
6184                                         } else {
6185                                                 emitpcode(POC_MOVLW, popGetLit(t));
6186                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6187                                                 pic14_emitcode("xrl","%s,%s",
6188                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6189                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6190                                         }
6191                         } else {
6192                                 if (AOP_TYPE(left) == AOP_ACC)
6193                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6194                                 else {
6195                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6196                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6197                                         /*
6198                                         if (IS_AOP_PREG(left)) {
6199                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6200                                         aopPut(AOP(result),"a",offset);
6201                                         } else
6202                                         pic14_emitcode("xrl","%s,a",
6203                                         aopGet(AOP(left),offset,FALSE,TRUE));
6204                                         */
6205                                 }
6206                         }
6207                 }
6208         } else {
6209                 // left & result in different registers
6210                 if(AOP_TYPE(result) == AOP_CRY){
6211                         // result = bit
6212                         // if(size), result in bit
6213                         // if(!size && ifx), conditional oper: if(left ^ right)
6214                         symbol *tlbl = newiTempLabel(NULL);
6215                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6216                         if(size)
6217                                 pic14_emitcode("setb","c");
6218                         while(sizer--){
6219                                 if((AOP_TYPE(right) == AOP_LIT) &&
6220                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6221                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6222                                 } else {
6223                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6224                                         pic14_emitcode("xrl","a,%s",
6225                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6226                                 }
6227                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6228                                 offset++;
6229                         }
6230                         if(size){
6231                                 CLRC;
6232                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6233                                 pic14_outBitC(result);
6234                         } else if(ifx)
6235                                 jmpTrueOrFalse(ifx, tlbl);
6236                 } else for(;(size--);offset++){
6237                         // normal case
6238                         // result = left & right
6239                         if(AOP_TYPE(right) == AOP_LIT){
6240                                 int t = (lit >> (offset*8)) & 0x0FFL;
6241                                 switch(t) { 
6242                                 case 0x00:
6243                                         if (AOP_TYPE(left) != AOP_ACC) {
6244                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6245                                         }
6246                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6247                                         pic14_emitcode("movf","%s,w",
6248                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6249                                         pic14_emitcode("movwf","%s",
6250                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6251                                         break;
6252                                 case 0xff:
6253                                         if (AOP_TYPE(left) == AOP_ACC) {
6254                                                 emitpcode(POC_XORLW, popGetLit(t));
6255                                         } else {
6256                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6257                                         }
6258                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6259                                         break;
6260                                 default:
6261                                         if (AOP_TYPE(left) == AOP_ACC) {
6262                                                 emitpcode(POC_XORLW, popGetLit(t));
6263                                         } else {
6264                                                 emitpcode(POC_MOVLW, popGetLit(t));
6265                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6266                                         }
6267                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6268                                         pic14_emitcode("movlw","0x%x",t);
6269                                         pic14_emitcode("xorwf","%s,w",
6270                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6271                                         pic14_emitcode("movwf","%s",
6272                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6273                                         
6274                                 }
6275                                 continue;
6276                         }
6277                         
6278                         // faster than result <- left, anl result,right
6279                         // and better if result is SFR
6280                         if (AOP_TYPE(left) == AOP_ACC) {
6281                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6282                         } else {
6283                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6284                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6285                         }
6286                         if ( AOP_TYPE(result) != AOP_ACC){
6287                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6288                         }
6289                 }
6290         }
6291         
6292 release :
6293         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6294         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295         freeAsmop(result,NULL,ic,TRUE);     
6296 }
6297
6298 /*-----------------------------------------------------------------*/
6299 /* genInline - write the inline code out                           */
6300 /*-----------------------------------------------------------------*/
6301 static void genInline (iCode *ic)
6302 {
6303   char *buffer, *bp, *bp1;
6304
6305   FENTRY;
6306   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6307
6308   _G.inLine += (!options.asmpeep);
6309
6310   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6311   strcpy(buffer,IC_INLINE(ic));
6312
6313   /* emit each line as a code */
6314   while (*bp) {
6315     if (*bp == '\n') {
6316       *bp++ = '\0';
6317       
6318       if(*bp1)
6319         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6320       bp1 = bp;
6321     } else {
6322       if (*bp == ':') {
6323         bp++;
6324         *bp = '\0';
6325         bp++;
6326
6327         /* print label, use this special format with NULL directive
6328          * to denote that the argument should not be indented with tab */
6329         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6330
6331         bp1 = bp;
6332       } else
6333         bp++;
6334     }
6335   }
6336   if ((bp1 != bp) && *bp1)
6337     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6338
6339   Safe_free(buffer);
6340
6341   _G.inLine -= (!options.asmpeep);
6342 }
6343
6344 /*-----------------------------------------------------------------*/
6345 /* genRRC - rotate right with carry                                */
6346 /*-----------------------------------------------------------------*/
6347 static void genRRC (iCode *ic)
6348 {
6349         operand *left , *result ;
6350         int size, offset = 0, same;
6351         
6352         FENTRY;
6353         /* rotate right with carry */
6354         left = IC_LEFT(ic);
6355         result=IC_RESULT(ic);
6356         aopOp (left,ic,FALSE);
6357         aopOp (result,ic,FALSE);
6358         
6359         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6360         
6361         same = pic14_sameRegs(AOP(result),AOP(left));
6362         
6363         size = AOP_SIZE(result);    
6364         
6365         /* get the lsb and put it into the carry */
6366         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6367         
6368         offset = 0 ;
6369         
6370         while(size--) {
6371                 
6372                 if(same) {
6373                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6374                 } else {
6375                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6376                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6377                 }
6378                 
6379                 offset++;
6380         }
6381         
6382         freeAsmop(left,NULL,ic,TRUE);
6383         freeAsmop(result,NULL,ic,TRUE);
6384 }
6385
6386 /*-----------------------------------------------------------------*/
6387 /* genRLC - generate code for rotate left with carry               */
6388 /*-----------------------------------------------------------------*/
6389 static void genRLC (iCode *ic)
6390 {    
6391         operand *left , *result ;
6392         int size, offset = 0;
6393         int same;
6394         
6395         FENTRY;
6396         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6397         /* rotate right with carry */
6398         left = IC_LEFT(ic);
6399         result=IC_RESULT(ic);
6400         aopOp (left,ic,FALSE);
6401         aopOp (result,ic,FALSE);
6402         
6403         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6404         
6405         same = pic14_sameRegs(AOP(result),AOP(left));
6406         
6407         /* move it to the result */
6408         size = AOP_SIZE(result);    
6409         
6410         /* get the msb and put it into the carry */
6411         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6412         
6413         offset = 0 ;
6414         
6415         while(size--) {
6416                 
6417                 if(same) {
6418                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6419                 } else {
6420                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6421                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6422                 }
6423                 
6424                 offset++;
6425         }
6426         
6427         
6428         freeAsmop(left,NULL,ic,TRUE);
6429         freeAsmop(result,NULL,ic,TRUE);
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* genGetHbit - generates code get highest order bit               */
6434 /*-----------------------------------------------------------------*/
6435 static void genGetHbit (iCode *ic)
6436 {
6437         operand *left, *result;
6438         left = IC_LEFT(ic);
6439         result=IC_RESULT(ic);
6440         aopOp (left,ic,FALSE);
6441         aopOp (result,ic,FALSE);
6442         
6443         FENTRY;
6444         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6445         /* get the highest order byte into a */
6446         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6447         if(AOP_TYPE(result) == AOP_CRY){
6448                 pic14_emitcode("rlc","a");
6449                 pic14_outBitC(result);
6450         }
6451         else{
6452                 pic14_emitcode("rl","a");
6453                 pic14_emitcode("anl","a,#0x01");
6454                 pic14_outAcc(result);
6455         }
6456         
6457         
6458         freeAsmop(left,NULL,ic,TRUE);
6459         freeAsmop(result,NULL,ic,TRUE);
6460 }
6461
6462 /*-----------------------------------------------------------------*/
6463 /* AccLsh - shift left accumulator by known count                  */
6464 /* MARK: pic14 always rotates through CARRY!                       */
6465 /*-----------------------------------------------------------------*/
6466 static void AccLsh (pCodeOp *pcop,int shCount)
6467 {
6468         FENTRY;
6469         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6470         shCount &= 0x0007;              // shCount : 0..7
6471         switch(shCount){
6472         case 0 :
6473                 return;
6474                 break;
6475         case 1 :
6476                 emitCLRC;
6477                 emitpcode(POC_RLF,pcop);
6478                 return;
6479                 break;
6480         case 2 :
6481                 emitpcode(POC_RLF,pcop);
6482                 emitpcode(POC_RLF,pcop);
6483                 break;
6484         case 3 :
6485                 emitpcode(POC_RLF,pcop);
6486                 emitpcode(POC_RLF,pcop);
6487                 emitpcode(POC_RLF,pcop);
6488                 break;
6489         case 4 :
6490                 emitpcode(POC_SWAPF,pcop);
6491                 break;
6492         case 5 :
6493                 emitpcode(POC_SWAPF,pcop);
6494                 emitpcode(POC_RLF,pcop);
6495                 break;
6496         case 6 :
6497                 emitpcode(POC_SWAPF,pcop);
6498                 emitpcode(POC_RLF,pcop);
6499                 emitpcode(POC_RLF,pcop);
6500                 break;
6501         case 7 :
6502                 emitpcode(POC_RRFW,pcop);
6503                 emitpcode(POC_RRF,pcop);
6504                 break;
6505         }
6506         /* clear invalid bits */
6507         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6508         emitpcode(POC_ANDWF, pcop);
6509 }
6510
6511 /*-----------------------------------------------------------------*/
6512 /* AccRsh - shift right accumulator by known count                 */
6513 /* MARK: pic14 always rotates through CARRY!                       */
6514 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6515 /*            1: mask out invalid bits (zero-extend)               */
6516 /*            2: sign-extend result (pretty slow)                  */
6517 /*-----------------------------------------------------------------*/
6518 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6519 {
6520         FENTRY;
6521         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6522         shCount &= 0x0007;              // shCount : 0..7
6523         switch(shCount){
6524         case 0 :
6525                 return;
6526                 break;
6527         case 1 :
6528                 /* load sign if needed */
6529                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6530                 else if (mask_mode == 1) emitCLRC;
6531                 emitpcode(POC_RRF,pcop);
6532                 return;
6533                 break;
6534         case 2 :
6535                 /* load sign if needed */
6536                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6537                 emitpcode(POC_RRF,pcop);
6538                 /* load sign if needed */
6539                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6540                 emitpcode(POC_RRF,pcop);
6541                 if (mask_mode == 2) return;
6542                 break;
6543         case 3 :
6544                 /* load sign if needed */
6545                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6546                 emitpcode(POC_RRF,pcop);
6547                 /* load sign if needed */
6548                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6549                 emitpcode(POC_RRF,pcop);
6550                 /* load sign if needed */
6551                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552                 emitpcode(POC_RRF,pcop);
6553                 if (mask_mode == 2) return;
6554                 break;
6555         case 4 :
6556                 emitpcode(POC_SWAPF,pcop);
6557                 break;
6558         case 5 :
6559                 emitpcode(POC_SWAPF,pcop);
6560                 emitpcode(POC_RRF,pcop);
6561                 break;
6562         case 6 :
6563                 emitpcode(POC_SWAPF,pcop);
6564                 emitpcode(POC_RRF,pcop);
6565                 emitpcode(POC_RRF,pcop);
6566                 break;
6567         case 7 :
6568                 if (mask_mode == 2)
6569                 {
6570                         /* load sign */
6571                         emitpcode(POC_RLFW,pcop);
6572                         emitpcode(POC_CLRF,pcop);
6573                         emitSKPNC;
6574                         emitpcode(POC_COMF,pcop);
6575                         return;
6576                 } else {
6577                         emitpcode(POC_RLFW,pcop);
6578                         emitpcode(POC_RLF,pcop);
6579                 }
6580                 break;
6581         }
6582
6583         if (mask_mode == 0)
6584         {
6585                 /* leave invalid bits undefined */
6586                 return;
6587         }
6588         
6589         /* clear invalid bits -- zero-extend */
6590         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6591         emitpcode(POC_ANDWF, pcop);
6592
6593         if (mask_mode == 2) {
6594           /* sign-extend */
6595           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6596           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6597           emitpcode(POC_IORWF, pcop);
6598         }
6599 }
6600
6601 #if 0
6602 /*-----------------------------------------------------------------*/
6603 /* AccSRsh - signed right shift accumulator by known count                 */
6604 /*-----------------------------------------------------------------*/
6605 static void AccSRsh (int shCount)
6606 {
6607         symbol *tlbl ;
6608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6609         if(shCount != 0){
6610                 if(shCount == 1){
6611                         pic14_emitcode("mov","c,acc.7");
6612                         pic14_emitcode("rrc","a");
6613                 } else if(shCount == 2){
6614                         pic14_emitcode("mov","c,acc.7");
6615                         pic14_emitcode("rrc","a");
6616                         pic14_emitcode("mov","c,acc.7");
6617                         pic14_emitcode("rrc","a");
6618                 } else {
6619                         tlbl = newiTempLabel(NULL);
6620                         /* rotate right accumulator */
6621                         AccRol(8 - shCount);
6622                         /* and kill the higher order bits */
6623                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6624                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6625                         pic14_emitcode("orl","a,#0x%02x",
6626                                 (unsigned char)~SRMask[shCount]);
6627                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6628                 }
6629         }
6630 }
6631
6632 /*-----------------------------------------------------------------*/
6633 /* shiftR1Left2Result - shift right one byte from left to result   */
6634 /*-----------------------------------------------------------------*/
6635 static void shiftR1Left2ResultSigned (operand *left, int offl,
6636                                                                           operand *result, int offr,
6637                                                                           int shCount)
6638 {
6639         int same;
6640         
6641         FENTRY;
6642         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6643         
6644         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6645         
6646         switch(shCount) {
6647         case 1:
6648                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6649                 if(same) 
6650                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6651                 else {
6652                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6653                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6654                 }
6655                 
6656                 break;
6657         case 2:
6658                 
6659                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6660                 if(same) 
6661                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6662                 else {
6663                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6664                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6665                 }
6666                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6667                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6668                 
6669                 break;
6670                 
6671         case 3:
6672                 if(same)
6673                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6674                 else {
6675                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6676                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6677                 }
6678                 
6679                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6680                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6681                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6682                 
6683                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6684                 emitpcode(POC_IORLW, popGetLit(0xe0));
6685                 
6686                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6687                 break;
6688                 
6689         case 4:
6690                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6691                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6692                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6693                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6694                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6695                 break;
6696         case 5:
6697                 if(same) {
6698                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6699                 } else {
6700                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6701                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6702                 }
6703                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6704                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6705                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6706                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6707                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6708                 break;
6709                 
6710         case 6:
6711                 if(same) {
6712                         emitpcode(POC_MOVLW, popGetLit(0x00));
6713                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6714                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6715                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6716                         emitpcode(POC_IORLW, popGetLit(0x01));
6717                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6718                 } else {
6719                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6720                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6721                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6722                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6723                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6724                 }
6725                 break;
6726                 
6727         case 7:
6728                 if(same) {
6729                         emitpcode(POC_MOVLW, popGetLit(0x00));
6730                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6731                         emitpcode(POC_MOVLW, popGetLit(0xff));
6732                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733                 } else {
6734                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6735                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6736                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6737                 }
6738                 
6739         default:
6740                 break;
6741         }
6742 }
6743
6744 /*-----------------------------------------------------------------*/
6745 /* shiftR1Left2Result - shift right one byte from left to result   */
6746 /*-----------------------------------------------------------------*/
6747 static void shiftR1Left2Result (operand *left, int offl,
6748                                                                 operand *result, int offr,
6749                                                                 int shCount, int sign)
6750 {
6751         int same;
6752         
6753         FENTRY;
6754         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6755         
6756         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6757         
6758         /* Copy the msb into the carry if signed. */
6759         if(sign) {
6760                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6761                 return;
6762         }
6763         
6764         
6765         
6766         switch(shCount) {
6767         case 1:
6768                 emitCLRC;
6769                 if(same) 
6770                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6771                 else {
6772                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6773                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6774                 }
6775                 break;
6776         case 2:
6777                 emitCLRC;
6778                 if(same) {
6779                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6780                 } else {
6781                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6782                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6783                 }
6784                 emitCLRC;
6785                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6786                 
6787                 break;
6788         case 3:
6789                 if(same)
6790                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6791                 else {
6792                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6793                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6794                 }
6795                 
6796                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6797                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6798                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6799                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6800                 break;
6801                 
6802         case 4:
6803                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6804                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6805                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6806                 break;
6807                 
6808         case 5:
6809                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6810                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6811                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6812                 emitCLRC;
6813                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6814                 
6815                 break;
6816         case 6:
6817                 
6818                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6819                 emitpcode(POC_ANDLW, popGetLit(0x80));
6820                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6822                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6823                 break;
6824                 
6825         case 7:
6826                 
6827                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6828                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6829                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6830                 
6831                 break;
6832                 
6833         default:
6834                 break;
6835         }
6836 }
6837
6838 /*-----------------------------------------------------------------*/
6839 /* shiftL1Left2Result - shift left one byte from left to result    */
6840 /*-----------------------------------------------------------------*/
6841 static void shiftL1Left2Result (operand *left, int offl,
6842                                                                 operand *result, int offr, int shCount)
6843 {
6844         int same;
6845         
6846         //    char *l;
6847         FENTRY;
6848         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6849         
6850         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6851         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6852         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6853         //    MOVA(l);
6854         /* shift left accumulator */
6855         //AccLsh(shCount); // don't comment out just yet...
6856         //    aopPut(AOP(result),"a",offr);
6857         
6858         switch(shCount) {
6859         case 1:
6860                 /* Shift left 1 bit position */
6861                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6862                 if(same) {
6863                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6864                 } else {
6865                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6866                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6867                 }
6868                 break;
6869         case 2:
6870                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6871                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6872                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6873                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6874                 break;
6875         case 3:
6876                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6878                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6879                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6880                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6881                 break;
6882         case 4:
6883                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6884                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6885                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6886                 break;
6887         case 5:
6888                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6889                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6890                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6891                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6892                 break;
6893         case 6:
6894                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6895                 emitpcode(POC_ANDLW, popGetLit(0x30));
6896                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6897                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6898                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6899                 break;
6900         case 7:
6901                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6902                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6903                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6904                 break;
6905                 
6906         default:
6907                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6908         }
6909         
6910 }
6911 #endif
6912
6913 /*-----------------------------------------------------------------*/
6914 /* movLeft2Result - move byte from left to result                  */
6915 /*-----------------------------------------------------------------*/
6916 static void movLeft2Result (operand *left, int offl,
6917                                                         operand *result, int offr)
6918 {
6919         char *l;
6920         FENTRY;
6921         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6922         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6923                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6924                 
6925                 if (*l == '@' && (IS_AOP_PREG(result))) {
6926                         pic14_emitcode("mov","a,%s",l);
6927                         aopPut(AOP(result),"a",offr);
6928                 } else {
6929                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6930                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6931                 }
6932         }
6933 }
6934
6935 /*-----------------------------------------------------------------*/
6936 /* shiftLeft_Left2ResultLit - shift left by known count            */
6937 /*-----------------------------------------------------------------*/
6938
6939 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6940 {
6941         int size, same, offr, i;
6942
6943         size = AOP_SIZE(left);
6944         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6945         
6946         same = pic14_sameRegs (AOP(left), AOP(result));
6947         
6948         offr = shCount / 8;
6949         shCount = shCount & 0x07;
6950
6951         size -= offr;
6952
6953         switch (shCount)
6954         {
6955         case 0: /* takes 0 or 2N cycles (for offr==0) */
6956                 if (!same || offr) {
6957                         for (i=size-1; i >= 0; i--)
6958                                 movLeft2Result (left, i, result, offr + i);
6959                 } // if
6960                 break;
6961                 
6962         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6963                 if (same && offr) {
6964                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6965                         shiftLeft_Left2ResultLit (result, result, shCount);
6966                         return; /* prevent clearing result again */
6967                 } else {
6968                         emitCLRC;
6969                         for (i=0; i < size; i++) {
6970                                 if (same && !offr) {
6971                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6972                                 } else {
6973                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6974                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6975                                 } // if
6976                         } // for
6977                 } // if (offr)
6978                 break;
6979                 
6980         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6981                 /* works in-place/with offr as well */
6982                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6983                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6984                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6985
6986                 for (i = size - 2; i >= 0; i--)
6987                 {
6988                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6989                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6990                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6991                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6992                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6993                 } // for i
6994                 break;
6995                 
6996         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6997                 /* works in-place/with offr as well */
6998                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6999                 for (i = size-2; i >= 0; i--) {
7000                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7001                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7002                 } // for i
7003                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7004                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7005                 break;
7006         
7007         default:
7008                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7009                 shiftLeft_Left2ResultLit (result, result, 1);
7010                 return; /* prevent clearing result again */
7011                 break;
7012         } // switch
7013
7014         while (0 < offr--)
7015         {
7016                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7017         } // while
7018 }
7019
7020 /*-----------------------------------------------------------------*/
7021 /* shiftRight_Left2ResultLit - shift right by known count          */
7022 /*-----------------------------------------------------------------*/
7023
7024 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7025 {
7026         int size, same, offr, i;
7027
7028         size = AOP_SIZE(left);
7029         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7030         
7031         same = pic14_sameRegs (AOP(left), AOP(result));
7032         
7033         offr = shCount / 8;
7034         shCount = shCount & 0x07;
7035
7036         size -= offr;
7037
7038         if (size)
7039         {
7040                 switch (shCount)
7041                 {
7042                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7043                         if (!same || offr) {
7044                                 for (i=0; i < size; i++)
7045                                         movLeft2Result (left, i + offr, result, i);
7046                         } // if
7047                         break;
7048                         
7049                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7050                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7051                         if (same && offr) {
7052                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7053                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7054                                 return; /* prevent sign-extending result again */
7055                         } else {
7056                                 emitCLRC;
7057                                 if (sign) {
7058                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7059                                         emitSETC;
7060                                 }
7061                                 for (i = size-1; i >= 0; i--) {
7062                                         if (same && !offr) {
7063                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7064                                         } else {
7065                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7066                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7067                                         }
7068                                 } // for i
7069                         } // if (offr)
7070                         break;
7071                         
7072                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7073                         /* works in-place/with offr as well */
7074                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7075                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7076                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7077
7078                         for (i = 1; i < size; i++)
7079                         {
7080                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7081                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7082                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7083                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7084                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7085                         } // for i
7086
7087                         if (sign)
7088                         {
7089                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7090                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7091                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7092                         } // if
7093                         break;
7094                         
7095                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7096                         /* works in-place/with offr as well */
7097                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7098                         for (i = 0; i < size-1; i++) {
7099                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7100                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7101                         } // for i
7102                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7103                         if (!sign) {
7104                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7105                         } else {
7106                                 emitSKPNC;
7107                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7108                         }
7109                         break;
7110                 
7111                 default:
7112                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7113                         shiftRight_Left2ResultLit (result, result, 1, sign);
7114                         return; /* prevent sign extending result again */
7115                         break;
7116                 } // switch
7117         } // if
7118
7119         addSign (result, size, sign);
7120 }
7121
7122 #if 0
7123 /*-----------------------------------------------------------------*/
7124 /* shiftL2Left2Result - shift left two bytes from left to result   */
7125 /*-----------------------------------------------------------------*/
7126 static void shiftL2Left2Result (operand *left, int offl,
7127                                                                 operand *result, int offr, int shCount)
7128 {
7129         FENTRY;
7130         
7131         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7132         
7133         if(pic14_sameRegs(AOP(result), AOP(left))) {
7134                 switch(shCount) {
7135                 case 0:
7136                         break;
7137                 case 1:
7138                 case 2:
7139                 case 3:
7140                         
7141                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7142                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7143                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7144                         
7145                         while(--shCount) {
7146                                 emitCLRC;
7147                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7148                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7149                         }
7150                         
7151                         break;
7152                 case 4:
7153                 case 5:
7154                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7155                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7156                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7157                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7158                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7159                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7160                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7161                         if(shCount >=5) {
7162                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7163                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7164                         }
7165                         break;
7166                 case 6:
7167                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7168                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7169                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7170                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7171                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7172                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7173                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7174                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7175                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7176                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7177                         break;
7178                 case 7:
7179                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7180                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7181                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7182                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7183                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7184                 }
7185                 
7186         } else {
7187                 switch(shCount) {
7188                 case 0:
7189                         break;
7190                 case 1:
7191                 case 2:
7192                 case 3:
7193                 /* note, use a mov/add for the shift since the mov has a
7194                         chance of getting optimized out */
7195                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7196                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7197                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7198                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7199                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7200                         
7201                         while(--shCount) {
7202                                 emitCLRC;
7203                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7204                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7205                         }
7206                         break;
7207                         
7208                 case 4:
7209                 case 5:
7210                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7211                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7212                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7213                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7214                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7215                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7216                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7217                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7218                         
7219                         
7220                         if(shCount == 5) {
7221                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7222                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7223                         }
7224                         break;
7225                 case 6:
7226                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7227                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7228                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7229                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7230                         
7231                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7232                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7233                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7234                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7235                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7236                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7237                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7238                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7239                         break;
7240                 case 7:
7241                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7242                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7243                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7244                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7245                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7246                 }
7247         }
7248         
7249 }
7250
7251 /*-----------------------------------------------------------------*/
7252 /* shiftR2Left2Result - shift right two bytes from left to result  */
7253 /*-----------------------------------------------------------------*/
7254 static void shiftR2Left2Result (operand *left, int offl,
7255                                                                 operand *result, int offr,
7256                                                                 int shCount, int sign)
7257 {
7258         int same=0;
7259         
7260         FENTRY;
7261         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7262         same = pic14_sameRegs(AOP(result), AOP(left));
7263         
7264         if(same && ((offl + MSB16) == offr)){
7265                 same=1;
7266                 /* don't crash result[offr] */
7267                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7268                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7269         }
7270         /* else {
7271         movLeft2Result(left,offl, result, offr);
7272         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7273         }
7274         */
7275         /* a:x >> shCount (x = lsb(result))*/
7276         /*
7277         if(sign)
7278         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7279         else {
7280         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7281         */
7282         switch(shCount) {
7283         case 0:
7284                 break;
7285         case 1:
7286         case 2:
7287         case 3:
7288                 if(sign)
7289                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7290                 else
7291                         emitCLRC;
7292                 
7293                 if(same) {
7294                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7295                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7296                 } else {
7297                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7298                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7299                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7300                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7301                 }
7302                 
7303                 while(--shCount) {
7304                         if(sign)
7305                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7306                         else
7307                                 emitCLRC;
7308                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7309                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7310                 }
7311                 break;
7312         case 4:
7313         case 5:
7314                 if(same) {
7315                         
7316                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7317                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7318                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7319                         
7320                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7321                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7322                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7323                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7324                 } else {
7325                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7326                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7327                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7328                         
7329                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7330                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7331                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7332                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7333                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7334                 }
7335                 
7336                 if(shCount >=5) {
7337                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7338                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7339                 }
7340                 
7341                 if(sign) {
7342                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7343                         emitpcode(POC_BTFSC, 
7344                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7345                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7346                 }
7347                 
7348                 break;
7349                 
7350         case 6:
7351                 if(same) {
7352                         
7353                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7354                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7355                         
7356                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7357                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7358                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7359                         emitpcode(POC_ANDLW,popGetLit(0x03));
7360                         if(sign) {
7361                                 emitpcode(POC_BTFSC, 
7362                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7363                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7364                         }
7365                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7366                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7367                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7368                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7369                 } else {
7370                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7371                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7372                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7373                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7374                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7375                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7376                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7377                         emitpcode(POC_ANDLW,popGetLit(0x03));
7378                         if(sign) {
7379                                 emitpcode(POC_BTFSC, 
7380                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7381                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7382                         }
7383                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7384                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7385                         
7386                         
7387                 }
7388                 
7389                 break;
7390         case 7:
7391                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7392                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7393                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7394                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7395                 if(sign) {
7396                         emitSKPNC;
7397                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7398                 } else 
7399                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7400   }
7401 }
7402
7403 /*-----------------------------------------------------------------*/
7404 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7405 /*-----------------------------------------------------------------*/
7406 static void shiftLLeftOrResult (operand *left, int offl,
7407                                                                 operand *result, int offr, int shCount)
7408 {
7409         FENTRY;
7410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7411         
7412         /* shift left accumulator */
7413         AccLsh(left,offl,shCount);
7414         /* or with result */
7415         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7416         assert ( !"broken (modifies left, fails for left==result))" );
7417 }
7418
7419 /*-----------------------------------------------------------------*/
7420 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7421 /*-----------------------------------------------------------------*/
7422 static void shiftRLeftOrResult (operand *left, int offl,
7423                                                                 operand *result, int offr, int shCount)
7424 {
7425         FENTRY;
7426         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7427         
7428         /* shift right accumulator */
7429         AccRsh(left,offl,shCount);
7430         /* or with result */
7431         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7432         assert ( !"broken (modifies left, fails for left==result))" );
7433 }
7434
7435 /*-----------------------------------------------------------------*/
7436 /* genlshOne - left shift a one byte quantity by known count       */
7437 /*-----------------------------------------------------------------*/
7438 static void genlshOne (operand *result, operand *left, int shCount)
7439 {       
7440         FENTRY;
7441         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7442         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genlshTwo - left shift two bytes by known amount != 0           */
7447 /*-----------------------------------------------------------------*/
7448 static void genlshTwo (operand *result,operand *left, int shCount)
7449 {
7450         int size;
7451         
7452         FENTRY;
7453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7454         size = pic14_getDataSize(result);
7455         
7456         /* if shCount >= 8 */
7457         if (shCount >= 8) {
7458                 shCount -= 8 ;
7459                 
7460                 if (size > 1){
7461                         if (shCount)
7462                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7463                         else 
7464                                 movLeft2Result(left, LSB, result, MSB16);
7465                 }
7466                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7467         }
7468         
7469         /*  1 <= shCount <= 7 */
7470         else {  
7471                 if(size == 1)
7472                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7473                 else 
7474                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7475         }
7476 }
7477
7478 /*-----------------------------------------------------------------*/
7479 /* shiftLLong - shift left one long from left to result            */
7480 /* offl = LSB or MSB16                                             */
7481 /*-----------------------------------------------------------------*/
7482 static void shiftLLong (operand *left, operand *result, int offr )
7483 {
7484         char *l;
7485         int size = AOP_SIZE(result);
7486         
7487         FENTRY;
7488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7489         if(size >= LSB+offr){
7490                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7491                 MOVA(l);
7492                 pic14_emitcode("add","a,acc");
7493                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7494                         size >= MSB16+offr && offr != LSB )
7495                         pic14_emitcode("xch","a,%s",
7496                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7497                 else      
7498                         aopPut(AOP(result),"a",LSB+offr);
7499         }
7500         
7501         if(size >= MSB16+offr){
7502                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7503                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7504                         MOVA(l);
7505                 }
7506                 pic14_emitcode("rlc","a");
7507                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7508                         size >= MSB24+offr && offr != LSB)
7509                         pic14_emitcode("xch","a,%s",
7510                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7511                 else      
7512                         aopPut(AOP(result),"a",MSB16+offr);
7513         }
7514         
7515         if(size >= MSB24+offr){
7516                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7517                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7518                         MOVA(l);
7519                 }
7520                 pic14_emitcode("rlc","a");
7521                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7522                         size >= MSB32+offr && offr != LSB )
7523                         pic14_emitcode("xch","a,%s",
7524                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7525                 else      
7526                         aopPut(AOP(result),"a",MSB24+offr);
7527         }
7528         
7529         if(size > MSB32+offr){
7530                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7531                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7532                         MOVA(l);  
7533                 }
7534                 pic14_emitcode("rlc","a");
7535                 aopPut(AOP(result),"a",MSB32+offr);
7536         }
7537         if(offr != LSB)
7538                 aopPut(AOP(result),zero,LSB);       
7539 }
7540
7541 /*-----------------------------------------------------------------*/
7542 /* genlshFour - shift four byte by a known amount != 0             */
7543 /*-----------------------------------------------------------------*/
7544 static void genlshFour (operand *result, operand *left, int shCount)
7545 {
7546         int size;
7547         
7548         FENTRY;
7549         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7550         size = AOP_SIZE(result);
7551         
7552         /* if shifting more that 3 bytes */
7553         if (shCount >= 24 ) {
7554                 shCount -= 24;
7555                 if (shCount)
7556                 /* lowest order of left goes to the highest
7557                 order of the destination */
7558                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7559                 else
7560                         movLeft2Result(left, LSB, result, MSB32);
7561                 aopPut(AOP(result),zero,LSB);
7562                 aopPut(AOP(result),zero,MSB16);
7563                 aopPut(AOP(result),zero,MSB32);
7564                 return;
7565         }
7566         
7567         /* more than two bytes */
7568         else if ( shCount >= 16 ) {
7569                 /* lower order two bytes goes to higher order two bytes */
7570                 shCount -= 16;
7571                 /* if some more remaining */
7572                 if (shCount)
7573                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7574                 else {
7575                         movLeft2Result(left, MSB16, result, MSB32);
7576                         movLeft2Result(left, LSB, result, MSB24);
7577                 }
7578                 aopPut(AOP(result),zero,MSB16);
7579                 aopPut(AOP(result),zero,LSB);
7580                 return;
7581         }    
7582         
7583         /* if more than 1 byte */
7584         else if ( shCount >= 8 ) {
7585                 /* lower order three bytes goes to higher order  three bytes */
7586                 shCount -= 8;
7587                 if(size == 2){
7588                         if(shCount)
7589                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7590                         else
7591                                 movLeft2Result(left, LSB, result, MSB16);
7592                 }
7593                 else{   /* size = 4 */
7594                         if(shCount == 0){
7595                                 movLeft2Result(left, MSB24, result, MSB32);
7596                                 movLeft2Result(left, MSB16, result, MSB24);
7597                                 movLeft2Result(left, LSB, result, MSB16);
7598                                 aopPut(AOP(result),zero,LSB);
7599                         }
7600                         else if(shCount == 1)
7601                                 shiftLLong(left, result, MSB16);
7602                         else{
7603                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7604                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7605                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7606                                 aopPut(AOP(result),zero,LSB);
7607                         }
7608                 }
7609         }
7610         
7611         /* 1 <= shCount <= 7 */
7612         else if(shCount <= 2){
7613                 shiftLLong(left, result, LSB);
7614                 if(shCount == 2)
7615                         shiftLLong(result, result, LSB);
7616         }
7617         /* 3 <= shCount <= 7, optimize */
7618         else{
7619                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7620                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7621                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7622         }
7623 }
7624 #endif
7625
7626 #if 0
7627 /*-----------------------------------------------------------------*/
7628 /* genLeftShiftLiteral - left shifting by known count              */
7629 /*-----------------------------------------------------------------*/
7630 static void genLeftShiftLiteral (operand *left,
7631                                                                  operand *right,
7632                                                                  operand *result,
7633                                                                  iCode *ic)
7634 {    
7635         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7636         //int size;
7637         
7638         FENTRY;
7639         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7640         freeAsmop(right,NULL,ic,TRUE);
7641         
7642         aopOp(left,ic,FALSE);
7643         aopOp(result,ic,FALSE);
7644
7645         size = getSize(operandType(result));
7646         
7647 #if VIEW_SIZE
7648         pic14_emitcode("; shift left ","result %d, left %d",size,
7649                 AOP_SIZE(left));
7650 #endif
7651         
7652         /* I suppose that the left size >= result size */
7653         if(shCount == 0){
7654                 while(size--){
7655                         movLeft2Result(left, size, result, size);
7656                 }
7657         }
7658         
7659         else if(shCount >= (size * 8))
7660                 while(size--)
7661                         aopPut(AOP(result),zero,size);
7662                 else{
7663                         switch (size) {
7664                         case 1:
7665                                 genlshOne (result,left,shCount);
7666                                 break;
7667                                 
7668                         case 2:
7669                         case 3:
7670                                 genlshTwo (result,left,shCount);
7671                                 break;
7672                                 
7673                         case 4:
7674                                 genlshFour (result,left,shCount);
7675                                 break;
7676                         }
7677                 }
7678                 freeAsmop(left,NULL,ic,TRUE);
7679                 freeAsmop(result,NULL,ic,TRUE);
7680 }
7681 #endif
7682
7683 /*-----------------------------------------------------------------*
7684 * genMultiAsm - repeat assembly instruction for size of register.
7685 * if endian == 1, then the high byte (i.e base address + size of 
7686 * register) is used first else the low byte is used first;
7687 *-----------------------------------------------------------------*/
7688 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7689 {
7690         
7691         int offset = 0;
7692         
7693         FENTRY;
7694         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7695         
7696         if(!reg)
7697                 return;
7698         
7699         if(!endian) {
7700                 endian = 1;
7701         } else {
7702                 endian = -1;
7703                 offset = size-1;
7704         }
7705         
7706         while(size--) {
7707                 emitpcode(poc,    popGet(AOP(reg),offset));
7708                 offset += endian;
7709         }
7710         
7711 }
7712
7713 #if 0
7714 /*-----------------------------------------------------------------*/
7715 /* genLeftShift - generates code for left shifting                 */
7716 /*-----------------------------------------------------------------*/
7717 static void genLeftShift (iCode *ic)
7718 {
7719         operand *left,*right, *result;
7720         int size, offset;
7721         unsigned long lit = 0L;
7722         char *l;
7723         symbol *tlbl , *tlbl1;
7724         pCodeOp *pctemp;
7725         
7726         FENTRY;
7727         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7728         
7729         right = IC_RIGHT(ic);
7730         left  = IC_LEFT(ic);
7731         result = IC_RESULT(ic);
7732         
7733         aopOp(right,ic,FALSE);
7734         aopOp(left,ic,FALSE);
7735         aopOp(result,ic,FALSE);
7736         
7737         
7738         /* if the shift count is known then do it 
7739         as efficiently as possible */
7740         if (AOP_TYPE(right) == AOP_LIT) {
7741                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7742                 return ;
7743         }
7744         
7745         /* shift count is unknown then we have to form 
7746         a loop get the loop count in B : Note: we take
7747         only the lower order byte since shifting
7748         more that 32 bits make no sense anyway, ( the
7749         largest size of an object can be only 32 bits ) */  
7750         
7751         /* this code fails for RIGHT == RESULT */
7752         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7753         
7754         /* now move the left to the result if they are not the
7755         same */
7756         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7757                 AOP_SIZE(result) > 1) {
7758                 
7759                 size = AOP_SIZE(result);
7760                 offset=0;
7761                 while (size--) {
7762                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7763                         if (*l == '@' && (IS_AOP_PREG(result))) {
7764                                 
7765                                 pic14_emitcode("mov","a,%s",l);
7766                                 aopPut(AOP(result),"a",offset);
7767                         } else {
7768                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7769                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7770                                 //aopPut(AOP(result),l,offset);
7771                         }
7772                         offset++;
7773                 }
7774         }
7775         
7776         if(AOP_TYPE(left) == AOP_LIT)
7777                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7778
7779         size = AOP_SIZE(result);
7780         
7781         /* if it is only one byte then */
7782         if (size == 1) {
7783                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7784                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7785                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7786                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7787                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7788                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7789                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7790                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7791                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7792                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7793                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7794                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7795                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7796                 } else {
7797                         
7798                         tlbl = newiTempLabel(NULL);
7799                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7800                                 mov2w (AOP(left), 0);
7801                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7802                         }
7803                         
7804                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7805                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7806                         emitpLabel(tlbl->key);
7807                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7808                         emitpcode(POC_ADDLW,  popGetLit(1));
7809                         emitSKPC;
7810                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7811                 }
7812                 goto release ;
7813         }
7814         
7815         if (pic14_sameRegs(AOP(left),AOP(result))) {
7816                 
7817                 tlbl = newiTempLabel(NULL);
7818                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7819                 genMultiAsm(POC_RRF, result, size,1);
7820                 emitpLabel(tlbl->key);
7821                 genMultiAsm(POC_RLF, result, size,0);
7822                 emitpcode(POC_ADDLW,  popGetLit(1));
7823                 emitSKPC;
7824                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7825                 goto release;
7826         }
7827         
7828         //tlbl = newiTempLabel(NULL);
7829         //offset = 0 ;   
7830         //tlbl1 = newiTempLabel(NULL);
7831         
7832         //reAdjustPreg(AOP(result));    
7833         
7834         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7835         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7836         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7837         //MOVA(l);
7838         //pic14_emitcode("add","a,acc");         
7839         //aopPut(AOP(result),"a",offset++);
7840         //while (--size) {
7841         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7842         //  MOVA(l);
7843         //  pic14_emitcode("rlc","a");         
7844         //  aopPut(AOP(result),"a",offset++);
7845         //}
7846         //reAdjustPreg(AOP(result));
7847         
7848         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7849         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7850         
7851         
7852         tlbl = newiTempLabel(NULL);
7853         tlbl1= newiTempLabel(NULL);
7854         
7855         size = AOP_SIZE(result);
7856         offset = 1;
7857         
7858         pctemp = popGetTempReg();  /* grab a temporary working register. */
7859         
7860         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7861         
7862         /* offset should be 0, 1 or 3 */
7863         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7864         emitSKPNZ;
7865         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7866         
7867         emitpcode(POC_MOVWF, pctemp);
7868         
7869         
7870         emitpLabel(tlbl->key);
7871         
7872         emitCLRC;
7873         emitpcode(POC_RLF,  popGet(AOP(result),0));
7874         while(--size)
7875                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7876         
7877         emitpcode(POC_DECFSZ,  pctemp);
7878         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7879         emitpLabel(tlbl1->key);
7880         
7881         popReleaseTempReg(pctemp);
7882         
7883         
7884 release:
7885         freeAsmop (right,NULL,ic,TRUE);
7886         freeAsmop(left,NULL,ic,TRUE);
7887         freeAsmop(result,NULL,ic,TRUE);
7888 }
7889 #endif
7890
7891 #if 0
7892 /*-----------------------------------------------------------------*/
7893 /* genrshOne - right shift a one byte quantity by known count      */
7894 /*-----------------------------------------------------------------*/
7895 static void genrshOne (operand *result, operand *left,
7896                                            int shCount, int sign)
7897 {
7898         FENTRY;
7899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7900         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7901 }
7902
7903 /*-----------------------------------------------------------------*/
7904 /* genrshTwo - right shift two bytes by known amount != 0          */
7905 /*-----------------------------------------------------------------*/
7906 static void genrshTwo (operand *result,operand *left,
7907                                            int shCount, int sign)
7908 {
7909         FENTRY;
7910         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7911         /* if shCount >= 8 */
7912         if (shCount >= 8) {
7913                 shCount -= 8 ;
7914                 if (shCount)
7915                         shiftR1Left2Result(left, MSB16, result, LSB,
7916                         shCount, sign);
7917                 else
7918                         movLeft2Result(left, MSB16, result, LSB);
7919                 
7920                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7921                 
7922                 if(sign) {
7923                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7924                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7925                 }
7926         }
7927         
7928         /*  1 <= shCount <= 7 */
7929         else
7930                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7931 }
7932
7933 /*-----------------------------------------------------------------*/
7934 /* shiftRLong - shift right one long from left to result           */
7935 /* offl = LSB or MSB16                                             */
7936 /*-----------------------------------------------------------------*/
7937 static void shiftRLong (operand *left, int offl,
7938                                                 operand *result, int sign)
7939 {
7940         int size, same;
7941         
7942         FENTRY;
7943         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7944         
7945         size = AOP_SIZE(left);
7946         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7947         
7948         if (sign)
7949                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7950         else
7951                 emitCLRC;
7952
7953         assert (offl >= 0 && offl < size);
7954
7955         same = pic14_sameRegs (AOP(left), AOP(result));
7956
7957         /* perform the shift */
7958         while (size--)
7959         {
7960                 if (same && !offl) {
7961                         emitpcode (POC_RRF, popGet (AOP(result), size));
7962                 } else {
7963                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7964                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7965                 }
7966         } // while
7967
7968         addSign (result, AOP_SIZE(left) - offl, sign);
7969 }
7970
7971 /*-----------------------------------------------------------------*/
7972 /* genrshFour - shift four byte by a known amount != 0             */
7973 /*-----------------------------------------------------------------*/
7974 static void genrshFour (operand *result, operand *left,
7975                                                 int shCount, int sign)
7976 {
7977         FENTRY;
7978         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7979         /* if shifting more that 3 bytes */
7980         if(shCount >= 24 ) {
7981                 shCount -= 24;
7982                 if(shCount)
7983                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7984                 else
7985                         movLeft2Result(left, MSB32, result, LSB);
7986                 
7987                 addSign(result, MSB16, sign);
7988         }
7989         else if(shCount >= 16){
7990                 shCount -= 16;
7991                 if(shCount)
7992                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7993                 else{
7994                         movLeft2Result(left, MSB24, result, LSB);
7995                         movLeft2Result(left, MSB32, result, MSB16);
7996                 }
7997                 addSign(result, MSB24, sign);
7998         }
7999         else if(shCount >= 8){
8000                 shCount -= 8;
8001                 if(shCount == 1)
8002                         shiftRLong(left, MSB16, result, sign);
8003                 else if(shCount == 0){
8004                         movLeft2Result(left, MSB16, result, LSB);
8005                         movLeft2Result(left, MSB24, result, MSB16);
8006                         movLeft2Result(left, MSB32, result, MSB24);
8007                         addSign(result, MSB32, sign);
8008                 }
8009                 else{
8010                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8011                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8012                         /* the last shift is signed */
8013                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8014                         addSign(result, MSB32, sign);
8015                 }
8016         }
8017         else{   /* 1 <= shCount <= 7 */
8018                 if(shCount <= 2){
8019                         shiftRLong(left, LSB, result, sign);
8020                         if(shCount == 2)
8021                                 shiftRLong(result, LSB, result, sign);
8022                 }
8023                 else{
8024                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8025                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8026                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8027                 }
8028         }
8029 }
8030
8031 /*-----------------------------------------------------------------*/
8032 /* genRightShiftLiteral - right shifting by known count            */
8033 /*-----------------------------------------------------------------*/
8034 static void genRightShiftLiteral (operand *left,
8035                                                                   operand *right,
8036                                                                   operand *result,
8037                                                                   iCode *ic,
8038                                                                   int sign)
8039 {    
8040         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8041         int lsize,res_size;
8042         
8043         FENTRY;
8044         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8045         freeAsmop(right,NULL,ic,TRUE);
8046         
8047         aopOp(left,ic,FALSE);
8048         aopOp(result,ic,FALSE);
8049         
8050 #if VIEW_SIZE
8051         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8052                 AOP_SIZE(left));
8053 #endif
8054         
8055         lsize = pic14_getDataSize(left);
8056         res_size = pic14_getDataSize(result);
8057         /* test the LEFT size !!! */
8058         
8059         /* I suppose that the left size >= result size */
8060         if(shCount == 0){
8061                 while(res_size--)
8062                         movLeft2Result(left, res_size, result, res_size);
8063         }
8064         
8065         else if(shCount >= (lsize * 8)){
8066                 
8067                 if(res_size == 1) {
8068                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8069                         if(sign) {
8070                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8071                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8072                         }
8073                 } else {
8074                         
8075                         if(sign) {
8076                                 emitpcode(POC_MOVLW, popGetLit(0));
8077                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8078                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8079                                 while(res_size--)
8080                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8081                                 
8082                         } else {
8083                                 
8084                                 while(res_size--)
8085                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8086                         }
8087                 }
8088         } else {
8089                 
8090                 switch (res_size) {
8091                 case 1:
8092                         genrshOne (result,left,shCount,sign);
8093                         break;
8094                         
8095                 case 2:
8096                         genrshTwo (result,left,shCount,sign);
8097                         break;
8098                         
8099                 case 4:
8100                         genrshFour (result,left,shCount,sign);
8101                         break;
8102                 default :
8103                         break;
8104                 }
8105                 
8106         }
8107
8108         freeAsmop(left,NULL,ic,TRUE);
8109         freeAsmop(result,NULL,ic,TRUE);
8110 }
8111 #endif
8112
8113 #if 0
8114 /*-----------------------------------------------------------------*/
8115 /* genSignedRightShift - right shift of signed number              */
8116 /*-----------------------------------------------------------------*/
8117 static void genSignedRightShift (iCode *ic)
8118 {
8119         operand *right, *left, *result;
8120         int size, offset;
8121         //  char *l;
8122         symbol *tlbl, *tlbl1 ;
8123         pCodeOp *pctemp;
8124         
8125         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8126         
8127         /* we do it the hard way put the shift count in b
8128         and loop thru preserving the sign */
8129         FENTRY;
8130         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8131         
8132         right = IC_RIGHT(ic);
8133         left  = IC_LEFT(ic);
8134         result = IC_RESULT(ic);
8135         
8136         aopOp(right,ic,FALSE);  
8137         aopOp(left,ic,FALSE);
8138         aopOp(result,ic,FALSE);
8139         
8140         
8141         if ( AOP_TYPE(right) == AOP_LIT) {
8142                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8143                 //genRightShiftLiteral (left,right,result,ic,1);
8144                 return ;
8145         }
8146         /* shift count is unknown then we have to form 
8147         a loop get the loop count in B : Note: we take
8148         only the lower order byte since shifting
8149         more that 32 bits make no sense anyway, ( the
8150         largest size of an object can be only 32 bits ) */  
8151         
8152         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8153         //pic14_emitcode("inc","b");
8154         //freeAsmop (right,NULL,ic,TRUE);
8155         //aopOp(left,ic,FALSE);
8156         //aopOp(result,ic,FALSE);
8157         
8158         /* now move the left to the result if they are not the
8159         same */
8160         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8161                 AOP_SIZE(result) > 1) {
8162                 
8163                 size = AOP_SIZE(result);
8164                 offset=0;
8165                 while (size--) { 
8166                         /*
8167                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8168                         if (*l == '@' && IS_AOP_PREG(result)) {
8169                                 pic14_emitcode("mov","a,%s",l);
8170                                 aopPut(AOP(result),"a",offset);
8171                         } else
8172                         aopPut(AOP(result),l,offset);
8173                         */
8174                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8175                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8176                         
8177                         offset++;
8178                 }
8179         }
8180         
8181         /* mov the highest order bit to OVR */    
8182         tlbl = newiTempLabel(NULL);
8183         tlbl1= newiTempLabel(NULL);
8184         
8185         size = AOP_SIZE(result);
8186         offset = size - 1;
8187         
8188         pctemp = popGetTempReg();  /* grab a temporary working register. */
8189         
8190         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8191         
8192         /* offset should be 0, 1 or 3 */
8193         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8194         emitSKPNZ;
8195         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8196         
8197         emitpcode(POC_MOVWF, pctemp);
8198         
8199         
8200         emitpLabel(tlbl->key);
8201         
8202         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8203         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8204         
8205         while(--size) {
8206                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8207         }
8208         
8209         emitpcode(POC_DECFSZ,  pctemp);
8210         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8211         emitpLabel(tlbl1->key);
8212         
8213         popReleaseTempReg(pctemp);
8214 #if 0
8215         size = AOP_SIZE(result);
8216         offset = size - 1;
8217         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8218         pic14_emitcode("rlc","a");
8219         pic14_emitcode("mov","ov,c");
8220         /* if it is only one byte then */
8221         if (size == 1) {
8222                 l = aopGet(AOP(left),0,FALSE,FALSE);
8223                 MOVA(l);
8224                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8225                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8226                 pic14_emitcode("mov","c,ov");
8227                 pic14_emitcode("rrc","a");
8228                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8229                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8230                 aopPut(AOP(result),"a",0);
8231                 goto release ;
8232         }
8233         
8234         reAdjustPreg(AOP(result));
8235         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8236         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8237         pic14_emitcode("mov","c,ov");
8238         while (size--) {
8239                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8240                 MOVA(l);
8241                 pic14_emitcode("rrc","a");         
8242                 aopPut(AOP(result),"a",offset--);
8243         }
8244         reAdjustPreg(AOP(result));
8245         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8246         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8247         
8248 release:
8249 #endif
8250         
8251         freeAsmop(left,NULL,ic,TRUE);
8252         freeAsmop(result,NULL,ic,TRUE);
8253         freeAsmop(right,NULL,ic,TRUE);
8254 }
8255 #endif
8256
8257 /*-----------------------------------------------------------------*/
8258 /* loadSignToC - load the operand's sign bit into CARRY            */
8259 /*-----------------------------------------------------------------*/
8260
8261 static void loadSignToC (operand *op)
8262 {
8263         FENTRY;
8264         assert (op && AOP(op) && AOP_SIZE(op));
8265
8266         emitCLRC;
8267         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8268         emitSETC;
8269 }
8270
8271 /*-----------------------------------------------------------------*/
8272 /* genRightShift - generate code for right shifting                */
8273 /*-----------------------------------------------------------------*/
8274 static void genGenericShift (iCode *ic, int shiftRight)
8275 {
8276         operand *right, *left, *result;
8277         sym_link *retype ;
8278         int size;
8279         symbol *tlbl, *tlbl1, *inverselbl;
8280         
8281         FENTRY;
8282         /* if signed then we do it the hard way preserve the
8283         sign bit moving it inwards */
8284         retype = getSpec(operandType(IC_RESULT(ic)));
8285         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8286         
8287         /* signed & unsigned types are treated the same : i.e. the
8288         signed is NOT propagated inwards : quoting from the
8289         ANSI - standard : "for E1 >> E2, is equivalent to division
8290         by 2**E2 if unsigned or if it has a non-negative value,
8291         otherwise the result is implementation defined ", MY definition
8292         is that the sign does not get propagated */
8293         
8294         right = IC_RIGHT(ic);
8295         left  = IC_LEFT(ic);
8296         result = IC_RESULT(ic);
8297         
8298         aopOp(right,ic,FALSE);
8299         aopOp(left,ic,FALSE);
8300         aopOp(result,ic,FALSE);
8301         
8302         /* if the shift count is known then do it 
8303         as efficiently as possible */
8304         if (AOP_TYPE(right) == AOP_LIT) {
8305                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8306                 if (lit < 0)
8307                 {
8308                         lit = -lit;
8309                         shiftRight = !shiftRight;
8310                 }
8311                 
8312                 if (shiftRight)
8313                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8314                 else
8315                         shiftLeft_Left2ResultLit (left, result, lit);
8316                 //genRightShiftLiteral (left,right,result,ic, 0);
8317                 return ;
8318         }
8319         
8320         /* shift count is unknown then we have to form 
8321         a loop get the loop count in B : Note: we take
8322         only the lower order byte since shifting
8323         more that 32 bits make no sense anyway, ( the
8324         largest size of an object can be only 32 bits ) */  
8325
8326         /* we must not overwrite the shift counter */
8327         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8328         
8329         /* now move the left to the result if they are not the
8330         same */
8331         if (!pic14_sameRegs(AOP(left),AOP(result)))
8332         {
8333                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8334                 while (size--) {
8335                         mov2w(AOP(left), size);
8336                         movwf(AOP(result), size);
8337                 }
8338                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8339         }
8340         
8341         tlbl = newiTempLabel(NULL);
8342         tlbl1= newiTempLabel(NULL);
8343         inverselbl = NULL;
8344         size = AOP_SIZE(result);
8345
8346         mov2w(AOP(right),0);
8347         if (!SPEC_USIGN(operandType(right)))
8348         {
8349                 inverselbl = newiTempLabel(NULL);
8350                 /* signed shift count -- invert shift direction for c<0 */
8351                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8352                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8353         } // if
8354         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8355         /* check for `a = b >> c' with `-c == 0' */
8356         emitSKPNZ;
8357         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8358         emitpLabel(tlbl->key);
8359         /* propagate the sign bit inwards for SIGNED result */
8360         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8361         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8362         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8363         emitSKPC;
8364         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8365
8366         if (!SPEC_USIGN(operandType(right)))
8367         {
8368                 symbol *inv_loop = newiTempLabel(NULL);
8369
8370                 shiftRight = !shiftRight;       /* invert shift direction */
8371                 
8372                 /* we came here from the code above -- we are done */
8373                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8374                 
8375                 /* emit code for shifting N<0 steps, count is already in W */
8376                 emitpLabel(inverselbl->key);
8377                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8378                 emitpLabel(inv_loop->key);
8379                 /* propagate the sign bit inwards for SIGNED result */
8380                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8381                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8382                 emitpcode(POC_ADDLW, popGetLit(1));
8383                 emitSKPC;
8384                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8385         } // if
8386         
8387         emitpLabel(tlbl1->key);
8388         
8389         freeAsmop(left,NULL,ic,TRUE);
8390         freeAsmop (right,NULL,ic,TRUE);
8391         freeAsmop(result,NULL,ic,TRUE);
8392 }
8393
8394 static void genRightShift (iCode *ic)
8395 {
8396         genGenericShift(ic, 1);
8397 }
8398
8399 static void genLeftShift (iCode *ic)
8400 {
8401         genGenericShift(ic, 0);
8402 }
8403
8404 /*-----------------------------------------------------------------*/
8405 /* SetIrp - Set IRP bit                                            */
8406 /*-----------------------------------------------------------------*/
8407 void SetIrp(operand *result) {
8408         FENTRY;
8409         if (AOP_TYPE(result) == AOP_LIT) {
8410                 unsigned lit = (unsigned)operandLitValue(result);
8411                 if (lit&0x100)
8412                         emitSETIRP;
8413                 else
8414                         emitCLRIRP;
8415         } else {
8416                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8417                         int addrs = PCOL(AOP(result))->lit;
8418                         if (addrs & 0x100)
8419                                 emitSETIRP;
8420                         else
8421                                 emitCLRIRP;
8422                 } else {
8423                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8424                         if(AOP_SIZE(result) > 1) {
8425                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8426                                 emitSETIRP;
8427                         }
8428                 }
8429         }
8430 }
8431
8432 static void
8433 setup_fsr (operand *ptr)
8434 {
8435   mov2w_op(ptr, 0);
8436   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8437
8438   /* also setup-up IRP */
8439   SetIrp (ptr);
8440 }
8441
8442 /*-----------------------------------------------------------------*/
8443 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8444 /*                  arbitrary pointer (__code, __data, generic)    */
8445 /*-----------------------------------------------------------------*/
8446 static void
8447 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8448 {
8449     FENTRY;
8450     switch (p_type)
8451     {
8452     case POINTER:
8453       if (!alreadyAddressed) setup_fsr (src);
8454       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8455       break;
8456     
8457     case CPOINTER:
8458       assert( AOP_SIZE(src) == 2 );
8459       mov2w_op(src, 0);
8460       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8461       mov2w_op(src, 1);
8462       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8463       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8464       call_libraryfunc ("__gptrget1");
8465       break;
8466     
8467     case GPOINTER:
8468       assert( AOP_SIZE(src) == 3 );
8469       mov2w_op(src, 0);
8470       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8471       mov2w_op(src, 1);
8472       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8473       mov2w_op(src, 2);
8474       call_libraryfunc ("__gptrget1");
8475       break;
8476     
8477     default:
8478       assert( !"unhandled pointer type" );
8479       break;
8480     }
8481 }
8482
8483 /*-----------------------------------------------------------------*/
8484 /* emitPtrByteSet - emits code to set a byte from src through a    */
8485 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8486 /*-----------------------------------------------------------------*/
8487 static void
8488 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8489 {
8490     FENTRY;
8491     switch (p_type)
8492     {
8493     case POINTER:
8494       if (!alreadyAddressed) setup_fsr (dst);
8495       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8496       break;
8497     
8498     case CPOINTER:
8499       assert( !"trying to assign to __code pointer" );
8500       break;
8501     
8502     case GPOINTER:
8503       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8504       mov2w_op(dst, 0);
8505       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8506       mov2w_op(dst, 1);
8507       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8508       mov2w_op(dst, 2);
8509       call_libraryfunc ("__gptrput1");
8510       break;
8511
8512     default:
8513       assert( !"unhandled pointer type" );
8514       break;
8515     }
8516 }
8517
8518 /*-----------------------------------------------------------------*/
8519 /* genUnpackBits - generates code for unpacking bits               */
8520 /*-----------------------------------------------------------------*/
8521 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8522 {    
8523   int rsize;            /* result size */
8524   sym_link *etype;      /* bitfield type information */
8525   int blen;             /* bitfield length */
8526   int bstr;             /* bitfield starting bit within byte */
8527
8528   FENTRY;
8529   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8530   etype = getSpec(operandType(result));
8531   rsize = getSize (operandType (result));
8532   blen = SPEC_BLEN (etype);
8533   bstr = SPEC_BSTR (etype);
8534
8535   /* single bit field case */
8536   if (blen == 1) {
8537     if (ifx) { /* that is for an if statement */
8538       pCodeOp *pcop;
8539       resolvedIfx rIfx;
8540       resolveIfx(&rIfx,ifx);
8541       if (ptype == -1) /* direct */
8542         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8543       else
8544         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8545       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8546       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8547       ifx->generated=1;
8548     } else {
8549       int i;
8550       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8551       for (i=0; i < AOP_SIZE(result); i++)
8552         emitpcode (POC_CLRF, popGet (AOP(result), i));
8553
8554       switch (ptype)
8555       {
8556       case -1:
8557         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8558         /* adjust result below */
8559         break;
8560         
8561       case POINTER:
8562       case GPOINTER:
8563       case CPOINTER:
8564         emitPtrByteGet (left, ptype, FALSE);
8565         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8566         emitSKPZ;
8567         /* adjust result below */
8568         break;
8569         
8570       default:
8571         assert( !"unhandled pointer type" );
8572       } // switch
8573
8574       /* move sign-/zero extended bit to result */
8575       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8576         emitpcode (POC_INCF, popGet (AOP(result), 0));
8577       } else {
8578         emitpcode (POC_DECF, popGet (AOP(result), 0));
8579       }
8580       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8581     }
8582     return;
8583   }
8584   else if (blen <= 8 && ((blen + bstr) <= 8))
8585   {
8586     /* blen > 1 */
8587     int i;
8588
8589     for (i=0; i < AOP_SIZE(result); i++)
8590       emitpcode (POC_CLRF, popGet (AOP(result), i));
8591
8592     switch (ptype)
8593     {
8594     case -1:
8595       mov2w(AOP(left), 0);
8596       break;
8597       
8598     case POINTER:
8599     case GPOINTER:
8600     case CPOINTER:
8601       emitPtrByteGet (left, ptype, FALSE);
8602       break;
8603       
8604     default:
8605       assert( !"unhandled pointer type" );
8606     } // switch
8607
8608     if (blen < 8)
8609       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8610     movwf(AOP(result), 0);
8611     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8612
8613     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8614     {
8615       /* signed bitfield */
8616       assert (bstr + blen > 0);
8617       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8618       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8619       emitpcode(POC_IORWF, popGet(AOP(result),0));
8620     }
8621     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8622     return;
8623   }
8624
8625   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8626 }
8627
8628 #if 1
8629 /*-----------------------------------------------------------------*/
8630 /* genDataPointerGet - generates code when ptr offset is known     */
8631 /*-----------------------------------------------------------------*/
8632 static void genDataPointerGet (operand *left, 
8633         operand *result, 
8634         iCode *ic)
8635 {
8636         int size , offset = 0;
8637                 
8638         FENTRY;
8639         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8640         
8641         
8642         /* optimization - most of the time, left and result are the same
8643         * address, but different types. for the pic code, we could omit
8644         * the following
8645         */
8646         aopOp(result,ic,TRUE);
8647         
8648         if (pic14_sameRegs (AOP(left), AOP(result)))
8649                 return;
8650         
8651         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8652         
8653         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8654         
8655         size = AOP_SIZE(result);
8656         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8657         
8658         offset = 0;
8659         while (size--) {
8660                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8661                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8662                 offset++;
8663         }
8664         
8665         freeAsmop(left,NULL,ic,TRUE);
8666         freeAsmop(result,NULL,ic,TRUE);
8667 }
8668 #endif
8669
8670 /*-----------------------------------------------------------------*/
8671 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8672 /*-----------------------------------------------------------------*/
8673 static void genNearPointerGet (operand *left, 
8674                                                            operand *result, 
8675                                                            iCode *ic)
8676 {
8677         asmop *aop = NULL;
8678         sym_link *ltype = operandType(left);
8679         sym_link *rtype = operandType(result);
8680         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8681         int direct = 0;
8682
8683         FENTRY;
8684         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8685         
8686         
8687         aopOp(left,ic,FALSE);
8688         
8689         /* if left is rematerialisable and
8690         result is not bit variable type and
8691         the left is pointer to data space i.e
8692         lower 128 bytes of space */
8693         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8694                 !IS_BITVAR(retype)         &&
8695                 DCL_TYPE(ltype) == POINTER) {
8696                 genDataPointerGet (left,result,ic);
8697                 return ;
8698         }
8699         
8700         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701         aopOp (result,ic,FALSE);
8702         
8703         /* Check if can access directly instead of via a pointer */
8704         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8705                 && AOP_SIZE(result) == 1)
8706         {
8707                 direct = 1;
8708         }
8709
8710         if (IS_BITFIELD(getSpec(operandType(result)))) 
8711         {
8712                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8713                 goto release;
8714         }
8715         
8716         /* If the pointer value is not in a the FSR then need to put it in */
8717         /* Must set/reset IRP bit for use with FSR. */
8718         if (!direct)
8719           setup_fsr (left);
8720         
8721 //      sym_link *etype;
8722         /* if bitfield then unpack the bits */
8723         {
8724                 /* we have can just get the values */
8725                 int size = AOP_SIZE(result);
8726                 int offset = 0 ;  
8727                 
8728                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8729                 
8730                 while(size--) {
8731                         if (direct)
8732                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8733                         else
8734                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8735                         if (AOP_TYPE(result) == AOP_LIT) {
8736                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8737                         } else {
8738                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8739                         }
8740                         if (size && !direct)
8741                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8742                         offset++;
8743                 }
8744         }
8745         
8746         /* now some housekeeping stuff */
8747         if (aop) {
8748                 /* we had to allocate for this iCode */
8749                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8750                 freeAsmop(NULL,aop,ic,TRUE);
8751         } else { 
8752                 /* we did not allocate which means left
8753                 already in a pointer register, then
8754                 if size > 0 && this could be used again
8755                 we have to point it back to where it 
8756                 belongs */
8757                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8758                 if (AOP_SIZE(result) > 1 &&
8759                         !OP_SYMBOL(left)->remat &&
8760                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8761                         ic->depth )) {
8762                         int size = AOP_SIZE(result) - 1;
8763                         while (size--)
8764                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8765                 }
8766         }
8767         
8768 release:
8769         /* done */
8770         freeAsmop(left,NULL,ic,TRUE);
8771         freeAsmop(result,NULL,ic,TRUE);
8772
8773 }
8774
8775 #if 0
8776 /*-----------------------------------------------------------------*/
8777 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8778 /*-----------------------------------------------------------------*/
8779 static void genPagedPointerGet (operand *left, 
8780                                                                 operand *result, 
8781                                                                 iCode *ic)
8782 {
8783         asmop *aop = NULL;
8784         regs *preg = NULL ;
8785         char *rname ;
8786         sym_link *rtype, *retype;    
8787         
8788         FENTRY;
8789         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8790         
8791         rtype = operandType(result);
8792         retype= getSpec(rtype);
8793         
8794         aopOp(left,ic,FALSE);
8795         
8796         /* if the value is already in a pointer register
8797         then don't need anything more */
8798         if (!AOP_INPREG(AOP(left))) {
8799                 /* otherwise get a free pointer register */
8800                 aop = newAsmop(0);
8801                 preg = getFreePtr(ic,&aop,FALSE);
8802                 pic14_emitcode("mov","%s,%s",
8803                         preg->name,
8804                         aopGet(AOP(left),0,FALSE,TRUE));
8805                 rname = preg->name ;
8806         } else
8807                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8808         
8809         freeAsmop(left,NULL,ic,TRUE);
8810         aopOp (result,ic,FALSE);
8811         
8812         /* if bitfield then unpack the bits */
8813         if (IS_BITFIELD(retype)) 
8814                 genUnpackBits (result,left,rname,PPOINTER,0);
8815         else {
8816                 /* we have can just get the values */
8817                 int size = AOP_SIZE(result);
8818                 int offset = 0 ;  
8819                 
8820                 while (size--) {
8821                         
8822                         pic14_emitcode("movx","a,@%s",rname);
8823                         aopPut(AOP(result),"a",offset);
8824                         
8825                         offset++ ;
8826                         
8827                         if (size)
8828                                 pic14_emitcode("inc","%s",rname);
8829                 }
8830         }
8831         
8832         /* now some housekeeping stuff */
8833         if (aop) {
8834                 /* we had to allocate for this iCode */
8835                 freeAsmop(NULL,aop,ic,TRUE);
8836         } else { 
8837         /* we did not allocate which means left
8838         already in a pointer register, then
8839         if size > 0 && this could be used again
8840         we have to point it back to where it 
8841                 belongs */
8842                 if (AOP_SIZE(result) > 1 &&
8843                         !OP_SYMBOL(left)->remat &&
8844                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8845                         ic->depth )) {
8846                         int size = AOP_SIZE(result) - 1;
8847                         while (size--)
8848                                 pic14_emitcode("dec","%s",rname);
8849                 }
8850         }
8851         
8852         /* done */
8853         freeAsmop(result,NULL,ic,TRUE);
8854         
8855         
8856 }
8857
8858 /*-----------------------------------------------------------------*/
8859 /* genFarPointerGet - gget value from far space                    */
8860 /*-----------------------------------------------------------------*/
8861 static void genFarPointerGet (operand *left,
8862                                                           operand *result, iCode *ic)
8863 {
8864         int size, offset ;
8865         sym_link *retype = getSpec(operandType(result));
8866         
8867         FENTRY;
8868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8869         
8870         aopOp(left,ic,FALSE);
8871         
8872         /* if the operand is already in dptr 
8873         then we do nothing else we move the value to dptr */
8874         if (AOP_TYPE(left) != AOP_STR) {
8875                 /* if this is remateriazable */
8876                 if (AOP_TYPE(left) == AOP_IMMD)
8877                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8878                 else { /* we need to get it byte by byte */
8879                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8880                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8881                         if (options.model == MODEL_FLAT24)
8882                         {
8883                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8884                         }
8885                 }
8886         }
8887         /* so dptr know contains the address */
8888         freeAsmop(left,NULL,ic,TRUE);
8889         aopOp(result,ic,FALSE);
8890         
8891         /* if bit then unpack */
8892         if (IS_BITFIELD(retype)) 
8893                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8894         else {
8895                 size = AOP_SIZE(result);
8896                 offset = 0 ;
8897                 
8898                 while (size--) {
8899                         pic14_emitcode("movx","a,@dptr");
8900                         aopPut(AOP(result),"a",offset++);
8901                         if (size)
8902                                 pic14_emitcode("inc","dptr");
8903                 }
8904         }
8905         
8906         freeAsmop(result,NULL,ic,TRUE);
8907 }
8908 #endif
8909
8910 #if 0
8911 /*-----------------------------------------------------------------*/
8912 /* genCodePointerGet - get value from code space                  */
8913 /*-----------------------------------------------------------------*/
8914 static void genCodePointerGet (operand *left,
8915                                                            operand *result, iCode *ic)
8916 {
8917         int size, offset ;
8918         sym_link *retype = getSpec(operandType(result));
8919         
8920         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8921         
8922         aopOp(left,ic,FALSE);
8923         
8924         /* if the operand is already in dptr 
8925         then we do nothing else we move the value to dptr */
8926         if (AOP_TYPE(left) != AOP_STR) {
8927                 /* if this is remateriazable */
8928                 if (AOP_TYPE(left) == AOP_IMMD)
8929                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8930                 else { /* we need to get it byte by byte */
8931                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8932                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8933                         if (options.model == MODEL_FLAT24)
8934                         {
8935                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8936                         }
8937                 }
8938         }
8939         /* so dptr know contains the address */
8940         freeAsmop(left,NULL,ic,TRUE);
8941         aopOp(result,ic,FALSE);
8942         
8943         /* if bit then unpack */
8944         if (IS_BITFIELD(retype)) 
8945                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8946         else {
8947                 size = AOP_SIZE(result);
8948                 offset = 0 ;
8949                 
8950                 while (size--) {
8951                         pic14_emitcode("clr","a");
8952                         pic14_emitcode("movc","a,@a+dptr");
8953                         aopPut(AOP(result),"a",offset++);
8954                         if (size)
8955                                 pic14_emitcode("inc","dptr");
8956                 }
8957         }
8958         
8959         freeAsmop(result,NULL,ic,TRUE);
8960 }
8961 #endif
8962 /*-----------------------------------------------------------------*/
8963 /* genGenPointerGet - gget value from generic pointer space        */
8964 /*-----------------------------------------------------------------*/
8965 static void genGenPointerGet (operand *left,
8966                                                           operand *result, iCode *ic)
8967 {
8968         FENTRY;
8969         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8970         aopOp(left,ic,FALSE);
8971         aopOp(result,ic,FALSE);
8972         
8973         
8974         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8975
8976         if (IS_BITFIELD(getSpec(operandType(result))))
8977         {
8978           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8979           return;
8980         }
8981
8982         {
8983           /* emit call to __gptrget */
8984           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8985           int size = AOP_SIZE(result);
8986           int idx = 0;
8987
8988           assert (size > 0 && size <= 4);
8989
8990           /* pass arguments */
8991           assert (AOP_SIZE(left) == 3);
8992           mov2w(AOP(left), 0);
8993           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8994           mov2w(AOP(left), 1);
8995           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8996           mov2w(AOP(left), 2);
8997           call_libraryfunc (func[size]);
8998           
8999           /* save result */
9000           movwf (AOP(result), --size);
9001           while (size--) {
9002             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9003             movwf (AOP(result), size);
9004           } // while
9005         }
9006         
9007         freeAsmop(left,NULL,ic,TRUE);
9008         freeAsmop(result,NULL,ic,TRUE);
9009         
9010 }
9011
9012 /*-----------------------------------------------------------------*/
9013 /* genConstPointerGet - get value from const generic pointer space */
9014 /*-----------------------------------------------------------------*/
9015 static void genConstPointerGet (operand *left,
9016                                                                 operand *result, iCode *ic)
9017 {
9018         //sym_link *retype = getSpec(operandType(result));
9019         #if 0
9020         symbol *albl, *blbl;//, *clbl;
9021         pCodeOp *pcop;
9022         #endif
9023         PIC_OPCODE poc;
9024         int i, size, lit;
9025         
9026         FENTRY;
9027         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9028         aopOp(left,ic,FALSE);
9029         aopOp(result,ic,FALSE);
9030         
9031         size = AOP_SIZE(result);
9032         
9033         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9034         
9035         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9036
9037         lit = op_isLitLike (left);
9038         poc = lit ? POC_MOVLW : POC_MOVFW;
9039
9040         if (IS_BITFIELD(getSpec(operandType(result))))
9041         {
9042                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9043                 goto release;
9044         }
9045
9046         {
9047                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9048                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9049                 assert (size > 0 && size <= 4);
9050                 
9051                 mov2w_op(left, 0);
9052                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9053                 mov2w_op(left, 1);
9054                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9055                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9056                 call_libraryfunc (func[size]);
9057
9058                 movwf(AOP(result),size-1);
9059                 for (i = 1; i < size; i++)
9060                 {
9061                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9062                         movwf(AOP(result),size - 1 - i);
9063                 } // for
9064         }
9065         
9066 release:
9067         freeAsmop(left,NULL,ic,TRUE);
9068         freeAsmop(result,NULL,ic,TRUE);
9069         
9070 }
9071 /*-----------------------------------------------------------------*/
9072 /* genPointerGet - generate code for pointer get                   */
9073 /*-----------------------------------------------------------------*/
9074 static void genPointerGet (iCode *ic)
9075 {
9076         operand *left, *result ;
9077         sym_link *type, *etype;
9078         int p_type = -1;
9079         
9080         FENTRY;
9081         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9082         
9083         left = IC_LEFT(ic);
9084         result = IC_RESULT(ic) ;
9085         
9086         /* depending on the type of pointer we need to
9087         move it to the correct pointer register */
9088         type = operandType(left);
9089         etype = getSpec(type);
9090         
9091         if (IS_PTR_CONST(type))
9092                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9093         
9094         /* if left is of type of pointer then it is simple */
9095         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9096                 p_type = DCL_TYPE(type);
9097         else {
9098                 /* we have to go by the storage class */
9099                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9100                 
9101                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9102                 
9103                 if (SPEC_OCLS(etype)->codesp ) {
9104                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9105                         //p_type = CPOINTER ; 
9106                 }
9107                 else
9108                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9109                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9110                         /*p_type = FPOINTER ;*/ 
9111                         else
9112                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9113                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9114                                 /*        p_type = PPOINTER; */
9115                                 else
9116                                         if (SPEC_OCLS(etype) == idata )
9117                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9118                                         /*      p_type = IPOINTER; */
9119                                         else
9120                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9121                                         /*      p_type = POINTER ; */
9122         }
9123         
9124         /* now that we have the pointer type we assign
9125         the pointer values */
9126         switch (p_type) {
9127                 
9128         case POINTER: 
9129         //case IPOINTER:
9130                 genNearPointerGet (left,result,ic);
9131                 break;
9132 /*
9133         case PPOINTER:
9134                 genPagedPointerGet(left,result,ic);
9135                 break;
9136                 
9137         case FPOINTER:
9138                 genFarPointerGet (left,result,ic);
9139                 break;
9140 */              
9141         case CPOINTER:
9142                 genConstPointerGet (left,result,ic);
9143                 break;
9144                 
9145         case GPOINTER:
9146                 genGenPointerGet (left,result,ic);
9147                 break;
9148         default:
9149                 assert ( !"unhandled pointer type" );
9150                 break;
9151         }
9152         
9153 }
9154
9155 /*-----------------------------------------------------------------*/
9156 /* genPackBits - generates code for packed bit storage             */
9157 /*-----------------------------------------------------------------*/
9158 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9159 {
9160   int blen;             /* bitfield length */
9161   int bstr;             /* bitfield starting bit within byte */
9162   int litval;           /* source literal value (if AOP_LIT) */
9163   unsigned char mask;   /* bitmask within current byte */
9164
9165   FENTRY;
9166   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9167
9168   blen = SPEC_BLEN (etype);
9169   bstr = SPEC_BSTR (etype);
9170
9171   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9172   if ((blen <= 8) && ((bstr + blen) <= 8))
9173   {
9174     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9175             (unsigned char) (0xFF >> (8 - bstr)));
9176
9177     if (AOP_TYPE (right) == AOP_LIT)
9178     {
9179       /* Case with a bitfield length <8 and literal source */
9180       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9181       if (blen == 1) {
9182         pCodeOp *pcop;
9183         
9184         switch (p_type)
9185         {
9186         case -1:
9187           if (AOP(result)->type == AOP_PCODE)
9188             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9189           else
9190             pcop = popGet(AOP(result),0);
9191           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9192           break;
9193         
9194         case POINTER:
9195           setup_fsr (result);
9196           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9197           break;
9198         
9199         case CPOINTER:
9200           assert( !"trying to assign to bitfield via pointer to __code space" );
9201           break;
9202         
9203         case GPOINTER:
9204           emitPtrByteGet(result, p_type, FALSE);
9205           if (lit) {
9206             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9207           } else {
9208             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9209           }
9210           emitPtrByteSet(result, p_type, TRUE);
9211           break;
9212         
9213         default:
9214           assert( !"unhandled pointer type" );
9215           break;
9216         } // switch (p_type)
9217       } else {
9218         /* blen > 1 */
9219         litval = lit << bstr;
9220         litval &= (~mask) & 0x00ff;
9221         
9222         switch (p_type)
9223         {
9224         case -1:
9225           mov2w (AOP(result), 0);
9226           if ((litval|mask) != 0x00ff)
9227             emitpcode(POC_ANDLW, popGetLit (mask));
9228           if (litval != 0x00)
9229             emitpcode(POC_IORLW, popGetLit (litval));
9230           movwf (AOP(result), 0);
9231           break;
9232         
9233         case POINTER:
9234         case GPOINTER:
9235           emitPtrByteGet(result, p_type, FALSE);
9236           if ((litval|mask) != 0x00ff)
9237             emitpcode(POC_ANDLW, popGetLit (mask));
9238           if (litval != 0x00)
9239             emitpcode(POC_IORLW, popGetLit (litval));
9240           emitPtrByteSet(result, p_type, TRUE);
9241           break;
9242         
9243         case CPOINTER:
9244           assert( !"trying to assign to bitfield via pointer to __code space" );
9245           break;
9246         
9247         default:
9248           assert( !"unhandled pointer type" );
9249           break;
9250         } // switch
9251       } // if (blen > 1)
9252     }
9253     else
9254     {
9255       /* right is no literal */
9256       if (blen==1) {
9257         switch (p_type)
9258         {
9259         case -1:
9260           /* Note more efficient code, of pre clearing bit then only setting it if required,
9261            * can only be done if it is known that the result is not a SFR */
9262           emitpcode(POC_RRFW,popGet(AOP(right),0));
9263           emitSKPC;
9264           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9265           emitSKPNC;
9266           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9267           break;
9268         
9269         case POINTER:
9270         case GPOINTER:
9271           emitPtrByteGet (result, p_type, FALSE);
9272           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9273           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9274           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9275           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9276           emitPtrByteSet (result, p_type, TRUE);
9277           break;
9278         
9279         case CPOINTER:
9280           assert( !"trying to assign to bitfield via pointer to __code space" );
9281           break;
9282         
9283         default:
9284           assert( !"unhandled pointer type" );
9285           break;
9286         } // switch
9287         return;
9288       } else {
9289         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9290         pCodeOp *temp = popGetTempReg ();
9291
9292         mov2w (AOP(right), 0);
9293         if (blen < 8) {
9294           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9295         }
9296         emitpcode(POC_MOVWF, temp);
9297         if (bstr) {
9298           AccLsh (temp, bstr);
9299         }
9300         
9301         switch (p_type)
9302         {
9303         case -1:
9304           mov2w (AOP(result), 0);
9305           emitpcode(POC_ANDLW, popGetLit (mask));
9306           emitpcode(POC_IORFW, temp);
9307           movwf (AOP(result), 0);
9308           break;
9309         
9310         case POINTER:
9311         case GPOINTER:
9312           emitPtrByteGet (result, p_type, FALSE);
9313           emitpcode(POC_ANDLW, popGetLit (mask));
9314           emitpcode(POC_IORFW, temp);
9315           emitPtrByteSet (result, p_type, TRUE);
9316           break;
9317         
9318         case CPOINTER:
9319           assert( !"trying to assign to bitfield via pointer to __code space" );
9320           break;
9321         
9322         default:
9323           assert( !"unhandled pointer type" );
9324           break;
9325         } // switch
9326
9327         popReleaseTempReg (temp);
9328       } // if (blen > 1)
9329     } // if (AOP(right)->type != AOP_LIT)
9330     return;
9331   } // if (blen <= 8 && ((blen + bstr) <= 8))
9332
9333   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9334 }
9335
9336 unsigned long
9337 bitpatternFromVal (value *val)
9338 {
9339   union {
9340     float d;
9341     unsigned long l;
9342   } float_long;
9343
9344   assert (sizeof (float) == sizeof (long));
9345
9346   //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9347
9348   switch (SPEC_NOUN(val->type))
9349   {
9350   case V_INT:
9351   case V_CHAR:
9352     return (unsigned long)floatFromVal (val);
9353     
9354   case V_FLOAT:
9355   case V_DOUBLE:
9356     float_long.d = floatFromVal (val);
9357     return float_long.l;
9358     
9359   default:
9360     assert( !"unhandled value type" );
9361     break;
9362   }
9363
9364   float_long.d = floatFromVal (val);
9365   return float_long.l;
9366 }
9367
9368 /*-----------------------------------------------------------------*/
9369 /* genDataPointerSet - remat pointer to data space                 */
9370 /*-----------------------------------------------------------------*/
9371 static void genDataPointerSet(operand *right,
9372         operand *result,
9373         iCode *ic)
9374 {
9375         int size, offset = 0 ;
9376         int ressize;
9377         
9378         FENTRY;
9379         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9380         aopOp(right,ic,FALSE);
9381         aopOp(result,ic,FALSE);
9382         
9383         assert (IS_SYMOP(result));
9384         assert (IS_PTR(OP_SYM_TYPE(result)));
9385         
9386         size = AOP_SIZE(right);
9387         ressize = getSize(OP_SYM_ETYPE(result));
9388         if (size > ressize) size = ressize;
9389         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9390         
9391         //assert( !"what's going on here?" );
9392
9393         /*
9394         if ( AOP_TYPE(result) == AOP_PCODE) {
9395         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9396         AOP(result)->aopu.pcop->name,
9397         PCOI(AOP(result)->aopu.pcop)->offset);
9398         }
9399         */
9400         
9401         // tsd, was l+1 - the underline `_' prefix was being stripped
9402         while (size--) {
9403                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9404                 
9405                 if (AOP_TYPE(right) == AOP_LIT) {
9406                         /* XXX: might be float... */
9407                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9408                         lit = lit >> (8*offset);
9409                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9410                         if(lit&0xff) {
9411                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9412                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9413                         } else {
9414                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9415                         }
9416                 } else {
9417                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9418                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9419                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9420                 }
9421                 
9422                 offset++;
9423         }
9424         
9425         freeAsmop(right,NULL,ic,TRUE);
9426         freeAsmop(result,NULL,ic,TRUE);
9427 }
9428
9429 /*-----------------------------------------------------------------*/
9430 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9431 /*-----------------------------------------------------------------*/
9432 static void genNearPointerSet (operand *right,
9433                                                            operand *result, 
9434                                                            iCode *ic)
9435 {
9436         asmop *aop = NULL;
9437         sym_link *ptype = operandType(result);
9438         sym_link *retype = getSpec(operandType(right));
9439         sym_link *letype = getSpec(ptype);
9440         int direct = 0;
9441         
9442         
9443         FENTRY;
9444         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445         aopOp(result,ic,FALSE);
9446         
9447 #if 1
9448         /* if the result is rematerializable &
9449         in data space & not a bit variable */
9450         //if (AOP_TYPE(result) == AOP_IMMD &&
9451         if (AOP_TYPE(result) == AOP_PCODE &&
9452                 DCL_TYPE(ptype) == POINTER   &&
9453                 !IS_BITVAR (retype) &&
9454                 !IS_BITVAR (letype)) {
9455                 genDataPointerSet (right,result,ic);
9456                 freeAsmop(result,NULL,ic,TRUE);
9457                 return;
9458         }
9459 #endif
9460
9461         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9462         aopOp(right,ic,FALSE);
9463         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9464         
9465         /* Check if can access directly instead of via a pointer */
9466         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9467                 direct = 1;
9468         }
9469         
9470         if (IS_BITFIELD (letype))
9471         {
9472           genPackBits (letype, result, right, direct?-1:POINTER);
9473           return;
9474         }
9475         
9476         /* If the pointer value is not in a the FSR then need to put it in */
9477         /* Must set/reset IRP bit for use with FSR. */
9478         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9479         if (!direct)
9480                 setup_fsr (result);
9481
9482         {
9483                 /* we have can just get the values */
9484                 int size = AOP_SIZE(right);
9485                 int offset = 0 ;    
9486                 
9487                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9488                 while (size--) {
9489                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9490                         if (*l == '@' ) {
9491                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9492                         } else {
9493                                 if (AOP_TYPE(right) == AOP_LIT) {
9494                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9495                                 } else {
9496                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9497                                 }
9498                                 if (direct)
9499                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9500                                 else
9501                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9502                         }
9503                         if (size && !direct)
9504                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9505                         offset++;
9506                 }
9507         }
9508         
9509         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9510         /* now some housekeeping stuff */
9511         if (aop) {
9512                 /* we had to allocate for this iCode */
9513                 freeAsmop(NULL,aop,ic,TRUE);
9514         } else { 
9515                 /* we did not allocate which means left
9516                 already in a pointer register, then
9517                 if size > 0 && this could be used again
9518                 we have to point it back to where it 
9519                 belongs */
9520                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9521                 if (AOP_SIZE(right) > 1 &&
9522                         !OP_SYMBOL(result)->remat &&
9523                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9524                         ic->depth )) {
9525                         int size = AOP_SIZE(right) - 1;
9526                         while (size--)
9527                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9528                 }
9529         }
9530         
9531         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9532         /* done */
9533
9534         freeAsmop(right,NULL,ic,TRUE);
9535         freeAsmop(result,NULL,ic,TRUE);
9536 }
9537
9538 #if 0
9539 /*-----------------------------------------------------------------*/
9540 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9541 /*-----------------------------------------------------------------*/
9542 static void genPagedPointerSet (operand *right,
9543                                                                 operand *result, 
9544                                                                 iCode *ic)
9545 {
9546         asmop *aop = NULL;
9547         regs *preg = NULL ;
9548         char *rname , *l;
9549         sym_link *retype;
9550         
9551         FENTRY;
9552         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9553         
9554         retype= getSpec(operandType(right));
9555         
9556         aopOp(result,ic,FALSE);
9557         
9558         /* if the value is already in a pointer register
9559         then don't need anything more */
9560         if (!AOP_INPREG(AOP(result))) {
9561                 /* otherwise get a free pointer register */
9562                 aop = newAsmop(0);
9563                 preg = getFreePtr(ic,&aop,FALSE);
9564                 pic14_emitcode("mov","%s,%s",
9565                         preg->name,
9566                         aopGet(AOP(result),0,FALSE,TRUE));
9567                 rname = preg->name ;
9568         } else
9569                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9570         
9571         freeAsmop(result,NULL,ic,TRUE);
9572         aopOp (right,ic,FALSE);
9573         
9574         /* if bitfield then unpack the bits */
9575         if (IS_BITFIELD(retype)) 
9576                 genPackBits (retype,result,right,rname,PPOINTER);
9577         else {
9578                 /* we have can just get the values */
9579                 int size = AOP_SIZE(right);
9580                 int offset = 0 ;  
9581                 
9582                 while (size--) {
9583                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9584                         
9585                         MOVA(l);
9586                         pic14_emitcode("movx","@%s,a",rname);
9587                         
9588                         if (size)
9589                                 pic14_emitcode("inc","%s",rname);
9590                         
9591                         offset++;
9592                 }
9593         }
9594         
9595         /* now some housekeeping stuff */
9596         if (aop) {
9597                 /* we had to allocate for this iCode */
9598                 freeAsmop(NULL,aop,ic,TRUE);
9599         } else { 
9600         /* we did not allocate which means left
9601         already in a pointer register, then
9602         if size > 0 && this could be used again
9603         we have to point it back to where it 
9604                 belongs */
9605                 if (AOP_SIZE(right) > 1 &&
9606                         !OP_SYMBOL(result)->remat &&
9607                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9608                         ic->depth )) {
9609                         int size = AOP_SIZE(right) - 1;
9610                         while (size--)
9611                                 pic14_emitcode("dec","%s",rname);
9612                 }
9613         }
9614         
9615         /* done */
9616         freeAsmop(right,NULL,ic,TRUE);
9617         
9618         
9619 }
9620
9621 /*-----------------------------------------------------------------*/
9622 /* genFarPointerSet - set value from far space                     */
9623 /*-----------------------------------------------------------------*/
9624 static void genFarPointerSet (operand *right,
9625                                                           operand *result, iCode *ic)
9626 {
9627         int size, offset ;
9628         sym_link *retype = getSpec(operandType(right));
9629         
9630         FENTRY;
9631         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9632         aopOp(result,ic,FALSE);
9633         
9634         /* if the operand is already in dptr 
9635         then we do nothing else we move the value to dptr */
9636         if (AOP_TYPE(result) != AOP_STR) {
9637                 /* if this is remateriazable */
9638                 if (AOP_TYPE(result) == AOP_IMMD)
9639                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9640                 else { /* we need to get it byte by byte */
9641                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9642                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9643                         if (options.model == MODEL_FLAT24)
9644                         {
9645                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9646                         }
9647                 }
9648         }
9649         /* so dptr know contains the address */
9650         freeAsmop(result,NULL,ic,TRUE);
9651         aopOp(right,ic,FALSE);
9652         
9653         /* if bit then unpack */
9654         if (IS_BITFIELD(retype)) 
9655                 genPackBits(retype,result,right,"dptr",FPOINTER);
9656         else {
9657                 size = AOP_SIZE(right);
9658                 offset = 0 ;
9659                 
9660                 while (size--) {
9661                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9662                         MOVA(l);
9663                         pic14_emitcode("movx","@dptr,a");
9664                         if (size)
9665                                 pic14_emitcode("inc","dptr");
9666                 }
9667         }
9668         
9669         freeAsmop(right,NULL,ic,TRUE);
9670 }
9671 #endif
9672
9673 /*-----------------------------------------------------------------*/
9674 /* genGenPointerSet - set value from generic pointer space         */
9675 /*-----------------------------------------------------------------*/
9676 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9677 {
9678         sym_link *retype = getSpec(operandType(result));
9679         
9680         FENTRY;
9681         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9682         aopOp(right,ic,FALSE);
9683         aopOp(result,ic,FALSE);
9684
9685         
9686         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9687
9688         if (IS_BITFIELD(retype))
9689         {
9690           genPackBits (retype, result, right, GPOINTER);
9691           return;
9692         }
9693
9694         {
9695           /* emit call to __gptrput */
9696           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9697           int size = AOP_SIZE(right);
9698           int idx = 0;
9699
9700           assert (size == getSize(OP_SYM_ETYPE(result)));
9701           assert (size > 0 && size <= 4);
9702
9703           /* pass arguments */
9704           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9705           {
9706             int off = size;
9707             idx = 2;
9708             while (off--)
9709             {
9710               mov2w_op (right, off);
9711               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9712             }
9713             idx = 0;
9714           }
9715           /* - address */
9716           assert (AOP_SIZE(result) == 3);
9717           mov2w(AOP(result), 0);
9718           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9719           mov2w(AOP(result), 1);
9720           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9721           mov2w(AOP(result), 2);
9722           call_libraryfunc (func[size]);
9723         }
9724         
9725         freeAsmop(right,NULL,ic,TRUE);
9726         freeAsmop(result,NULL,ic,TRUE);
9727 }
9728
9729 /*-----------------------------------------------------------------*/
9730 /* genPointerSet - stores the value into a pointer location        */
9731 /*-----------------------------------------------------------------*/
9732 static void genPointerSet (iCode *ic)
9733 {    
9734         operand *right, *result ;
9735         sym_link *type, *etype;
9736         int p_type;
9737         
9738         FENTRY;
9739         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9740         
9741         right = IC_RIGHT(ic);
9742         result = IC_RESULT(ic) ;
9743         
9744         /* depending on the type of pointer we need to
9745         move it to the correct pointer register */
9746         type = operandType(result);
9747         etype = getSpec(type);
9748         /* if left is of type of pointer then it is simple */
9749         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9750                 p_type = DCL_TYPE(type);
9751         }
9752         else {
9753                 /* we have to go by the storage class */
9754                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9755                 
9756                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9757                 /*      p_type = CPOINTER ;  */
9758                 /*  } */
9759                 /*  else */
9760                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9761                 /*    p_type = FPOINTER ; */
9762                 /*      else */
9763                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9764                 /*        p_type = PPOINTER ; */
9765                 /*    else */
9766                 /*        if (SPEC_OCLS(etype) == idata ) */
9767                 /*      p_type = IPOINTER ; */
9768                 /*        else */
9769                 /*      p_type = POINTER ; */
9770         }
9771         
9772         /* now that we have the pointer type we assign
9773         the pointer values */
9774         switch (p_type) {
9775                 
9776         case POINTER:
9777         //case IPOINTER:
9778                 genNearPointerSet (right,result,ic);
9779                 break;
9780 /*
9781         case PPOINTER:
9782                 genPagedPointerSet (right,result,ic);
9783                 break;
9784                 
9785         case FPOINTER:
9786                 genFarPointerSet (right,result,ic);
9787                 break;
9788 */
9789         case GPOINTER:
9790                 genGenPointerSet (right,result,ic);
9791                 break;
9792                 
9793         default:
9794                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9795                         "genPointerSet: illegal pointer type");
9796         }
9797 }
9798
9799 /*-----------------------------------------------------------------*/
9800 /* genIfx - generate code for Ifx statement                        */
9801 /*-----------------------------------------------------------------*/
9802 static void genIfx (iCode *ic, iCode *popIc)
9803 {
9804         operand *cond = IC_COND(ic);
9805         int isbit =0;
9806         
9807         FENTRY;
9808         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9809         
9810         aopOp(cond,ic,FALSE);
9811         
9812         /* get the value into acc */
9813         if (AOP_TYPE(cond) != AOP_CRY)
9814                 pic14_toBoolean(cond);
9815         else
9816                 isbit = 1;
9817         /* the result is now in the accumulator */
9818         freeAsmop(cond,NULL,ic,TRUE);
9819         
9820         /* if there was something to be popped then do it */
9821         if (popIc)
9822                 genIpop(popIc);
9823         
9824         if (isbit)
9825         {
9826                 assert (!"genIfx not implemented for bit variables...");
9827         }
9828         else
9829         {
9830                 /* now Z if set iff !cond */
9831                 if (IC_TRUE(ic))
9832                 {
9833                         assert (!IC_FALSE(ic));
9834                         emitSKPZ;
9835                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9836                 } else {
9837                         emitSKPNZ;
9838                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9839                 }
9840         }
9841         
9842         ic->generated = 1;
9843         
9844 }
9845
9846 /*-----------------------------------------------------------------*/
9847 /* genAddrOf - generates code for address of                       */
9848 /*-----------------------------------------------------------------*/
9849 static void genAddrOf (iCode *ic)
9850 {
9851         operand *right, *result, *left;
9852         int size, offset ;
9853         
9854         FENTRY;
9855         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9856         
9857         
9858         //aopOp(IC_RESULT(ic),ic,FALSE);
9859         
9860         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9861         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9862         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9863         
9864         DEBUGpic14_AopType(__LINE__,left,right,result);
9865         assert (IS_SYMOP (left));
9866         
9867         /* sanity check: generic pointers to code space are not yet supported,
9868          * pionters to codespace must not be assigned addresses of __data values. */
9869  #if 0
9870         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9871         fprintf (stderr, "result->type : "); printTypeChain (OP_SYM_TYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(result)))), IS_CODEPTR(OP_SYM_TYPE(result)), IS_PTR_CONST(OP_SYM_TYPE(result)));
9872         fprintf (stderr, "result->etype: "); printTypeChain (OP_SYM_ETYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(result)))), IS_CODEPTR(OP_SYM_ETYPE(result)), IS_PTR_CONST(OP_SYM_ETYPE(result)));
9873         fprintf (stderr, "left->type   : "); printTypeChain (OP_SYM_TYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left)))), IS_CODEPTR(OP_SYM_TYPE(left)), IS_PTR_CONST(OP_SYM_TYPE(left)));
9874         fprintf (stderr, "left->etype  : "); printTypeChain (OP_SYM_ETYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n",IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(left)))), IS_CODEPTR(OP_SYM_ETYPE(left)), IS_PTR_CONST(OP_SYM_ETYPE(left)));
9875 #endif
9876
9877         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9878           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9879                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9880                 OP_SYMBOL(left)->name);
9881         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9882           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9883                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9884                 OP_SYMBOL(left)->name);
9885         }
9886         
9887         size = AOP_SIZE(IC_RESULT(ic));
9888         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9889                 /* strip tag */
9890                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9891         }
9892         offset = 0;
9893         
9894         while (size--) {
9895                 /* fixing bug #863624, reported from (errolv) */
9896                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9897                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9898                 
9899 #if 0
9900                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9901                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9902 #endif
9903                 offset++;
9904         }
9905
9906         if (IS_GENPTR(OP_SYM_TYPE(result)))
9907         {
9908                 /* provide correct tag */
9909                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9910                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9911                 movwf (AOP(result), 2);
9912         }
9913         
9914         freeAsmop(left,NULL,ic,FALSE);
9915         freeAsmop(result,NULL,ic,TRUE);
9916         
9917 }
9918
9919 #if 0
9920 /*-----------------------------------------------------------------*/
9921 /* genFarFarAssign - assignment when both are in far space         */
9922 /*-----------------------------------------------------------------*/
9923 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9924 {
9925         int size = AOP_SIZE(right);
9926         int offset = 0;
9927         char *l ;
9928         /* first push the right side on to the stack */
9929         while (size--) {
9930                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9931                 MOVA(l);
9932                 pic14_emitcode ("push","acc");
9933         }
9934         
9935         freeAsmop(right,NULL,ic,FALSE);
9936         /* now assign DPTR to result */
9937         aopOp(result,ic,FALSE);
9938         size = AOP_SIZE(result);
9939         while (size--) {
9940                 pic14_emitcode ("pop","acc");
9941                 aopPut(AOP(result),"a",--offset);
9942         }
9943         freeAsmop(result,NULL,ic,FALSE);
9944         
9945 }
9946 #endif
9947
9948 /*-----------------------------------------------------------------*/
9949 /* genAssign - generate code for assignment                        */
9950 /*-----------------------------------------------------------------*/
9951 static void genAssign (iCode *ic)
9952 {
9953         operand *result, *right;
9954         int size, offset,know_W;
9955         unsigned long lit = 0L;
9956         
9957         result = IC_RESULT(ic);
9958         right  = IC_RIGHT(ic) ;
9959         
9960         FENTRY;
9961         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9962         
9963         /* if they are the same */
9964         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9965                 return ;
9966         
9967         aopOp(right,ic,FALSE);
9968         aopOp(result,ic,TRUE);
9969         
9970         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9971         
9972         /* if they are the same registers */
9973         if (pic14_sameRegs(AOP(right),AOP(result)))
9974                 goto release;
9975
9976         /* special case: assign from __code */
9977         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9978                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9979                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9980                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9981                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9982         {
9983           emitpComment ("genAssign from CODESPACE");
9984           genConstPointerGet (right, result, ic);
9985           goto release;
9986         }
9987         
9988         /* just for symmetry reasons... */
9989         if (!IS_ITEMP(result)
9990                 && IS_SYMOP (result)
9991                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9992         {
9993           assert ( !"cannot write to CODESPACE" );
9994         }
9995
9996         /* if the result is a bit */
9997         if (AOP_TYPE(result) == AOP_CRY) {
9998                 
9999         /* if the right size is a literal then
10000                 we know what the value is */
10001                 if (AOP_TYPE(right) == AOP_LIT) {
10002                         
10003                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10004                                 popGet(AOP(result),0));
10005                         
10006                         if (((int) operandLitValue(right))) 
10007                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10008                                 AOP(result)->aopu.aop_dir,
10009                                 AOP(result)->aopu.aop_dir);
10010                         else
10011                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10012                                 AOP(result)->aopu.aop_dir,
10013                                 AOP(result)->aopu.aop_dir);
10014                         goto release;
10015                 }
10016                 
10017                 /* the right is also a bit variable */
10018                 if (AOP_TYPE(right) == AOP_CRY) {
10019                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10020                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10021                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10022                         
10023                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10024                                 AOP(result)->aopu.aop_dir,
10025                                 AOP(result)->aopu.aop_dir);
10026                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10027                                 AOP(right)->aopu.aop_dir,
10028                                 AOP(right)->aopu.aop_dir);
10029                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10030                                 AOP(result)->aopu.aop_dir,
10031                                 AOP(result)->aopu.aop_dir);
10032                         goto release ;
10033                 }
10034                 
10035                 /* we need to or */
10036                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10037                 pic14_toBoolean(right);
10038                 emitSKPZ;
10039                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10040                 //aopPut(AOP(result),"a",0);
10041                 goto release ;
10042         }
10043         
10044         /* bit variables done */
10045         /* general case */
10046         size = AOP_SIZE(result);
10047         offset = 0 ;
10048         if(AOP_TYPE(right) == AOP_LIT)
10049                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10050         
10051         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10052                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10053                 if(aopIdx(AOP(result),0) == 4) {
10054                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10055                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10056                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10057                         goto release;
10058                 } else
10059                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10060         }
10061         
10062         know_W=-1;
10063         while (size--) {
10064                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10065                 if(AOP_TYPE(right) == AOP_LIT) {
10066                         if(lit&0xff) {
10067                                 if(know_W != (int)(lit&0xff))
10068                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10069                                 know_W = lit&0xff;
10070                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10071                         } else
10072                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10073                         
10074                         lit >>= 8;
10075                         
10076                 } else if (AOP_TYPE(right) == AOP_CRY) {
10077                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10078                         if(offset == 0) {
10079                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10080                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10081                         }
10082                 } else {
10083                         mov2w_op (right, offset);
10084                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10085                 }
10086                 
10087                 offset++;
10088         }
10089         
10090         
10091 release:
10092         freeAsmop (right,NULL,ic,FALSE);
10093         freeAsmop (result,NULL,ic,TRUE);
10094 }   
10095
10096 /*-----------------------------------------------------------------*/
10097 /* genJumpTab - genrates code for jump table                       */
10098 /*-----------------------------------------------------------------*/
10099 static void genJumpTab (iCode *ic)
10100 {
10101         symbol *jtab;
10102         char *l;
10103         
10104         FENTRY;
10105         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10106         
10107         aopOp(IC_JTCOND(ic),ic,FALSE);
10108         /* get the condition into accumulator */
10109         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10110         MOVA(l);
10111         /* multiply by three */
10112         pic14_emitcode("add","a,acc");
10113         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10114         
10115         jtab = newiTempLabel(NULL);
10116         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10117         pic14_emitcode("jmp","@a+dptr");
10118         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10119         
10120         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10121         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10122         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10123         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10124         emitSKPNC;
10125         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10126         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10127         emitpLabel(jtab->key);
10128         
10129         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10130         
10131         /* now generate the jump labels */
10132         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10133         jtab = setNextItem(IC_JTLABELS(ic))) {
10134                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10135                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10136                 
10137         }
10138         
10139 }
10140
10141 /*-----------------------------------------------------------------*/
10142 /* genMixedOperation - gen code for operators between mixed types  */
10143 /*-----------------------------------------------------------------*/
10144 /*
10145 TSD - Written for the PIC port - but this unfortunately is buggy.
10146 This routine is good in that it is able to efficiently promote 
10147 types to different (larger) sizes. Unfortunately, the temporary
10148 variables that are optimized out by this routine are sometimes
10149 used in other places. So until I know how to really parse the 
10150 iCode tree, I'm going to not be using this routine :(.
10151 */
10152 static int genMixedOperation (iCode *ic)
10153 {
10154         FENTRY;
10155 #if 0
10156         operand *result = IC_RESULT(ic);
10157         sym_link *ctype = operandType(IC_LEFT(ic));
10158         operand *right = IC_RIGHT(ic);
10159         int ret = 0;
10160         int big,small;
10161         int offset;
10162         
10163         iCode *nextic;
10164         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10165         
10166         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10167         
10168         nextic = ic->next;
10169         if(!nextic)
10170                 return 0;
10171         
10172         nextright = IC_RIGHT(nextic);
10173         nextleft  = IC_LEFT(nextic);
10174         nextresult = IC_RESULT(nextic);
10175         
10176         aopOp(right,ic,FALSE);
10177         aopOp(result,ic,FALSE);
10178         aopOp(nextright,  nextic, FALSE);
10179         aopOp(nextleft,   nextic, FALSE);
10180         aopOp(nextresult, nextic, FALSE);
10181         
10182         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10183                 
10184                 operand *t = right;
10185                 right = nextright;
10186                 nextright = t; 
10187                 
10188                 pic14_emitcode(";remove right +","");
10189                 
10190         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10191         /*
10192         operand *t = right;
10193         right = nextleft;
10194         nextleft = t; 
10195                 */
10196                 pic14_emitcode(";remove left +","");
10197         } else
10198                 return 0;
10199         
10200         big = AOP_SIZE(nextleft);
10201         small = AOP_SIZE(nextright);
10202         
10203         switch(nextic->op) {
10204                 
10205         case '+':
10206                 pic14_emitcode(";optimize a +","");
10207                 /* if unsigned or not an integral type */
10208                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10209                         pic14_emitcode(";add a bit to something","");
10210                 } else {
10211                         
10212                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10213                         
10214                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10215                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10216                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10217                         } else
10218                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10219                         
10220                         offset = 0;
10221                         while(--big) {
10222                                 
10223                                 offset++;
10224                                 
10225                                 if(--small) {
10226                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10227                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10228                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10229                                         }
10230                                         
10231                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10232                                         emitSKPNC;
10233                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10234                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10235                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10236                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10237                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10238                                         
10239                                 } else {
10240                                         pic14_emitcode("rlf","known_zero,w");
10241                                         
10242                                         /*
10243                                         if right is signed
10244                                         btfsc  right,7
10245                                         addlw ff
10246                                         */
10247                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10248                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10249                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10250                                         } else {
10251                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10252                                         }
10253                                 }
10254                         }
10255                         ret = 1;
10256                 }
10257         }
10258         ret = 1;
10259         
10260 release:
10261         freeAsmop(right,NULL,ic,TRUE);
10262         freeAsmop(result,NULL,ic,TRUE);
10263         freeAsmop(nextright,NULL,ic,TRUE);
10264         freeAsmop(nextleft,NULL,ic,TRUE);
10265         if(ret)
10266                 nextic->generated = 1;
10267         
10268         return ret;
10269 #else
10270         return 0;
10271 #endif
10272 }
10273 /*-----------------------------------------------------------------*/
10274 /* genCast - gen code for casting                                  */
10275 /*-----------------------------------------------------------------*/
10276 static void genCast (iCode *ic)
10277 {
10278         operand *result = IC_RESULT(ic);
10279         sym_link *restype = operandType(result);
10280         sym_link *rtype = operandType(IC_RIGHT(ic));
10281         operand *right = IC_RIGHT(ic);
10282         int size, offset ;
10283         
10284         FENTRY;
10285         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10286         /* if they are equivalent then do nothing */
10287         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10288                 return ;
10289         
10290         aopOp(right,ic,FALSE) ;
10291         aopOp(result,ic,FALSE);
10292         
10293         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10294         
10295         /* if the result is a bit */
10296         if (AOP_TYPE(result) == AOP_CRY) {
10297                 assert(!"assigning to bit variables is not supported");
10298         }
10299         
10300         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10301                 int offset = 1;
10302                 size = AOP_SIZE(result);
10303                 
10304                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10305                 
10306                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10307                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10308                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10309                 
10310                 while (size--)
10311                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10312                 
10313                 goto release;
10314         }
10315         
10316         if (IS_PTR(restype))
10317         {
10318           operand *result = IC_RESULT(ic);
10319           //operand *left = IC_LEFT(ic);
10320           operand *right = IC_RIGHT(ic);
10321           int tag = 0xff;
10322           
10323           /* copy common part */
10324           int max, size = AOP_SIZE(result);
10325           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10326           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10327
10328           /* warn if we discard generic opinter tag */
10329           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10330           {
10331             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10332           } // if
10333
10334           max = size;
10335           while (size--)
10336           {
10337             mov2w_op (right, size);
10338             movwf (AOP(result), size);
10339           } // while
10340
10341           /* upcast into generic pointer type? */
10342           if (IS_GENPTR(restype)
10343                 && (size < AOP_SIZE(result))
10344                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10345           {
10346             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10347             if (IS_PTR(rtype))
10348             {
10349               switch (DCL_TYPE(rtype))
10350               {
10351               case POINTER:     /* __data */
10352               case FPOINTER:    /* __data */
10353                 assert (AOP_SIZE(right) == 2);
10354                 tag = GPTRTAG_DATA;
10355                 break;
10356
10357               case CPOINTER:    /* __code */
10358                 assert (AOP_SIZE(right) == 2);
10359                 tag = GPTRTAG_CODE;
10360                 break;
10361                 
10362               case GPOINTER:    /* unknown destination, __data or __code */
10363                 /* assume __data space (address of immediate) */
10364                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10365                 if (AOP(right)->code)
10366                   tag = GPTRTAG_CODE;
10367                 else
10368                   tag = GPTRTAG_DATA;
10369                 break;
10370                 
10371               default:
10372                 assert (!"unhandled pointer type");
10373               } // switch
10374             } else {
10375               /* convert other values into pointers to __data space */
10376               tag = GPTRTAG_DATA;
10377             }
10378
10379             assert (AOP_SIZE(result) == 3);
10380             if (tag == 0) {
10381               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10382             } else {
10383               emitpcode(POC_MOVLW, popGetLit(tag));
10384               movwf(AOP(result), 2);
10385             }
10386           } else {
10387             addSign(result, max, 0);
10388           } // if
10389           goto release;
10390         }
10391         
10392         /* if they are the same size : or less */
10393         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10394                 
10395                 /* if they are in the same place */
10396                 if (pic14_sameRegs(AOP(right),AOP(result)))
10397                         goto release;
10398                 
10399                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10400                 if (IS_PTR_CONST(rtype))
10401                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10402                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10403                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10404                 
10405                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10406                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10407                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10408                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10409                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10410                         if(AOP_SIZE(result) <2)
10411                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10412                         
10413                 } else {
10414                         
10415                         /* if they in different places then copy */
10416                         size = AOP_SIZE(result);
10417                         offset = 0 ;
10418                         while (size--) {
10419                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10420                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10421                                 
10422                                 //aopPut(AOP(result),
10423                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10424                                 // offset);
10425                                 
10426                                 offset++;
10427                         }
10428                 }
10429                 goto release;
10430         }
10431         
10432         /* so we now know that the size of destination is greater
10433         than the size of the source.
10434         Now, if the next iCode is an operator then we might be
10435         able to optimize the operation without performing a cast.
10436         */
10437         if(0 && genMixedOperation(ic)) {
10438                 /* XXX: cannot optimize: must copy regs! */
10439                 goto release;
10440         }
10441         
10442         /* we move to result for the size of source */
10443         size = AOP_SIZE(right);
10444         offset = 0 ;
10445         while (size--) {
10446                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10447                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10448                 offset++;
10449         }
10450
10451         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10452
10453 release:
10454         freeAsmop(right,NULL,ic,TRUE);
10455         freeAsmop(result,NULL,ic,TRUE);
10456         
10457 }
10458
10459 /*-----------------------------------------------------------------*/
10460 /* genDjnz - generate decrement & jump if not zero instrucion      */
10461 /*-----------------------------------------------------------------*/
10462 static int genDjnz (iCode *ic, iCode *ifx)
10463 {
10464         symbol *lbl, *lbl1;
10465         FENTRY;
10466         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10467         
10468         if (!ifx)
10469                 return 0;
10470         
10471                 /* if the if condition has a false label
10472         then we cannot save */
10473         if (IC_FALSE(ifx))
10474                 return 0;
10475         
10476                 /* if the minus is not of the form 
10477         a = a - 1 */
10478         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10479                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10480                 return 0;
10481         
10482         if (operandLitValue(IC_RIGHT(ic)) != 1)
10483                 return 0;
10484         
10485                 /* if the size of this greater than one then no
10486         saving */
10487         if (getSize(operandType(IC_RESULT(ic))) > 1)
10488                 return 0;
10489         
10490         /* otherwise we can save BIG */
10491         lbl = newiTempLabel(NULL);
10492         lbl1= newiTempLabel(NULL);
10493         
10494         aopOp(IC_RESULT(ic),ic,FALSE);
10495         
10496         if (IS_AOP_PREG(IC_RESULT(ic))) {
10497                 pic14_emitcode("dec","%s",
10498                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10499                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10500                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10501         } else {  
10502                 
10503                 
10504                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10505                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10506                 
10507                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10508                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10509                 
10510         }
10511         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10512         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10513         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10514         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10515         
10516         
10517         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10518         ifx->generated = 1;
10519         return 1;
10520 }
10521
10522 /*-----------------------------------------------------------------*/
10523 /* genReceive - generate code for a receive iCode                  */
10524 /*-----------------------------------------------------------------*/
10525 static void genReceive (iCode *ic)
10526 {
10527         FENTRY;
10528         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10529         
10530         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10531                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10532                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10533                 
10534                 int size = getSize(operandType(IC_RESULT(ic)));
10535                 int offset =  fReturnSizePic - size;
10536                 while (size--) {
10537                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10538                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10539                         offset++;
10540                 }
10541                 aopOp(IC_RESULT(ic),ic,FALSE);
10542                 size = AOP_SIZE(IC_RESULT(ic));
10543                 offset = 0;
10544                 while (size--) {
10545                         pic14_emitcode ("pop","acc");
10546                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10547                 }
10548                 
10549         } else {
10550                 _G.accInUse++;
10551                 aopOp(IC_RESULT(ic),ic,FALSE);
10552                 _G.accInUse--;
10553                 assignResultValue(IC_RESULT(ic));
10554         }
10555         
10556         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10557 }
10558
10559 /*-----------------------------------------------------------------*/
10560 /* genDummyRead - generate code for dummy read of volatiles        */
10561 /*-----------------------------------------------------------------*/
10562 static void
10563 genDummyRead (iCode * ic)
10564 {
10565         FENTRY;
10566         pic14_emitcode ("; genDummyRead","");
10567         pic14_emitcode ("; not implemented","");
10568         
10569         ic = ic;
10570 }
10571
10572 /*-----------------------------------------------------------------*/
10573 /* genpic14Code - generate code for pic14 based controllers        */
10574 /*-----------------------------------------------------------------*/
10575 /*
10576 * At this point, ralloc.c has gone through the iCode and attempted
10577 * to optimize in a way suitable for a PIC. Now we've got to generate
10578 * PIC instructions that correspond to the iCode.
10579 *
10580 * Once the instructions are generated, we'll pass through both the
10581 * peep hole optimizer and the pCode optimizer.
10582 *-----------------------------------------------------------------*/
10583
10584 void genpic14Code (iCode *lic)
10585 {
10586         iCode *ic;
10587         int cln = 0;
10588         const char *cline;
10589         
10590         FENTRY;
10591         lineHead = lineCurr = NULL;
10592         
10593         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10594         addpBlock(pb);
10595         
10596         /* if debug information required */
10597         if (options.debug && currFunc) { 
10598                 if (currFunc) {
10599                         debugFile->writeFunction (currFunc, lic);
10600                 }
10601         }
10602         
10603         
10604         for (ic = lic ; ic ; ic = ic->next ) {
10605                 
10606                 //DEBUGpic14_emitcode(";ic","");
10607                 //fprintf (stderr, "in ic loop\n");
10608                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10609                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10610                 
10611                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10612                   cln = ic->lineno;
10613                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10614                   cline = printCLine (ic->filename, ic->lineno);
10615                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10616                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10617                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10618                 }
10619                 
10620                 if (options.iCodeInAsm) {
10621                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10622                 }
10623                 /* if the result is marked as
10624                 spilt and rematerializable or code for
10625                 this has already been generated then
10626                 do nothing */
10627                 if (resultRemat(ic) || ic->generated ) 
10628                         continue ;
10629                 
10630                 /* depending on the operation */
10631                 switch (ic->op) {
10632                 case '!' :
10633                         genNot(ic);
10634                         break;
10635                         
10636                 case '~' :
10637                         genCpl(ic);
10638                         break;
10639                         
10640                 case UNARYMINUS:
10641                         genUminus (ic);
10642                         break;
10643                         
10644                 case IPUSH:
10645                         genIpush (ic);
10646                         break;
10647                         
10648                 case IPOP:
10649                         /* IPOP happens only when trying to restore a 
10650                         spilt live range, if there is an ifx statement
10651                         following this pop then the if statement might
10652                         be using some of the registers being popped which
10653                         would destory the contents of the register so
10654                         we need to check for this condition and handle it */
10655                         if (ic->next            && 
10656                                 ic->next->op == IFX &&
10657                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10658                                 genIfx (ic->next,ic);
10659                         else
10660                                 genIpop (ic);
10661                         break; 
10662                         
10663                 case CALL:
10664                         genCall (ic);
10665                         break;
10666                         
10667                 case PCALL:
10668                         genPcall (ic);
10669                         break;
10670                         
10671                 case FUNCTION:
10672                         genFunction (ic);
10673                         break;
10674                         
10675                 case ENDFUNCTION:
10676                         genEndFunction (ic);
10677                         break;
10678                         
10679                 case RETURN:
10680                         genRet (ic);
10681                         break;
10682                         
10683                 case LABEL:
10684                         genLabel (ic);
10685                         break;
10686                         
10687                 case GOTO:
10688                         genGoto (ic);
10689                         break;
10690                         
10691                 case '+' :
10692                         genPlus (ic) ;
10693                         break;
10694                         
10695                 case '-' :
10696                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10697                                 genMinus (ic);
10698                         break;
10699                         
10700                 case '*' :
10701                         genMult (ic);
10702                         break;
10703                         
10704                 case '/' :
10705                         genDiv (ic) ;
10706                         break;
10707                         
10708                 case '%' :
10709                         genMod (ic);
10710                         break;
10711                         
10712                 case '>' :
10713                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10714                         break;
10715                         
10716                 case '<' :
10717                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10718                         break;
10719                         
10720                 case LE_OP:
10721                 case GE_OP:
10722                 case NE_OP:
10723                         
10724                         /* note these two are xlated by algebraic equivalence
10725                         during parsing SDCC.y */
10726                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10727                                 "got '>=' or '<=' shouldn't have come here");
10728                         break;  
10729                         
10730                 case EQ_OP:
10731                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10732                         break;      
10733                         
10734                 case AND_OP:
10735                         genAndOp (ic);
10736                         break;
10737                         
10738                 case OR_OP:
10739                         genOrOp (ic);
10740                         break;
10741                         
10742                 case '^' :
10743                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10744                         break;
10745                         
10746                 case '|' :
10747                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10748                         break;
10749                         
10750                 case BITWISEAND:
10751                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10752                         break;
10753                         
10754                 case INLINEASM:
10755                         genInline (ic);
10756                         break;
10757                         
10758                 case RRC:
10759                         genRRC (ic);
10760                         break;
10761                         
10762                 case RLC:
10763                         genRLC (ic);
10764                         break;
10765                         
10766                 case GETHBIT:
10767                         genGetHbit (ic);
10768                         break;
10769                         
10770                 case LEFT_OP:
10771                         genLeftShift (ic);
10772                         break;
10773                         
10774                 case RIGHT_OP:
10775                         genRightShift (ic);
10776                         break;
10777                         
10778                 case GET_VALUE_AT_ADDRESS:
10779                         genPointerGet(ic);
10780                         break;
10781                         
10782                 case '=' :
10783                         if (POINTER_SET(ic))
10784                                 genPointerSet(ic);
10785                         else
10786                                 genAssign(ic);
10787                         break;
10788                         
10789                 case IFX:
10790                         genIfx (ic,NULL);
10791                         break;
10792                         
10793                 case ADDRESS_OF:
10794                         genAddrOf (ic);
10795                         break;
10796                         
10797                 case JUMPTABLE:
10798                         genJumpTab (ic);
10799                         break;
10800                         
10801                 case CAST:
10802                         genCast (ic);
10803                         break;
10804                         
10805                 case RECEIVE:
10806                         genReceive(ic);
10807                         break;
10808                         
10809                 case SEND:
10810                         addSet(&_G.sendSet,ic);
10811                         break;
10812                         
10813                 case DUMMY_READ_VOLATILE:
10814                         genDummyRead (ic);
10815                         break;
10816                         
10817                 default :
10818                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10819                         ic = ic;
10820                         break;
10821                 }
10822         }
10823
10824         
10825         /* now we are ready to call the
10826         peep hole optimizer */
10827         if (!options.nopeep) {
10828                 peepHole (&lineHead);
10829         }
10830         /* now do the actual printing */
10831         printLine (lineHead,codeOutFile);
10832         
10833 #ifdef PCODE_DEBUG
10834         DFPRINTF((stderr,"printing pBlock\n\n"));
10835         printpBlock(stdout,pb);
10836 #endif
10837         
10838         return;
10839 }
10840
10841 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10842  * (meaning: representing its own address) or not (referencing its contents).
10843  * This can only be decided based on the operand's type. */
10844 int
10845 aop_isLitLike (asmop *aop)
10846 {
10847   assert (aop);
10848   if (aop->type == AOP_LIT) return 1;
10849 if (aop->type == AOP_IMMD) return 1;
10850   if ((aop->type == AOP_PCODE) &&
10851                 ((aop->aopu.pcop->type == PO_LITERAL)))
10852   {
10853     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10854      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10855     return 1;
10856   }
10857   return 0;
10858 }
10859
10860 int
10861 op_isLitLike (operand *op)
10862 {
10863   assert (op);
10864   if (aop_isLitLike (AOP(op))) return 1;
10865   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10866   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10867   return 0;
10868 }