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