* src/pic/gen.c (genGenPointerSet): removed bogus assertion
[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 AT 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 #include "glue.h"
46
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
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 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
60
61 /* max_key keeps track of the largest label number used in 
62 a function. This is then used to adjust the label offset
63 for the next function.
64 */
65 static int max_key=0;
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
68
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
72
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
74
75 /* this is the down and dirty file with all kinds of 
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
79
80 static char *zero = "0x00";
81 static char *one  = "0x01";
82 static char *spname = "sp";
83
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
87
88 //static char *accUse[] = {"a","b"};
89
90 //static short rbank = -1;
91
92 static struct {
93         short r0Pushed;
94         short r1Pushed;
95         short accInUse;
96         short inLine;
97         short debugLine;
98         short nRegsSaved;
99         set *sendSet;
100 } _G;
101
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
104 */
105 typedef struct resolvedIfx {
106         symbol *lbl;     /* pointer to a label */
107         int condition;   /* true or false ifx */
108         int generated;   /* set true when the code associated with the ifx
109                           * is generated */
110 } resolvedIfx;
111
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 #if 0
121 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
125 #endif
126
127 static  pBlock *pb;
128
129 /*-----------------------------------------------------------------*/
130 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
131 /*                                 exponent of 2 is returned, otherwise -1 is      */
132 /*                                 returned.                                                                       */
133 /* note that this is similar to the function `powof2' in SDCCsymt  */
134 /* if(n == 2^y)                                                                                                    */
135 /*       return y;                                                                                                         */
136 /* return -1;                                                                                                      */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
139 {
140         if(num) {
141                 if( (num & (num-1)) == 0) {
142                         int nshifts = -1;
143                         while(num) {
144                                 num>>=1;
145                                 nshifts++;
146                         }
147                         return nshifts;
148                 }
149         }
150         
151         return -1;
152 }
153
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
155 {
156         
157         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
158                 line_no,
159                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161                 ((result) ? AOP_SIZE(result) : 0),
162                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
163                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164                 ((left)   ? AOP_SIZE(left) : 0),
165                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
166                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167                 ((right)  ? AOP_SIZE(right) : 0));
168         
169 }
170
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
172 {
173         
174         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
175                 line_no,
176                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
177                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
179                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
180                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
181                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
182         
183 }
184
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
186 {
187         va_list ap;
188         char lb[INITIAL_INLINEASM];  
189         unsigned char *lbp = (unsigned char *)lb;
190         
191         if(!debug_verbose && !options.debug)
192                 return;
193         
194         va_start(ap,fmt);   
195         
196         if (inst && *inst) {
197                 if (fmt && *fmt)
198                         sprintf(lb,"%s\t",inst);
199                 else
200                         sprintf(lb,"%s",inst);
201                 vsprintf(lb+(strlen(lb)),fmt,ap);
202         }  else
203                 vsprintf(lb,fmt,ap);
204         
205         while (isspace(*lbp)) lbp++;
206         
207         if (lbp && *lbp) 
208                 lineCurr = (lineCurr ?
209                 connectLine(lineCurr,newLineNode(lb)) :
210         (lineHead = newLineNode(lb)));
211         lineCurr->isInline = _G.inLine;
212         lineCurr->isDebug  = _G.debugLine;
213         
214         addpCode2pBlock(pb,newpCodeCharP(lb));
215         
216         va_end(ap);
217 }
218
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
220 {
221 #if defined (HAVE_VSNPRINTF)
222   vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224   vsprintf (buf, size, fmt, ap);
225   if (strlen (buf) >= size)
226   {
227     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
228   }
229 #elif defined (HAVE_SNPRINTF)
230   snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232   sprintf (buf, "vs(n)printf required");
233   if (strlen (buf) >= size)
234   {
235     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
236   }
237 #else
238   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
239 #endif
240 }
241
242 void emitpComment (const char *fmt, ...)
243 {
244   va_list va;
245   char buffer[4096];
246   
247   va_start (va, fmt);
248   if (pb) {
249     Safe_vsnprintf (buffer, 4096, fmt, va);
250     //fprintf (stderr, "%s\n" ,buffer);
251     addpCode2pBlock (pb, newpCodeCharP (buffer));
252 #if 0
253   } else {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
256 #endif
257   }
258   va_end (va);
259 }
260
261 void emitpLabel(int key)
262 {
263         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
264 }
265
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267  * as this allows for easy debugging (ever asked the question: where was
268  * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
270 {
271         if(pcop)
272                 addpCode2pBlock(pb,newpCode(poc,pcop));
273         else {
274                 static int has_warned = 0;
275                 
276                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
277                 if (!has_warned) {
278                         has_warned = 1;
279                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
280                 }
281         }
282 }
283
284 void emitpcodeNULLop(PIC_OPCODE poc)
285 {
286         
287         addpCode2pBlock(pb,newpCode(poc,NULL));
288         
289 }
290
291
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple    */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
296 {
297         va_list ap;
298         char lb[INITIAL_INLINEASM];  
299         char *lbp = lb;
300         
301         va_start(ap,fmt);   
302         
303         if (inst && *inst) {
304                 if (fmt && *fmt)
305                         sprintf(lb,"%s\t",inst);
306                 else
307                         sprintf(lb,"%s",inst);
308                 vsprintf(lb+(strlen(lb)),fmt,ap);
309         }  else
310                 vsprintf(lb,fmt,ap);
311         
312         while (isspace(*lbp)) lbp++;
313         
314         if (lbp && *lbp) 
315                 lineCurr = (lineCurr ?
316                 connectLine(lineCurr,newLineNode(lb)) :
317         (lineHead = newLineNode(lb)));
318         lineCurr->isInline = _G.inLine;
319         lineCurr->isDebug  = _G.debugLine;
320         lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
321         
322         if(debug_verbose)
323                 addpCode2pBlock(pb,newpCodeCharP(lb));
324         
325         va_end(ap);
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location  */
330 /*       with a debugger symbol                                                                            */
331 /*-----------------------------------------------------------------*/
332 void
333 pic14_emitDebuggerSymbol (char * debugSym)
334 {
335         _G.debugLine = 1;
336         pic14_emitcode ("", ";%s ==.", debugSym);
337         _G.debugLine = 0;
338 }
339
340 #if 0
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
345 {
346         bool r0iu = FALSE , r1iu = FALSE;
347         bool r0ou = FALSE , r1ou = FALSE;
348         
349         /* the logic: if r0 & r1 used in the instruction
350         then we are in trouble otherwise */
351         
352         /* first check if r0 & r1 are used by this
353         instruction, in which case we are in trouble */
354         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
356         {
357                 goto endOfWorld;          
358         }
359         
360         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
362         
363         /* if no usage of r0 then return it */
364         if (!r0iu && !r0ou) {
365                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366                 (*aopp)->type = AOP_R0;
367                 
368                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
369         }
370         
371         /* if no usage of r1 then return it */
372         if (!r1iu && !r1ou) {
373                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374                 (*aopp)->type = AOP_R1;
375                 
376                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
377         }    
378         
379         /* now we know they both have usage */
380         /* if r0 not used in this instruction */
381         if (!r0iu) {
382                 /* push it if not already pushed */
383                 if (!_G.r0Pushed) {
384                         //pic14_emitcode ("push","%s",
385                         //                pic14_regWithIdx(R0_IDX)->dname);
386                         _G.r0Pushed++ ;
387                 }
388                 
389                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390                 (*aopp)->type = AOP_R0;
391                 
392                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
393         }
394         
395         /* if r1 not used then */
396         
397         if (!r1iu) {
398                 /* push it if not already pushed */
399                 if (!_G.r1Pushed) {
400                         //pic14_emitcode ("push","%s",
401                         //                pic14_regWithIdx(R1_IDX)->dname);
402                         _G.r1Pushed++ ;
403                 }
404                 
405                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406                 (*aopp)->type = AOP_R1;
407                 return pic14_regWithIdx(R1_IDX);
408         }
409         
410 endOfWorld :
411         /* I said end of world but not quite end of world yet */
412         /* if this is a result then we can push it on the stack*/
413         if (result) {
414                 (*aopp)->type = AOP_STK;        
415                 return NULL;
416         }
417         
418         /* other wise this is true end of the world */
419         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420                 "getFreePtr should never reach here");
421         exit(0);
422 }
423 #endif
424
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp                                                                  */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
429 {
430         asmop *aop;
431         
432         aop = Safe_calloc(1,sizeof(asmop));
433         aop->type = type;
434         return aop;
435 }
436
437 static void genSetDPTR(int n)
438 {
439         if (!n)
440         {
441                 pic14_emitcode(";", "Select standard DPTR");
442                 pic14_emitcode("mov", "dps, #0x00");
443         }
444         else
445         {
446                 pic14_emitcode(";", "Select alternate DPTR");
447                 pic14_emitcode("mov", "dps, #0x01");
448         }
449 }
450
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for  */
453 /*                              generating code                                                                    */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 {
457         if(!resIfx) 
458                 return;
459         
460         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
461         
462         resIfx->condition = 1;  /* assume that the ifx is true */
463         resIfx->generated = 0;  /* indicate that the ifx has not been used */
464         
465         if(!ifx) {
466                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
467                                                                                         /*
468                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
470                 */
471         } else {
472                 if(IC_TRUE(ifx)) {
473                         resIfx->lbl = IC_TRUE(ifx);
474                 } else {
475                         resIfx->lbl = IC_FALSE(ifx);
476                         resIfx->condition = 0;
477                 }
478                 /*
479                 if(IC_TRUE(ifx)) 
480                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
481                 if(IC_FALSE(ifx)) 
482                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
483                 */
484         }
485         
486         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
487         
488 }
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type                       */
491 /*-----------------------------------------------------------------*/
492 #if 0
493 static int pointerCode (sym_link *etype)
494 {
495         
496         return PTR_TYPE(SPEC_OCLS(etype));
497         
498 }
499 #endif
500
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol                                                                   */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
505 {
506         asmop *aop;
507         memmap *space= SPEC_OCLS(sym->etype);
508         
509         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510         /* if already has one */
511         if (sym->aop)
512                 return sym->aop;
513         
514         //DEBUGpic14_emitcode(";","%d",__LINE__);
515         /* if it is in direct space */
516         if (IN_DIRSPACE(space)) {
517                 sym->aop = aop = newAsmop (AOP_DIR);
518                 aop->aopu.aop_dir = sym->rname ;
519                 aop->size = getSize(sym->type);
520                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521                 return aop;
522         }
523         
524         /* special case for a function */
525         if (IS_FUNC(sym->type)) {   
526                 
527                 sym->aop = aop = newAsmop(AOP_PCODE);
528                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530                 PCOI(aop->aopu.pcop)->_function = 1;
531                 PCOI(aop->aopu.pcop)->index = 0;
532                 aop->size = FPTRSIZE; 
533                 /*
534                 sym->aop = aop = newAsmop(AOP_IMMD);    
535                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536                 strcpy(aop->aopu.aop_immd,sym->rname);
537                 aop->size = FPTRSIZE; 
538                 */
539                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540                 return aop;
541         }
542         
543         if (IS_ARRAY(sym->type)) {
544                 sym->aop = aop = newAsmop(AOP_PCODE);
545                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547                 PCOI(aop->aopu.pcop)->_function = 0;
548                 PCOI(aop->aopu.pcop)->index = 0;
549                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
550                 
551                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552                 return aop;
553         }
554         
555         /* only remaining is far space */
556         /* in which case DPTR gets the address */
557         sym->aop = aop = newAsmop(AOP_PCODE);
558         
559         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561         PCOI(aop->aopu.pcop)->index = 0;
562         
563         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565         
566         allocDirReg (IC_LEFT(ic));
567         
568         aop->size = FPTRSIZE;
569         /*
570         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571         sym->aop = aop = newAsmop(AOP_DPTR);
572         pic14_emitcode ("mov","dptr,#%s", sym->rname);
573         aop->size = getSize(sym->type);
574         
575           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
576         */
577         
578         /* if it is in code space */
579         if (IN_CODESPACE(space))
580                 aop->code = 1;
581         
582         return aop;       
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                                                   */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590         symbol *sym = OP_SYMBOL(op);
591         iCode *ic = NULL;
592         asmop *aop = newAsmop(AOP_PCODE);
593         int val = 0;
594         int offset = 0;
595         
596         ic = sym->rematiCode;
597
598         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599         if(IS_OP_POINTER(op)) {
600                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601         }
602         for (;;) {
603                 if (ic->op == '+') {
604                         val += (int) operandLitValue(IC_RIGHT(ic));
605                 } else if (ic->op == '-') {
606                         val -= (int) operandLitValue(IC_RIGHT(ic));
607                 } else
608                         break;
609                 
610                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611         }
612         
613         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616         PCOI(aop->aopu.pcop)->index = val;
617         
618         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620                 val, IS_PTR_CONST(operandType(op)));
621         
622         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
623         
624         allocDirReg (IC_LEFT(ic));
625         
626         return aop;              
627 }
628
629 int aopIdx (asmop *aop, int offset)
630 {
631         if(!aop)
632                 return -1;
633         
634         if(aop->type !=  AOP_REG)
635                 return -2;
636         
637         return aop->aopu.aop_reg[offset]->rIdx;
638         
639 }
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common       */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
644 {
645         symbol *sym1, *sym2;
646         int i;
647         
648         /* if they have registers in common */
649         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
650                 return FALSE ;
651         
652         sym1 = OP_SYMBOL(op1);
653         sym2 = OP_SYMBOL(op2);
654         
655         if (sym1->nRegs == 0 || sym2->nRegs == 0)
656                 return FALSE ;
657         
658         for (i = 0 ; i < sym1->nRegs ; i++) {
659                 int j;
660                 if (!sym1->regs[i])
661                         continue ;
662                 
663                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
664                         if (!sym2->regs[j])
665                                 continue ;
666                         
667                         if (sym2->regs[j] == sym1->regs[i])
668                                 return TRUE ;
669                 }
670         }
671         
672         return FALSE ;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                                                        */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
679 {
680         symbol *sym1, *sym2;
681         
682         /* if they not symbols */
683         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
684                 return FALSE;
685         
686         sym1 = OP_SYMBOL(op1);
687         sym2 = OP_SYMBOL(op2);
688         
689         /* if both are itemps & one is spilt
690         and the other is not then false */
691         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692                 sym1->isspilt != sym2->isspilt )
693                 return FALSE ;
694         
695         /* if they are the same */
696         if (sym1 == sym2)
697                 return TRUE ;
698         
699         if (sym1->rname[0] && sym2->rname[0]
700                 && strcmp (sym1->rname, sym2->rname) == 0)
701                 return TRUE;
702         
703         
704         /* if left is a tmp & right is not */
705         if (IS_ITEMP(op1)  && 
706                 !IS_ITEMP(op2) &&
707                 sym1->isspilt  &&
708                 (sym1->usl.spillLoc == sym2))
709                 return TRUE;
710         
711         if (IS_ITEMP(op2)  && 
712                 !IS_ITEMP(op1) &&
713                 sym2->isspilt  &&
714                 sym1->level > 0 &&
715                 (sym2->usl.spillLoc == sym1))
716                 return TRUE ;
717         
718         return FALSE ;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers             */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
725 {
726         int i;
727         
728         if (aop1 == aop2)
729                 return TRUE ;
730         
731         if (aop1->type != AOP_REG ||
732                 aop2->type != AOP_REG )
733                 return FALSE ;
734         
735         if (aop1->size != aop2->size )
736                 return FALSE ;
737         
738         for (i = 0 ; i < aop1->size ; i++ )
739                 if (aop1->aopu.aop_reg[i] !=
740                         aop2->aopu.aop_reg[i] )
741                         return FALSE ;
742                 
743                 return TRUE ;
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand  :                    */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
750 {
751         asmop *aop;
752         symbol *sym;
753         int i;
754         
755         if (!op)
756                 return ;
757         
758         /* if this a literal */
759         if (IS_OP_LITERAL(op)) {
760                 op->aop = aop = newAsmop(AOP_LIT);
761                 aop->aopu.aop_lit = op->operand.valOperand;
762                 aop->size = getSize(operandType(op));
763                 return;
764         }
765         
766         {
767                 sym_link *type = operandType(op);
768                 if(IS_PTR_CONST(type))
769                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
770         }
771         
772         /* if already has a asmop then continue */
773         if (op->aop)
774                 return ;
775         
776         /* if the underlying symbol has a aop */
777         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778                 DEBUGpic14_emitcode(";","%d",__LINE__);
779                 op->aop = OP_SYMBOL(op)->aop;
780                 return;
781         }
782         
783         /* if this is a true symbol */
784         if (IS_TRUE_SYMOP(op)) {          
785                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
787                 return ;
788         }
789         
790         /* this is a temporary : this has
791         only four choices :
792         a) register
793         b) spillocation
794         c) rematerialize 
795         d) conditional   
796         e) can be a return use only */
797         
798         sym = OP_SYMBOL(op);
799         
800         
801         /* if the type is a conditional */
802         if (sym->regType == REG_CND) {
803                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
804                 aop->size = 0;
805                 return;
806         }
807         
808         /* if it is spilt then two situations
809         a) is rematerialize 
810         b) has a spill location */
811         if (sym->isspilt || sym->nRegs == 0) {
812                 
813                 DEBUGpic14_emitcode(";","%d",__LINE__);
814                 /* rematerialize it NOW */
815                 if (sym->remat) {
816                         
817                         sym->aop = op->aop = aop = aopForRemat (op);
818                         aop->size = getSize(sym->type);
819                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
820                         return;
821                 }
822                 
823 #if 0
824                 /* WREG is not usable as an ordinary operand with PIC architecture,
825                  * one might introduce a scratch register that can be used to make
826                  * WREG accesible as an operand... disable WREG for now */
827                 if (sym->accuse) {
828                         int i;
829                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830                         aop->size = getSize(sym->type);
831                         for ( i = 0 ; i < 2 ; i++ )
832                                 aop->aopu.aop_str[i] = accUse[i];
833                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
834                         return;  
835                 }
836 #endif
837                 
838                 if (sym->ruonly ) {
839                         if(sym->isptr) {        // && sym->uptr 
840                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
842                                 
843                                 //PCOI(aop->aopu.pcop)->_const = 0;
844                                 //PCOI(aop->aopu.pcop)->index = 0;
845                                 /*
846                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
848                                 */
849                                 //allocDirReg (IC_LEFT(ic));
850                                 
851                                 aop->size = getSize(sym->type);
852                                 DEBUGpic14_emitcode(";","%d",__LINE__);
853                                 return;
854                                 
855                         } else {
856                                 
857                                 unsigned i;
858                                 
859                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860                                 aop->size = getSize(sym->type);
861                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
862                                         aop->aopu.aop_str[i] = fReturn[i];
863                                 
864                                 DEBUGpic14_emitcode(";","%d",__LINE__);
865                                 return;
866                         }
867                 }
868                 
869                 /* else spill location  */
870                 if (sym->usl.spillLoc)
871                 {
872                         asmop *oldAsmOp = NULL;
873
874                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
875                         {
876                                 /* force a new aop if sizes differ */
877                                 oldAsmOp = sym->usl.spillLoc->aop;
878                                 sym->usl.spillLoc->aop = NULL;
879                         }
880                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881                                 __FUNCTION__,__LINE__,
882                                 sym->usl.spillLoc->rname,
883                                 sym->rname, sym->usl.spillLoc->offset);
884                 
885                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
887                         {
888                                 /* Don't reuse the new aop, go with the last one */
889                                 sym->usl.spillLoc->aop = oldAsmOp;
890                         }
891                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
893                                 getSize(sym->type), 
894                                 sym->usl.spillLoc->offset);
895                         aop->size = getSize(sym->type);
896                 
897                         return;
898                 }
899         }
900         
901         {
902                 sym_link *type = operandType(op);
903                 if(IS_PTR_CONST(type)) 
904                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
905         }
906         
907         /* must be in a register */
908         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909         sym->aop = op->aop = aop = newAsmop(AOP_REG);
910         aop->size = sym->nRegs;
911         for ( i = 0 ; i < sym->nRegs ;i++)
912                 aop->aopu.aop_reg[i] = sym->regs[i];
913 }
914
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand                       */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
919 {       
920         asmop *aop ;
921         
922         if (!op)
923                 aop = aaop;
924         else 
925                 aop = op->aop;
926         
927         if (!aop)
928                 return ;
929         
930         if (aop->freed)
931                 goto dealloc; 
932         
933         aop->freed = 1;
934         
935         /* depending on the asmop type only three cases need work AOP_RO
936         , AOP_R1 && AOP_STK */
937 #if 0
938         switch (aop->type) {
939         case AOP_R0 :
940                 if (_G.r0Pushed ) {
941                         if (pop) {
942                                 pic14_emitcode ("pop","ar0");     
943                                 _G.r0Pushed--;
944                         }
945                 }
946                 bitVectUnSetBit(ic->rUsed,R0_IDX);
947                 break;
948                 
949         case AOP_R1 :
950                 if (_G.r1Pushed ) {
951                         if (pop) {
952                                 pic14_emitcode ("pop","ar1");
953                                 _G.r1Pushed--;
954                         }
955                 }
956                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
957                 break;
958                 
959         case AOP_STK :
960                 {
961                         int sz = aop->size;      
962                         int stk = aop->aopu.aop_stk + aop->size;
963                         bitVectUnSetBit(ic->rUsed,R0_IDX);
964                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
965                         
966                         getFreePtr(ic,&aop,FALSE);
967                         
968                         if (options.stack10bit)
969                         {
970                                 /* I'm not sure what to do here yet... */
971                                 /* #STUB */
972                                 fprintf(stderr, 
973                                         "*** Warning: probably generating bad code for "
974                                         "10 bit stack mode.\n");
975                         }
976                         
977                         if (stk) {
978                                 pic14_emitcode ("mov","a,_bp");
979                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
981                         } else {
982                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
983                         }
984                         
985                         while (sz--) {
986                                 pic14_emitcode("pop","acc");
987                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
988                                 if (!sz) break;
989                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
990                         }
991                         op->aop = aop;
992                         freeAsmop(op,NULL,ic,TRUE);
993                         if (_G.r0Pushed) {
994                                 pic14_emitcode("pop","ar0");
995                                 _G.r0Pushed--;
996                         }
997                         
998                         if (_G.r1Pushed) {
999                                 pic14_emitcode("pop","ar1");
1000                                 _G.r1Pushed--;
1001                         }         
1002                 }
1003         }
1004 #endif
1005         
1006 dealloc:
1007         /* all other cases just dealloc */
1008         if (op ) {
1009                 op->aop = NULL;
1010                 if (IS_SYMOP(op)) {
1011                         OP_SYMBOL(op)->aop = NULL;      
1012                         /* if the symbol has a spill */
1013                         if (SPIL_LOC(op))
1014                                 SPIL_LOC(op)->aop = NULL;
1015                 }
1016         }
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop                                                  */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1023 {
1024         char *s = buffer ;
1025         char *rs;
1026         
1027         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1028         /* offset is greater than
1029         size then zero */
1030         assert(aop);
1031         if (offset > (aop->size - 1) &&
1032                 aop->type != AOP_LIT)
1033                 return zero;
1034         
1035         /* depending on type */
1036         switch (aop->type) {
1037                 
1038         case AOP_R0:
1039         case AOP_R1:
1040                 DEBUGpic14_emitcode(";","%d",__LINE__);
1041                 /* if we need to increment it */           
1042                 while (offset > aop->coff) {            
1043                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1044                         aop->coff++;
1045                 }
1046                 
1047                 while (offset < aop->coff) {
1048                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1049                         aop->coff--;
1050                 }
1051                 
1052                 aop->coff = offset ;
1053                 if (aop->paged) {
1054                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055                         return (dname ? "acc" : "a");
1056                 }               
1057                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058                 rs = Safe_calloc(1,strlen(s)+1);
1059                 strcpy(rs,s);   
1060                 return rs;
1061                 
1062         case AOP_DPTR:
1063         case AOP_DPTR2:
1064                 DEBUGpic14_emitcode(";","%d",__LINE__);
1065                 if (aop->type == AOP_DPTR2)
1066                 {
1067                         genSetDPTR(1);
1068                 }
1069                 
1070                 while (offset > aop->coff) {
1071                         pic14_emitcode ("inc","dptr");
1072                         aop->coff++;
1073                 }
1074                 
1075                 while (offset < aop->coff) {            
1076                         pic14_emitcode("lcall","__decdptr");
1077                         aop->coff--;
1078                 }
1079                 
1080                 aop->coff = offset;
1081                 if (aop->code) {
1082                         pic14_emitcode("clr","a");
1083                         pic14_emitcode("movc","a,@a+dptr");
1084                 }
1085                 else {
1086                         pic14_emitcode("movx","a,@dptr");
1087                 }
1088                 
1089                 if (aop->type == AOP_DPTR2)
1090                 {
1091                         genSetDPTR(0);
1092                 }
1093                 
1094                 return (dname ? "acc" : "a");
1095                 
1096                 
1097         case AOP_IMMD:
1098                 if (bit16) 
1099                         sprintf (s,"%s",aop->aopu.aop_immd);
1100                 else
1101                         if (offset) 
1102                                 sprintf(s,"(%s >> %d)",
1103                                 aop->aopu.aop_immd,
1104                                 offset*8);
1105                         else
1106                                 sprintf(s,"%s",
1107                                 aop->aopu.aop_immd);
1108                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109                         rs = Safe_calloc(1,strlen(s)+1);
1110                         strcpy(rs,s);   
1111                         return rs;
1112                         
1113         case AOP_DIR:
1114                 if (offset) {
1115                         sprintf(s,"(%s + %d)",
1116                                 aop->aopu.aop_dir,
1117                                 offset);
1118                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1119                 } else
1120                         sprintf(s,"%s",aop->aopu.aop_dir);
1121                 rs = Safe_calloc(1,strlen(s)+1);
1122                 strcpy(rs,s);   
1123                 return rs;
1124                 
1125         case AOP_REG:
1126                 //if (dname) 
1127                 //        return aop->aopu.aop_reg[offset]->dname;
1128                 //else
1129                 return aop->aopu.aop_reg[offset]->name;
1130                 
1131         case AOP_CRY:
1132                 //pic14_emitcode(";","%d",__LINE__);
1133                 return aop->aopu.aop_dir;
1134                 
1135         case AOP_ACC:
1136                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137                 return "AOP_accumulator_bug";
1138                 
1139         case AOP_LIT:
1140                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141                 rs = Safe_strdup(s);
1142                 return rs;
1143                 
1144         case AOP_STR:
1145                 aop->coff = offset ;
1146                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1147                         dname)
1148                         return "acc";
1149                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1150                 
1151                 return aop->aopu.aop_str[offset];
1152                 
1153         case AOP_PCODE:
1154                 {
1155                         pCodeOp *pcop = aop->aopu.pcop;
1156                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1157                         if(pcop->name) {
1158                                 if (pcop->type == PO_IMMEDIATE) {
1159                                         offset += PCOI(pcop)->index;
1160                                 }
1161                                 if (offset) {
1162                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1164                                 } else {
1165                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1166                                         sprintf(s,"%s", pcop->name);
1167                                 }
1168                         } else
1169                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1170                         
1171                 }
1172                 rs = Safe_calloc(1,strlen(s)+1);
1173                 strcpy(rs,s);   
1174                 return rs;
1175                 
1176   }
1177   
1178   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179           "aopget got unsupported aop->type");
1180   exit(0);
1181 }
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp                                  */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1188 {
1189         
1190         pCodeOp *pcop;
1191         
1192         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194                 PCOR(pcop)->r->wasUsed=1;
1195                 PCOR(pcop)->r->isFree=0;
1196         }
1197         
1198         return pcop;
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1205 {
1206         
1207         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208                 PCOR(pcop)->r->isFree = 1;
1209         
1210 }
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1215 {
1216         
1217         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1218         
1219         if(key>(unsigned int)max_key)
1220                 max_key = key;
1221         
1222         return newpCodeOpLabel(NULL,key+100+labelOffset);
1223 }
1224
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1229 {
1230         pCodeOp *pcop;
1231         pcop = popGetLabel(key);
1232         PCOLAB(pcop)->offset = 1;
1233         return pcop;
1234 }
1235
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion                           */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1240 {
1241         
1242         return newpCodeOpLit((unsigned char)lit);
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion                 */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1249 {
1250         
1251         return newpCodeOpImmd(name, offset,index, 0, is_func);
1252 }
1253
1254 extern set *externs;
1255
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion                    */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1260 {
1261         pCodeOp *pcop;
1262         
1263         
1264         if(!str) {
1265                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1266                 exit (1);
1267         }
1268         
1269         pcop = newpCodeOp(str,PO_STR);
1270         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1271
1272         return pcop;
1273 }
1274
1275 pCodeOp *popGetExternal (char *str)
1276 {
1277         pCodeOp *pcop = popGetWithString (str, 1);
1278         
1279         if (str) {
1280           symbol *sym;
1281
1282           for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1283           {
1284             if (!strcmp (str, sym->rname)) break;
1285           }
1286           
1287           if (!sym)
1288           {
1289             sym = newSymbol(str, 0);
1290             strncpy(sym->rname, str, SDCC_NAME_MAX);
1291             addSet (&externs, sym);
1292           } // if
1293           sym->used++;
1294         }
1295         return pcop;
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* popRegFromString -                                                                                      */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *popRegFromString(char *str, int size, int offset)
1302 {
1303         
1304         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1305         pcop->type = PO_DIR;
1306         
1307         DEBUGpic14_emitcode(";","%d",__LINE__);
1308         
1309         if(!str)
1310                 str = "BAD_STRING";
1311         
1312         pcop->name = Safe_calloc(1,strlen(str)+1);
1313         strcpy(pcop->name,str);
1314         
1315         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1316         
1317         PCOR(pcop)->r = dirregWithName(pcop->name);
1318         if(PCOR(pcop)->r == NULL) {
1319                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1320                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1321                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1322         } else {
1323                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1324         }
1325         PCOR(pcop)->instance = offset;
1326         
1327         return pcop;
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /*-----------------------------------------------------------------*/
1332 pCodeOp *popRegFromIdx(int rIdx)
1333 {
1334         pCodeOp *pcop;
1335         
1336         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1337                 __FUNCTION__,__LINE__,rIdx);
1338         
1339         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1340         
1341         PCOR(pcop)->rIdx = rIdx;
1342         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1343         PCOR(pcop)->r->isFree = 0;
1344         PCOR(pcop)->r->wasUsed = 1;
1345         
1346         pcop->type = PCOR(pcop)->r->pc_type;
1347         
1348         
1349         return pcop;
1350 }
1351
1352 /*-----------------------------------------------------------------*/
1353 /* popGet - asm operator to pcode operator conversion                      */
1354 /*-----------------------------------------------------------------*/
1355 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1356 {
1357         //char *s = buffer ;
1358         //char *rs;
1359         
1360         pCodeOp *pcop;
1361         
1362         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1363         /* offset is greater than
1364         size then zero */
1365
1366         assert (aop);
1367
1368
1369         /* XXX: still needed for BIT operands (AOP_CRY) */
1370         if (offset > (aop->size - 1) &&
1371                 aop->type != AOP_LIT &&
1372                 aop->type != AOP_PCODE)
1373         {
1374                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1375                 return NULL;  //zero;
1376         }
1377         
1378         /* depending on type */
1379         switch (aop->type) {
1380                 
1381         case AOP_R0:
1382         case AOP_R1:
1383         case AOP_DPTR:
1384         case AOP_DPTR2:
1385         case AOP_ACC:
1386                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1387                 return NULL;
1388                 
1389         case AOP_IMMD:
1390                 DEBUGpic14_emitcode(";","%d",__LINE__);
1391                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1392                 
1393         case AOP_DIR:
1394                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1395 #if 0
1396                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397                 pcop->type = PO_DIR;
1398                 
1399                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1400                 strcpy(pcop->name,aop->aopu.aop_dir);   
1401                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1402                 if(PCOR(pcop)->r == NULL) {
1403                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1404                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1405                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1406                 } else {
1407                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1408                 }
1409                 PCOR(pcop)->instance = offset;
1410                 
1411                 return pcop;
1412 #endif
1413                 
1414         case AOP_REG:
1415                 {
1416                         int rIdx;
1417                         assert (offset < aop->size);
1418                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1419                         
1420                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1421                         PCOR(pcop)->rIdx = rIdx;
1422                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1423                         PCOR(pcop)->r->wasUsed=1;
1424                         PCOR(pcop)->r->isFree=0;
1425                         
1426                         PCOR(pcop)->instance = offset;
1427                         pcop->type = PCOR(pcop)->r->pc_type;
1428                         //rs = aop->aopu.aop_reg[offset]->name;
1429                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1430                         return pcop;
1431                 }
1432                 
1433         case AOP_CRY:
1434                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1435                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1436                 //if(PCOR(pcop)->r == NULL)
1437                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1438                 return pcop;
1439                 
1440         case AOP_LIT:
1441                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1442                 
1443         case AOP_STR:
1444                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1445                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1446                 /*
1447                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1448                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1449                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1450                 pcop->type = PCOR(pcop)->r->pc_type;
1451                 pcop->name = PCOR(pcop)->r->name;
1452                 
1453                   return pcop;
1454                 */
1455                 
1456         case AOP_PCODE:
1457                 pcop = NULL;
1458                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1459                         __LINE__, 
1460                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1461                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1462                 switch (aop->aopu.pcop->type)
1463                 {
1464                 case PO_IMMEDIATE:
1465                   pcop = pCodeOpCopy (aop->aopu.pcop);
1466                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1467                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1468                   PCOI(pcop)->index += offset;
1469                   //PCOI(pcop)->offset = 0;
1470                   break;
1471                 case PO_DIR:
1472                   pcop = pCodeOpCopy (aop->aopu.pcop);
1473                   PCOR(pcop)->instance = offset;
1474                   break;
1475                 default:
1476                   assert ( !"unhandled pCode type" );
1477                   break;
1478                 } // switch
1479                 return pcop;
1480         }
1481         
1482         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1483                 "popGet got unsupported aop->type");
1484         exit(0);
1485 }
1486
1487 /*-----------------------------------------------------------------*/
1488 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1489 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1490 /*-----------------------------------------------------------------*/
1491 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1492 {
1493   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1494   {
1495     pCodeOp *pcop = aop->aopu.pcop;
1496     assert (offset <= GPTRSIZE);
1497
1498     /* special case: index >= 2 should return GPOINTER-style values */
1499     if (offset == 2)
1500     {
1501       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1502       return pcop;
1503     }
1504     
1505     pcop = pCodeOpCopy (pcop);
1506     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1507      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1508     PCOI(pcop)->offset += offset;
1509     PCOI(pcop)->index += index;
1510     //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);
1511     return pcop;
1512   } else {
1513     return popGet (aop, offset + index);
1514   }
1515 }
1516
1517 /*-----------------------------------------------------------------*/
1518 /* aopPut - puts a string for a aop                                                        */
1519 /*-----------------------------------------------------------------*/
1520 void aopPut (asmop *aop, char *s, int offset)
1521 {
1522         char *d = buffer ;
1523         symbol *lbl ;
1524         
1525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1526         
1527         if (aop->size && offset > ( aop->size - 1)) {
1528                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1529                         "aopPut got offset > aop->size");
1530                 exit(0);
1531         }
1532         
1533         /* will assign value to value */
1534         /* depending on where it is ofcourse */
1535         switch (aop->type) {
1536         case AOP_DIR:
1537                 if (offset) {
1538                         sprintf(d,"(%s + %d)",
1539                                 aop->aopu.aop_dir,offset);
1540                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1541                         
1542                 } else
1543                         sprintf(d,"%s",aop->aopu.aop_dir);
1544                 
1545                 if (strcmp(d,s)) {
1546                         DEBUGpic14_emitcode(";","%d",__LINE__);
1547                         if(strcmp(s,"W"))
1548                                 pic14_emitcode("movf","%s,w",s);
1549                         pic14_emitcode("movwf","%s",d);
1550                         
1551                         if(strcmp(s,"W")) {
1552                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1553                                 if(offset >= aop->size) {
1554                                         emitpcode(POC_CLRF,popGet(aop,offset));
1555                                         break;
1556                                 } else {
1557                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1558                                 }
1559                         }
1560                         emitpcode(POC_MOVWF,popGet(aop,offset));
1561                 
1562                 }
1563                 break;
1564                 
1565         case AOP_REG:
1566                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1567                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1568                         /*
1569                         if (*s == '@'             ||
1570                         strcmp(s,"r0") == 0 ||
1571                         strcmp(s,"r1") == 0 ||
1572                         strcmp(s,"r2") == 0 ||
1573                         strcmp(s,"r3") == 0 ||
1574                         strcmp(s,"r4") == 0 ||
1575                         strcmp(s,"r5") == 0 ||
1576                         strcmp(s,"r6") == 0 || 
1577                         strcmp(s,"r7") == 0 )
1578                         pic14_emitcode("mov","%s,%s  ; %d",
1579                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1580                         else
1581                         */
1582                         
1583                         if(strcmp(s,"W")==0 )
1584                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1585                         
1586                         pic14_emitcode("movwf","%s",
1587                                 aop->aopu.aop_reg[offset]->name);
1588                         
1589                         if(strcmp(s,zero)==0) {
1590                                 emitpcode(POC_CLRF,popGet(aop,offset));
1591                                 
1592                         } else if(strcmp(s,"W")==0) {
1593                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1594                                 pcop->type = PO_GPR_REGISTER;
1595                                 
1596                                 PCOR(pcop)->rIdx = -1;
1597                                 PCOR(pcop)->r = NULL;
1598                                 
1599                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1600                                 pcop->name = Safe_strdup(s);
1601                                 emitpcode(POC_MOVFW,pcop);
1602                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1603                         } else if(strcmp(s,one)==0) {
1604                                 emitpcode(POC_CLRF,popGet(aop,offset));
1605                                 emitpcode(POC_INCF,popGet(aop,offset));
1606                         } else {
1607                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1608                         }
1609                 }
1610                 break;
1611                 
1612         case AOP_DPTR:
1613         case AOP_DPTR2:
1614                 
1615                 if (aop->type == AOP_DPTR2)
1616                 {
1617                         genSetDPTR(1);
1618                 }
1619                 
1620                 if (aop->code) {
1621                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1622                                 "aopPut writting to code space");
1623                         exit(0);
1624                 }
1625                 
1626                 while (offset > aop->coff) {
1627                         aop->coff++;
1628                         pic14_emitcode ("inc","dptr");
1629                 }
1630                 
1631                 while (offset < aop->coff) {
1632                         aop->coff-- ;
1633                         pic14_emitcode("lcall","__decdptr");
1634                 }
1635                 
1636                 aop->coff = offset;
1637                 
1638                 /* if not in accumulater */
1639                 MOVA(s);
1640                 
1641                 pic14_emitcode ("movx","@dptr,a");
1642                 
1643                 if (aop->type == AOP_DPTR2)
1644                 {
1645                         genSetDPTR(0);
1646                 }
1647                 break;
1648                 
1649         case AOP_R0:
1650         case AOP_R1:
1651                 while (offset > aop->coff) {
1652                         aop->coff++;
1653                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1654                 }
1655                 while (offset < aop->coff) {
1656                         aop->coff-- ;
1657                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1658                 }
1659                 aop->coff = offset;
1660                 
1661                 if (aop->paged) {
1662                         MOVA(s);                         
1663                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1664                         
1665                 } else
1666                         if (*s == '@') {
1667                                 MOVA(s);
1668                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1669                         } else
1670                                 if (strcmp(s,"r0") == 0 ||
1671                                         strcmp(s,"r1") == 0 ||
1672                                         strcmp(s,"r2") == 0 ||
1673                                         strcmp(s,"r3") == 0 ||
1674                                         strcmp(s,"r4") == 0 ||
1675                                         strcmp(s,"r5") == 0 ||
1676                                         strcmp(s,"r6") == 0 || 
1677                                         strcmp(s,"r7") == 0 ) {
1678                                         char buffer[10];
1679                                         sprintf(buffer,"a%s",s);
1680                                         pic14_emitcode("mov","@%s,%s",
1681                                                 aop->aopu.aop_ptr->name,buffer);
1682                                 } else
1683                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1684                                 
1685                                 break;
1686                                 
1687         case AOP_STK:
1688                 if (strcmp(s,"a") == 0)
1689                         pic14_emitcode("push","acc");
1690                 else
1691                         pic14_emitcode("push","%s",s);
1692                 
1693                 break;
1694                 
1695         case AOP_CRY:
1696                 /* if bit variable */
1697                 if (!aop->aopu.aop_dir) {
1698                         pic14_emitcode("clr","a");
1699                         pic14_emitcode("rlc","a");
1700                 } else {
1701                         if (s == zero) 
1702                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1703                         else
1704                                 if (s == one)
1705                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1706                                 else
1707                                         if (!strcmp(s,"c"))
1708                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1709                                         else {
1710                                                 lbl = newiTempLabel(NULL);
1711                                                 
1712                                                 if (strcmp(s,"a")) {
1713                                                         MOVA(s);
1714                                                 }
1715                                                 pic14_emitcode("clr","c");
1716                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1717                                                 pic14_emitcode("cpl","c");
1718                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1719                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1720                                         }
1721                 }
1722                 break;
1723                 
1724         case AOP_STR:
1725                 aop->coff = offset;
1726                 if (strcmp(aop->aopu.aop_str[offset],s))
1727                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1728                 break;
1729                 
1730         case AOP_ACC:
1731                 aop->coff = offset;
1732                 if (!offset && (strcmp(s,"acc") == 0))
1733                         break;
1734                 
1735                 if (strcmp(aop->aopu.aop_str[offset],s))
1736                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1737                 break;
1738                 
1739         default :
1740                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1741                         "aopPut got unsupported aop->type");
1742                 exit(0);
1743         }
1744         
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1749 /*-----------------------------------------------------------------*/
1750 static void mov2w_op (operand *op, int offset)
1751 {
1752         assert (op);
1753         FENTRY;
1754
1755         /* for PO_IMMEDIATEs: use address or value? */
1756         if (op_isLitLike (op))
1757         {
1758                 /* access address of op */
1759                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1760                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1761                 {
1762                         if (offset == GPTRSIZE-1)
1763                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1764                         else
1765                                 emitpcode (POC_MOVLW, popGetLit (0));
1766                 }
1767                 else
1768                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1769         } else {
1770                 /* access value stored in op */
1771                 mov2w (AOP(op), offset);
1772         }
1773 }
1774
1775
1776 /*-----------------------------------------------------------------*/
1777 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1778 /*-----------------------------------------------------------------*/
1779 void mov2w (asmop *aop, int offset)
1780 {
1781         
1782         if(!aop)
1783                 return;
1784         
1785         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1786         
1787         if ( aop_isLitLike (aop) )
1788                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1789         else
1790                 emitpcode(POC_MOVFW,popGet(aop,offset));
1791         
1792 }
1793
1794 static void movwf (asmop *op, int offset)
1795 {
1796         emitpcode (POC_MOVWF, popGet(op, offset));
1797 }
1798
1799 static pCodeOp *get_argument_pcop (int idx)
1800 {
1801         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1802         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1803 }
1804
1805 static pCodeOp *get_return_val_pcop (int offset)
1806 {
1807         assert (offset > 0 && "the most significant byte is returned via WREG");
1808         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1809 }
1810
1811 static void pass_argument (operand *op, int offset, int idx)
1812 {
1813         if (op)
1814                 mov2w_op (op, offset);
1815         if (idx != 0)
1816                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1817 }
1818
1819 static void get_returnvalue (operand *op, int offset, int idx)
1820 {
1821         if (idx != 0)
1822                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1823         movwf(AOP(op), offset);
1824 }
1825
1826 static void call_libraryfunc (char *name)
1827 {
1828     symbol *sym;
1829
1830     /* library code might reside in different page... */
1831     emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1832     /* call the library function */
1833     emitpcode (POC_CALL, popGetExternal (name));
1834     /* might return from different page... */
1835     emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1836
1837     /* create symbol, mark it as `extern' */
1838     sym = findSym(SymbolTab, NULL, name);
1839     if (!sym) {
1840         sym = newSymbol(name, 0);
1841         strncpy(sym->rname, name, SDCC_NAME_MAX);
1842         addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1843         addSet(&externs, sym); 
1844     } // if
1845     sym->used++;
1846 }
1847
1848 #if 0
1849 /*-----------------------------------------------------------------*/
1850 /* reAdjustPreg - points a register back to where it should        */
1851 /*-----------------------------------------------------------------*/
1852 static void reAdjustPreg (asmop *aop)
1853 {
1854         int size ;
1855         
1856         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1857         aop->coff = 0;
1858         if ((size = aop->size) <= 1)
1859                 return ;
1860         size-- ;
1861         switch (aop->type) {
1862         case AOP_R0 :
1863         case AOP_R1 :
1864                 while (size--)
1865                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1866                 break;                  
1867         case AOP_DPTR :
1868         case AOP_DPTR2:
1869                 if (aop->type == AOP_DPTR2)
1870                 {
1871                         genSetDPTR(1);
1872                 } 
1873                 while (size--)
1874                 {
1875                         pic14_emitcode("lcall","__decdptr");
1876                 }
1877                 
1878                 if (aop->type == AOP_DPTR2)
1879                 {
1880                         genSetDPTR(0);
1881                 }
1882                 break;
1883                 
1884         }
1885         
1886 }
1887 #endif
1888
1889
1890 #if 0
1891 /*-----------------------------------------------------------------*/
1892 /* opIsGptr: returns non-zero if the passed operand is             */
1893 /* a generic pointer type.                                         */
1894 /*-----------------------------------------------------------------*/ 
1895 static int opIsGptr(operand *op)
1896 {
1897         sym_link *type = operandType(op);
1898         
1899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1900         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1901         {
1902                 return 1;
1903         }
1904         return 0;          
1905 }
1906 #endif
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic14_getDataSize - get the operand data size                   */
1910 /*-----------------------------------------------------------------*/
1911 int pic14_getDataSize(operand *op)
1912 {
1913         int size;
1914         
1915         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1916         
1917 #if 0
1918         size = getSize(OP_SYM_ETYPE(op));
1919         return size;
1920         //return AOP_SIZE(op);
1921         
1922         // tsd- in the pic port, the genptr size is 1, so this code here
1923         // fails. ( in the 8051 port, the size was 4).
1924 #else
1925         size = AOP_SIZE(op);
1926         if (IS_GENPTR(OP_SYM_TYPE(op)))
1927         {
1928                 sym_link *type = operandType(op);
1929                 if (IS_GENPTR(type))
1930                 {
1931                         /* generic pointer; arithmetic operations
1932                         * should ignore the high byte (pointer type).
1933                         */
1934                         size--;
1935                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1936                 }
1937         }
1938         return size;
1939 #endif
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* pic14_outAcc - output Acc                                       */
1944 /*-----------------------------------------------------------------*/
1945 void pic14_outAcc(operand *result)
1946 {
1947         int size,offset;
1948         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1949         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1950         
1951         
1952         size = pic14_getDataSize(result);
1953         if(size){
1954                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1955                 size--;
1956                 offset = 1;
1957                 /* unsigned or positive */
1958                 while(size--)
1959                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1960         }
1961         
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* pic14_outBitC - output a bit C                                  */
1966 /*-----------------------------------------------------------------*/
1967 void pic14_outBitC(operand *result)
1968 {
1969         
1970         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1971         /* if the result is bit */
1972         if (AOP_TYPE(result) == AOP_CRY) 
1973                 aopPut(AOP(result),"c",0);
1974         else {
1975                 pic14_emitcode("clr","a  ; %d", __LINE__);
1976                 pic14_emitcode("rlc","a");
1977                 pic14_outAcc(result);
1978         }
1979 }
1980
1981 /*-----------------------------------------------------------------*/
1982 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1983 /*-----------------------------------------------------------------*/
1984 void pic14_toBoolean(operand *oper)
1985 {
1986         int size = AOP_SIZE(oper);
1987         int offset = 0;
1988         
1989         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1990
1991         assert (size > 0);
1992
1993         if (size == 1) {
1994                 /* MOVFW does not load the flags... */
1995                 if (AOP_TYPE(oper) == AOP_ACC) {
1996                         emitpcode(POC_IORLW, popGetLit(0));
1997                         offset = 1;
1998                 } else {
1999                         emitpcode(POC_MOVLW, popGetLit(0));
2000                         offset = 0;
2001                 }
2002         } else {
2003                 if ( AOP_TYPE(oper) != AOP_ACC) {
2004                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2005                         offset = 1;
2006                 }
2007         }
2008         
2009         while (offset < size) {
2010                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2011         }
2012         /* Z is set iff (oper == 0) */
2013 }
2014
2015
2016 /*-----------------------------------------------------------------*/
2017 /* genNot - generate code for ! operation                          */
2018 /*-----------------------------------------------------------------*/
2019 static void genNot (iCode *ic)
2020 {
2021         //symbol *tlbl;
2022         int size;
2023
2024         FENTRY;
2025         
2026         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2027         /* assign asmOps to operand & result */
2028         aopOp (IC_LEFT(ic),ic,FALSE);
2029         aopOp (IC_RESULT(ic),ic,TRUE);
2030         
2031         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2032         /* if in bit space then a special case */
2033         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2034                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2035                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2036                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2037                 } else {
2038                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2039                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2040                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2041                 }
2042                 goto release;
2043         }
2044         
2045         size = AOP_SIZE(IC_LEFT(ic));
2046         mov2w (AOP(IC_LEFT(ic)),0);
2047         while (--size > 0)
2048         {
2049           if (op_isLitLike (IC_LEFT(ic)))
2050             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2051           else
2052             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2053         }
2054         emitpcode(POC_MOVLW, popGetLit (0));
2055         emitSKPNZ;
2056         emitpcode(POC_MOVLW, popGetLit (1));
2057         movwf(AOP(IC_RESULT(ic)), 0);
2058
2059         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2060         {
2061           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2062         }
2063         goto release;
2064         
2065 release:        
2066         /* release the aops */
2067         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2068         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2069 }
2070
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genCpl - generate code for complement                                                   */
2074 /*-----------------------------------------------------------------*/
2075 static void genCpl (iCode *ic)
2076 {
2077         operand *left, *result;
2078         int size, offset=0;  
2079         
2080         FENTRY;
2081         
2082         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2083         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2084         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2085         
2086         /* if both are in bit space then 
2087         a special case */
2088         if (AOP_TYPE(result) == AOP_CRY &&
2089                 AOP_TYPE(left) == AOP_CRY ) { 
2090                 
2091                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2092                 pic14_emitcode("cpl","c"); 
2093                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2094                 goto release; 
2095         } 
2096         
2097         size = AOP_SIZE(result);
2098         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2099         while (size--) {
2100                 
2101                 if(AOP_TYPE(left) == AOP_ACC) 
2102                         emitpcode(POC_XORLW, popGetLit(0xff));
2103                 else
2104                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2105                 
2106                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2107                 offset++;
2108         }
2109         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2110         
2111         
2112 release:
2113         /* release the aops */
2114         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2115         freeAsmop(result,NULL,ic,TRUE);
2116 }
2117
2118 /*-----------------------------------------------------------------*/
2119 /* genUminusFloat - unary minus for floating points                        */
2120 /*-----------------------------------------------------------------*/
2121 static void genUminusFloat(operand *op,operand *result)
2122 {
2123         int size ,offset =0 ;
2124         char *l;
2125         
2126         FENTRY;
2127
2128         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2129         /* for this we just need to flip the 
2130         first it then copy the rest in place */
2131         size = AOP_SIZE(op) - 1;
2132         l = aopGet(AOP(op),3,FALSE,FALSE);
2133         
2134         MOVA(l);          
2135         
2136         pic14_emitcode("cpl","acc.7");
2137         aopPut(AOP(result),"a",3);      
2138         
2139         while(size--) {
2140                 aopPut(AOP(result),
2141                         aopGet(AOP(op),offset,FALSE,FALSE),
2142                         offset);
2143                 offset++;
2144         }                
2145 }
2146
2147 /*-----------------------------------------------------------------*/
2148 /* genUminus - unary minus code generation                                                 */
2149 /*-----------------------------------------------------------------*/
2150 static void genUminus (iCode *ic)
2151 {
2152         int size, i;
2153         sym_link *optype, *rtype;
2154         
2155         FENTRY;
2156         
2157         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158         /* assign asmops */
2159         aopOp(IC_LEFT(ic),ic,FALSE);
2160         aopOp(IC_RESULT(ic),ic,TRUE);
2161         
2162         /* if both in bit space then special
2163         case */
2164         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2165                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2166                 
2167                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2168                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2169                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2170                 
2171                 goto release; 
2172         } 
2173         
2174         optype = operandType(IC_LEFT(ic));
2175         rtype = operandType(IC_RESULT(ic));
2176         
2177         /* if float then do float stuff */
2178         if (IS_FLOAT(optype)) {
2179                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2180                 goto release;
2181         }
2182         
2183         /* otherwise subtract from zero by taking the 2's complement */
2184         size = AOP_SIZE(IC_LEFT(ic));
2185         
2186         for(i=0; i<size; i++) {
2187                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2188                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2189                 else {
2190                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2191                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2192                 }
2193         }
2194         
2195         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2196         for(i=1; i<size; i++) {
2197                 emitSKPNZ;
2198                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2199         }
2200         
2201 release:
2202         /* release the aops */
2203         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2204         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* saveRegisters - will look for a call and save the registers     */
2209 /*-----------------------------------------------------------------*/
2210 static void saveRegisters(iCode *lic) 
2211 {
2212         int i;
2213         iCode *ic;
2214         bitVect *rsave;
2215         sym_link *dtype;
2216         
2217         FENTRY;
2218
2219         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2220         /* look for call */
2221         for (ic = lic ; ic ; ic = ic->next) 
2222                 if (ic->op == CALL || ic->op == PCALL)
2223                         break;
2224                 
2225                 if (!ic) {
2226                         fprintf(stderr,"found parameter push with no function call\n");
2227                         return ;
2228                 }
2229                 
2230                 /* if the registers have been saved already then
2231                 do nothing */
2232                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2233                         return ;
2234                 
2235                         /* find the registers in use at this time 
2236                 and push them away to safety */
2237                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2238                         ic->rUsed);
2239                 
2240                 ic->regsSaved = 1;
2241                 if (options.useXstack) {
2242                         if (bitVectBitValue(rsave,R0_IDX))
2243                                 pic14_emitcode("mov","b,r0");
2244                         pic14_emitcode("mov","r0,%s",spname);
2245                         for (i = 0 ; i < pic14_nRegs ; i++) {
2246                                 if (bitVectBitValue(rsave,i)) {
2247                                         if (i == R0_IDX)
2248                                                 pic14_emitcode("mov","a,b");
2249                                         else
2250                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2251                                         pic14_emitcode("movx","@r0,a");
2252                                         pic14_emitcode("inc","r0");
2253                                 }
2254                         }
2255                         pic14_emitcode("mov","%s,r0",spname);
2256                         if (bitVectBitValue(rsave,R0_IDX))
2257                                 pic14_emitcode("mov","r0,b");     
2258                 }// else
2259                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2260                 //        if (bitVectBitValue(rsave,i))
2261                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2262                 //}
2263                 
2264                 dtype = operandType(IC_LEFT(ic));
2265                 if (currFunc && dtype && 
2266                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2267                         IFFUNC_ISISR(currFunc->type) &&
2268                         !ic->bankSaved) 
2269                         
2270                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2271                 
2272 }
2273 /*-----------------------------------------------------------------*/
2274 /* unsaveRegisters - pop the pushed registers                                      */
2275 /*-----------------------------------------------------------------*/
2276 static void unsaveRegisters (iCode *ic)
2277 {
2278         int i;
2279         bitVect *rsave;
2280         
2281         FENTRY;
2282
2283         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2284         /* find the registers in use at this time 
2285         and push them away to safety */
2286         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2287                 ic->rUsed);
2288         
2289         if (options.useXstack) {
2290                 pic14_emitcode("mov","r0,%s",spname); 
2291                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2292                         if (bitVectBitValue(rsave,i)) {
2293                                 pic14_emitcode("dec","r0");
2294                                 pic14_emitcode("movx","a,@r0");
2295                                 if (i == R0_IDX)
2296                                         pic14_emitcode("mov","b,a");
2297                                 else
2298                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2299                         }       
2300                         
2301                 }
2302                 pic14_emitcode("mov","%s,r0",spname);
2303                 if (bitVectBitValue(rsave,R0_IDX))
2304                         pic14_emitcode("mov","r0,b");
2305         } //else
2306         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2307         //      if (bitVectBitValue(rsave,i))
2308         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2309         //}
2310         
2311 }  
2312
2313
2314 /*-----------------------------------------------------------------*/
2315 /* pushSide -                            */
2316 /*-----------------------------------------------------------------*/
2317 static void pushSide(operand * oper, int size)
2318 {
2319 #if 0
2320         int offset = 0;
2321         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2322         while (size--) {
2323                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2324                 if (AOP_TYPE(oper) != AOP_REG &&
2325                         AOP_TYPE(oper) != AOP_DIR &&
2326                         strcmp(l,"a") ) {
2327                         pic14_emitcode("mov","a,%s",l);
2328                         pic14_emitcode("push","acc");
2329                 } else
2330                         pic14_emitcode("push","%s",l);
2331         }
2332 #endif
2333 }
2334
2335 /*-----------------------------------------------------------------*/
2336 /* assignResultValue -                           */
2337 /*-----------------------------------------------------------------*/
2338 static void assignResultValue(operand * oper)
2339 {
2340         int size = AOP_SIZE(oper);
2341         int offset = 0;
2342         
2343         FENTRY;
2344
2345         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2346         
2347         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2348         
2349         /* assign MSB first (passed via WREG) */
2350         while (size--) {
2351                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2352                 GpsuedoStkPtr++;
2353         }
2354 }
2355
2356
2357 /*-----------------------------------------------------------------*/
2358 /* genIpush - genrate code for pushing this gets a little complex  */
2359 /*-----------------------------------------------------------------*/
2360 static void genIpush (iCode *ic)
2361 {
2362         FENTRY;
2363         
2364         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2365 #if 0
2366         int size, offset = 0 ;
2367         char *l;
2368         
2369         
2370         /* if this is not a parm push : ie. it is spill push 
2371         and spill push is always done on the local stack */
2372         if (!ic->parmPush) {
2373                 
2374                 /* and the item is spilt then do nothing */
2375                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2376                         return ;
2377                 
2378                 aopOp(IC_LEFT(ic),ic,FALSE);
2379                 size = AOP_SIZE(IC_LEFT(ic));
2380                 /* push it on the stack */
2381                 while(size--) {
2382                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2383                         if (*l == '#') {
2384                                 MOVA(l);
2385                                 l = "acc";
2386                         }
2387                         pic14_emitcode("push","%s",l);
2388                 }
2389                 return ;                
2390         }
2391         
2392         /* this is a paramter push: in this case we call
2393         the routine to find the call and save those
2394         registers that need to be saved */   
2395         saveRegisters(ic);
2396         
2397         /* then do the push */
2398         aopOp(IC_LEFT(ic),ic,FALSE);
2399         
2400         
2401         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2402         size = AOP_SIZE(IC_LEFT(ic));
2403         
2404         while (size--) {
2405                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2406                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2407                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2408                         strcmp(l,"a") ) {
2409                         pic14_emitcode("mov","a,%s",l);
2410                         pic14_emitcode("push","acc");
2411                 } else
2412                         pic14_emitcode("push","%s",l);
2413         }         
2414         
2415         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2416 #endif
2417 }
2418
2419 /*-----------------------------------------------------------------*/
2420 /* genIpop - recover the registers: can happen only for spilling   */
2421 /*-----------------------------------------------------------------*/
2422 static void genIpop (iCode *ic)
2423 {
2424         FENTRY;
2425
2426         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2427         assert (!"genIpop -- unimplemented");
2428 #if 0
2429         int size,offset ;
2430         
2431         
2432         /* if the temp was not pushed then */
2433         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2434                 return ;
2435         
2436         aopOp(IC_LEFT(ic),ic,FALSE);
2437         size = AOP_SIZE(IC_LEFT(ic));
2438         offset = (size-1);
2439         while (size--) 
2440                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2441                 FALSE,TRUE));
2442         
2443         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2444 #endif
2445 }
2446
2447 /*-----------------------------------------------------------------*/
2448 /* unsaverbank - restores the resgister bank from stack                    */
2449 /*-----------------------------------------------------------------*/
2450 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2451 {
2452         FENTRY;
2453
2454         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2455 #if 0
2456         int i;
2457         asmop *aop ;
2458         regs *r = NULL;
2459         
2460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2461         if (popPsw) {
2462                 if (options.useXstack) {
2463                         aop = newAsmop(0);
2464                         r = getFreePtr(ic,&aop,FALSE);
2465                         
2466                         
2467                         pic14_emitcode("mov","%s,_spx",r->name);
2468                         pic14_emitcode("movx","a,@%s",r->name);
2469                         pic14_emitcode("mov","psw,a");
2470                         pic14_emitcode("dec","%s",r->name);
2471                         
2472                 }else
2473                         pic14_emitcode ("pop","psw");
2474         }
2475         
2476         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2477                 if (options.useXstack) {           
2478                         pic14_emitcode("movx","a,@%s",r->name);
2479                         //pic14_emitcode("mov","(%s+%d),a",
2480                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2481                         pic14_emitcode("dec","%s",r->name);
2482                         
2483                 } else 
2484                         pic14_emitcode("pop",""); //"(%s+%d)",
2485                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2486         }
2487         
2488         if (options.useXstack) {
2489                 
2490                 pic14_emitcode("mov","_spx,%s",r->name);
2491                 freeAsmop(NULL,aop,ic,TRUE);
2492                 
2493         }
2494 #endif 
2495 }
2496
2497 /*-----------------------------------------------------------------*/
2498 /* saverbank - saves an entire register bank on the stack                  */
2499 /*-----------------------------------------------------------------*/
2500 static void saverbank (int bank, iCode *ic, bool pushPsw)
2501 {
2502         FENTRY;
2503
2504         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2505 #if 0
2506         int i;
2507         asmop *aop ;
2508         regs *r = NULL;
2509         
2510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511         if (options.useXstack) {
2512                 
2513                 aop = newAsmop(0);
2514                 r = getFreePtr(ic,&aop,FALSE);  
2515                 pic14_emitcode("mov","%s,_spx",r->name);
2516                 
2517         }
2518         
2519         for (i = 0 ; i < pic14_nRegs ;i++) {
2520                 if (options.useXstack) {
2521                         pic14_emitcode("inc","%s",r->name);
2522                         //pic14_emitcode("mov","a,(%s+%d)",
2523                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2524                         pic14_emitcode("movx","@%s,a",r->name);                 
2525                 } else 
2526                         pic14_emitcode("push","");// "(%s+%d)",
2527                 //regspic14[i].base,8*bank+regspic14[i].offset);
2528         }
2529         
2530         if (pushPsw) {
2531                 if (options.useXstack) {
2532                         pic14_emitcode("mov","a,psw");
2533                         pic14_emitcode("movx","@%s,a",r->name); 
2534                         pic14_emitcode("inc","%s",r->name);
2535                         pic14_emitcode("mov","_spx,%s",r->name);                 
2536                         freeAsmop (NULL,aop,ic,TRUE);
2537                         
2538                 } else
2539                         pic14_emitcode("push","psw");
2540                 
2541                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2542         }
2543         ic->bankSaved = 1;
2544 #endif
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genCall - generates a call statement                                                    */
2549 /*-----------------------------------------------------------------*/
2550 static void genCall (iCode *ic)
2551 {
2552         sym_link *dtype;         
2553         symbol *sym;
2554         char *name;
2555         int isExtern;
2556         
2557         FENTRY;
2558
2559         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2560         
2561         /* if caller saves & we have not saved then */
2562         if (!ic->regsSaved)
2563                 saveRegisters(ic);
2564         
2565                 /* if we are calling a function that is not using
2566                 the same register bank then we need to save the
2567         destination registers on the stack */
2568         dtype = operandType(IC_LEFT(ic));
2569         if (currFunc && dtype && 
2570                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2571                 IFFUNC_ISISR(currFunc->type) &&
2572                 !ic->bankSaved) 
2573                 
2574                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2575         
2576         /* if send set is not empty the assign */
2577         if (_G.sendSet) {
2578                 iCode *sic;
2579                 /* For the Pic port, there is no data stack.
2580                 * So parameters passed to functions are stored
2581                 * in registers. (The pCode optimizer will get
2582                 * rid of most of these :).
2583                 */
2584                 int psuedoStkPtr=-1;
2585                 int firstTimeThruLoop = 1;
2586                 
2587                 _G.sendSet = reverseSet(_G.sendSet);
2588                 
2589                 /* First figure how many parameters are getting passed */
2590                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2591                 sic = setNextItem(_G.sendSet)) {
2592                         
2593                         aopOp(IC_LEFT(sic),sic,FALSE);
2594                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2595                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2596                 }
2597                 
2598                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2599                 sic = setNextItem(_G.sendSet)) {
2600                         int size, offset = 0;
2601                         
2602                         aopOp(IC_LEFT(sic),sic,FALSE);
2603                         size = AOP_SIZE(IC_LEFT(sic));
2604                         
2605                         while (size--) {
2606                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2607                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2608                                 
2609                                 if(!firstTimeThruLoop) {
2610                                         /* If this is not the first time we've been through the loop
2611                                         * then we need to save the parameter in a temporary
2612                                         * register. The last byte of the last parameter is
2613                                         * passed in W. */
2614                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2615                                         
2616                                 }
2617                                 firstTimeThruLoop=0;
2618                                 
2619                                 mov2w_op (IC_LEFT(sic),  offset);
2620                                 offset++;
2621                         }
2622                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2623                 }
2624                 _G.sendSet = NULL;
2625         }
2626         /* make the call */
2627         sym = OP_SYMBOL(IC_LEFT(ic));
2628         name = sym->rname[0] ? sym->rname : sym->name;
2629         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2630         if (isExtern) {
2631                 /* Extern functions and ISRs maybe on a different page;
2632                  * must call pagesel */
2633                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2634         }
2635         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2636         if (isExtern) {
2637                 /* May have returned from a different page;
2638                  * must use pagesel to restore PCLATH before next
2639                  * goto or call instruction */
2640                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2641         }
2642         GpsuedoStkPtr=0;
2643         /* if we need assign a result value */
2644         if ((IS_ITEMP(IC_RESULT(ic)) && 
2645                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2646                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2647                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2648                 
2649                 _G.accInUse++;
2650                 aopOp(IC_RESULT(ic),ic,FALSE);
2651                 _G.accInUse--;
2652                 
2653                 assignResultValue(IC_RESULT(ic));
2654                 
2655                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2656                         AopType(AOP_TYPE(IC_RESULT(ic))));
2657                 
2658                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2659         }
2660         
2661         /* if register bank was saved then pop them */
2662         if (ic->bankSaved)
2663                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2664         
2665         /* if we hade saved some registers then unsave them */
2666         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2667                 unsaveRegisters (ic);
2668         
2669         
2670 }
2671
2672 /*-----------------------------------------------------------------*/
2673 /* genPcall - generates a call by pointer statement                        */
2674 /*-----------------------------------------------------------------*/
2675 static void genPcall (iCode *ic)
2676 {
2677         sym_link *dtype;
2678         symbol *albl = newiTempLabel(NULL);
2679         symbol *blbl = newiTempLabel(NULL);
2680         PIC_OPCODE poc;
2681         pCodeOp *pcop;
2682         operand *left;
2683         
2684         FENTRY;
2685
2686         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2687         /* if caller saves & we have not saved then */
2688         if (!ic->regsSaved)
2689                 saveRegisters(ic);
2690         
2691                 /* if we are calling a function that is not using
2692                 the same register bank then we need to save the
2693         destination registers on the stack */
2694         dtype = operandType(IC_LEFT(ic));
2695         if (currFunc && dtype && 
2696                 IFFUNC_ISISR(currFunc->type) &&
2697                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2698                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2699         
2700         left = IC_LEFT(ic);
2701         aopOp(left,ic,FALSE);
2702         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2703         
2704         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2705         
2706         pushSide(IC_LEFT(ic), FPTRSIZE);
2707         
2708         /* if send set is not empty, assign parameters */
2709         if (_G.sendSet) {
2710                 
2711                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2712                 /* no way to pass args - W always gets used to make the call */
2713         }
2714         /* first idea - factor out a common helper function and call it.
2715         But don't know how to get it generated only once in its own block
2716         
2717         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2718                 char *rname;
2719                 char *buffer;
2720                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2721                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2722                 buffer = Safe_calloc(1,strlen(rname)+16);
2723                 sprintf(buffer, "%s_goto_helper", rname);
2724                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2725                 free(buffer);
2726         }
2727         */
2728         emitpcode(POC_CALL,popGetLabel(albl->key));
2729         pcop = popGetLabel(blbl->key);
2730         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2731         emitpcode(POC_GOTO,pcop);
2732         emitpLabel(albl->key);
2733         
2734         emitpcode(poc,popGetAddr(AOP(left),1,0));
2735         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2736         emitpcode(poc,popGetAddr(AOP(left),0,0));
2737         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2738         
2739         emitpLabel(blbl->key);
2740         
2741         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2742         
2743         /* if we need to assign a result value */
2744         if ((IS_ITEMP(IC_RESULT(ic)) &&
2745                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2746                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2747                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2748                 
2749                 _G.accInUse++;
2750                 aopOp(IC_RESULT(ic),ic,FALSE);
2751                 _G.accInUse--;
2752
2753                 GpsuedoStkPtr = 0;
2754                 
2755                 assignResultValue(IC_RESULT(ic));
2756                 
2757                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2758         }
2759         
2760         /* if register bank was saved then unsave them */
2761         if (currFunc && dtype && 
2762                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2764         
2765                 /* if we hade saved some registers then
2766         unsave them */
2767         if (ic->regsSaved)
2768                 unsaveRegisters (ic);
2769         
2770 }
2771
2772 /*-----------------------------------------------------------------*/
2773 /* resultRemat - result  is rematerializable                                       */
2774 /*-----------------------------------------------------------------*/
2775 static int resultRemat (iCode *ic)
2776 {
2777         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2778         FENTRY;
2779
2780         if (SKIP_IC(ic) || ic->op == IFX)
2781                 return 0;
2782         
2783         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2784                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2785                 if (sym->remat && !POINTER_SET(ic)) 
2786                         return 1;
2787         }
2788         
2789         return 0;
2790 }
2791
2792 #if 0
2793 /*-----------------------------------------------------------------*/
2794 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2795 /*-----------------------------------------------------------------*/
2796 static bool inExcludeList(char *s)
2797 {
2798         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2799         int i =0;
2800         
2801         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2802         if (options.excludeRegs[i] &&
2803                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2804                 return FALSE ;
2805         
2806         for ( i = 0 ; options.excludeRegs[i]; i++) {
2807                 if (options.excludeRegs[i] &&
2808                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2809                         return TRUE;
2810         }
2811         return FALSE ;
2812 }
2813 #endif
2814
2815 /*-----------------------------------------------------------------*/
2816 /* genFunction - generated code for function entry                                 */
2817 /*-----------------------------------------------------------------*/
2818 static void genFunction (iCode *ic)
2819 {
2820         symbol *sym;
2821         sym_link *ftype;
2822         
2823         FENTRY;
2824
2825         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2826         
2827         labelOffset += (max_key+4);
2828         max_key=0;
2829         GpsuedoStkPtr=0;
2830         _G.nRegsSaved = 0;
2831         /* create the function header */
2832         pic14_emitcode(";","-----------------------------------------");
2833         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2834         pic14_emitcode(";","-----------------------------------------");
2835         
2836         /* prevent this symbol from being emitted as 'extern' */
2837         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2838
2839         pic14_emitcode("","%s:",sym->rname);
2840         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2841
2842         /* mark symbol as NOT extern (even if it was declared so previously) */
2843         assert(IS_SPEC(sym->etype));
2844         SPEC_EXTR(sym->etype) = 0;
2845         sym->cdef = 0;
2846         if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2847         addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2848         
2849         ftype = operandType(IC_LEFT(ic));
2850         
2851         /* if critical function then turn interrupts off */
2852         if (IFFUNC_ISCRITICAL(ftype))
2853                 pic14_emitcode("clr","ea");
2854         
2855                 /* here we need to generate the equates for the
2856         register bank if required */
2857 #if 0
2858         if (FUNC_REGBANK(ftype) != rbank) {
2859                 int i ;
2860                 
2861                 rbank = FUNC_REGBANK(ftype);
2862                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2863                         if (strcmp(regspic14[i].base,"0") == 0)
2864                                 pic14_emitcode("","%s = 0x%02x",
2865                                 regspic14[i].dname,
2866                                 8*rbank+regspic14[i].offset);
2867                         else
2868                                 pic14_emitcode ("","%s = %s + 0x%02x",
2869                                 regspic14[i].dname,
2870                                 regspic14[i].base,
2871                                 8*rbank+regspic14[i].offset);
2872                 }
2873         }
2874 #endif
2875         
2876         /* if this is an interrupt service routine */
2877         pic14_inISR = 0;
2878         if (IFFUNC_ISISR(sym->type)) {
2879                 pic14_inISR = 1;
2880         /*  already done in pic14createInterruptVect() - delete me
2881         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2882         emitpcodeNULLop(POC_NOP);
2883         emitpcodeNULLop(POC_NOP);
2884         emitpcodeNULLop(POC_NOP);
2885                 */
2886                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2887                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2888                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2889                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2890                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2891                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2892                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2893                 
2894                 pBlockConvert2ISR(pb);
2895                 pic14_hasInterrupt = 1;
2896 #if 0  
2897                 if (!inExcludeList("acc"))              
2898                         pic14_emitcode ("push","acc");  
2899                 if (!inExcludeList("b"))
2900                         pic14_emitcode ("push","b");
2901                 if (!inExcludeList("dpl"))
2902                         pic14_emitcode ("push","dpl");
2903                 if (!inExcludeList("dph"))
2904                         pic14_emitcode ("push","dph");
2905                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2906                 {
2907                         pic14_emitcode ("push", "dpx");
2908                         /* Make sure we're using standard DPTR */
2909                         pic14_emitcode ("push", "dps");
2910                         pic14_emitcode ("mov", "dps, #0x00");
2911                         if (options.stack10bit)
2912                         { 
2913                                 /* This ISR could conceivably use DPTR2. Better save it. */
2914                                 pic14_emitcode ("push", "dpl1");
2915                                 pic14_emitcode ("push", "dph1");
2916                                 pic14_emitcode ("push", "dpx1");
2917                         }
2918                 }
2919                 /* if this isr has no bank i.e. is going to
2920                 run with bank 0 , then we need to save more
2921                 registers :-) */
2922                 if (!FUNC_REGBANK(sym->type)) {
2923                         
2924                 /* if this function does not call any other
2925                 function then we can be economical and
2926                         save only those registers that are used */
2927                         if (! IFFUNC_HASFCALL(sym->type)) {
2928                                 int i;
2929                                 
2930                                 /* if any registers used */
2931                                 if (sym->regsUsed) {
2932                                         /* save the registers used */
2933                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2934                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2935                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2936                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2937                                         }
2938                                 }
2939                                 
2940                         } else {
2941                         /* this function has    a function call cannot
2942                         determines register usage so we will have the
2943                                 entire bank */
2944                                 saverbank(0,ic,FALSE);
2945                         }       
2946                 }
2947 #endif
2948         } else {
2949         /* if callee-save to be used for this function
2950                 then save the registers being used in this function */
2951                 if (IFFUNC_CALLEESAVES(sym->type)) {
2952                         int i;
2953                         
2954                         /* if any registers used */
2955                         if (sym->regsUsed) {
2956                                 /* save the registers used */
2957                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2958                                         if (bitVectBitValue(sym->regsUsed,i) ||
2959                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2960                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2961                                                 _G.nRegsSaved++;
2962                                         }
2963                                 }
2964                         }
2965                 }
2966         }
2967         
2968         /* set the register bank to the desired value */
2969         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2970                 pic14_emitcode("push","psw");
2971                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2972         }
2973         
2974         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2975                 
2976                 if (options.useXstack) {
2977                         pic14_emitcode("mov","r0,%s",spname);
2978                         pic14_emitcode("mov","a,_bp");
2979                         pic14_emitcode("movx","@r0,a");
2980                         pic14_emitcode("inc","%s",spname);
2981                 }
2982                 else
2983                 {
2984                         /* set up the stack */
2985                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2986                 }
2987                 pic14_emitcode ("mov","_bp,%s",spname);
2988         }
2989         
2990         /* adjust the stack for the function */
2991         if (sym->stack) {
2992                 
2993                 int i = sym->stack;
2994                 if (i > 256 ) 
2995                         werror(W_STACK_OVERFLOW,sym->name);
2996                 
2997                 if (i > 3 && sym->recvSize < 4) {                
2998                         
2999                         pic14_emitcode ("mov","a,sp");
3000                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3001                         pic14_emitcode ("mov","sp,a");
3002                         
3003                 }
3004                 else
3005                         while(i--)
3006                                 pic14_emitcode("inc","sp");
3007         }
3008         
3009         if (sym->xstack) {
3010                 
3011                 pic14_emitcode ("mov","a,_spx");
3012                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013                 pic14_emitcode ("mov","_spx,a");
3014         }
3015         
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions                       */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3022 {
3023         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3024         
3025         FENTRY;
3026
3027         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3028         
3029         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3030         {
3031                 pic14_emitcode ("mov","%s,_bp",spname);
3032         }
3033         
3034         /* if use external stack but some variables were
3035         added to the local stack then decrement the
3036         local stack */
3037         if (options.useXstack && sym->stack) {    
3038                 pic14_emitcode("mov","a,sp");
3039                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3040                 pic14_emitcode("mov","sp,a");
3041         }
3042         
3043         
3044         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3045                 if (options.useXstack) {
3046                         pic14_emitcode("mov","r0,%s",spname);
3047                         pic14_emitcode("movx","a,@r0");
3048                         pic14_emitcode("mov","_bp,a");
3049                         pic14_emitcode("dec","%s",spname);
3050                 }
3051                 else
3052                 {
3053                         pic14_emitcode ("pop","_bp");
3054                 }
3055         }
3056         
3057         /* restore the register bank    */        
3058         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3059                 pic14_emitcode ("pop","psw");
3060         
3061         if (IFFUNC_ISISR(sym->type)) {
3062                 
3063                 /* now we need to restore the registers */
3064                 /* if this isr has no bank i.e. is going to
3065                 run with bank 0 , then we need to save more
3066 registers :-) */
3067                 if (!FUNC_REGBANK(sym->type)) {
3068                         
3069                 /* if this function does not call any other
3070                 function then we can be economical and
3071                         save only those registers that are used */
3072                         if (! IFFUNC_HASFCALL(sym->type)) {
3073                                 int i;
3074                                 
3075                                 /* if any registers used */
3076                                 if (sym->regsUsed) {
3077                                         /* save the registers used */
3078                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3079                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3080                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3081                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3082                                         }
3083                                 }
3084                                 
3085                         } else {
3086                         /* this function has    a function call cannot
3087                         determines register usage so we will have the
3088                                 entire bank */
3089                                 unsaverbank(0,ic,FALSE);
3090                         }       
3091                 }
3092 #if 0
3093                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3094                 {
3095                         if (options.stack10bit)
3096                         {
3097                                 pic14_emitcode ("pop", "dpx1");
3098                                 pic14_emitcode ("pop", "dph1");
3099                                 pic14_emitcode ("pop", "dpl1");
3100                         } 
3101                         pic14_emitcode ("pop", "dps");
3102                         pic14_emitcode ("pop", "dpx");
3103                 }
3104                 if (!inExcludeList("dph"))
3105                         pic14_emitcode ("pop","dph");
3106                 if (!inExcludeList("dpl"))
3107                         pic14_emitcode ("pop","dpl");
3108                 if (!inExcludeList("b"))
3109                         pic14_emitcode ("pop","b");
3110                 if (!inExcludeList("acc"))
3111                         pic14_emitcode ("pop","acc");
3112                 
3113                 if (IFFUNC_ISCRITICAL(sym->type))
3114                         pic14_emitcode("setb","ea");
3115 #endif
3116                 
3117                 /* if debug then send end of function */
3118                 /*      if (options.debug && currFunc) { */
3119                 if (currFunc) {
3120                         debugFile->writeEndFunction (currFunc, ic, 1);
3121                 }
3122                 
3123                 pic14_emitcode ("reti","");
3124                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3125                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3126                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3127                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3128                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3129                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3130                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3131                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3132                 emitpcodeNULLop(POC_RETFIE);
3133         }
3134         else {
3135                 if (IFFUNC_ISCRITICAL(sym->type))
3136                         pic14_emitcode("setb","ea");
3137                 
3138                 if (IFFUNC_CALLEESAVES(sym->type)) {
3139                         int i;
3140                         
3141                         /* if any registers used */
3142                         if (sym->regsUsed) {
3143                                 /* save the registers used */
3144                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3145                                         if (bitVectBitValue(sym->regsUsed,i) ||
3146                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3147                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3148                                 }
3149                         }
3150                         
3151                 }
3152                 
3153                 /* if debug then send end of function */
3154                 if (currFunc) {
3155                         debugFile->writeEndFunction (currFunc, ic, 1);
3156                 }
3157                 
3158                 pic14_emitcode ("return","");
3159                 emitpcodeNULLop(POC_RETURN);
3160                 
3161                 /* Mark the end of a function */
3162                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3163         }
3164         
3165 }
3166
3167 /*-----------------------------------------------------------------*/
3168 /* genRet - generate code for return statement                                     */
3169 /*-----------------------------------------------------------------*/
3170 static void genRet (iCode *ic)
3171 {
3172         int size,offset = 0;
3173         
3174         FENTRY;
3175
3176         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3177         /* if we have no return value then
3178         just generate the "ret" */
3179         if (!IC_LEFT(ic)) 
3180                 goto jumpret;           
3181         
3182                 /* we have something to return then
3183         move the return value into place */
3184         aopOp(IC_LEFT(ic),ic,FALSE);
3185         size = AOP_SIZE(IC_LEFT(ic));
3186
3187         for (offset = 0; offset < size; offset++)
3188         {
3189                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3190         }
3191         
3192         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3193         
3194 jumpret:
3195         /* generate a jump to the return label
3196         if the next is not the return statement */
3197         if (!(ic->next && ic->next->op == LABEL &&
3198                 IC_LABEL(ic->next) == returnLabel)) {
3199                 
3200                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3201         }
3202         
3203 }
3204
3205 /*-----------------------------------------------------------------*/
3206 /* genLabel - generates a label                                                                    */
3207 /*-----------------------------------------------------------------*/
3208 static void genLabel (iCode *ic)
3209 {
3210         FENTRY;
3211
3212         /* special case never generate */
3213         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3214         if (IC_LABEL(ic) == entryLabel)
3215                 return ;
3216         
3217         emitpLabel(IC_LABEL(ic)->key);
3218         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3219 }
3220
3221 /*-----------------------------------------------------------------*/
3222 /* genGoto - generates a goto                                                                      */
3223 /*-----------------------------------------------------------------*/
3224 //tsd
3225 static void genGoto (iCode *ic)
3226 {
3227         FENTRY;
3228
3229         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3230         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3231 }
3232
3233
3234 /*-----------------------------------------------------------------*/
3235 /* genMultbits :- multiplication of bits                                                   */
3236 /*-----------------------------------------------------------------*/
3237 static void genMultbits (operand *left, 
3238                                                  operand *right, 
3239                                                  operand *result)
3240 {
3241         FENTRY;
3242         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3243         
3244         if(!pic14_sameRegs(AOP(result),AOP(right)))
3245                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3246         
3247         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3248         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3249         emitpcode(POC_BCF,  popGet(AOP(result),0));
3250         
3251 }
3252
3253
3254 /*-----------------------------------------------------------------*/
3255 /* genMultOneByte : 8 bit multiplication & division                        */
3256 /*-----------------------------------------------------------------*/
3257 static void genMultOneByte (operand *left,
3258                                                         operand *right,
3259                                                         operand *result)
3260 {
3261         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3262         
3263         // symbol *lbl ;
3264         int size,offset,i;
3265         
3266         
3267         FENTRY;
3268         
3269         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3270         DEBUGpic14_AopType(__LINE__,left,right,result);
3271         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3272         
3273         /* (if two literals, the value is computed before) */
3274         /* if one literal, literal on the right */
3275         if (AOP_TYPE(left) == AOP_LIT){
3276                 operand *t = right;
3277                 right = left;
3278                 left = t;
3279         }
3280
3281         assert (AOP_SIZE(left) == AOP_SIZE(right));
3282         
3283         size = min(AOP_SIZE(result),AOP_SIZE(left));
3284         offset = Gstack_base_addr - (2*size - 1);
3285
3286         /* pass right operand as argument */
3287         for (i=0; i < size; i++)
3288         {
3289                 mov2w (AOP(right), i);
3290                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3291         } // for
3292         
3293         /* pass left operand as argument */
3294         for (i=0; i < size; i++)
3295         {
3296                 mov2w (AOP(left), i);
3297                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3298         } // for
3299         assert (offset == Gstack_base_addr);
3300         
3301         /* call library routine */
3302         assert (size > 0 && size <= 4);
3303         call_libraryfunc (func[size]);
3304         
3305         /* assign result */
3306         movwf (AOP(result), size-1);
3307         for (i=0; i < size - 1; i++)
3308         {
3309                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3310                 movwf (AOP(result), size - 2 - i);
3311         } // for
3312
3313         /* now (zero-/sign) extend the result to its size */
3314         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3315 }
3316
3317 /*-----------------------------------------------------------------*/
3318 /* genMult - generates code for multiplication                                     */
3319 /*-----------------------------------------------------------------*/
3320 static void genMult (iCode *ic)
3321 {
3322         operand *left = IC_LEFT(ic);
3323         operand *right = IC_RIGHT(ic);
3324         operand *result= IC_RESULT(ic); 
3325         
3326         FENTRY;
3327
3328         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3329         /* assign the amsops */
3330         aopOp (left,ic,FALSE);
3331         aopOp (right,ic,FALSE);
3332         aopOp (result,ic,TRUE);
3333         
3334         DEBUGpic14_AopType(__LINE__,left,right,result);
3335         
3336         /* special cases first */
3337         /* both are bits */
3338         if (AOP_TYPE(left) == AOP_CRY &&
3339                 AOP_TYPE(right)== AOP_CRY) {
3340                 genMultbits(left,right,result);
3341                 goto release ;
3342         }
3343         
3344         /* if both are of size == 1 */
3345         if (AOP_SIZE(left) == 1 &&
3346                 AOP_SIZE(right) == 1 ) {
3347                 genMultOneByte(left,right,result);
3348                 goto release ;
3349         }
3350         
3351         /* should have been converted to function call */
3352         assert(0) ;
3353         
3354 release :
3355         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3356         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3357         freeAsmop(result,NULL,ic,TRUE); 
3358 }
3359
3360 /*-----------------------------------------------------------------*/
3361 /* genDivbits :- division of bits                                                                  */
3362 /*-----------------------------------------------------------------*/
3363 static void genDivbits (operand *left, 
3364                                                 operand *right, 
3365                                                 operand *result)
3366 {
3367         
3368         char *l;
3369         
3370         FENTRY;
3371
3372         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3373         /* the result must be bit */      
3374         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3375         l = aopGet(AOP(left),0,FALSE,FALSE);
3376         
3377         MOVA(l);          
3378         
3379         pic14_emitcode("div","ab");
3380         pic14_emitcode("rrc","a");
3381         aopPut(AOP(result),"c",0);
3382 }
3383
3384 /*-----------------------------------------------------------------*/
3385 /* genDivOneByte : 8 bit division                                                                  */
3386 /*-----------------------------------------------------------------*/
3387 static void genDivOneByte (operand *left,
3388                                                    operand *right,
3389                                                    operand *result)
3390 {
3391         int size;
3392         int sign;
3393         
3394         FENTRY;
3395         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3396         
3397         assert (AOP_SIZE(right) == 1);
3398         assert (AOP_SIZE(left) == 1);
3399
3400         size = min(AOP_SIZE(result),AOP_SIZE(left));
3401         sign = !(SPEC_USIGN(operandType(left))
3402                 && SPEC_USIGN(operandType(right)));
3403
3404         if (AOP_TYPE(right) == AOP_LIT)
3405         {
3406                 /* XXX: might add specialized code */
3407         }
3408
3409         if (!sign)
3410         {
3411                 /* unsigned division */
3412         #if 1
3413                 mov2w(AOP(right),0);
3414                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3415                 mov2w(AOP(left),0);
3416                 call_libraryfunc("__divuchar");
3417                 movwf(AOP(result),0);
3418         #else
3419                 pCodeOp *temp;
3420                 symbol *lbl;
3421
3422                 temp = popGetTempReg();
3423                 lbl = newiTempLabel(NULL);
3424                 
3425                 /* XXX: improve this naive approach:
3426                    [result] = [a] / [b]
3427                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3428
3429                    In PIC assembler:
3430                    movf  left,W
3431                    movwf temp           // temp <-- left
3432                    movf  right,W        // W <-- right
3433                    clrf  result
3434                    label1:
3435                    incf  result
3436                    subwf temp,F         // temp <-- temp - W
3437                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3438                    goto  label1
3439                    decf result          // we just subtract once too often
3440                  */
3441
3442                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3443                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3444                 
3445                 mov2w(AOP(left),0);
3446                 emitpcode(POC_MOVWF, temp);
3447                 mov2w(AOP(right),0);
3448                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3449
3450                 emitpLabel(lbl->key);
3451                 emitpcode(POC_INCF, popGet(AOP(result),0));
3452                 emitpcode(POC_SUBWF, temp);
3453                 emitSKPNC;
3454                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3455                 emitpcode(POC_DECF, popGet(AOP(result),0));
3456         #endif
3457         }
3458         else
3459         {
3460                 /* signed division */
3461                 mov2w(AOP(right),0);
3462                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3463                 mov2w(AOP(left),0);
3464                 call_libraryfunc("__divschar");
3465                 movwf(AOP(result),0);
3466         }
3467
3468         /* now performed the signed/unsigned division -- extend result */
3469         addSign(result, 1, sign);
3470 }
3471
3472 /*-----------------------------------------------------------------*/
3473 /* genDiv - generates code for division                            */
3474 /*-----------------------------------------------------------------*/
3475 static void genDiv (iCode *ic)
3476 {
3477         operand *left = IC_LEFT(ic);
3478         operand *right = IC_RIGHT(ic);
3479         operand *result= IC_RESULT(ic); 
3480         
3481         FENTRY;
3482         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3483         /* assign the amsops */
3484         aopOp (left,ic,FALSE);
3485         aopOp (right,ic,FALSE);
3486         aopOp (result,ic,TRUE);
3487         
3488         /* special cases first */
3489         /* both are bits */
3490         if (AOP_TYPE(left) == AOP_CRY &&
3491                 AOP_TYPE(right)== AOP_CRY) {
3492                 genDivbits(left,right,result);
3493                 goto release ;
3494         }
3495         
3496         /* if both are of size == 1 */
3497         if (AOP_SIZE(left) == 1 &&
3498                 AOP_SIZE(right) == 1 ) {
3499                 genDivOneByte(left,right,result);
3500                 goto release ;
3501         }
3502         
3503         /* should have been converted to function call */
3504         assert(0);
3505 release :
3506         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508         freeAsmop(result,NULL,ic,TRUE); 
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* genModOneByte : 8 bit modulus                                                                   */
3513 /*-----------------------------------------------------------------*/
3514 static void genModOneByte (operand *left,
3515                                                    operand *right,
3516                                                    operand *result)
3517 {
3518         int size;
3519         int sign;
3520         
3521         FENTRY;
3522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3523         
3524         assert (AOP_SIZE(right) == 1);
3525         assert (AOP_SIZE(left) == 1);
3526
3527         size = min(AOP_SIZE(result),AOP_SIZE(left));
3528         sign = !(SPEC_USIGN(operandType(left))
3529                 && SPEC_USIGN(operandType(right)));
3530
3531         if (AOP_TYPE(right) == AOP_LIT)
3532         {
3533                 /* XXX: might add specialized code */
3534         }
3535
3536         if (!sign)
3537         {
3538                 /* unsigned division */
3539         #if 1
3540                 mov2w(AOP(right),0);
3541                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3542                 mov2w(AOP(left),0);
3543                 call_libraryfunc("__moduchar");
3544                 movwf(AOP(result),0);
3545         #else
3546                 pCodeOp *temp;
3547                 symbol *lbl;
3548
3549                 lbl = newiTempLabel(NULL);
3550                 
3551                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3552
3553                 /* XXX: improve this naive approach:
3554                    [result] = [a] % [b]
3555                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3556
3557                    In PIC assembler:
3558                    movf  left,W
3559                    movwf result         // result <-- left
3560                    movf  right,W        // W <-- right
3561                    label1:
3562                    subwf result,F       // result <-- result - W
3563                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3564                    goto  label1
3565                    addwf result, F      // we just subtract once too often
3566                  */
3567
3568                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3569                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3570                 
3571                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3572                 {
3573                         mov2w(AOP(left),0);
3574                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3575                 }
3576                 mov2w(AOP(right),0);
3577
3578                 emitpLabel(lbl->key);
3579                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3580                 emitSKPNC;
3581                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3582                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3583         #endif
3584         }
3585         else
3586         {
3587                 /* signed division */
3588                 mov2w(AOP(right),0);
3589                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3590                 mov2w(AOP(left),0);
3591                 call_libraryfunc("__modschar");
3592                 movwf(AOP(result),0);
3593         }
3594
3595         /* now we performed the signed/unsigned modulus -- extend result */
3596         addSign(result, 1, sign);
3597 }
3598
3599 /*-----------------------------------------------------------------*/
3600 /* genMod - generates code for division                                                    */
3601 /*-----------------------------------------------------------------*/
3602 static void genMod (iCode *ic)
3603 {
3604         operand *left = IC_LEFT(ic);
3605         operand *right = IC_RIGHT(ic);
3606         operand *result= IC_RESULT(ic);  
3607         
3608         FENTRY;
3609         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3610         /* assign the amsops */
3611         aopOp (left,ic,FALSE);
3612         aopOp (right,ic,FALSE);
3613         aopOp (result,ic,TRUE);
3614         
3615         /* if both are of size == 1 */
3616         if (AOP_SIZE(left) == 1 &&
3617                 AOP_SIZE(right) == 1 ) {
3618                 genModOneByte(left,right,result);
3619                 goto release ;
3620         }
3621         
3622         /* should have been converted to function call */
3623         assert(0);
3624         
3625 release :
3626         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3627         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3628         freeAsmop(result,NULL,ic,TRUE); 
3629 }
3630
3631 /*-----------------------------------------------------------------*/
3632 /* genIfxJump :- will create a jump depending on the ifx                   */
3633 /*-----------------------------------------------------------------*/
3634 /*
3635 note: May need to add parameter to indicate when a variable is in bit space.
3636 */
3637 static void genIfxJump (iCode *ic, char *jval)
3638 {
3639         
3640         FENTRY;
3641         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3642         /* if true label then we jump if condition
3643         supplied is true */
3644         if ( IC_TRUE(ic) ) {
3645                 
3646                 if(strcmp(jval,"a") == 0)
3647                         emitSKPZ;
3648                 else if (strcmp(jval,"c") == 0)
3649                         emitSKPC;
3650                 else {
3651                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3652                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3653                 }
3654                 
3655                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3656                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3657                 
3658         }
3659         else {
3660                 /* false label is present */
3661                 if(strcmp(jval,"a") == 0)
3662                         emitSKPNZ;
3663                 else if (strcmp(jval,"c") == 0)
3664                         emitSKPNC;
3665                 else {
3666                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3667                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3668                 }
3669                 
3670                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3671                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3672                 
3673         }
3674         
3675         
3676         /* mark the icode as generated */
3677         ic->generated = 1;
3678 }
3679
3680 #if 0
3681 /*-----------------------------------------------------------------*/
3682 /* genSkip                                                                                                                 */
3683 /*-----------------------------------------------------------------*/
3684 static void genSkip(iCode *ifx,int status_bit)
3685 {
3686         FENTRY;
3687         if(!ifx)
3688                 return;
3689         
3690         if ( IC_TRUE(ifx) ) {
3691                 switch(status_bit) {
3692                 case 'z':
3693                         emitSKPNZ;
3694                         break;
3695                         
3696                 case 'c':
3697                         emitSKPNC;
3698                         break;
3699                         
3700                 case 'd':
3701                         emitSKPDC;
3702                         break;
3703                         
3704                 }
3705                 
3706                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3707                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3708                 
3709         } else {
3710                 
3711                 switch(status_bit) {
3712                         
3713                 case 'z':
3714                         emitSKPZ;
3715                         break;
3716                         
3717                 case 'c':
3718                         emitSKPC;
3719                         break;
3720                         
3721                 case 'd':
3722                         emitSKPDC;
3723                         break;
3724                 }
3725                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3726                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3727                 
3728         }
3729         
3730 }
3731 #endif
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genSkipc                                                                                                        */
3735 /*-----------------------------------------------------------------*/
3736 static void genSkipc(resolvedIfx *rifx)
3737 {
3738         FENTRY;
3739         if(!rifx)
3740                 return;
3741         
3742         if(rifx->condition)
3743                 emitSKPNC;
3744         else
3745                 emitSKPC;
3746         
3747         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3748         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3749         rifx->generated = 1;
3750 }
3751
3752 #if 0
3753 /*-----------------------------------------------------------------*/
3754 /* genSkipz2                                                                                                       */
3755 /*-----------------------------------------------------------------*/
3756 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3757 {
3758         FENTRY;
3759         if(!rifx)
3760                 return;
3761         
3762         if( (rifx->condition ^ invert_condition) & 1)
3763                 emitSKPZ;
3764         else
3765                 emitSKPNZ;
3766         
3767         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3768         rifx->generated = 1;
3769 }
3770 #endif
3771
3772 #if 0
3773 /*-----------------------------------------------------------------*/
3774 /* genSkipz                                                        */
3775 /*-----------------------------------------------------------------*/
3776 static void genSkipz(iCode *ifx, int condition)
3777 {
3778         FENTRY;
3779         assert (ifx != NULL);
3780         
3781         if(condition)
3782                 emitSKPNZ;
3783         else
3784                 emitSKPZ;
3785         
3786         if ( IC_TRUE(ifx) )
3787                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3788         else
3789                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3790         
3791         if ( IC_TRUE(ifx) )
3792                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3793         else
3794                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3795         
3796 }
3797 #endif
3798
3799 #if 0
3800 /*-----------------------------------------------------------------*/
3801 /* genSkipCond                                                     */
3802 /*-----------------------------------------------------------------*/
3803 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3804 {
3805         FENTRY;
3806         if(!rifx)
3807                 return;
3808         
3809         if(rifx->condition)
3810                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3811         else
3812                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3813         
3814         
3815         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3816         rifx->generated = 1;
3817 }
3818 #endif
3819
3820 #if 0
3821 /*-----------------------------------------------------------------*/
3822 /* genChkZeroes :- greater or less than comparison                 */
3823 /*     For each byte in a literal that is zero, inclusive or the   */
3824 /*     the corresponding byte in the operand with W                */
3825 /*     returns true if any of the bytes are zero                   */
3826 /*-----------------------------------------------------------------*/
3827 static int genChkZeroes(operand *op, int lit,  int size)
3828 {
3829         
3830         int i;
3831         int flag =1;
3832         
3833         while(size--) {
3834                 i = (lit >> (size*8)) & 0xff;
3835                 
3836                 if(i==0) {
3837                         if(flag) 
3838                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3839                         else
3840                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3841                         flag = 0;
3842                 }
3843         }
3844         
3845         return (flag==0);
3846 }
3847 #endif
3848
3849
3850 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3851 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3852 #define DEBUGpc           emitpComment
3853
3854 /*-----------------------------------------------------------------*/
3855 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3856 /*                  aop (if it's NOT a literal) or from lit (if    */
3857 /*                  aop is a literal)                              */
3858 /*-----------------------------------------------------------------*/
3859 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3860   if (aop->type == AOP_LIT) {
3861     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3862   } else {
3863     emitpcode (POC_MOVFW, popGet (aop, offset));
3864   }
3865 }
3866
3867 /* genCmp performs a left < right comparison, stores
3868  * the outcome in result (if != NULL) and generates
3869  * control flow code for the ifx (if != NULL).
3870  *
3871  * This version leaves in sequences like
3872  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3873  * which should be optmized by the peephole
3874  * optimizer - RN 2005-01-01 */
3875 static void genCmp (operand *left,operand *right,
3876                     operand *result, iCode *ifx, int sign)
3877 {
3878   resolvedIfx rIfx;
3879   int size;
3880   int offs;
3881   symbol *templbl;
3882   operand *dummy;
3883   unsigned long lit;
3884   unsigned long mask;
3885   int performedLt;
3886   int invert_result = 0;
3887
3888   FENTRY;
3889   
3890   assert (AOP_SIZE(left) == AOP_SIZE(right));
3891   assert (left && right);
3892
3893   size = AOP_SIZE(right) - 1;
3894   mask = (0x100UL << (size*8)) - 1;
3895   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3896   performedLt = 1;
3897   templbl = NULL;
3898   lit = 0;
3899   
3900   resolveIfx (&rIfx, ifx);
3901
3902   /**********************************************************************
3903    * handle bits - bit compares are promoted to int compares seemingly! *
3904    **********************************************************************/
3905 #if 0
3906   // THIS IS COMPLETELY UNTESTED!
3907   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3908     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3909     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3910     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3911
3912     emitSETC;
3913     // 1 < {0,1} is false --> clear C by skipping the next instruction
3914     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3915     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3916     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3917     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3918     emitCLRC; // only skipped for left=0 && right=1
3919
3920     goto correct_result_in_carry;
3921   } // if
3922 #endif
3923
3924   /*************************************************
3925    * make sure that left is register (or the like) *
3926    *************************************************/
3927   if (!isAOP_REGlike(left)) {
3928     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3929     assert (isAOP_LIT(left));
3930     assert (isAOP_REGlike(right));
3931     // swap left and right
3932     // left < right <==> right > left <==> (right >= left + 1)
3933     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3934
3935     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3936       // MAXVALUE < right? always false
3937       if (performedLt) emitCLRC; else emitSETC;
3938       goto correct_result_in_carry;
3939     } // if
3940
3941     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3942     // that's why we handled it above.
3943     lit++;
3944
3945     dummy = left;
3946     left = right;
3947     right = dummy;
3948
3949     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3950   } else if (isAOP_LIT(right)) {
3951     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3952   } // if
3953
3954   assert (isAOP_REGlike(left)); // left must be register or the like
3955   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3956
3957   /*************************************************
3958    * special cases go here                         *
3959    *************************************************/
3960
3961   if (isAOP_LIT(right)) {
3962     if (!sign) {
3963       // unsigned comparison to a literal
3964       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3965       if (lit == 0) {
3966         // unsigned left < 0? always false
3967         if (performedLt) emitCLRC; else emitSETC;
3968         goto correct_result_in_carry;
3969       }
3970     } else {
3971       // signed comparison to a literal
3972       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3973       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3974         // signed left < 0x80000000? always false
3975         if (performedLt) emitCLRC; else emitSETC;
3976         goto correct_result_in_carry;
3977       } else if (lit == 0) {
3978         // compare left < 0; set CARRY if SIGNBIT(left) is set
3979         if (performedLt) emitSETC; else emitCLRC;
3980         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3981         if (performedLt) emitCLRC; else emitSETC;
3982         goto correct_result_in_carry;
3983       }
3984     } // if (!sign)
3985   } // right is literal
3986
3987   /*************************************************
3988    * perform a general case comparison             *
3989    * make sure we get CARRY==1 <==> left >= right  *
3990    *************************************************/
3991   // compare most significant bytes
3992   //DEBUGpc ("comparing bytes at offset %d", size);
3993   if (!sign) {
3994     // unsigned comparison
3995     pic14_mov2w_regOrLit (AOP(right), lit, size);
3996     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3997   } else {
3998     // signed comparison
3999     // (add 2^n to both operands then perform an unsigned comparison)
4000     if (isAOP_LIT(right)) {
4001       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4002       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4003
4004       if (litbyte == 0x80) {
4005         // left >= 0x80 -- always true, but more bytes to come
4006         mov2w (AOP(left), size);
4007         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4008         emitSETC;
4009       } else {
4010         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4011         mov2w (AOP(left), size);
4012         emitpcode (POC_ADDLW, popGetLit (0x80));
4013         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4014       } // if
4015     } else {
4016       pCodeOp *pctemp = popGetTempReg();
4017       mov2w (AOP(left), size);
4018       emitpcode (POC_ADDLW, popGetLit (0x80));
4019       emitpcode (POC_MOVWF, pctemp);
4020       mov2w (AOP(right), size);
4021       emitpcode (POC_ADDLW, popGetLit (0x80));
4022       emitpcode (POC_SUBFW, pctemp);
4023       popReleaseTempReg(pctemp);
4024     }
4025   } // if (!sign)
4026
4027   // compare remaining bytes (treat as unsigned case from above)
4028   templbl = newiTempLabel ( NULL );
4029   offs = size;
4030   while (offs--) {
4031     //DEBUGpc ("comparing bytes at offset %d", offs);
4032     emitSKPZ;
4033     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4034     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4035     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4036   } // while (offs)
4037   emitpLabel (templbl->key);
4038   goto result_in_carry;
4039
4040 result_in_carry:
4041   
4042   /****************************************************
4043    * now CARRY contains the result of the comparison: *
4044    * SUBWF sets CARRY iff                             *
4045    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4046    * (F=left, W=right)                                *
4047    ****************************************************/
4048
4049   if (performedLt) {
4050     invert_result = 1;
4051     // value will be used in the following genSkipc()
4052     rIfx.condition ^= 1;
4053   } // if
4054
4055 correct_result_in_carry:
4056
4057   // assign result to variable (if neccessary)
4058   if (result && AOP_TYPE(result) != AOP_CRY) {
4059     //DEBUGpc ("assign result");
4060     size = AOP_SIZE(result);
4061     while (size--) {
4062       emitpcode (POC_CLRF, popGet (AOP(result), size));
4063     } // while
4064     if (invert_result) {
4065       emitSKPC;
4066       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4067     } else {
4068       emitpcode (POC_RLF, popGet (AOP(result), 0));
4069     }
4070   } // if (result)
4071
4072   // perform conditional jump
4073   if (ifx) {
4074     //DEBUGpc ("generate control flow");
4075     genSkipc (&rIfx);
4076     ifx->generated = 1;
4077   } // if
4078 }
4079
4080
4081 #if 0
4082 /* OLD VERSION -- BUGGY, DO NOT USE */
4083
4084 /*-----------------------------------------------------------------*/
4085 /* genCmp :- greater or less than comparison                       */
4086 /*-----------------------------------------------------------------*/
4087 static void genCmp (operand *left,operand *right,
4088                                         operand *result, iCode *ifx, int sign)
4089 {
4090         int size; //, offset = 0 ;
4091         unsigned long lit = 0L,i = 0;
4092         resolvedIfx rFalseIfx;
4093         //  resolvedIfx rTrueIfx;
4094         symbol *truelbl;
4095
4096         FENTRY;
4097         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4098         /*
4099         if(ifx) {
4100         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4101         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4102         }
4103         */
4104         
4105         resolveIfx(&rFalseIfx,ifx);
4106         truelbl  = newiTempLabel(NULL);
4107         size = max(AOP_SIZE(left),AOP_SIZE(right));
4108         
4109         DEBUGpic14_AopType(__LINE__,left,right,result);
4110         
4111 #define _swapp
4112         
4113         /* if literal is on the right then swap with left */
4114         if ((AOP_TYPE(right) == AOP_LIT)) {
4115                 operand *tmp = right ;
4116                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4117                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4118 #ifdef _swapp
4119                 
4120                 lit = (lit - 1) & mask;
4121                 right = left;
4122                 left = tmp;
4123                 rFalseIfx.condition ^= 1;
4124 #endif
4125                 
4126         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4127                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4128         }
4129         
4130         
4131         //if(IC_TRUE(ifx) == NULL)
4132         /* if left & right are bit variables */
4133         if (AOP_TYPE(left) == AOP_CRY &&
4134                 AOP_TYPE(right) == AOP_CRY ) {
4135                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4136                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4137         } else {
4138         /* subtract right from left if at the
4139         end the carry flag is set then we know that
4140                 left is greater than right */
4141                 
4142                 symbol *lbl  = newiTempLabel(NULL);
4143                 
4144 #ifndef _swapp
4145                 if(AOP_TYPE(right) == AOP_LIT) {
4146                         
4147                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4148                         
4149                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4150                         
4151                         /* special cases */
4152                         
4153                         if(lit == 0) {
4154                                 
4155                                 if(sign != 0) 
4156                                         genSkipCond(&rFalseIfx,left,size-1,7);
4157                                 else 
4158                                         /* no need to compare to 0...*/
4159                                         /* NOTE: this is a de-generate compare that most certainly 
4160                                         *       creates some dead code. */
4161                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4162                                 
4163                                 if(ifx) ifx->generated = 1;
4164                                 return;
4165                                 
4166                         }
4167                         size--;
4168                         
4169                         if(size == 0) {
4170                                 //i = (lit >> (size*8)) & 0xff;
4171                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4172                                 
4173                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4174                                 
4175                                 i = ((0-lit) & 0xff);
4176                                 if(sign) {
4177                                         if( i == 0x81) { 
4178                                         /* lit is 0x7f, all signed chars are less than
4179                                                 * this except for 0x7f itself */
4180                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4181                                                 genSkipz2(&rFalseIfx,0);
4182                                         } else {
4183                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4184                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4185                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4186                                         }
4187                                         
4188                                 } else {
4189                                         if(lit == 1) {
4190                                                 genSkipz2(&rFalseIfx,1);
4191                                         } else {
4192                                                 emitpcode(POC_ADDLW, popGetLit(i));
4193                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4194                                         }
4195                                 }
4196                                 
4197                                 if(ifx) ifx->generated = 1;
4198                                 return;
4199                         }
4200                         
4201                         /* chars are out of the way. now do ints and longs */
4202                         
4203                         
4204                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4205                         
4206                         /* special cases */
4207                         
4208                         if(sign) {
4209                                 
4210                                 if(lit == 0) {
4211                                         genSkipCond(&rFalseIfx,left,size,7);
4212                                         if(ifx) ifx->generated = 1;
4213                                         return;
4214                                 }
4215                                 
4216                                 if(lit <0x100) {
4217                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218                                         
4219                                         //rFalseIfx.condition ^= 1;
4220                                         //genSkipCond(&rFalseIfx,left,size,7);
4221                                         //rFalseIfx.condition ^= 1;
4222                                         
4223                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4224                                         if(rFalseIfx.condition)
4225                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4226                                         else
4227                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4228                                         
4229                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4230                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4231                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4232                                         
4233                                         while(size > 1)
4234                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4235                                         
4236                                         if(rFalseIfx.condition) {
4237                                                 emitSKPZ;
4238                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4239                                                 
4240                                         } else {
4241                                                 emitSKPNZ;
4242                                         }
4243                                         
4244                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4245                                         emitpLabel(truelbl->key);
4246                                         if(ifx) ifx->generated = 1;
4247                                         return;
4248                                         
4249                                 }
4250                                 
4251                                 if(size == 1) {
4252                                         
4253                                         if( (lit & 0xff) == 0) {
4254                                                 /* lower byte is zero */
4255                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4256                                                 i = ((lit >> 8) & 0xff) ^0x80;
4257                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4258                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4259                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4260                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4261                                                 
4262                                                 
4263                                                 if(ifx) ifx->generated = 1;
4264                                                 return;
4265                                                 
4266                                         }
4267                                 } else {
4268                                         /* Special cases for signed longs */
4269                                         if( (lit & 0xffffff) == 0) {
4270                                                 /* lower byte is zero */
4271                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4272                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4273                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4274                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4275                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4276                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4277                                                 
4278                                                 
4279                                                 if(ifx) ifx->generated = 1;
4280                                                 return;
4281                                                 
4282                                         }
4283                                         
4284                                 }
4285                                 
4286                                 
4287                                 if(lit & (0x80 << (size*8))) {
4288                                         /* lit is negative */
4289                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4290                                         
4291                                         //genSkipCond(&rFalseIfx,left,size,7);
4292                                         
4293                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4294                                         
4295                                         if(rFalseIfx.condition)
4296                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4297                                         else
4298                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4299                                         
4300                                         
4301                                 } else {
4302                                         /* lit is positive */
4303                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4304                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4305                                         if(rFalseIfx.condition)
4306                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4307                                         else
4308                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4309                                         
4310                                 }
4311                                 
4312                                 /* There are no more special cases, so perform a general compare */
4313                                 
4314                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4315                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4316                                 
4317                                 while(size--) {
4318                                         
4319                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4320                                         emitSKPNZ;
4321                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4322                                 }
4323                                 //rFalseIfx.condition ^= 1;
4324                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4325                                 
4326                                 emitpLabel(truelbl->key);
4327                                 
4328                                 if(ifx) ifx->generated = 1;
4329                                 return;
4330                                 
4331                                 
4332                         }
4333
4334
4335                         /* sign is out of the way. So now do an unsigned compare */
4336                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4337
4338
4339                         /* General case - compare to an unsigned literal on the right.*/
4340
4341                         i = (lit >> (size*8)) & 0xff;
4342                         emitpcode(POC_MOVLW, popGetLit(i));
4343                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4344                         while(size--) {
4345                                 i = (lit >> (size*8)) & 0xff;
4346                                 
4347                                 if(i) {
4348                                         emitpcode(POC_MOVLW, popGetLit(i));
4349                                         emitSKPNZ;
4350                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4351                                 } else {
4352                                 /* this byte of the lit is zero, 
4353                                         *if it's not the last then OR in the variable */
4354                                         if(size)
4355                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4356                                 }
4357                         }
4358
4359
4360                 emitpLabel(lbl->key);
4361                 //if(emitFinalCheck)
4362                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4363                 if(sign)
4364                         emitpLabel(truelbl->key);
4365
4366                 if(ifx) ifx->generated = 1;
4367                 return;
4368
4369
4370                 }
4371 #endif  // _swapp
4372
4373                 if(AOP_TYPE(left) == AOP_LIT) {
4374                         //symbol *lbl = newiTempLabel(NULL);
4375                         
4376                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4377                         
4378                         
4379                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4380                         
4381                         /* Special cases */
4382                         if((lit == 0) && (sign == 0)){
4383                                 
4384                                 size--;
4385                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4386                                 while(size) 
4387                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4388                                 
4389                                 genSkipz2(&rFalseIfx,0);
4390                                 if(ifx) ifx->generated = 1;
4391                                 return;
4392                         }
4393                         
4394                         if(size==1) {
4395                                 /* Special cases */
4396                                 lit &= 0xff;
4397                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4398                                         /* degenerate compare can never be true */
4399                                         if(rFalseIfx.condition == 0)
4400                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4401                                         
4402                                         if(ifx) ifx->generated = 1;
4403                                         return;
4404                                 }
4405                                 
4406                                 if(sign) {
4407                                         /* signed comparisons to a literal byte */
4408                                         
4409                                         int lp1 = (lit+1) & 0xff;
4410                                         
4411                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4412                                         switch (lp1) {
4413                                         case 0:
4414                                                 rFalseIfx.condition ^= 1;
4415                                                 genSkipCond(&rFalseIfx,right,0,7);
4416                                                 break;
4417                                         case 0x7f:
4418                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4419                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4420                                                 genSkipz2(&rFalseIfx,1);
4421                                                 break;
4422                                         default:
4423                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4424                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4425                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4426                                                 rFalseIfx.condition ^= 1;
4427                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4428                                                 break;
4429                                         }
4430                                         if(ifx) ifx->generated = 1;
4431                                 } else {
4432                                         /* unsigned comparisons to a literal byte */
4433                                         
4434                                         switch(lit & 0xff ) {
4435                                         case 0:
4436                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4437                                                 genSkipz2(&rFalseIfx,0);
4438                                                 if(ifx) ifx->generated = 1;
4439                                                 break;
4440                                         case 0x7f:
4441                                                 genSkipCond(&rFalseIfx,right,0,7);
4442                                                 if(ifx) ifx->generated = 1;
4443                                                 break;
4444                                                 
4445                                         default:
4446                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4447                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4448                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4449                                                 rFalseIfx.condition ^= 1;
4450                                                 if (AOP_TYPE(result) == AOP_CRY) {
4451                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4452                                                         if(ifx) ifx->generated = 1;
4453                                                 } else {
4454                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4455                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4456                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4457                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4458                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4459                                                 }       
4460                                                 break;
4461                                         }
4462                                 }
4463                                 
4464                                 //goto check_carry;
4465                                 return;
4466                                 
4467                         } else {
4468                                 
4469                                 /* Size is greater than 1 */
4470                                 
4471                                 if(sign) {
4472                                         int lp1 = lit+1;
4473                                         
4474                                         size--;
4475                                         
4476                                         if(lp1 == 0) {
4477                                                 /* this means lit = 0xffffffff, or -1 */
4478                                                 
4479                                                 
4480                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4481                                                 rFalseIfx.condition ^= 1;
4482                                                 genSkipCond(&rFalseIfx,right,size,7);
4483                                                 if(ifx) ifx->generated = 1;
4484                                                 return;
4485                                         }
4486                                         
4487                                         if(lit == 0) {
4488                                                 int s = size;
4489                                                 
4490                                                 if(rFalseIfx.condition) {
4491                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4492                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4493                                                 }
4494                                                 
4495                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4496                                                 while(size--)
4497                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4498                                                 
4499                                                 
4500                                                 emitSKPZ;
4501                                                 if(rFalseIfx.condition) {
4502                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4503                                                         emitpLabel(truelbl->key);
4504                                                 }else {
4505                                                         rFalseIfx.condition ^= 1;
4506                                                         genSkipCond(&rFalseIfx,right,s,7);
4507                                                 }
4508                                                 
4509                                                 if(ifx) ifx->generated = 1;
4510                                                 return;
4511                                         }
4512                                         
4513                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4514                                                 /* lower byte of signed word is zero */
4515                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4516                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4517                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4518                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4519                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4520                                                 rFalseIfx.condition ^= 1;
4521                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4522                                                 
4523                                                 
4524                                                 if(ifx) ifx->generated = 1;
4525                                                 return;
4526                                         }
4527                                         
4528                                         if(lit & (0x80 << (size*8))) {
4529                                                 /* Lit is less than zero */
4530                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4531                                                 //rFalseIfx.condition ^= 1;
4532                                                 //genSkipCond(&rFalseIfx,left,size,7);
4533                                                 //rFalseIfx.condition ^= 1;
4534                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4535                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4536                                                 
4537                                                 if(rFalseIfx.condition)
4538                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4539                                                 else
4540                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4541                                                 
4542                                                 
4543                                         } else {
4544                                                 /* Lit is greater than or equal to zero */
4545                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4546                                                 //rFalseIfx.condition ^= 1;
4547                                                 //genSkipCond(&rFalseIfx,right,size,7);
4548                                                 //rFalseIfx.condition ^= 1;
4549                                                 
4550                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4551                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4552                                                 
4553                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4554                                                 if(rFalseIfx.condition)
4555                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4556                                                 else
4557                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4558                                                 
4559                                         }
4560                                         
4561                                         
4562                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4563                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4564                                         
4565                                         while(size--) {
4566                                                 
4567                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4568                                                 emitSKPNZ;
4569                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4570                                         }
4571                                         rFalseIfx.condition ^= 1;
4572                                         //rFalseIfx.condition = 1;
4573                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4574                                         
4575                                         emitpLabel(truelbl->key);
4576                                         
4577                                         if(ifx) ifx->generated = 1;
4578                                         return;
4579                                         // end of if (sign)
4580                                 } else {
4581                                         
4582                                         /* compare word or long to an unsigned literal on the right.*/
4583                                         
4584                                         
4585                                         size--;
4586                                         if(lit < 0xff) {
4587                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4588                                                 switch (lit) {
4589                                                 case 0:
4590                                                         break; /* handled above */
4591                                                 /*
4592                                                 case 0xff:
4593                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4594                                                         while(size--)
4595                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4596                                                         genSkipz2(&rFalseIfx,0);
4597                                                         break;
4598                                                 */
4599                                                 default:
4600                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4601                                                         while(--size)
4602                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4603                                                         
4604                                                         emitSKPZ;
4605                                                         if(rFalseIfx.condition)
4606                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4607                                                         else
4608                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4609                                                         
4610                                                         
4611                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4612                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4613                                                         
4614                                                         rFalseIfx.condition ^= 1;
4615                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4616                                                 }
4617                                                 
4618                                                 emitpLabel(truelbl->key);
4619                                                 
4620                                                 if(ifx) ifx->generated = 1;
4621                                                 return;
4622                                         }
4623                                         
4624                                         
4625                                         lit++;
4626                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4627                                         i = (lit >> (size*8)) & 0xff;
4628                                         
4629                                         emitpcode(POC_MOVLW, popGetLit(i));
4630                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4631                                         
4632                                         while(size--) {
4633                                                 i = (lit >> (size*8)) & 0xff;
4634                                                 
4635                                                 if(i) {
4636                                                         emitpcode(POC_MOVLW, popGetLit(i));
4637                                                         emitSKPNZ;
4638                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4639                                                 } else {
4640                                                 /* this byte of the lit is zero, 
4641                                                         *if it's not the last then OR in the variable */
4642                                                         if(size)
4643                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4644                                                 }
4645                                         }
4646                                         
4647                                         
4648                                         emitpLabel(lbl->key);
4649                                         
4650                                         rFalseIfx.condition ^= 1;
4651                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4652                                 }
4653                                 
4654                                 if(sign)
4655                                         emitpLabel(truelbl->key);
4656                                 if(ifx) ifx->generated = 1;
4657                                 return;
4658                         }
4659                 }
4660                 /* Compare two variables */
4661                 
4662                 DEBUGpic14_emitcode(";sign","%d",sign);
4663                 
4664                 size--;
4665                 if(sign) {
4666                         /* Sigh. thus sucks... */
4667                         if(size) {
4668                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4669                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4670                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4671                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4672                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4673                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4674                         } else {
4675                                 /* Signed char comparison */
4676                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4677                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4678                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4679                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4680                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4681                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4682                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4683                                 
4684                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4685                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4686                                 
4687                                 if(ifx) ifx->generated = 1;
4688                                 return;
4689                         }
4690                         
4691                 } else {
4692                         
4693                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4694                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4695                 }
4696                 
4697                 
4698                 /* The rest of the bytes of a multi-byte compare */
4699                 while (size) {
4700                         
4701                         emitSKPZ;
4702                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4703                         size--;
4704                         
4705                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4706                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4707                         
4708                         
4709                 }
4710                 
4711                 emitpLabel(lbl->key);
4712                 
4713                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4714                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4715                         (AOP_TYPE(result) == AOP_REG)) {
4716                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4717                         emitpcode(POC_RLF, popGet(AOP(result),0));
4718                 } else {
4719                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4720                 }       
4721                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4722                 if(ifx) ifx->generated = 1;
4723                 
4724                 return;
4725                 
4726         }
4727         
4728         // check_carry:
4729         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4730                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4731                 pic14_outBitC(result);
4732         } else {
4733                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4734                 /* if the result is used in the next
4735                 ifx conditional branch then generate
4736                 code a little differently */
4737                 if (ifx )
4738                         genIfxJump (ifx,"c");
4739                 else
4740                         pic14_outBitC(result);
4741                 /* leave the result in acc */
4742         }
4743         
4744 }
4745 #endif
4746
4747 /*-----------------------------------------------------------------*/
4748 /* genCmpGt :- greater than comparison                             */
4749 /*-----------------------------------------------------------------*/
4750 static void genCmpGt (iCode *ic, iCode *ifx)
4751 {
4752         operand *left, *right, *result;
4753         sym_link *letype , *retype;
4754         int sign ;
4755         
4756         FENTRY;
4757         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4758         left = IC_LEFT(ic);
4759         right= IC_RIGHT(ic);
4760         result = IC_RESULT(ic);
4761         
4762         letype = getSpec(operandType(left));
4763         retype =getSpec(operandType(right));
4764         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4765         /* assign the amsops */
4766         aopOp (left,ic,FALSE);
4767         aopOp (right,ic,FALSE);
4768         aopOp (result,ic,TRUE);
4769         
4770         genCmp(right, left, result, ifx, sign);
4771         
4772         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774         freeAsmop(result,NULL,ic,TRUE); 
4775 }
4776
4777 /*-----------------------------------------------------------------*/
4778 /* genCmpLt - less than comparisons                                */
4779 /*-----------------------------------------------------------------*/
4780 static void genCmpLt (iCode *ic, iCode *ifx)
4781 {
4782         operand *left, *right, *result;
4783         sym_link *letype , *retype;
4784         int sign ;
4785         
4786         FENTRY;
4787         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4788         left = IC_LEFT(ic);
4789         right= IC_RIGHT(ic);
4790         result = IC_RESULT(ic);
4791         
4792         letype = getSpec(operandType(left));
4793         retype =getSpec(operandType(right));
4794         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4795         
4796         /* assign the amsops */
4797         aopOp (left,ic,FALSE);
4798         aopOp (right,ic,FALSE);
4799         aopOp (result,ic,TRUE);
4800         
4801         genCmp(left, right, result, ifx, sign);
4802         
4803         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4805         freeAsmop(result,NULL,ic,TRUE); 
4806 }
4807
4808 #if 0
4809 /*-----------------------------------------------------------------*/
4810 /* genc16bit2lit - compare a 16 bit value to a literal             */
4811 /*-----------------------------------------------------------------*/
4812 static void genc16bit2lit(operand *op, int lit, int offset)
4813 {
4814         int i;
4815         
4816         FENTRY;
4817         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4818         if( (lit&0xff) == 0) 
4819                 i=1;
4820         else
4821                 i=0;
4822         
4823         switch( BYTEofLONG(lit,i)) { 
4824         case 0:
4825                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4826                 break;
4827         case 1:
4828                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4829                 break;
4830         case 0xff:
4831                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4832                 break;
4833         default:
4834                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4835                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4836         }
4837         
4838         i ^= 1;
4839         
4840         switch( BYTEofLONG(lit,i)) { 
4841         case 0:
4842                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4843                 break;
4844         case 1:
4845                 emitSKPNZ;
4846                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4847                 break;
4848         case 0xff:
4849                 emitSKPNZ;
4850                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4851                 break;
4852         default:
4853                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4854                 emitSKPNZ;
4855                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4856                 
4857         }
4858         
4859 }
4860 #endif
4861
4862 #if 0
4863 /*-----------------------------------------------------------------*/
4864 /* gencjneshort - compare and jump if not equal                    */
4865 /*-----------------------------------------------------------------*/
4866 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4867 {
4868         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4869         int offset = 0;
4870         //resolvedIfx rIfx;
4871         symbol *lbl;
4872         
4873         //unsigned long lit = 0L;
4874         FENTRY;
4875         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4876           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4877           return;
4878         }
4879         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4880         DEBUGpic14_AopType(__LINE__,left,right,result);
4881         
4882         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4883         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4884         if (AOP_SIZE(result)) {
4885           for (offset = 0; offset < AOP_SIZE(result); offset++)
4886             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4887         }
4888         
4889         assert (AOP_SIZE(left) == AOP_SIZE(right));
4890         //resolveIfx(&rIfx,ifx);
4891         lbl = newiTempLabel (NULL);
4892         while (size--)
4893         {
4894           mov2w (AOP(right),size);
4895           emitpcode (POC_XORFW, popGet (AOP(left), size));
4896           if (size)
4897           {
4898             emitSKPZ;
4899             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4900           }
4901         } // while
4902         emitpLabel (lbl->key);
4903         if (AOP_SIZE(result)) {
4904           emitSKPNZ;
4905           emitpcode (POC_INCF, popGet (AOP(result), 0));
4906         } else {
4907           assert (ifx);
4908           genSkipz (ifx, NULL != IC_TRUE(ifx));
4909           ifx->generated = 1;
4910         }
4911         return;
4912 #if 0   
4913         if(result)
4914         {
4915                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4916                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4917                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4918                 for (offset=0; offset < AOP_SIZE(result); offset++)
4919                 {
4920                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4921                 } // for offset
4922         }
4923         
4924         
4925         /* if the left side is a literal or 
4926         if the right is in a pointer register and left 
4927         is not */
4928         if ((AOP_TYPE(left) == AOP_LIT) || 
4929                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4930                 operand *t = right;
4931                 right = left;
4932                 left = t;
4933         }
4934         if(AOP_TYPE(right) == AOP_LIT)
4935                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4936         
4937         /* if the right side is a literal then anything goes */
4938         if (AOP_TYPE(right) == AOP_LIT &&
4939                 AOP_TYPE(left) != AOP_DIR ) {
4940                 switch(size) {
4941                 case 2:
4942                         genc16bit2lit(left, lit, 0);
4943                         emitSKPNZ;
4944                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4945                         break;
4946                 default:
4947                         offset = 0;
4948                         while (size--) {
4949                                 if(lit & 0xff) {
4950                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4951                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4952                                 } else {
4953                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4954                                 }
4955                                 
4956                                 emitSKPNZ;
4957                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4958                                 offset++;
4959                                 lit >>= 8;
4960                         }
4961                         break;
4962                 }
4963         }
4964         
4965         /* if the right side is in a register or in direct space or
4966         if the left is a pointer register & right is not */    
4967         else if (AOP_TYPE(right) == AOP_REG ||
4968                 AOP_TYPE(right) == AOP_DIR || 
4969                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4970                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4971                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4972                 int lbl_key = lbl->key;
4973                 
4974                 if(!result) {
4975                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4976                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4977                                 __FUNCTION__,__LINE__);
4978                         return;
4979                 }
4980                 
4981                 /*     switch(size) { */
4982                 /*     case 2: */
4983                 /*       genc16bit2lit(left, lit, 0); */
4984                 /*       emitSKPNZ; */
4985                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4986                 /*       break; */
4987                 /*     default: */
4988                 offset = 0;
4989                 while (size--) {
4990                         int emit_skip=1;
4991                         if((AOP_TYPE(left) == AOP_DIR) && 
4992                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4993                                 
4994                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4995                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4996                                 
4997                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4998                                 
4999                                 switch (lit & 0xff) {
5000                                 case 0:
5001                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5002                                         break;
5003                                 case 1:
5004                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5005                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5006                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5007                                         emit_skip=0;
5008                                         break;
5009                                 case 0xff:
5010                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5011                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5012                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5013                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5014                                         emit_skip=0;
5015                                         break;
5016                                 default:
5017                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5018                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5019                                 }
5020                                 lit >>= 8;
5021                                 
5022                         } else {
5023                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5024                         }
5025                         if(emit_skip) {
5026                                 if(AOP_TYPE(result) == AOP_CRY) {
5027                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5028                                         if(rIfx.condition)
5029                                                 emitSKPNZ;
5030                                         else
5031                                                 emitSKPZ;
5032                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5033                                 } else {
5034                                         /* fix me. probably need to check result size too */
5035                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5036                                         if(rIfx.condition)
5037                                                 emitSKPZ;
5038                                         else
5039                                                 emitSKPNZ;
5040                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5041                                 }
5042                                 if(ifx)
5043                                         ifx->generated=1;
5044                         }
5045                         emit_skip++;
5046                         offset++;
5047                 }
5048                 /*       break; */
5049                 /*     } */
5050         } else if(AOP_TYPE(right) == AOP_REG &&
5051                 AOP_TYPE(left) != AOP_DIR){
5052
5053                 offset = 0;
5054                 while(size--) {
5055                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5056                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5057                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5058                         if(rIfx.condition)
5059                                 emitSKPNZ;
5060                         else
5061                                 emitSKPZ;
5062                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5063                         offset++;
5064                 }
5065                 
5066         }else{
5067                 /* right is a pointer reg need both a & b */
5068                 offset = 0;
5069                 while(size--) {
5070                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5071                         if(strcmp(l,"b"))
5072                                 pic14_emitcode("mov","b,%s",l);
5073                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5074                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5075                         offset++;
5076                 }
5077         }
5078         
5079         emitpcode(POC_INCF,popGet(AOP(result),0));
5080         if(!rIfx.condition)
5081                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5082         
5083         emitpLabel(lbl->key);
5084         
5085         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5086         
5087         if(ifx)
5088                 ifx->generated = 1;
5089 #endif
5090 }
5091 #endif
5092
5093 #if 0
5094 /*-----------------------------------------------------------------*/
5095 /* gencjne - compare and jump if not equal                         */
5096 /*-----------------------------------------------------------------*/
5097 static void gencjne(operand *left, operand *right, iCode *ifx)
5098 {
5099         symbol *tlbl  = newiTempLabel(NULL);
5100         
5101         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5102         gencjneshort(left, right, lbl);
5103         
5104         pic14_emitcode("mov","a,%s",one);
5105         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5106         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5107         pic14_emitcode("clr","a");
5108         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5109         
5110         emitpLabel(lbl->key);
5111         emitpLabel(tlbl->key);
5112         
5113 }
5114 #endif
5115
5116 /*-----------------------------------------------------------------*/
5117 /* genCmpEq - generates code for equal to                          */
5118 /*-----------------------------------------------------------------*/
5119 static void genCmpEq (iCode *ic, iCode *ifx)
5120 {
5121   operand *left, *right, *result;
5122   int size;
5123   symbol *false_label;
5124
5125   FENTRY;
5126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5127
5128   if(ifx)
5129     DEBUGpic14_emitcode ("; ifx is non-null","");
5130   else
5131     DEBUGpic14_emitcode ("; ifx is null","");
5132
5133   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5134   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5135   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5136
5137   DEBUGpic14_AopType(__LINE__,left,right,result);
5138
5139   /* if literal, move literal to right */ 
5140   if (op_isLitLike (IC_LEFT(ic))) {
5141     operand *tmp = right ;
5142     right = left;
5143     left = tmp;
5144   }
5145
5146   false_label = NULL;
5147   if (ifx && !IC_TRUE(ifx))
5148   {
5149     assert (IC_FALSE(ifx));
5150     false_label = IC_FALSE(ifx);
5151   }
5152
5153   size = min(AOP_SIZE(left),AOP_SIZE(right));
5154   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5155   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5156
5157   /* assume left != right */
5158   {
5159     int i;
5160     for (i=0; i < AOP_SIZE(result); i++)
5161     {
5162       emitpcode(POC_CLRF, popGet(AOP(result),i));
5163     }
5164   }
5165
5166   if (AOP_TYPE(right) == AOP_LIT)
5167   {
5168     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5169     int i;
5170     size = AOP_SIZE(left);
5171     assert(!op_isLitLike(left));
5172
5173     switch (lit)
5174     {
5175       case 0:
5176         mov2w(AOP(left), 0);
5177         for (i=1; i < size; i++)
5178           emitpcode(POC_IORFW,popGet(AOP(left),i));
5179         /* now Z is set iff `left == right' */
5180         emitSKPZ;
5181         if (!false_label) false_label = newiTempLabel(NULL);
5182         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5183         break;
5184
5185       default:
5186         for (i=0; i < size; i++)
5187         {
5188           mov2w(AOP(left),i);
5189           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5190           /* now Z is cleared if `left != right' */
5191           emitSKPZ;
5192           if (!false_label) false_label = newiTempLabel(NULL);
5193           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5194         } // for i
5195         break;
5196     } // switch (lit)
5197   }
5198   else
5199   {
5200     /* right is no literal */
5201     int i;
5202
5203     for (i=0; i < size; i++)
5204     {
5205       mov2w(AOP(right),i);
5206       emitpcode(POC_XORFW,popGet(AOP(left),i));
5207       /* now Z is cleared if `left != right' */
5208       emitSKPZ;
5209       if (!false_label) false_label = newiTempLabel(NULL);
5210       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5211     } // for i
5212   }
5213
5214   /* if we reach here, left == right */
5215
5216   if (AOP_SIZE(result) > 0)
5217   {
5218     emitpcode(POC_INCF, popGet(AOP(result),0));
5219   }
5220
5221   if (ifx && IC_TRUE(ifx))
5222   {
5223     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5224   }
5225
5226   if (false_label && (!ifx || IC_TRUE(ifx)))
5227     emitpLabel(false_label->key);
5228
5229   if (ifx) ifx->generated = 1;
5230
5231   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5232   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5233   freeAsmop(result,NULL,ic,TRUE);
5234 }
5235
5236 /*-----------------------------------------------------------------*/
5237 /* ifxForOp - returns the icode containing the ifx for operand     */
5238 /*-----------------------------------------------------------------*/
5239 static iCode *ifxForOp ( operand *op, iCode *ic )
5240 {
5241         FENTRY;
5242         /* if true symbol then needs to be assigned */
5243         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5244         if (IS_TRUE_SYMOP(op))
5245                 return NULL ;
5246         
5247         /* if this has register type condition and
5248         the next instruction is ifx with the same operand
5249         and live to of the operand is upto the ifx only then */
5250         if (ic->next &&
5251                 ic->next->op == IFX &&
5252                 IC_COND(ic->next)->key == op->key &&
5253                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5254                 return ic->next;
5255         
5256         if (ic->next &&
5257                 ic->next->op == IFX &&
5258                 IC_COND(ic->next)->key == op->key) {
5259                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5260                 return ic->next;
5261         }
5262         
5263         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5264         if (ic->next &&
5265                 ic->next->op == IFX)
5266                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5267         
5268         if (ic->next &&
5269                 ic->next->op == IFX &&
5270                 IC_COND(ic->next)->key == op->key) {
5271                 DEBUGpic14_emitcode ("; "," key is okay");
5272                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5273                         OP_SYMBOL(op)->liveTo,
5274                         ic->next->seq);
5275         }
5276         
5277         
5278         return NULL;
5279 }
5280 /*-----------------------------------------------------------------*/
5281 /* genAndOp - for && operation                                     */
5282 /*-----------------------------------------------------------------*/
5283 static void genAndOp (iCode *ic)
5284 {
5285         operand *left,*right, *result;
5286         /*     symbol *tlbl; */
5287         
5288         FENTRY;
5289         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5290         /* note here that && operations that are in an
5291         if statement are taken away by backPatchLabels
5292         only those used in arthmetic operations remain */
5293         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5294         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5295         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5296         
5297         DEBUGpic14_AopType(__LINE__,left,right,result);
5298         
5299         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5300         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5301         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5302         
5303         /* if both are bit variables */
5304         /*     if (AOP_TYPE(left) == AOP_CRY && */
5305         /*         AOP_TYPE(right) == AOP_CRY ) { */
5306         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5307         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5308         /*         pic14_outBitC(result); */
5309         /*     } else { */
5310         /*         tlbl = newiTempLabel(NULL); */
5311         /*         pic14_toBoolean(left);     */
5312         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5313         /*         pic14_toBoolean(right); */
5314         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5315         /*         pic14_outBitAcc(result); */
5316         /*     } */
5317         
5318         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5319         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5320         freeAsmop(result,NULL,ic,TRUE);
5321 }
5322
5323
5324 /*-----------------------------------------------------------------*/
5325 /* genOrOp - for || operation                                      */
5326 /*-----------------------------------------------------------------*/
5327 /*
5328 tsd pic port -
5329 modified this code, but it doesn't appear to ever get called
5330 */
5331
5332 static void genOrOp (iCode *ic)
5333 {
5334         operand *left,*right, *result;
5335         symbol *tlbl;
5336         int i;
5337         
5338         /* note here that || operations that are in an
5339         if statement are taken away by backPatchLabels
5340         only those used in arthmetic operations remain */
5341         FENTRY;
5342         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5343         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5344         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5345         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5346         
5347         DEBUGpic14_AopType(__LINE__,left,right,result);
5348
5349         for (i=0; i < AOP_SIZE(result); i++)
5350         {
5351                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5352         } // for i
5353
5354         tlbl = newiTempLabel(NULL);
5355         pic14_toBoolean(left);
5356         emitSKPZ;
5357         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5358         pic14_toBoolean(right);
5359         emitpLabel(tlbl->key);
5360         /* here Z is clear IFF `left || right' */
5361         emitSKPZ;
5362         emitpcode(POC_INCF, popGet(AOP(result), 0));
5363         
5364         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5365         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5366         freeAsmop(result,NULL,ic,TRUE);            
5367 }
5368
5369 /*-----------------------------------------------------------------*/
5370 /* isLiteralBit - test if lit == 2^n                               */
5371 /*-----------------------------------------------------------------*/
5372 static int isLiteralBit(unsigned long lit)
5373 {
5374         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5375                 0x100L,0x200L,0x400L,0x800L,
5376                 0x1000L,0x2000L,0x4000L,0x8000L,
5377                 0x10000L,0x20000L,0x40000L,0x80000L,
5378                 0x100000L,0x200000L,0x400000L,0x800000L,
5379                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5380                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5381         int idx;
5382         
5383         FENTRY;
5384         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5385         for(idx = 0; idx < 32; idx++)
5386                 if(lit == pw[idx])
5387                         return idx+1;
5388                 return 0;
5389 }
5390
5391 /*-----------------------------------------------------------------*/
5392 /* continueIfTrue -                                                */
5393 /*-----------------------------------------------------------------*/
5394 static void continueIfTrue (iCode *ic)
5395 {
5396         FENTRY;
5397         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5398         if(IC_TRUE(ic))
5399         {
5400                 // Why +100?!?
5401                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5402                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5403         }
5404         ic->generated = 1;
5405 }
5406
5407 /*-----------------------------------------------------------------*/
5408 /* jmpIfTrue -                                                     */
5409 /*-----------------------------------------------------------------*/
5410 static void jumpIfTrue (iCode *ic)
5411 {
5412         FENTRY;
5413         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5414         if(!IC_TRUE(ic))
5415         {
5416                 // Why +100?!?
5417                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5418                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5419         }
5420         ic->generated = 1;
5421 }
5422
5423 /*-----------------------------------------------------------------*/
5424 /* jmpTrueOrFalse -                                                */
5425 /*-----------------------------------------------------------------*/
5426 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5427 {
5428         FENTRY;
5429         // ugly but optimized by peephole
5430         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5431         if(IC_TRUE(ic)){
5432                 symbol *nlbl = newiTempLabel(NULL);
5433                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5434                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5435                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5436                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5437         }
5438         else{
5439                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5440                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5441         }
5442         ic->generated = 1;
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genAnd  - code for and                                          */
5447 /*-----------------------------------------------------------------*/
5448 static void genAnd (iCode *ic, iCode *ifx)
5449 {
5450         operand *left, *right, *result;
5451         int size, offset=0;  
5452         unsigned long lit = 0L;
5453         int bytelit = 0;
5454         resolvedIfx rIfx;
5455         
5456         FENTRY;
5457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5458         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5459         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5460         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5461         
5462         resolveIfx(&rIfx,ifx);
5463         
5464         /* if left is a literal & right is not then exchange them */
5465         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5466                 AOP_NEEDSACC(left)) {
5467                 operand *tmp = right ;
5468                 right = left;
5469                 left = tmp;
5470         }
5471         
5472         /* if result = right then exchange them */
5473         if(pic14_sameRegs(AOP(result),AOP(right))){
5474                 operand *tmp = right ;
5475                 right = left;
5476                 left = tmp;
5477         }
5478         
5479         /* if right is bit then exchange them */
5480         if (AOP_TYPE(right) == AOP_CRY &&
5481                 AOP_TYPE(left) != AOP_CRY){
5482                 operand *tmp = right ;
5483                 right = left;
5484                 left = tmp;
5485         }
5486         if(AOP_TYPE(right) == AOP_LIT)
5487                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5488         
5489         size = AOP_SIZE(result);
5490         
5491         DEBUGpic14_AopType(__LINE__,left,right,result);
5492         
5493         // if(bit & yy)
5494         // result = bit & yy;
5495         if (AOP_TYPE(left) == AOP_CRY){
5496                 // c = bit & literal;
5497                 if(AOP_TYPE(right) == AOP_LIT){
5498                         if(lit & 1) {
5499                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5500                                         // no change
5501                                         goto release;
5502                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5503                         } else {
5504                                 // bit(result) = 0;
5505                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5506                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5507                                         goto release;
5508                                 }
5509                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5510                                         jumpIfTrue(ifx);
5511                                         goto release;
5512                                 }
5513                                 pic14_emitcode("clr","c");
5514                         }
5515                 } else {
5516                         if (AOP_TYPE(right) == AOP_CRY){
5517                                 // c = bit & bit;
5518                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5519                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5520                         } else {
5521                                 // c = bit & val;
5522                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5523                                 // c = lsb
5524                                 pic14_emitcode("rrc","a");
5525                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5526                         }
5527                 }
5528                 // bit = c
5529                 // val = c
5530                 if(size)
5531                         pic14_outBitC(result);
5532                 // if(bit & ...)
5533                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5534                         genIfxJump(ifx, "c");           
5535                 goto release ;
5536         }
5537         
5538         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5539         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5540         if((AOP_TYPE(right) == AOP_LIT) &&
5541                 (AOP_TYPE(result) == AOP_CRY) &&
5542                 (AOP_TYPE(left) != AOP_CRY)){
5543                 int posbit = isLiteralBit(lit);
5544                 /* left &  2^n */
5545                 if(posbit){
5546                         posbit--;
5547                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5548                         // bit = left & 2^n
5549                         if(size)
5550                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5551                         // if(left &  2^n)
5552                         else{
5553                                 if(ifx){
5554                                         int offset = 0;
5555                                         while (posbit > 7) {
5556                                                 posbit -= 8;
5557                                                 offset++;
5558                                         }
5559                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5560                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5561                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5562                                         
5563                                         ifx->generated = 1;
5564                                 }
5565                                 goto release;
5566                         }
5567                 } else {
5568                         symbol *tlbl = newiTempLabel(NULL);
5569                         int sizel = AOP_SIZE(left);
5570                         if(size)
5571                                 pic14_emitcode("setb","c");
5572                         while(sizel--){
5573                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5574                                         mov2w( AOP(left), offset);
5575                                         // byte ==  2^n ?
5576                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5577                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5578                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5579                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5580                                         }
5581                                         else{
5582                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5583                                                 if (rIfx.condition) emitSKPZ;
5584                                                 else emitSKPNZ;
5585                                                 
5586                                                 if(bytelit != 0x0FFL)
5587                                                 {
5588                                                         pic14_emitcode("anl","a,%s",
5589                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5590                                                 }
5591                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5592                                         }
5593
5594                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5595                                         ifx->generated = 1;
5596                                                 
5597                                 }
5598                                 offset++;
5599                         }
5600                         // bit = left & literal
5601                         if(size){
5602                                 pic14_emitcode("clr","c");
5603                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5604                         }
5605                         // if(left & literal)
5606                         else{
5607                                 if(ifx)
5608                                         jmpTrueOrFalse(ifx, tlbl);
5609                                 goto release ;
5610                         }
5611                 }
5612                 pic14_outBitC(result);
5613                 goto release ;
5614         }
5615         
5616         /* if left is same as result */
5617         if(pic14_sameRegs(AOP(result),AOP(left))){
5618                 int know_W = -1;
5619                 for(;size--; offset++,lit>>=8) {
5620                         if(AOP_TYPE(right) == AOP_LIT){
5621                                 switch(lit & 0xff) {
5622                                 case 0x00:
5623                                         /*  and'ing with 0 has clears the result */
5624                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5625                                         break;
5626                                 case 0xff:
5627                                         /* and'ing with 0xff is a nop when the result and left are the same */
5628                                         break;
5629                                         
5630                                 default:
5631                                         {
5632                                                 int p = my_powof2( (~lit) & 0xff );
5633                                                 if(p>=0) {
5634                                                         /* only one bit is set in the literal, so use a bcf instruction */
5635                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5636                                                         
5637                                                 } else {
5638                                                         if(know_W != (int)(lit&0xff))
5639                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5640                                                         know_W = lit &0xff;
5641                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5642                                                 }
5643                                         }    
5644                                 }
5645                         } else {
5646                                 if (AOP_TYPE(left) == AOP_ACC) {
5647                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5648                                 } else {        
5649                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5650                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5651                                         
5652                                 }
5653                         }
5654                 }
5655                 
5656         } else {
5657                 // left & result in different registers
5658                 if(AOP_TYPE(result) == AOP_CRY){
5659                         // result = bit
5660                         // if(size), result in bit
5661                         // if(!size && ifx), conditional oper: if(left & right)
5662                         symbol *tlbl = newiTempLabel(NULL);
5663                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5664                         if(size)
5665                                 pic14_emitcode("setb","c");
5666                         while(sizer--){
5667                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5668                                 pic14_emitcode("anl","a,%s",
5669                                         aopGet(AOP(left),offset,FALSE,FALSE));
5670                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5671                                 offset++;
5672                         }
5673                         if(size){
5674                                 CLRC;
5675                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5676                                 pic14_outBitC(result);
5677                         } else if(ifx)
5678                                 jmpTrueOrFalse(ifx, tlbl);
5679                 } else {
5680                         for(;(size--);offset++) {
5681                                 // normal case
5682                                 // result = left & right
5683                                 if(AOP_TYPE(right) == AOP_LIT){
5684                                         int t = (lit >> (offset*8)) & 0x0FFL;
5685                                         switch(t) { 
5686                                         case 0x00:
5687                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5688                                                 break;
5689                                         case 0xff:
5690                                                 if(AOP_TYPE(left) != AOP_ACC) {
5691                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5692                                                 }
5693                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5694                                                 break;
5695                                         default:
5696                                                 if(AOP_TYPE(left) == AOP_ACC) {
5697                                                         emitpcode(POC_ANDLW, popGetLit(t));
5698                                                 } else {
5699                                                         emitpcode(POC_MOVLW, popGetLit(t));
5700                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5701                                                 }
5702                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5703                                         }
5704                                         continue;
5705                                 }
5706                                 
5707                                 if (AOP_TYPE(left) == AOP_ACC) {
5708                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5709                                 } else {
5710                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5711                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5712                                 }
5713                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5714                         }
5715                 }
5716         }
5717         
5718 release :
5719         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721         freeAsmop(result,NULL,ic,TRUE);     
5722 }
5723
5724 /*-----------------------------------------------------------------*/
5725 /* genOr  - code for or                                            */
5726 /*-----------------------------------------------------------------*/
5727 static void genOr (iCode *ic, iCode *ifx)
5728 {
5729         operand *left, *right, *result;
5730         int size, offset=0;
5731         unsigned long lit = 0L;
5732         
5733         FENTRY;
5734         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5735         
5736         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5737         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5738         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5739         
5740         DEBUGpic14_AopType(__LINE__,left,right,result);
5741         
5742         /* if left is a literal & right is not then exchange them */
5743         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5744                 AOP_NEEDSACC(left)) {
5745                 operand *tmp = right ;
5746                 right = left;
5747                 left = tmp;
5748         }
5749         
5750         /* if result = right then exchange them */
5751         if(pic14_sameRegs(AOP(result),AOP(right))){
5752                 operand *tmp = right ;
5753                 right = left;
5754                 left = tmp;
5755         }
5756         
5757         /* if right is bit then exchange them */
5758         if (AOP_TYPE(right) == AOP_CRY &&
5759                 AOP_TYPE(left) != AOP_CRY){
5760                 operand *tmp = right ;
5761                 right = left;
5762                 left = tmp;
5763         }
5764         
5765         DEBUGpic14_AopType(__LINE__,left,right,result);
5766         
5767         if(AOP_TYPE(right) == AOP_LIT)
5768                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5769         
5770         size = AOP_SIZE(result);
5771         
5772         // if(bit | yy)
5773         // xx = bit | yy;
5774         if (AOP_TYPE(left) == AOP_CRY){
5775                 if(AOP_TYPE(right) == AOP_LIT){
5776                         // c = bit & literal;
5777                         if(lit){
5778                                 // lit != 0 => result = 1
5779                                 if(AOP_TYPE(result) == AOP_CRY){
5780                                         if(size)
5781                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5782                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5783                                         //   AOP(result)->aopu.aop_dir,
5784                                         //   AOP(result)->aopu.aop_dir);
5785                                         else if(ifx)
5786                                                 continueIfTrue(ifx);
5787                                         goto release;
5788                                 }
5789                         } else {
5790                                 // lit == 0 => result = left
5791                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5792                                         goto release;
5793                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5794                         }
5795                 } else {
5796                         if (AOP_TYPE(right) == AOP_CRY){
5797                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5798                                         // c = bit | bit;
5799                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5800                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5801                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5802                                         
5803                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5804                                                 AOP(result)->aopu.aop_dir,
5805                                                 AOP(result)->aopu.aop_dir);
5806                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5807                                                 AOP(right)->aopu.aop_dir,
5808                                                 AOP(right)->aopu.aop_dir);
5809                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5810                                                 AOP(result)->aopu.aop_dir,
5811                                                 AOP(result)->aopu.aop_dir);
5812                                 } else {
5813                                         if( AOP_TYPE(result) == AOP_ACC) {
5814                                                 emitpcode(POC_MOVLW, popGetLit(0));
5815                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5816                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5817                                                 emitpcode(POC_MOVLW, popGetLit(1));
5818                                                 
5819                                         } else {
5820                                                 
5821                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5822                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5823                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5824                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5825                                                 
5826                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5827                                                         AOP(result)->aopu.aop_dir,
5828                                                         AOP(result)->aopu.aop_dir);
5829                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5830                                                         AOP(right)->aopu.aop_dir,
5831                                                         AOP(right)->aopu.aop_dir);
5832                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5833                                                         AOP(left)->aopu.aop_dir,
5834                                                         AOP(left)->aopu.aop_dir);
5835                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5836                                                         AOP(result)->aopu.aop_dir,
5837                                                         AOP(result)->aopu.aop_dir);
5838                                         }
5839                                 }
5840                         } else {
5841                                 // c = bit | val;
5842                                 symbol *tlbl = newiTempLabel(NULL);
5843                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5844                                 
5845                                 
5846                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5847                                 if( AOP_TYPE(right) == AOP_ACC) {
5848                                         emitpcode(POC_IORLW, popGetLit(0));
5849                                         emitSKPNZ;
5850                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5851                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5852                                 }
5853                                 
5854                                 
5855                                 
5856                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5857                                         pic14_emitcode(";XXX setb","c");
5858                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5859                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5860                                 pic14_toBoolean(right);
5861                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5862                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5863                                         jmpTrueOrFalse(ifx, tlbl);
5864                                         goto release;
5865                                 } else {
5866                                         CLRC;
5867                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5868                                 }
5869                         }
5870                 }
5871                 // bit = c
5872                 // val = c
5873                 if(size)
5874                         pic14_outBitC(result);
5875                 // if(bit | ...)
5876                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5877                         genIfxJump(ifx, "c");           
5878                 goto release ;
5879         }
5880
5881         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5882         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5883         if((AOP_TYPE(right) == AOP_LIT) &&
5884           (AOP_TYPE(result) == AOP_CRY) &&
5885           (AOP_TYPE(left) != AOP_CRY)){
5886                 if(lit){
5887                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5888                         // result = 1
5889                         if(size)
5890                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5891                         else 
5892                                 continueIfTrue(ifx);
5893                         goto release;
5894                 } else {
5895                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5896                         // lit = 0, result = boolean(left)
5897                         if(size)
5898                                 pic14_emitcode(";XXX setb","c");
5899                         pic14_toBoolean(right);
5900                         if(size){
5901                                 symbol *tlbl = newiTempLabel(NULL);
5902                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5903                                 CLRC;
5904                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5905                         } else {
5906                                 genIfxJump (ifx,"a");
5907                                 goto release;
5908                         }
5909                 }
5910                 pic14_outBitC(result);
5911                 goto release ;
5912         }
5913
5914         /* if left is same as result */
5915         if(pic14_sameRegs(AOP(result),AOP(left))){
5916                 int know_W = -1;
5917                 for(;size--; offset++,lit>>=8) {
5918                         if(AOP_TYPE(right) == AOP_LIT){
5919                                 if((lit & 0xff) == 0)
5920                                         /*  or'ing with 0 has no effect */
5921                                         continue;
5922                                 else {
5923                                         int p = my_powof2(lit & 0xff);
5924                                         if(p>=0) {
5925                                                 /* only one bit is set in the literal, so use a bsf instruction */
5926                                                 emitpcode(POC_BSF,
5927                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5928                                         } else {
5929                                                 if(know_W != (int)(lit & 0xff))
5930                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5931                                                 know_W = lit & 0xff;
5932                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5933                                         }
5934                                         
5935                                 }
5936                         } else {
5937                                 if (AOP_TYPE(left) == AOP_ACC) {
5938                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5939                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5940                                 } else {        
5941                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5942                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5943                                         
5944                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5945                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5946                                         
5947                                 }
5948                         }
5949                 }
5950         } else {
5951                 // left & result in different registers
5952                 if(AOP_TYPE(result) == AOP_CRY){
5953                         // result = bit
5954                         // if(size), result in bit
5955                         // if(!size && ifx), conditional oper: if(left | right)
5956                         symbol *tlbl = newiTempLabel(NULL);
5957                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5958                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5959                         
5960                         
5961                         if(size)
5962                                 pic14_emitcode(";XXX setb","c");
5963                         while(sizer--){
5964                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5965                                 pic14_emitcode(";XXX orl","a,%s",
5966                                         aopGet(AOP(left),offset,FALSE,FALSE));
5967                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5968                                 offset++;
5969                         }
5970                         if(size){
5971                                 CLRC;
5972                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5973                                 pic14_outBitC(result);
5974                         } else if(ifx)
5975                                 jmpTrueOrFalse(ifx, tlbl);
5976                 } else for(;(size--);offset++){
5977                         // normal case
5978                         // result = left | right
5979                         if(AOP_TYPE(right) == AOP_LIT){
5980                                 int t = (lit >> (offset*8)) & 0x0FFL;
5981                                 switch(t) { 
5982                                 case 0x00:
5983                                         if (AOP_TYPE(left) != AOP_ACC) {
5984                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5985                                         }
5986                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5987                                         
5988                                         break;
5989                                 default:
5990                                         if (AOP_TYPE(left) == AOP_ACC) {
5991                                                 emitpcode(POC_IORLW,  popGetLit(t));
5992                                         } else {
5993                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5994                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5995                                         }
5996                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5997                                 }
5998                                 continue;
5999                         }
6000                         
6001                         // faster than result <- left, anl result,right
6002                         // and better if result is SFR
6003                         if (AOP_TYPE(left) == AOP_ACC) {
6004                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6005                         } else {
6006                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6007                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6008                         }
6009                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6010                 }
6011         }
6012
6013 release :
6014         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6015         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6016         freeAsmop(result,NULL,ic,TRUE);     
6017 }
6018
6019 /*-----------------------------------------------------------------*/
6020 /* genXor - code for xclusive or                                   */
6021 /*-----------------------------------------------------------------*/
6022 static void genXor (iCode *ic, iCode *ifx)
6023 {
6024         operand *left, *right, *result;
6025         int size, offset=0;
6026         unsigned long lit = 0L;
6027         
6028         FENTRY;
6029         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6030         
6031         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6032         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6033         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6034         
6035         /* if left is a literal & right is not ||
6036         if left needs acc & right does not */
6037         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6038                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6039                 operand *tmp = right ;
6040                 right = left;
6041                 left = tmp;
6042         }
6043         
6044         /* if result = right then exchange them */
6045         if(pic14_sameRegs(AOP(result),AOP(right))){
6046                 operand *tmp = right ;
6047                 right = left;
6048                 left = tmp;
6049         }
6050         
6051         /* if right is bit then exchange them */
6052         if (AOP_TYPE(right) == AOP_CRY &&
6053                 AOP_TYPE(left) != AOP_CRY){
6054                 operand *tmp = right ;
6055                 right = left;
6056                 left = tmp;
6057         }
6058         if(AOP_TYPE(right) == AOP_LIT)
6059                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6060         
6061         size = AOP_SIZE(result);
6062         
6063         // if(bit ^ yy)
6064         // xx = bit ^ yy;
6065         if (AOP_TYPE(left) == AOP_CRY){
6066                 if(AOP_TYPE(right) == AOP_LIT){
6067                         // c = bit & literal;
6068                         if(lit>>1){
6069                                 // lit>>1  != 0 => result = 1
6070                                 if(AOP_TYPE(result) == AOP_CRY){
6071                                         if(size)
6072                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6073                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6074                                         else if(ifx)
6075                                                 continueIfTrue(ifx);
6076                                         goto release;
6077                                 }
6078                                 pic14_emitcode("setb","c");
6079                         } else{
6080                                 // lit == (0 or 1)
6081                                 if(lit == 0){
6082                                         // lit == 0, result = left
6083                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6084                                                 goto release;
6085                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6086                                 } else{
6087                                         // lit == 1, result = not(left)
6088                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6089                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6090                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6091                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6092                                                 goto release;
6093                                         } else {
6094                                                 assert ( !"incomplete genXor" );
6095                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6096                                                 pic14_emitcode("cpl","c");
6097                                         }
6098                                 }
6099                         }
6100                         
6101                 } else {
6102                         // right != literal
6103                         symbol *tlbl = newiTempLabel(NULL);
6104                         if (AOP_TYPE(right) == AOP_CRY){
6105                                 // c = bit ^ bit;
6106                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6107                         }
6108                         else{
6109                                 int sizer = AOP_SIZE(right);
6110                                 // c = bit ^ val
6111                                 // if val>>1 != 0, result = 1
6112                                 pic14_emitcode("setb","c");
6113                                 while(sizer){
6114                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6115                                         if(sizer == 1)
6116                                                 // test the msb of the lsb
6117                                                 pic14_emitcode("anl","a,#0xfe");
6118                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6119                                         sizer--;
6120                                 }
6121                                 // val = (0,1)
6122                                 pic14_emitcode("rrc","a");
6123                         }
6124                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6125                         pic14_emitcode("cpl","c");
6126                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6127                 }
6128                 // bit = c
6129                 // val = c
6130                 if(size)
6131                         pic14_outBitC(result);
6132                 // if(bit | ...)
6133                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6134                         genIfxJump(ifx, "c");           
6135                 goto release ;
6136         }
6137         
6138         if(pic14_sameRegs(AOP(result),AOP(left))){
6139                 /* if left is same as result */
6140                 for(;size--; offset++) {
6141                         if(AOP_TYPE(right) == AOP_LIT){
6142                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6143                                 if(t == 0x00L)
6144                                         continue;
6145                                 else
6146                                         if (IS_AOP_PREG(left)) {
6147                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6148                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6149                                                 aopPut(AOP(result),"a",offset);
6150                                         } else {
6151                                                 emitpcode(POC_MOVLW, popGetLit(t));
6152                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6153                                                 pic14_emitcode("xrl","%s,%s",
6154                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6155                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6156                                         }
6157                         } else {
6158                                 if (AOP_TYPE(left) == AOP_ACC)
6159                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6160                                 else {
6161                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6162                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6163                                         /*
6164                                         if (IS_AOP_PREG(left)) {
6165                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6166                                         aopPut(AOP(result),"a",offset);
6167                                         } else
6168                                         pic14_emitcode("xrl","%s,a",
6169                                         aopGet(AOP(left),offset,FALSE,TRUE));
6170                                         */
6171                                 }
6172                         }
6173                 }
6174         } else {
6175                 // left & result in different registers
6176                 if(AOP_TYPE(result) == AOP_CRY){
6177                         // result = bit
6178                         // if(size), result in bit
6179                         // if(!size && ifx), conditional oper: if(left ^ right)
6180                         symbol *tlbl = newiTempLabel(NULL);
6181                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6182                         if(size)
6183                                 pic14_emitcode("setb","c");
6184                         while(sizer--){
6185                                 if((AOP_TYPE(right) == AOP_LIT) &&
6186                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6187                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6188                                 } else {
6189                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6190                                         pic14_emitcode("xrl","a,%s",
6191                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6192                                 }
6193                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6194                                 offset++;
6195                         }
6196                         if(size){
6197                                 CLRC;
6198                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6199                                 pic14_outBitC(result);
6200                         } else if(ifx)
6201                                 jmpTrueOrFalse(ifx, tlbl);
6202                 } else for(;(size--);offset++){
6203                         // normal case
6204                         // result = left & right
6205                         if(AOP_TYPE(right) == AOP_LIT){
6206                                 int t = (lit >> (offset*8)) & 0x0FFL;
6207                                 switch(t) { 
6208                                 case 0x00:
6209                                         if (AOP_TYPE(left) != AOP_ACC) {
6210                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6211                                         }
6212                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6213                                         pic14_emitcode("movf","%s,w",
6214                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6215                                         pic14_emitcode("movwf","%s",
6216                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6217                                         break;
6218                                 case 0xff:
6219                                         if (AOP_TYPE(left) == AOP_ACC) {
6220                                                 emitpcode(POC_XORLW, popGetLit(t));
6221                                         } else {
6222                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6223                                         }
6224                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6225                                         break;
6226                                 default:
6227                                         if (AOP_TYPE(left) == AOP_ACC) {
6228                                                 emitpcode(POC_XORLW, popGetLit(t));
6229                                         } else {
6230                                                 emitpcode(POC_MOVLW, popGetLit(t));
6231                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6232                                         }
6233                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6234                                         pic14_emitcode("movlw","0x%x",t);
6235                                         pic14_emitcode("xorwf","%s,w",
6236                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6237                                         pic14_emitcode("movwf","%s",
6238                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6239                                         
6240                                 }
6241                                 continue;
6242                         }
6243                         
6244                         // faster than result <- left, anl result,right
6245                         // and better if result is SFR
6246                         if (AOP_TYPE(left) == AOP_ACC) {
6247                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6248                         } else {
6249                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6250                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6251                         }
6252                         if ( AOP_TYPE(result) != AOP_ACC){
6253                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6254                         }
6255                 }
6256         }
6257         
6258 release :
6259         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261         freeAsmop(result,NULL,ic,TRUE);     
6262 }
6263
6264 /*-----------------------------------------------------------------*/
6265 /* genInline - write the inline code out                           */
6266 /*-----------------------------------------------------------------*/
6267 static void genInline (iCode *ic)
6268 {
6269   char *buffer, *bp, *bp1;
6270
6271   FENTRY;
6272   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6273
6274   _G.inLine += (!options.asmpeep);
6275
6276   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6277   strcpy(buffer,IC_INLINE(ic));
6278
6279   /* emit each line as a code */
6280   while (*bp) {
6281     if (*bp == '\n') {
6282       *bp++ = '\0';
6283       
6284       if(*bp1)
6285         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6286       bp1 = bp;
6287     } else {
6288       if (*bp == ':') {
6289         bp++;
6290         *bp = '\0';
6291         bp++;
6292
6293         /* print label, use this special format with NULL directive
6294          * to denote that the argument should not be indented with tab */
6295         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6296
6297         bp1 = bp;
6298       } else
6299         bp++;
6300     }
6301   }
6302   if ((bp1 != bp) && *bp1)
6303     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6304
6305   Safe_free(buffer);
6306
6307   _G.inLine -= (!options.asmpeep);
6308 }
6309
6310 /*-----------------------------------------------------------------*/
6311 /* genRRC - rotate right with carry                                */
6312 /*-----------------------------------------------------------------*/
6313 static void genRRC (iCode *ic)
6314 {
6315         operand *left , *result ;
6316         int size, offset = 0, same;
6317         
6318         FENTRY;
6319         /* rotate right with carry */
6320         left = IC_LEFT(ic);
6321         result=IC_RESULT(ic);
6322         aopOp (left,ic,FALSE);
6323         aopOp (result,ic,FALSE);
6324         
6325         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6326         
6327         same = pic14_sameRegs(AOP(result),AOP(left));
6328         
6329         size = AOP_SIZE(result);    
6330         
6331         /* get the lsb and put it into the carry */
6332         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6333         
6334         offset = 0 ;
6335         
6336         while(size--) {
6337                 
6338                 if(same) {
6339                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6340                 } else {
6341                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6342                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6343                 }
6344                 
6345                 offset++;
6346         }
6347         
6348         freeAsmop(left,NULL,ic,TRUE);
6349         freeAsmop(result,NULL,ic,TRUE);
6350 }
6351
6352 /*-----------------------------------------------------------------*/
6353 /* genRLC - generate code for rotate left with carry               */
6354 /*-----------------------------------------------------------------*/
6355 static void genRLC (iCode *ic)
6356 {    
6357         operand *left , *result ;
6358         int size, offset = 0;
6359         int same;
6360         
6361         FENTRY;
6362         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363         /* rotate right with carry */
6364         left = IC_LEFT(ic);
6365         result=IC_RESULT(ic);
6366         aopOp (left,ic,FALSE);
6367         aopOp (result,ic,FALSE);
6368         
6369         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6370         
6371         same = pic14_sameRegs(AOP(result),AOP(left));
6372         
6373         /* move it to the result */
6374         size = AOP_SIZE(result);    
6375         
6376         /* get the msb and put it into the carry */
6377         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6378         
6379         offset = 0 ;
6380         
6381         while(size--) {
6382                 
6383                 if(same) {
6384                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6385                 } else {
6386                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6387                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6388                 }
6389                 
6390                 offset++;
6391         }
6392         
6393         
6394         freeAsmop(left,NULL,ic,TRUE);
6395         freeAsmop(result,NULL,ic,TRUE);
6396 }
6397
6398 /*-----------------------------------------------------------------*/
6399 /* genGetHbit - generates code get highest order bit               */
6400 /*-----------------------------------------------------------------*/
6401 static void genGetHbit (iCode *ic)
6402 {
6403         operand *left, *result;
6404         left = IC_LEFT(ic);
6405         result=IC_RESULT(ic);
6406         aopOp (left,ic,FALSE);
6407         aopOp (result,ic,FALSE);
6408         
6409         FENTRY;
6410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411         /* get the highest order byte into a */
6412         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6413         if(AOP_TYPE(result) == AOP_CRY){
6414                 pic14_emitcode("rlc","a");
6415                 pic14_outBitC(result);
6416         }
6417         else{
6418                 pic14_emitcode("rl","a");
6419                 pic14_emitcode("anl","a,#0x01");
6420                 pic14_outAcc(result);
6421         }
6422         
6423         
6424         freeAsmop(left,NULL,ic,TRUE);
6425         freeAsmop(result,NULL,ic,TRUE);
6426 }
6427
6428 /*-----------------------------------------------------------------*/
6429 /* AccLsh - shift left accumulator by known count                  */
6430 /* MARK: pic14 always rotates through CARRY!                       */
6431 /*-----------------------------------------------------------------*/
6432 static void AccLsh (pCodeOp *pcop,int shCount)
6433 {
6434         FENTRY;
6435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6436         shCount &= 0x0007;              // shCount : 0..7
6437         switch(shCount){
6438         case 0 :
6439                 return;
6440                 break;
6441         case 1 :
6442                 emitCLRC;
6443                 emitpcode(POC_RLF,pcop);
6444                 return;
6445                 break;
6446         case 2 :
6447                 emitpcode(POC_RLF,pcop);
6448                 emitpcode(POC_RLF,pcop);
6449                 break;
6450         case 3 :
6451                 emitpcode(POC_RLF,pcop);
6452                 emitpcode(POC_RLF,pcop);
6453                 emitpcode(POC_RLF,pcop);
6454                 break;
6455         case 4 :
6456                 emitpcode(POC_SWAPF,pcop);
6457                 break;
6458         case 5 :
6459                 emitpcode(POC_SWAPF,pcop);
6460                 emitpcode(POC_RLF,pcop);
6461                 break;
6462         case 6 :
6463                 emitpcode(POC_SWAPF,pcop);
6464                 emitpcode(POC_RLF,pcop);
6465                 emitpcode(POC_RLF,pcop);
6466                 break;
6467         case 7 :
6468                 emitpcode(POC_RRFW,pcop);
6469                 emitpcode(POC_RRF,pcop);
6470                 break;
6471         }
6472         /* clear invalid bits */
6473         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6474         emitpcode(POC_ANDWF, pcop);
6475 }
6476
6477 /*-----------------------------------------------------------------*/
6478 /* AccRsh - shift right accumulator by known count                 */
6479 /* MARK: pic14 always rotates through CARRY!                       */
6480 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6481 /*            1: mask out invalid bits (zero-extend)               */
6482 /*            2: sign-extend result (pretty slow)                  */
6483 /*-----------------------------------------------------------------*/
6484 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6485 {
6486         FENTRY;
6487         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6488         shCount &= 0x0007;              // shCount : 0..7
6489         switch(shCount){
6490         case 0 :
6491                 return;
6492                 break;
6493         case 1 :
6494                 /* load sign if needed */
6495                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6496                 else if (mask_mode == 1) emitCLRC;
6497                 emitpcode(POC_RRF,pcop);
6498                 return;
6499                 break;
6500         case 2 :
6501                 /* load sign if needed */
6502                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6503                 emitpcode(POC_RRF,pcop);
6504                 /* load sign if needed */
6505                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6506                 emitpcode(POC_RRF,pcop);
6507                 if (mask_mode == 2) return;
6508                 break;
6509         case 3 :
6510                 /* load sign if needed */
6511                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6512                 emitpcode(POC_RRF,pcop);
6513                 /* load sign if needed */
6514                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6515                 emitpcode(POC_RRF,pcop);
6516                 /* load sign if needed */
6517                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6518                 emitpcode(POC_RRF,pcop);
6519                 if (mask_mode == 2) return;
6520                 break;
6521         case 4 :
6522                 emitpcode(POC_SWAPF,pcop);
6523                 break;
6524         case 5 :
6525                 emitpcode(POC_SWAPF,pcop);
6526                 emitpcode(POC_RRF,pcop);
6527                 break;
6528         case 6 :
6529                 emitpcode(POC_SWAPF,pcop);
6530                 emitpcode(POC_RRF,pcop);
6531                 emitpcode(POC_RRF,pcop);
6532                 break;
6533         case 7 :
6534                 if (mask_mode == 2)
6535                 {
6536                         /* load sign */
6537                         emitpcode(POC_RLFW,pcop);
6538                         emitpcode(POC_CLRF,pcop);
6539                         emitSKPNC;
6540                         emitpcode(POC_COMF,pcop);
6541                         return;
6542                 } else {
6543                         emitpcode(POC_RLFW,pcop);
6544                         emitpcode(POC_RLF,pcop);
6545                 }
6546                 break;
6547         }
6548
6549         if (mask_mode == 0)
6550         {
6551                 /* leave invalid bits undefined */
6552                 return;
6553         }
6554         
6555         /* clear invalid bits -- zero-extend */
6556         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6557         emitpcode(POC_ANDWF, pcop);
6558
6559         if (mask_mode == 2) {
6560           /* sign-extend */
6561           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6562           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6563           emitpcode(POC_IORWF, pcop);
6564         }
6565 }
6566
6567 #if 0
6568 /*-----------------------------------------------------------------*/
6569 /* AccSRsh - signed right shift accumulator by known count                 */
6570 /*-----------------------------------------------------------------*/
6571 static void AccSRsh (int shCount)
6572 {
6573         symbol *tlbl ;
6574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6575         if(shCount != 0){
6576                 if(shCount == 1){
6577                         pic14_emitcode("mov","c,acc.7");
6578                         pic14_emitcode("rrc","a");
6579                 } else if(shCount == 2){
6580                         pic14_emitcode("mov","c,acc.7");
6581                         pic14_emitcode("rrc","a");
6582                         pic14_emitcode("mov","c,acc.7");
6583                         pic14_emitcode("rrc","a");
6584                 } else {
6585                         tlbl = newiTempLabel(NULL);
6586                         /* rotate right accumulator */
6587                         AccRol(8 - shCount);
6588                         /* and kill the higher order bits */
6589                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6590                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6591                         pic14_emitcode("orl","a,#0x%02x",
6592                                 (unsigned char)~SRMask[shCount]);
6593                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6594                 }
6595         }
6596 }
6597
6598 /*-----------------------------------------------------------------*/
6599 /* shiftR1Left2Result - shift right one byte from left to result   */
6600 /*-----------------------------------------------------------------*/
6601 static void shiftR1Left2ResultSigned (operand *left, int offl,
6602                                                                           operand *result, int offr,
6603                                                                           int shCount)
6604 {
6605         int same;
6606         
6607         FENTRY;
6608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6609         
6610         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6611         
6612         switch(shCount) {
6613         case 1:
6614                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6615                 if(same) 
6616                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6617                 else {
6618                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6619                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6620                 }
6621                 
6622                 break;
6623         case 2:
6624                 
6625                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6626                 if(same) 
6627                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6628                 else {
6629                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6630                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6631                 }
6632                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6633                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6634                 
6635                 break;
6636                 
6637         case 3:
6638                 if(same)
6639                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6640                 else {
6641                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6642                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6643                 }
6644                 
6645                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6646                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6647                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6648                 
6649                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6650                 emitpcode(POC_IORLW, popGetLit(0xe0));
6651                 
6652                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6653                 break;
6654                 
6655         case 4:
6656                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6657                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6658                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6659                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6660                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6661                 break;
6662         case 5:
6663                 if(same) {
6664                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6665                 } else {
6666                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6667                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6668                 }
6669                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6670                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6671                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6672                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6673                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6674                 break;
6675                 
6676         case 6:
6677                 if(same) {
6678                         emitpcode(POC_MOVLW, popGetLit(0x00));
6679                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6680                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6681                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6682                         emitpcode(POC_IORLW, popGetLit(0x01));
6683                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6684                 } else {
6685                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6686                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6687                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6688                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6689                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6690                 }
6691                 break;
6692                 
6693         case 7:
6694                 if(same) {
6695                         emitpcode(POC_MOVLW, popGetLit(0x00));
6696                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6697                         emitpcode(POC_MOVLW, popGetLit(0xff));
6698                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6699                 } else {
6700                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6701                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6702                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6703                 }
6704                 
6705         default:
6706                 break;
6707         }
6708 }
6709
6710 /*-----------------------------------------------------------------*/
6711 /* shiftR1Left2Result - shift right one byte from left to result   */
6712 /*-----------------------------------------------------------------*/
6713 static void shiftR1Left2Result (operand *left, int offl,
6714                                                                 operand *result, int offr,
6715                                                                 int shCount, int sign)
6716 {
6717         int same;
6718         
6719         FENTRY;
6720         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6721         
6722         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6723         
6724         /* Copy the msb into the carry if signed. */
6725         if(sign) {
6726                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6727                 return;
6728         }
6729         
6730         
6731         
6732         switch(shCount) {
6733         case 1:
6734                 emitCLRC;
6735                 if(same) 
6736                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6737                 else {
6738                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6739                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6740                 }
6741                 break;
6742         case 2:
6743                 emitCLRC;
6744                 if(same) {
6745                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6746                 } else {
6747                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6748                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749                 }
6750                 emitCLRC;
6751                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6752                 
6753                 break;
6754         case 3:
6755                 if(same)
6756                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6757                 else {
6758                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6759                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6760                 }
6761                 
6762                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6763                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6764                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6765                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6766                 break;
6767                 
6768         case 4:
6769                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6770                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6771                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6772                 break;
6773                 
6774         case 5:
6775                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6776                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6777                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6778                 emitCLRC;
6779                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6780                 
6781                 break;
6782         case 6:
6783                 
6784                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6785                 emitpcode(POC_ANDLW, popGetLit(0x80));
6786                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6787                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6788                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6789                 break;
6790                 
6791         case 7:
6792                 
6793                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6794                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6795                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6796                 
6797                 break;
6798                 
6799         default:
6800                 break;
6801         }
6802 }
6803
6804 /*-----------------------------------------------------------------*/
6805 /* shiftL1Left2Result - shift left one byte from left to result    */
6806 /*-----------------------------------------------------------------*/
6807 static void shiftL1Left2Result (operand *left, int offl,
6808                                                                 operand *result, int offr, int shCount)
6809 {
6810         int same;
6811         
6812         //    char *l;
6813         FENTRY;
6814         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6815         
6816         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6817         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6818         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6819         //    MOVA(l);
6820         /* shift left accumulator */
6821         //AccLsh(shCount); // don't comment out just yet...
6822         //    aopPut(AOP(result),"a",offr);
6823         
6824         switch(shCount) {
6825         case 1:
6826                 /* Shift left 1 bit position */
6827                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6828                 if(same) {
6829                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6830                 } else {
6831                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6832                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6833                 }
6834                 break;
6835         case 2:
6836                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6837                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6838                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6839                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6840                 break;
6841         case 3:
6842                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6843                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6844                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6845                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6846                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6847                 break;
6848         case 4:
6849                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6850                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6851                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6852                 break;
6853         case 5:
6854                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6855                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6856                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6857                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6858                 break;
6859         case 6:
6860                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6861                 emitpcode(POC_ANDLW, popGetLit(0x30));
6862                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6863                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6864                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6865                 break;
6866         case 7:
6867                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6868                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6869                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6870                 break;
6871                 
6872         default:
6873                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6874         }
6875         
6876 }
6877 #endif
6878
6879 /*-----------------------------------------------------------------*/
6880 /* movLeft2Result - move byte from left to result                  */
6881 /*-----------------------------------------------------------------*/
6882 static void movLeft2Result (operand *left, int offl,
6883                                                         operand *result, int offr)
6884 {
6885         char *l;
6886         FENTRY;
6887         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6888         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6889                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6890                 
6891                 if (*l == '@' && (IS_AOP_PREG(result))) {
6892                         pic14_emitcode("mov","a,%s",l);
6893                         aopPut(AOP(result),"a",offr);
6894                 } else {
6895                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6896                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6897                 }
6898         }
6899 }
6900
6901 /*-----------------------------------------------------------------*/
6902 /* shiftLeft_Left2ResultLit - shift left by known count            */
6903 /*-----------------------------------------------------------------*/
6904
6905 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6906 {
6907         int size, same, offr, i;
6908
6909         size = AOP_SIZE(left);
6910         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6911         
6912         same = pic14_sameRegs (AOP(left), AOP(result));
6913         
6914         offr = shCount / 8;
6915         shCount = shCount & 0x07;
6916
6917         size -= offr;
6918
6919         switch (shCount)
6920         {
6921         case 0: /* takes 0 or 2N cycles (for offr==0) */
6922                 if (!same || offr) {
6923                         for (i=size-1; i >= 0; i--)
6924                                 movLeft2Result (left, i, result, offr + i);
6925                 } // if
6926                 break;
6927                 
6928         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6929                 if (same && offr) {
6930                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6931                         shiftLeft_Left2ResultLit (result, result, shCount);
6932                         return; /* prevent clearing result again */
6933                 } else {
6934                         emitCLRC;
6935                         for (i=0; i < size; i++) {
6936                                 if (same && !offr) {
6937                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6938                                 } else {
6939                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6940                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6941                                 } // if
6942                         } // for
6943                 } // if (offr)
6944                 break;
6945                 
6946         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6947                 /* works in-place/with offr as well */
6948                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6949                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6950                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6951
6952                 for (i = size - 2; i >= 0; i--)
6953                 {
6954                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6955                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6956                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6957                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6958                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6959                 } // for i
6960                 break;
6961                 
6962         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6963                 /* works in-place/with offr as well */
6964                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6965                 for (i = size-2; i >= 0; i--) {
6966                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6967                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6968                 } // for i
6969                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6970                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6971                 break;
6972         
6973         default:
6974                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6975                 shiftLeft_Left2ResultLit (result, result, 1);
6976                 return; /* prevent clearing result again */
6977                 break;
6978         } // switch
6979
6980         while (0 < offr--)
6981         {
6982                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6983         } // while
6984 }
6985
6986 /*-----------------------------------------------------------------*/
6987 /* shiftRight_Left2ResultLit - shift right by known count          */
6988 /*-----------------------------------------------------------------*/
6989
6990 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6991 {
6992         int size, same, offr, i;
6993
6994         size = AOP_SIZE(left);
6995         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6996         
6997         same = pic14_sameRegs (AOP(left), AOP(result));
6998         
6999         offr = shCount / 8;
7000         shCount = shCount & 0x07;
7001
7002         size -= offr;
7003
7004         if (size)
7005         {
7006                 switch (shCount)
7007                 {
7008                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7009                         if (!same || offr) {
7010                                 for (i=0; i < size; i++)
7011                                         movLeft2Result (left, i + offr, result, i);
7012                         } // if
7013                         break;
7014                         
7015                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7016                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7017                         if (same && offr) {
7018                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7019                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7020                                 return; /* prevent sign-extending result again */
7021                         } else {
7022                                 emitCLRC;
7023                                 if (sign) {
7024                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7025                                         emitSETC;
7026                                 }
7027                                 for (i = size-1; i >= 0; i--) {
7028                                         if (same && !offr) {
7029                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7030                                         } else {
7031                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7032                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7033                                         }
7034                                 } // for i
7035                         } // if (offr)
7036                         break;
7037                         
7038                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7039                         /* works in-place/with offr as well */
7040                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7041                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7042                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7043
7044                         for (i = 1; i < size; i++)
7045                         {
7046                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7047                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7048                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7049                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7050                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7051                         } // for i
7052
7053                         if (sign)
7054                         {
7055                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7056                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7057                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7058                         } // if
7059                         break;
7060                         
7061                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7062                         /* works in-place/with offr as well */
7063                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7064                         for (i = 0; i < size-1; i++) {
7065                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7066                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7067                         } // for i
7068                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7069                         if (!sign) {
7070                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7071                         } else {
7072                                 emitSKPNC;
7073                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7074                         }
7075                         break;
7076                 
7077                 default:
7078                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7079                         shiftRight_Left2ResultLit (result, result, 1, sign);
7080                         return; /* prevent sign extending result again */
7081                         break;
7082                 } // switch
7083         } // if
7084
7085         addSign (result, size, sign);
7086 }
7087
7088 #if 0
7089 /*-----------------------------------------------------------------*/
7090 /* shiftL2Left2Result - shift left two bytes from left to result   */
7091 /*-----------------------------------------------------------------*/
7092 static void shiftL2Left2Result (operand *left, int offl,
7093                                                                 operand *result, int offr, int shCount)
7094 {
7095         FENTRY;
7096         
7097         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7098         
7099         if(pic14_sameRegs(AOP(result), AOP(left))) {
7100                 switch(shCount) {
7101                 case 0:
7102                         break;
7103                 case 1:
7104                 case 2:
7105                 case 3:
7106                         
7107                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7108                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7109                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7110                         
7111                         while(--shCount) {
7112                                 emitCLRC;
7113                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7114                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7115                         }
7116                         
7117                         break;
7118                 case 4:
7119                 case 5:
7120                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7121                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7122                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7123                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7124                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7125                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7126                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7127                         if(shCount >=5) {
7128                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7129                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7130                         }
7131                         break;
7132                 case 6:
7133                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7134                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7135                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7136                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7137                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7138                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7139                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7140                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7141                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7142                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7143                         break;
7144                 case 7:
7145                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7146                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7147                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7148                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7149                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7150                 }
7151                 
7152         } else {
7153                 switch(shCount) {
7154                 case 0:
7155                         break;
7156                 case 1:
7157                 case 2:
7158                 case 3:
7159                 /* note, use a mov/add for the shift since the mov has a
7160                         chance of getting optimized out */
7161                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7162                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7163                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7164                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7165                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7166                         
7167                         while(--shCount) {
7168                                 emitCLRC;
7169                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7170                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7171                         }
7172                         break;
7173                         
7174                 case 4:
7175                 case 5:
7176                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7177                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7178                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7179                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7180                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7181                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7182                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7183                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7184                         
7185                         
7186                         if(shCount == 5) {
7187                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7188                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7189                         }
7190                         break;
7191                 case 6:
7192                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7193                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7195                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7196                         
7197                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7198                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7199                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7200                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7201                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7202                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7203                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7204                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7205                         break;
7206                 case 7:
7207                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7208                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7209                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7210                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7211                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7212                 }
7213         }
7214         
7215 }
7216
7217 /*-----------------------------------------------------------------*/
7218 /* shiftR2Left2Result - shift right two bytes from left to result  */
7219 /*-----------------------------------------------------------------*/
7220 static void shiftR2Left2Result (operand *left, int offl,
7221                                                                 operand *result, int offr,
7222                                                                 int shCount, int sign)
7223 {
7224         int same=0;
7225         
7226         FENTRY;
7227         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228         same = pic14_sameRegs(AOP(result), AOP(left));
7229         
7230         if(same && ((offl + MSB16) == offr)){
7231                 same=1;
7232                 /* don't crash result[offr] */
7233                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7234                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7235         }
7236         /* else {
7237         movLeft2Result(left,offl, result, offr);
7238         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7239         }
7240         */
7241         /* a:x >> shCount (x = lsb(result))*/
7242         /*
7243         if(sign)
7244         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7245         else {
7246         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7247         */
7248         switch(shCount) {
7249         case 0:
7250                 break;
7251         case 1:
7252         case 2:
7253         case 3:
7254                 if(sign)
7255                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7256                 else
7257                         emitCLRC;
7258                 
7259                 if(same) {
7260                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7261                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7262                 } else {
7263                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7264                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7265                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7266                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7267                 }
7268                 
7269                 while(--shCount) {
7270                         if(sign)
7271                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7272                         else
7273                                 emitCLRC;
7274                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7275                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7276                 }
7277                 break;
7278         case 4:
7279         case 5:
7280                 if(same) {
7281                         
7282                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7283                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7284                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7285                         
7286                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7287                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7288                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7289                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7290                 } else {
7291                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7292                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7293                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7294                         
7295                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7296                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7297                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7298                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7299                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7300                 }
7301                 
7302                 if(shCount >=5) {
7303                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7304                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7305                 }
7306                 
7307                 if(sign) {
7308                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7309                         emitpcode(POC_BTFSC, 
7310                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7311                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7312                 }
7313                 
7314                 break;
7315                 
7316         case 6:
7317                 if(same) {
7318                         
7319                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7320                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7321                         
7322                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7323                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7324                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7325                         emitpcode(POC_ANDLW,popGetLit(0x03));
7326                         if(sign) {
7327                                 emitpcode(POC_BTFSC, 
7328                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7329                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7330                         }
7331                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7332                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7333                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7334                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7335                 } else {
7336                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7337                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7338                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7339                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7340                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7341                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7342                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7343                         emitpcode(POC_ANDLW,popGetLit(0x03));
7344                         if(sign) {
7345                                 emitpcode(POC_BTFSC, 
7346                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7347                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7348                         }
7349                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7350                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7351                         
7352                         
7353                 }
7354                 
7355                 break;
7356         case 7:
7357                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7358                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7359                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7360                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7361                 if(sign) {
7362                         emitSKPNC;
7363                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7364                 } else 
7365                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7366   }
7367 }
7368
7369 /*-----------------------------------------------------------------*/
7370 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7371 /*-----------------------------------------------------------------*/
7372 static void shiftLLeftOrResult (operand *left, int offl,
7373                                                                 operand *result, int offr, int shCount)
7374 {
7375         FENTRY;
7376         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7377         
7378         /* shift left accumulator */
7379         AccLsh(left,offl,shCount);
7380         /* or with result */
7381         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7382         assert ( !"broken (modifies left, fails for left==result))" );
7383 }
7384
7385 /*-----------------------------------------------------------------*/
7386 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7387 /*-----------------------------------------------------------------*/
7388 static void shiftRLeftOrResult (operand *left, int offl,
7389                                                                 operand *result, int offr, int shCount)
7390 {
7391         FENTRY;
7392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7393         
7394         /* shift right accumulator */
7395         AccRsh(left,offl,shCount);
7396         /* or with result */
7397         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7398         assert ( !"broken (modifies left, fails for left==result))" );
7399 }
7400
7401 /*-----------------------------------------------------------------*/
7402 /* genlshOne - left shift a one byte quantity by known count       */
7403 /*-----------------------------------------------------------------*/
7404 static void genlshOne (operand *result, operand *left, int shCount)
7405 {       
7406         FENTRY;
7407         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7408         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7409 }
7410
7411 /*-----------------------------------------------------------------*/
7412 /* genlshTwo - left shift two bytes by known amount != 0           */
7413 /*-----------------------------------------------------------------*/
7414 static void genlshTwo (operand *result,operand *left, int shCount)
7415 {
7416         int size;
7417         
7418         FENTRY;
7419         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7420         size = pic14_getDataSize(result);
7421         
7422         /* if shCount >= 8 */
7423         if (shCount >= 8) {
7424                 shCount -= 8 ;
7425                 
7426                 if (size > 1){
7427                         if (shCount)
7428                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7429                         else 
7430                                 movLeft2Result(left, LSB, result, MSB16);
7431                 }
7432                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7433         }
7434         
7435         /*  1 <= shCount <= 7 */
7436         else {  
7437                 if(size == 1)
7438                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7439                 else 
7440                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7441         }
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* shiftLLong - shift left one long from left to result            */
7446 /* offl = LSB or MSB16                                             */
7447 /*-----------------------------------------------------------------*/
7448 static void shiftLLong (operand *left, operand *result, int offr )
7449 {
7450         char *l;
7451         int size = AOP_SIZE(result);
7452         
7453         FENTRY;
7454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455         if(size >= LSB+offr){
7456                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7457                 MOVA(l);
7458                 pic14_emitcode("add","a,acc");
7459                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7460                         size >= MSB16+offr && offr != LSB )
7461                         pic14_emitcode("xch","a,%s",
7462                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7463                 else      
7464                         aopPut(AOP(result),"a",LSB+offr);
7465         }
7466         
7467         if(size >= MSB16+offr){
7468                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7469                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7470                         MOVA(l);
7471                 }
7472                 pic14_emitcode("rlc","a");
7473                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7474                         size >= MSB24+offr && offr != LSB)
7475                         pic14_emitcode("xch","a,%s",
7476                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7477                 else      
7478                         aopPut(AOP(result),"a",MSB16+offr);
7479         }
7480         
7481         if(size >= MSB24+offr){
7482                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7483                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7484                         MOVA(l);
7485                 }
7486                 pic14_emitcode("rlc","a");
7487                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7488                         size >= MSB32+offr && offr != LSB )
7489                         pic14_emitcode("xch","a,%s",
7490                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7491                 else      
7492                         aopPut(AOP(result),"a",MSB24+offr);
7493         }
7494         
7495         if(size > MSB32+offr){
7496                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7497                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7498                         MOVA(l);  
7499                 }
7500                 pic14_emitcode("rlc","a");
7501                 aopPut(AOP(result),"a",MSB32+offr);
7502         }
7503         if(offr != LSB)
7504                 aopPut(AOP(result),zero,LSB);       
7505 }
7506
7507 /*-----------------------------------------------------------------*/
7508 /* genlshFour - shift four byte by a known amount != 0             */
7509 /*-----------------------------------------------------------------*/
7510 static void genlshFour (operand *result, operand *left, int shCount)
7511 {
7512         int size;
7513         
7514         FENTRY;
7515         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7516         size = AOP_SIZE(result);
7517         
7518         /* if shifting more that 3 bytes */
7519         if (shCount >= 24 ) {
7520                 shCount -= 24;
7521                 if (shCount)
7522                 /* lowest order of left goes to the highest
7523                 order of the destination */
7524                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7525                 else
7526                         movLeft2Result(left, LSB, result, MSB32);
7527                 aopPut(AOP(result),zero,LSB);
7528                 aopPut(AOP(result),zero,MSB16);
7529                 aopPut(AOP(result),zero,MSB32);
7530                 return;
7531         }
7532         
7533         /* more than two bytes */
7534         else if ( shCount >= 16 ) {
7535                 /* lower order two bytes goes to higher order two bytes */
7536                 shCount -= 16;
7537                 /* if some more remaining */
7538                 if (shCount)
7539                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7540                 else {
7541                         movLeft2Result(left, MSB16, result, MSB32);
7542                         movLeft2Result(left, LSB, result, MSB24);
7543                 }
7544                 aopPut(AOP(result),zero,MSB16);
7545                 aopPut(AOP(result),zero,LSB);
7546                 return;
7547         }    
7548         
7549         /* if more than 1 byte */
7550         else if ( shCount >= 8 ) {
7551                 /* lower order three bytes goes to higher order  three bytes */
7552                 shCount -= 8;
7553                 if(size == 2){
7554                         if(shCount)
7555                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7556                         else
7557                                 movLeft2Result(left, LSB, result, MSB16);
7558                 }
7559                 else{   /* size = 4 */
7560                         if(shCount == 0){
7561                                 movLeft2Result(left, MSB24, result, MSB32);
7562                                 movLeft2Result(left, MSB16, result, MSB24);
7563                                 movLeft2Result(left, LSB, result, MSB16);
7564                                 aopPut(AOP(result),zero,LSB);
7565                         }
7566                         else if(shCount == 1)
7567                                 shiftLLong(left, result, MSB16);
7568                         else{
7569                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7570                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7571                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7572                                 aopPut(AOP(result),zero,LSB);
7573                         }
7574                 }
7575         }
7576         
7577         /* 1 <= shCount <= 7 */
7578         else if(shCount <= 2){
7579                 shiftLLong(left, result, LSB);
7580                 if(shCount == 2)
7581                         shiftLLong(result, result, LSB);
7582         }
7583         /* 3 <= shCount <= 7, optimize */
7584         else{
7585                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7586                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7587                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7588         }
7589 }
7590 #endif
7591
7592 #if 0
7593 /*-----------------------------------------------------------------*/
7594 /* genLeftShiftLiteral - left shifting by known count              */
7595 /*-----------------------------------------------------------------*/
7596 static void genLeftShiftLiteral (operand *left,
7597                                                                  operand *right,
7598                                                                  operand *result,
7599                                                                  iCode *ic)
7600 {    
7601         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7602         //int size;
7603         
7604         FENTRY;
7605         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7606         freeAsmop(right,NULL,ic,TRUE);
7607         
7608         aopOp(left,ic,FALSE);
7609         aopOp(result,ic,FALSE);
7610
7611         size = getSize(operandType(result));
7612         
7613 #if VIEW_SIZE
7614         pic14_emitcode("; shift left ","result %d, left %d",size,
7615                 AOP_SIZE(left));
7616 #endif
7617         
7618         /* I suppose that the left size >= result size */
7619         if(shCount == 0){
7620                 while(size--){
7621                         movLeft2Result(left, size, result, size);
7622                 }
7623         }
7624         
7625         else if(shCount >= (size * 8))
7626                 while(size--)
7627                         aopPut(AOP(result),zero,size);
7628                 else{
7629                         switch (size) {
7630                         case 1:
7631                                 genlshOne (result,left,shCount);
7632                                 break;
7633                                 
7634                         case 2:
7635                         case 3:
7636                                 genlshTwo (result,left,shCount);
7637                                 break;
7638                                 
7639                         case 4:
7640                                 genlshFour (result,left,shCount);
7641                                 break;
7642                         }
7643                 }
7644                 freeAsmop(left,NULL,ic,TRUE);
7645                 freeAsmop(result,NULL,ic,TRUE);
7646 }
7647 #endif
7648
7649 /*-----------------------------------------------------------------*
7650 * genMultiAsm - repeat assembly instruction for size of register.
7651 * if endian == 1, then the high byte (i.e base address + size of 
7652 * register) is used first else the low byte is used first;
7653 *-----------------------------------------------------------------*/
7654 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7655 {
7656         
7657         int offset = 0;
7658         
7659         FENTRY;
7660         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7661         
7662         if(!reg)
7663                 return;
7664         
7665         if(!endian) {
7666                 endian = 1;
7667         } else {
7668                 endian = -1;
7669                 offset = size-1;
7670         }
7671         
7672         while(size--) {
7673                 emitpcode(poc,    popGet(AOP(reg),offset));
7674                 offset += endian;
7675         }
7676         
7677 }
7678
7679 #if 0
7680 /*-----------------------------------------------------------------*/
7681 /* genLeftShift - generates code for left shifting                 */
7682 /*-----------------------------------------------------------------*/
7683 static void genLeftShift (iCode *ic)
7684 {
7685         operand *left,*right, *result;
7686         int size, offset;
7687         unsigned long lit = 0L;
7688         char *l;
7689         symbol *tlbl , *tlbl1;
7690         pCodeOp *pctemp;
7691         
7692         FENTRY;
7693         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7694         
7695         right = IC_RIGHT(ic);
7696         left  = IC_LEFT(ic);
7697         result = IC_RESULT(ic);
7698         
7699         aopOp(right,ic,FALSE);
7700         aopOp(left,ic,FALSE);
7701         aopOp(result,ic,FALSE);
7702         
7703         
7704         /* if the shift count is known then do it 
7705         as efficiently as possible */
7706         if (AOP_TYPE(right) == AOP_LIT) {
7707                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7708                 return ;
7709         }
7710         
7711         /* shift count is unknown then we have to form 
7712         a loop get the loop count in B : Note: we take
7713         only the lower order byte since shifting
7714         more that 32 bits make no sense anyway, ( the
7715         largest size of an object can be only 32 bits ) */  
7716         
7717         /* this code fails for RIGHT == RESULT */
7718         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7719         
7720         /* now move the left to the result if they are not the
7721         same */
7722         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7723                 AOP_SIZE(result) > 1) {
7724                 
7725                 size = AOP_SIZE(result);
7726                 offset=0;
7727                 while (size--) {
7728                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7729                         if (*l == '@' && (IS_AOP_PREG(result))) {
7730                                 
7731                                 pic14_emitcode("mov","a,%s",l);
7732                                 aopPut(AOP(result),"a",offset);
7733                         } else {
7734                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7735                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7736                                 //aopPut(AOP(result),l,offset);
7737                         }
7738                         offset++;
7739                 }
7740         }
7741         
7742         if(AOP_TYPE(left) == AOP_LIT)
7743                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7744
7745         size = AOP_SIZE(result);
7746         
7747         /* if it is only one byte then */
7748         if (size == 1) {
7749                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7750                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7751                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7752                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7753                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7754                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7755                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7756                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7757                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7758                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7759                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7760                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7761                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7762                 } else {
7763                         
7764                         tlbl = newiTempLabel(NULL);
7765                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7766                                 mov2w (AOP(left), 0);
7767                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7768                         }
7769                         
7770                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7771                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7772                         emitpLabel(tlbl->key);
7773                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7774                         emitpcode(POC_ADDLW,  popGetLit(1));
7775                         emitSKPC;
7776                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7777                 }
7778                 goto release ;
7779         }
7780         
7781         if (pic14_sameRegs(AOP(left),AOP(result))) {
7782                 
7783                 tlbl = newiTempLabel(NULL);
7784                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7785                 genMultiAsm(POC_RRF, result, size,1);
7786                 emitpLabel(tlbl->key);
7787                 genMultiAsm(POC_RLF, result, size,0);
7788                 emitpcode(POC_ADDLW,  popGetLit(1));
7789                 emitSKPC;
7790                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7791                 goto release;
7792         }
7793         
7794         //tlbl = newiTempLabel(NULL);
7795         //offset = 0 ;   
7796         //tlbl1 = newiTempLabel(NULL);
7797         
7798         //reAdjustPreg(AOP(result));    
7799         
7800         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7801         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7802         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7803         //MOVA(l);
7804         //pic14_emitcode("add","a,acc");         
7805         //aopPut(AOP(result),"a",offset++);
7806         //while (--size) {
7807         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7808         //  MOVA(l);
7809         //  pic14_emitcode("rlc","a");         
7810         //  aopPut(AOP(result),"a",offset++);
7811         //}
7812         //reAdjustPreg(AOP(result));
7813         
7814         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7815         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7816         
7817         
7818         tlbl = newiTempLabel(NULL);
7819         tlbl1= newiTempLabel(NULL);
7820         
7821         size = AOP_SIZE(result);
7822         offset = 1;
7823         
7824         pctemp = popGetTempReg();  /* grab a temporary working register. */
7825         
7826         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7827         
7828         /* offset should be 0, 1 or 3 */
7829         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7830         emitSKPNZ;
7831         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7832         
7833         emitpcode(POC_MOVWF, pctemp);
7834         
7835         
7836         emitpLabel(tlbl->key);
7837         
7838         emitCLRC;
7839         emitpcode(POC_RLF,  popGet(AOP(result),0));
7840         while(--size)
7841                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7842         
7843         emitpcode(POC_DECFSZ,  pctemp);
7844         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7845         emitpLabel(tlbl1->key);
7846         
7847         popReleaseTempReg(pctemp);
7848         
7849         
7850 release:
7851         freeAsmop (right,NULL,ic,TRUE);
7852         freeAsmop(left,NULL,ic,TRUE);
7853         freeAsmop(result,NULL,ic,TRUE);
7854 }
7855 #endif
7856
7857 #if 0
7858 /*-----------------------------------------------------------------*/
7859 /* genrshOne - right shift a one byte quantity by known count      */
7860 /*-----------------------------------------------------------------*/
7861 static void genrshOne (operand *result, operand *left,
7862                                            int shCount, int sign)
7863 {
7864         FENTRY;
7865         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7866         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7867 }
7868
7869 /*-----------------------------------------------------------------*/
7870 /* genrshTwo - right shift two bytes by known amount != 0          */
7871 /*-----------------------------------------------------------------*/
7872 static void genrshTwo (operand *result,operand *left,
7873                                            int shCount, int sign)
7874 {
7875         FENTRY;
7876         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7877         /* if shCount >= 8 */
7878         if (shCount >= 8) {
7879                 shCount -= 8 ;
7880                 if (shCount)
7881                         shiftR1Left2Result(left, MSB16, result, LSB,
7882                         shCount, sign);
7883                 else
7884                         movLeft2Result(left, MSB16, result, LSB);
7885                 
7886                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7887                 
7888                 if(sign) {
7889                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7890                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7891                 }
7892         }
7893         
7894         /*  1 <= shCount <= 7 */
7895         else
7896                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7897 }
7898
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLong - shift right one long from left to result           */
7901 /* offl = LSB or MSB16                                             */
7902 /*-----------------------------------------------------------------*/
7903 static void shiftRLong (operand *left, int offl,
7904                                                 operand *result, int sign)
7905 {
7906         int size, same;
7907         
7908         FENTRY;
7909         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7910         
7911         size = AOP_SIZE(left);
7912         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7913         
7914         if (sign)
7915                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7916         else
7917                 emitCLRC;
7918
7919         assert (offl >= 0 && offl < size);
7920
7921         same = pic14_sameRegs (AOP(left), AOP(result));
7922
7923         /* perform the shift */
7924         while (size--)
7925         {
7926                 if (same && !offl) {
7927                         emitpcode (POC_RRF, popGet (AOP(result), size));
7928                 } else {
7929                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7930                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7931                 }
7932         } // while
7933
7934         addSign (result, AOP_SIZE(left) - offl, sign);
7935 }
7936
7937 /*-----------------------------------------------------------------*/
7938 /* genrshFour - shift four byte by a known amount != 0             */
7939 /*-----------------------------------------------------------------*/
7940 static void genrshFour (operand *result, operand *left,
7941                                                 int shCount, int sign)
7942 {
7943         FENTRY;
7944         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7945         /* if shifting more that 3 bytes */
7946         if(shCount >= 24 ) {
7947                 shCount -= 24;
7948                 if(shCount)
7949                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7950                 else
7951                         movLeft2Result(left, MSB32, result, LSB);
7952                 
7953                 addSign(result, MSB16, sign);
7954         }
7955         else if(shCount >= 16){
7956                 shCount -= 16;
7957                 if(shCount)
7958                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7959                 else{
7960                         movLeft2Result(left, MSB24, result, LSB);
7961                         movLeft2Result(left, MSB32, result, MSB16);
7962                 }
7963                 addSign(result, MSB24, sign);
7964         }
7965         else if(shCount >= 8){
7966                 shCount -= 8;
7967                 if(shCount == 1)
7968                         shiftRLong(left, MSB16, result, sign);
7969                 else if(shCount == 0){
7970                         movLeft2Result(left, MSB16, result, LSB);
7971                         movLeft2Result(left, MSB24, result, MSB16);
7972                         movLeft2Result(left, MSB32, result, MSB24);
7973                         addSign(result, MSB32, sign);
7974                 }
7975                 else{
7976                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7977                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7978                         /* the last shift is signed */
7979                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7980                         addSign(result, MSB32, sign);
7981                 }
7982         }
7983         else{   /* 1 <= shCount <= 7 */
7984                 if(shCount <= 2){
7985                         shiftRLong(left, LSB, result, sign);
7986                         if(shCount == 2)
7987                                 shiftRLong(result, LSB, result, sign);
7988                 }
7989                 else{
7990                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7991                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7992                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7993                 }
7994         }
7995 }
7996
7997 /*-----------------------------------------------------------------*/
7998 /* genRightShiftLiteral - right shifting by known count            */
7999 /*-----------------------------------------------------------------*/
8000 static void genRightShiftLiteral (operand *left,
8001                                                                   operand *right,
8002                                                                   operand *result,
8003                                                                   iCode *ic,
8004                                                                   int sign)
8005 {    
8006         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8007         int lsize,res_size;
8008         
8009         FENTRY;
8010         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8011         freeAsmop(right,NULL,ic,TRUE);
8012         
8013         aopOp(left,ic,FALSE);
8014         aopOp(result,ic,FALSE);
8015         
8016 #if VIEW_SIZE
8017         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8018                 AOP_SIZE(left));
8019 #endif
8020         
8021         lsize = pic14_getDataSize(left);
8022         res_size = pic14_getDataSize(result);
8023         /* test the LEFT size !!! */
8024         
8025         /* I suppose that the left size >= result size */
8026         if(shCount == 0){
8027                 while(res_size--)
8028                         movLeft2Result(left, res_size, result, res_size);
8029         }
8030         
8031         else if(shCount >= (lsize * 8)){
8032                 
8033                 if(res_size == 1) {
8034                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8035                         if(sign) {
8036                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8037                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8038                         }
8039                 } else {
8040                         
8041                         if(sign) {
8042                                 emitpcode(POC_MOVLW, popGetLit(0));
8043                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8044                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8045                                 while(res_size--)
8046                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8047                                 
8048                         } else {
8049                                 
8050                                 while(res_size--)
8051                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8052                         }
8053                 }
8054         } else {
8055                 
8056                 switch (res_size) {
8057                 case 1:
8058                         genrshOne (result,left,shCount,sign);
8059                         break;
8060                         
8061                 case 2:
8062                         genrshTwo (result,left,shCount,sign);
8063                         break;
8064                         
8065                 case 4:
8066                         genrshFour (result,left,shCount,sign);
8067                         break;
8068                 default :
8069                         break;
8070                 }
8071                 
8072         }
8073
8074         freeAsmop(left,NULL,ic,TRUE);
8075         freeAsmop(result,NULL,ic,TRUE);
8076 }
8077 #endif
8078
8079 #if 0
8080 /*-----------------------------------------------------------------*/
8081 /* genSignedRightShift - right shift of signed number              */
8082 /*-----------------------------------------------------------------*/
8083 static void genSignedRightShift (iCode *ic)
8084 {
8085         operand *right, *left, *result;
8086         int size, offset;
8087         //  char *l;
8088         symbol *tlbl, *tlbl1 ;
8089         pCodeOp *pctemp;
8090         
8091         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8092         
8093         /* we do it the hard way put the shift count in b
8094         and loop thru preserving the sign */
8095         FENTRY;
8096         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8097         
8098         right = IC_RIGHT(ic);
8099         left  = IC_LEFT(ic);
8100         result = IC_RESULT(ic);
8101         
8102         aopOp(right,ic,FALSE);  
8103         aopOp(left,ic,FALSE);
8104         aopOp(result,ic,FALSE);
8105         
8106         
8107         if ( AOP_TYPE(right) == AOP_LIT) {
8108                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8109                 //genRightShiftLiteral (left,right,result,ic,1);
8110                 return ;
8111         }
8112         /* shift count is unknown then we have to form 
8113         a loop get the loop count in B : Note: we take
8114         only the lower order byte since shifting
8115         more that 32 bits make no sense anyway, ( the
8116         largest size of an object can be only 32 bits ) */  
8117         
8118         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8119         //pic14_emitcode("inc","b");
8120         //freeAsmop (right,NULL,ic,TRUE);
8121         //aopOp(left,ic,FALSE);
8122         //aopOp(result,ic,FALSE);
8123         
8124         /* now move the left to the result if they are not the
8125         same */
8126         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8127                 AOP_SIZE(result) > 1) {
8128                 
8129                 size = AOP_SIZE(result);
8130                 offset=0;
8131                 while (size--) { 
8132                         /*
8133                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8134                         if (*l == '@' && IS_AOP_PREG(result)) {
8135                                 pic14_emitcode("mov","a,%s",l);
8136                                 aopPut(AOP(result),"a",offset);
8137                         } else
8138                         aopPut(AOP(result),l,offset);
8139                         */
8140                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8141                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8142                         
8143                         offset++;
8144                 }
8145         }
8146         
8147         /* mov the highest order bit to OVR */    
8148         tlbl = newiTempLabel(NULL);
8149         tlbl1= newiTempLabel(NULL);
8150         
8151         size = AOP_SIZE(result);
8152         offset = size - 1;
8153         
8154         pctemp = popGetTempReg();  /* grab a temporary working register. */
8155         
8156         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8157         
8158         /* offset should be 0, 1 or 3 */
8159         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8160         emitSKPNZ;
8161         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8162         
8163         emitpcode(POC_MOVWF, pctemp);
8164         
8165         
8166         emitpLabel(tlbl->key);
8167         
8168         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8169         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8170         
8171         while(--size) {
8172                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8173         }
8174         
8175         emitpcode(POC_DECFSZ,  pctemp);
8176         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8177         emitpLabel(tlbl1->key);
8178         
8179         popReleaseTempReg(pctemp);
8180 #if 0
8181         size = AOP_SIZE(result);
8182         offset = size - 1;
8183         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8184         pic14_emitcode("rlc","a");
8185         pic14_emitcode("mov","ov,c");
8186         /* if it is only one byte then */
8187         if (size == 1) {
8188                 l = aopGet(AOP(left),0,FALSE,FALSE);
8189                 MOVA(l);
8190                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8191                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8192                 pic14_emitcode("mov","c,ov");
8193                 pic14_emitcode("rrc","a");
8194                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8195                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8196                 aopPut(AOP(result),"a",0);
8197                 goto release ;
8198         }
8199         
8200         reAdjustPreg(AOP(result));
8201         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8202         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8203         pic14_emitcode("mov","c,ov");
8204         while (size--) {
8205                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8206                 MOVA(l);
8207                 pic14_emitcode("rrc","a");         
8208                 aopPut(AOP(result),"a",offset--);
8209         }
8210         reAdjustPreg(AOP(result));
8211         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8212         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8213         
8214 release:
8215 #endif
8216         
8217         freeAsmop(left,NULL,ic,TRUE);
8218         freeAsmop(result,NULL,ic,TRUE);
8219         freeAsmop(right,NULL,ic,TRUE);
8220 }
8221 #endif
8222
8223 /*-----------------------------------------------------------------*/
8224 /* loadSignToC - load the operand's sign bit into CARRY            */
8225 /*-----------------------------------------------------------------*/
8226
8227 static void loadSignToC (operand *op)
8228 {
8229         FENTRY;
8230         assert (op && AOP(op) && AOP_SIZE(op));
8231
8232         emitCLRC;
8233         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8234         emitSETC;
8235 }
8236
8237 /*-----------------------------------------------------------------*/
8238 /* genRightShift - generate code for right shifting                */
8239 /*-----------------------------------------------------------------*/
8240 static void genGenericShift (iCode *ic, int shiftRight)
8241 {
8242         operand *right, *left, *result;
8243         sym_link *retype ;
8244         int size;
8245         symbol *tlbl, *tlbl1, *inverselbl;
8246         
8247         FENTRY;
8248         /* if signed then we do it the hard way preserve the
8249         sign bit moving it inwards */
8250         retype = getSpec(operandType(IC_RESULT(ic)));
8251         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8252         
8253         /* signed & unsigned types are treated the same : i.e. the
8254         signed is NOT propagated inwards : quoting from the
8255         ANSI - standard : "for E1 >> E2, is equivalent to division
8256         by 2**E2 if unsigned or if it has a non-negative value,
8257         otherwise the result is implementation defined ", MY definition
8258         is that the sign does not get propagated */
8259         
8260         right = IC_RIGHT(ic);
8261         left  = IC_LEFT(ic);
8262         result = IC_RESULT(ic);
8263         
8264         aopOp(right,ic,FALSE);
8265         aopOp(left,ic,FALSE);
8266         aopOp(result,ic,FALSE);
8267         
8268         /* if the shift count is known then do it 
8269         as efficiently as possible */
8270         if (AOP_TYPE(right) == AOP_LIT) {
8271                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8272                 if (lit < 0)
8273                 {
8274                         lit = -lit;
8275                         shiftRight = !shiftRight;
8276                 }
8277                 
8278                 if (shiftRight)
8279                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8280                 else
8281                         shiftLeft_Left2ResultLit (left, result, lit);
8282                 //genRightShiftLiteral (left,right,result,ic, 0);
8283                 return ;
8284         }
8285         
8286         /* shift count is unknown then we have to form 
8287         a loop get the loop count in B : Note: we take
8288         only the lower order byte since shifting
8289         more that 32 bits make no sense anyway, ( the
8290         largest size of an object can be only 32 bits ) */  
8291
8292         /* we must not overwrite the shift counter */
8293         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8294         
8295         /* now move the left to the result if they are not the
8296         same */
8297         if (!pic14_sameRegs(AOP(left),AOP(result)))
8298         {
8299                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8300                 while (size--) {
8301                         mov2w(AOP(left), size);
8302                         movwf(AOP(result), size);
8303                 }
8304                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8305         }
8306         
8307         tlbl = newiTempLabel(NULL);
8308         tlbl1= newiTempLabel(NULL);
8309         inverselbl = NULL;
8310         size = AOP_SIZE(result);
8311
8312         mov2w(AOP(right),0);
8313         if (!SPEC_USIGN(operandType(right)))
8314         {
8315                 inverselbl = newiTempLabel(NULL);
8316                 /* signed shift count -- invert shift direction for c<0 */
8317                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8318                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8319         } // if
8320         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8321         /* check for `a = b >> c' with `-c == 0' */
8322         emitSKPNZ;
8323         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8324         emitpLabel(tlbl->key);
8325         /* propagate the sign bit inwards for SIGNED result */
8326         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8327         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8328         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8329         emitSKPC;
8330         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8331
8332         if (!SPEC_USIGN(operandType(right)))
8333         {
8334                 symbol *inv_loop = newiTempLabel(NULL);
8335
8336                 shiftRight = !shiftRight;       /* invert shift direction */
8337                 
8338                 /* we came here from the code above -- we are done */
8339                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8340                 
8341                 /* emit code for shifting N<0 steps, count is already in W */
8342                 emitpLabel(inverselbl->key);
8343                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8344                 emitpLabel(inv_loop->key);
8345                 /* propagate the sign bit inwards for SIGNED result */
8346                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8347                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8348                 emitpcode(POC_ADDLW, popGetLit(1));
8349                 emitSKPC;
8350                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8351         } // if
8352         
8353         emitpLabel(tlbl1->key);
8354         
8355         freeAsmop(left,NULL,ic,TRUE);
8356         freeAsmop (right,NULL,ic,TRUE);
8357         freeAsmop(result,NULL,ic,TRUE);
8358 }
8359
8360 static void genRightShift (iCode *ic)
8361 {
8362         genGenericShift(ic, 1);
8363 }
8364
8365 static void genLeftShift (iCode *ic)
8366 {
8367         genGenericShift(ic, 0);
8368 }
8369
8370 /*-----------------------------------------------------------------*/
8371 /* SetIrp - Set IRP bit                                            */
8372 /*-----------------------------------------------------------------*/
8373 void SetIrp(operand *result) {
8374         FENTRY;
8375         if (AOP_TYPE(result) == AOP_LIT) {
8376                 unsigned lit = (unsigned)operandLitValue(result);
8377                 if (lit&0x100)
8378                         emitSETIRP;
8379                 else
8380                         emitCLRIRP;
8381         } else {
8382                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8383                         int addrs = PCOL(AOP(result))->lit;
8384                         if (addrs & 0x100)
8385                                 emitSETIRP;
8386                         else
8387                                 emitCLRIRP;
8388                 } else {
8389                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8390                         if(AOP_SIZE(result) > 1) {
8391                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8392                                 emitSETIRP;
8393                         }
8394                 }
8395         }
8396 }
8397
8398 static void
8399 setup_fsr (operand *ptr)
8400 {
8401   mov2w_op(ptr, 0);
8402   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8403
8404   /* also setup-up IRP */
8405   SetIrp (ptr);
8406 }
8407
8408 /*-----------------------------------------------------------------*/
8409 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8410 /*                  arbitrary pointer (__code, __data, generic)    */
8411 /*-----------------------------------------------------------------*/
8412 static void
8413 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8414 {
8415     FENTRY;
8416     switch (p_type)
8417     {
8418     case POINTER:
8419     case FPOINTER:
8420       if (!alreadyAddressed) setup_fsr (src);
8421       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8422       break;
8423     
8424     case CPOINTER:
8425       assert( AOP_SIZE(src) == 2 );
8426       mov2w_op(src, 0);
8427       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8428       mov2w_op(src, 1);
8429       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8430       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8431       call_libraryfunc ("__gptrget1");
8432       break;
8433     
8434     case GPOINTER:
8435       assert( AOP_SIZE(src) == 3 );
8436       mov2w_op(src, 0);
8437       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8438       mov2w_op(src, 1);
8439       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8440       mov2w_op(src, 2);
8441       call_libraryfunc ("__gptrget1");
8442       break;
8443     
8444     default:
8445       assert( !"unhandled pointer type" );
8446       break;
8447     }
8448 }
8449
8450 /*-----------------------------------------------------------------*/
8451 /* emitPtrByteSet - emits code to set a byte from src through a    */
8452 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8453 /*-----------------------------------------------------------------*/
8454 static void
8455 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8456 {
8457     FENTRY;
8458     switch (p_type)
8459     {
8460     case POINTER:
8461     case FPOINTER:
8462       if (!alreadyAddressed) setup_fsr (dst);
8463       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8464       break;
8465     
8466     case CPOINTER:
8467       assert( !"trying to assign to __code pointer" );
8468       break;
8469     
8470     case GPOINTER:
8471       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8472       mov2w_op(dst, 0);
8473       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8474       mov2w_op(dst, 1);
8475       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8476       mov2w_op(dst, 2);
8477       call_libraryfunc ("__gptrput1");
8478       break;
8479
8480     default:
8481       assert( !"unhandled pointer type" );
8482       break;
8483     }
8484 }
8485
8486 /*-----------------------------------------------------------------*/
8487 /* genUnpackBits - generates code for unpacking bits               */
8488 /*-----------------------------------------------------------------*/
8489 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8490 {    
8491   int rsize;            /* result size */
8492   sym_link *etype;      /* bitfield type information */
8493   int blen;             /* bitfield length */
8494   int bstr;             /* bitfield starting bit within byte */
8495
8496   FENTRY;
8497   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8498   etype = getSpec(operandType(result));
8499   rsize = getSize (operandType (result));
8500   blen = SPEC_BLEN (etype);
8501   bstr = SPEC_BSTR (etype);
8502
8503   /* single bit field case */
8504   if (blen == 1) {
8505     if (ifx) { /* that is for an if statement */
8506       pCodeOp *pcop;
8507       resolvedIfx rIfx;
8508       resolveIfx(&rIfx,ifx);
8509       if (ptype == -1) /* direct */
8510         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8511       else
8512         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8513       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8514       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8515       ifx->generated=1;
8516     } else {
8517       int i;
8518       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8519       for (i=0; i < AOP_SIZE(result); i++)
8520         emitpcode (POC_CLRF, popGet (AOP(result), i));
8521
8522       switch (ptype)
8523       {
8524       case -1:
8525         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8526         /* adjust result below */
8527         break;
8528         
8529       case POINTER:
8530       case FPOINTER:
8531       case GPOINTER:
8532       case CPOINTER:
8533         emitPtrByteGet (left, ptype, FALSE);
8534         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8535         emitSKPZ;
8536         /* adjust result below */
8537         break;
8538         
8539       default:
8540         assert( !"unhandled pointer type" );
8541       } // switch
8542
8543       /* move sign-/zero extended bit to result */
8544       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8545         emitpcode (POC_INCF, popGet (AOP(result), 0));
8546       } else {
8547         emitpcode (POC_DECF, popGet (AOP(result), 0));
8548       }
8549       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8550     }
8551     return;
8552   }
8553   else if (blen <= 8 && ((blen + bstr) <= 8))
8554   {
8555     /* blen > 1 */
8556     int i;
8557
8558     for (i=0; i < AOP_SIZE(result); i++)
8559       emitpcode (POC_CLRF, popGet (AOP(result), i));
8560
8561     switch (ptype)
8562     {
8563     case -1:
8564       mov2w(AOP(left), 0);
8565       break;
8566       
8567     case POINTER:
8568     case FPOINTER:
8569     case GPOINTER:
8570     case CPOINTER:
8571       emitPtrByteGet (left, ptype, FALSE);
8572       break;
8573       
8574     default:
8575       assert( !"unhandled pointer type" );
8576     } // switch
8577
8578     if (blen < 8)
8579       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8580     movwf(AOP(result), 0);
8581     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8582
8583     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8584     {
8585       /* signed bitfield */
8586       assert (bstr + blen > 0);
8587       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8588       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8589       emitpcode(POC_IORWF, popGet(AOP(result),0));
8590     }
8591     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8592     return;
8593   }
8594
8595   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8596 }
8597
8598 #if 1
8599 /*-----------------------------------------------------------------*/
8600 /* genDataPointerGet - generates code when ptr offset is known     */
8601 /*-----------------------------------------------------------------*/
8602 static void genDataPointerGet (operand *left, 
8603         operand *result, 
8604         iCode *ic)
8605 {
8606         int size , offset = 0;
8607                 
8608         FENTRY;
8609         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8610         
8611         
8612         /* optimization - most of the time, left and result are the same
8613         * address, but different types. for the pic code, we could omit
8614         * the following
8615         */
8616         aopOp(result,ic,TRUE);
8617         
8618         if (pic14_sameRegs (AOP(left), AOP(result)))
8619                 return;
8620         
8621         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8622         
8623         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8624         
8625         size = AOP_SIZE(result);
8626         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8627         
8628         offset = 0;
8629         while (size--) {
8630                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8631                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8632                 offset++;
8633         }
8634         
8635         freeAsmop(left,NULL,ic,TRUE);
8636         freeAsmop(result,NULL,ic,TRUE);
8637 }
8638 #endif
8639
8640 /*-----------------------------------------------------------------*/
8641 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8642 /*-----------------------------------------------------------------*/
8643 static void genNearPointerGet (operand *left, 
8644                                                            operand *result, 
8645                                                            iCode *ic)
8646 {
8647         asmop *aop = NULL;
8648         sym_link *ltype = operandType(left);
8649         sym_link *rtype = operandType(result);
8650         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8651         int direct = 0;
8652
8653         FENTRY;
8654         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8655         
8656         
8657         aopOp(left,ic,FALSE);
8658         
8659         /* if left is rematerialisable and
8660         result is not bit variable type and
8661         the left is pointer to data space i.e
8662         lower 128 bytes of space */
8663         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8664                 !IS_BITVAR(retype)         &&
8665                 PIC_IS_DATA_PTR(ltype)) {
8666                 genDataPointerGet (left,result,ic);
8667                 return ;
8668         }
8669         
8670         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8671         aopOp (result,ic,FALSE);
8672         
8673         /* Check if can access directly instead of via a pointer */
8674         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8675                 && AOP_SIZE(result) == 1)
8676         {
8677                 direct = 1;
8678         }
8679
8680         if (IS_BITFIELD(getSpec(operandType(result)))) 
8681         {
8682                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8683                 goto release;
8684         }
8685         
8686         /* If the pointer value is not in a the FSR then need to put it in */
8687         /* Must set/reset IRP bit for use with FSR. */
8688         if (!direct)
8689           setup_fsr (left);
8690         
8691 //      sym_link *etype;
8692         /* if bitfield then unpack the bits */
8693         {
8694                 /* we have can just get the values */
8695                 int size = AOP_SIZE(result);
8696                 int offset = 0 ;  
8697                 
8698                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8699                 
8700                 while(size--) {
8701                         if (direct)
8702                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8703                         else
8704                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8705                         if (AOP_TYPE(result) == AOP_LIT) {
8706                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8707                         } else {
8708                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8709                         }
8710                         if (size && !direct)
8711                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8712                         offset++;
8713                 }
8714         }
8715         
8716         /* now some housekeeping stuff */
8717         if (aop) {
8718                 /* we had to allocate for this iCode */
8719                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8720                 freeAsmop(NULL,aop,ic,TRUE);
8721         } else { 
8722                 /* we did not allocate which means left
8723                 already in a pointer register, then
8724                 if size > 0 && this could be used again
8725                 we have to point it back to where it 
8726                 belongs */
8727                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8728                 if (AOP_SIZE(result) > 1 &&
8729                         !OP_SYMBOL(left)->remat &&
8730                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8731                         ic->depth )) {
8732                         int size = AOP_SIZE(result) - 1;
8733                         while (size--)
8734                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8735                 }
8736         }
8737         
8738 release:
8739         /* done */
8740         freeAsmop(left,NULL,ic,TRUE);
8741         freeAsmop(result,NULL,ic,TRUE);
8742
8743 }
8744
8745 #if 0
8746 /*-----------------------------------------------------------------*/
8747 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8748 /*-----------------------------------------------------------------*/
8749 static void genPagedPointerGet (operand *left, 
8750                                                                 operand *result, 
8751                                                                 iCode *ic)
8752 {
8753         asmop *aop = NULL;
8754         regs *preg = NULL ;
8755         char *rname ;
8756         sym_link *rtype, *retype;    
8757         
8758         FENTRY;
8759         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760         
8761         rtype = operandType(result);
8762         retype= getSpec(rtype);
8763         
8764         aopOp(left,ic,FALSE);
8765         
8766         /* if the value is already in a pointer register
8767         then don't need anything more */
8768         if (!AOP_INPREG(AOP(left))) {
8769                 /* otherwise get a free pointer register */
8770                 aop = newAsmop(0);
8771                 preg = getFreePtr(ic,&aop,FALSE);
8772                 pic14_emitcode("mov","%s,%s",
8773                         preg->name,
8774                         aopGet(AOP(left),0,FALSE,TRUE));
8775                 rname = preg->name ;
8776         } else
8777                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8778         
8779         freeAsmop(left,NULL,ic,TRUE);
8780         aopOp (result,ic,FALSE);
8781         
8782         /* if bitfield then unpack the bits */
8783         if (IS_BITFIELD(retype)) 
8784                 genUnpackBits (result,left,rname,PPOINTER,0);
8785         else {
8786                 /* we have can just get the values */
8787                 int size = AOP_SIZE(result);
8788                 int offset = 0 ;  
8789                 
8790                 while (size--) {
8791                         
8792                         pic14_emitcode("movx","a,@%s",rname);
8793                         aopPut(AOP(result),"a",offset);
8794                         
8795                         offset++ ;
8796                         
8797                         if (size)
8798                                 pic14_emitcode("inc","%s",rname);
8799                 }
8800         }
8801         
8802         /* now some housekeeping stuff */
8803         if (aop) {
8804                 /* we had to allocate for this iCode */
8805                 freeAsmop(NULL,aop,ic,TRUE);
8806         } else { 
8807         /* we did not allocate which means left
8808         already in a pointer register, then
8809         if size > 0 && this could be used again
8810         we have to point it back to where it 
8811                 belongs */
8812                 if (AOP_SIZE(result) > 1 &&
8813                         !OP_SYMBOL(left)->remat &&
8814                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8815                         ic->depth )) {
8816                         int size = AOP_SIZE(result) - 1;
8817                         while (size--)
8818                                 pic14_emitcode("dec","%s",rname);
8819                 }
8820         }
8821         
8822         /* done */
8823         freeAsmop(result,NULL,ic,TRUE);
8824         
8825         
8826 }
8827
8828 /*-----------------------------------------------------------------*/
8829 /* genFarPointerGet - gget value from far space                    */
8830 /*-----------------------------------------------------------------*/
8831 static void genFarPointerGet (operand *left,
8832                                                           operand *result, iCode *ic)
8833 {
8834         int size, offset ;
8835         sym_link *retype = getSpec(operandType(result));
8836         
8837         FENTRY;
8838         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839         
8840         aopOp(left,ic,FALSE);
8841         
8842         /* if the operand is already in dptr 
8843         then we do nothing else we move the value to dptr */
8844         if (AOP_TYPE(left) != AOP_STR) {
8845                 /* if this is remateriazable */
8846                 if (AOP_TYPE(left) == AOP_IMMD)
8847                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8848                 else { /* we need to get it byte by byte */
8849                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8850                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8851                         if (options.model == MODEL_FLAT24)
8852                         {
8853                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8854                         }
8855                 }
8856         }
8857         /* so dptr know contains the address */
8858         freeAsmop(left,NULL,ic,TRUE);
8859         aopOp(result,ic,FALSE);
8860         
8861         /* if bit then unpack */
8862         if (IS_BITFIELD(retype)) 
8863                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8864         else {
8865                 size = AOP_SIZE(result);
8866                 offset = 0 ;
8867                 
8868                 while (size--) {
8869                         pic14_emitcode("movx","a,@dptr");
8870                         aopPut(AOP(result),"a",offset++);
8871                         if (size)
8872                                 pic14_emitcode("inc","dptr");
8873                 }
8874         }
8875         
8876         freeAsmop(result,NULL,ic,TRUE);
8877 }
8878 #endif
8879
8880 #if 0
8881 /*-----------------------------------------------------------------*/
8882 /* genCodePointerGet - get value from code space                  */
8883 /*-----------------------------------------------------------------*/
8884 static void genCodePointerGet (operand *left,
8885                                                            operand *result, iCode *ic)
8886 {
8887         int size, offset ;
8888         sym_link *retype = getSpec(operandType(result));
8889         
8890         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8891         
8892         aopOp(left,ic,FALSE);
8893         
8894         /* if the operand is already in dptr 
8895         then we do nothing else we move the value to dptr */
8896         if (AOP_TYPE(left) != AOP_STR) {
8897                 /* if this is remateriazable */
8898                 if (AOP_TYPE(left) == AOP_IMMD)
8899                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8900                 else { /* we need to get it byte by byte */
8901                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8902                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8903                         if (options.model == MODEL_FLAT24)
8904                         {
8905                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8906                         }
8907                 }
8908         }
8909         /* so dptr know contains the address */
8910         freeAsmop(left,NULL,ic,TRUE);
8911         aopOp(result,ic,FALSE);
8912         
8913         /* if bit then unpack */
8914         if (IS_BITFIELD(retype)) 
8915                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8916         else {
8917                 size = AOP_SIZE(result);
8918                 offset = 0 ;
8919                 
8920                 while (size--) {
8921                         pic14_emitcode("clr","a");
8922                         pic14_emitcode("movc","a,@a+dptr");
8923                         aopPut(AOP(result),"a",offset++);
8924                         if (size)
8925                                 pic14_emitcode("inc","dptr");
8926                 }
8927         }
8928         
8929         freeAsmop(result,NULL,ic,TRUE);
8930 }
8931 #endif
8932 /*-----------------------------------------------------------------*/
8933 /* genGenPointerGet - gget value from generic pointer space        */
8934 /*-----------------------------------------------------------------*/
8935 static void genGenPointerGet (operand *left,
8936                                                           operand *result, iCode *ic)
8937 {
8938         FENTRY;
8939         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8940         aopOp(left,ic,FALSE);
8941         aopOp(result,ic,FALSE);
8942         
8943         
8944         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8945
8946         if (IS_BITFIELD(getSpec(operandType(result))))
8947         {
8948           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8949           return;
8950         }
8951
8952         {
8953           /* emit call to __gptrget */
8954           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8955           int size = AOP_SIZE(result);
8956           int idx = 0;
8957
8958           assert (size > 0 && size <= 4);
8959
8960           /* pass arguments */
8961           assert (AOP_SIZE(left) == 3);
8962           mov2w(AOP(left), 0);
8963           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8964           mov2w(AOP(left), 1);
8965           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8966           mov2w(AOP(left), 2);
8967           call_libraryfunc (func[size]);
8968           
8969           /* save result */
8970           movwf (AOP(result), --size);
8971           while (size--) {
8972             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8973             movwf (AOP(result), size);
8974           } // while
8975         }
8976         
8977         freeAsmop(left,NULL,ic,TRUE);
8978         freeAsmop(result,NULL,ic,TRUE);
8979         
8980 }
8981
8982 /*-----------------------------------------------------------------*/
8983 /* genConstPointerGet - get value from const generic pointer space */
8984 /*-----------------------------------------------------------------*/
8985 static void genConstPointerGet (operand *left,
8986                                                                 operand *result, iCode *ic)
8987 {
8988         //sym_link *retype = getSpec(operandType(result));
8989         #if 0
8990         symbol *albl, *blbl;//, *clbl;
8991         pCodeOp *pcop;
8992         #endif
8993         PIC_OPCODE poc;
8994         int i, size, lit;
8995         
8996         FENTRY;
8997         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8998         aopOp(left,ic,FALSE);
8999         aopOp(result,ic,FALSE);
9000         
9001         size = AOP_SIZE(result);
9002         
9003         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9004         
9005         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9006
9007         lit = op_isLitLike (left);
9008         poc = lit ? POC_MOVLW : POC_MOVFW;
9009
9010         if (IS_BITFIELD(getSpec(operandType(result))))
9011         {
9012                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9013                 goto release;
9014         }
9015
9016         {
9017                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9018                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9019                 assert (size > 0 && size <= 4);
9020                 
9021                 mov2w_op(left, 0);
9022                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9023                 mov2w_op(left, 1);
9024                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9025                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9026                 call_libraryfunc (func[size]);
9027
9028                 movwf(AOP(result),size-1);
9029                 for (i = 1; i < size; i++)
9030                 {
9031                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9032                         movwf(AOP(result),size - 1 - i);
9033                 } // for
9034         }
9035         
9036 release:
9037         freeAsmop(left,NULL,ic,TRUE);
9038         freeAsmop(result,NULL,ic,TRUE);
9039         
9040 }
9041 /*-----------------------------------------------------------------*/
9042 /* genPointerGet - generate code for pointer get                   */
9043 /*-----------------------------------------------------------------*/
9044 static void genPointerGet (iCode *ic)
9045 {
9046         operand *left, *result ;
9047         sym_link *type, *etype;
9048         int p_type = -1;
9049         
9050         FENTRY;
9051         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9052         
9053         left = IC_LEFT(ic);
9054         result = IC_RESULT(ic) ;
9055         
9056         /* depending on the type of pointer we need to
9057         move it to the correct pointer register */
9058         type = operandType(left);
9059         etype = getSpec(type);
9060         
9061         if (IS_PTR_CONST(type))
9062                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9063         
9064         /* if left is of type of pointer then it is simple */
9065         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9066                 p_type = DCL_TYPE(type);
9067         else {
9068                 /* we have to go by the storage class */
9069                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9070                 
9071                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9072                 
9073                 if (SPEC_OCLS(etype)->codesp ) {
9074                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9075                         //p_type = CPOINTER ; 
9076                 }
9077                 else
9078                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9079                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9080                         /*p_type = FPOINTER ;*/ 
9081                         else
9082                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9083                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9084                                 /*        p_type = PPOINTER; */
9085                                 else
9086                                         if (SPEC_OCLS(etype) == idata )
9087                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9088                                         /*      p_type = IPOINTER; */
9089                                         else
9090                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9091                                         /*      p_type = POINTER ; */
9092         }
9093         
9094         /* now that we have the pointer type we assign
9095         the pointer values */
9096         switch (p_type) {
9097                 
9098         case POINTER: 
9099         case FPOINTER:
9100         //case IPOINTER:
9101                 genNearPointerGet (left,result,ic);
9102                 break;
9103 /*
9104         case PPOINTER:
9105                 genPagedPointerGet(left,result,ic);
9106                 break;
9107                 
9108         case FPOINTER:
9109                 genFarPointerGet (left,result,ic);
9110                 break;
9111 */              
9112         case CPOINTER:
9113                 genConstPointerGet (left,result,ic);
9114                 break;
9115                 
9116         case GPOINTER:
9117                 genGenPointerGet (left,result,ic);
9118                 break;
9119         default:
9120                 assert ( !"unhandled pointer type" );
9121                 break;
9122         }
9123         
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* genPackBits - generates code for packed bit storage             */
9128 /*-----------------------------------------------------------------*/
9129 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9130 {
9131   int blen;             /* bitfield length */
9132   int bstr;             /* bitfield starting bit within byte */
9133   int litval;           /* source literal value (if AOP_LIT) */
9134   unsigned char mask;   /* bitmask within current byte */
9135
9136   FENTRY;
9137   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9138
9139   blen = SPEC_BLEN (etype);
9140   bstr = SPEC_BSTR (etype);
9141
9142   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9143   if ((blen <= 8) && ((bstr + blen) <= 8))
9144   {
9145     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9146             (unsigned char) (0xFF >> (8 - bstr)));
9147
9148     if (AOP_TYPE (right) == AOP_LIT)
9149     {
9150       /* Case with a bitfield length <8 and literal source */
9151       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9152       if (blen == 1) {
9153         pCodeOp *pcop;
9154         
9155         switch (p_type)
9156         {
9157         case -1:
9158           if (AOP(result)->type == AOP_PCODE)
9159             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9160           else
9161             pcop = popGet(AOP(result),0);
9162           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9163           break;
9164         
9165         case POINTER:
9166         case FPOINTER:
9167           setup_fsr (result);
9168           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9169           break;
9170         
9171         case CPOINTER:
9172           assert( !"trying to assign to bitfield via pointer to __code space" );
9173           break;
9174         
9175         case GPOINTER:
9176           emitPtrByteGet(result, p_type, FALSE);
9177           if (lit) {
9178             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9179           } else {
9180             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9181           }
9182           emitPtrByteSet(result, p_type, TRUE);
9183           break;
9184         
9185         default:
9186           assert( !"unhandled pointer type" );
9187           break;
9188         } // switch (p_type)
9189       } else {
9190         /* blen > 1 */
9191         litval = lit << bstr;
9192         litval &= (~mask) & 0x00ff;
9193         
9194         switch (p_type)
9195         {
9196         case -1:
9197           mov2w (AOP(result), 0);
9198           if ((litval|mask) != 0x00ff)
9199             emitpcode(POC_ANDLW, popGetLit (mask));
9200           if (litval != 0x00)
9201             emitpcode(POC_IORLW, popGetLit (litval));
9202           movwf (AOP(result), 0);
9203           break;
9204         
9205         case POINTER:
9206         case FPOINTER:
9207         case GPOINTER:
9208           emitPtrByteGet(result, p_type, FALSE);
9209           if ((litval|mask) != 0x00ff)
9210             emitpcode(POC_ANDLW, popGetLit (mask));
9211           if (litval != 0x00)
9212             emitpcode(POC_IORLW, popGetLit (litval));
9213           emitPtrByteSet(result, p_type, TRUE);
9214           break;
9215         
9216         case CPOINTER:
9217           assert( !"trying to assign to bitfield via pointer to __code space" );
9218           break;
9219         
9220         default:
9221           assert( !"unhandled pointer type" );
9222           break;
9223         } // switch
9224       } // if (blen > 1)
9225     }
9226     else
9227     {
9228       /* right is no literal */
9229       if (blen==1) {
9230         switch (p_type)
9231         {
9232         case -1:
9233           /* Note more efficient code, of pre clearing bit then only setting it if required,
9234            * can only be done if it is known that the result is not a SFR */
9235           emitpcode(POC_RRFW,popGet(AOP(right),0));
9236           emitSKPC;
9237           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9238           emitSKPNC;
9239           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9240           break;
9241         
9242         case POINTER:
9243         case FPOINTER:
9244         case GPOINTER:
9245           emitPtrByteGet (result, p_type, FALSE);
9246           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9247           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9248           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9249           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9250           emitPtrByteSet (result, p_type, TRUE);
9251           break;
9252         
9253         case CPOINTER:
9254           assert( !"trying to assign to bitfield via pointer to __code space" );
9255           break;
9256         
9257         default:
9258           assert( !"unhandled pointer type" );
9259           break;
9260         } // switch
9261         return;
9262       } else {
9263         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9264         pCodeOp *temp = popGetTempReg ();
9265
9266         mov2w (AOP(right), 0);
9267         if (blen < 8) {
9268           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9269         }
9270         emitpcode(POC_MOVWF, temp);
9271         if (bstr) {
9272           AccLsh (temp, bstr);
9273         }
9274         
9275         switch (p_type)
9276         {
9277         case -1:
9278           mov2w (AOP(result), 0);
9279           emitpcode(POC_ANDLW, popGetLit (mask));
9280           emitpcode(POC_IORFW, temp);
9281           movwf (AOP(result), 0);
9282           break;
9283         
9284         case POINTER:
9285         case FPOINTER:
9286         case GPOINTER:
9287           emitPtrByteGet (result, p_type, FALSE);
9288           emitpcode(POC_ANDLW, popGetLit (mask));
9289           emitpcode(POC_IORFW, temp);
9290           emitPtrByteSet (result, p_type, TRUE);
9291           break;
9292         
9293         case CPOINTER:
9294           assert( !"trying to assign to bitfield via pointer to __code space" );
9295           break;
9296         
9297         default:
9298           assert( !"unhandled pointer type" );
9299           break;
9300         } // switch
9301
9302         popReleaseTempReg (temp);
9303       } // if (blen > 1)
9304     } // if (AOP(right)->type != AOP_LIT)
9305     return;
9306   } // if (blen <= 8 && ((blen + bstr) <= 8))
9307
9308   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9309 }
9310
9311 /*-----------------------------------------------------------------*/
9312 /* genDataPointerSet - remat pointer to data space                 */
9313 /*-----------------------------------------------------------------*/
9314 static void genDataPointerSet(operand *right,
9315         operand *result,
9316         iCode *ic)
9317 {
9318         int size, offset = 0 ;
9319         int ressize;
9320         
9321         FENTRY;
9322         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9323         aopOp(right,ic,FALSE);
9324         aopOp(result,ic,FALSE);
9325         
9326         assert (IS_SYMOP(result));
9327         assert (IS_PTR(OP_SYM_TYPE(result)));
9328         
9329         if (AOP_TYPE(right) == AOP_LIT)
9330           size = 4;
9331         else
9332           size = AOP_SIZE(right);
9333         ressize = getSize(OP_SYM_ETYPE(result));
9334         if (size > ressize) size = ressize;
9335         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9336         
9337         //assert( !"what's going on here?" );
9338
9339         /*
9340         if ( AOP_TYPE(result) == AOP_PCODE) {
9341         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9342         AOP(result)->aopu.pcop->name,
9343         PCOI(AOP(result)->aopu.pcop)->offset);
9344         }
9345         */
9346         
9347         // tsd, was l+1 - the underline `_' prefix was being stripped
9348         while (size--) {
9349                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9350                 
9351                 if (AOP_TYPE(right) == AOP_LIT) {
9352                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9353                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9354                         if(lit&0xff) {
9355                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9356                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9357                         } else {
9358                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9359                         }
9360                 } else {
9361                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9362                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9363                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9364                 }
9365                 
9366                 offset++;
9367         }
9368         
9369         freeAsmop(right,NULL,ic,TRUE);
9370         freeAsmop(result,NULL,ic,TRUE);
9371 }
9372
9373 /*-----------------------------------------------------------------*/
9374 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9375 /*-----------------------------------------------------------------*/
9376 static void genNearPointerSet (operand *right,
9377                                                            operand *result, 
9378                                                            iCode *ic)
9379 {
9380         asmop *aop = NULL;
9381         sym_link *ptype = operandType(result);
9382         sym_link *retype = getSpec(operandType(right));
9383         sym_link *letype = getSpec(ptype);
9384         int direct = 0;
9385         
9386         
9387         FENTRY;
9388         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9389         aopOp(result,ic,FALSE);
9390         
9391 #if 1
9392         /* if the result is rematerializable &
9393         in data space & not a bit variable */
9394         //if (AOP_TYPE(result) == AOP_IMMD &&
9395         if (AOP_TYPE(result) == AOP_PCODE &&
9396                 PIC_IS_DATA_PTR(ptype) &&
9397                 !IS_BITVAR (retype) &&
9398                 !IS_BITVAR (letype)) {
9399                 genDataPointerSet (right,result,ic);
9400                 freeAsmop(result,NULL,ic,TRUE);
9401                 return;
9402         }
9403 #endif
9404
9405         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9406         aopOp(right,ic,FALSE);
9407         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9408         
9409         /* Check if can access directly instead of via a pointer */
9410         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9411                 direct = 1;
9412         }
9413         
9414         if (IS_BITFIELD (letype))
9415         {
9416           genPackBits (letype, result, right, direct?-1:POINTER);
9417           return;
9418         }
9419         
9420         /* If the pointer value is not in a the FSR then need to put it in */
9421         /* Must set/reset IRP bit for use with FSR. */
9422         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9423         if (!direct)
9424                 setup_fsr (result);
9425
9426         {
9427                 /* we have can just get the values */
9428                 int size = AOP_SIZE(right);
9429                 int offset = 0 ;    
9430                 
9431                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9432                 while (size--) {
9433                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9434                         if (*l == '@' ) {
9435                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9436                         } else {
9437                                 if (AOP_TYPE(right) == AOP_LIT) {
9438                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9439                                 } else {
9440                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9441                                 }
9442                                 if (direct)
9443                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9444                                 else
9445                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9446                         }
9447                         if (size && !direct)
9448                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9449                         offset++;
9450                 }
9451         }
9452         
9453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9454         /* now some housekeeping stuff */
9455         if (aop) {
9456                 /* we had to allocate for this iCode */
9457                 freeAsmop(NULL,aop,ic,TRUE);
9458         } else { 
9459                 /* we did not allocate which means left
9460                 already in a pointer register, then
9461                 if size > 0 && this could be used again
9462                 we have to point it back to where it 
9463                 belongs */
9464                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9465                 if (AOP_SIZE(right) > 1 &&
9466                         !OP_SYMBOL(result)->remat &&
9467                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9468                         ic->depth )) {
9469                         int size = AOP_SIZE(right) - 1;
9470                         while (size--)
9471                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9472                 }
9473         }
9474         
9475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9476         /* done */
9477
9478         freeAsmop(right,NULL,ic,TRUE);
9479         freeAsmop(result,NULL,ic,TRUE);
9480 }
9481
9482 #if 0
9483 /*-----------------------------------------------------------------*/
9484 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9485 /*-----------------------------------------------------------------*/
9486 static void genPagedPointerSet (operand *right,
9487                                                                 operand *result, 
9488                                                                 iCode *ic)
9489 {
9490         asmop *aop = NULL;
9491         regs *preg = NULL ;
9492         char *rname , *l;
9493         sym_link *retype;
9494         
9495         FENTRY;
9496         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497         
9498         retype= getSpec(operandType(right));
9499         
9500         aopOp(result,ic,FALSE);
9501         
9502         /* if the value is already in a pointer register
9503         then don't need anything more */
9504         if (!AOP_INPREG(AOP(result))) {
9505                 /* otherwise get a free pointer register */
9506                 aop = newAsmop(0);
9507                 preg = getFreePtr(ic,&aop,FALSE);
9508                 pic14_emitcode("mov","%s,%s",
9509                         preg->name,
9510                         aopGet(AOP(result),0,FALSE,TRUE));
9511                 rname = preg->name ;
9512         } else
9513                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9514         
9515         freeAsmop(result,NULL,ic,TRUE);
9516         aopOp (right,ic,FALSE);
9517         
9518         /* if bitfield then unpack the bits */
9519         if (IS_BITFIELD(retype)) 
9520                 genPackBits (retype,result,right,rname,PPOINTER);
9521         else {
9522                 /* we have can just get the values */
9523                 int size = AOP_SIZE(right);
9524                 int offset = 0 ;  
9525                 
9526                 while (size--) {
9527                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9528                         
9529                         MOVA(l);
9530                         pic14_emitcode("movx","@%s,a",rname);
9531                         
9532                         if (size)
9533                                 pic14_emitcode("inc","%s",rname);
9534                         
9535                         offset++;
9536                 }
9537         }
9538         
9539         /* now some housekeeping stuff */
9540         if (aop) {
9541                 /* we had to allocate for this iCode */
9542                 freeAsmop(NULL,aop,ic,TRUE);
9543         } else { 
9544         /* we did not allocate which means left
9545         already in a pointer register, then
9546         if size > 0 && this could be used again
9547         we have to point it back to where it 
9548                 belongs */
9549                 if (AOP_SIZE(right) > 1 &&
9550                         !OP_SYMBOL(result)->remat &&
9551                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9552                         ic->depth )) {
9553                         int size = AOP_SIZE(right) - 1;
9554                         while (size--)
9555                                 pic14_emitcode("dec","%s",rname);
9556                 }
9557         }
9558         
9559         /* done */
9560         freeAsmop(right,NULL,ic,TRUE);
9561         
9562         
9563 }
9564
9565 /*-----------------------------------------------------------------*/
9566 /* genFarPointerSet - set value from far space                     */
9567 /*-----------------------------------------------------------------*/
9568 static void genFarPointerSet (operand *right,
9569                                                           operand *result, iCode *ic)
9570 {
9571         int size, offset ;
9572         sym_link *retype = getSpec(operandType(right));
9573         
9574         FENTRY;
9575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9576         aopOp(result,ic,FALSE);
9577         
9578         /* if the operand is already in dptr 
9579         then we do nothing else we move the value to dptr */
9580         if (AOP_TYPE(result) != AOP_STR) {
9581                 /* if this is remateriazable */
9582                 if (AOP_TYPE(result) == AOP_IMMD)
9583                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9584                 else { /* we need to get it byte by byte */
9585                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9586                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9587                         if (options.model == MODEL_FLAT24)
9588                         {
9589                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9590                         }
9591                 }
9592         }
9593         /* so dptr know contains the address */
9594         freeAsmop(result,NULL,ic,TRUE);
9595         aopOp(right,ic,FALSE);
9596         
9597         /* if bit then unpack */
9598         if (IS_BITFIELD(retype)) 
9599                 genPackBits(retype,result,right,"dptr",FPOINTER);
9600         else {
9601                 size = AOP_SIZE(right);
9602                 offset = 0 ;
9603                 
9604                 while (size--) {
9605                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9606                         MOVA(l);
9607                         pic14_emitcode("movx","@dptr,a");
9608                         if (size)
9609                                 pic14_emitcode("inc","dptr");
9610                 }
9611         }
9612         
9613         freeAsmop(right,NULL,ic,TRUE);
9614 }
9615 #endif
9616
9617 /*-----------------------------------------------------------------*/
9618 /* genGenPointerSet - set value from generic pointer space         */
9619 /*-----------------------------------------------------------------*/
9620 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9621 {
9622         sym_link *retype = getSpec(operandType(result));
9623         
9624         FENTRY;
9625         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9626         aopOp(right,ic,FALSE);
9627         aopOp(result,ic,FALSE);
9628
9629         
9630         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9631
9632         if (IS_BITFIELD(retype))
9633         {
9634           genPackBits (retype, result, right, GPOINTER);
9635           return;
9636         }
9637
9638         {
9639           /* emit call to __gptrput */
9640           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9641           int size = AOP_SIZE(right);
9642           int idx = 0;
9643
9644           /* The following assertion fails for
9645            *   struct foo { char a; char b; } bar;
9646            *   void demo(struct foo *dst, char c) { dst->b = c; }
9647            * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9648            * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9649            * of size 2.
9650            * The frontend seems to guarantee that IC_LEFT has the correct size,
9651            * it works fine both for larger and smaller types of `char c'.
9652            * */
9653           //assert (size == getSize(OP_SYM_ETYPE(result)));
9654           assert (size > 0 && size <= 4);
9655
9656           /* pass arguments */
9657           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9658           {
9659             int off = size;
9660             idx = 2;
9661             while (off--)
9662             {
9663               mov2w_op (right, off);
9664               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9665             }
9666             idx = 0;
9667           }
9668           /* - address */
9669           assert (AOP_SIZE(result) == 3);
9670           mov2w(AOP(result), 0);
9671           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9672           mov2w(AOP(result), 1);
9673           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9674           mov2w(AOP(result), 2);
9675           call_libraryfunc (func[size]);
9676         }
9677         
9678         freeAsmop(right,NULL,ic,TRUE);
9679         freeAsmop(result,NULL,ic,TRUE);
9680 }
9681
9682 /*-----------------------------------------------------------------*/
9683 /* genPointerSet - stores the value into a pointer location        */
9684 /*-----------------------------------------------------------------*/
9685 static void genPointerSet (iCode *ic)
9686 {    
9687         operand *right, *result ;
9688         sym_link *type, *etype;
9689         int p_type;
9690         
9691         FENTRY;
9692         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9693         
9694         right = IC_RIGHT(ic);
9695         result = IC_RESULT(ic) ;
9696         
9697         /* depending on the type of pointer we need to
9698         move it to the correct pointer register */
9699         type = operandType(result);
9700         etype = getSpec(type);
9701         /* if left is of type of pointer then it is simple */
9702         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9703                 p_type = DCL_TYPE(type);
9704         }
9705         else {
9706                 /* we have to go by the storage class */
9707                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9708                 
9709                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9710                 /*      p_type = CPOINTER ;  */
9711                 /*  } */
9712                 /*  else */
9713                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9714                 /*    p_type = FPOINTER ; */
9715                 /*      else */
9716                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9717                 /*        p_type = PPOINTER ; */
9718                 /*    else */
9719                 /*        if (SPEC_OCLS(etype) == idata ) */
9720                 /*      p_type = IPOINTER ; */
9721                 /*        else */
9722                 /*      p_type = POINTER ; */
9723         }
9724         
9725         /* now that we have the pointer type we assign
9726         the pointer values */
9727         switch (p_type) {
9728                 
9729         case POINTER:
9730         case FPOINTER:
9731         //case IPOINTER:
9732                 genNearPointerSet (right,result,ic);
9733                 break;
9734 /*
9735         case PPOINTER:
9736                 genPagedPointerSet (right,result,ic);
9737                 break;
9738                 
9739         case FPOINTER:
9740                 genFarPointerSet (right,result,ic);
9741                 break;
9742 */
9743         case GPOINTER:
9744                 genGenPointerSet (right,result,ic);
9745                 break;
9746                 
9747         default:
9748                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9749                         "genPointerSet: illegal pointer type");
9750         }
9751 }
9752
9753 /*-----------------------------------------------------------------*/
9754 /* genIfx - generate code for Ifx statement                        */
9755 /*-----------------------------------------------------------------*/
9756 static void genIfx (iCode *ic, iCode *popIc)
9757 {
9758         operand *cond = IC_COND(ic);
9759         int isbit =0;
9760         
9761         FENTRY;
9762         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9763         
9764         aopOp(cond,ic,FALSE);
9765         
9766         /* get the value into acc */
9767         if (AOP_TYPE(cond) != AOP_CRY)
9768                 pic14_toBoolean(cond);
9769         else
9770                 isbit = 1;
9771         
9772         /* if there was something to be popped then do it */
9773         if (popIc)
9774                 genIpop(popIc);
9775         
9776         if (isbit)
9777         {
9778                 /* This assumes that CARRY is set iff cond is true */
9779                 if (IC_TRUE(ic))
9780                 {
9781                         assert (!IC_FALSE(ic));
9782                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9783                         //emitSKPNC;
9784                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9785                 } else {
9786                         assert (IC_FALSE(ic));
9787                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9788                         //emitSKPC;
9789                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9790                 }
9791                 if (0)
9792                 {
9793                         static int hasWarned = 0;
9794                         if (!hasWarned)
9795                         {
9796                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9797                                 hasWarned = 1;
9798                         }
9799                 }
9800         }
9801         else
9802         {
9803                 /* now Z is set iff !cond */
9804                 if (IC_TRUE(ic))
9805                 {
9806                         assert (!IC_FALSE(ic));
9807                         emitSKPZ;
9808                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9809                 } else {
9810                         emitSKPNZ;
9811                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9812                 }
9813         }
9814         
9815         ic->generated = 1;
9816         
9817         /* the result is now in the accumulator */
9818         freeAsmop(cond,NULL,ic,TRUE);
9819 }
9820
9821 /*-----------------------------------------------------------------*/
9822 /* genAddrOf - generates code for address of                       */
9823 /*-----------------------------------------------------------------*/
9824 static void genAddrOf (iCode *ic)
9825 {
9826         operand *right, *result, *left;
9827         int size, offset ;
9828         
9829         FENTRY;
9830         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9831         
9832         
9833         //aopOp(IC_RESULT(ic),ic,FALSE);
9834         
9835         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9836         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9837         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9838         
9839         DEBUGpic14_AopType(__LINE__,left,right,result);
9840         assert (IS_SYMOP (left));
9841         
9842         /* sanity check: generic pointers to code space are not yet supported,
9843          * pionters to codespace must not be assigned addresses of __data values. */
9844  #if 0
9845         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9846         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)));
9847         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)));
9848         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)));
9849         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)));
9850 #endif
9851
9852         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9853           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9854                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9855                 OP_SYMBOL(left)->name);
9856         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9857           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9858                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9859                 OP_SYMBOL(left)->name);
9860         }
9861         
9862         size = AOP_SIZE(IC_RESULT(ic));
9863         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9864                 /* strip tag */
9865                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9866         }
9867         offset = 0;
9868         
9869         while (size--) {
9870                 /* fixing bug #863624, reported from (errolv) */
9871                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9872                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9873                 
9874 #if 0
9875                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9876                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9877 #endif
9878                 offset++;
9879         }
9880
9881         if (IS_GENPTR(OP_SYM_TYPE(result)))
9882         {
9883                 /* provide correct tag */
9884                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9885                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9886                 movwf (AOP(result), 2);
9887         }
9888         
9889         freeAsmop(left,NULL,ic,FALSE);
9890         freeAsmop(result,NULL,ic,TRUE);
9891         
9892 }
9893
9894 #if 0
9895 /*-----------------------------------------------------------------*/
9896 /* genFarFarAssign - assignment when both are in far space         */
9897 /*-----------------------------------------------------------------*/
9898 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9899 {
9900         int size = AOP_SIZE(right);
9901         int offset = 0;
9902         char *l ;
9903         /* first push the right side on to the stack */
9904         while (size--) {
9905                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9906                 MOVA(l);
9907                 pic14_emitcode ("push","acc");
9908         }
9909         
9910         freeAsmop(right,NULL,ic,FALSE);
9911         /* now assign DPTR to result */
9912         aopOp(result,ic,FALSE);
9913         size = AOP_SIZE(result);
9914         while (size--) {
9915                 pic14_emitcode ("pop","acc");
9916                 aopPut(AOP(result),"a",--offset);
9917         }
9918         freeAsmop(result,NULL,ic,FALSE);
9919         
9920 }
9921 #endif
9922
9923 /*-----------------------------------------------------------------*/
9924 /* genAssign - generate code for assignment                        */
9925 /*-----------------------------------------------------------------*/
9926 static void genAssign (iCode *ic)
9927 {
9928         operand *result, *right;
9929         int size, offset,know_W;
9930         unsigned long lit = 0L;
9931         
9932         result = IC_RESULT(ic);
9933         right  = IC_RIGHT(ic) ;
9934         
9935         FENTRY;
9936         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9937         
9938         /* if they are the same */
9939         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9940                 return ;
9941         
9942         aopOp(right,ic,FALSE);
9943         aopOp(result,ic,TRUE);
9944         
9945         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9946         
9947         /* if they are the same registers */
9948         if (pic14_sameRegs(AOP(right),AOP(result)))
9949                 goto release;
9950
9951         /* special case: assign from __code */
9952         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9953                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9954                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9955                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9956                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9957         {
9958           emitpComment ("genAssign from CODESPACE");
9959           genConstPointerGet (right, result, ic);
9960           goto release;
9961         }
9962         
9963         /* just for symmetry reasons... */
9964         if (!IS_ITEMP(result)
9965                 && IS_SYMOP (result)
9966                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9967         {
9968           assert ( !"cannot write to CODESPACE" );
9969         }
9970
9971         /* if the result is a bit */
9972         if (AOP_TYPE(result) == AOP_CRY) {
9973                 
9974         /* if the right size is a literal then
9975                 we know what the value is */
9976                 if (AOP_TYPE(right) == AOP_LIT) {
9977                         
9978                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9979                                 popGet(AOP(result),0));
9980                         
9981                         if (((int) operandLitValue(right))) 
9982                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9983                                 AOP(result)->aopu.aop_dir,
9984                                 AOP(result)->aopu.aop_dir);
9985                         else
9986                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9987                                 AOP(result)->aopu.aop_dir,
9988                                 AOP(result)->aopu.aop_dir);
9989                         goto release;
9990                 }
9991                 
9992                 /* the right is also a bit variable */
9993                 if (AOP_TYPE(right) == AOP_CRY) {
9994                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9995                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9996                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9997                         
9998                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9999                                 AOP(result)->aopu.aop_dir,
10000                                 AOP(result)->aopu.aop_dir);
10001                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10002                                 AOP(right)->aopu.aop_dir,
10003                                 AOP(right)->aopu.aop_dir);
10004                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10005                                 AOP(result)->aopu.aop_dir,
10006                                 AOP(result)->aopu.aop_dir);
10007                         goto release ;
10008                 }
10009                 
10010                 /* we need to or */
10011                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10012                 pic14_toBoolean(right);
10013                 emitSKPZ;
10014                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10015                 //aopPut(AOP(result),"a",0);
10016                 goto release ;
10017         }
10018         
10019         /* bit variables done */
10020         /* general case */
10021         size = AOP_SIZE(result);
10022         offset = 0 ;
10023         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10024                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10025                 if(aopIdx(AOP(result),0) == 4) {
10026                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10027                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10028                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10029                         goto release;
10030                 } else
10031                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10032         }
10033         
10034         know_W=-1;
10035         while (size--) {
10036         
10037                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10038                 if(AOP_TYPE(right) == AOP_LIT) {
10039                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10040                         if(lit&0xff) {
10041                                 if(know_W != (int)(lit&0xff))
10042                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10043                                 know_W = lit&0xff;
10044                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10045                         } else
10046                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10047                         
10048                 } else if (AOP_TYPE(right) == AOP_CRY) {
10049                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10050                         if(offset == 0) {
10051                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10052                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10053                         }
10054                 } else {
10055                         mov2w_op (right, offset);
10056                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10057                 }
10058                 
10059                 offset++;
10060         }
10061         
10062         
10063 release:
10064         freeAsmop (right,NULL,ic,FALSE);
10065         freeAsmop (result,NULL,ic,TRUE);
10066 }   
10067
10068 /*-----------------------------------------------------------------*/
10069 /* genJumpTab - genrates code for jump table                       */
10070 /*-----------------------------------------------------------------*/
10071 static void genJumpTab (iCode *ic)
10072 {
10073         symbol *jtab;
10074         char *l;
10075         
10076         FENTRY;
10077         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10078         
10079         aopOp(IC_JTCOND(ic),ic,FALSE);
10080         /* get the condition into accumulator */
10081         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10082         MOVA(l);
10083         /* multiply by three */
10084         pic14_emitcode("add","a,acc");
10085         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10086         
10087         jtab = newiTempLabel(NULL);
10088         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10089         pic14_emitcode("jmp","@a+dptr");
10090         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10091         
10092         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10093         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10094         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10095         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10096         emitSKPNC;
10097         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10098         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10099         emitpLabel(jtab->key);
10100         
10101         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10102         
10103         /* now generate the jump labels */
10104         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10105         jtab = setNextItem(IC_JTLABELS(ic))) {
10106                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10107                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10108                 
10109         }
10110         
10111 }
10112
10113 /*-----------------------------------------------------------------*/
10114 /* genMixedOperation - gen code for operators between mixed types  */
10115 /*-----------------------------------------------------------------*/
10116 /*
10117 TSD - Written for the PIC port - but this unfortunately is buggy.
10118 This routine is good in that it is able to efficiently promote 
10119 types to different (larger) sizes. Unfortunately, the temporary
10120 variables that are optimized out by this routine are sometimes
10121 used in other places. So until I know how to really parse the 
10122 iCode tree, I'm going to not be using this routine :(.
10123 */
10124 static int genMixedOperation (iCode *ic)
10125 {
10126         FENTRY;
10127 #if 0
10128         operand *result = IC_RESULT(ic);
10129         sym_link *ctype = operandType(IC_LEFT(ic));
10130         operand *right = IC_RIGHT(ic);
10131         int ret = 0;
10132         int big,small;
10133         int offset;
10134         
10135         iCode *nextic;
10136         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10137         
10138         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10139         
10140         nextic = ic->next;
10141         if(!nextic)
10142                 return 0;
10143         
10144         nextright = IC_RIGHT(nextic);
10145         nextleft  = IC_LEFT(nextic);
10146         nextresult = IC_RESULT(nextic);
10147         
10148         aopOp(right,ic,FALSE);
10149         aopOp(result,ic,FALSE);
10150         aopOp(nextright,  nextic, FALSE);
10151         aopOp(nextleft,   nextic, FALSE);
10152         aopOp(nextresult, nextic, FALSE);
10153         
10154         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10155                 
10156                 operand *t = right;
10157                 right = nextright;
10158                 nextright = t; 
10159                 
10160                 pic14_emitcode(";remove right +","");
10161                 
10162         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10163         /*
10164         operand *t = right;
10165         right = nextleft;
10166         nextleft = t; 
10167                 */
10168                 pic14_emitcode(";remove left +","");
10169         } else
10170                 return 0;
10171         
10172         big = AOP_SIZE(nextleft);
10173         small = AOP_SIZE(nextright);
10174         
10175         switch(nextic->op) {
10176                 
10177         case '+':
10178                 pic14_emitcode(";optimize a +","");
10179                 /* if unsigned or not an integral type */
10180                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10181                         pic14_emitcode(";add a bit to something","");
10182                 } else {
10183                         
10184                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10185                         
10186                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10187                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10188                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10189                         } else
10190                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10191                         
10192                         offset = 0;
10193                         while(--big) {
10194                                 
10195                                 offset++;
10196                                 
10197                                 if(--small) {
10198                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10199                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10200                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10201                                         }
10202                                         
10203                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10204                                         emitSKPNC;
10205                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10206                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10207                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10208                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10209                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10210                                         
10211                                 } else {
10212                                         pic14_emitcode("rlf","known_zero,w");
10213                                         
10214                                         /*
10215                                         if right is signed
10216                                         btfsc  right,7
10217                                         addlw ff
10218                                         */
10219                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10220                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10221                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10222                                         } else {
10223                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10224                                         }
10225                                 }
10226                         }
10227                         ret = 1;
10228                 }
10229         }
10230         ret = 1;
10231         
10232 release:
10233         freeAsmop(right,NULL,ic,TRUE);
10234         freeAsmop(result,NULL,ic,TRUE);
10235         freeAsmop(nextright,NULL,ic,TRUE);
10236         freeAsmop(nextleft,NULL,ic,TRUE);
10237         if(ret)
10238                 nextic->generated = 1;
10239         
10240         return ret;
10241 #else
10242         return 0;
10243 #endif
10244 }
10245 /*-----------------------------------------------------------------*/
10246 /* genCast - gen code for casting                                  */
10247 /*-----------------------------------------------------------------*/
10248 static void genCast (iCode *ic)
10249 {
10250         operand *result = IC_RESULT(ic);
10251         sym_link *restype = operandType(result);
10252         sym_link *rtype = operandType(IC_RIGHT(ic));
10253         operand *right = IC_RIGHT(ic);
10254         int size, offset ;
10255         
10256         FENTRY;
10257         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10258         /* if they are equivalent then do nothing */
10259         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10260                 return ;
10261         
10262         aopOp(right,ic,FALSE) ;
10263         aopOp(result,ic,FALSE);
10264         
10265         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10266         
10267         /* if the result is a bit */
10268         if (AOP_TYPE(result) == AOP_CRY) {
10269                 assert(!"assigning to bit variables is not supported");
10270         }
10271         
10272         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10273                 int offset = 1;
10274                 size = AOP_SIZE(result);
10275                 
10276                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10277                 
10278                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10279                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10280                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10281                 
10282                 while (size--)
10283                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10284                 
10285                 goto release;
10286         }
10287         
10288         if (IS_PTR(restype))
10289         {
10290           operand *result = IC_RESULT(ic);
10291           //operand *left = IC_LEFT(ic);
10292           operand *right = IC_RIGHT(ic);
10293           int tag = 0xff;
10294           
10295           /* copy common part */
10296           int max, size = AOP_SIZE(result);
10297           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10298           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10299
10300           /* warn if we discard generic opinter tag */
10301           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10302           {
10303             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10304           } // if
10305
10306           max = size;
10307           while (size--)
10308           {
10309             mov2w_op (right, size);
10310             movwf (AOP(result), size);
10311           } // while
10312
10313           /* upcast into generic pointer type? */
10314           if (IS_GENPTR(restype)
10315                 && (size < AOP_SIZE(result))
10316                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10317           {
10318             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10319             if (IS_PTR(rtype))
10320             {
10321               switch (DCL_TYPE(rtype))
10322               {
10323               case POINTER:     /* __data */
10324               case FPOINTER:    /* __data */
10325                 assert (AOP_SIZE(right) == 2);
10326                 tag = GPTRTAG_DATA;
10327                 break;
10328
10329               case CPOINTER:    /* __code */
10330                 assert (AOP_SIZE(right) == 2);
10331                 tag = GPTRTAG_CODE;
10332                 break;
10333                 
10334               case GPOINTER:    /* unknown destination, __data or __code */
10335                 /* assume __data space (address of immediate) */
10336                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10337                 if (AOP(right)->code)
10338                   tag = GPTRTAG_CODE;
10339                 else
10340                   tag = GPTRTAG_DATA;
10341                 break;
10342                 
10343               default:
10344                 assert (!"unhandled pointer type");
10345               } // switch
10346             } else {
10347               /* convert other values into pointers to __data space */
10348               tag = GPTRTAG_DATA;
10349             }
10350
10351             assert (AOP_SIZE(result) == 3);
10352             if (tag == 0) {
10353               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10354             } else {
10355               emitpcode(POC_MOVLW, popGetLit(tag));
10356               movwf(AOP(result), 2);
10357             }
10358           } else {
10359             addSign(result, max, 0);
10360           } // if
10361           goto release;
10362         }
10363         
10364         /* if they are the same size : or less */
10365         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10366                 
10367                 /* if they are in the same place */
10368                 if (pic14_sameRegs(AOP(right),AOP(result)))
10369                         goto release;
10370                 
10371                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10372                 if (IS_PTR_CONST(rtype))
10373                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10374                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10375                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10376                 
10377                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10378                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10379                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10380                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10381                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10382                         if(AOP_SIZE(result) <2)
10383                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10384                         
10385                 } else {
10386                         
10387                         /* if they in different places then copy */
10388                         size = AOP_SIZE(result);
10389                         offset = 0 ;
10390                         while (size--) {
10391                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10392                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10393                                 
10394                                 //aopPut(AOP(result),
10395                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10396                                 // offset);
10397                                 
10398                                 offset++;
10399                         }
10400                 }
10401                 goto release;
10402         }
10403         
10404         /* so we now know that the size of destination is greater
10405         than the size of the source.
10406         Now, if the next iCode is an operator then we might be
10407         able to optimize the operation without performing a cast.
10408         */
10409         if(0 && genMixedOperation(ic)) {
10410                 /* XXX: cannot optimize: must copy regs! */
10411                 goto release;
10412         }
10413         
10414         /* we move to result for the size of source */
10415         size = AOP_SIZE(right);
10416         offset = 0 ;
10417         while (size--) {
10418                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10419                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10420                 offset++;
10421         }
10422
10423         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10424
10425 release:
10426         freeAsmop(right,NULL,ic,TRUE);
10427         freeAsmop(result,NULL,ic,TRUE);
10428         
10429 }
10430
10431 /*-----------------------------------------------------------------*/
10432 /* genDjnz - generate decrement & jump if not zero instrucion      */
10433 /*-----------------------------------------------------------------*/
10434 static int genDjnz (iCode *ic, iCode *ifx)
10435 {
10436         symbol *lbl, *lbl1;
10437         FENTRY;
10438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10439         
10440         if (!ifx)
10441                 return 0;
10442         
10443                 /* if the if condition has a false label
10444         then we cannot save */
10445         if (IC_FALSE(ifx))
10446                 return 0;
10447         
10448                 /* if the minus is not of the form 
10449         a = a - 1 */
10450         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10451                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10452                 return 0;
10453         
10454         if (operandLitValue(IC_RIGHT(ic)) != 1)
10455                 return 0;
10456         
10457                 /* if the size of this greater than one then no
10458         saving */
10459         if (getSize(operandType(IC_RESULT(ic))) > 1)
10460                 return 0;
10461         
10462         /* otherwise we can save BIG */
10463         lbl = newiTempLabel(NULL);
10464         lbl1= newiTempLabel(NULL);
10465         
10466         aopOp(IC_RESULT(ic),ic,FALSE);
10467         
10468         if (IS_AOP_PREG(IC_RESULT(ic))) {
10469                 pic14_emitcode("dec","%s",
10470                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10471                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10472                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10473         } else {  
10474                 
10475                 
10476                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10477                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10478                 
10479                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10480                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10481                 
10482         }
10483         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10484         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10485         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10486         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10487         
10488         
10489         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10490         ifx->generated = 1;
10491         return 1;
10492 }
10493
10494 /*-----------------------------------------------------------------*/
10495 /* genReceive - generate code for a receive iCode                  */
10496 /*-----------------------------------------------------------------*/
10497 static void genReceive (iCode *ic)
10498 {
10499         FENTRY;
10500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10501         
10502         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10503                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10504                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10505                 
10506                 int size = getSize(operandType(IC_RESULT(ic)));
10507                 int offset =  fReturnSizePic - size;
10508                 while (size--) {
10509                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10510                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10511                         offset++;
10512                 }
10513                 aopOp(IC_RESULT(ic),ic,FALSE);
10514                 size = AOP_SIZE(IC_RESULT(ic));
10515                 offset = 0;
10516                 while (size--) {
10517                         pic14_emitcode ("pop","acc");
10518                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10519                 }
10520                 
10521         } else {
10522                 _G.accInUse++;
10523                 aopOp(IC_RESULT(ic),ic,FALSE);
10524                 _G.accInUse--;
10525                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10526                 assignResultValue(IC_RESULT(ic));
10527         }
10528         
10529         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10530 }
10531
10532 /*-----------------------------------------------------------------*/
10533 /* genDummyRead - generate code for dummy read of volatiles        */
10534 /*-----------------------------------------------------------------*/
10535 static void
10536 genDummyRead (iCode * ic)
10537 {
10538         FENTRY;
10539         pic14_emitcode ("; genDummyRead","");
10540         pic14_emitcode ("; not implemented","");
10541         
10542         ic = ic;
10543 }
10544
10545 /*-----------------------------------------------------------------*/
10546 /* genpic14Code - generate code for pic14 based controllers        */
10547 /*-----------------------------------------------------------------*/
10548 /*
10549 * At this point, ralloc.c has gone through the iCode and attempted
10550 * to optimize in a way suitable for a PIC. Now we've got to generate
10551 * PIC instructions that correspond to the iCode.
10552 *
10553 * Once the instructions are generated, we'll pass through both the
10554 * peep hole optimizer and the pCode optimizer.
10555 *-----------------------------------------------------------------*/
10556
10557 void genpic14Code (iCode *lic)
10558 {
10559         iCode *ic;
10560         int cln = 0;
10561         const char *cline;
10562         
10563         FENTRY;
10564         lineHead = lineCurr = NULL;
10565         
10566         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10567         addpBlock(pb);
10568         
10569         /* if debug information required */
10570         if (options.debug && currFunc) { 
10571                 if (currFunc) {
10572                         debugFile->writeFunction (currFunc, lic);
10573                 }
10574         }
10575         
10576         
10577         for (ic = lic ; ic ; ic = ic->next ) {
10578                 
10579                 //DEBUGpic14_emitcode(";ic","");
10580                 //fprintf (stderr, "in ic loop\n");
10581                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10582                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10583                 
10584                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10585                   cln = ic->lineno;
10586                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10587                   cline = printCLine (ic->filename, ic->lineno);
10588                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10589                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10590                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10591                 }
10592                 
10593                 if (options.iCodeInAsm) {
10594                   char *iLine = printILine(ic);
10595                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10596                   dbuf_free(iLine);
10597                 }
10598                 /* if the result is marked as
10599                 spilt and rematerializable or code for
10600                 this has already been generated then
10601                 do nothing */
10602                 if (resultRemat(ic) || ic->generated ) 
10603                         continue ;
10604                 
10605                 /* depending on the operation */
10606                 switch (ic->op) {
10607                 case '!' :
10608                         genNot(ic);
10609                         break;
10610                         
10611                 case '~' :
10612                         genCpl(ic);
10613                         break;
10614                         
10615                 case UNARYMINUS:
10616                         genUminus (ic);
10617                         break;
10618                         
10619                 case IPUSH:
10620                         genIpush (ic);
10621                         break;
10622                         
10623                 case IPOP:
10624                         /* IPOP happens only when trying to restore a 
10625                         spilt live range, if there is an ifx statement
10626                         following this pop then the if statement might
10627                         be using some of the registers being popped which
10628                         would destory the contents of the register so
10629                         we need to check for this condition and handle it */
10630                         if (ic->next            && 
10631                                 ic->next->op == IFX &&
10632                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10633                                 genIfx (ic->next,ic);
10634                         else
10635                                 genIpop (ic);
10636                         break; 
10637                         
10638                 case CALL:
10639                         genCall (ic);
10640                         break;
10641                         
10642                 case PCALL:
10643                         genPcall (ic);
10644                         break;
10645                         
10646                 case FUNCTION:
10647                         genFunction (ic);
10648                         break;
10649                         
10650                 case ENDFUNCTION:
10651                         genEndFunction (ic);
10652                         break;
10653                         
10654                 case RETURN:
10655                         genRet (ic);
10656                         break;
10657                         
10658                 case LABEL:
10659                         genLabel (ic);
10660                         break;
10661                         
10662                 case GOTO:
10663                         genGoto (ic);
10664                         break;
10665                         
10666                 case '+' :
10667                         genPlus (ic) ;
10668                         break;
10669                         
10670                 case '-' :
10671                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10672                                 genMinus (ic);
10673                         break;
10674                         
10675                 case '*' :
10676                         genMult (ic);
10677                         break;
10678                         
10679                 case '/' :
10680                         genDiv (ic) ;
10681                         break;
10682                         
10683                 case '%' :
10684                         genMod (ic);
10685                         break;
10686                         
10687                 case '>' :
10688                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10689                         break;
10690                         
10691                 case '<' :
10692                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10693                         break;
10694                         
10695                 case LE_OP:
10696                 case GE_OP:
10697                 case NE_OP:
10698                         
10699                         /* note these two are xlated by algebraic equivalence
10700                         during parsing SDCC.y */
10701                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10702                                 "got '>=' or '<=' shouldn't have come here");
10703                         break;  
10704                         
10705                 case EQ_OP:
10706                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10707                         break;      
10708                         
10709                 case AND_OP:
10710                         genAndOp (ic);
10711                         break;
10712                         
10713                 case OR_OP:
10714                         genOrOp (ic);
10715                         break;
10716                         
10717                 case '^' :
10718                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10719                         break;
10720                         
10721                 case '|' :
10722                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10723                         break;
10724                         
10725                 case BITWISEAND:
10726                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10727                         break;
10728                         
10729                 case INLINEASM:
10730                         genInline (ic);
10731                         break;
10732                         
10733                 case RRC:
10734                         genRRC (ic);
10735                         break;
10736                         
10737                 case RLC:
10738                         genRLC (ic);
10739                         break;
10740                         
10741                 case GETHBIT:
10742                         genGetHbit (ic);
10743                         break;
10744                         
10745                 case LEFT_OP:
10746                         genLeftShift (ic);
10747                         break;
10748                         
10749                 case RIGHT_OP:
10750                         genRightShift (ic);
10751                         break;
10752                         
10753                 case GET_VALUE_AT_ADDRESS:
10754                         genPointerGet(ic);
10755                         break;
10756                         
10757                 case '=' :
10758                         if (POINTER_SET(ic))
10759                                 genPointerSet(ic);
10760                         else
10761                                 genAssign(ic);
10762                         break;
10763                         
10764                 case IFX:
10765                         genIfx (ic,NULL);
10766                         break;
10767                         
10768                 case ADDRESS_OF:
10769                         genAddrOf (ic);
10770                         break;
10771                         
10772                 case JUMPTABLE:
10773                         genJumpTab (ic);
10774                         break;
10775                         
10776                 case CAST:
10777                         genCast (ic);
10778                         break;
10779                         
10780                 case RECEIVE:
10781                         genReceive(ic);
10782                         break;
10783                         
10784                 case SEND:
10785                         addSet(&_G.sendSet,ic);
10786                         break;
10787                         
10788                 case DUMMY_READ_VOLATILE:
10789                         genDummyRead (ic);
10790                         break;
10791                         
10792                 default :
10793                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10794                         ic = ic;
10795                         break;
10796                 }
10797         }
10798
10799         
10800         /* now we are ready to call the
10801         peep hole optimizer */
10802         if (!options.nopeep) {
10803                 peepHole (&lineHead);
10804         }
10805         /* now do the actual printing */
10806         printLine (lineHead,codeOutBuf);
10807         
10808 #ifdef PCODE_DEBUG
10809         DFPRINTF((stderr,"printing pBlock\n\n"));
10810         printpBlock(stdout,pb);
10811 #endif
10812         
10813         return;
10814 }
10815
10816 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10817  * (meaning: representing its own address) or not (referencing its contents).
10818  * This can only be decided based on the operand's type. */
10819 int
10820 aop_isLitLike (asmop *aop)
10821 {
10822   assert (aop);
10823   if (aop->type == AOP_LIT) return 1;
10824 if (aop->type == AOP_IMMD) return 1;
10825   if ((aop->type == AOP_PCODE) &&
10826                 ((aop->aopu.pcop->type == PO_LITERAL)))
10827   {
10828     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10829      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10830     return 1;
10831   }
10832   return 0;
10833 }
10834
10835 int
10836 op_isLitLike (operand *op)
10837 {
10838   assert (op);
10839   if (aop_isLitLike (AOP(op))) return 1;
10840   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10841   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10842   return 0;
10843 }
10844