* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[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           bool found = 0;
1282
1283           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1284           {
1285             if (!strcmp (str, sym->rname))
1286               found = 1;
1287           }
1288           
1289           if (!found)
1290           {
1291             sym = newSymbol(str, 0);
1292             strncpy(sym->rname, str, SDCC_NAME_MAX);
1293             addSet (&externs, sym);
1294           } // if
1295         }
1296         return pcop;
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* popRegFromString -                                                                                      */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *popRegFromString(char *str, int size, int offset)
1303 {
1304         
1305         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1306         pcop->type = PO_DIR;
1307         
1308         DEBUGpic14_emitcode(";","%d",__LINE__);
1309         
1310         if(!str)
1311                 str = "BAD_STRING";
1312         
1313         pcop->name = Safe_calloc(1,strlen(str)+1);
1314         strcpy(pcop->name,str);
1315         
1316         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1317         
1318         PCOR(pcop)->r = dirregWithName(pcop->name);
1319         if(PCOR(pcop)->r == NULL) {
1320                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1321                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1322                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1323         } else {
1324                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1325         }
1326         PCOR(pcop)->instance = offset;
1327         
1328         return pcop;
1329 }
1330
1331 /*-----------------------------------------------------------------*/
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *popRegFromIdx(int rIdx)
1334 {
1335         pCodeOp *pcop;
1336         
1337         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1338                 __FUNCTION__,__LINE__,rIdx);
1339         
1340         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1341         
1342         PCOR(pcop)->rIdx = rIdx;
1343         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1344         PCOR(pcop)->r->isFree = 0;
1345         PCOR(pcop)->r->wasUsed = 1;
1346         
1347         pcop->type = PCOR(pcop)->r->pc_type;
1348         
1349         
1350         return pcop;
1351 }
1352
1353 /*-----------------------------------------------------------------*/
1354 /* popGet - asm operator to pcode operator conversion                      */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1357 {
1358         //char *s = buffer ;
1359         //char *rs;
1360         
1361         pCodeOp *pcop;
1362         
1363         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1364         /* offset is greater than
1365         size then zero */
1366
1367         assert (aop);
1368
1369
1370         /* XXX: still needed for BIT operands (AOP_CRY) */
1371         if (offset > (aop->size - 1) &&
1372                 aop->type != AOP_LIT &&
1373                 aop->type != AOP_PCODE)
1374         {
1375                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1376                 return NULL;  //zero;
1377         }
1378         
1379         /* depending on type */
1380         switch (aop->type) {
1381                 
1382         case AOP_R0:
1383         case AOP_R1:
1384         case AOP_DPTR:
1385         case AOP_DPTR2:
1386         case AOP_ACC:
1387                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1388                 return NULL;
1389                 
1390         case AOP_IMMD:
1391                 DEBUGpic14_emitcode(";","%d",__LINE__);
1392                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1393                 
1394         case AOP_DIR:
1395                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1396 #if 0
1397                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1398                 pcop->type = PO_DIR;
1399                 
1400                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1401                 strcpy(pcop->name,aop->aopu.aop_dir);   
1402                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1403                 if(PCOR(pcop)->r == NULL) {
1404                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1405                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1406                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1407                 } else {
1408                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1409                 }
1410                 PCOR(pcop)->instance = offset;
1411                 
1412                 return pcop;
1413 #endif
1414                 
1415         case AOP_REG:
1416                 {
1417                         int rIdx;
1418                         assert (offset < aop->size);
1419                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1420                         
1421                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1422                         PCOR(pcop)->rIdx = rIdx;
1423                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1424                         PCOR(pcop)->r->wasUsed=1;
1425                         PCOR(pcop)->r->isFree=0;
1426                         
1427                         PCOR(pcop)->instance = offset;
1428                         pcop->type = PCOR(pcop)->r->pc_type;
1429                         //rs = aop->aopu.aop_reg[offset]->name;
1430                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1431                         return pcop;
1432                 }
1433                 
1434         case AOP_CRY:
1435                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1436                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1437                 //if(PCOR(pcop)->r == NULL)
1438                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1439                 return pcop;
1440                 
1441         case AOP_LIT:
1442                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1443                 
1444         case AOP_STR:
1445                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1446                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1447                 /*
1448                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1449                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1450                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1451                 pcop->type = PCOR(pcop)->r->pc_type;
1452                 pcop->name = PCOR(pcop)->r->name;
1453                 
1454                   return pcop;
1455                 */
1456                 
1457         case AOP_PCODE:
1458                 pcop = NULL;
1459                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1460                         __LINE__, 
1461                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1462                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1463                 switch (aop->aopu.pcop->type)
1464                 {
1465                 case PO_IMMEDIATE:
1466                   pcop = pCodeOpCopy (aop->aopu.pcop);
1467                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1468                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1469                   PCOI(pcop)->index += offset;
1470                   //PCOI(pcop)->offset = 0;
1471                   break;
1472                 case PO_DIR:
1473                   pcop = pCodeOpCopy (aop->aopu.pcop);
1474                   PCOR(pcop)->instance = offset;
1475                   break;
1476                 default:
1477                   assert ( !"unhandled pCode type" );
1478                   break;
1479                 } // switch
1480                 return pcop;
1481         }
1482         
1483         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1484                 "popGet got unsupported aop->type");
1485         exit(0);
1486 }
1487
1488 /*-----------------------------------------------------------------*/
1489 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1490 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1491 /*-----------------------------------------------------------------*/
1492 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1493 {
1494   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1495   {
1496     pCodeOp *pcop = aop->aopu.pcop;
1497     assert (offset <= GPTRSIZE);
1498
1499     /* special case: index >= 2 should return GPOINTER-style values */
1500     if (offset == 2)
1501     {
1502       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1503       return pcop;
1504     }
1505     
1506     pcop = pCodeOpCopy (pcop);
1507     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1508      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1509     PCOI(pcop)->offset += offset;
1510     PCOI(pcop)->index += index;
1511     //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);
1512     return pcop;
1513   } else {
1514     return popGet (aop, offset + index);
1515   }
1516 }
1517
1518 /*-----------------------------------------------------------------*/
1519 /* aopPut - puts a string for a aop                                                        */
1520 /*-----------------------------------------------------------------*/
1521 void aopPut (asmop *aop, char *s, int offset)
1522 {
1523         char *d = buffer ;
1524         symbol *lbl ;
1525         
1526         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1527         
1528         if (aop->size && offset > ( aop->size - 1)) {
1529                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530                         "aopPut got offset > aop->size");
1531                 exit(0);
1532         }
1533         
1534         /* will assign value to value */
1535         /* depending on where it is ofcourse */
1536         switch (aop->type) {
1537         case AOP_DIR:
1538                 if (offset) {
1539                         sprintf(d,"(%s + %d)",
1540                                 aop->aopu.aop_dir,offset);
1541                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1542                         
1543                 } else
1544                         sprintf(d,"%s",aop->aopu.aop_dir);
1545                 
1546                 if (strcmp(d,s)) {
1547                         DEBUGpic14_emitcode(";","%d",__LINE__);
1548                         if(strcmp(s,"W"))
1549                                 pic14_emitcode("movf","%s,w",s);
1550                         pic14_emitcode("movwf","%s",d);
1551                         
1552                         if(strcmp(s,"W")) {
1553                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1554                                 if(offset >= aop->size) {
1555                                         emitpcode(POC_CLRF,popGet(aop,offset));
1556                                         break;
1557                                 } else {
1558                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1559                                 }
1560                         }
1561                         emitpcode(POC_MOVWF,popGet(aop,offset));
1562                 
1563                 }
1564                 break;
1565                 
1566         case AOP_REG:
1567                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1568                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1569                         /*
1570                         if (*s == '@'             ||
1571                         strcmp(s,"r0") == 0 ||
1572                         strcmp(s,"r1") == 0 ||
1573                         strcmp(s,"r2") == 0 ||
1574                         strcmp(s,"r3") == 0 ||
1575                         strcmp(s,"r4") == 0 ||
1576                         strcmp(s,"r5") == 0 ||
1577                         strcmp(s,"r6") == 0 || 
1578                         strcmp(s,"r7") == 0 )
1579                         pic14_emitcode("mov","%s,%s  ; %d",
1580                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1581                         else
1582                         */
1583                         
1584                         if(strcmp(s,"W")==0 )
1585                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1586                         
1587                         pic14_emitcode("movwf","%s",
1588                                 aop->aopu.aop_reg[offset]->name);
1589                         
1590                         if(strcmp(s,zero)==0) {
1591                                 emitpcode(POC_CLRF,popGet(aop,offset));
1592                                 
1593                         } else if(strcmp(s,"W")==0) {
1594                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595                                 pcop->type = PO_GPR_REGISTER;
1596                                 
1597                                 PCOR(pcop)->rIdx = -1;
1598                                 PCOR(pcop)->r = NULL;
1599                                 
1600                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1601                                 pcop->name = Safe_strdup(s);
1602                                 emitpcode(POC_MOVFW,pcop);
1603                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1604                         } else if(strcmp(s,one)==0) {
1605                                 emitpcode(POC_CLRF,popGet(aop,offset));
1606                                 emitpcode(POC_INCF,popGet(aop,offset));
1607                         } else {
1608                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1609                         }
1610                 }
1611                 break;
1612                 
1613         case AOP_DPTR:
1614         case AOP_DPTR2:
1615                 
1616                 if (aop->type == AOP_DPTR2)
1617                 {
1618                         genSetDPTR(1);
1619                 }
1620                 
1621                 if (aop->code) {
1622                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1623                                 "aopPut writting to code space");
1624                         exit(0);
1625                 }
1626                 
1627                 while (offset > aop->coff) {
1628                         aop->coff++;
1629                         pic14_emitcode ("inc","dptr");
1630                 }
1631                 
1632                 while (offset < aop->coff) {
1633                         aop->coff-- ;
1634                         pic14_emitcode("lcall","__decdptr");
1635                 }
1636                 
1637                 aop->coff = offset;
1638                 
1639                 /* if not in accumulater */
1640                 MOVA(s);
1641                 
1642                 pic14_emitcode ("movx","@dptr,a");
1643                 
1644                 if (aop->type == AOP_DPTR2)
1645                 {
1646                         genSetDPTR(0);
1647                 }
1648                 break;
1649                 
1650         case AOP_R0:
1651         case AOP_R1:
1652                 while (offset > aop->coff) {
1653                         aop->coff++;
1654                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1655                 }
1656                 while (offset < aop->coff) {
1657                         aop->coff-- ;
1658                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1659                 }
1660                 aop->coff = offset;
1661                 
1662                 if (aop->paged) {
1663                         MOVA(s);                         
1664                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1665                         
1666                 } else
1667                         if (*s == '@') {
1668                                 MOVA(s);
1669                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1670                         } else
1671                                 if (strcmp(s,"r0") == 0 ||
1672                                         strcmp(s,"r1") == 0 ||
1673                                         strcmp(s,"r2") == 0 ||
1674                                         strcmp(s,"r3") == 0 ||
1675                                         strcmp(s,"r4") == 0 ||
1676                                         strcmp(s,"r5") == 0 ||
1677                                         strcmp(s,"r6") == 0 || 
1678                                         strcmp(s,"r7") == 0 ) {
1679                                         char buffer[10];
1680                                         sprintf(buffer,"a%s",s);
1681                                         pic14_emitcode("mov","@%s,%s",
1682                                                 aop->aopu.aop_ptr->name,buffer);
1683                                 } else
1684                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1685                                 
1686                                 break;
1687                                 
1688         case AOP_STK:
1689                 if (strcmp(s,"a") == 0)
1690                         pic14_emitcode("push","acc");
1691                 else
1692                         pic14_emitcode("push","%s",s);
1693                 
1694                 break;
1695                 
1696         case AOP_CRY:
1697                 /* if bit variable */
1698                 if (!aop->aopu.aop_dir) {
1699                         pic14_emitcode("clr","a");
1700                         pic14_emitcode("rlc","a");
1701                 } else {
1702                         if (s == zero) 
1703                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1704                         else
1705                                 if (s == one)
1706                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1707                                 else
1708                                         if (!strcmp(s,"c"))
1709                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1710                                         else {
1711                                                 lbl = newiTempLabel(NULL);
1712                                                 
1713                                                 if (strcmp(s,"a")) {
1714                                                         MOVA(s);
1715                                                 }
1716                                                 pic14_emitcode("clr","c");
1717                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1718                                                 pic14_emitcode("cpl","c");
1719                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1720                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1721                                         }
1722                 }
1723                 break;
1724                 
1725         case AOP_STR:
1726                 aop->coff = offset;
1727                 if (strcmp(aop->aopu.aop_str[offset],s))
1728                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1729                 break;
1730                 
1731         case AOP_ACC:
1732                 aop->coff = offset;
1733                 if (!offset && (strcmp(s,"acc") == 0))
1734                         break;
1735                 
1736                 if (strcmp(aop->aopu.aop_str[offset],s))
1737                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1738                 break;
1739                 
1740         default :
1741                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1742                         "aopPut got unsupported aop->type");
1743                 exit(0);
1744         }
1745         
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1750 /*-----------------------------------------------------------------*/
1751 static void mov2w_op (operand *op, int offset)
1752 {
1753         assert (op);
1754         FENTRY;
1755
1756         /* for PO_IMMEDIATEs: use address or value? */
1757         if (op_isLitLike (op))
1758         {
1759                 /* access address of op */
1760                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1761                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1762                 {
1763                         if (offset == GPTRSIZE-1)
1764                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1765                         else
1766                                 emitpcode (POC_MOVLW, popGetLit (0));
1767                 }
1768                 else
1769                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1770         } else {
1771                 /* access value stored in op */
1772                 mov2w (AOP(op), offset);
1773         }
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1779 /*-----------------------------------------------------------------*/
1780 void mov2w (asmop *aop, int offset)
1781 {
1782         
1783         if(!aop)
1784                 return;
1785         
1786         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1787         
1788         if ( aop_isLitLike (aop) )
1789                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1790         else
1791                 emitpcode(POC_MOVFW,popGet(aop,offset));
1792         
1793 }
1794
1795 static void movwf (asmop *op, int offset)
1796 {
1797         emitpcode (POC_MOVWF, popGet(op, offset));
1798 }
1799
1800 static pCodeOp *get_argument_pcop (int idx)
1801 {
1802         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1803         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1804 }
1805
1806 static pCodeOp *get_return_val_pcop (int offset)
1807 {
1808         assert (offset > 0 && "the most significant byte is returned via WREG");
1809         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1810 }
1811
1812 static void pass_argument (operand *op, int offset, int idx)
1813 {
1814         if (op)
1815                 mov2w_op (op, offset);
1816         if (idx != 0)
1817                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1818 }
1819
1820 static void get_returnvalue (operand *op, int offset, int idx)
1821 {
1822         if (idx != 0)
1823                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1824         movwf(AOP(op), offset);
1825 }
1826
1827 static void call_libraryfunc (char *name)
1828 {
1829   /* library code might reside in different page... */
1830   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1831   /* call the library function */
1832   emitpcode (POC_CALL, popGetExternal (name));
1833   /* might return from different page... */
1834   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1835 }
1836 #if 0
1837 /*-----------------------------------------------------------------*/
1838 /* reAdjustPreg - points a register back to where it should        */
1839 /*-----------------------------------------------------------------*/
1840 static void reAdjustPreg (asmop *aop)
1841 {
1842         int size ;
1843         
1844         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845         aop->coff = 0;
1846         if ((size = aop->size) <= 1)
1847                 return ;
1848         size-- ;
1849         switch (aop->type) {
1850         case AOP_R0 :
1851         case AOP_R1 :
1852                 while (size--)
1853                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1854                 break;                  
1855         case AOP_DPTR :
1856         case AOP_DPTR2:
1857                 if (aop->type == AOP_DPTR2)
1858                 {
1859                         genSetDPTR(1);
1860                 } 
1861                 while (size--)
1862                 {
1863                         pic14_emitcode("lcall","__decdptr");
1864                 }
1865                 
1866                 if (aop->type == AOP_DPTR2)
1867                 {
1868                         genSetDPTR(0);
1869                 }
1870                 break;
1871                 
1872         }
1873         
1874 }
1875 #endif
1876
1877
1878 #if 0
1879 /*-----------------------------------------------------------------*/
1880 /* opIsGptr: returns non-zero if the passed operand is             */
1881 /* a generic pointer type.                                         */
1882 /*-----------------------------------------------------------------*/ 
1883 static int opIsGptr(operand *op)
1884 {
1885         sym_link *type = operandType(op);
1886         
1887         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1888         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1889         {
1890                 return 1;
1891         }
1892         return 0;          
1893 }
1894 #endif
1895
1896 /*-----------------------------------------------------------------*/
1897 /* pic14_getDataSize - get the operand data size                   */
1898 /*-----------------------------------------------------------------*/
1899 int pic14_getDataSize(operand *op)
1900 {
1901         int size;
1902         
1903         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1904         
1905 #if 0
1906         size = getSize(OP_SYM_ETYPE(op));
1907         return size;
1908         //return AOP_SIZE(op);
1909         
1910         // tsd- in the pic port, the genptr size is 1, so this code here
1911         // fails. ( in the 8051 port, the size was 4).
1912 #else
1913         size = AOP_SIZE(op);
1914         if (IS_GENPTR(OP_SYM_TYPE(op)))
1915         {
1916                 sym_link *type = operandType(op);
1917                 if (IS_GENPTR(type))
1918                 {
1919                         /* generic pointer; arithmetic operations
1920                         * should ignore the high byte (pointer type).
1921                         */
1922                         size--;
1923                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1924                 }
1925         }
1926         return size;
1927 #endif
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* pic14_outAcc - output Acc                                       */
1932 /*-----------------------------------------------------------------*/
1933 void pic14_outAcc(operand *result)
1934 {
1935         int size,offset;
1936         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1937         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1938         
1939         
1940         size = pic14_getDataSize(result);
1941         if(size){
1942                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1943                 size--;
1944                 offset = 1;
1945                 /* unsigned or positive */
1946                 while(size--)
1947                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1948         }
1949         
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* pic14_outBitC - output a bit C                                  */
1954 /*-----------------------------------------------------------------*/
1955 void pic14_outBitC(operand *result)
1956 {
1957         
1958         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1959         /* if the result is bit */
1960         if (AOP_TYPE(result) == AOP_CRY) 
1961                 aopPut(AOP(result),"c",0);
1962         else {
1963                 pic14_emitcode("clr","a  ; %d", __LINE__);
1964                 pic14_emitcode("rlc","a");
1965                 pic14_outAcc(result);
1966         }
1967 }
1968
1969 /*-----------------------------------------------------------------*/
1970 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1971 /*-----------------------------------------------------------------*/
1972 void pic14_toBoolean(operand *oper)
1973 {
1974         int size = AOP_SIZE(oper);
1975         int offset = 0;
1976         
1977         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1978
1979         assert (size > 0);
1980
1981         if (size == 1) {
1982                 /* MOVFW does not load the flags... */
1983                 if (AOP_TYPE(oper) == AOP_ACC) {
1984                         emitpcode(POC_IORLW, popGetLit(0));
1985                         offset = 1;
1986                 } else {
1987                         emitpcode(POC_MOVLW, popGetLit(0));
1988                         offset = 0;
1989                 }
1990         } else {
1991                 if ( AOP_TYPE(oper) != AOP_ACC) {
1992                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1993                         offset = 1;
1994                 }
1995         }
1996         
1997         while (offset < size) {
1998                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1999         }
2000         /* Z is set iff (oper == 0) */
2001 }
2002
2003
2004 /*-----------------------------------------------------------------*/
2005 /* genNot - generate code for ! operation                          */
2006 /*-----------------------------------------------------------------*/
2007 static void genNot (iCode *ic)
2008 {
2009         //symbol *tlbl;
2010         int size;
2011
2012         FENTRY;
2013         
2014         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2015         /* assign asmOps to operand & result */
2016         aopOp (IC_LEFT(ic),ic,FALSE);
2017         aopOp (IC_RESULT(ic),ic,TRUE);
2018         
2019         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2020         /* if in bit space then a special case */
2021         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2022                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2023                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2024                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2025                 } else {
2026                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2027                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2028                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2029                 }
2030                 goto release;
2031         }
2032         
2033         size = AOP_SIZE(IC_LEFT(ic));
2034         mov2w (AOP(IC_LEFT(ic)),0);
2035         while (--size > 0)
2036         {
2037           if (op_isLitLike (IC_LEFT(ic)))
2038             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2039           else
2040             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2041         }
2042         emitpcode(POC_MOVLW, popGetLit (0));
2043         emitSKPNZ;
2044         emitpcode(POC_MOVLW, popGetLit (1));
2045         movwf(AOP(IC_RESULT(ic)), 0);
2046
2047         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2048         {
2049           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2050         }
2051         goto release;
2052         
2053 release:        
2054         /* release the aops */
2055         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2056         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2057 }
2058
2059
2060 /*-----------------------------------------------------------------*/
2061 /* genCpl - generate code for complement                                                   */
2062 /*-----------------------------------------------------------------*/
2063 static void genCpl (iCode *ic)
2064 {
2065         operand *left, *result;
2066         int size, offset=0;  
2067         
2068         FENTRY;
2069         
2070         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2072         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2073         
2074         /* if both are in bit space then 
2075         a special case */
2076         if (AOP_TYPE(result) == AOP_CRY &&
2077                 AOP_TYPE(left) == AOP_CRY ) { 
2078                 
2079                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2080                 pic14_emitcode("cpl","c"); 
2081                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2082                 goto release; 
2083         } 
2084         
2085         size = AOP_SIZE(result);
2086         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2087         while (size--) {
2088                 
2089                 if(AOP_TYPE(left) == AOP_ACC) 
2090                         emitpcode(POC_XORLW, popGetLit(0xff));
2091                 else
2092                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2093                 
2094                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2095                 offset++;
2096         }
2097         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2098         
2099         
2100 release:
2101         /* release the aops */
2102         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2103         freeAsmop(result,NULL,ic,TRUE);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* genUminusFloat - unary minus for floating points                        */
2108 /*-----------------------------------------------------------------*/
2109 static void genUminusFloat(operand *op,operand *result)
2110 {
2111         int size ,offset =0 ;
2112         char *l;
2113         
2114         FENTRY;
2115
2116         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2117         /* for this we just need to flip the 
2118         first it then copy the rest in place */
2119         size = AOP_SIZE(op) - 1;
2120         l = aopGet(AOP(op),3,FALSE,FALSE);
2121         
2122         MOVA(l);          
2123         
2124         pic14_emitcode("cpl","acc.7");
2125         aopPut(AOP(result),"a",3);      
2126         
2127         while(size--) {
2128                 aopPut(AOP(result),
2129                         aopGet(AOP(op),offset,FALSE,FALSE),
2130                         offset);
2131                 offset++;
2132         }                
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* genUminus - unary minus code generation                                                 */
2137 /*-----------------------------------------------------------------*/
2138 static void genUminus (iCode *ic)
2139 {
2140         int size, i;
2141         sym_link *optype, *rtype;
2142         
2143         FENTRY;
2144         
2145         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2146         /* assign asmops */
2147         aopOp(IC_LEFT(ic),ic,FALSE);
2148         aopOp(IC_RESULT(ic),ic,TRUE);
2149         
2150         /* if both in bit space then special
2151         case */
2152         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2153                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2154                 
2155                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2156                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2157                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2158                 
2159                 goto release; 
2160         } 
2161         
2162         optype = operandType(IC_LEFT(ic));
2163         rtype = operandType(IC_RESULT(ic));
2164         
2165         /* if float then do float stuff */
2166         if (IS_FLOAT(optype)) {
2167                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2168                 goto release;
2169         }
2170         
2171         /* otherwise subtract from zero by taking the 2's complement */
2172         size = AOP_SIZE(IC_LEFT(ic));
2173         
2174         for(i=0; i<size; i++) {
2175                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2176                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2177                 else {
2178                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2179                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2180                 }
2181         }
2182         
2183         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2184         for(i=1; i<size; i++) {
2185                 emitSKPNZ;
2186                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2187         }
2188         
2189 release:
2190         /* release the aops */
2191         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2192         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2193 }
2194
2195 /*-----------------------------------------------------------------*/
2196 /* saveRegisters - will look for a call and save the registers     */
2197 /*-----------------------------------------------------------------*/
2198 static void saveRegisters(iCode *lic) 
2199 {
2200         int i;
2201         iCode *ic;
2202         bitVect *rsave;
2203         sym_link *dtype;
2204         
2205         FENTRY;
2206
2207         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2208         /* look for call */
2209         for (ic = lic ; ic ; ic = ic->next) 
2210                 if (ic->op == CALL || ic->op == PCALL)
2211                         break;
2212                 
2213                 if (!ic) {
2214                         fprintf(stderr,"found parameter push with no function call\n");
2215                         return ;
2216                 }
2217                 
2218                 /* if the registers have been saved already then
2219                 do nothing */
2220                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2221                         return ;
2222                 
2223                         /* find the registers in use at this time 
2224                 and push them away to safety */
2225                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2226                         ic->rUsed);
2227                 
2228                 ic->regsSaved = 1;
2229                 if (options.useXstack) {
2230                         if (bitVectBitValue(rsave,R0_IDX))
2231                                 pic14_emitcode("mov","b,r0");
2232                         pic14_emitcode("mov","r0,%s",spname);
2233                         for (i = 0 ; i < pic14_nRegs ; i++) {
2234                                 if (bitVectBitValue(rsave,i)) {
2235                                         if (i == R0_IDX)
2236                                                 pic14_emitcode("mov","a,b");
2237                                         else
2238                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2239                                         pic14_emitcode("movx","@r0,a");
2240                                         pic14_emitcode("inc","r0");
2241                                 }
2242                         }
2243                         pic14_emitcode("mov","%s,r0",spname);
2244                         if (bitVectBitValue(rsave,R0_IDX))
2245                                 pic14_emitcode("mov","r0,b");     
2246                 }// else
2247                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2248                 //        if (bitVectBitValue(rsave,i))
2249                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2250                 //}
2251                 
2252                 dtype = operandType(IC_LEFT(ic));
2253                 if (currFunc && dtype && 
2254                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2255                         IFFUNC_ISISR(currFunc->type) &&
2256                         !ic->bankSaved) 
2257                         
2258                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2259                 
2260 }
2261 /*-----------------------------------------------------------------*/
2262 /* unsaveRegisters - pop the pushed registers                                      */
2263 /*-----------------------------------------------------------------*/
2264 static void unsaveRegisters (iCode *ic)
2265 {
2266         int i;
2267         bitVect *rsave;
2268         
2269         FENTRY;
2270
2271         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272         /* find the registers in use at this time 
2273         and push them away to safety */
2274         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2275                 ic->rUsed);
2276         
2277         if (options.useXstack) {
2278                 pic14_emitcode("mov","r0,%s",spname); 
2279                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2280                         if (bitVectBitValue(rsave,i)) {
2281                                 pic14_emitcode("dec","r0");
2282                                 pic14_emitcode("movx","a,@r0");
2283                                 if (i == R0_IDX)
2284                                         pic14_emitcode("mov","b,a");
2285                                 else
2286                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2287                         }       
2288                         
2289                 }
2290                 pic14_emitcode("mov","%s,r0",spname);
2291                 if (bitVectBitValue(rsave,R0_IDX))
2292                         pic14_emitcode("mov","r0,b");
2293         } //else
2294         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2295         //      if (bitVectBitValue(rsave,i))
2296         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2297         //}
2298         
2299 }  
2300
2301
2302 /*-----------------------------------------------------------------*/
2303 /* pushSide -                            */
2304 /*-----------------------------------------------------------------*/
2305 static void pushSide(operand * oper, int size)
2306 {
2307 #if 0
2308         int offset = 0;
2309         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2310         while (size--) {
2311                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2312                 if (AOP_TYPE(oper) != AOP_REG &&
2313                         AOP_TYPE(oper) != AOP_DIR &&
2314                         strcmp(l,"a") ) {
2315                         pic14_emitcode("mov","a,%s",l);
2316                         pic14_emitcode("push","acc");
2317                 } else
2318                         pic14_emitcode("push","%s",l);
2319         }
2320 #endif
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* assignResultValue -                           */
2325 /*-----------------------------------------------------------------*/
2326 static void assignResultValue(operand * oper)
2327 {
2328         int size = AOP_SIZE(oper);
2329         int offset = 0;
2330         
2331         FENTRY;
2332
2333         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334         
2335         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2336         
2337         /* assign MSB first (passed via WREG) */
2338         while (size--) {
2339                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2340                 GpsuedoStkPtr++;
2341         }
2342 }
2343
2344
2345 /*-----------------------------------------------------------------*/
2346 /* genIpush - genrate code for pushing this gets a little complex  */
2347 /*-----------------------------------------------------------------*/
2348 static void genIpush (iCode *ic)
2349 {
2350         FENTRY;
2351         
2352         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2353 #if 0
2354         int size, offset = 0 ;
2355         char *l;
2356         
2357         
2358         /* if this is not a parm push : ie. it is spill push 
2359         and spill push is always done on the local stack */
2360         if (!ic->parmPush) {
2361                 
2362                 /* and the item is spilt then do nothing */
2363                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2364                         return ;
2365                 
2366                 aopOp(IC_LEFT(ic),ic,FALSE);
2367                 size = AOP_SIZE(IC_LEFT(ic));
2368                 /* push it on the stack */
2369                 while(size--) {
2370                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2371                         if (*l == '#') {
2372                                 MOVA(l);
2373                                 l = "acc";
2374                         }
2375                         pic14_emitcode("push","%s",l);
2376                 }
2377                 return ;                
2378         }
2379         
2380         /* this is a paramter push: in this case we call
2381         the routine to find the call and save those
2382         registers that need to be saved */   
2383         saveRegisters(ic);
2384         
2385         /* then do the push */
2386         aopOp(IC_LEFT(ic),ic,FALSE);
2387         
2388         
2389         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2390         size = AOP_SIZE(IC_LEFT(ic));
2391         
2392         while (size--) {
2393                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2394                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2395                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2396                         strcmp(l,"a") ) {
2397                         pic14_emitcode("mov","a,%s",l);
2398                         pic14_emitcode("push","acc");
2399                 } else
2400                         pic14_emitcode("push","%s",l);
2401         }         
2402         
2403         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2404 #endif
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* genIpop - recover the registers: can happen only for spilling   */
2409 /*-----------------------------------------------------------------*/
2410 static void genIpop (iCode *ic)
2411 {
2412         FENTRY;
2413
2414         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2415         assert (!"genIpop -- unimplemented");
2416 #if 0
2417         int size,offset ;
2418         
2419         
2420         /* if the temp was not pushed then */
2421         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2422                 return ;
2423         
2424         aopOp(IC_LEFT(ic),ic,FALSE);
2425         size = AOP_SIZE(IC_LEFT(ic));
2426         offset = (size-1);
2427         while (size--) 
2428                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2429                 FALSE,TRUE));
2430         
2431         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2432 #endif
2433 }
2434
2435 /*-----------------------------------------------------------------*/
2436 /* unsaverbank - restores the resgister bank from stack                    */
2437 /*-----------------------------------------------------------------*/
2438 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2439 {
2440         FENTRY;
2441
2442         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2443 #if 0
2444         int i;
2445         asmop *aop ;
2446         regs *r = NULL;
2447         
2448         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2449         if (popPsw) {
2450                 if (options.useXstack) {
2451                         aop = newAsmop(0);
2452                         r = getFreePtr(ic,&aop,FALSE);
2453                         
2454                         
2455                         pic14_emitcode("mov","%s,_spx",r->name);
2456                         pic14_emitcode("movx","a,@%s",r->name);
2457                         pic14_emitcode("mov","psw,a");
2458                         pic14_emitcode("dec","%s",r->name);
2459                         
2460                 }else
2461                         pic14_emitcode ("pop","psw");
2462         }
2463         
2464         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2465                 if (options.useXstack) {           
2466                         pic14_emitcode("movx","a,@%s",r->name);
2467                         //pic14_emitcode("mov","(%s+%d),a",
2468                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2469                         pic14_emitcode("dec","%s",r->name);
2470                         
2471                 } else 
2472                         pic14_emitcode("pop",""); //"(%s+%d)",
2473                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2474         }
2475         
2476         if (options.useXstack) {
2477                 
2478                 pic14_emitcode("mov","_spx,%s",r->name);
2479                 freeAsmop(NULL,aop,ic,TRUE);
2480                 
2481         }
2482 #endif 
2483 }
2484
2485 /*-----------------------------------------------------------------*/
2486 /* saverbank - saves an entire register bank on the stack                  */
2487 /*-----------------------------------------------------------------*/
2488 static void saverbank (int bank, iCode *ic, bool pushPsw)
2489 {
2490         FENTRY;
2491
2492         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2493 #if 0
2494         int i;
2495         asmop *aop ;
2496         regs *r = NULL;
2497         
2498         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2499         if (options.useXstack) {
2500                 
2501                 aop = newAsmop(0);
2502                 r = getFreePtr(ic,&aop,FALSE);  
2503                 pic14_emitcode("mov","%s,_spx",r->name);
2504                 
2505         }
2506         
2507         for (i = 0 ; i < pic14_nRegs ;i++) {
2508                 if (options.useXstack) {
2509                         pic14_emitcode("inc","%s",r->name);
2510                         //pic14_emitcode("mov","a,(%s+%d)",
2511                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2512                         pic14_emitcode("movx","@%s,a",r->name);                 
2513                 } else 
2514                         pic14_emitcode("push","");// "(%s+%d)",
2515                 //regspic14[i].base,8*bank+regspic14[i].offset);
2516         }
2517         
2518         if (pushPsw) {
2519                 if (options.useXstack) {
2520                         pic14_emitcode("mov","a,psw");
2521                         pic14_emitcode("movx","@%s,a",r->name); 
2522                         pic14_emitcode("inc","%s",r->name);
2523                         pic14_emitcode("mov","_spx,%s",r->name);                 
2524                         freeAsmop (NULL,aop,ic,TRUE);
2525                         
2526                 } else
2527                         pic14_emitcode("push","psw");
2528                 
2529                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2530         }
2531         ic->bankSaved = 1;
2532 #endif
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /* genCall - generates a call statement                                                    */
2537 /*-----------------------------------------------------------------*/
2538 static void genCall (iCode *ic)
2539 {
2540         sym_link *dtype;         
2541         symbol *sym;
2542         char *name;
2543         int isExtern;
2544         
2545         FENTRY;
2546
2547         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548         
2549         /* if caller saves & we have not saved then */
2550         if (!ic->regsSaved)
2551                 saveRegisters(ic);
2552         
2553                 /* if we are calling a function that is not using
2554                 the same register bank then we need to save the
2555         destination registers on the stack */
2556         dtype = operandType(IC_LEFT(ic));
2557         if (currFunc && dtype && 
2558                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2559                 IFFUNC_ISISR(currFunc->type) &&
2560                 !ic->bankSaved) 
2561                 
2562                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2563         
2564         /* if send set is not empty the assign */
2565         if (_G.sendSet) {
2566                 iCode *sic;
2567                 /* For the Pic port, there is no data stack.
2568                 * So parameters passed to functions are stored
2569                 * in registers. (The pCode optimizer will get
2570                 * rid of most of these :).
2571                 */
2572                 int psuedoStkPtr=-1;
2573                 int firstTimeThruLoop = 1;
2574                 
2575                 _G.sendSet = reverseSet(_G.sendSet);
2576                 
2577                 /* First figure how many parameters are getting passed */
2578                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2579                 sic = setNextItem(_G.sendSet)) {
2580                         
2581                         aopOp(IC_LEFT(sic),sic,FALSE);
2582                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2583                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2584                 }
2585                 
2586                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2587                 sic = setNextItem(_G.sendSet)) {
2588                         int size, offset = 0;
2589                         
2590                         aopOp(IC_LEFT(sic),sic,FALSE);
2591                         size = AOP_SIZE(IC_LEFT(sic));
2592                         
2593                         while (size--) {
2594                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2595                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2596                                 
2597                                 if(!firstTimeThruLoop) {
2598                                         /* If this is not the first time we've been through the loop
2599                                         * then we need to save the parameter in a temporary
2600                                         * register. The last byte of the last parameter is
2601                                         * passed in W. */
2602                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2603                                         
2604                                 }
2605                                 firstTimeThruLoop=0;
2606                                 
2607                                 mov2w_op (IC_LEFT(sic),  offset);
2608                                 offset++;
2609                         }
2610                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2611                 }
2612                 _G.sendSet = NULL;
2613         }
2614         /* make the call */
2615         sym = OP_SYMBOL(IC_LEFT(ic));
2616         name = sym->rname[0] ? sym->rname : sym->name;
2617         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2618         if (isExtern) {
2619                 /* Extern functions and ISRs maybe on a different page;
2620                  * must call pagesel */
2621                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2622         }
2623         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2624         if (isExtern) {
2625                 /* May have returned from a different page;
2626                  * must use pagesel to restore PCLATH before next
2627                  * goto or call instruction */
2628                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2629         }
2630         GpsuedoStkPtr=0;
2631         /* if we need assign a result value */
2632         if ((IS_ITEMP(IC_RESULT(ic)) && 
2633                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2634                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2635                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2636                 
2637                 _G.accInUse++;
2638                 aopOp(IC_RESULT(ic),ic,FALSE);
2639                 _G.accInUse--;
2640                 
2641                 assignResultValue(IC_RESULT(ic));
2642                 
2643                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2644                         AopType(AOP_TYPE(IC_RESULT(ic))));
2645                 
2646                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2647         }
2648         
2649         /* if register bank was saved then pop them */
2650         if (ic->bankSaved)
2651                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2652         
2653         /* if we hade saved some registers then unsave them */
2654         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2655                 unsaveRegisters (ic);
2656         
2657         
2658 }
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genPcall - generates a call by pointer statement                        */
2662 /*-----------------------------------------------------------------*/
2663 static void genPcall (iCode *ic)
2664 {
2665         sym_link *dtype;
2666         symbol *albl = newiTempLabel(NULL);
2667         symbol *blbl = newiTempLabel(NULL);
2668         PIC_OPCODE poc;
2669         pCodeOp *pcop;
2670         operand *left;
2671         
2672         FENTRY;
2673
2674         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2675         /* if caller saves & we have not saved then */
2676         if (!ic->regsSaved)
2677                 saveRegisters(ic);
2678         
2679                 /* if we are calling a function that is not using
2680                 the same register bank then we need to save the
2681         destination registers on the stack */
2682         dtype = operandType(IC_LEFT(ic));
2683         if (currFunc && dtype && 
2684                 IFFUNC_ISISR(currFunc->type) &&
2685                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2686                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2687         
2688         left = IC_LEFT(ic);
2689         aopOp(left,ic,FALSE);
2690         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2691         
2692         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2693         
2694         pushSide(IC_LEFT(ic), FPTRSIZE);
2695         
2696         /* if send set is not empty, assign parameters */
2697         if (_G.sendSet) {
2698                 
2699                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2700                 /* no way to pass args - W always gets used to make the call */
2701         }
2702         /* first idea - factor out a common helper function and call it.
2703         But don't know how to get it generated only once in its own block
2704         
2705         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2706                 char *rname;
2707                 char *buffer;
2708                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2709                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2710                 buffer = Safe_calloc(1,strlen(rname)+16);
2711                 sprintf(buffer, "%s_goto_helper", rname);
2712                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2713                 free(buffer);
2714         }
2715         */
2716         emitpcode(POC_CALL,popGetLabel(albl->key));
2717         pcop = popGetLabel(blbl->key);
2718         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2719         emitpcode(POC_GOTO,pcop);
2720         emitpLabel(albl->key);
2721         
2722         emitpcode(poc,popGetAddr(AOP(left),1,0));
2723         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2724         emitpcode(poc,popGetAddr(AOP(left),0,0));
2725         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2726         
2727         emitpLabel(blbl->key);
2728         
2729         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2730         
2731         /* if we need to assign a result value */
2732         if ((IS_ITEMP(IC_RESULT(ic)) &&
2733                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2734                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2735                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2736                 
2737                 _G.accInUse++;
2738                 aopOp(IC_RESULT(ic),ic,FALSE);
2739                 _G.accInUse--;
2740
2741                 GpsuedoStkPtr = 0;
2742                 
2743                 assignResultValue(IC_RESULT(ic));
2744                 
2745                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2746         }
2747         
2748         /* if register bank was saved then unsave them */
2749         if (currFunc && dtype && 
2750                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2751                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2752         
2753                 /* if we hade saved some registers then
2754         unsave them */
2755         if (ic->regsSaved)
2756                 unsaveRegisters (ic);
2757         
2758 }
2759
2760 /*-----------------------------------------------------------------*/
2761 /* resultRemat - result  is rematerializable                                       */
2762 /*-----------------------------------------------------------------*/
2763 static int resultRemat (iCode *ic)
2764 {
2765         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2766         FENTRY;
2767
2768         if (SKIP_IC(ic) || ic->op == IFX)
2769                 return 0;
2770         
2771         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2772                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2773                 if (sym->remat && !POINTER_SET(ic)) 
2774                         return 1;
2775         }
2776         
2777         return 0;
2778 }
2779
2780 #if 0
2781 /*-----------------------------------------------------------------*/
2782 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2783 /*-----------------------------------------------------------------*/
2784 static bool inExcludeList(char *s)
2785 {
2786         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2787         int i =0;
2788         
2789         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2790         if (options.excludeRegs[i] &&
2791                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2792                 return FALSE ;
2793         
2794         for ( i = 0 ; options.excludeRegs[i]; i++) {
2795                 if (options.excludeRegs[i] &&
2796                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2797                         return TRUE;
2798         }
2799         return FALSE ;
2800 }
2801 #endif
2802
2803 /*-----------------------------------------------------------------*/
2804 /* genFunction - generated code for function entry                                 */
2805 /*-----------------------------------------------------------------*/
2806 static void genFunction (iCode *ic)
2807 {
2808         symbol *sym;
2809         sym_link *ftype;
2810         
2811         FENTRY;
2812
2813         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2814         
2815         labelOffset += (max_key+4);
2816         max_key=0;
2817         GpsuedoStkPtr=0;
2818         _G.nRegsSaved = 0;
2819         /* create the function header */
2820         pic14_emitcode(";","-----------------------------------------");
2821         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2822         pic14_emitcode(";","-----------------------------------------");
2823         
2824         /* prevent this symbol from being emitted as 'extern' */
2825         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2826
2827         pic14_emitcode("","%s:",sym->rname);
2828         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2829         
2830         ftype = operandType(IC_LEFT(ic));
2831         
2832         /* if critical function then turn interrupts off */
2833         if (IFFUNC_ISCRITICAL(ftype))
2834                 pic14_emitcode("clr","ea");
2835         
2836                 /* here we need to generate the equates for the
2837         register bank if required */
2838 #if 0
2839         if (FUNC_REGBANK(ftype) != rbank) {
2840                 int i ;
2841                 
2842                 rbank = FUNC_REGBANK(ftype);
2843                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2844                         if (strcmp(regspic14[i].base,"0") == 0)
2845                                 pic14_emitcode("","%s = 0x%02x",
2846                                 regspic14[i].dname,
2847                                 8*rbank+regspic14[i].offset);
2848                         else
2849                                 pic14_emitcode ("","%s = %s + 0x%02x",
2850                                 regspic14[i].dname,
2851                                 regspic14[i].base,
2852                                 8*rbank+regspic14[i].offset);
2853                 }
2854         }
2855 #endif
2856         
2857         /* if this is an interrupt service routine */
2858         pic14_inISR = 0;
2859         if (IFFUNC_ISISR(sym->type)) {
2860                 pic14_inISR = 1;
2861         /*  already done in pic14createInterruptVect() - delete me
2862         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2863         emitpcodeNULLop(POC_NOP);
2864         emitpcodeNULLop(POC_NOP);
2865         emitpcodeNULLop(POC_NOP);
2866                 */
2867                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2868                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2869                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2870                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2871                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2872                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2873                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2874                 
2875                 pBlockConvert2ISR(pb);
2876                 pic14_hasInterrupt = 1;
2877 #if 0  
2878                 if (!inExcludeList("acc"))              
2879                         pic14_emitcode ("push","acc");  
2880                 if (!inExcludeList("b"))
2881                         pic14_emitcode ("push","b");
2882                 if (!inExcludeList("dpl"))
2883                         pic14_emitcode ("push","dpl");
2884                 if (!inExcludeList("dph"))
2885                         pic14_emitcode ("push","dph");
2886                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2887                 {
2888                         pic14_emitcode ("push", "dpx");
2889                         /* Make sure we're using standard DPTR */
2890                         pic14_emitcode ("push", "dps");
2891                         pic14_emitcode ("mov", "dps, #0x00");
2892                         if (options.stack10bit)
2893                         { 
2894                                 /* This ISR could conceivably use DPTR2. Better save it. */
2895                                 pic14_emitcode ("push", "dpl1");
2896                                 pic14_emitcode ("push", "dph1");
2897                                 pic14_emitcode ("push", "dpx1");
2898                         }
2899                 }
2900                 /* if this isr has no bank i.e. is going to
2901                 run with bank 0 , then we need to save more
2902                 registers :-) */
2903                 if (!FUNC_REGBANK(sym->type)) {
2904                         
2905                 /* if this function does not call any other
2906                 function then we can be economical and
2907                         save only those registers that are used */
2908                         if (! IFFUNC_HASFCALL(sym->type)) {
2909                                 int i;
2910                                 
2911                                 /* if any registers used */
2912                                 if (sym->regsUsed) {
2913                                         /* save the registers used */
2914                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2915                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2916                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2917                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2918                                         }
2919                                 }
2920                                 
2921                         } else {
2922                         /* this function has    a function call cannot
2923                         determines register usage so we will have the
2924                                 entire bank */
2925                                 saverbank(0,ic,FALSE);
2926                         }       
2927                 }
2928 #endif
2929         } else {
2930         /* if callee-save to be used for this function
2931                 then save the registers being used in this function */
2932                 if (IFFUNC_CALLEESAVES(sym->type)) {
2933                         int i;
2934                         
2935                         /* if any registers used */
2936                         if (sym->regsUsed) {
2937                                 /* save the registers used */
2938                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2939                                         if (bitVectBitValue(sym->regsUsed,i) ||
2940                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2941                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2942                                                 _G.nRegsSaved++;
2943                                         }
2944                                 }
2945                         }
2946                 }
2947         }
2948         
2949         /* set the register bank to the desired value */
2950         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2951                 pic14_emitcode("push","psw");
2952                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2953         }
2954         
2955         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2956                 
2957                 if (options.useXstack) {
2958                         pic14_emitcode("mov","r0,%s",spname);
2959                         pic14_emitcode("mov","a,_bp");
2960                         pic14_emitcode("movx","@r0,a");
2961                         pic14_emitcode("inc","%s",spname);
2962                 }
2963                 else
2964                 {
2965                         /* set up the stack */
2966                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2967                 }
2968                 pic14_emitcode ("mov","_bp,%s",spname);
2969         }
2970         
2971         /* adjust the stack for the function */
2972         if (sym->stack) {
2973                 
2974                 int i = sym->stack;
2975                 if (i > 256 ) 
2976                         werror(W_STACK_OVERFLOW,sym->name);
2977                 
2978                 if (i > 3 && sym->recvSize < 4) {                
2979                         
2980                         pic14_emitcode ("mov","a,sp");
2981                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2982                         pic14_emitcode ("mov","sp,a");
2983                         
2984                 }
2985                 else
2986                         while(i--)
2987                                 pic14_emitcode("inc","sp");
2988         }
2989         
2990         if (sym->xstack) {
2991                 
2992                 pic14_emitcode ("mov","a,_spx");
2993                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2994                 pic14_emitcode ("mov","_spx,a");
2995         }
2996         
2997 }
2998
2999 /*-----------------------------------------------------------------*/
3000 /* genEndFunction - generates epilogue for functions                       */
3001 /*-----------------------------------------------------------------*/
3002 static void genEndFunction (iCode *ic)
3003 {
3004         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3005         
3006         FENTRY;
3007
3008         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3009         
3010         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3011         {
3012                 pic14_emitcode ("mov","%s,_bp",spname);
3013         }
3014         
3015         /* if use external stack but some variables were
3016         added to the local stack then decrement the
3017         local stack */
3018         if (options.useXstack && sym->stack) {    
3019                 pic14_emitcode("mov","a,sp");
3020                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3021                 pic14_emitcode("mov","sp,a");
3022         }
3023         
3024         
3025         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3026                 if (options.useXstack) {
3027                         pic14_emitcode("mov","r0,%s",spname);
3028                         pic14_emitcode("movx","a,@r0");
3029                         pic14_emitcode("mov","_bp,a");
3030                         pic14_emitcode("dec","%s",spname);
3031                 }
3032                 else
3033                 {
3034                         pic14_emitcode ("pop","_bp");
3035                 }
3036         }
3037         
3038         /* restore the register bank    */        
3039         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3040                 pic14_emitcode ("pop","psw");
3041         
3042         if (IFFUNC_ISISR(sym->type)) {
3043                 
3044                 /* now we need to restore the registers */
3045                 /* if this isr has no bank i.e. is going to
3046                 run with bank 0 , then we need to save more
3047 registers :-) */
3048                 if (!FUNC_REGBANK(sym->type)) {
3049                         
3050                 /* if this function does not call any other
3051                 function then we can be economical and
3052                         save only those registers that are used */
3053                         if (! IFFUNC_HASFCALL(sym->type)) {
3054                                 int i;
3055                                 
3056                                 /* if any registers used */
3057                                 if (sym->regsUsed) {
3058                                         /* save the registers used */
3059                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3060                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3061                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3062                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3063                                         }
3064                                 }
3065                                 
3066                         } else {
3067                         /* this function has    a function call cannot
3068                         determines register usage so we will have the
3069                                 entire bank */
3070                                 unsaverbank(0,ic,FALSE);
3071                         }       
3072                 }
3073 #if 0
3074                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3075                 {
3076                         if (options.stack10bit)
3077                         {
3078                                 pic14_emitcode ("pop", "dpx1");
3079                                 pic14_emitcode ("pop", "dph1");
3080                                 pic14_emitcode ("pop", "dpl1");
3081                         } 
3082                         pic14_emitcode ("pop", "dps");
3083                         pic14_emitcode ("pop", "dpx");
3084                 }
3085                 if (!inExcludeList("dph"))
3086                         pic14_emitcode ("pop","dph");
3087                 if (!inExcludeList("dpl"))
3088                         pic14_emitcode ("pop","dpl");
3089                 if (!inExcludeList("b"))
3090                         pic14_emitcode ("pop","b");
3091                 if (!inExcludeList("acc"))
3092                         pic14_emitcode ("pop","acc");
3093                 
3094                 if (IFFUNC_ISCRITICAL(sym->type))
3095                         pic14_emitcode("setb","ea");
3096 #endif
3097                 
3098                 /* if debug then send end of function */
3099                 /*      if (options.debug && currFunc) { */
3100                 if (currFunc) {
3101                         debugFile->writeEndFunction (currFunc, ic, 1);
3102                 }
3103                 
3104                 pic14_emitcode ("reti","");
3105                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3106                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3107                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3108                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3109                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3110                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3111                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3112                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3113                 emitpcodeNULLop(POC_RETFIE);
3114         }
3115         else {
3116                 if (IFFUNC_ISCRITICAL(sym->type))
3117                         pic14_emitcode("setb","ea");
3118                 
3119                 if (IFFUNC_CALLEESAVES(sym->type)) {
3120                         int i;
3121                         
3122                         /* if any registers used */
3123                         if (sym->regsUsed) {
3124                                 /* save the registers used */
3125                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3126                                         if (bitVectBitValue(sym->regsUsed,i) ||
3127                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3128                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3129                                 }
3130                         }
3131                         
3132                 }
3133                 
3134                 /* if debug then send end of function */
3135                 if (currFunc) {
3136                         debugFile->writeEndFunction (currFunc, ic, 1);
3137                 }
3138                 
3139                 pic14_emitcode ("return","");
3140                 emitpcodeNULLop(POC_RETURN);
3141                 
3142                 /* Mark the end of a function */
3143                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3144         }
3145         
3146 }
3147
3148 /*-----------------------------------------------------------------*/
3149 /* genRet - generate code for return statement                                     */
3150 /*-----------------------------------------------------------------*/
3151 static void genRet (iCode *ic)
3152 {
3153         int size,offset = 0;
3154         
3155         FENTRY;
3156
3157         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3158         /* if we have no return value then
3159         just generate the "ret" */
3160         if (!IC_LEFT(ic)) 
3161                 goto jumpret;           
3162         
3163                 /* we have something to return then
3164         move the return value into place */
3165         aopOp(IC_LEFT(ic),ic,FALSE);
3166         size = AOP_SIZE(IC_LEFT(ic));
3167
3168         for (offset = 0; offset < size; offset++)
3169         {
3170                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3171         }
3172         
3173         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3174         
3175 jumpret:
3176         /* generate a jump to the return label
3177         if the next is not the return statement */
3178         if (!(ic->next && ic->next->op == LABEL &&
3179                 IC_LABEL(ic->next) == returnLabel)) {
3180                 
3181                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3182         }
3183         
3184 }
3185
3186 /*-----------------------------------------------------------------*/
3187 /* genLabel - generates a label                                                                    */
3188 /*-----------------------------------------------------------------*/
3189 static void genLabel (iCode *ic)
3190 {
3191         FENTRY;
3192
3193         /* special case never generate */
3194         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3195         if (IC_LABEL(ic) == entryLabel)
3196                 return ;
3197         
3198         emitpLabel(IC_LABEL(ic)->key);
3199         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3200 }
3201
3202 /*-----------------------------------------------------------------*/
3203 /* genGoto - generates a goto                                                                      */
3204 /*-----------------------------------------------------------------*/
3205 //tsd
3206 static void genGoto (iCode *ic)
3207 {
3208         FENTRY;
3209
3210         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3211         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3212 }
3213
3214
3215 /*-----------------------------------------------------------------*/
3216 /* genMultbits :- multiplication of bits                                                   */
3217 /*-----------------------------------------------------------------*/
3218 static void genMultbits (operand *left, 
3219                                                  operand *right, 
3220                                                  operand *result)
3221 {
3222         FENTRY;
3223         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3224         
3225         if(!pic14_sameRegs(AOP(result),AOP(right)))
3226                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3227         
3228         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3229         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3230         emitpcode(POC_BCF,  popGet(AOP(result),0));
3231         
3232 }
3233
3234
3235 /*-----------------------------------------------------------------*/
3236 /* genMultOneByte : 8 bit multiplication & division                        */
3237 /*-----------------------------------------------------------------*/
3238 static void genMultOneByte (operand *left,
3239                                                         operand *right,
3240                                                         operand *result)
3241 {
3242         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3243         
3244         // symbol *lbl ;
3245         int size,offset,i;
3246         
3247         
3248         FENTRY;
3249         
3250         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3251         DEBUGpic14_AopType(__LINE__,left,right,result);
3252         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3253         
3254         /* (if two literals, the value is computed before) */
3255         /* if one literal, literal on the right */
3256         if (AOP_TYPE(left) == AOP_LIT){
3257                 operand *t = right;
3258                 right = left;
3259                 left = t;
3260         }
3261
3262         assert (AOP_SIZE(left) == AOP_SIZE(right));
3263         
3264         size = min(AOP_SIZE(result),AOP_SIZE(left));
3265         offset = Gstack_base_addr - (2*size - 1);
3266
3267         /* pass right operand as argument */
3268         for (i=0; i < size; i++)
3269         {
3270                 mov2w (AOP(right), i);
3271                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3272         } // for
3273         
3274         /* pass left operand as argument */
3275         for (i=0; i < size; i++)
3276         {
3277                 mov2w (AOP(left), i);
3278                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3279         } // for
3280         assert (offset == Gstack_base_addr);
3281         
3282         /* call library routine */
3283         assert (size > 0 && size <= 4);
3284         call_libraryfunc (func[size]);
3285         
3286         /* assign result */
3287         movwf (AOP(result), size-1);
3288         for (i=0; i < size - 1; i++)
3289         {
3290                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3291                 movwf (AOP(result), size - 2 - i);
3292         } // for
3293
3294         /* now (zero-/sign) extend the result to its size */
3295         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3296 }
3297
3298 /*-----------------------------------------------------------------*/
3299 /* genMult - generates code for multiplication                                     */
3300 /*-----------------------------------------------------------------*/
3301 static void genMult (iCode *ic)
3302 {
3303         operand *left = IC_LEFT(ic);
3304         operand *right = IC_RIGHT(ic);
3305         operand *result= IC_RESULT(ic); 
3306         
3307         FENTRY;
3308
3309         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3310         /* assign the amsops */
3311         aopOp (left,ic,FALSE);
3312         aopOp (right,ic,FALSE);
3313         aopOp (result,ic,TRUE);
3314         
3315         DEBUGpic14_AopType(__LINE__,left,right,result);
3316         
3317         /* special cases first */
3318         /* both are bits */
3319         if (AOP_TYPE(left) == AOP_CRY &&
3320                 AOP_TYPE(right)== AOP_CRY) {
3321                 genMultbits(left,right,result);
3322                 goto release ;
3323         }
3324         
3325         /* if both are of size == 1 */
3326         if (AOP_SIZE(left) == 1 &&
3327                 AOP_SIZE(right) == 1 ) {
3328                 genMultOneByte(left,right,result);
3329                 goto release ;
3330         }
3331         
3332         /* should have been converted to function call */
3333         assert(0) ;
3334         
3335 release :
3336         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338         freeAsmop(result,NULL,ic,TRUE); 
3339 }
3340
3341 /*-----------------------------------------------------------------*/
3342 /* genDivbits :- division of bits                                                                  */
3343 /*-----------------------------------------------------------------*/
3344 static void genDivbits (operand *left, 
3345                                                 operand *right, 
3346                                                 operand *result)
3347 {
3348         
3349         char *l;
3350         
3351         FENTRY;
3352
3353         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3354         /* the result must be bit */      
3355         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3356         l = aopGet(AOP(left),0,FALSE,FALSE);
3357         
3358         MOVA(l);          
3359         
3360         pic14_emitcode("div","ab");
3361         pic14_emitcode("rrc","a");
3362         aopPut(AOP(result),"c",0);
3363 }
3364
3365 /*-----------------------------------------------------------------*/
3366 /* genDivOneByte : 8 bit division                                                                  */
3367 /*-----------------------------------------------------------------*/
3368 static void genDivOneByte (operand *left,
3369                                                    operand *right,
3370                                                    operand *result)
3371 {
3372         int size;
3373         int sign;
3374         
3375         FENTRY;
3376         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3377         
3378         assert (AOP_SIZE(right) == 1);
3379         assert (AOP_SIZE(left) == 1);
3380
3381         size = min(AOP_SIZE(result),AOP_SIZE(left));
3382         sign = !(SPEC_USIGN(operandType(left))
3383                 && SPEC_USIGN(operandType(right)));
3384
3385         if (AOP_TYPE(right) == AOP_LIT)
3386         {
3387                 /* XXX: might add specialized code */
3388         }
3389
3390         if (!sign)
3391         {
3392                 /* unsigned division */
3393         #if 1
3394                 mov2w(AOP(right),0);
3395                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3396                 mov2w(AOP(left),0);
3397                 call_libraryfunc("__divuchar");
3398                 movwf(AOP(result),0);
3399         #else
3400                 pCodeOp *temp;
3401                 symbol *lbl;
3402
3403                 temp = popGetTempReg();
3404                 lbl = newiTempLabel(NULL);
3405                 
3406                 /* XXX: improve this naive approach:
3407                    [result] = [a] / [b]
3408                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3409
3410                    In PIC assembler:
3411                    movf  left,W
3412                    movwf temp           // temp <-- left
3413                    movf  right,W        // W <-- right
3414                    clrf  result
3415                    label1:
3416                    incf  result
3417                    subwf temp,F         // temp <-- temp - W
3418                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3419                    goto  label1
3420                    decf result          // we just subtract once too often
3421                  */
3422
3423                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3424                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3425                 
3426                 mov2w(AOP(left),0);
3427                 emitpcode(POC_MOVWF, temp);
3428                 mov2w(AOP(right),0);
3429                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3430
3431                 emitpLabel(lbl->key);
3432                 emitpcode(POC_INCF, popGet(AOP(result),0));
3433                 emitpcode(POC_SUBWF, temp);
3434                 emitSKPNC;
3435                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3436                 emitpcode(POC_DECF, popGet(AOP(result),0));
3437         #endif
3438         }
3439         else
3440         {
3441                 /* signed division */
3442                 mov2w(AOP(right),0);
3443                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3444                 mov2w(AOP(left),0);
3445                 call_libraryfunc("__divschar");
3446                 movwf(AOP(result),0);
3447         }
3448
3449         /* now performed the signed/unsigned division -- extend result */
3450         addSign(result, 1, sign);
3451 }
3452
3453 /*-----------------------------------------------------------------*/
3454 /* genDiv - generates code for division                            */
3455 /*-----------------------------------------------------------------*/
3456 static void genDiv (iCode *ic)
3457 {
3458         operand *left = IC_LEFT(ic);
3459         operand *right = IC_RIGHT(ic);
3460         operand *result= IC_RESULT(ic); 
3461         
3462         FENTRY;
3463         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3464         /* assign the amsops */
3465         aopOp (left,ic,FALSE);
3466         aopOp (right,ic,FALSE);
3467         aopOp (result,ic,TRUE);
3468         
3469         /* special cases first */
3470         /* both are bits */
3471         if (AOP_TYPE(left) == AOP_CRY &&
3472                 AOP_TYPE(right)== AOP_CRY) {
3473                 genDivbits(left,right,result);
3474                 goto release ;
3475         }
3476         
3477         /* if both are of size == 1 */
3478         if (AOP_SIZE(left) == 1 &&
3479                 AOP_SIZE(right) == 1 ) {
3480                 genDivOneByte(left,right,result);
3481                 goto release ;
3482         }
3483         
3484         /* should have been converted to function call */
3485         assert(0);
3486 release :
3487         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3488         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3489         freeAsmop(result,NULL,ic,TRUE); 
3490 }
3491
3492 /*-----------------------------------------------------------------*/
3493 /* genModOneByte : 8 bit modulus                                                                   */
3494 /*-----------------------------------------------------------------*/
3495 static void genModOneByte (operand *left,
3496                                                    operand *right,
3497                                                    operand *result)
3498 {
3499         int size;
3500         int sign;
3501         
3502         FENTRY;
3503         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3504         
3505         assert (AOP_SIZE(right) == 1);
3506         assert (AOP_SIZE(left) == 1);
3507
3508         size = min(AOP_SIZE(result),AOP_SIZE(left));
3509         sign = !(SPEC_USIGN(operandType(left))
3510                 && SPEC_USIGN(operandType(right)));
3511
3512         if (AOP_TYPE(right) == AOP_LIT)
3513         {
3514                 /* XXX: might add specialized code */
3515         }
3516
3517         if (!sign)
3518         {
3519                 /* unsigned division */
3520         #if 1
3521                 mov2w(AOP(right),0);
3522                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3523                 mov2w(AOP(left),0);
3524                 call_libraryfunc("__moduchar");
3525                 movwf(AOP(result),0);
3526         #else
3527                 pCodeOp *temp;
3528                 symbol *lbl;
3529
3530                 lbl = newiTempLabel(NULL);
3531                 
3532                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3533
3534                 /* XXX: improve this naive approach:
3535                    [result] = [a] % [b]
3536                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3537
3538                    In PIC assembler:
3539                    movf  left,W
3540                    movwf result         // result <-- left
3541                    movf  right,W        // W <-- right
3542                    label1:
3543                    subwf result,F       // result <-- result - W
3544                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3545                    goto  label1
3546                    addwf result, F      // we just subtract once too often
3547                  */
3548
3549                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3550                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3551                 
3552                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3553                 {
3554                         mov2w(AOP(left),0);
3555                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3556                 }
3557                 mov2w(AOP(right),0);
3558
3559                 emitpLabel(lbl->key);
3560                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3561                 emitSKPNC;
3562                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3563                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3564         #endif
3565         }
3566         else
3567         {
3568                 /* signed division */
3569                 mov2w(AOP(right),0);
3570                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3571                 mov2w(AOP(left),0);
3572                 call_libraryfunc("__modschar");
3573                 movwf(AOP(result),0);
3574         }
3575
3576         /* now we performed the signed/unsigned modulus -- extend result */
3577         addSign(result, 1, sign);
3578 }
3579
3580 /*-----------------------------------------------------------------*/
3581 /* genMod - generates code for division                                                    */
3582 /*-----------------------------------------------------------------*/
3583 static void genMod (iCode *ic)
3584 {
3585         operand *left = IC_LEFT(ic);
3586         operand *right = IC_RIGHT(ic);
3587         operand *result= IC_RESULT(ic);  
3588         
3589         FENTRY;
3590         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3591         /* assign the amsops */
3592         aopOp (left,ic,FALSE);
3593         aopOp (right,ic,FALSE);
3594         aopOp (result,ic,TRUE);
3595         
3596         /* if both are of size == 1 */
3597         if (AOP_SIZE(left) == 1 &&
3598                 AOP_SIZE(right) == 1 ) {
3599                 genModOneByte(left,right,result);
3600                 goto release ;
3601         }
3602         
3603         /* should have been converted to function call */
3604         assert(0);
3605         
3606 release :
3607         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3608         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3609         freeAsmop(result,NULL,ic,TRUE); 
3610 }
3611
3612 /*-----------------------------------------------------------------*/
3613 /* genIfxJump :- will create a jump depending on the ifx                   */
3614 /*-----------------------------------------------------------------*/
3615 /*
3616 note: May need to add parameter to indicate when a variable is in bit space.
3617 */
3618 static void genIfxJump (iCode *ic, char *jval)
3619 {
3620         
3621         FENTRY;
3622         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3623         /* if true label then we jump if condition
3624         supplied is true */
3625         if ( IC_TRUE(ic) ) {
3626                 
3627                 if(strcmp(jval,"a") == 0)
3628                         emitSKPZ;
3629                 else if (strcmp(jval,"c") == 0)
3630                         emitSKPC;
3631                 else {
3632                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3633                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3634                 }
3635                 
3636                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3637                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3638                 
3639         }
3640         else {
3641                 /* false label is present */
3642                 if(strcmp(jval,"a") == 0)
3643                         emitSKPNZ;
3644                 else if (strcmp(jval,"c") == 0)
3645                         emitSKPNC;
3646                 else {
3647                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3648                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3649                 }
3650                 
3651                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3652                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3653                 
3654         }
3655         
3656         
3657         /* mark the icode as generated */
3658         ic->generated = 1;
3659 }
3660
3661 #if 0
3662 /*-----------------------------------------------------------------*/
3663 /* genSkip                                                                                                                 */
3664 /*-----------------------------------------------------------------*/
3665 static void genSkip(iCode *ifx,int status_bit)
3666 {
3667         FENTRY;
3668         if(!ifx)
3669                 return;
3670         
3671         if ( IC_TRUE(ifx) ) {
3672                 switch(status_bit) {
3673                 case 'z':
3674                         emitSKPNZ;
3675                         break;
3676                         
3677                 case 'c':
3678                         emitSKPNC;
3679                         break;
3680                         
3681                 case 'd':
3682                         emitSKPDC;
3683                         break;
3684                         
3685                 }
3686                 
3687                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3688                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3689                 
3690         } else {
3691                 
3692                 switch(status_bit) {
3693                         
3694                 case 'z':
3695                         emitSKPZ;
3696                         break;
3697                         
3698                 case 'c':
3699                         emitSKPC;
3700                         break;
3701                         
3702                 case 'd':
3703                         emitSKPDC;
3704                         break;
3705                 }
3706                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3707                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3708                 
3709         }
3710         
3711 }
3712 #endif
3713
3714 /*-----------------------------------------------------------------*/
3715 /* genSkipc                                                                                                        */
3716 /*-----------------------------------------------------------------*/
3717 static void genSkipc(resolvedIfx *rifx)
3718 {
3719         FENTRY;
3720         if(!rifx)
3721                 return;
3722         
3723         if(rifx->condition)
3724                 emitSKPNC;
3725         else
3726                 emitSKPC;
3727         
3728         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3729         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3730         rifx->generated = 1;
3731 }
3732
3733 #if 0
3734 /*-----------------------------------------------------------------*/
3735 /* genSkipz2                                                                                                       */
3736 /*-----------------------------------------------------------------*/
3737 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3738 {
3739         FENTRY;
3740         if(!rifx)
3741                 return;
3742         
3743         if( (rifx->condition ^ invert_condition) & 1)
3744                 emitSKPZ;
3745         else
3746                 emitSKPNZ;
3747         
3748         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3749         rifx->generated = 1;
3750 }
3751 #endif
3752
3753 #if 0
3754 /*-----------------------------------------------------------------*/
3755 /* genSkipz                                                        */
3756 /*-----------------------------------------------------------------*/
3757 static void genSkipz(iCode *ifx, int condition)
3758 {
3759         FENTRY;
3760         assert (ifx != NULL);
3761         
3762         if(condition)
3763                 emitSKPNZ;
3764         else
3765                 emitSKPZ;
3766         
3767         if ( IC_TRUE(ifx) )
3768                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3769         else
3770                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3771         
3772         if ( IC_TRUE(ifx) )
3773                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3774         else
3775                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3776         
3777 }
3778 #endif
3779
3780 #if 0
3781 /*-----------------------------------------------------------------*/
3782 /* genSkipCond                                                     */
3783 /*-----------------------------------------------------------------*/
3784 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3785 {
3786         FENTRY;
3787         if(!rifx)
3788                 return;
3789         
3790         if(rifx->condition)
3791                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3792         else
3793                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3794         
3795         
3796         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3797         rifx->generated = 1;
3798 }
3799 #endif
3800
3801 #if 0
3802 /*-----------------------------------------------------------------*/
3803 /* genChkZeroes :- greater or less than comparison                 */
3804 /*     For each byte in a literal that is zero, inclusive or the   */
3805 /*     the corresponding byte in the operand with W                */
3806 /*     returns true if any of the bytes are zero                   */
3807 /*-----------------------------------------------------------------*/
3808 static int genChkZeroes(operand *op, int lit,  int size)
3809 {
3810         
3811         int i;
3812         int flag =1;
3813         
3814         while(size--) {
3815                 i = (lit >> (size*8)) & 0xff;
3816                 
3817                 if(i==0) {
3818                         if(flag) 
3819                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3820                         else
3821                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3822                         flag = 0;
3823                 }
3824         }
3825         
3826         return (flag==0);
3827 }
3828 #endif
3829
3830
3831 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3832 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3833 #define DEBUGpc           emitpComment
3834
3835 /*-----------------------------------------------------------------*/
3836 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3837 /*                  aop (if it's NOT a literal) or from lit (if    */
3838 /*                  aop is a literal)                              */
3839 /*-----------------------------------------------------------------*/
3840 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3841   if (aop->type == AOP_LIT) {
3842     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3843   } else {
3844     emitpcode (POC_MOVFW, popGet (aop, offset));
3845   }
3846 }
3847
3848 /* genCmp performs a left < right comparison, stores
3849  * the outcome in result (if != NULL) and generates
3850  * control flow code for the ifx (if != NULL).
3851  *
3852  * This version leaves in sequences like
3853  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3854  * which should be optmized by the peephole
3855  * optimizer - RN 2005-01-01 */
3856 static void genCmp (operand *left,operand *right,
3857                     operand *result, iCode *ifx, int sign)
3858 {
3859   resolvedIfx rIfx;
3860   int size;
3861   int offs;
3862   symbol *templbl;
3863   operand *dummy;
3864   unsigned long lit;
3865   unsigned long mask;
3866   int performedLt;
3867   int invert_result = 0;
3868
3869   FENTRY;
3870   
3871   assert (AOP_SIZE(left) == AOP_SIZE(right));
3872   assert (left && right);
3873
3874   size = AOP_SIZE(right) - 1;
3875   mask = (0x100UL << (size*8)) - 1;
3876   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3877   performedLt = 1;
3878   templbl = NULL;
3879   lit = 0;
3880   
3881   resolveIfx (&rIfx, ifx);
3882
3883   /**********************************************************************
3884    * handle bits - bit compares are promoted to int compares seemingly! *
3885    **********************************************************************/
3886 #if 0
3887   // THIS IS COMPLETELY UNTESTED!
3888   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3889     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3890     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3891     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3892
3893     emitSETC;
3894     // 1 < {0,1} is false --> clear C by skipping the next instruction
3895     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3896     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3897     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3898     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3899     emitCLRC; // only skipped for left=0 && right=1
3900
3901     goto correct_result_in_carry;
3902   } // if
3903 #endif
3904
3905   /*************************************************
3906    * make sure that left is register (or the like) *
3907    *************************************************/
3908   if (!isAOP_REGlike(left)) {
3909     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3910     assert (isAOP_LIT(left));
3911     assert (isAOP_REGlike(right));
3912     // swap left and right
3913     // left < right <==> right > left <==> (right >= left + 1)
3914     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3915
3916     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3917       // MAXVALUE < right? always false
3918       if (performedLt) emitCLRC; else emitSETC;
3919       goto correct_result_in_carry;
3920     } // if
3921
3922     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3923     // that's why we handled it above.
3924     lit++;
3925
3926     dummy = left;
3927     left = right;
3928     right = dummy;
3929
3930     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3931   } else if (isAOP_LIT(right)) {
3932     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3933   } // if
3934
3935   assert (isAOP_REGlike(left)); // left must be register or the like
3936   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3937
3938   /*************************************************
3939    * special cases go here                         *
3940    *************************************************/
3941
3942   if (isAOP_LIT(right)) {
3943     if (!sign) {
3944       // unsigned comparison to a literal
3945       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3946       if (lit == 0) {
3947         // unsigned left < 0? always false
3948         if (performedLt) emitCLRC; else emitSETC;
3949         goto correct_result_in_carry;
3950       }
3951     } else {
3952       // signed comparison to a literal
3953       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3954       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3955         // signed left < 0x80000000? always false
3956         if (performedLt) emitCLRC; else emitSETC;
3957         goto correct_result_in_carry;
3958       } else if (lit == 0) {
3959         // compare left < 0; set CARRY if SIGNBIT(left) is set
3960         if (performedLt) emitSETC; else emitCLRC;
3961         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3962         if (performedLt) emitCLRC; else emitSETC;
3963         goto correct_result_in_carry;
3964       }
3965     } // if (!sign)
3966   } // right is literal
3967
3968   /*************************************************
3969    * perform a general case comparison             *
3970    * make sure we get CARRY==1 <==> left >= right  *
3971    *************************************************/
3972   // compare most significant bytes
3973   //DEBUGpc ("comparing bytes at offset %d", size);
3974   if (!sign) {
3975     // unsigned comparison
3976     pic14_mov2w_regOrLit (AOP(right), lit, size);
3977     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3978   } else {
3979     // signed comparison
3980     // (add 2^n to both operands then perform an unsigned comparison)
3981     if (isAOP_LIT(right)) {
3982       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3983       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3984
3985       if (litbyte == 0x80) {
3986         // left >= 0x80 -- always true, but more bytes to come
3987         mov2w (AOP(left), size);
3988         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3989         emitSETC;
3990       } else {
3991         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3992         mov2w (AOP(left), size);
3993         emitpcode (POC_ADDLW, popGetLit (0x80));
3994         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3995       } // if
3996     } else {
3997       pCodeOp *pctemp = popGetTempReg();
3998       mov2w (AOP(left), size);
3999       emitpcode (POC_ADDLW, popGetLit (0x80));
4000       emitpcode (POC_MOVWF, pctemp);
4001       mov2w (AOP(right), size);
4002       emitpcode (POC_ADDLW, popGetLit (0x80));
4003       emitpcode (POC_SUBFW, pctemp);
4004       popReleaseTempReg(pctemp);
4005     }
4006   } // if (!sign)
4007
4008   // compare remaining bytes (treat as unsigned case from above)
4009   templbl = newiTempLabel ( NULL );
4010   offs = size;
4011   while (offs--) {
4012     //DEBUGpc ("comparing bytes at offset %d", offs);
4013     emitSKPZ;
4014     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4015     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4016     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4017   } // while (offs)
4018   emitpLabel (templbl->key);
4019   goto result_in_carry;
4020
4021 result_in_carry:
4022   
4023   /****************************************************
4024    * now CARRY contains the result of the comparison: *
4025    * SUBWF sets CARRY iff                             *
4026    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4027    * (F=left, W=right)                                *
4028    ****************************************************/
4029
4030   if (performedLt) {
4031     invert_result = 1;
4032     // value will be used in the following genSkipc()
4033     rIfx.condition ^= 1;
4034   } // if
4035
4036 correct_result_in_carry:
4037
4038   // assign result to variable (if neccessary)
4039   if (result && AOP_TYPE(result) != AOP_CRY) {
4040     //DEBUGpc ("assign result");
4041     size = AOP_SIZE(result);
4042     while (size--) {
4043       emitpcode (POC_CLRF, popGet (AOP(result), size));
4044     } // while
4045     if (invert_result) {
4046       emitSKPC;
4047       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4048     } else {
4049       emitpcode (POC_RLF, popGet (AOP(result), 0));
4050     }
4051   } // if (result)
4052
4053   // perform conditional jump
4054   if (ifx) {
4055     //DEBUGpc ("generate control flow");
4056     genSkipc (&rIfx);
4057     ifx->generated = 1;
4058   } // if
4059 }
4060
4061
4062 #if 0
4063 /* OLD VERSION -- BUGGY, DO NOT USE */
4064
4065 /*-----------------------------------------------------------------*/
4066 /* genCmp :- greater or less than comparison                       */
4067 /*-----------------------------------------------------------------*/
4068 static void genCmp (operand *left,operand *right,
4069                                         operand *result, iCode *ifx, int sign)
4070 {
4071         int size; //, offset = 0 ;
4072         unsigned long lit = 0L,i = 0;
4073         resolvedIfx rFalseIfx;
4074         //  resolvedIfx rTrueIfx;
4075         symbol *truelbl;
4076
4077         FENTRY;
4078         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4079         /*
4080         if(ifx) {
4081         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4082         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4083         }
4084         */
4085         
4086         resolveIfx(&rFalseIfx,ifx);
4087         truelbl  = newiTempLabel(NULL);
4088         size = max(AOP_SIZE(left),AOP_SIZE(right));
4089         
4090         DEBUGpic14_AopType(__LINE__,left,right,result);
4091         
4092 #define _swapp
4093         
4094         /* if literal is on the right then swap with left */
4095         if ((AOP_TYPE(right) == AOP_LIT)) {
4096                 operand *tmp = right ;
4097                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4098                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4099 #ifdef _swapp
4100                 
4101                 lit = (lit - 1) & mask;
4102                 right = left;
4103                 left = tmp;
4104                 rFalseIfx.condition ^= 1;
4105 #endif
4106                 
4107         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4108                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4109         }
4110         
4111         
4112         //if(IC_TRUE(ifx) == NULL)
4113         /* if left & right are bit variables */
4114         if (AOP_TYPE(left) == AOP_CRY &&
4115                 AOP_TYPE(right) == AOP_CRY ) {
4116                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4117                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4118         } else {
4119         /* subtract right from left if at the
4120         end the carry flag is set then we know that
4121                 left is greater than right */
4122                 
4123                 symbol *lbl  = newiTempLabel(NULL);
4124                 
4125 #ifndef _swapp
4126                 if(AOP_TYPE(right) == AOP_LIT) {
4127                         
4128                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4129                         
4130                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4131                         
4132                         /* special cases */
4133                         
4134                         if(lit == 0) {
4135                                 
4136                                 if(sign != 0) 
4137                                         genSkipCond(&rFalseIfx,left,size-1,7);
4138                                 else 
4139                                         /* no need to compare to 0...*/
4140                                         /* NOTE: this is a de-generate compare that most certainly 
4141                                         *       creates some dead code. */
4142                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4143                                 
4144                                 if(ifx) ifx->generated = 1;
4145                                 return;
4146                                 
4147                         }
4148                         size--;
4149                         
4150                         if(size == 0) {
4151                                 //i = (lit >> (size*8)) & 0xff;
4152                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4153                                 
4154                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4155                                 
4156                                 i = ((0-lit) & 0xff);
4157                                 if(sign) {
4158                                         if( i == 0x81) { 
4159                                         /* lit is 0x7f, all signed chars are less than
4160                                                 * this except for 0x7f itself */
4161                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4162                                                 genSkipz2(&rFalseIfx,0);
4163                                         } else {
4164                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4165                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4166                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4167                                         }
4168                                         
4169                                 } else {
4170                                         if(lit == 1) {
4171                                                 genSkipz2(&rFalseIfx,1);
4172                                         } else {
4173                                                 emitpcode(POC_ADDLW, popGetLit(i));
4174                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4175                                         }
4176                                 }
4177                                 
4178                                 if(ifx) ifx->generated = 1;
4179                                 return;
4180                         }
4181                         
4182                         /* chars are out of the way. now do ints and longs */
4183                         
4184                         
4185                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4186                         
4187                         /* special cases */
4188                         
4189                         if(sign) {
4190                                 
4191                                 if(lit == 0) {
4192                                         genSkipCond(&rFalseIfx,left,size,7);
4193                                         if(ifx) ifx->generated = 1;
4194                                         return;
4195                                 }
4196                                 
4197                                 if(lit <0x100) {
4198                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4199                                         
4200                                         //rFalseIfx.condition ^= 1;
4201                                         //genSkipCond(&rFalseIfx,left,size,7);
4202                                         //rFalseIfx.condition ^= 1;
4203                                         
4204                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4205                                         if(rFalseIfx.condition)
4206                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4207                                         else
4208                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4209                                         
4210                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4211                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4212                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4213                                         
4214                                         while(size > 1)
4215                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4216                                         
4217                                         if(rFalseIfx.condition) {
4218                                                 emitSKPZ;
4219                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4220                                                 
4221                                         } else {
4222                                                 emitSKPNZ;
4223                                         }
4224                                         
4225                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4226                                         emitpLabel(truelbl->key);
4227                                         if(ifx) ifx->generated = 1;
4228                                         return;
4229                                         
4230                                 }
4231                                 
4232                                 if(size == 1) {
4233                                         
4234                                         if( (lit & 0xff) == 0) {
4235                                                 /* lower byte is zero */
4236                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4237                                                 i = ((lit >> 8) & 0xff) ^0x80;
4238                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4239                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4240                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4241                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4242                                                 
4243                                                 
4244                                                 if(ifx) ifx->generated = 1;
4245                                                 return;
4246                                                 
4247                                         }
4248                                 } else {
4249                                         /* Special cases for signed longs */
4250                                         if( (lit & 0xffffff) == 0) {
4251                                                 /* lower byte is zero */
4252                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4253                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4254                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4255                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4256                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4257                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4258                                                 
4259                                                 
4260                                                 if(ifx) ifx->generated = 1;
4261                                                 return;
4262                                                 
4263                                         }
4264                                         
4265                                 }
4266                                 
4267                                 
4268                                 if(lit & (0x80 << (size*8))) {
4269                                         /* lit is negative */
4270                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4271                                         
4272                                         //genSkipCond(&rFalseIfx,left,size,7);
4273                                         
4274                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4275                                         
4276                                         if(rFalseIfx.condition)
4277                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4278                                         else
4279                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4280                                         
4281                                         
4282                                 } else {
4283                                         /* lit is positive */
4284                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4285                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4286                                         if(rFalseIfx.condition)
4287                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4288                                         else
4289                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4290                                         
4291                                 }
4292                                 
4293                                 /* There are no more special cases, so perform a general compare */
4294                                 
4295                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4296                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4297                                 
4298                                 while(size--) {
4299                                         
4300                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4301                                         emitSKPNZ;
4302                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4303                                 }
4304                                 //rFalseIfx.condition ^= 1;
4305                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4306                                 
4307                                 emitpLabel(truelbl->key);
4308                                 
4309                                 if(ifx) ifx->generated = 1;
4310                                 return;
4311                                 
4312                                 
4313                         }
4314
4315
4316                         /* sign is out of the way. So now do an unsigned compare */
4317                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4318
4319
4320                         /* General case - compare to an unsigned literal on the right.*/
4321
4322                         i = (lit >> (size*8)) & 0xff;
4323                         emitpcode(POC_MOVLW, popGetLit(i));
4324                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4325                         while(size--) {
4326                                 i = (lit >> (size*8)) & 0xff;
4327                                 
4328                                 if(i) {
4329                                         emitpcode(POC_MOVLW, popGetLit(i));
4330                                         emitSKPNZ;
4331                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4332                                 } else {
4333                                 /* this byte of the lit is zero, 
4334                                         *if it's not the last then OR in the variable */
4335                                         if(size)
4336                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4337                                 }
4338                         }
4339
4340
4341                 emitpLabel(lbl->key);
4342                 //if(emitFinalCheck)
4343                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4344                 if(sign)
4345                         emitpLabel(truelbl->key);
4346
4347                 if(ifx) ifx->generated = 1;
4348                 return;
4349
4350
4351                 }
4352 #endif  // _swapp
4353
4354                 if(AOP_TYPE(left) == AOP_LIT) {
4355                         //symbol *lbl = newiTempLabel(NULL);
4356                         
4357                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4358                         
4359                         
4360                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4361                         
4362                         /* Special cases */
4363                         if((lit == 0) && (sign == 0)){
4364                                 
4365                                 size--;
4366                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4367                                 while(size) 
4368                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4369                                 
4370                                 genSkipz2(&rFalseIfx,0);
4371                                 if(ifx) ifx->generated = 1;
4372                                 return;
4373                         }
4374                         
4375                         if(size==1) {
4376                                 /* Special cases */
4377                                 lit &= 0xff;
4378                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4379                                         /* degenerate compare can never be true */
4380                                         if(rFalseIfx.condition == 0)
4381                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4382                                         
4383                                         if(ifx) ifx->generated = 1;
4384                                         return;
4385                                 }
4386                                 
4387                                 if(sign) {
4388                                         /* signed comparisons to a literal byte */
4389                                         
4390                                         int lp1 = (lit+1) & 0xff;
4391                                         
4392                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4393                                         switch (lp1) {
4394                                         case 0:
4395                                                 rFalseIfx.condition ^= 1;
4396                                                 genSkipCond(&rFalseIfx,right,0,7);
4397                                                 break;
4398                                         case 0x7f:
4399                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4400                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4401                                                 genSkipz2(&rFalseIfx,1);
4402                                                 break;
4403                                         default:
4404                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4405                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4406                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4407                                                 rFalseIfx.condition ^= 1;
4408                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4409                                                 break;
4410                                         }
4411                                         if(ifx) ifx->generated = 1;
4412                                 } else {
4413                                         /* unsigned comparisons to a literal byte */
4414                                         
4415                                         switch(lit & 0xff ) {
4416                                         case 0:
4417                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4418                                                 genSkipz2(&rFalseIfx,0);
4419                                                 if(ifx) ifx->generated = 1;
4420                                                 break;
4421                                         case 0x7f:
4422                                                 genSkipCond(&rFalseIfx,right,0,7);
4423                                                 if(ifx) ifx->generated = 1;
4424                                                 break;
4425                                                 
4426                                         default:
4427                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4428                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4429                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4430                                                 rFalseIfx.condition ^= 1;
4431                                                 if (AOP_TYPE(result) == AOP_CRY) {
4432                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4433                                                         if(ifx) ifx->generated = 1;
4434                                                 } else {
4435                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4436                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4437                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4438                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4439                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4440                                                 }       
4441                                                 break;
4442                                         }
4443                                 }
4444                                 
4445                                 //goto check_carry;
4446                                 return;
4447                                 
4448                         } else {
4449                                 
4450                                 /* Size is greater than 1 */
4451                                 
4452                                 if(sign) {
4453                                         int lp1 = lit+1;
4454                                         
4455                                         size--;
4456                                         
4457                                         if(lp1 == 0) {
4458                                                 /* this means lit = 0xffffffff, or -1 */
4459                                                 
4460                                                 
4461                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4462                                                 rFalseIfx.condition ^= 1;
4463                                                 genSkipCond(&rFalseIfx,right,size,7);
4464                                                 if(ifx) ifx->generated = 1;
4465                                                 return;
4466                                         }
4467                                         
4468                                         if(lit == 0) {
4469                                                 int s = size;
4470                                                 
4471                                                 if(rFalseIfx.condition) {
4472                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4473                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4474                                                 }
4475                                                 
4476                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4477                                                 while(size--)
4478                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4479                                                 
4480                                                 
4481                                                 emitSKPZ;
4482                                                 if(rFalseIfx.condition) {
4483                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4484                                                         emitpLabel(truelbl->key);
4485                                                 }else {
4486                                                         rFalseIfx.condition ^= 1;
4487                                                         genSkipCond(&rFalseIfx,right,s,7);
4488                                                 }
4489                                                 
4490                                                 if(ifx) ifx->generated = 1;
4491                                                 return;
4492                                         }
4493                                         
4494                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4495                                                 /* lower byte of signed word is zero */
4496                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4497                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4498                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4499                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4500                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4501                                                 rFalseIfx.condition ^= 1;
4502                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4503                                                 
4504                                                 
4505                                                 if(ifx) ifx->generated = 1;
4506                                                 return;
4507                                         }
4508                                         
4509                                         if(lit & (0x80 << (size*8))) {
4510                                                 /* Lit is less than zero */
4511                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4512                                                 //rFalseIfx.condition ^= 1;
4513                                                 //genSkipCond(&rFalseIfx,left,size,7);
4514                                                 //rFalseIfx.condition ^= 1;
4515                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4516                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4517                                                 
4518                                                 if(rFalseIfx.condition)
4519                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4520                                                 else
4521                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4522                                                 
4523                                                 
4524                                         } else {
4525                                                 /* Lit is greater than or equal to zero */
4526                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4527                                                 //rFalseIfx.condition ^= 1;
4528                                                 //genSkipCond(&rFalseIfx,right,size,7);
4529                                                 //rFalseIfx.condition ^= 1;
4530                                                 
4531                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4532                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4533                                                 
4534                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4535                                                 if(rFalseIfx.condition)
4536                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4537                                                 else
4538                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4539                                                 
4540                                         }
4541                                         
4542                                         
4543                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4544                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4545                                         
4546                                         while(size--) {
4547                                                 
4548                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4549                                                 emitSKPNZ;
4550                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4551                                         }
4552                                         rFalseIfx.condition ^= 1;
4553                                         //rFalseIfx.condition = 1;
4554                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4555                                         
4556                                         emitpLabel(truelbl->key);
4557                                         
4558                                         if(ifx) ifx->generated = 1;
4559                                         return;
4560                                         // end of if (sign)
4561                                 } else {
4562                                         
4563                                         /* compare word or long to an unsigned literal on the right.*/
4564                                         
4565                                         
4566                                         size--;
4567                                         if(lit < 0xff) {
4568                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4569                                                 switch (lit) {
4570                                                 case 0:
4571                                                         break; /* handled above */
4572                                                 /*
4573                                                 case 0xff:
4574                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4575                                                         while(size--)
4576                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4577                                                         genSkipz2(&rFalseIfx,0);
4578                                                         break;
4579                                                 */
4580                                                 default:
4581                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4582                                                         while(--size)
4583                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4584                                                         
4585                                                         emitSKPZ;
4586                                                         if(rFalseIfx.condition)
4587                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4588                                                         else
4589                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4590                                                         
4591                                                         
4592                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4593                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4594                                                         
4595                                                         rFalseIfx.condition ^= 1;
4596                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4597                                                 }
4598                                                 
4599                                                 emitpLabel(truelbl->key);
4600                                                 
4601                                                 if(ifx) ifx->generated = 1;
4602                                                 return;
4603                                         }
4604                                         
4605                                         
4606                                         lit++;
4607                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4608                                         i = (lit >> (size*8)) & 0xff;
4609                                         
4610                                         emitpcode(POC_MOVLW, popGetLit(i));
4611                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4612                                         
4613                                         while(size--) {
4614                                                 i = (lit >> (size*8)) & 0xff;
4615                                                 
4616                                                 if(i) {
4617                                                         emitpcode(POC_MOVLW, popGetLit(i));
4618                                                         emitSKPNZ;
4619                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4620                                                 } else {
4621                                                 /* this byte of the lit is zero, 
4622                                                         *if it's not the last then OR in the variable */
4623                                                         if(size)
4624                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4625                                                 }
4626                                         }
4627                                         
4628                                         
4629                                         emitpLabel(lbl->key);
4630                                         
4631                                         rFalseIfx.condition ^= 1;
4632                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4633                                 }
4634                                 
4635                                 if(sign)
4636                                         emitpLabel(truelbl->key);
4637                                 if(ifx) ifx->generated = 1;
4638                                 return;
4639                         }
4640                 }
4641                 /* Compare two variables */
4642                 
4643                 DEBUGpic14_emitcode(";sign","%d",sign);
4644                 
4645                 size--;
4646                 if(sign) {
4647                         /* Sigh. thus sucks... */
4648                         if(size) {
4649                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4650                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4651                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4652                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4653                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4654                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4655                         } else {
4656                                 /* Signed char comparison */
4657                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4658                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4659                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4660                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4661                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4662                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4663                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4664                                 
4665                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4666                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4667                                 
4668                                 if(ifx) ifx->generated = 1;
4669                                 return;
4670                         }
4671                         
4672                 } else {
4673                         
4674                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4675                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4676                 }
4677                 
4678                 
4679                 /* The rest of the bytes of a multi-byte compare */
4680                 while (size) {
4681                         
4682                         emitSKPZ;
4683                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4684                         size--;
4685                         
4686                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4687                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4688                         
4689                         
4690                 }
4691                 
4692                 emitpLabel(lbl->key);
4693                 
4694                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4695                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4696                         (AOP_TYPE(result) == AOP_REG)) {
4697                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4698                         emitpcode(POC_RLF, popGet(AOP(result),0));
4699                 } else {
4700                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4701                 }       
4702                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4703                 if(ifx) ifx->generated = 1;
4704                 
4705                 return;
4706                 
4707         }
4708         
4709         // check_carry:
4710         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4711                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4712                 pic14_outBitC(result);
4713         } else {
4714                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4715                 /* if the result is used in the next
4716                 ifx conditional branch then generate
4717                 code a little differently */
4718                 if (ifx )
4719                         genIfxJump (ifx,"c");
4720                 else
4721                         pic14_outBitC(result);
4722                 /* leave the result in acc */
4723         }
4724         
4725 }
4726 #endif
4727
4728 /*-----------------------------------------------------------------*/
4729 /* genCmpGt :- greater than comparison                             */
4730 /*-----------------------------------------------------------------*/
4731 static void genCmpGt (iCode *ic, iCode *ifx)
4732 {
4733         operand *left, *right, *result;
4734         sym_link *letype , *retype;
4735         int sign ;
4736         
4737         FENTRY;
4738         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4739         left = IC_LEFT(ic);
4740         right= IC_RIGHT(ic);
4741         result = IC_RESULT(ic);
4742         
4743         letype = getSpec(operandType(left));
4744         retype =getSpec(operandType(right));
4745         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4746         /* assign the amsops */
4747         aopOp (left,ic,FALSE);
4748         aopOp (right,ic,FALSE);
4749         aopOp (result,ic,TRUE);
4750         
4751         genCmp(right, left, result, ifx, sign);
4752         
4753         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4754         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4755         freeAsmop(result,NULL,ic,TRUE); 
4756 }
4757
4758 /*-----------------------------------------------------------------*/
4759 /* genCmpLt - less than comparisons                                */
4760 /*-----------------------------------------------------------------*/
4761 static void genCmpLt (iCode *ic, iCode *ifx)
4762 {
4763         operand *left, *right, *result;
4764         sym_link *letype , *retype;
4765         int sign ;
4766         
4767         FENTRY;
4768         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4769         left = IC_LEFT(ic);
4770         right= IC_RIGHT(ic);
4771         result = IC_RESULT(ic);
4772         
4773         letype = getSpec(operandType(left));
4774         retype =getSpec(operandType(right));
4775         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4776         
4777         /* assign the amsops */
4778         aopOp (left,ic,FALSE);
4779         aopOp (right,ic,FALSE);
4780         aopOp (result,ic,TRUE);
4781         
4782         genCmp(left, right, result, ifx, sign);
4783         
4784         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4785         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4786         freeAsmop(result,NULL,ic,TRUE); 
4787 }
4788
4789 #if 0
4790 /*-----------------------------------------------------------------*/
4791 /* genc16bit2lit - compare a 16 bit value to a literal             */
4792 /*-----------------------------------------------------------------*/
4793 static void genc16bit2lit(operand *op, int lit, int offset)
4794 {
4795         int i;
4796         
4797         FENTRY;
4798         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4799         if( (lit&0xff) == 0) 
4800                 i=1;
4801         else
4802                 i=0;
4803         
4804         switch( BYTEofLONG(lit,i)) { 
4805         case 0:
4806                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4807                 break;
4808         case 1:
4809                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4810                 break;
4811         case 0xff:
4812                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4813                 break;
4814         default:
4815                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4816                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4817         }
4818         
4819         i ^= 1;
4820         
4821         switch( BYTEofLONG(lit,i)) { 
4822         case 0:
4823                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4824                 break;
4825         case 1:
4826                 emitSKPNZ;
4827                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4828                 break;
4829         case 0xff:
4830                 emitSKPNZ;
4831                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4832                 break;
4833         default:
4834                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4835                 emitSKPNZ;
4836                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4837                 
4838         }
4839         
4840 }
4841 #endif
4842
4843 #if 0
4844 /*-----------------------------------------------------------------*/
4845 /* gencjneshort - compare and jump if not equal                    */
4846 /*-----------------------------------------------------------------*/
4847 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4848 {
4849         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4850         int offset = 0;
4851         //resolvedIfx rIfx;
4852         symbol *lbl;
4853         
4854         //unsigned long lit = 0L;
4855         FENTRY;
4856         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4857           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4858           return;
4859         }
4860         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4861         DEBUGpic14_AopType(__LINE__,left,right,result);
4862         
4863         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4864         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4865         if (AOP_SIZE(result)) {
4866           for (offset = 0; offset < AOP_SIZE(result); offset++)
4867             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4868         }
4869         
4870         assert (AOP_SIZE(left) == AOP_SIZE(right));
4871         //resolveIfx(&rIfx,ifx);
4872         lbl = newiTempLabel (NULL);
4873         while (size--)
4874         {
4875           mov2w (AOP(right),size);
4876           emitpcode (POC_XORFW, popGet (AOP(left), size));
4877           if (size)
4878           {
4879             emitSKPZ;
4880             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4881           }
4882         } // while
4883         emitpLabel (lbl->key);
4884         if (AOP_SIZE(result)) {
4885           emitSKPNZ;
4886           emitpcode (POC_INCF, popGet (AOP(result), 0));
4887         } else {
4888           assert (ifx);
4889           genSkipz (ifx, NULL != IC_TRUE(ifx));
4890           ifx->generated = 1;
4891         }
4892         return;
4893 #if 0   
4894         if(result)
4895         {
4896                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4897                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4898                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4899                 for (offset=0; offset < AOP_SIZE(result); offset++)
4900                 {
4901                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4902                 } // for offset
4903         }
4904         
4905         
4906         /* if the left side is a literal or 
4907         if the right is in a pointer register and left 
4908         is not */
4909         if ((AOP_TYPE(left) == AOP_LIT) || 
4910                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4911                 operand *t = right;
4912                 right = left;
4913                 left = t;
4914         }
4915         if(AOP_TYPE(right) == AOP_LIT)
4916                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4917         
4918         /* if the right side is a literal then anything goes */
4919         if (AOP_TYPE(right) == AOP_LIT &&
4920                 AOP_TYPE(left) != AOP_DIR ) {
4921                 switch(size) {
4922                 case 2:
4923                         genc16bit2lit(left, lit, 0);
4924                         emitSKPNZ;
4925                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4926                         break;
4927                 default:
4928                         offset = 0;
4929                         while (size--) {
4930                                 if(lit & 0xff) {
4931                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4932                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4933                                 } else {
4934                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4935                                 }
4936                                 
4937                                 emitSKPNZ;
4938                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4939                                 offset++;
4940                                 lit >>= 8;
4941                         }
4942                         break;
4943                 }
4944         }
4945         
4946         /* if the right side is in a register or in direct space or
4947         if the left is a pointer register & right is not */    
4948         else if (AOP_TYPE(right) == AOP_REG ||
4949                 AOP_TYPE(right) == AOP_DIR || 
4950                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4951                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4952                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4953                 int lbl_key = lbl->key;
4954                 
4955                 if(!result) {
4956                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4957                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4958                                 __FUNCTION__,__LINE__);
4959                         return;
4960                 }
4961                 
4962                 /*     switch(size) { */
4963                 /*     case 2: */
4964                 /*       genc16bit2lit(left, lit, 0); */
4965                 /*       emitSKPNZ; */
4966                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4967                 /*       break; */
4968                 /*     default: */
4969                 offset = 0;
4970                 while (size--) {
4971                         int emit_skip=1;
4972                         if((AOP_TYPE(left) == AOP_DIR) && 
4973                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4974                                 
4975                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4976                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4977                                 
4978                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4979                                 
4980                                 switch (lit & 0xff) {
4981                                 case 0:
4982                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4983                                         break;
4984                                 case 1:
4985                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4986                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4987                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4988                                         emit_skip=0;
4989                                         break;
4990                                 case 0xff:
4991                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4992                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4993                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4994                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4995                                         emit_skip=0;
4996                                         break;
4997                                 default:
4998                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4999                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5000                                 }
5001                                 lit >>= 8;
5002                                 
5003                         } else {
5004                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5005                         }
5006                         if(emit_skip) {
5007                                 if(AOP_TYPE(result) == AOP_CRY) {
5008                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5009                                         if(rIfx.condition)
5010                                                 emitSKPNZ;
5011                                         else
5012                                                 emitSKPZ;
5013                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5014                                 } else {
5015                                         /* fix me. probably need to check result size too */
5016                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5017                                         if(rIfx.condition)
5018                                                 emitSKPZ;
5019                                         else
5020                                                 emitSKPNZ;
5021                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5022                                 }
5023                                 if(ifx)
5024                                         ifx->generated=1;
5025                         }
5026                         emit_skip++;
5027                         offset++;
5028                 }
5029                 /*       break; */
5030                 /*     } */
5031         } else if(AOP_TYPE(right) == AOP_REG &&
5032                 AOP_TYPE(left) != AOP_DIR){
5033
5034                 offset = 0;
5035                 while(size--) {
5036                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5037                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5038                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5039                         if(rIfx.condition)
5040                                 emitSKPNZ;
5041                         else
5042                                 emitSKPZ;
5043                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5044                         offset++;
5045                 }
5046                 
5047         }else{
5048                 /* right is a pointer reg need both a & b */
5049                 offset = 0;
5050                 while(size--) {
5051                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5052                         if(strcmp(l,"b"))
5053                                 pic14_emitcode("mov","b,%s",l);
5054                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5055                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5056                         offset++;
5057                 }
5058         }
5059         
5060         emitpcode(POC_INCF,popGet(AOP(result),0));
5061         if(!rIfx.condition)
5062                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5063         
5064         emitpLabel(lbl->key);
5065         
5066         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5067         
5068         if(ifx)
5069                 ifx->generated = 1;
5070 #endif
5071 }
5072 #endif
5073
5074 #if 0
5075 /*-----------------------------------------------------------------*/
5076 /* gencjne - compare and jump if not equal                         */
5077 /*-----------------------------------------------------------------*/
5078 static void gencjne(operand *left, operand *right, iCode *ifx)
5079 {
5080         symbol *tlbl  = newiTempLabel(NULL);
5081         
5082         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5083         gencjneshort(left, right, lbl);
5084         
5085         pic14_emitcode("mov","a,%s",one);
5086         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5087         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5088         pic14_emitcode("clr","a");
5089         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5090         
5091         emitpLabel(lbl->key);
5092         emitpLabel(tlbl->key);
5093         
5094 }
5095 #endif
5096
5097 /*-----------------------------------------------------------------*/
5098 /* genCmpEq - generates code for equal to                          */
5099 /*-----------------------------------------------------------------*/
5100 static void genCmpEq (iCode *ic, iCode *ifx)
5101 {
5102   operand *left, *right, *result;
5103   int size;
5104   symbol *false_label;
5105
5106   FENTRY;
5107   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5108
5109   if(ifx)
5110     DEBUGpic14_emitcode ("; ifx is non-null","");
5111   else
5112     DEBUGpic14_emitcode ("; ifx is null","");
5113
5114   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5115   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5116   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5117
5118   DEBUGpic14_AopType(__LINE__,left,right,result);
5119
5120   /* if literal, move literal to right */ 
5121   if (op_isLitLike (IC_LEFT(ic))) {
5122     operand *tmp = right ;
5123     right = left;
5124     left = tmp;
5125   }
5126
5127   false_label = NULL;
5128   if (ifx && !IC_TRUE(ifx))
5129   {
5130     assert (IC_FALSE(ifx));
5131     false_label = IC_FALSE(ifx);
5132   }
5133
5134   size = min(AOP_SIZE(left),AOP_SIZE(right));
5135   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5136   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5137
5138   /* assume left != right */
5139   {
5140     int i;
5141     for (i=0; i < AOP_SIZE(result); i++)
5142     {
5143       emitpcode(POC_CLRF, popGet(AOP(result),i));
5144     }
5145   }
5146
5147   if (AOP_TYPE(right) == AOP_LIT)
5148   {
5149     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5150     int i;
5151     size = AOP_SIZE(left);
5152     assert(!op_isLitLike(left));
5153
5154     switch (lit)
5155     {
5156       case 0:
5157         mov2w(AOP(left), 0);
5158         for (i=1; i < size; i++)
5159           emitpcode(POC_IORFW,popGet(AOP(left),i));
5160         /* now Z is set iff `left == right' */
5161         emitSKPZ;
5162         if (!false_label) false_label = newiTempLabel(NULL);
5163         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5164         break;
5165
5166       default:
5167         for (i=0; i < size; i++)
5168         {
5169           mov2w(AOP(left),i);
5170           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5171           /* now Z is cleared if `left != right' */
5172           emitSKPZ;
5173           if (!false_label) false_label = newiTempLabel(NULL);
5174           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5175         } // for i
5176         break;
5177     } // switch (lit)
5178   }
5179   else
5180   {
5181     /* right is no literal */
5182     int i;
5183
5184     for (i=0; i < size; i++)
5185     {
5186       mov2w(AOP(right),i);
5187       emitpcode(POC_XORFW,popGet(AOP(left),i));
5188       /* now Z is cleared if `left != right' */
5189       emitSKPZ;
5190       if (!false_label) false_label = newiTempLabel(NULL);
5191       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5192     } // for i
5193   }
5194
5195   /* if we reach here, left == right */
5196
5197   if (AOP_SIZE(result) > 0)
5198   {
5199     emitpcode(POC_INCF, popGet(AOP(result),0));
5200   }
5201
5202   if (ifx && IC_TRUE(ifx))
5203   {
5204     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5205   }
5206
5207   if (false_label && (!ifx || IC_TRUE(ifx)))
5208     emitpLabel(false_label->key);
5209
5210   if (ifx) ifx->generated = 1;
5211
5212   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5213   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5214   freeAsmop(result,NULL,ic,TRUE);
5215 }
5216
5217 /*-----------------------------------------------------------------*/
5218 /* ifxForOp - returns the icode containing the ifx for operand     */
5219 /*-----------------------------------------------------------------*/
5220 static iCode *ifxForOp ( operand *op, iCode *ic )
5221 {
5222         FENTRY;
5223         /* if true symbol then needs to be assigned */
5224         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5225         if (IS_TRUE_SYMOP(op))
5226                 return NULL ;
5227         
5228         /* if this has register type condition and
5229         the next instruction is ifx with the same operand
5230         and live to of the operand is upto the ifx only then */
5231         if (ic->next &&
5232                 ic->next->op == IFX &&
5233                 IC_COND(ic->next)->key == op->key &&
5234                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5235                 return ic->next;
5236         
5237         if (ic->next &&
5238                 ic->next->op == IFX &&
5239                 IC_COND(ic->next)->key == op->key) {
5240                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5241                 return ic->next;
5242         }
5243         
5244         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5245         if (ic->next &&
5246                 ic->next->op == IFX)
5247                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5248         
5249         if (ic->next &&
5250                 ic->next->op == IFX &&
5251                 IC_COND(ic->next)->key == op->key) {
5252                 DEBUGpic14_emitcode ("; "," key is okay");
5253                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5254                         OP_SYMBOL(op)->liveTo,
5255                         ic->next->seq);
5256         }
5257         
5258         
5259         return NULL;
5260 }
5261 /*-----------------------------------------------------------------*/
5262 /* genAndOp - for && operation                                     */
5263 /*-----------------------------------------------------------------*/
5264 static void genAndOp (iCode *ic)
5265 {
5266         operand *left,*right, *result;
5267         /*     symbol *tlbl; */
5268         
5269         FENTRY;
5270         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5271         /* note here that && operations that are in an
5272         if statement are taken away by backPatchLabels
5273         only those used in arthmetic operations remain */
5274         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5275         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5276         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5277         
5278         DEBUGpic14_AopType(__LINE__,left,right,result);
5279         
5280         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5281         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5282         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5283         
5284         /* if both are bit variables */
5285         /*     if (AOP_TYPE(left) == AOP_CRY && */
5286         /*         AOP_TYPE(right) == AOP_CRY ) { */
5287         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5288         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5289         /*         pic14_outBitC(result); */
5290         /*     } else { */
5291         /*         tlbl = newiTempLabel(NULL); */
5292         /*         pic14_toBoolean(left);     */
5293         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5294         /*         pic14_toBoolean(right); */
5295         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5296         /*         pic14_outBitAcc(result); */
5297         /*     } */
5298         
5299         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5300         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5301         freeAsmop(result,NULL,ic,TRUE);
5302 }
5303
5304
5305 /*-----------------------------------------------------------------*/
5306 /* genOrOp - for || operation                                      */
5307 /*-----------------------------------------------------------------*/
5308 /*
5309 tsd pic port -
5310 modified this code, but it doesn't appear to ever get called
5311 */
5312
5313 static void genOrOp (iCode *ic)
5314 {
5315         operand *left,*right, *result;
5316         symbol *tlbl;
5317         int i;
5318         
5319         /* note here that || operations that are in an
5320         if statement are taken away by backPatchLabels
5321         only those used in arthmetic operations remain */
5322         FENTRY;
5323         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5324         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5325         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5326         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5327         
5328         DEBUGpic14_AopType(__LINE__,left,right,result);
5329
5330         for (i=0; i < AOP_SIZE(result); i++)
5331         {
5332                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5333         } // for i
5334
5335         tlbl = newiTempLabel(NULL);
5336         pic14_toBoolean(left);
5337         emitSKPZ;
5338         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5339         pic14_toBoolean(right);
5340         emitpLabel(tlbl->key);
5341         /* here Z is clear IFF `left || right' */
5342         emitSKPZ;
5343         emitpcode(POC_INCF, popGet(AOP(result), 0));
5344         
5345         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5346         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5347         freeAsmop(result,NULL,ic,TRUE);            
5348 }
5349
5350 /*-----------------------------------------------------------------*/
5351 /* isLiteralBit - test if lit == 2^n                               */
5352 /*-----------------------------------------------------------------*/
5353 static int isLiteralBit(unsigned long lit)
5354 {
5355         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5356                 0x100L,0x200L,0x400L,0x800L,
5357                 0x1000L,0x2000L,0x4000L,0x8000L,
5358                 0x10000L,0x20000L,0x40000L,0x80000L,
5359                 0x100000L,0x200000L,0x400000L,0x800000L,
5360                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5361                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5362         int idx;
5363         
5364         FENTRY;
5365         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5366         for(idx = 0; idx < 32; idx++)
5367                 if(lit == pw[idx])
5368                         return idx+1;
5369                 return 0;
5370 }
5371
5372 /*-----------------------------------------------------------------*/
5373 /* continueIfTrue -                                                */
5374 /*-----------------------------------------------------------------*/
5375 static void continueIfTrue (iCode *ic)
5376 {
5377         FENTRY;
5378         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5379         if(IC_TRUE(ic))
5380         {
5381                 // Why +100?!?
5382                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5383                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5384         }
5385         ic->generated = 1;
5386 }
5387
5388 /*-----------------------------------------------------------------*/
5389 /* jmpIfTrue -                                                     */
5390 /*-----------------------------------------------------------------*/
5391 static void jumpIfTrue (iCode *ic)
5392 {
5393         FENTRY;
5394         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5395         if(!IC_TRUE(ic))
5396         {
5397                 // Why +100?!?
5398                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5399                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5400         }
5401         ic->generated = 1;
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* jmpTrueOrFalse -                                                */
5406 /*-----------------------------------------------------------------*/
5407 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5408 {
5409         FENTRY;
5410         // ugly but optimized by peephole
5411         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5412         if(IC_TRUE(ic)){
5413                 symbol *nlbl = newiTempLabel(NULL);
5414                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5415                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5416                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5417                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5418         }
5419         else{
5420                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5421                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5422         }
5423         ic->generated = 1;
5424 }
5425
5426 /*-----------------------------------------------------------------*/
5427 /* genAnd  - code for and                                          */
5428 /*-----------------------------------------------------------------*/
5429 static void genAnd (iCode *ic, iCode *ifx)
5430 {
5431         operand *left, *right, *result;
5432         int size, offset=0;  
5433         unsigned long lit = 0L;
5434         int bytelit = 0;
5435         resolvedIfx rIfx;
5436         
5437         FENTRY;
5438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5439         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5440         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5441         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5442         
5443         resolveIfx(&rIfx,ifx);
5444         
5445         /* if left is a literal & right is not then exchange them */
5446         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5447                 AOP_NEEDSACC(left)) {
5448                 operand *tmp = right ;
5449                 right = left;
5450                 left = tmp;
5451         }
5452         
5453         /* if result = right then exchange them */
5454         if(pic14_sameRegs(AOP(result),AOP(right))){
5455                 operand *tmp = right ;
5456                 right = left;
5457                 left = tmp;
5458         }
5459         
5460         /* if right is bit then exchange them */
5461         if (AOP_TYPE(right) == AOP_CRY &&
5462                 AOP_TYPE(left) != AOP_CRY){
5463                 operand *tmp = right ;
5464                 right = left;
5465                 left = tmp;
5466         }
5467         if(AOP_TYPE(right) == AOP_LIT)
5468                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5469         
5470         size = AOP_SIZE(result);
5471         
5472         DEBUGpic14_AopType(__LINE__,left,right,result);
5473         
5474         // if(bit & yy)
5475         // result = bit & yy;
5476         if (AOP_TYPE(left) == AOP_CRY){
5477                 // c = bit & literal;
5478                 if(AOP_TYPE(right) == AOP_LIT){
5479                         if(lit & 1) {
5480                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5481                                         // no change
5482                                         goto release;
5483                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5484                         } else {
5485                                 // bit(result) = 0;
5486                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5487                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5488                                         goto release;
5489                                 }
5490                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5491                                         jumpIfTrue(ifx);
5492                                         goto release;
5493                                 }
5494                                 pic14_emitcode("clr","c");
5495                         }
5496                 } else {
5497                         if (AOP_TYPE(right) == AOP_CRY){
5498                                 // c = bit & bit;
5499                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5500                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5501                         } else {
5502                                 // c = bit & val;
5503                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5504                                 // c = lsb
5505                                 pic14_emitcode("rrc","a");
5506                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5507                         }
5508                 }
5509                 // bit = c
5510                 // val = c
5511                 if(size)
5512                         pic14_outBitC(result);
5513                 // if(bit & ...)
5514                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5515                         genIfxJump(ifx, "c");           
5516                 goto release ;
5517         }
5518         
5519         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5520         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5521         if((AOP_TYPE(right) == AOP_LIT) &&
5522                 (AOP_TYPE(result) == AOP_CRY) &&
5523                 (AOP_TYPE(left) != AOP_CRY)){
5524                 int posbit = isLiteralBit(lit);
5525                 /* left &  2^n */
5526                 if(posbit){
5527                         posbit--;
5528                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5529                         // bit = left & 2^n
5530                         if(size)
5531                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5532                         // if(left &  2^n)
5533                         else{
5534                                 if(ifx){
5535                                         int offset = 0;
5536                                         while (posbit > 7) {
5537                                                 posbit -= 8;
5538                                                 offset++;
5539                                         }
5540                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5541                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5542                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5543                                         
5544                                         ifx->generated = 1;
5545                                 }
5546                                 goto release;
5547                         }
5548                 } else {
5549                         symbol *tlbl = newiTempLabel(NULL);
5550                         int sizel = AOP_SIZE(left);
5551                         if(size)
5552                                 pic14_emitcode("setb","c");
5553                         while(sizel--){
5554                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5555                                         mov2w( AOP(left), offset);
5556                                         // byte ==  2^n ?
5557                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5558                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5559                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5560                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5561                                         }
5562                                         else{
5563                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5564                                                 if (rIfx.condition) emitSKPZ;
5565                                                 else emitSKPNZ;
5566                                                 
5567                                                 if(bytelit != 0x0FFL)
5568                                                 {
5569                                                         pic14_emitcode("anl","a,%s",
5570                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5571                                                 }
5572                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5573                                         }
5574
5575                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5576                                         ifx->generated = 1;
5577                                                 
5578                                 }
5579                                 offset++;
5580                         }
5581                         // bit = left & literal
5582                         if(size){
5583                                 pic14_emitcode("clr","c");
5584                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5585                         }
5586                         // if(left & literal)
5587                         else{
5588                                 if(ifx)
5589                                         jmpTrueOrFalse(ifx, tlbl);
5590                                 goto release ;
5591                         }
5592                 }
5593                 pic14_outBitC(result);
5594                 goto release ;
5595         }
5596         
5597         /* if left is same as result */
5598         if(pic14_sameRegs(AOP(result),AOP(left))){
5599                 int know_W = -1;
5600                 for(;size--; offset++,lit>>=8) {
5601                         if(AOP_TYPE(right) == AOP_LIT){
5602                                 switch(lit & 0xff) {
5603                                 case 0x00:
5604                                         /*  and'ing with 0 has clears the result */
5605                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5606                                         break;
5607                                 case 0xff:
5608                                         /* and'ing with 0xff is a nop when the result and left are the same */
5609                                         break;
5610                                         
5611                                 default:
5612                                         {
5613                                                 int p = my_powof2( (~lit) & 0xff );
5614                                                 if(p>=0) {
5615                                                         /* only one bit is set in the literal, so use a bcf instruction */
5616                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5617                                                         
5618                                                 } else {
5619                                                         if(know_W != (int)(lit&0xff))
5620                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5621                                                         know_W = lit &0xff;
5622                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5623                                                 }
5624                                         }    
5625                                 }
5626                         } else {
5627                                 if (AOP_TYPE(left) == AOP_ACC) {
5628                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5629                                 } else {        
5630                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5631                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5632                                         
5633                                 }
5634                         }
5635                 }
5636                 
5637         } else {
5638                 // left & result in different registers
5639                 if(AOP_TYPE(result) == AOP_CRY){
5640                         // result = bit
5641                         // if(size), result in bit
5642                         // if(!size && ifx), conditional oper: if(left & right)
5643                         symbol *tlbl = newiTempLabel(NULL);
5644                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5645                         if(size)
5646                                 pic14_emitcode("setb","c");
5647                         while(sizer--){
5648                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5649                                 pic14_emitcode("anl","a,%s",
5650                                         aopGet(AOP(left),offset,FALSE,FALSE));
5651                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5652                                 offset++;
5653                         }
5654                         if(size){
5655                                 CLRC;
5656                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5657                                 pic14_outBitC(result);
5658                         } else if(ifx)
5659                                 jmpTrueOrFalse(ifx, tlbl);
5660                 } else {
5661                         for(;(size--);offset++) {
5662                                 // normal case
5663                                 // result = left & right
5664                                 if(AOP_TYPE(right) == AOP_LIT){
5665                                         int t = (lit >> (offset*8)) & 0x0FFL;
5666                                         switch(t) { 
5667                                         case 0x00:
5668                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5669                                                 break;
5670                                         case 0xff:
5671                                                 if(AOP_TYPE(left) != AOP_ACC) {
5672                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5673                                                 }
5674                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5675                                                 break;
5676                                         default:
5677                                                 if(AOP_TYPE(left) == AOP_ACC) {
5678                                                         emitpcode(POC_ANDLW, popGetLit(t));
5679                                                 } else {
5680                                                         emitpcode(POC_MOVLW, popGetLit(t));
5681                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5682                                                 }
5683                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5684                                         }
5685                                         continue;
5686                                 }
5687                                 
5688                                 if (AOP_TYPE(left) == AOP_ACC) {
5689                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5690                                 } else {
5691                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5692                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5693                                 }
5694                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5695                         }
5696                 }
5697         }
5698         
5699 release :
5700         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5701         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5702         freeAsmop(result,NULL,ic,TRUE);     
5703 }
5704
5705 /*-----------------------------------------------------------------*/
5706 /* genOr  - code for or                                            */
5707 /*-----------------------------------------------------------------*/
5708 static void genOr (iCode *ic, iCode *ifx)
5709 {
5710         operand *left, *right, *result;
5711         int size, offset=0;
5712         unsigned long lit = 0L;
5713         
5714         FENTRY;
5715         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5716         
5717         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5718         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5719         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5720         
5721         DEBUGpic14_AopType(__LINE__,left,right,result);
5722         
5723         /* if left is a literal & right is not then exchange them */
5724         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5725                 AOP_NEEDSACC(left)) {
5726                 operand *tmp = right ;
5727                 right = left;
5728                 left = tmp;
5729         }
5730         
5731         /* if result = right then exchange them */
5732         if(pic14_sameRegs(AOP(result),AOP(right))){
5733                 operand *tmp = right ;
5734                 right = left;
5735                 left = tmp;
5736         }
5737         
5738         /* if right is bit then exchange them */
5739         if (AOP_TYPE(right) == AOP_CRY &&
5740                 AOP_TYPE(left) != AOP_CRY){
5741                 operand *tmp = right ;
5742                 right = left;
5743                 left = tmp;
5744         }
5745         
5746         DEBUGpic14_AopType(__LINE__,left,right,result);
5747         
5748         if(AOP_TYPE(right) == AOP_LIT)
5749                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5750         
5751         size = AOP_SIZE(result);
5752         
5753         // if(bit | yy)
5754         // xx = bit | yy;
5755         if (AOP_TYPE(left) == AOP_CRY){
5756                 if(AOP_TYPE(right) == AOP_LIT){
5757                         // c = bit & literal;
5758                         if(lit){
5759                                 // lit != 0 => result = 1
5760                                 if(AOP_TYPE(result) == AOP_CRY){
5761                                         if(size)
5762                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5763                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5764                                         //   AOP(result)->aopu.aop_dir,
5765                                         //   AOP(result)->aopu.aop_dir);
5766                                         else if(ifx)
5767                                                 continueIfTrue(ifx);
5768                                         goto release;
5769                                 }
5770                         } else {
5771                                 // lit == 0 => result = left
5772                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5773                                         goto release;
5774                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5775                         }
5776                 } else {
5777                         if (AOP_TYPE(right) == AOP_CRY){
5778                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5779                                         // c = bit | bit;
5780                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5781                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5782                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5783                                         
5784                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5785                                                 AOP(result)->aopu.aop_dir,
5786                                                 AOP(result)->aopu.aop_dir);
5787                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5788                                                 AOP(right)->aopu.aop_dir,
5789                                                 AOP(right)->aopu.aop_dir);
5790                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5791                                                 AOP(result)->aopu.aop_dir,
5792                                                 AOP(result)->aopu.aop_dir);
5793                                 } else {
5794                                         if( AOP_TYPE(result) == AOP_ACC) {
5795                                                 emitpcode(POC_MOVLW, popGetLit(0));
5796                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5797                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5798                                                 emitpcode(POC_MOVLW, popGetLit(1));
5799                                                 
5800                                         } else {
5801                                                 
5802                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5803                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5804                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5805                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5806                                                 
5807                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5808                                                         AOP(result)->aopu.aop_dir,
5809                                                         AOP(result)->aopu.aop_dir);
5810                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5811                                                         AOP(right)->aopu.aop_dir,
5812                                                         AOP(right)->aopu.aop_dir);
5813                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5814                                                         AOP(left)->aopu.aop_dir,
5815                                                         AOP(left)->aopu.aop_dir);
5816                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5817                                                         AOP(result)->aopu.aop_dir,
5818                                                         AOP(result)->aopu.aop_dir);
5819                                         }
5820                                 }
5821                         } else {
5822                                 // c = bit | val;
5823                                 symbol *tlbl = newiTempLabel(NULL);
5824                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5825                                 
5826                                 
5827                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5828                                 if( AOP_TYPE(right) == AOP_ACC) {
5829                                         emitpcode(POC_IORLW, popGetLit(0));
5830                                         emitSKPNZ;
5831                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5832                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5833                                 }
5834                                 
5835                                 
5836                                 
5837                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5838                                         pic14_emitcode(";XXX setb","c");
5839                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5840                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5841                                 pic14_toBoolean(right);
5842                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5843                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5844                                         jmpTrueOrFalse(ifx, tlbl);
5845                                         goto release;
5846                                 } else {
5847                                         CLRC;
5848                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5849                                 }
5850                         }
5851                 }
5852                 // bit = c
5853                 // val = c
5854                 if(size)
5855                         pic14_outBitC(result);
5856                 // if(bit | ...)
5857                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5858                         genIfxJump(ifx, "c");           
5859                 goto release ;
5860         }
5861
5862         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5863         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5864         if((AOP_TYPE(right) == AOP_LIT) &&
5865           (AOP_TYPE(result) == AOP_CRY) &&
5866           (AOP_TYPE(left) != AOP_CRY)){
5867                 if(lit){
5868                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5869                         // result = 1
5870                         if(size)
5871                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5872                         else 
5873                                 continueIfTrue(ifx);
5874                         goto release;
5875                 } else {
5876                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5877                         // lit = 0, result = boolean(left)
5878                         if(size)
5879                                 pic14_emitcode(";XXX setb","c");
5880                         pic14_toBoolean(right);
5881                         if(size){
5882                                 symbol *tlbl = newiTempLabel(NULL);
5883                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5884                                 CLRC;
5885                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5886                         } else {
5887                                 genIfxJump (ifx,"a");
5888                                 goto release;
5889                         }
5890                 }
5891                 pic14_outBitC(result);
5892                 goto release ;
5893         }
5894
5895         /* if left is same as result */
5896         if(pic14_sameRegs(AOP(result),AOP(left))){
5897                 int know_W = -1;
5898                 for(;size--; offset++,lit>>=8) {
5899                         if(AOP_TYPE(right) == AOP_LIT){
5900                                 if((lit & 0xff) == 0)
5901                                         /*  or'ing with 0 has no effect */
5902                                         continue;
5903                                 else {
5904                                         int p = my_powof2(lit & 0xff);
5905                                         if(p>=0) {
5906                                                 /* only one bit is set in the literal, so use a bsf instruction */
5907                                                 emitpcode(POC_BSF,
5908                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5909                                         } else {
5910                                                 if(know_W != (int)(lit & 0xff))
5911                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5912                                                 know_W = lit & 0xff;
5913                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5914                                         }
5915                                         
5916                                 }
5917                         } else {
5918                                 if (AOP_TYPE(left) == AOP_ACC) {
5919                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5920                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5921                                 } else {        
5922                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5923                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5924                                         
5925                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5926                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5927                                         
5928                                 }
5929                         }
5930                 }
5931         } else {
5932                 // left & result in different registers
5933                 if(AOP_TYPE(result) == AOP_CRY){
5934                         // result = bit
5935                         // if(size), result in bit
5936                         // if(!size && ifx), conditional oper: if(left | right)
5937                         symbol *tlbl = newiTempLabel(NULL);
5938                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5939                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5940                         
5941                         
5942                         if(size)
5943                                 pic14_emitcode(";XXX setb","c");
5944                         while(sizer--){
5945                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5946                                 pic14_emitcode(";XXX orl","a,%s",
5947                                         aopGet(AOP(left),offset,FALSE,FALSE));
5948                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5949                                 offset++;
5950                         }
5951                         if(size){
5952                                 CLRC;
5953                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5954                                 pic14_outBitC(result);
5955                         } else if(ifx)
5956                                 jmpTrueOrFalse(ifx, tlbl);
5957                 } else for(;(size--);offset++){
5958                         // normal case
5959                         // result = left | right
5960                         if(AOP_TYPE(right) == AOP_LIT){
5961                                 int t = (lit >> (offset*8)) & 0x0FFL;
5962                                 switch(t) { 
5963                                 case 0x00:
5964                                         if (AOP_TYPE(left) != AOP_ACC) {
5965                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5966                                         }
5967                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5968                                         
5969                                         break;
5970                                 default:
5971                                         if (AOP_TYPE(left) == AOP_ACC) {
5972                                                 emitpcode(POC_IORLW,  popGetLit(t));
5973                                         } else {
5974                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5975                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5976                                         }
5977                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5978                                 }
5979                                 continue;
5980                         }
5981                         
5982                         // faster than result <- left, anl result,right
5983                         // and better if result is SFR
5984                         if (AOP_TYPE(left) == AOP_ACC) {
5985                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5986                         } else {
5987                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5988                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5989                         }
5990                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5991                 }
5992         }
5993
5994 release :
5995         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5996         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5997         freeAsmop(result,NULL,ic,TRUE);     
5998 }
5999
6000 /*-----------------------------------------------------------------*/
6001 /* genXor - code for xclusive or                                   */
6002 /*-----------------------------------------------------------------*/
6003 static void genXor (iCode *ic, iCode *ifx)
6004 {
6005         operand *left, *right, *result;
6006         int size, offset=0;
6007         unsigned long lit = 0L;
6008         
6009         FENTRY;
6010         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6011         
6012         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6013         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6014         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6015         
6016         /* if left is a literal & right is not ||
6017         if left needs acc & right does not */
6018         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6019                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6020                 operand *tmp = right ;
6021                 right = left;
6022                 left = tmp;
6023         }
6024         
6025         /* if result = right then exchange them */
6026         if(pic14_sameRegs(AOP(result),AOP(right))){
6027                 operand *tmp = right ;
6028                 right = left;
6029                 left = tmp;
6030         }
6031         
6032         /* if right is bit then exchange them */
6033         if (AOP_TYPE(right) == AOP_CRY &&
6034                 AOP_TYPE(left) != AOP_CRY){
6035                 operand *tmp = right ;
6036                 right = left;
6037                 left = tmp;
6038         }
6039         if(AOP_TYPE(right) == AOP_LIT)
6040                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6041         
6042         size = AOP_SIZE(result);
6043         
6044         // if(bit ^ yy)
6045         // xx = bit ^ yy;
6046         if (AOP_TYPE(left) == AOP_CRY){
6047                 if(AOP_TYPE(right) == AOP_LIT){
6048                         // c = bit & literal;
6049                         if(lit>>1){
6050                                 // lit>>1  != 0 => result = 1
6051                                 if(AOP_TYPE(result) == AOP_CRY){
6052                                         if(size)
6053                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6054                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6055                                         else if(ifx)
6056                                                 continueIfTrue(ifx);
6057                                         goto release;
6058                                 }
6059                                 pic14_emitcode("setb","c");
6060                         } else{
6061                                 // lit == (0 or 1)
6062                                 if(lit == 0){
6063                                         // lit == 0, result = left
6064                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6065                                                 goto release;
6066                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6067                                 } else{
6068                                         // lit == 1, result = not(left)
6069                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6070                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6071                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6072                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6073                                                 goto release;
6074                                         } else {
6075                                                 assert ( !"incomplete genXor" );
6076                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6077                                                 pic14_emitcode("cpl","c");
6078                                         }
6079                                 }
6080                         }
6081                         
6082                 } else {
6083                         // right != literal
6084                         symbol *tlbl = newiTempLabel(NULL);
6085                         if (AOP_TYPE(right) == AOP_CRY){
6086                                 // c = bit ^ bit;
6087                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6088                         }
6089                         else{
6090                                 int sizer = AOP_SIZE(right);
6091                                 // c = bit ^ val
6092                                 // if val>>1 != 0, result = 1
6093                                 pic14_emitcode("setb","c");
6094                                 while(sizer){
6095                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6096                                         if(sizer == 1)
6097                                                 // test the msb of the lsb
6098                                                 pic14_emitcode("anl","a,#0xfe");
6099                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6100                                         sizer--;
6101                                 }
6102                                 // val = (0,1)
6103                                 pic14_emitcode("rrc","a");
6104                         }
6105                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6106                         pic14_emitcode("cpl","c");
6107                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6108                 }
6109                 // bit = c
6110                 // val = c
6111                 if(size)
6112                         pic14_outBitC(result);
6113                 // if(bit | ...)
6114                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6115                         genIfxJump(ifx, "c");           
6116                 goto release ;
6117         }
6118         
6119         if(pic14_sameRegs(AOP(result),AOP(left))){
6120                 /* if left is same as result */
6121                 for(;size--; offset++) {
6122                         if(AOP_TYPE(right) == AOP_LIT){
6123                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6124                                 if(t == 0x00L)
6125                                         continue;
6126                                 else
6127                                         if (IS_AOP_PREG(left)) {
6128                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6129                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6130                                                 aopPut(AOP(result),"a",offset);
6131                                         } else {
6132                                                 emitpcode(POC_MOVLW, popGetLit(t));
6133                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6134                                                 pic14_emitcode("xrl","%s,%s",
6135                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6136                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6137                                         }
6138                         } else {
6139                                 if (AOP_TYPE(left) == AOP_ACC)
6140                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6141                                 else {
6142                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6143                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6144                                         /*
6145                                         if (IS_AOP_PREG(left)) {
6146                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6147                                         aopPut(AOP(result),"a",offset);
6148                                         } else
6149                                         pic14_emitcode("xrl","%s,a",
6150                                         aopGet(AOP(left),offset,FALSE,TRUE));
6151                                         */
6152                                 }
6153                         }
6154                 }
6155         } else {
6156                 // left & result in different registers
6157                 if(AOP_TYPE(result) == AOP_CRY){
6158                         // result = bit
6159                         // if(size), result in bit
6160                         // if(!size && ifx), conditional oper: if(left ^ right)
6161                         symbol *tlbl = newiTempLabel(NULL);
6162                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6163                         if(size)
6164                                 pic14_emitcode("setb","c");
6165                         while(sizer--){
6166                                 if((AOP_TYPE(right) == AOP_LIT) &&
6167                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6168                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6169                                 } else {
6170                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6171                                         pic14_emitcode("xrl","a,%s",
6172                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6173                                 }
6174                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6175                                 offset++;
6176                         }
6177                         if(size){
6178                                 CLRC;
6179                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6180                                 pic14_outBitC(result);
6181                         } else if(ifx)
6182                                 jmpTrueOrFalse(ifx, tlbl);
6183                 } else for(;(size--);offset++){
6184                         // normal case
6185                         // result = left & right
6186                         if(AOP_TYPE(right) == AOP_LIT){
6187                                 int t = (lit >> (offset*8)) & 0x0FFL;
6188                                 switch(t) { 
6189                                 case 0x00:
6190                                         if (AOP_TYPE(left) != AOP_ACC) {
6191                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6192                                         }
6193                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6194                                         pic14_emitcode("movf","%s,w",
6195                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6196                                         pic14_emitcode("movwf","%s",
6197                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6198                                         break;
6199                                 case 0xff:
6200                                         if (AOP_TYPE(left) == AOP_ACC) {
6201                                                 emitpcode(POC_XORLW, popGetLit(t));
6202                                         } else {
6203                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6204                                         }
6205                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6206                                         break;
6207                                 default:
6208                                         if (AOP_TYPE(left) == AOP_ACC) {
6209                                                 emitpcode(POC_XORLW, popGetLit(t));
6210                                         } else {
6211                                                 emitpcode(POC_MOVLW, popGetLit(t));
6212                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6213                                         }
6214                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6215                                         pic14_emitcode("movlw","0x%x",t);
6216                                         pic14_emitcode("xorwf","%s,w",
6217                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6218                                         pic14_emitcode("movwf","%s",
6219                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6220                                         
6221                                 }
6222                                 continue;
6223                         }
6224                         
6225                         // faster than result <- left, anl result,right
6226                         // and better if result is SFR
6227                         if (AOP_TYPE(left) == AOP_ACC) {
6228                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6229                         } else {
6230                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6231                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6232                         }
6233                         if ( AOP_TYPE(result) != AOP_ACC){
6234                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6235                         }
6236                 }
6237         }
6238         
6239 release :
6240         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6241         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6242         freeAsmop(result,NULL,ic,TRUE);     
6243 }
6244
6245 /*-----------------------------------------------------------------*/
6246 /* genInline - write the inline code out                           */
6247 /*-----------------------------------------------------------------*/
6248 static void genInline (iCode *ic)
6249 {
6250   char *buffer, *bp, *bp1;
6251
6252   FENTRY;
6253   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6254
6255   _G.inLine += (!options.asmpeep);
6256
6257   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6258   strcpy(buffer,IC_INLINE(ic));
6259
6260   /* emit each line as a code */
6261   while (*bp) {
6262     if (*bp == '\n') {
6263       *bp++ = '\0';
6264       
6265       if(*bp1)
6266         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6267       bp1 = bp;
6268     } else {
6269       if (*bp == ':') {
6270         bp++;
6271         *bp = '\0';
6272         bp++;
6273
6274         /* print label, use this special format with NULL directive
6275          * to denote that the argument should not be indented with tab */
6276         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6277
6278         bp1 = bp;
6279       } else
6280         bp++;
6281     }
6282   }
6283   if ((bp1 != bp) && *bp1)
6284     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6285
6286   Safe_free(buffer);
6287
6288   _G.inLine -= (!options.asmpeep);
6289 }
6290
6291 /*-----------------------------------------------------------------*/
6292 /* genRRC - rotate right with carry                                */
6293 /*-----------------------------------------------------------------*/
6294 static void genRRC (iCode *ic)
6295 {
6296         operand *left , *result ;
6297         int size, offset = 0, same;
6298         
6299         FENTRY;
6300         /* rotate right with carry */
6301         left = IC_LEFT(ic);
6302         result=IC_RESULT(ic);
6303         aopOp (left,ic,FALSE);
6304         aopOp (result,ic,FALSE);
6305         
6306         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6307         
6308         same = pic14_sameRegs(AOP(result),AOP(left));
6309         
6310         size = AOP_SIZE(result);    
6311         
6312         /* get the lsb and put it into the carry */
6313         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6314         
6315         offset = 0 ;
6316         
6317         while(size--) {
6318                 
6319                 if(same) {
6320                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6321                 } else {
6322                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6323                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6324                 }
6325                 
6326                 offset++;
6327         }
6328         
6329         freeAsmop(left,NULL,ic,TRUE);
6330         freeAsmop(result,NULL,ic,TRUE);
6331 }
6332
6333 /*-----------------------------------------------------------------*/
6334 /* genRLC - generate code for rotate left with carry               */
6335 /*-----------------------------------------------------------------*/
6336 static void genRLC (iCode *ic)
6337 {    
6338         operand *left , *result ;
6339         int size, offset = 0;
6340         int same;
6341         
6342         FENTRY;
6343         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6344         /* rotate right with carry */
6345         left = IC_LEFT(ic);
6346         result=IC_RESULT(ic);
6347         aopOp (left,ic,FALSE);
6348         aopOp (result,ic,FALSE);
6349         
6350         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6351         
6352         same = pic14_sameRegs(AOP(result),AOP(left));
6353         
6354         /* move it to the result */
6355         size = AOP_SIZE(result);    
6356         
6357         /* get the msb and put it into the carry */
6358         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6359         
6360         offset = 0 ;
6361         
6362         while(size--) {
6363                 
6364                 if(same) {
6365                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6366                 } else {
6367                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6368                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6369                 }
6370                 
6371                 offset++;
6372         }
6373         
6374         
6375         freeAsmop(left,NULL,ic,TRUE);
6376         freeAsmop(result,NULL,ic,TRUE);
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* genGetHbit - generates code get highest order bit               */
6381 /*-----------------------------------------------------------------*/
6382 static void genGetHbit (iCode *ic)
6383 {
6384         operand *left, *result;
6385         left = IC_LEFT(ic);
6386         result=IC_RESULT(ic);
6387         aopOp (left,ic,FALSE);
6388         aopOp (result,ic,FALSE);
6389         
6390         FENTRY;
6391         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6392         /* get the highest order byte into a */
6393         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6394         if(AOP_TYPE(result) == AOP_CRY){
6395                 pic14_emitcode("rlc","a");
6396                 pic14_outBitC(result);
6397         }
6398         else{
6399                 pic14_emitcode("rl","a");
6400                 pic14_emitcode("anl","a,#0x01");
6401                 pic14_outAcc(result);
6402         }
6403         
6404         
6405         freeAsmop(left,NULL,ic,TRUE);
6406         freeAsmop(result,NULL,ic,TRUE);
6407 }
6408
6409 /*-----------------------------------------------------------------*/
6410 /* AccLsh - shift left accumulator by known count                  */
6411 /* MARK: pic14 always rotates through CARRY!                       */
6412 /*-----------------------------------------------------------------*/
6413 static void AccLsh (pCodeOp *pcop,int shCount)
6414 {
6415         FENTRY;
6416         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6417         shCount &= 0x0007;              // shCount : 0..7
6418         switch(shCount){
6419         case 0 :
6420                 return;
6421                 break;
6422         case 1 :
6423                 emitCLRC;
6424                 emitpcode(POC_RLF,pcop);
6425                 return;
6426                 break;
6427         case 2 :
6428                 emitpcode(POC_RLF,pcop);
6429                 emitpcode(POC_RLF,pcop);
6430                 break;
6431         case 3 :
6432                 emitpcode(POC_RLF,pcop);
6433                 emitpcode(POC_RLF,pcop);
6434                 emitpcode(POC_RLF,pcop);
6435                 break;
6436         case 4 :
6437                 emitpcode(POC_SWAPF,pcop);
6438                 break;
6439         case 5 :
6440                 emitpcode(POC_SWAPF,pcop);
6441                 emitpcode(POC_RLF,pcop);
6442                 break;
6443         case 6 :
6444                 emitpcode(POC_SWAPF,pcop);
6445                 emitpcode(POC_RLF,pcop);
6446                 emitpcode(POC_RLF,pcop);
6447                 break;
6448         case 7 :
6449                 emitpcode(POC_RRFW,pcop);
6450                 emitpcode(POC_RRF,pcop);
6451                 break;
6452         }
6453         /* clear invalid bits */
6454         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6455         emitpcode(POC_ANDWF, pcop);
6456 }
6457
6458 /*-----------------------------------------------------------------*/
6459 /* AccRsh - shift right accumulator by known count                 */
6460 /* MARK: pic14 always rotates through CARRY!                       */
6461 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6462 /*            1: mask out invalid bits (zero-extend)               */
6463 /*            2: sign-extend result (pretty slow)                  */
6464 /*-----------------------------------------------------------------*/
6465 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6466 {
6467         FENTRY;
6468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6469         shCount &= 0x0007;              // shCount : 0..7
6470         switch(shCount){
6471         case 0 :
6472                 return;
6473                 break;
6474         case 1 :
6475                 /* load sign if needed */
6476                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6477                 else if (mask_mode == 1) emitCLRC;
6478                 emitpcode(POC_RRF,pcop);
6479                 return;
6480                 break;
6481         case 2 :
6482                 /* load sign if needed */
6483                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6484                 emitpcode(POC_RRF,pcop);
6485                 /* load sign if needed */
6486                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6487                 emitpcode(POC_RRF,pcop);
6488                 if (mask_mode == 2) return;
6489                 break;
6490         case 3 :
6491                 /* load sign if needed */
6492                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6493                 emitpcode(POC_RRF,pcop);
6494                 /* load sign if needed */
6495                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6496                 emitpcode(POC_RRF,pcop);
6497                 /* load sign if needed */
6498                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6499                 emitpcode(POC_RRF,pcop);
6500                 if (mask_mode == 2) return;
6501                 break;
6502         case 4 :
6503                 emitpcode(POC_SWAPF,pcop);
6504                 break;
6505         case 5 :
6506                 emitpcode(POC_SWAPF,pcop);
6507                 emitpcode(POC_RRF,pcop);
6508                 break;
6509         case 6 :
6510                 emitpcode(POC_SWAPF,pcop);
6511                 emitpcode(POC_RRF,pcop);
6512                 emitpcode(POC_RRF,pcop);
6513                 break;
6514         case 7 :
6515                 if (mask_mode == 2)
6516                 {
6517                         /* load sign */
6518                         emitpcode(POC_RLFW,pcop);
6519                         emitpcode(POC_CLRF,pcop);
6520                         emitSKPNC;
6521                         emitpcode(POC_COMF,pcop);
6522                         return;
6523                 } else {
6524                         emitpcode(POC_RLFW,pcop);
6525                         emitpcode(POC_RLF,pcop);
6526                 }
6527                 break;
6528         }
6529
6530         if (mask_mode == 0)
6531         {
6532                 /* leave invalid bits undefined */
6533                 return;
6534         }
6535         
6536         /* clear invalid bits -- zero-extend */
6537         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6538         emitpcode(POC_ANDWF, pcop);
6539
6540         if (mask_mode == 2) {
6541           /* sign-extend */
6542           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6543           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6544           emitpcode(POC_IORWF, pcop);
6545         }
6546 }
6547
6548 #if 0
6549 /*-----------------------------------------------------------------*/
6550 /* AccSRsh - signed right shift accumulator by known count                 */
6551 /*-----------------------------------------------------------------*/
6552 static void AccSRsh (int shCount)
6553 {
6554         symbol *tlbl ;
6555         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6556         if(shCount != 0){
6557                 if(shCount == 1){
6558                         pic14_emitcode("mov","c,acc.7");
6559                         pic14_emitcode("rrc","a");
6560                 } else if(shCount == 2){
6561                         pic14_emitcode("mov","c,acc.7");
6562                         pic14_emitcode("rrc","a");
6563                         pic14_emitcode("mov","c,acc.7");
6564                         pic14_emitcode("rrc","a");
6565                 } else {
6566                         tlbl = newiTempLabel(NULL);
6567                         /* rotate right accumulator */
6568                         AccRol(8 - shCount);
6569                         /* and kill the higher order bits */
6570                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6571                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6572                         pic14_emitcode("orl","a,#0x%02x",
6573                                 (unsigned char)~SRMask[shCount]);
6574                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6575                 }
6576         }
6577 }
6578
6579 /*-----------------------------------------------------------------*/
6580 /* shiftR1Left2Result - shift right one byte from left to result   */
6581 /*-----------------------------------------------------------------*/
6582 static void shiftR1Left2ResultSigned (operand *left, int offl,
6583                                                                           operand *result, int offr,
6584                                                                           int shCount)
6585 {
6586         int same;
6587         
6588         FENTRY;
6589         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6590         
6591         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6592         
6593         switch(shCount) {
6594         case 1:
6595                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6596                 if(same) 
6597                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6598                 else {
6599                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6600                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6601                 }
6602                 
6603                 break;
6604         case 2:
6605                 
6606                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6607                 if(same) 
6608                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6609                 else {
6610                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6611                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6612                 }
6613                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6614                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6615                 
6616                 break;
6617                 
6618         case 3:
6619                 if(same)
6620                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6621                 else {
6622                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6623                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6624                 }
6625                 
6626                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6627                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6628                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6629                 
6630                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6631                 emitpcode(POC_IORLW, popGetLit(0xe0));
6632                 
6633                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6634                 break;
6635                 
6636         case 4:
6637                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6638                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6639                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6640                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6641                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6642                 break;
6643         case 5:
6644                 if(same) {
6645                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6646                 } else {
6647                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6648                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6649                 }
6650                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6651                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6652                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6653                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6654                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6655                 break;
6656                 
6657         case 6:
6658                 if(same) {
6659                         emitpcode(POC_MOVLW, popGetLit(0x00));
6660                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6661                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6662                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6663                         emitpcode(POC_IORLW, popGetLit(0x01));
6664                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6665                 } else {
6666                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6667                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6668                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6669                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6670                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6671                 }
6672                 break;
6673                 
6674         case 7:
6675                 if(same) {
6676                         emitpcode(POC_MOVLW, popGetLit(0x00));
6677                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6678                         emitpcode(POC_MOVLW, popGetLit(0xff));
6679                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6680                 } else {
6681                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6682                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6683                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6684                 }
6685                 
6686         default:
6687                 break;
6688         }
6689 }
6690
6691 /*-----------------------------------------------------------------*/
6692 /* shiftR1Left2Result - shift right one byte from left to result   */
6693 /*-----------------------------------------------------------------*/
6694 static void shiftR1Left2Result (operand *left, int offl,
6695                                                                 operand *result, int offr,
6696                                                                 int shCount, int sign)
6697 {
6698         int same;
6699         
6700         FENTRY;
6701         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6702         
6703         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6704         
6705         /* Copy the msb into the carry if signed. */
6706         if(sign) {
6707                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6708                 return;
6709         }
6710         
6711         
6712         
6713         switch(shCount) {
6714         case 1:
6715                 emitCLRC;
6716                 if(same) 
6717                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6718                 else {
6719                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6720                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6721                 }
6722                 break;
6723         case 2:
6724                 emitCLRC;
6725                 if(same) {
6726                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6727                 } else {
6728                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6729                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6730                 }
6731                 emitCLRC;
6732                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6733                 
6734                 break;
6735         case 3:
6736                 if(same)
6737                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6738                 else {
6739                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6740                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6741                 }
6742                 
6743                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6744                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6745                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6746                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747                 break;
6748                 
6749         case 4:
6750                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6751                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6752                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6753                 break;
6754                 
6755         case 5:
6756                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6757                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6758                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6759                 emitCLRC;
6760                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6761                 
6762                 break;
6763         case 6:
6764                 
6765                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6766                 emitpcode(POC_ANDLW, popGetLit(0x80));
6767                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6768                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6769                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6770                 break;
6771                 
6772         case 7:
6773                 
6774                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6775                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6776                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6777                 
6778                 break;
6779                 
6780         default:
6781                 break;
6782         }
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* shiftL1Left2Result - shift left one byte from left to result    */
6787 /*-----------------------------------------------------------------*/
6788 static void shiftL1Left2Result (operand *left, int offl,
6789                                                                 operand *result, int offr, int shCount)
6790 {
6791         int same;
6792         
6793         //    char *l;
6794         FENTRY;
6795         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6796         
6797         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6798         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6799         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6800         //    MOVA(l);
6801         /* shift left accumulator */
6802         //AccLsh(shCount); // don't comment out just yet...
6803         //    aopPut(AOP(result),"a",offr);
6804         
6805         switch(shCount) {
6806         case 1:
6807                 /* Shift left 1 bit position */
6808                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6809                 if(same) {
6810                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6811                 } else {
6812                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6813                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6814                 }
6815                 break;
6816         case 2:
6817                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6818                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6819                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6820                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6821                 break;
6822         case 3:
6823                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6824                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6825                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6826                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6827                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6828                 break;
6829         case 4:
6830                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6831                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6832                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6833                 break;
6834         case 5:
6835                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6836                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6837                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6838                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6839                 break;
6840         case 6:
6841                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6842                 emitpcode(POC_ANDLW, popGetLit(0x30));
6843                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6845                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6846                 break;
6847         case 7:
6848                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6849                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6850                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6851                 break;
6852                 
6853         default:
6854                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6855         }
6856         
6857 }
6858 #endif
6859
6860 /*-----------------------------------------------------------------*/
6861 /* movLeft2Result - move byte from left to result                  */
6862 /*-----------------------------------------------------------------*/
6863 static void movLeft2Result (operand *left, int offl,
6864                                                         operand *result, int offr)
6865 {
6866         char *l;
6867         FENTRY;
6868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6869         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6870                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6871                 
6872                 if (*l == '@' && (IS_AOP_PREG(result))) {
6873                         pic14_emitcode("mov","a,%s",l);
6874                         aopPut(AOP(result),"a",offr);
6875                 } else {
6876                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6877                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6878                 }
6879         }
6880 }
6881
6882 /*-----------------------------------------------------------------*/
6883 /* shiftLeft_Left2ResultLit - shift left by known count            */
6884 /*-----------------------------------------------------------------*/
6885
6886 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6887 {
6888         int size, same, offr, i;
6889
6890         size = AOP_SIZE(left);
6891         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6892         
6893         same = pic14_sameRegs (AOP(left), AOP(result));
6894         
6895         offr = shCount / 8;
6896         shCount = shCount & 0x07;
6897
6898         size -= offr;
6899
6900         switch (shCount)
6901         {
6902         case 0: /* takes 0 or 2N cycles (for offr==0) */
6903                 if (!same || offr) {
6904                         for (i=size-1; i >= 0; i--)
6905                                 movLeft2Result (left, i, result, offr + i);
6906                 } // if
6907                 break;
6908                 
6909         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6910                 if (same && offr) {
6911                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6912                         shiftLeft_Left2ResultLit (result, result, shCount);
6913                         return; /* prevent clearing result again */
6914                 } else {
6915                         emitCLRC;
6916                         for (i=0; i < size; i++) {
6917                                 if (same && !offr) {
6918                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6919                                 } else {
6920                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6921                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6922                                 } // if
6923                         } // for
6924                 } // if (offr)
6925                 break;
6926                 
6927         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6928                 /* works in-place/with offr as well */
6929                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6930                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6931                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6932
6933                 for (i = size - 2; i >= 0; i--)
6934                 {
6935                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6936                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6937                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6938                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6939                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6940                 } // for i
6941                 break;
6942                 
6943         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6944                 /* works in-place/with offr as well */
6945                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6946                 for (i = size-2; i >= 0; i--) {
6947                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6948                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6949                 } // for i
6950                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6951                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6952                 break;
6953         
6954         default:
6955                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6956                 shiftLeft_Left2ResultLit (result, result, 1);
6957                 return; /* prevent clearing result again */
6958                 break;
6959         } // switch
6960
6961         while (0 < offr--)
6962         {
6963                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6964         } // while
6965 }
6966
6967 /*-----------------------------------------------------------------*/
6968 /* shiftRight_Left2ResultLit - shift right by known count          */
6969 /*-----------------------------------------------------------------*/
6970
6971 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6972 {
6973         int size, same, offr, i;
6974
6975         size = AOP_SIZE(left);
6976         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6977         
6978         same = pic14_sameRegs (AOP(left), AOP(result));
6979         
6980         offr = shCount / 8;
6981         shCount = shCount & 0x07;
6982
6983         size -= offr;
6984
6985         if (size)
6986         {
6987                 switch (shCount)
6988                 {
6989                 case 0: /* takes 0 or 2N cycles (for offr==0) */
6990                         if (!same || offr) {
6991                                 for (i=0; i < size; i++)
6992                                         movLeft2Result (left, i + offr, result, i);
6993                         } // if
6994                         break;
6995                         
6996                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6997                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6998                         if (same && offr) {
6999                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7000                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7001                                 return; /* prevent sign-extending result again */
7002                         } else {
7003                                 emitCLRC;
7004                                 if (sign) {
7005                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7006                                         emitSETC;
7007                                 }
7008                                 for (i = size-1; i >= 0; i--) {
7009                                         if (same && !offr) {
7010                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7011                                         } else {
7012                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7013                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7014                                         }
7015                                 } // for i
7016                         } // if (offr)
7017                         break;
7018                         
7019                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7020                         /* works in-place/with offr as well */
7021                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7022                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7023                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7024
7025                         for (i = 1; i < size; i++)
7026                         {
7027                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7028                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7029                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7030                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7031                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7032                         } // for i
7033
7034                         if (sign)
7035                         {
7036                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7037                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7038                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7039                         } // if
7040                         break;
7041                         
7042                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7043                         /* works in-place/with offr as well */
7044                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7045                         for (i = 0; i < size-1; i++) {
7046                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7047                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7048                         } // for i
7049                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7050                         if (!sign) {
7051                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7052                         } else {
7053                                 emitSKPNC;
7054                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7055                         }
7056                         break;
7057                 
7058                 default:
7059                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7060                         shiftRight_Left2ResultLit (result, result, 1, sign);
7061                         return; /* prevent sign extending result again */
7062                         break;
7063                 } // switch
7064         } // if
7065
7066         addSign (result, size, sign);
7067 }
7068
7069 #if 0
7070 /*-----------------------------------------------------------------*/
7071 /* shiftL2Left2Result - shift left two bytes from left to result   */
7072 /*-----------------------------------------------------------------*/
7073 static void shiftL2Left2Result (operand *left, int offl,
7074                                                                 operand *result, int offr, int shCount)
7075 {
7076         FENTRY;
7077         
7078         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7079         
7080         if(pic14_sameRegs(AOP(result), AOP(left))) {
7081                 switch(shCount) {
7082                 case 0:
7083                         break;
7084                 case 1:
7085                 case 2:
7086                 case 3:
7087                         
7088                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7089                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7090                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7091                         
7092                         while(--shCount) {
7093                                 emitCLRC;
7094                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7095                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7096                         }
7097                         
7098                         break;
7099                 case 4:
7100                 case 5:
7101                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7102                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7103                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7104                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7105                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7106                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7107                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7108                         if(shCount >=5) {
7109                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7110                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7111                         }
7112                         break;
7113                 case 6:
7114                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7115                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7116                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7117                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7118                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7119                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7120                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7121                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7122                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7123                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7124                         break;
7125                 case 7:
7126                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7127                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7128                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7129                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7130                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7131                 }
7132                 
7133         } else {
7134                 switch(shCount) {
7135                 case 0:
7136                         break;
7137                 case 1:
7138                 case 2:
7139                 case 3:
7140                 /* note, use a mov/add for the shift since the mov has a
7141                         chance of getting optimized out */
7142                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7143                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7144                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7145                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7146                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7147                         
7148                         while(--shCount) {
7149                                 emitCLRC;
7150                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7151                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7152                         }
7153                         break;
7154                         
7155                 case 4:
7156                 case 5:
7157                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7158                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7159                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7160                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7161                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7162                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7163                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7164                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7165                         
7166                         
7167                         if(shCount == 5) {
7168                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7169                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7170                         }
7171                         break;
7172                 case 6:
7173                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7174                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7175                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7176                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7177                         
7178                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7179                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7180                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7181                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7182                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7183                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7184                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7185                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7186                         break;
7187                 case 7:
7188                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7189                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7190                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7191                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7192                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7193                 }
7194         }
7195         
7196 }
7197
7198 /*-----------------------------------------------------------------*/
7199 /* shiftR2Left2Result - shift right two bytes from left to result  */
7200 /*-----------------------------------------------------------------*/
7201 static void shiftR2Left2Result (operand *left, int offl,
7202                                                                 operand *result, int offr,
7203                                                                 int shCount, int sign)
7204 {
7205         int same=0;
7206         
7207         FENTRY;
7208         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7209         same = pic14_sameRegs(AOP(result), AOP(left));
7210         
7211         if(same && ((offl + MSB16) == offr)){
7212                 same=1;
7213                 /* don't crash result[offr] */
7214                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7215                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7216         }
7217         /* else {
7218         movLeft2Result(left,offl, result, offr);
7219         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7220         }
7221         */
7222         /* a:x >> shCount (x = lsb(result))*/
7223         /*
7224         if(sign)
7225         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7226         else {
7227         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7228         */
7229         switch(shCount) {
7230         case 0:
7231                 break;
7232         case 1:
7233         case 2:
7234         case 3:
7235                 if(sign)
7236                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7237                 else
7238                         emitCLRC;
7239                 
7240                 if(same) {
7241                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7242                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7243                 } else {
7244                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7245                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7246                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7247                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7248                 }
7249                 
7250                 while(--shCount) {
7251                         if(sign)
7252                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7253                         else
7254                                 emitCLRC;
7255                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7256                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7257                 }
7258                 break;
7259         case 4:
7260         case 5:
7261                 if(same) {
7262                         
7263                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7264                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7265                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7266                         
7267                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7268                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7269                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7270                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7271                 } else {
7272                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7273                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7274                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7275                         
7276                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7277                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7278                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7279                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7280                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7281                 }
7282                 
7283                 if(shCount >=5) {
7284                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7285                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7286                 }
7287                 
7288                 if(sign) {
7289                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7290                         emitpcode(POC_BTFSC, 
7291                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7292                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7293                 }
7294                 
7295                 break;
7296                 
7297         case 6:
7298                 if(same) {
7299                         
7300                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7301                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7302                         
7303                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7304                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7305                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7306                         emitpcode(POC_ANDLW,popGetLit(0x03));
7307                         if(sign) {
7308                                 emitpcode(POC_BTFSC, 
7309                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7310                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7311                         }
7312                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7313                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7314                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7315                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7316                 } else {
7317                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7318                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7319                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7320                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7321                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7322                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7323                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7324                         emitpcode(POC_ANDLW,popGetLit(0x03));
7325                         if(sign) {
7326                                 emitpcode(POC_BTFSC, 
7327                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7328                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7329                         }
7330                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7331                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7332                         
7333                         
7334                 }
7335                 
7336                 break;
7337         case 7:
7338                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7339                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7340                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7341                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7342                 if(sign) {
7343                         emitSKPNC;
7344                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7345                 } else 
7346                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7347   }
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7352 /*-----------------------------------------------------------------*/
7353 static void shiftLLeftOrResult (operand *left, int offl,
7354                                                                 operand *result, int offr, int shCount)
7355 {
7356         FENTRY;
7357         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7358         
7359         /* shift left accumulator */
7360         AccLsh(left,offl,shCount);
7361         /* or with result */
7362         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7363         assert ( !"broken (modifies left, fails for left==result))" );
7364 }
7365
7366 /*-----------------------------------------------------------------*/
7367 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7368 /*-----------------------------------------------------------------*/
7369 static void shiftRLeftOrResult (operand *left, int offl,
7370                                                                 operand *result, int offr, int shCount)
7371 {
7372         FENTRY;
7373         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7374         
7375         /* shift right accumulator */
7376         AccRsh(left,offl,shCount);
7377         /* or with result */
7378         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7379         assert ( !"broken (modifies left, fails for left==result))" );
7380 }
7381
7382 /*-----------------------------------------------------------------*/
7383 /* genlshOne - left shift a one byte quantity by known count       */
7384 /*-----------------------------------------------------------------*/
7385 static void genlshOne (operand *result, operand *left, int shCount)
7386 {       
7387         FENTRY;
7388         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7389         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7390 }
7391
7392 /*-----------------------------------------------------------------*/
7393 /* genlshTwo - left shift two bytes by known amount != 0           */
7394 /*-----------------------------------------------------------------*/
7395 static void genlshTwo (operand *result,operand *left, int shCount)
7396 {
7397         int size;
7398         
7399         FENTRY;
7400         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7401         size = pic14_getDataSize(result);
7402         
7403         /* if shCount >= 8 */
7404         if (shCount >= 8) {
7405                 shCount -= 8 ;
7406                 
7407                 if (size > 1){
7408                         if (shCount)
7409                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7410                         else 
7411                                 movLeft2Result(left, LSB, result, MSB16);
7412                 }
7413                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7414         }
7415         
7416         /*  1 <= shCount <= 7 */
7417         else {  
7418                 if(size == 1)
7419                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7420                 else 
7421                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7422         }
7423 }
7424
7425 /*-----------------------------------------------------------------*/
7426 /* shiftLLong - shift left one long from left to result            */
7427 /* offl = LSB or MSB16                                             */
7428 /*-----------------------------------------------------------------*/
7429 static void shiftLLong (operand *left, operand *result, int offr )
7430 {
7431         char *l;
7432         int size = AOP_SIZE(result);
7433         
7434         FENTRY;
7435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7436         if(size >= LSB+offr){
7437                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7438                 MOVA(l);
7439                 pic14_emitcode("add","a,acc");
7440                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7441                         size >= MSB16+offr && offr != LSB )
7442                         pic14_emitcode("xch","a,%s",
7443                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7444                 else      
7445                         aopPut(AOP(result),"a",LSB+offr);
7446         }
7447         
7448         if(size >= MSB16+offr){
7449                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7450                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7451                         MOVA(l);
7452                 }
7453                 pic14_emitcode("rlc","a");
7454                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7455                         size >= MSB24+offr && offr != LSB)
7456                         pic14_emitcode("xch","a,%s",
7457                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7458                 else      
7459                         aopPut(AOP(result),"a",MSB16+offr);
7460         }
7461         
7462         if(size >= MSB24+offr){
7463                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7464                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7465                         MOVA(l);
7466                 }
7467                 pic14_emitcode("rlc","a");
7468                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7469                         size >= MSB32+offr && offr != LSB )
7470                         pic14_emitcode("xch","a,%s",
7471                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7472                 else      
7473                         aopPut(AOP(result),"a",MSB24+offr);
7474         }
7475         
7476         if(size > MSB32+offr){
7477                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7478                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7479                         MOVA(l);  
7480                 }
7481                 pic14_emitcode("rlc","a");
7482                 aopPut(AOP(result),"a",MSB32+offr);
7483         }
7484         if(offr != LSB)
7485                 aopPut(AOP(result),zero,LSB);       
7486 }
7487
7488 /*-----------------------------------------------------------------*/
7489 /* genlshFour - shift four byte by a known amount != 0             */
7490 /*-----------------------------------------------------------------*/
7491 static void genlshFour (operand *result, operand *left, int shCount)
7492 {
7493         int size;
7494         
7495         FENTRY;
7496         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7497         size = AOP_SIZE(result);
7498         
7499         /* if shifting more that 3 bytes */
7500         if (shCount >= 24 ) {
7501                 shCount -= 24;
7502                 if (shCount)
7503                 /* lowest order of left goes to the highest
7504                 order of the destination */
7505                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7506                 else
7507                         movLeft2Result(left, LSB, result, MSB32);
7508                 aopPut(AOP(result),zero,LSB);
7509                 aopPut(AOP(result),zero,MSB16);
7510                 aopPut(AOP(result),zero,MSB32);
7511                 return;
7512         }
7513         
7514         /* more than two bytes */
7515         else if ( shCount >= 16 ) {
7516                 /* lower order two bytes goes to higher order two bytes */
7517                 shCount -= 16;
7518                 /* if some more remaining */
7519                 if (shCount)
7520                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7521                 else {
7522                         movLeft2Result(left, MSB16, result, MSB32);
7523                         movLeft2Result(left, LSB, result, MSB24);
7524                 }
7525                 aopPut(AOP(result),zero,MSB16);
7526                 aopPut(AOP(result),zero,LSB);
7527                 return;
7528         }    
7529         
7530         /* if more than 1 byte */
7531         else if ( shCount >= 8 ) {
7532                 /* lower order three bytes goes to higher order  three bytes */
7533                 shCount -= 8;
7534                 if(size == 2){
7535                         if(shCount)
7536                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7537                         else
7538                                 movLeft2Result(left, LSB, result, MSB16);
7539                 }
7540                 else{   /* size = 4 */
7541                         if(shCount == 0){
7542                                 movLeft2Result(left, MSB24, result, MSB32);
7543                                 movLeft2Result(left, MSB16, result, MSB24);
7544                                 movLeft2Result(left, LSB, result, MSB16);
7545                                 aopPut(AOP(result),zero,LSB);
7546                         }
7547                         else if(shCount == 1)
7548                                 shiftLLong(left, result, MSB16);
7549                         else{
7550                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7551                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7552                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7553                                 aopPut(AOP(result),zero,LSB);
7554                         }
7555                 }
7556         }
7557         
7558         /* 1 <= shCount <= 7 */
7559         else if(shCount <= 2){
7560                 shiftLLong(left, result, LSB);
7561                 if(shCount == 2)
7562                         shiftLLong(result, result, LSB);
7563         }
7564         /* 3 <= shCount <= 7, optimize */
7565         else{
7566                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7567                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7568                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7569         }
7570 }
7571 #endif
7572
7573 #if 0
7574 /*-----------------------------------------------------------------*/
7575 /* genLeftShiftLiteral - left shifting by known count              */
7576 /*-----------------------------------------------------------------*/
7577 static void genLeftShiftLiteral (operand *left,
7578                                                                  operand *right,
7579                                                                  operand *result,
7580                                                                  iCode *ic)
7581 {    
7582         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7583         //int size;
7584         
7585         FENTRY;
7586         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7587         freeAsmop(right,NULL,ic,TRUE);
7588         
7589         aopOp(left,ic,FALSE);
7590         aopOp(result,ic,FALSE);
7591
7592         size = getSize(operandType(result));
7593         
7594 #if VIEW_SIZE
7595         pic14_emitcode("; shift left ","result %d, left %d",size,
7596                 AOP_SIZE(left));
7597 #endif
7598         
7599         /* I suppose that the left size >= result size */
7600         if(shCount == 0){
7601                 while(size--){
7602                         movLeft2Result(left, size, result, size);
7603                 }
7604         }
7605         
7606         else if(shCount >= (size * 8))
7607                 while(size--)
7608                         aopPut(AOP(result),zero,size);
7609                 else{
7610                         switch (size) {
7611                         case 1:
7612                                 genlshOne (result,left,shCount);
7613                                 break;
7614                                 
7615                         case 2:
7616                         case 3:
7617                                 genlshTwo (result,left,shCount);
7618                                 break;
7619                                 
7620                         case 4:
7621                                 genlshFour (result,left,shCount);
7622                                 break;
7623                         }
7624                 }
7625                 freeAsmop(left,NULL,ic,TRUE);
7626                 freeAsmop(result,NULL,ic,TRUE);
7627 }
7628 #endif
7629
7630 /*-----------------------------------------------------------------*
7631 * genMultiAsm - repeat assembly instruction for size of register.
7632 * if endian == 1, then the high byte (i.e base address + size of 
7633 * register) is used first else the low byte is used first;
7634 *-----------------------------------------------------------------*/
7635 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7636 {
7637         
7638         int offset = 0;
7639         
7640         FENTRY;
7641         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7642         
7643         if(!reg)
7644                 return;
7645         
7646         if(!endian) {
7647                 endian = 1;
7648         } else {
7649                 endian = -1;
7650                 offset = size-1;
7651         }
7652         
7653         while(size--) {
7654                 emitpcode(poc,    popGet(AOP(reg),offset));
7655                 offset += endian;
7656         }
7657         
7658 }
7659
7660 #if 0
7661 /*-----------------------------------------------------------------*/
7662 /* genLeftShift - generates code for left shifting                 */
7663 /*-----------------------------------------------------------------*/
7664 static void genLeftShift (iCode *ic)
7665 {
7666         operand *left,*right, *result;
7667         int size, offset;
7668         unsigned long lit = 0L;
7669         char *l;
7670         symbol *tlbl , *tlbl1;
7671         pCodeOp *pctemp;
7672         
7673         FENTRY;
7674         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7675         
7676         right = IC_RIGHT(ic);
7677         left  = IC_LEFT(ic);
7678         result = IC_RESULT(ic);
7679         
7680         aopOp(right,ic,FALSE);
7681         aopOp(left,ic,FALSE);
7682         aopOp(result,ic,FALSE);
7683         
7684         
7685         /* if the shift count is known then do it 
7686         as efficiently as possible */
7687         if (AOP_TYPE(right) == AOP_LIT) {
7688                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7689                 return ;
7690         }
7691         
7692         /* shift count is unknown then we have to form 
7693         a loop get the loop count in B : Note: we take
7694         only the lower order byte since shifting
7695         more that 32 bits make no sense anyway, ( the
7696         largest size of an object can be only 32 bits ) */  
7697         
7698         /* this code fails for RIGHT == RESULT */
7699         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7700         
7701         /* now move the left to the result if they are not the
7702         same */
7703         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7704                 AOP_SIZE(result) > 1) {
7705                 
7706                 size = AOP_SIZE(result);
7707                 offset=0;
7708                 while (size--) {
7709                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7710                         if (*l == '@' && (IS_AOP_PREG(result))) {
7711                                 
7712                                 pic14_emitcode("mov","a,%s",l);
7713                                 aopPut(AOP(result),"a",offset);
7714                         } else {
7715                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7716                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7717                                 //aopPut(AOP(result),l,offset);
7718                         }
7719                         offset++;
7720                 }
7721         }
7722         
7723         if(AOP_TYPE(left) == AOP_LIT)
7724                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7725
7726         size = AOP_SIZE(result);
7727         
7728         /* if it is only one byte then */
7729         if (size == 1) {
7730                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7731                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7732                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7733                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7734                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7735                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7736                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7737                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7738                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7739                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7740                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7741                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7742                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7743                 } else {
7744                         
7745                         tlbl = newiTempLabel(NULL);
7746                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7747                                 mov2w (AOP(left), 0);
7748                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7749                         }
7750                         
7751                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7752                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7753                         emitpLabel(tlbl->key);
7754                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7755                         emitpcode(POC_ADDLW,  popGetLit(1));
7756                         emitSKPC;
7757                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7758                 }
7759                 goto release ;
7760         }
7761         
7762         if (pic14_sameRegs(AOP(left),AOP(result))) {
7763                 
7764                 tlbl = newiTempLabel(NULL);
7765                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7766                 genMultiAsm(POC_RRF, result, size,1);
7767                 emitpLabel(tlbl->key);
7768                 genMultiAsm(POC_RLF, result, size,0);
7769                 emitpcode(POC_ADDLW,  popGetLit(1));
7770                 emitSKPC;
7771                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7772                 goto release;
7773         }
7774         
7775         //tlbl = newiTempLabel(NULL);
7776         //offset = 0 ;   
7777         //tlbl1 = newiTempLabel(NULL);
7778         
7779         //reAdjustPreg(AOP(result));    
7780         
7781         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7782         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7783         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7784         //MOVA(l);
7785         //pic14_emitcode("add","a,acc");         
7786         //aopPut(AOP(result),"a",offset++);
7787         //while (--size) {
7788         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7789         //  MOVA(l);
7790         //  pic14_emitcode("rlc","a");         
7791         //  aopPut(AOP(result),"a",offset++);
7792         //}
7793         //reAdjustPreg(AOP(result));
7794         
7795         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7796         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7797         
7798         
7799         tlbl = newiTempLabel(NULL);
7800         tlbl1= newiTempLabel(NULL);
7801         
7802         size = AOP_SIZE(result);
7803         offset = 1;
7804         
7805         pctemp = popGetTempReg();  /* grab a temporary working register. */
7806         
7807         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7808         
7809         /* offset should be 0, 1 or 3 */
7810         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7811         emitSKPNZ;
7812         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7813         
7814         emitpcode(POC_MOVWF, pctemp);
7815         
7816         
7817         emitpLabel(tlbl->key);
7818         
7819         emitCLRC;
7820         emitpcode(POC_RLF,  popGet(AOP(result),0));
7821         while(--size)
7822                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7823         
7824         emitpcode(POC_DECFSZ,  pctemp);
7825         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7826         emitpLabel(tlbl1->key);
7827         
7828         popReleaseTempReg(pctemp);
7829         
7830         
7831 release:
7832         freeAsmop (right,NULL,ic,TRUE);
7833         freeAsmop(left,NULL,ic,TRUE);
7834         freeAsmop(result,NULL,ic,TRUE);
7835 }
7836 #endif
7837
7838 #if 0
7839 /*-----------------------------------------------------------------*/
7840 /* genrshOne - right shift a one byte quantity by known count      */
7841 /*-----------------------------------------------------------------*/
7842 static void genrshOne (operand *result, operand *left,
7843                                            int shCount, int sign)
7844 {
7845         FENTRY;
7846         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7847         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7848 }
7849
7850 /*-----------------------------------------------------------------*/
7851 /* genrshTwo - right shift two bytes by known amount != 0          */
7852 /*-----------------------------------------------------------------*/
7853 static void genrshTwo (operand *result,operand *left,
7854                                            int shCount, int sign)
7855 {
7856         FENTRY;
7857         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7858         /* if shCount >= 8 */
7859         if (shCount >= 8) {
7860                 shCount -= 8 ;
7861                 if (shCount)
7862                         shiftR1Left2Result(left, MSB16, result, LSB,
7863                         shCount, sign);
7864                 else
7865                         movLeft2Result(left, MSB16, result, LSB);
7866                 
7867                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7868                 
7869                 if(sign) {
7870                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7871                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7872                 }
7873         }
7874         
7875         /*  1 <= shCount <= 7 */
7876         else
7877                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7878 }
7879
7880 /*-----------------------------------------------------------------*/
7881 /* shiftRLong - shift right one long from left to result           */
7882 /* offl = LSB or MSB16                                             */
7883 /*-----------------------------------------------------------------*/
7884 static void shiftRLong (operand *left, int offl,
7885                                                 operand *result, int sign)
7886 {
7887         int size, same;
7888         
7889         FENTRY;
7890         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7891         
7892         size = AOP_SIZE(left);
7893         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7894         
7895         if (sign)
7896                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7897         else
7898                 emitCLRC;
7899
7900         assert (offl >= 0 && offl < size);
7901
7902         same = pic14_sameRegs (AOP(left), AOP(result));
7903
7904         /* perform the shift */
7905         while (size--)
7906         {
7907                 if (same && !offl) {
7908                         emitpcode (POC_RRF, popGet (AOP(result), size));
7909                 } else {
7910                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7911                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7912                 }
7913         } // while
7914
7915         addSign (result, AOP_SIZE(left) - offl, sign);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genrshFour - shift four byte by a known amount != 0             */
7920 /*-----------------------------------------------------------------*/
7921 static void genrshFour (operand *result, operand *left,
7922                                                 int shCount, int sign)
7923 {
7924         FENTRY;
7925         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7926         /* if shifting more that 3 bytes */
7927         if(shCount >= 24 ) {
7928                 shCount -= 24;
7929                 if(shCount)
7930                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7931                 else
7932                         movLeft2Result(left, MSB32, result, LSB);
7933                 
7934                 addSign(result, MSB16, sign);
7935         }
7936         else if(shCount >= 16){
7937                 shCount -= 16;
7938                 if(shCount)
7939                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7940                 else{
7941                         movLeft2Result(left, MSB24, result, LSB);
7942                         movLeft2Result(left, MSB32, result, MSB16);
7943                 }
7944                 addSign(result, MSB24, sign);
7945         }
7946         else if(shCount >= 8){
7947                 shCount -= 8;
7948                 if(shCount == 1)
7949                         shiftRLong(left, MSB16, result, sign);
7950                 else if(shCount == 0){
7951                         movLeft2Result(left, MSB16, result, LSB);
7952                         movLeft2Result(left, MSB24, result, MSB16);
7953                         movLeft2Result(left, MSB32, result, MSB24);
7954                         addSign(result, MSB32, sign);
7955                 }
7956                 else{
7957                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7958                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7959                         /* the last shift is signed */
7960                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7961                         addSign(result, MSB32, sign);
7962                 }
7963         }
7964         else{   /* 1 <= shCount <= 7 */
7965                 if(shCount <= 2){
7966                         shiftRLong(left, LSB, result, sign);
7967                         if(shCount == 2)
7968                                 shiftRLong(result, LSB, result, sign);
7969                 }
7970                 else{
7971                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7972                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7973                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7974                 }
7975         }
7976 }
7977
7978 /*-----------------------------------------------------------------*/
7979 /* genRightShiftLiteral - right shifting by known count            */
7980 /*-----------------------------------------------------------------*/
7981 static void genRightShiftLiteral (operand *left,
7982                                                                   operand *right,
7983                                                                   operand *result,
7984                                                                   iCode *ic,
7985                                                                   int sign)
7986 {    
7987         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7988         int lsize,res_size;
7989         
7990         FENTRY;
7991         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7992         freeAsmop(right,NULL,ic,TRUE);
7993         
7994         aopOp(left,ic,FALSE);
7995         aopOp(result,ic,FALSE);
7996         
7997 #if VIEW_SIZE
7998         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7999                 AOP_SIZE(left));
8000 #endif
8001         
8002         lsize = pic14_getDataSize(left);
8003         res_size = pic14_getDataSize(result);
8004         /* test the LEFT size !!! */
8005         
8006         /* I suppose that the left size >= result size */
8007         if(shCount == 0){
8008                 while(res_size--)
8009                         movLeft2Result(left, res_size, result, res_size);
8010         }
8011         
8012         else if(shCount >= (lsize * 8)){
8013                 
8014                 if(res_size == 1) {
8015                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8016                         if(sign) {
8017                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8018                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8019                         }
8020                 } else {
8021                         
8022                         if(sign) {
8023                                 emitpcode(POC_MOVLW, popGetLit(0));
8024                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8025                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8026                                 while(res_size--)
8027                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8028                                 
8029                         } else {
8030                                 
8031                                 while(res_size--)
8032                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8033                         }
8034                 }
8035         } else {
8036                 
8037                 switch (res_size) {
8038                 case 1:
8039                         genrshOne (result,left,shCount,sign);
8040                         break;
8041                         
8042                 case 2:
8043                         genrshTwo (result,left,shCount,sign);
8044                         break;
8045                         
8046                 case 4:
8047                         genrshFour (result,left,shCount,sign);
8048                         break;
8049                 default :
8050                         break;
8051                 }
8052                 
8053         }
8054
8055         freeAsmop(left,NULL,ic,TRUE);
8056         freeAsmop(result,NULL,ic,TRUE);
8057 }
8058 #endif
8059
8060 #if 0
8061 /*-----------------------------------------------------------------*/
8062 /* genSignedRightShift - right shift of signed number              */
8063 /*-----------------------------------------------------------------*/
8064 static void genSignedRightShift (iCode *ic)
8065 {
8066         operand *right, *left, *result;
8067         int size, offset;
8068         //  char *l;
8069         symbol *tlbl, *tlbl1 ;
8070         pCodeOp *pctemp;
8071         
8072         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8073         
8074         /* we do it the hard way put the shift count in b
8075         and loop thru preserving the sign */
8076         FENTRY;
8077         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8078         
8079         right = IC_RIGHT(ic);
8080         left  = IC_LEFT(ic);
8081         result = IC_RESULT(ic);
8082         
8083         aopOp(right,ic,FALSE);  
8084         aopOp(left,ic,FALSE);
8085         aopOp(result,ic,FALSE);
8086         
8087         
8088         if ( AOP_TYPE(right) == AOP_LIT) {
8089                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8090                 //genRightShiftLiteral (left,right,result,ic,1);
8091                 return ;
8092         }
8093         /* shift count is unknown then we have to form 
8094         a loop get the loop count in B : Note: we take
8095         only the lower order byte since shifting
8096         more that 32 bits make no sense anyway, ( the
8097         largest size of an object can be only 32 bits ) */  
8098         
8099         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8100         //pic14_emitcode("inc","b");
8101         //freeAsmop (right,NULL,ic,TRUE);
8102         //aopOp(left,ic,FALSE);
8103         //aopOp(result,ic,FALSE);
8104         
8105         /* now move the left to the result if they are not the
8106         same */
8107         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8108                 AOP_SIZE(result) > 1) {
8109                 
8110                 size = AOP_SIZE(result);
8111                 offset=0;
8112                 while (size--) { 
8113                         /*
8114                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8115                         if (*l == '@' && IS_AOP_PREG(result)) {
8116                                 pic14_emitcode("mov","a,%s",l);
8117                                 aopPut(AOP(result),"a",offset);
8118                         } else
8119                         aopPut(AOP(result),l,offset);
8120                         */
8121                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8122                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8123                         
8124                         offset++;
8125                 }
8126         }
8127         
8128         /* mov the highest order bit to OVR */    
8129         tlbl = newiTempLabel(NULL);
8130         tlbl1= newiTempLabel(NULL);
8131         
8132         size = AOP_SIZE(result);
8133         offset = size - 1;
8134         
8135         pctemp = popGetTempReg();  /* grab a temporary working register. */
8136         
8137         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8138         
8139         /* offset should be 0, 1 or 3 */
8140         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8141         emitSKPNZ;
8142         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8143         
8144         emitpcode(POC_MOVWF, pctemp);
8145         
8146         
8147         emitpLabel(tlbl->key);
8148         
8149         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8150         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8151         
8152         while(--size) {
8153                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8154         }
8155         
8156         emitpcode(POC_DECFSZ,  pctemp);
8157         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8158         emitpLabel(tlbl1->key);
8159         
8160         popReleaseTempReg(pctemp);
8161 #if 0
8162         size = AOP_SIZE(result);
8163         offset = size - 1;
8164         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8165         pic14_emitcode("rlc","a");
8166         pic14_emitcode("mov","ov,c");
8167         /* if it is only one byte then */
8168         if (size == 1) {
8169                 l = aopGet(AOP(left),0,FALSE,FALSE);
8170                 MOVA(l);
8171                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8172                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8173                 pic14_emitcode("mov","c,ov");
8174                 pic14_emitcode("rrc","a");
8175                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8176                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8177                 aopPut(AOP(result),"a",0);
8178                 goto release ;
8179         }
8180         
8181         reAdjustPreg(AOP(result));
8182         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8183         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8184         pic14_emitcode("mov","c,ov");
8185         while (size--) {
8186                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8187                 MOVA(l);
8188                 pic14_emitcode("rrc","a");         
8189                 aopPut(AOP(result),"a",offset--);
8190         }
8191         reAdjustPreg(AOP(result));
8192         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8193         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8194         
8195 release:
8196 #endif
8197         
8198         freeAsmop(left,NULL,ic,TRUE);
8199         freeAsmop(result,NULL,ic,TRUE);
8200         freeAsmop(right,NULL,ic,TRUE);
8201 }
8202 #endif
8203
8204 /*-----------------------------------------------------------------*/
8205 /* loadSignToC - load the operand's sign bit into CARRY            */
8206 /*-----------------------------------------------------------------*/
8207
8208 static void loadSignToC (operand *op)
8209 {
8210         FENTRY;
8211         assert (op && AOP(op) && AOP_SIZE(op));
8212
8213         emitCLRC;
8214         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8215         emitSETC;
8216 }
8217
8218 /*-----------------------------------------------------------------*/
8219 /* genRightShift - generate code for right shifting                */
8220 /*-----------------------------------------------------------------*/
8221 static void genGenericShift (iCode *ic, int shiftRight)
8222 {
8223         operand *right, *left, *result;
8224         sym_link *retype ;
8225         int size;
8226         symbol *tlbl, *tlbl1, *inverselbl;
8227         
8228         FENTRY;
8229         /* if signed then we do it the hard way preserve the
8230         sign bit moving it inwards */
8231         retype = getSpec(operandType(IC_RESULT(ic)));
8232         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8233         
8234         /* signed & unsigned types are treated the same : i.e. the
8235         signed is NOT propagated inwards : quoting from the
8236         ANSI - standard : "for E1 >> E2, is equivalent to division
8237         by 2**E2 if unsigned or if it has a non-negative value,
8238         otherwise the result is implementation defined ", MY definition
8239         is that the sign does not get propagated */
8240         
8241         right = IC_RIGHT(ic);
8242         left  = IC_LEFT(ic);
8243         result = IC_RESULT(ic);
8244         
8245         aopOp(right,ic,FALSE);
8246         aopOp(left,ic,FALSE);
8247         aopOp(result,ic,FALSE);
8248         
8249         /* if the shift count is known then do it 
8250         as efficiently as possible */
8251         if (AOP_TYPE(right) == AOP_LIT) {
8252                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8253                 if (lit < 0)
8254                 {
8255                         lit = -lit;
8256                         shiftRight = !shiftRight;
8257                 }
8258                 
8259                 if (shiftRight)
8260                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8261                 else
8262                         shiftLeft_Left2ResultLit (left, result, lit);
8263                 //genRightShiftLiteral (left,right,result,ic, 0);
8264                 return ;
8265         }
8266         
8267         /* shift count is unknown then we have to form 
8268         a loop get the loop count in B : Note: we take
8269         only the lower order byte since shifting
8270         more that 32 bits make no sense anyway, ( the
8271         largest size of an object can be only 32 bits ) */  
8272
8273         /* we must not overwrite the shift counter */
8274         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8275         
8276         /* now move the left to the result if they are not the
8277         same */
8278         if (!pic14_sameRegs(AOP(left),AOP(result)))
8279         {
8280                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8281                 while (size--) {
8282                         mov2w(AOP(left), size);
8283                         movwf(AOP(result), size);
8284                 }
8285                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8286         }
8287         
8288         tlbl = newiTempLabel(NULL);
8289         tlbl1= newiTempLabel(NULL);
8290         inverselbl = NULL;
8291         size = AOP_SIZE(result);
8292
8293         mov2w(AOP(right),0);
8294         if (!SPEC_USIGN(operandType(right)))
8295         {
8296                 inverselbl = newiTempLabel(NULL);
8297                 /* signed shift count -- invert shift direction for c<0 */
8298                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8299                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8300         } // if
8301         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8302         /* check for `a = b >> c' with `-c == 0' */
8303         emitSKPNZ;
8304         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8305         emitpLabel(tlbl->key);
8306         /* propagate the sign bit inwards for SIGNED result */
8307         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8308         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8309         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8310         emitSKPC;
8311         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8312
8313         if (!SPEC_USIGN(operandType(right)))
8314         {
8315                 symbol *inv_loop = newiTempLabel(NULL);
8316
8317                 shiftRight = !shiftRight;       /* invert shift direction */
8318                 
8319                 /* we came here from the code above -- we are done */
8320                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8321                 
8322                 /* emit code for shifting N<0 steps, count is already in W */
8323                 emitpLabel(inverselbl->key);
8324                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8325                 emitpLabel(inv_loop->key);
8326                 /* propagate the sign bit inwards for SIGNED result */
8327                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8328                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8329                 emitpcode(POC_ADDLW, popGetLit(1));
8330                 emitSKPC;
8331                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8332         } // if
8333         
8334         emitpLabel(tlbl1->key);
8335         
8336         freeAsmop(left,NULL,ic,TRUE);
8337         freeAsmop (right,NULL,ic,TRUE);
8338         freeAsmop(result,NULL,ic,TRUE);
8339 }
8340
8341 static void genRightShift (iCode *ic)
8342 {
8343         genGenericShift(ic, 1);
8344 }
8345
8346 static void genLeftShift (iCode *ic)
8347 {
8348         genGenericShift(ic, 0);
8349 }
8350
8351 /*-----------------------------------------------------------------*/
8352 /* SetIrp - Set IRP bit                                            */
8353 /*-----------------------------------------------------------------*/
8354 void SetIrp(operand *result) {
8355         FENTRY;
8356         if (AOP_TYPE(result) == AOP_LIT) {
8357                 unsigned lit = (unsigned)operandLitValue(result);
8358                 if (lit&0x100)
8359                         emitSETIRP;
8360                 else
8361                         emitCLRIRP;
8362         } else {
8363                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8364                         int addrs = PCOL(AOP(result))->lit;
8365                         if (addrs & 0x100)
8366                                 emitSETIRP;
8367                         else
8368                                 emitCLRIRP;
8369                 } else {
8370                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8371                         if(AOP_SIZE(result) > 1) {
8372                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8373                                 emitSETIRP;
8374                         }
8375                 }
8376         }
8377 }
8378
8379 static void
8380 setup_fsr (operand *ptr)
8381 {
8382   mov2w_op(ptr, 0);
8383   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8384
8385   /* also setup-up IRP */
8386   SetIrp (ptr);
8387 }
8388
8389 /*-----------------------------------------------------------------*/
8390 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8391 /*                  arbitrary pointer (__code, __data, generic)    */
8392 /*-----------------------------------------------------------------*/
8393 static void
8394 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8395 {
8396     FENTRY;
8397     switch (p_type)
8398     {
8399     case POINTER:
8400     case FPOINTER:
8401       if (!alreadyAddressed) setup_fsr (src);
8402       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8403       break;
8404     
8405     case CPOINTER:
8406       assert( AOP_SIZE(src) == 2 );
8407       mov2w_op(src, 0);
8408       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8409       mov2w_op(src, 1);
8410       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8411       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8412       call_libraryfunc ("__gptrget1");
8413       break;
8414     
8415     case GPOINTER:
8416       assert( AOP_SIZE(src) == 3 );
8417       mov2w_op(src, 0);
8418       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8419       mov2w_op(src, 1);
8420       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8421       mov2w_op(src, 2);
8422       call_libraryfunc ("__gptrget1");
8423       break;
8424     
8425     default:
8426       assert( !"unhandled pointer type" );
8427       break;
8428     }
8429 }
8430
8431 /*-----------------------------------------------------------------*/
8432 /* emitPtrByteSet - emits code to set a byte from src through a    */
8433 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8434 /*-----------------------------------------------------------------*/
8435 static void
8436 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8437 {
8438     FENTRY;
8439     switch (p_type)
8440     {
8441     case POINTER:
8442     case FPOINTER:
8443       if (!alreadyAddressed) setup_fsr (dst);
8444       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8445       break;
8446     
8447     case CPOINTER:
8448       assert( !"trying to assign to __code pointer" );
8449       break;
8450     
8451     case GPOINTER:
8452       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8453       mov2w_op(dst, 0);
8454       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8455       mov2w_op(dst, 1);
8456       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8457       mov2w_op(dst, 2);
8458       call_libraryfunc ("__gptrput1");
8459       break;
8460
8461     default:
8462       assert( !"unhandled pointer type" );
8463       break;
8464     }
8465 }
8466
8467 /*-----------------------------------------------------------------*/
8468 /* genUnpackBits - generates code for unpacking bits               */
8469 /*-----------------------------------------------------------------*/
8470 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8471 {    
8472   int rsize;            /* result size */
8473   sym_link *etype;      /* bitfield type information */
8474   int blen;             /* bitfield length */
8475   int bstr;             /* bitfield starting bit within byte */
8476
8477   FENTRY;
8478   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8479   etype = getSpec(operandType(result));
8480   rsize = getSize (operandType (result));
8481   blen = SPEC_BLEN (etype);
8482   bstr = SPEC_BSTR (etype);
8483
8484   /* single bit field case */
8485   if (blen == 1) {
8486     if (ifx) { /* that is for an if statement */
8487       pCodeOp *pcop;
8488       resolvedIfx rIfx;
8489       resolveIfx(&rIfx,ifx);
8490       if (ptype == -1) /* direct */
8491         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8492       else
8493         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8494       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8495       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8496       ifx->generated=1;
8497     } else {
8498       int i;
8499       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8500       for (i=0; i < AOP_SIZE(result); i++)
8501         emitpcode (POC_CLRF, popGet (AOP(result), i));
8502
8503       switch (ptype)
8504       {
8505       case -1:
8506         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8507         /* adjust result below */
8508         break;
8509         
8510       case POINTER:
8511       case FPOINTER:
8512       case GPOINTER:
8513       case CPOINTER:
8514         emitPtrByteGet (left, ptype, FALSE);
8515         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8516         emitSKPZ;
8517         /* adjust result below */
8518         break;
8519         
8520       default:
8521         assert( !"unhandled pointer type" );
8522       } // switch
8523
8524       /* move sign-/zero extended bit to result */
8525       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8526         emitpcode (POC_INCF, popGet (AOP(result), 0));
8527       } else {
8528         emitpcode (POC_DECF, popGet (AOP(result), 0));
8529       }
8530       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8531     }
8532     return;
8533   }
8534   else if (blen <= 8 && ((blen + bstr) <= 8))
8535   {
8536     /* blen > 1 */
8537     int i;
8538
8539     for (i=0; i < AOP_SIZE(result); i++)
8540       emitpcode (POC_CLRF, popGet (AOP(result), i));
8541
8542     switch (ptype)
8543     {
8544     case -1:
8545       mov2w(AOP(left), 0);
8546       break;
8547       
8548     case POINTER:
8549     case FPOINTER:
8550     case GPOINTER:
8551     case CPOINTER:
8552       emitPtrByteGet (left, ptype, FALSE);
8553       break;
8554       
8555     default:
8556       assert( !"unhandled pointer type" );
8557     } // switch
8558
8559     if (blen < 8)
8560       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8561     movwf(AOP(result), 0);
8562     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8563
8564     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8565     {
8566       /* signed bitfield */
8567       assert (bstr + blen > 0);
8568       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8569       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8570       emitpcode(POC_IORWF, popGet(AOP(result),0));
8571     }
8572     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8573     return;
8574   }
8575
8576   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8577 }
8578
8579 #if 1
8580 /*-----------------------------------------------------------------*/
8581 /* genDataPointerGet - generates code when ptr offset is known     */
8582 /*-----------------------------------------------------------------*/
8583 static void genDataPointerGet (operand *left, 
8584         operand *result, 
8585         iCode *ic)
8586 {
8587         int size , offset = 0;
8588                 
8589         FENTRY;
8590         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8591         
8592         
8593         /* optimization - most of the time, left and result are the same
8594         * address, but different types. for the pic code, we could omit
8595         * the following
8596         */
8597         aopOp(result,ic,TRUE);
8598         
8599         if (pic14_sameRegs (AOP(left), AOP(result)))
8600                 return;
8601         
8602         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8603         
8604         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8605         
8606         size = AOP_SIZE(result);
8607         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8608         
8609         offset = 0;
8610         while (size--) {
8611                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8612                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8613                 offset++;
8614         }
8615         
8616         freeAsmop(left,NULL,ic,TRUE);
8617         freeAsmop(result,NULL,ic,TRUE);
8618 }
8619 #endif
8620
8621 /*-----------------------------------------------------------------*/
8622 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8623 /*-----------------------------------------------------------------*/
8624 static void genNearPointerGet (operand *left, 
8625                                                            operand *result, 
8626                                                            iCode *ic)
8627 {
8628         asmop *aop = NULL;
8629         sym_link *ltype = operandType(left);
8630         sym_link *rtype = operandType(result);
8631         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8632         int direct = 0;
8633
8634         FENTRY;
8635         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8636         
8637         
8638         aopOp(left,ic,FALSE);
8639         
8640         /* if left is rematerialisable and
8641         result is not bit variable type and
8642         the left is pointer to data space i.e
8643         lower 128 bytes of space */
8644         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8645                 !IS_BITVAR(retype)         &&
8646                 PIC_IS_DATA_PTR(ltype)) {
8647                 genDataPointerGet (left,result,ic);
8648                 return ;
8649         }
8650         
8651         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8652         aopOp (result,ic,FALSE);
8653         
8654         /* Check if can access directly instead of via a pointer */
8655         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8656                 && AOP_SIZE(result) == 1)
8657         {
8658                 direct = 1;
8659         }
8660
8661         if (IS_BITFIELD(getSpec(operandType(result)))) 
8662         {
8663                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8664                 goto release;
8665         }
8666         
8667         /* If the pointer value is not in a the FSR then need to put it in */
8668         /* Must set/reset IRP bit for use with FSR. */
8669         if (!direct)
8670           setup_fsr (left);
8671         
8672 //      sym_link *etype;
8673         /* if bitfield then unpack the bits */
8674         {
8675                 /* we have can just get the values */
8676                 int size = AOP_SIZE(result);
8677                 int offset = 0 ;  
8678                 
8679                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8680                 
8681                 while(size--) {
8682                         if (direct)
8683                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8684                         else
8685                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8686                         if (AOP_TYPE(result) == AOP_LIT) {
8687                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8688                         } else {
8689                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8690                         }
8691                         if (size && !direct)
8692                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8693                         offset++;
8694                 }
8695         }
8696         
8697         /* now some housekeeping stuff */
8698         if (aop) {
8699                 /* we had to allocate for this iCode */
8700                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701                 freeAsmop(NULL,aop,ic,TRUE);
8702         } else { 
8703                 /* we did not allocate which means left
8704                 already in a pointer register, then
8705                 if size > 0 && this could be used again
8706                 we have to point it back to where it 
8707                 belongs */
8708                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8709                 if (AOP_SIZE(result) > 1 &&
8710                         !OP_SYMBOL(left)->remat &&
8711                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8712                         ic->depth )) {
8713                         int size = AOP_SIZE(result) - 1;
8714                         while (size--)
8715                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8716                 }
8717         }
8718         
8719 release:
8720         /* done */
8721         freeAsmop(left,NULL,ic,TRUE);
8722         freeAsmop(result,NULL,ic,TRUE);
8723
8724 }
8725
8726 #if 0
8727 /*-----------------------------------------------------------------*/
8728 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8729 /*-----------------------------------------------------------------*/
8730 static void genPagedPointerGet (operand *left, 
8731                                                                 operand *result, 
8732                                                                 iCode *ic)
8733 {
8734         asmop *aop = NULL;
8735         regs *preg = NULL ;
8736         char *rname ;
8737         sym_link *rtype, *retype;    
8738         
8739         FENTRY;
8740         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741         
8742         rtype = operandType(result);
8743         retype= getSpec(rtype);
8744         
8745         aopOp(left,ic,FALSE);
8746         
8747         /* if the value is already in a pointer register
8748         then don't need anything more */
8749         if (!AOP_INPREG(AOP(left))) {
8750                 /* otherwise get a free pointer register */
8751                 aop = newAsmop(0);
8752                 preg = getFreePtr(ic,&aop,FALSE);
8753                 pic14_emitcode("mov","%s,%s",
8754                         preg->name,
8755                         aopGet(AOP(left),0,FALSE,TRUE));
8756                 rname = preg->name ;
8757         } else
8758                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8759         
8760         freeAsmop(left,NULL,ic,TRUE);
8761         aopOp (result,ic,FALSE);
8762         
8763         /* if bitfield then unpack the bits */
8764         if (IS_BITFIELD(retype)) 
8765                 genUnpackBits (result,left,rname,PPOINTER,0);
8766         else {
8767                 /* we have can just get the values */
8768                 int size = AOP_SIZE(result);
8769                 int offset = 0 ;  
8770                 
8771                 while (size--) {
8772                         
8773                         pic14_emitcode("movx","a,@%s",rname);
8774                         aopPut(AOP(result),"a",offset);
8775                         
8776                         offset++ ;
8777                         
8778                         if (size)
8779                                 pic14_emitcode("inc","%s",rname);
8780                 }
8781         }
8782         
8783         /* now some housekeeping stuff */
8784         if (aop) {
8785                 /* we had to allocate for this iCode */
8786                 freeAsmop(NULL,aop,ic,TRUE);
8787         } else { 
8788         /* we did not allocate which means left
8789         already in a pointer register, then
8790         if size > 0 && this could be used again
8791         we have to point it back to where it 
8792                 belongs */
8793                 if (AOP_SIZE(result) > 1 &&
8794                         !OP_SYMBOL(left)->remat &&
8795                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8796                         ic->depth )) {
8797                         int size = AOP_SIZE(result) - 1;
8798                         while (size--)
8799                                 pic14_emitcode("dec","%s",rname);
8800                 }
8801         }
8802         
8803         /* done */
8804         freeAsmop(result,NULL,ic,TRUE);
8805         
8806         
8807 }
8808
8809 /*-----------------------------------------------------------------*/
8810 /* genFarPointerGet - gget value from far space                    */
8811 /*-----------------------------------------------------------------*/
8812 static void genFarPointerGet (operand *left,
8813                                                           operand *result, iCode *ic)
8814 {
8815         int size, offset ;
8816         sym_link *retype = getSpec(operandType(result));
8817         
8818         FENTRY;
8819         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8820         
8821         aopOp(left,ic,FALSE);
8822         
8823         /* if the operand is already in dptr 
8824         then we do nothing else we move the value to dptr */
8825         if (AOP_TYPE(left) != AOP_STR) {
8826                 /* if this is remateriazable */
8827                 if (AOP_TYPE(left) == AOP_IMMD)
8828                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8829                 else { /* we need to get it byte by byte */
8830                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8831                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8832                         if (options.model == MODEL_FLAT24)
8833                         {
8834                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8835                         }
8836                 }
8837         }
8838         /* so dptr know contains the address */
8839         freeAsmop(left,NULL,ic,TRUE);
8840         aopOp(result,ic,FALSE);
8841         
8842         /* if bit then unpack */
8843         if (IS_BITFIELD(retype)) 
8844                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8845         else {
8846                 size = AOP_SIZE(result);
8847                 offset = 0 ;
8848                 
8849                 while (size--) {
8850                         pic14_emitcode("movx","a,@dptr");
8851                         aopPut(AOP(result),"a",offset++);
8852                         if (size)
8853                                 pic14_emitcode("inc","dptr");
8854                 }
8855         }
8856         
8857         freeAsmop(result,NULL,ic,TRUE);
8858 }
8859 #endif
8860
8861 #if 0
8862 /*-----------------------------------------------------------------*/
8863 /* genCodePointerGet - get value from code space                  */
8864 /*-----------------------------------------------------------------*/
8865 static void genCodePointerGet (operand *left,
8866                                                            operand *result, iCode *ic)
8867 {
8868         int size, offset ;
8869         sym_link *retype = getSpec(operandType(result));
8870         
8871         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8872         
8873         aopOp(left,ic,FALSE);
8874         
8875         /* if the operand is already in dptr 
8876         then we do nothing else we move the value to dptr */
8877         if (AOP_TYPE(left) != AOP_STR) {
8878                 /* if this is remateriazable */
8879                 if (AOP_TYPE(left) == AOP_IMMD)
8880                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8881                 else { /* we need to get it byte by byte */
8882                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8883                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8884                         if (options.model == MODEL_FLAT24)
8885                         {
8886                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8887                         }
8888                 }
8889         }
8890         /* so dptr know contains the address */
8891         freeAsmop(left,NULL,ic,TRUE);
8892         aopOp(result,ic,FALSE);
8893         
8894         /* if bit then unpack */
8895         if (IS_BITFIELD(retype)) 
8896                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8897         else {
8898                 size = AOP_SIZE(result);
8899                 offset = 0 ;
8900                 
8901                 while (size--) {
8902                         pic14_emitcode("clr","a");
8903                         pic14_emitcode("movc","a,@a+dptr");
8904                         aopPut(AOP(result),"a",offset++);
8905                         if (size)
8906                                 pic14_emitcode("inc","dptr");
8907                 }
8908         }
8909         
8910         freeAsmop(result,NULL,ic,TRUE);
8911 }
8912 #endif
8913 /*-----------------------------------------------------------------*/
8914 /* genGenPointerGet - gget value from generic pointer space        */
8915 /*-----------------------------------------------------------------*/
8916 static void genGenPointerGet (operand *left,
8917                                                           operand *result, iCode *ic)
8918 {
8919         FENTRY;
8920         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8921         aopOp(left,ic,FALSE);
8922         aopOp(result,ic,FALSE);
8923         
8924         
8925         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8926
8927         if (IS_BITFIELD(getSpec(operandType(result))))
8928         {
8929           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8930           return;
8931         }
8932
8933         {
8934           /* emit call to __gptrget */
8935           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8936           int size = AOP_SIZE(result);
8937           int idx = 0;
8938
8939           assert (size > 0 && size <= 4);
8940
8941           /* pass arguments */
8942           assert (AOP_SIZE(left) == 3);
8943           mov2w(AOP(left), 0);
8944           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8945           mov2w(AOP(left), 1);
8946           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8947           mov2w(AOP(left), 2);
8948           call_libraryfunc (func[size]);
8949           
8950           /* save result */
8951           movwf (AOP(result), --size);
8952           while (size--) {
8953             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8954             movwf (AOP(result), size);
8955           } // while
8956         }
8957         
8958         freeAsmop(left,NULL,ic,TRUE);
8959         freeAsmop(result,NULL,ic,TRUE);
8960         
8961 }
8962
8963 /*-----------------------------------------------------------------*/
8964 /* genConstPointerGet - get value from const generic pointer space */
8965 /*-----------------------------------------------------------------*/
8966 static void genConstPointerGet (operand *left,
8967                                                                 operand *result, iCode *ic)
8968 {
8969         //sym_link *retype = getSpec(operandType(result));
8970         #if 0
8971         symbol *albl, *blbl;//, *clbl;
8972         pCodeOp *pcop;
8973         #endif
8974         PIC_OPCODE poc;
8975         int i, size, lit;
8976         
8977         FENTRY;
8978         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8979         aopOp(left,ic,FALSE);
8980         aopOp(result,ic,FALSE);
8981         
8982         size = AOP_SIZE(result);
8983         
8984         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8985         
8986         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8987
8988         lit = op_isLitLike (left);
8989         poc = lit ? POC_MOVLW : POC_MOVFW;
8990
8991         if (IS_BITFIELD(getSpec(operandType(result))))
8992         {
8993                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8994                 goto release;
8995         }
8996
8997         {
8998                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8999                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9000                 assert (size > 0 && size <= 4);
9001                 
9002                 mov2w_op(left, 0);
9003                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9004                 mov2w_op(left, 1);
9005                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9006                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9007                 call_libraryfunc (func[size]);
9008
9009                 movwf(AOP(result),size-1);
9010                 for (i = 1; i < size; i++)
9011                 {
9012                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9013                         movwf(AOP(result),size - 1 - i);
9014                 } // for
9015         }
9016         
9017 release:
9018         freeAsmop(left,NULL,ic,TRUE);
9019         freeAsmop(result,NULL,ic,TRUE);
9020         
9021 }
9022 /*-----------------------------------------------------------------*/
9023 /* genPointerGet - generate code for pointer get                   */
9024 /*-----------------------------------------------------------------*/
9025 static void genPointerGet (iCode *ic)
9026 {
9027         operand *left, *result ;
9028         sym_link *type, *etype;
9029         int p_type = -1;
9030         
9031         FENTRY;
9032         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9033         
9034         left = IC_LEFT(ic);
9035         result = IC_RESULT(ic) ;
9036         
9037         /* depending on the type of pointer we need to
9038         move it to the correct pointer register */
9039         type = operandType(left);
9040         etype = getSpec(type);
9041         
9042         if (IS_PTR_CONST(type))
9043                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9044         
9045         /* if left is of type of pointer then it is simple */
9046         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9047                 p_type = DCL_TYPE(type);
9048         else {
9049                 /* we have to go by the storage class */
9050                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9051                 
9052                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9053                 
9054                 if (SPEC_OCLS(etype)->codesp ) {
9055                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9056                         //p_type = CPOINTER ; 
9057                 }
9058                 else
9059                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9060                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9061                         /*p_type = FPOINTER ;*/ 
9062                         else
9063                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9064                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9065                                 /*        p_type = PPOINTER; */
9066                                 else
9067                                         if (SPEC_OCLS(etype) == idata )
9068                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9069                                         /*      p_type = IPOINTER; */
9070                                         else
9071                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9072                                         /*      p_type = POINTER ; */
9073         }
9074         
9075         /* now that we have the pointer type we assign
9076         the pointer values */
9077         switch (p_type) {
9078                 
9079         case POINTER: 
9080         case FPOINTER:
9081         //case IPOINTER:
9082                 genNearPointerGet (left,result,ic);
9083                 break;
9084 /*
9085         case PPOINTER:
9086                 genPagedPointerGet(left,result,ic);
9087                 break;
9088                 
9089         case FPOINTER:
9090                 genFarPointerGet (left,result,ic);
9091                 break;
9092 */              
9093         case CPOINTER:
9094                 genConstPointerGet (left,result,ic);
9095                 break;
9096                 
9097         case GPOINTER:
9098                 genGenPointerGet (left,result,ic);
9099                 break;
9100         default:
9101                 assert ( !"unhandled pointer type" );
9102                 break;
9103         }
9104         
9105 }
9106
9107 /*-----------------------------------------------------------------*/
9108 /* genPackBits - generates code for packed bit storage             */
9109 /*-----------------------------------------------------------------*/
9110 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9111 {
9112   int blen;             /* bitfield length */
9113   int bstr;             /* bitfield starting bit within byte */
9114   int litval;           /* source literal value (if AOP_LIT) */
9115   unsigned char mask;   /* bitmask within current byte */
9116
9117   FENTRY;
9118   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9119
9120   blen = SPEC_BLEN (etype);
9121   bstr = SPEC_BSTR (etype);
9122
9123   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9124   if ((blen <= 8) && ((bstr + blen) <= 8))
9125   {
9126     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9127             (unsigned char) (0xFF >> (8 - bstr)));
9128
9129     if (AOP_TYPE (right) == AOP_LIT)
9130     {
9131       /* Case with a bitfield length <8 and literal source */
9132       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9133       if (blen == 1) {
9134         pCodeOp *pcop;
9135         
9136         switch (p_type)
9137         {
9138         case -1:
9139           if (AOP(result)->type == AOP_PCODE)
9140             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9141           else
9142             pcop = popGet(AOP(result),0);
9143           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9144           break;
9145         
9146         case POINTER:
9147         case FPOINTER:
9148           setup_fsr (result);
9149           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9150           break;
9151         
9152         case CPOINTER:
9153           assert( !"trying to assign to bitfield via pointer to __code space" );
9154           break;
9155         
9156         case GPOINTER:
9157           emitPtrByteGet(result, p_type, FALSE);
9158           if (lit) {
9159             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9160           } else {
9161             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9162           }
9163           emitPtrByteSet(result, p_type, TRUE);
9164           break;
9165         
9166         default:
9167           assert( !"unhandled pointer type" );
9168           break;
9169         } // switch (p_type)
9170       } else {
9171         /* blen > 1 */
9172         litval = lit << bstr;
9173         litval &= (~mask) & 0x00ff;
9174         
9175         switch (p_type)
9176         {
9177         case -1:
9178           mov2w (AOP(result), 0);
9179           if ((litval|mask) != 0x00ff)
9180             emitpcode(POC_ANDLW, popGetLit (mask));
9181           if (litval != 0x00)
9182             emitpcode(POC_IORLW, popGetLit (litval));
9183           movwf (AOP(result), 0);
9184           break;
9185         
9186         case POINTER:
9187         case FPOINTER:
9188         case GPOINTER:
9189           emitPtrByteGet(result, p_type, FALSE);
9190           if ((litval|mask) != 0x00ff)
9191             emitpcode(POC_ANDLW, popGetLit (mask));
9192           if (litval != 0x00)
9193             emitpcode(POC_IORLW, popGetLit (litval));
9194           emitPtrByteSet(result, p_type, TRUE);
9195           break;
9196         
9197         case CPOINTER:
9198           assert( !"trying to assign to bitfield via pointer to __code space" );
9199           break;
9200         
9201         default:
9202           assert( !"unhandled pointer type" );
9203           break;
9204         } // switch
9205       } // if (blen > 1)
9206     }
9207     else
9208     {
9209       /* right is no literal */
9210       if (blen==1) {
9211         switch (p_type)
9212         {
9213         case -1:
9214           /* Note more efficient code, of pre clearing bit then only setting it if required,
9215            * can only be done if it is known that the result is not a SFR */
9216           emitpcode(POC_RRFW,popGet(AOP(right),0));
9217           emitSKPC;
9218           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9219           emitSKPNC;
9220           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9221           break;
9222         
9223         case POINTER:
9224         case FPOINTER:
9225         case GPOINTER:
9226           emitPtrByteGet (result, p_type, FALSE);
9227           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9228           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9229           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9230           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9231           emitPtrByteSet (result, p_type, TRUE);
9232           break;
9233         
9234         case CPOINTER:
9235           assert( !"trying to assign to bitfield via pointer to __code space" );
9236           break;
9237         
9238         default:
9239           assert( !"unhandled pointer type" );
9240           break;
9241         } // switch
9242         return;
9243       } else {
9244         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9245         pCodeOp *temp = popGetTempReg ();
9246
9247         mov2w (AOP(right), 0);
9248         if (blen < 8) {
9249           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9250         }
9251         emitpcode(POC_MOVWF, temp);
9252         if (bstr) {
9253           AccLsh (temp, bstr);
9254         }
9255         
9256         switch (p_type)
9257         {
9258         case -1:
9259           mov2w (AOP(result), 0);
9260           emitpcode(POC_ANDLW, popGetLit (mask));
9261           emitpcode(POC_IORFW, temp);
9262           movwf (AOP(result), 0);
9263           break;
9264         
9265         case POINTER:
9266         case FPOINTER:
9267         case GPOINTER:
9268           emitPtrByteGet (result, p_type, FALSE);
9269           emitpcode(POC_ANDLW, popGetLit (mask));
9270           emitpcode(POC_IORFW, temp);
9271           emitPtrByteSet (result, p_type, TRUE);
9272           break;
9273         
9274         case CPOINTER:
9275           assert( !"trying to assign to bitfield via pointer to __code space" );
9276           break;
9277         
9278         default:
9279           assert( !"unhandled pointer type" );
9280           break;
9281         } // switch
9282
9283         popReleaseTempReg (temp);
9284       } // if (blen > 1)
9285     } // if (AOP(right)->type != AOP_LIT)
9286     return;
9287   } // if (blen <= 8 && ((blen + bstr) <= 8))
9288
9289   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9290 }
9291
9292 /*-----------------------------------------------------------------*/
9293 /* genDataPointerSet - remat pointer to data space                 */
9294 /*-----------------------------------------------------------------*/
9295 static void genDataPointerSet(operand *right,
9296         operand *result,
9297         iCode *ic)
9298 {
9299         int size, offset = 0 ;
9300         int ressize;
9301         
9302         FENTRY;
9303         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9304         aopOp(right,ic,FALSE);
9305         aopOp(result,ic,FALSE);
9306         
9307         assert (IS_SYMOP(result));
9308         assert (IS_PTR(OP_SYM_TYPE(result)));
9309         
9310         if (AOP_TYPE(right) == AOP_LIT)
9311           size = 4;
9312         else
9313           size = AOP_SIZE(right);
9314         ressize = getSize(OP_SYM_ETYPE(result));
9315         if (size > ressize) size = ressize;
9316         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9317         
9318         //assert( !"what's going on here?" );
9319
9320         /*
9321         if ( AOP_TYPE(result) == AOP_PCODE) {
9322         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9323         AOP(result)->aopu.pcop->name,
9324         PCOI(AOP(result)->aopu.pcop)->offset);
9325         }
9326         */
9327         
9328         // tsd, was l+1 - the underline `_' prefix was being stripped
9329         while (size--) {
9330                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9331                 
9332                 if (AOP_TYPE(right) == AOP_LIT) {
9333                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9334                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9335                         if(lit&0xff) {
9336                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9337                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9338                         } else {
9339                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9340                         }
9341                 } else {
9342                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9343                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9344                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9345                 }
9346                 
9347                 offset++;
9348         }
9349         
9350         freeAsmop(right,NULL,ic,TRUE);
9351         freeAsmop(result,NULL,ic,TRUE);
9352 }
9353
9354 /*-----------------------------------------------------------------*/
9355 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9356 /*-----------------------------------------------------------------*/
9357 static void genNearPointerSet (operand *right,
9358                                                            operand *result, 
9359                                                            iCode *ic)
9360 {
9361         asmop *aop = NULL;
9362         sym_link *ptype = operandType(result);
9363         sym_link *retype = getSpec(operandType(right));
9364         sym_link *letype = getSpec(ptype);
9365         int direct = 0;
9366         
9367         
9368         FENTRY;
9369         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9370         aopOp(result,ic,FALSE);
9371         
9372 #if 1
9373         /* if the result is rematerializable &
9374         in data space & not a bit variable */
9375         //if (AOP_TYPE(result) == AOP_IMMD &&
9376         if (AOP_TYPE(result) == AOP_PCODE &&
9377                 PIC_IS_DATA_PTR(ptype) &&
9378                 !IS_BITVAR (retype) &&
9379                 !IS_BITVAR (letype)) {
9380                 genDataPointerSet (right,result,ic);
9381                 freeAsmop(result,NULL,ic,TRUE);
9382                 return;
9383         }
9384 #endif
9385
9386         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9387         aopOp(right,ic,FALSE);
9388         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9389         
9390         /* Check if can access directly instead of via a pointer */
9391         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9392                 direct = 1;
9393         }
9394         
9395         if (IS_BITFIELD (letype))
9396         {
9397           genPackBits (letype, result, right, direct?-1:POINTER);
9398           return;
9399         }
9400         
9401         /* If the pointer value is not in a the FSR then need to put it in */
9402         /* Must set/reset IRP bit for use with FSR. */
9403         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9404         if (!direct)
9405                 setup_fsr (result);
9406
9407         {
9408                 /* we have can just get the values */
9409                 int size = AOP_SIZE(right);
9410                 int offset = 0 ;    
9411                 
9412                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9413                 while (size--) {
9414                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9415                         if (*l == '@' ) {
9416                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9417                         } else {
9418                                 if (AOP_TYPE(right) == AOP_LIT) {
9419                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9420                                 } else {
9421                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9422                                 }
9423                                 if (direct)
9424                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9425                                 else
9426                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9427                         }
9428                         if (size && !direct)
9429                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9430                         offset++;
9431                 }
9432         }
9433         
9434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9435         /* now some housekeeping stuff */
9436         if (aop) {
9437                 /* we had to allocate for this iCode */
9438                 freeAsmop(NULL,aop,ic,TRUE);
9439         } else { 
9440                 /* we did not allocate which means left
9441                 already in a pointer register, then
9442                 if size > 0 && this could be used again
9443                 we have to point it back to where it 
9444                 belongs */
9445                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9446                 if (AOP_SIZE(right) > 1 &&
9447                         !OP_SYMBOL(result)->remat &&
9448                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9449                         ic->depth )) {
9450                         int size = AOP_SIZE(right) - 1;
9451                         while (size--)
9452                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9453                 }
9454         }
9455         
9456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9457         /* done */
9458
9459         freeAsmop(right,NULL,ic,TRUE);
9460         freeAsmop(result,NULL,ic,TRUE);
9461 }
9462
9463 #if 0
9464 /*-----------------------------------------------------------------*/
9465 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9466 /*-----------------------------------------------------------------*/
9467 static void genPagedPointerSet (operand *right,
9468                                                                 operand *result, 
9469                                                                 iCode *ic)
9470 {
9471         asmop *aop = NULL;
9472         regs *preg = NULL ;
9473         char *rname , *l;
9474         sym_link *retype;
9475         
9476         FENTRY;
9477         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9478         
9479         retype= getSpec(operandType(right));
9480         
9481         aopOp(result,ic,FALSE);
9482         
9483         /* if the value is already in a pointer register
9484         then don't need anything more */
9485         if (!AOP_INPREG(AOP(result))) {
9486                 /* otherwise get a free pointer register */
9487                 aop = newAsmop(0);
9488                 preg = getFreePtr(ic,&aop,FALSE);
9489                 pic14_emitcode("mov","%s,%s",
9490                         preg->name,
9491                         aopGet(AOP(result),0,FALSE,TRUE));
9492                 rname = preg->name ;
9493         } else
9494                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9495         
9496         freeAsmop(result,NULL,ic,TRUE);
9497         aopOp (right,ic,FALSE);
9498         
9499         /* if bitfield then unpack the bits */
9500         if (IS_BITFIELD(retype)) 
9501                 genPackBits (retype,result,right,rname,PPOINTER);
9502         else {
9503                 /* we have can just get the values */
9504                 int size = AOP_SIZE(right);
9505                 int offset = 0 ;  
9506                 
9507                 while (size--) {
9508                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9509                         
9510                         MOVA(l);
9511                         pic14_emitcode("movx","@%s,a",rname);
9512                         
9513                         if (size)
9514                                 pic14_emitcode("inc","%s",rname);
9515                         
9516                         offset++;
9517                 }
9518         }
9519         
9520         /* now some housekeeping stuff */
9521         if (aop) {
9522                 /* we had to allocate for this iCode */
9523                 freeAsmop(NULL,aop,ic,TRUE);
9524         } else { 
9525         /* we did not allocate which means left
9526         already in a pointer register, then
9527         if size > 0 && this could be used again
9528         we have to point it back to where it 
9529                 belongs */
9530                 if (AOP_SIZE(right) > 1 &&
9531                         !OP_SYMBOL(result)->remat &&
9532                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9533                         ic->depth )) {
9534                         int size = AOP_SIZE(right) - 1;
9535                         while (size--)
9536                                 pic14_emitcode("dec","%s",rname);
9537                 }
9538         }
9539         
9540         /* done */
9541         freeAsmop(right,NULL,ic,TRUE);
9542         
9543         
9544 }
9545
9546 /*-----------------------------------------------------------------*/
9547 /* genFarPointerSet - set value from far space                     */
9548 /*-----------------------------------------------------------------*/
9549 static void genFarPointerSet (operand *right,
9550                                                           operand *result, iCode *ic)
9551 {
9552         int size, offset ;
9553         sym_link *retype = getSpec(operandType(right));
9554         
9555         FENTRY;
9556         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9557         aopOp(result,ic,FALSE);
9558         
9559         /* if the operand is already in dptr 
9560         then we do nothing else we move the value to dptr */
9561         if (AOP_TYPE(result) != AOP_STR) {
9562                 /* if this is remateriazable */
9563                 if (AOP_TYPE(result) == AOP_IMMD)
9564                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9565                 else { /* we need to get it byte by byte */
9566                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9567                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9568                         if (options.model == MODEL_FLAT24)
9569                         {
9570                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9571                         }
9572                 }
9573         }
9574         /* so dptr know contains the address */
9575         freeAsmop(result,NULL,ic,TRUE);
9576         aopOp(right,ic,FALSE);
9577         
9578         /* if bit then unpack */
9579         if (IS_BITFIELD(retype)) 
9580                 genPackBits(retype,result,right,"dptr",FPOINTER);
9581         else {
9582                 size = AOP_SIZE(right);
9583                 offset = 0 ;
9584                 
9585                 while (size--) {
9586                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9587                         MOVA(l);
9588                         pic14_emitcode("movx","@dptr,a");
9589                         if (size)
9590                                 pic14_emitcode("inc","dptr");
9591                 }
9592         }
9593         
9594         freeAsmop(right,NULL,ic,TRUE);
9595 }
9596 #endif
9597
9598 /*-----------------------------------------------------------------*/
9599 /* genGenPointerSet - set value from generic pointer space         */
9600 /*-----------------------------------------------------------------*/
9601 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9602 {
9603         sym_link *retype = getSpec(operandType(result));
9604         
9605         FENTRY;
9606         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9607         aopOp(right,ic,FALSE);
9608         aopOp(result,ic,FALSE);
9609
9610         
9611         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9612
9613         if (IS_BITFIELD(retype))
9614         {
9615           genPackBits (retype, result, right, GPOINTER);
9616           return;
9617         }
9618
9619         {
9620           /* emit call to __gptrput */
9621           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9622           int size = AOP_SIZE(right);
9623           int idx = 0;
9624
9625           assert (size == getSize(OP_SYM_ETYPE(result)));
9626           assert (size > 0 && size <= 4);
9627
9628           /* pass arguments */
9629           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9630           {
9631             int off = size;
9632             idx = 2;
9633             while (off--)
9634             {
9635               mov2w_op (right, off);
9636               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9637             }
9638             idx = 0;
9639           }
9640           /* - address */
9641           assert (AOP_SIZE(result) == 3);
9642           mov2w(AOP(result), 0);
9643           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9644           mov2w(AOP(result), 1);
9645           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9646           mov2w(AOP(result), 2);
9647           call_libraryfunc (func[size]);
9648         }
9649         
9650         freeAsmop(right,NULL,ic,TRUE);
9651         freeAsmop(result,NULL,ic,TRUE);
9652 }
9653
9654 /*-----------------------------------------------------------------*/
9655 /* genPointerSet - stores the value into a pointer location        */
9656 /*-----------------------------------------------------------------*/
9657 static void genPointerSet (iCode *ic)
9658 {    
9659         operand *right, *result ;
9660         sym_link *type, *etype;
9661         int p_type;
9662         
9663         FENTRY;
9664         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9665         
9666         right = IC_RIGHT(ic);
9667         result = IC_RESULT(ic) ;
9668         
9669         /* depending on the type of pointer we need to
9670         move it to the correct pointer register */
9671         type = operandType(result);
9672         etype = getSpec(type);
9673         /* if left is of type of pointer then it is simple */
9674         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9675                 p_type = DCL_TYPE(type);
9676         }
9677         else {
9678                 /* we have to go by the storage class */
9679                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9680                 
9681                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9682                 /*      p_type = CPOINTER ;  */
9683                 /*  } */
9684                 /*  else */
9685                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9686                 /*    p_type = FPOINTER ; */
9687                 /*      else */
9688                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9689                 /*        p_type = PPOINTER ; */
9690                 /*    else */
9691                 /*        if (SPEC_OCLS(etype) == idata ) */
9692                 /*      p_type = IPOINTER ; */
9693                 /*        else */
9694                 /*      p_type = POINTER ; */
9695         }
9696         
9697         /* now that we have the pointer type we assign
9698         the pointer values */
9699         switch (p_type) {
9700                 
9701         case POINTER:
9702         case FPOINTER:
9703         //case IPOINTER:
9704                 genNearPointerSet (right,result,ic);
9705                 break;
9706 /*
9707         case PPOINTER:
9708                 genPagedPointerSet (right,result,ic);
9709                 break;
9710                 
9711         case FPOINTER:
9712                 genFarPointerSet (right,result,ic);
9713                 break;
9714 */
9715         case GPOINTER:
9716                 genGenPointerSet (right,result,ic);
9717                 break;
9718                 
9719         default:
9720                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9721                         "genPointerSet: illegal pointer type");
9722         }
9723 }
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genIfx - generate code for Ifx statement                        */
9727 /*-----------------------------------------------------------------*/
9728 static void genIfx (iCode *ic, iCode *popIc)
9729 {
9730         operand *cond = IC_COND(ic);
9731         int isbit =0;
9732         
9733         FENTRY;
9734         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9735         
9736         aopOp(cond,ic,FALSE);
9737         
9738         /* get the value into acc */
9739         if (AOP_TYPE(cond) != AOP_CRY)
9740                 pic14_toBoolean(cond);
9741         else
9742                 isbit = 1;
9743         
9744         /* if there was something to be popped then do it */
9745         if (popIc)
9746                 genIpop(popIc);
9747         
9748         if (isbit)
9749         {
9750                 /* This assumes that CARRY is set iff cond is true */
9751                 if (IC_TRUE(ic))
9752                 {
9753                         assert (!IC_FALSE(ic));
9754                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9755                         //emitSKPNC;
9756                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9757                 } else {
9758                         assert (IC_FALSE(ic));
9759                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9760                         //emitSKPC;
9761                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9762                 }
9763                 if (0)
9764                 {
9765                         static int hasWarned = 0;
9766                         if (!hasWarned)
9767                         {
9768                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9769                                 hasWarned = 1;
9770                         }
9771                 }
9772         }
9773         else
9774         {
9775                 /* now Z is set iff !cond */
9776                 if (IC_TRUE(ic))
9777                 {
9778                         assert (!IC_FALSE(ic));
9779                         emitSKPZ;
9780                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9781                 } else {
9782                         emitSKPNZ;
9783                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9784                 }
9785         }
9786         
9787         ic->generated = 1;
9788         
9789         /* the result is now in the accumulator */
9790         freeAsmop(cond,NULL,ic,TRUE);
9791 }
9792
9793 /*-----------------------------------------------------------------*/
9794 /* genAddrOf - generates code for address of                       */
9795 /*-----------------------------------------------------------------*/
9796 static void genAddrOf (iCode *ic)
9797 {
9798         operand *right, *result, *left;
9799         int size, offset ;
9800         
9801         FENTRY;
9802         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9803         
9804         
9805         //aopOp(IC_RESULT(ic),ic,FALSE);
9806         
9807         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9808         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9809         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9810         
9811         DEBUGpic14_AopType(__LINE__,left,right,result);
9812         assert (IS_SYMOP (left));
9813         
9814         /* sanity check: generic pointers to code space are not yet supported,
9815          * pionters to codespace must not be assigned addresses of __data values. */
9816  #if 0
9817         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9818         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)));
9819         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)));
9820         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)));
9821         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)));
9822 #endif
9823
9824         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9825           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9826                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9827                 OP_SYMBOL(left)->name);
9828         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9829           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9830                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9831                 OP_SYMBOL(left)->name);
9832         }
9833         
9834         size = AOP_SIZE(IC_RESULT(ic));
9835         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9836                 /* strip tag */
9837                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9838         }
9839         offset = 0;
9840         
9841         while (size--) {
9842                 /* fixing bug #863624, reported from (errolv) */
9843                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9844                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9845                 
9846 #if 0
9847                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9848                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9849 #endif
9850                 offset++;
9851         }
9852
9853         if (IS_GENPTR(OP_SYM_TYPE(result)))
9854         {
9855                 /* provide correct tag */
9856                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9857                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9858                 movwf (AOP(result), 2);
9859         }
9860         
9861         freeAsmop(left,NULL,ic,FALSE);
9862         freeAsmop(result,NULL,ic,TRUE);
9863         
9864 }
9865
9866 #if 0
9867 /*-----------------------------------------------------------------*/
9868 /* genFarFarAssign - assignment when both are in far space         */
9869 /*-----------------------------------------------------------------*/
9870 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9871 {
9872         int size = AOP_SIZE(right);
9873         int offset = 0;
9874         char *l ;
9875         /* first push the right side on to the stack */
9876         while (size--) {
9877                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9878                 MOVA(l);
9879                 pic14_emitcode ("push","acc");
9880         }
9881         
9882         freeAsmop(right,NULL,ic,FALSE);
9883         /* now assign DPTR to result */
9884         aopOp(result,ic,FALSE);
9885         size = AOP_SIZE(result);
9886         while (size--) {
9887                 pic14_emitcode ("pop","acc");
9888                 aopPut(AOP(result),"a",--offset);
9889         }
9890         freeAsmop(result,NULL,ic,FALSE);
9891         
9892 }
9893 #endif
9894
9895 /*-----------------------------------------------------------------*/
9896 /* genAssign - generate code for assignment                        */
9897 /*-----------------------------------------------------------------*/
9898 static void genAssign (iCode *ic)
9899 {
9900         operand *result, *right;
9901         int size, offset,know_W;
9902         unsigned long lit = 0L;
9903         
9904         result = IC_RESULT(ic);
9905         right  = IC_RIGHT(ic) ;
9906         
9907         FENTRY;
9908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9909         
9910         /* if they are the same */
9911         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9912                 return ;
9913         
9914         aopOp(right,ic,FALSE);
9915         aopOp(result,ic,TRUE);
9916         
9917         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9918         
9919         /* if they are the same registers */
9920         if (pic14_sameRegs(AOP(right),AOP(result)))
9921                 goto release;
9922
9923         /* special case: assign from __code */
9924         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9925                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9926                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9927                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9928                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9929         {
9930           emitpComment ("genAssign from CODESPACE");
9931           genConstPointerGet (right, result, ic);
9932           goto release;
9933         }
9934         
9935         /* just for symmetry reasons... */
9936         if (!IS_ITEMP(result)
9937                 && IS_SYMOP (result)
9938                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9939         {
9940           assert ( !"cannot write to CODESPACE" );
9941         }
9942
9943         /* if the result is a bit */
9944         if (AOP_TYPE(result) == AOP_CRY) {
9945                 
9946         /* if the right size is a literal then
9947                 we know what the value is */
9948                 if (AOP_TYPE(right) == AOP_LIT) {
9949                         
9950                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9951                                 popGet(AOP(result),0));
9952                         
9953                         if (((int) operandLitValue(right))) 
9954                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9955                                 AOP(result)->aopu.aop_dir,
9956                                 AOP(result)->aopu.aop_dir);
9957                         else
9958                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9959                                 AOP(result)->aopu.aop_dir,
9960                                 AOP(result)->aopu.aop_dir);
9961                         goto release;
9962                 }
9963                 
9964                 /* the right is also a bit variable */
9965                 if (AOP_TYPE(right) == AOP_CRY) {
9966                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9967                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9968                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9969                         
9970                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9971                                 AOP(result)->aopu.aop_dir,
9972                                 AOP(result)->aopu.aop_dir);
9973                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9974                                 AOP(right)->aopu.aop_dir,
9975                                 AOP(right)->aopu.aop_dir);
9976                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9977                                 AOP(result)->aopu.aop_dir,
9978                                 AOP(result)->aopu.aop_dir);
9979                         goto release ;
9980                 }
9981                 
9982                 /* we need to or */
9983                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9984                 pic14_toBoolean(right);
9985                 emitSKPZ;
9986                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9987                 //aopPut(AOP(result),"a",0);
9988                 goto release ;
9989         }
9990         
9991         /* bit variables done */
9992         /* general case */
9993         size = AOP_SIZE(result);
9994         offset = 0 ;
9995         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9996                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9997                 if(aopIdx(AOP(result),0) == 4) {
9998                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9999                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10000                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10001                         goto release;
10002                 } else
10003                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10004         }
10005         
10006         know_W=-1;
10007         while (size--) {
10008         
10009                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10010                 if(AOP_TYPE(right) == AOP_LIT) {
10011                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10012                         if(lit&0xff) {
10013                                 if(know_W != (int)(lit&0xff))
10014                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10015                                 know_W = lit&0xff;
10016                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10017                         } else
10018                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10019                         
10020                 } else if (AOP_TYPE(right) == AOP_CRY) {
10021                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10022                         if(offset == 0) {
10023                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10024                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10025                         }
10026                 } else {
10027                         mov2w_op (right, offset);
10028                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10029                 }
10030                 
10031                 offset++;
10032         }
10033         
10034         
10035 release:
10036         freeAsmop (right,NULL,ic,FALSE);
10037         freeAsmop (result,NULL,ic,TRUE);
10038 }   
10039
10040 /*-----------------------------------------------------------------*/
10041 /* genJumpTab - genrates code for jump table                       */
10042 /*-----------------------------------------------------------------*/
10043 static void genJumpTab (iCode *ic)
10044 {
10045         symbol *jtab;
10046         char *l;
10047         
10048         FENTRY;
10049         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10050         
10051         aopOp(IC_JTCOND(ic),ic,FALSE);
10052         /* get the condition into accumulator */
10053         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10054         MOVA(l);
10055         /* multiply by three */
10056         pic14_emitcode("add","a,acc");
10057         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10058         
10059         jtab = newiTempLabel(NULL);
10060         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10061         pic14_emitcode("jmp","@a+dptr");
10062         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10063         
10064         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10065         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10066         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10067         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10068         emitSKPNC;
10069         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10070         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10071         emitpLabel(jtab->key);
10072         
10073         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10074         
10075         /* now generate the jump labels */
10076         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10077         jtab = setNextItem(IC_JTLABELS(ic))) {
10078                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10079                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10080                 
10081         }
10082         
10083 }
10084
10085 /*-----------------------------------------------------------------*/
10086 /* genMixedOperation - gen code for operators between mixed types  */
10087 /*-----------------------------------------------------------------*/
10088 /*
10089 TSD - Written for the PIC port - but this unfortunately is buggy.
10090 This routine is good in that it is able to efficiently promote 
10091 types to different (larger) sizes. Unfortunately, the temporary
10092 variables that are optimized out by this routine are sometimes
10093 used in other places. So until I know how to really parse the 
10094 iCode tree, I'm going to not be using this routine :(.
10095 */
10096 static int genMixedOperation (iCode *ic)
10097 {
10098         FENTRY;
10099 #if 0
10100         operand *result = IC_RESULT(ic);
10101         sym_link *ctype = operandType(IC_LEFT(ic));
10102         operand *right = IC_RIGHT(ic);
10103         int ret = 0;
10104         int big,small;
10105         int offset;
10106         
10107         iCode *nextic;
10108         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10109         
10110         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10111         
10112         nextic = ic->next;
10113         if(!nextic)
10114                 return 0;
10115         
10116         nextright = IC_RIGHT(nextic);
10117         nextleft  = IC_LEFT(nextic);
10118         nextresult = IC_RESULT(nextic);
10119         
10120         aopOp(right,ic,FALSE);
10121         aopOp(result,ic,FALSE);
10122         aopOp(nextright,  nextic, FALSE);
10123         aopOp(nextleft,   nextic, FALSE);
10124         aopOp(nextresult, nextic, FALSE);
10125         
10126         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10127                 
10128                 operand *t = right;
10129                 right = nextright;
10130                 nextright = t; 
10131                 
10132                 pic14_emitcode(";remove right +","");
10133                 
10134         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10135         /*
10136         operand *t = right;
10137         right = nextleft;
10138         nextleft = t; 
10139                 */
10140                 pic14_emitcode(";remove left +","");
10141         } else
10142                 return 0;
10143         
10144         big = AOP_SIZE(nextleft);
10145         small = AOP_SIZE(nextright);
10146         
10147         switch(nextic->op) {
10148                 
10149         case '+':
10150                 pic14_emitcode(";optimize a +","");
10151                 /* if unsigned or not an integral type */
10152                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10153                         pic14_emitcode(";add a bit to something","");
10154                 } else {
10155                         
10156                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10157                         
10158                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10159                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10160                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10161                         } else
10162                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10163                         
10164                         offset = 0;
10165                         while(--big) {
10166                                 
10167                                 offset++;
10168                                 
10169                                 if(--small) {
10170                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10171                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10172                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10173                                         }
10174                                         
10175                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10176                                         emitSKPNC;
10177                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10178                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10179                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10180                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10181                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10182                                         
10183                                 } else {
10184                                         pic14_emitcode("rlf","known_zero,w");
10185                                         
10186                                         /*
10187                                         if right is signed
10188                                         btfsc  right,7
10189                                         addlw ff
10190                                         */
10191                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10192                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10193                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10194                                         } else {
10195                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10196                                         }
10197                                 }
10198                         }
10199                         ret = 1;
10200                 }
10201         }
10202         ret = 1;
10203         
10204 release:
10205         freeAsmop(right,NULL,ic,TRUE);
10206         freeAsmop(result,NULL,ic,TRUE);
10207         freeAsmop(nextright,NULL,ic,TRUE);
10208         freeAsmop(nextleft,NULL,ic,TRUE);
10209         if(ret)
10210                 nextic->generated = 1;
10211         
10212         return ret;
10213 #else
10214         return 0;
10215 #endif
10216 }
10217 /*-----------------------------------------------------------------*/
10218 /* genCast - gen code for casting                                  */
10219 /*-----------------------------------------------------------------*/
10220 static void genCast (iCode *ic)
10221 {
10222         operand *result = IC_RESULT(ic);
10223         sym_link *restype = operandType(result);
10224         sym_link *rtype = operandType(IC_RIGHT(ic));
10225         operand *right = IC_RIGHT(ic);
10226         int size, offset ;
10227         
10228         FENTRY;
10229         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10230         /* if they are equivalent then do nothing */
10231         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10232                 return ;
10233         
10234         aopOp(right,ic,FALSE) ;
10235         aopOp(result,ic,FALSE);
10236         
10237         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10238         
10239         /* if the result is a bit */
10240         if (AOP_TYPE(result) == AOP_CRY) {
10241                 assert(!"assigning to bit variables is not supported");
10242         }
10243         
10244         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10245                 int offset = 1;
10246                 size = AOP_SIZE(result);
10247                 
10248                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10249                 
10250                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10251                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10252                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10253                 
10254                 while (size--)
10255                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10256                 
10257                 goto release;
10258         }
10259         
10260         if (IS_PTR(restype))
10261         {
10262           operand *result = IC_RESULT(ic);
10263           //operand *left = IC_LEFT(ic);
10264           operand *right = IC_RIGHT(ic);
10265           int tag = 0xff;
10266           
10267           /* copy common part */
10268           int max, size = AOP_SIZE(result);
10269           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10270           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10271
10272           /* warn if we discard generic opinter tag */
10273           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10274           {
10275             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10276           } // if
10277
10278           max = size;
10279           while (size--)
10280           {
10281             mov2w_op (right, size);
10282             movwf (AOP(result), size);
10283           } // while
10284
10285           /* upcast into generic pointer type? */
10286           if (IS_GENPTR(restype)
10287                 && (size < AOP_SIZE(result))
10288                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10289           {
10290             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10291             if (IS_PTR(rtype))
10292             {
10293               switch (DCL_TYPE(rtype))
10294               {
10295               case POINTER:     /* __data */
10296               case FPOINTER:    /* __data */
10297                 assert (AOP_SIZE(right) == 2);
10298                 tag = GPTRTAG_DATA;
10299                 break;
10300
10301               case CPOINTER:    /* __code */
10302                 assert (AOP_SIZE(right) == 2);
10303                 tag = GPTRTAG_CODE;
10304                 break;
10305                 
10306               case GPOINTER:    /* unknown destination, __data or __code */
10307                 /* assume __data space (address of immediate) */
10308                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10309                 if (AOP(right)->code)
10310                   tag = GPTRTAG_CODE;
10311                 else
10312                   tag = GPTRTAG_DATA;
10313                 break;
10314                 
10315               default:
10316                 assert (!"unhandled pointer type");
10317               } // switch
10318             } else {
10319               /* convert other values into pointers to __data space */
10320               tag = GPTRTAG_DATA;
10321             }
10322
10323             assert (AOP_SIZE(result) == 3);
10324             if (tag == 0) {
10325               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10326             } else {
10327               emitpcode(POC_MOVLW, popGetLit(tag));
10328               movwf(AOP(result), 2);
10329             }
10330           } else {
10331             addSign(result, max, 0);
10332           } // if
10333           goto release;
10334         }
10335         
10336         /* if they are the same size : or less */
10337         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10338                 
10339                 /* if they are in the same place */
10340                 if (pic14_sameRegs(AOP(right),AOP(result)))
10341                         goto release;
10342                 
10343                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10344                 if (IS_PTR_CONST(rtype))
10345                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10346                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10347                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10348                 
10349                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10350                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10351                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10352                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10353                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10354                         if(AOP_SIZE(result) <2)
10355                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10356                         
10357                 } else {
10358                         
10359                         /* if they in different places then copy */
10360                         size = AOP_SIZE(result);
10361                         offset = 0 ;
10362                         while (size--) {
10363                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10364                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10365                                 
10366                                 //aopPut(AOP(result),
10367                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10368                                 // offset);
10369                                 
10370                                 offset++;
10371                         }
10372                 }
10373                 goto release;
10374         }
10375         
10376         /* so we now know that the size of destination is greater
10377         than the size of the source.
10378         Now, if the next iCode is an operator then we might be
10379         able to optimize the operation without performing a cast.
10380         */
10381         if(0 && genMixedOperation(ic)) {
10382                 /* XXX: cannot optimize: must copy regs! */
10383                 goto release;
10384         }
10385         
10386         /* we move to result for the size of source */
10387         size = AOP_SIZE(right);
10388         offset = 0 ;
10389         while (size--) {
10390                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10391                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10392                 offset++;
10393         }
10394
10395         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10396
10397 release:
10398         freeAsmop(right,NULL,ic,TRUE);
10399         freeAsmop(result,NULL,ic,TRUE);
10400         
10401 }
10402
10403 /*-----------------------------------------------------------------*/
10404 /* genDjnz - generate decrement & jump if not zero instrucion      */
10405 /*-----------------------------------------------------------------*/
10406 static int genDjnz (iCode *ic, iCode *ifx)
10407 {
10408         symbol *lbl, *lbl1;
10409         FENTRY;
10410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10411         
10412         if (!ifx)
10413                 return 0;
10414         
10415                 /* if the if condition has a false label
10416         then we cannot save */
10417         if (IC_FALSE(ifx))
10418                 return 0;
10419         
10420                 /* if the minus is not of the form 
10421         a = a - 1 */
10422         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10423                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10424                 return 0;
10425         
10426         if (operandLitValue(IC_RIGHT(ic)) != 1)
10427                 return 0;
10428         
10429                 /* if the size of this greater than one then no
10430         saving */
10431         if (getSize(operandType(IC_RESULT(ic))) > 1)
10432                 return 0;
10433         
10434         /* otherwise we can save BIG */
10435         lbl = newiTempLabel(NULL);
10436         lbl1= newiTempLabel(NULL);
10437         
10438         aopOp(IC_RESULT(ic),ic,FALSE);
10439         
10440         if (IS_AOP_PREG(IC_RESULT(ic))) {
10441                 pic14_emitcode("dec","%s",
10442                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10443                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10444                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10445         } else {  
10446                 
10447                 
10448                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10449                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10450                 
10451                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10452                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10453                 
10454         }
10455         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10456         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10457         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10458         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10459         
10460         
10461         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10462         ifx->generated = 1;
10463         return 1;
10464 }
10465
10466 /*-----------------------------------------------------------------*/
10467 /* genReceive - generate code for a receive iCode                  */
10468 /*-----------------------------------------------------------------*/
10469 static void genReceive (iCode *ic)
10470 {
10471         FENTRY;
10472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10473         
10474         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10475                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10476                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10477                 
10478                 int size = getSize(operandType(IC_RESULT(ic)));
10479                 int offset =  fReturnSizePic - size;
10480                 while (size--) {
10481                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10482                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10483                         offset++;
10484                 }
10485                 aopOp(IC_RESULT(ic),ic,FALSE);
10486                 size = AOP_SIZE(IC_RESULT(ic));
10487                 offset = 0;
10488                 while (size--) {
10489                         pic14_emitcode ("pop","acc");
10490                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10491                 }
10492                 
10493         } else {
10494                 _G.accInUse++;
10495                 aopOp(IC_RESULT(ic),ic,FALSE);
10496                 _G.accInUse--;
10497                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10498                 assignResultValue(IC_RESULT(ic));
10499         }
10500         
10501         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10502 }
10503
10504 /*-----------------------------------------------------------------*/
10505 /* genDummyRead - generate code for dummy read of volatiles        */
10506 /*-----------------------------------------------------------------*/
10507 static void
10508 genDummyRead (iCode * ic)
10509 {
10510         FENTRY;
10511         pic14_emitcode ("; genDummyRead","");
10512         pic14_emitcode ("; not implemented","");
10513         
10514         ic = ic;
10515 }
10516
10517 /*-----------------------------------------------------------------*/
10518 /* genpic14Code - generate code for pic14 based controllers        */
10519 /*-----------------------------------------------------------------*/
10520 /*
10521 * At this point, ralloc.c has gone through the iCode and attempted
10522 * to optimize in a way suitable for a PIC. Now we've got to generate
10523 * PIC instructions that correspond to the iCode.
10524 *
10525 * Once the instructions are generated, we'll pass through both the
10526 * peep hole optimizer and the pCode optimizer.
10527 *-----------------------------------------------------------------*/
10528
10529 void genpic14Code (iCode *lic)
10530 {
10531         iCode *ic;
10532         int cln = 0;
10533         const char *cline;
10534         
10535         FENTRY;
10536         lineHead = lineCurr = NULL;
10537         
10538         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10539         addpBlock(pb);
10540         
10541         /* if debug information required */
10542         if (options.debug && currFunc) { 
10543                 if (currFunc) {
10544                         debugFile->writeFunction (currFunc, lic);
10545                 }
10546         }
10547         
10548         
10549         for (ic = lic ; ic ; ic = ic->next ) {
10550                 
10551                 //DEBUGpic14_emitcode(";ic","");
10552                 //fprintf (stderr, "in ic loop\n");
10553                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10554                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10555                 
10556                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10557                   cln = ic->lineno;
10558                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10559                   cline = printCLine (ic->filename, ic->lineno);
10560                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10561                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10562                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10563                 }
10564                 
10565                 if (options.iCodeInAsm) {
10566                   char *iLine = printILine(ic);
10567                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10568                   dbuf_free(iLine);
10569                 }
10570                 /* if the result is marked as
10571                 spilt and rematerializable or code for
10572                 this has already been generated then
10573                 do nothing */
10574                 if (resultRemat(ic) || ic->generated ) 
10575                         continue ;
10576                 
10577                 /* depending on the operation */
10578                 switch (ic->op) {
10579                 case '!' :
10580                         genNot(ic);
10581                         break;
10582                         
10583                 case '~' :
10584                         genCpl(ic);
10585                         break;
10586                         
10587                 case UNARYMINUS:
10588                         genUminus (ic);
10589                         break;
10590                         
10591                 case IPUSH:
10592                         genIpush (ic);
10593                         break;
10594                         
10595                 case IPOP:
10596                         /* IPOP happens only when trying to restore a 
10597                         spilt live range, if there is an ifx statement
10598                         following this pop then the if statement might
10599                         be using some of the registers being popped which
10600                         would destory the contents of the register so
10601                         we need to check for this condition and handle it */
10602                         if (ic->next            && 
10603                                 ic->next->op == IFX &&
10604                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10605                                 genIfx (ic->next,ic);
10606                         else
10607                                 genIpop (ic);
10608                         break; 
10609                         
10610                 case CALL:
10611                         genCall (ic);
10612                         break;
10613                         
10614                 case PCALL:
10615                         genPcall (ic);
10616                         break;
10617                         
10618                 case FUNCTION:
10619                         genFunction (ic);
10620                         break;
10621                         
10622                 case ENDFUNCTION:
10623                         genEndFunction (ic);
10624                         break;
10625                         
10626                 case RETURN:
10627                         genRet (ic);
10628                         break;
10629                         
10630                 case LABEL:
10631                         genLabel (ic);
10632                         break;
10633                         
10634                 case GOTO:
10635                         genGoto (ic);
10636                         break;
10637                         
10638                 case '+' :
10639                         genPlus (ic) ;
10640                         break;
10641                         
10642                 case '-' :
10643                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10644                                 genMinus (ic);
10645                         break;
10646                         
10647                 case '*' :
10648                         genMult (ic);
10649                         break;
10650                         
10651                 case '/' :
10652                         genDiv (ic) ;
10653                         break;
10654                         
10655                 case '%' :
10656                         genMod (ic);
10657                         break;
10658                         
10659                 case '>' :
10660                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10661                         break;
10662                         
10663                 case '<' :
10664                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10665                         break;
10666                         
10667                 case LE_OP:
10668                 case GE_OP:
10669                 case NE_OP:
10670                         
10671                         /* note these two are xlated by algebraic equivalence
10672                         during parsing SDCC.y */
10673                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10674                                 "got '>=' or '<=' shouldn't have come here");
10675                         break;  
10676                         
10677                 case EQ_OP:
10678                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10679                         break;      
10680                         
10681                 case AND_OP:
10682                         genAndOp (ic);
10683                         break;
10684                         
10685                 case OR_OP:
10686                         genOrOp (ic);
10687                         break;
10688                         
10689                 case '^' :
10690                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10691                         break;
10692                         
10693                 case '|' :
10694                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10695                         break;
10696                         
10697                 case BITWISEAND:
10698                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10699                         break;
10700                         
10701                 case INLINEASM:
10702                         genInline (ic);
10703                         break;
10704                         
10705                 case RRC:
10706                         genRRC (ic);
10707                         break;
10708                         
10709                 case RLC:
10710                         genRLC (ic);
10711                         break;
10712                         
10713                 case GETHBIT:
10714                         genGetHbit (ic);
10715                         break;
10716                         
10717                 case LEFT_OP:
10718                         genLeftShift (ic);
10719                         break;
10720                         
10721                 case RIGHT_OP:
10722                         genRightShift (ic);
10723                         break;
10724                         
10725                 case GET_VALUE_AT_ADDRESS:
10726                         genPointerGet(ic);
10727                         break;
10728                         
10729                 case '=' :
10730                         if (POINTER_SET(ic))
10731                                 genPointerSet(ic);
10732                         else
10733                                 genAssign(ic);
10734                         break;
10735                         
10736                 case IFX:
10737                         genIfx (ic,NULL);
10738                         break;
10739                         
10740                 case ADDRESS_OF:
10741                         genAddrOf (ic);
10742                         break;
10743                         
10744                 case JUMPTABLE:
10745                         genJumpTab (ic);
10746                         break;
10747                         
10748                 case CAST:
10749                         genCast (ic);
10750                         break;
10751                         
10752                 case RECEIVE:
10753                         genReceive(ic);
10754                         break;
10755                         
10756                 case SEND:
10757                         addSet(&_G.sendSet,ic);
10758                         break;
10759                         
10760                 case DUMMY_READ_VOLATILE:
10761                         genDummyRead (ic);
10762                         break;
10763                         
10764                 default :
10765                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10766                         ic = ic;
10767                         break;
10768                 }
10769         }
10770
10771         
10772         /* now we are ready to call the
10773         peep hole optimizer */
10774         if (!options.nopeep) {
10775                 peepHole (&lineHead);
10776         }
10777         /* now do the actual printing */
10778         printLine (lineHead,codeOutBuf);
10779         
10780 #ifdef PCODE_DEBUG
10781         DFPRINTF((stderr,"printing pBlock\n\n"));
10782         printpBlock(stdout,pb);
10783 #endif
10784         
10785         return;
10786 }
10787
10788 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10789  * (meaning: representing its own address) or not (referencing its contents).
10790  * This can only be decided based on the operand's type. */
10791 int
10792 aop_isLitLike (asmop *aop)
10793 {
10794   assert (aop);
10795   if (aop->type == AOP_LIT) return 1;
10796 if (aop->type == AOP_IMMD) return 1;
10797   if ((aop->type == AOP_PCODE) &&
10798                 ((aop->aopu.pcop->type == PO_LITERAL)))
10799   {
10800     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10801      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10802     return 1;
10803   }
10804   return 0;
10805 }
10806
10807 int
10808 op_isLitLike (operand *op)
10809 {
10810   assert (op);
10811   if (aop_isLitLike (AOP(op))) return 1;
10812   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10813   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10814   return 0;
10815 }
10816