* src/mcs51/gen.c, src/avr/gen.c, src/pic/gen.c, src/z80/gen.c,
[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   bool inComment = FALSE;
6217
6218   FENTRY;
6219   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6220
6221   _G.inLine += (!options.asmpeep);
6222
6223   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6224
6225   while (*bp)
6226     {
6227       switch (*bp)
6228         {
6229         case ';':
6230           inComment = TRUE;
6231           ++bp;
6232           break;
6233
6234         case '\n':
6235           inComment = FALSE;
6236           *bp++ = '\0';
6237           if (*bp1)
6238             addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6239           bp1 = bp;
6240           break;
6241
6242         default:
6243           /* Add \n for labels, not dirs such as c:\mydir */
6244           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6245             {
6246               ++bp;
6247               *bp = '\0';
6248               ++bp;
6249               /* print label, use this special format with NULL directive
6250                * to denote that the argument should not be indented with tab */
6251               addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6252               bp1 = bp;
6253             }
6254           else
6255             ++bp;
6256           break;
6257         }
6258     }
6259   if ((bp1 != bp) && *bp1)
6260     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6261
6262   Safe_free (buffer);
6263
6264   _G.inLine -= (!options.asmpeep);
6265 }
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genRRC - rotate right with carry                                */
6269 /*-----------------------------------------------------------------*/
6270 static void genRRC (iCode *ic)
6271 {
6272         operand *left , *result ;
6273         int size, offset = 0, same;
6274         
6275         FENTRY;
6276         /* rotate right with carry */
6277         left = IC_LEFT(ic);
6278         result=IC_RESULT(ic);
6279         aopOp (left,ic,FALSE);
6280         aopOp (result,ic,FALSE);
6281         
6282         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6283         
6284         same = pic14_sameRegs(AOP(result),AOP(left));
6285         
6286         size = AOP_SIZE(result);    
6287         
6288         /* get the lsb and put it into the carry */
6289         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6290         
6291         offset = 0 ;
6292         
6293         while(size--) {
6294                 
6295                 if(same) {
6296                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6297                 } else {
6298                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6299                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6300                 }
6301                 
6302                 offset++;
6303         }
6304         
6305         freeAsmop(left,NULL,ic,TRUE);
6306         freeAsmop(result,NULL,ic,TRUE);
6307 }
6308
6309 /*-----------------------------------------------------------------*/
6310 /* genRLC - generate code for rotate left with carry               */
6311 /*-----------------------------------------------------------------*/
6312 static void genRLC (iCode *ic)
6313 {    
6314         operand *left , *result ;
6315         int size, offset = 0;
6316         int same;
6317         
6318         FENTRY;
6319         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6320         /* rotate right with carry */
6321         left = IC_LEFT(ic);
6322         result=IC_RESULT(ic);
6323         aopOp (left,ic,FALSE);
6324         aopOp (result,ic,FALSE);
6325         
6326         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6327         
6328         same = pic14_sameRegs(AOP(result),AOP(left));
6329         
6330         /* move it to the result */
6331         size = AOP_SIZE(result);    
6332         
6333         /* get the msb and put it into the carry */
6334         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6335         
6336         offset = 0 ;
6337         
6338         while(size--) {
6339                 
6340                 if(same) {
6341                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6342                 } else {
6343                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6344                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6345                 }
6346                 
6347                 offset++;
6348         }
6349         
6350         
6351         freeAsmop(left,NULL,ic,TRUE);
6352         freeAsmop(result,NULL,ic,TRUE);
6353 }
6354
6355 /*-----------------------------------------------------------------*/
6356 /* genGetHbit - generates code get highest order bit               */
6357 /*-----------------------------------------------------------------*/
6358 static void genGetHbit (iCode *ic)
6359 {
6360         operand *left, *result;
6361         left = IC_LEFT(ic);
6362         result=IC_RESULT(ic);
6363         aopOp (left,ic,FALSE);
6364         aopOp (result,ic,FALSE);
6365         
6366         FENTRY;
6367         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6368         /* get the highest order byte into a */
6369         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6370         if(AOP_TYPE(result) == AOP_CRY){
6371                 pic14_emitcode("rlc","a");
6372                 pic14_outBitC(result);
6373         }
6374         else{
6375                 pic14_emitcode("rl","a");
6376                 pic14_emitcode("anl","a,#0x01");
6377                 pic14_outAcc(result);
6378         }
6379         
6380         
6381         freeAsmop(left,NULL,ic,TRUE);
6382         freeAsmop(result,NULL,ic,TRUE);
6383 }
6384
6385 /*-----------------------------------------------------------------*/
6386 /* AccLsh - shift left accumulator by known count                  */
6387 /* MARK: pic14 always rotates through CARRY!                       */
6388 /*-----------------------------------------------------------------*/
6389 static void AccLsh (pCodeOp *pcop,int shCount)
6390 {
6391         FENTRY;
6392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6393         shCount &= 0x0007;              // shCount : 0..7
6394         switch(shCount){
6395         case 0 :
6396                 return;
6397                 break;
6398         case 1 :
6399                 emitCLRC;
6400                 emitpcode(POC_RLF,pcop);
6401                 return;
6402                 break;
6403         case 2 :
6404                 emitpcode(POC_RLF,pcop);
6405                 emitpcode(POC_RLF,pcop);
6406                 break;
6407         case 3 :
6408                 emitpcode(POC_RLF,pcop);
6409                 emitpcode(POC_RLF,pcop);
6410                 emitpcode(POC_RLF,pcop);
6411                 break;
6412         case 4 :
6413                 emitpcode(POC_SWAPF,pcop);
6414                 break;
6415         case 5 :
6416                 emitpcode(POC_SWAPF,pcop);
6417                 emitpcode(POC_RLF,pcop);
6418                 break;
6419         case 6 :
6420                 emitpcode(POC_SWAPF,pcop);
6421                 emitpcode(POC_RLF,pcop);
6422                 emitpcode(POC_RLF,pcop);
6423                 break;
6424         case 7 :
6425                 emitpcode(POC_RRFW,pcop);
6426                 emitpcode(POC_RRF,pcop);
6427                 break;
6428         }
6429         /* clear invalid bits */
6430         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6431         emitpcode(POC_ANDWF, pcop);
6432 }
6433
6434 /*-----------------------------------------------------------------*/
6435 /* AccRsh - shift right accumulator by known count                 */
6436 /* MARK: pic14 always rotates through CARRY!                       */
6437 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6438 /*            1: mask out invalid bits (zero-extend)               */
6439 /*            2: sign-extend result (pretty slow)                  */
6440 /*-----------------------------------------------------------------*/
6441 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6442 {
6443         FENTRY;
6444         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6445         shCount &= 0x0007;              // shCount : 0..7
6446         switch(shCount){
6447         case 0 :
6448                 return;
6449                 break;
6450         case 1 :
6451                 /* load sign if needed */
6452                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6453                 else if (mask_mode == 1) emitCLRC;
6454                 emitpcode(POC_RRF,pcop);
6455                 return;
6456                 break;
6457         case 2 :
6458                 /* load sign if needed */
6459                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6460                 emitpcode(POC_RRF,pcop);
6461                 /* load sign if needed */
6462                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6463                 emitpcode(POC_RRF,pcop);
6464                 if (mask_mode == 2) return;
6465                 break;
6466         case 3 :
6467                 /* load sign if needed */
6468                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6469                 emitpcode(POC_RRF,pcop);
6470                 /* load sign if needed */
6471                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6472                 emitpcode(POC_RRF,pcop);
6473                 /* load sign if needed */
6474                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6475                 emitpcode(POC_RRF,pcop);
6476                 if (mask_mode == 2) return;
6477                 break;
6478         case 4 :
6479                 emitpcode(POC_SWAPF,pcop);
6480                 break;
6481         case 5 :
6482                 emitpcode(POC_SWAPF,pcop);
6483                 emitpcode(POC_RRF,pcop);
6484                 break;
6485         case 6 :
6486                 emitpcode(POC_SWAPF,pcop);
6487                 emitpcode(POC_RRF,pcop);
6488                 emitpcode(POC_RRF,pcop);
6489                 break;
6490         case 7 :
6491                 if (mask_mode == 2)
6492                 {
6493                         /* load sign */
6494                         emitpcode(POC_RLFW,pcop);
6495                         emitpcode(POC_CLRF,pcop);
6496                         emitSKPNC;
6497                         emitpcode(POC_COMF,pcop);
6498                         return;
6499                 } else {
6500                         emitpcode(POC_RLFW,pcop);
6501                         emitpcode(POC_RLF,pcop);
6502                 }
6503                 break;
6504         }
6505
6506         if (mask_mode == 0)
6507         {
6508                 /* leave invalid bits undefined */
6509                 return;
6510         }
6511         
6512         /* clear invalid bits -- zero-extend */
6513         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6514         emitpcode(POC_ANDWF, pcop);
6515
6516         if (mask_mode == 2) {
6517           /* sign-extend */
6518           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6519           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6520           emitpcode(POC_IORWF, pcop);
6521         }
6522 }
6523
6524 #if 0
6525 /*-----------------------------------------------------------------*/
6526 /* AccSRsh - signed right shift accumulator by known count                 */
6527 /*-----------------------------------------------------------------*/
6528 static void AccSRsh (int shCount)
6529 {
6530         symbol *tlbl ;
6531         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6532         if(shCount != 0){
6533                 if(shCount == 1){
6534                         pic14_emitcode("mov","c,acc.7");
6535                         pic14_emitcode("rrc","a");
6536                 } else if(shCount == 2){
6537                         pic14_emitcode("mov","c,acc.7");
6538                         pic14_emitcode("rrc","a");
6539                         pic14_emitcode("mov","c,acc.7");
6540                         pic14_emitcode("rrc","a");
6541                 } else {
6542                         tlbl = newiTempLabel(NULL);
6543                         /* rotate right accumulator */
6544                         AccRol(8 - shCount);
6545                         /* and kill the higher order bits */
6546                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6547                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6548                         pic14_emitcode("orl","a,#0x%02x",
6549                                 (unsigned char)~SRMask[shCount]);
6550                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6551                 }
6552         }
6553 }
6554
6555 /*-----------------------------------------------------------------*/
6556 /* shiftR1Left2Result - shift right one byte from left to result   */
6557 /*-----------------------------------------------------------------*/
6558 static void shiftR1Left2ResultSigned (operand *left, int offl,
6559                                                                           operand *result, int offr,
6560                                                                           int shCount)
6561 {
6562         int same;
6563         
6564         FENTRY;
6565         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6566         
6567         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6568         
6569         switch(shCount) {
6570         case 1:
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                 
6579                 break;
6580         case 2:
6581                 
6582                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6583                 if(same) 
6584                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6585                 else {
6586                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6587                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6588                 }
6589                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6590                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6591                 
6592                 break;
6593                 
6594         case 3:
6595                 if(same)
6596                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6597                 else {
6598                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6599                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6600                 }
6601                 
6602                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6603                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6604                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6605                 
6606                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6607                 emitpcode(POC_IORLW, popGetLit(0xe0));
6608                 
6609                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6610                 break;
6611                 
6612         case 4:
6613                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6614                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6615                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6616                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6617                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6618                 break;
6619         case 5:
6620                 if(same) {
6621                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6622                 } else {
6623                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6624                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6625                 }
6626                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6627                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6628                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6629                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6630                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6631                 break;
6632                 
6633         case 6:
6634                 if(same) {
6635                         emitpcode(POC_MOVLW, popGetLit(0x00));
6636                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6637                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6638                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6639                         emitpcode(POC_IORLW, popGetLit(0x01));
6640                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6641                 } else {
6642                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6643                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6644                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6645                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6646                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6647                 }
6648                 break;
6649                 
6650         case 7:
6651                 if(same) {
6652                         emitpcode(POC_MOVLW, popGetLit(0x00));
6653                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6654                         emitpcode(POC_MOVLW, popGetLit(0xff));
6655                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6656                 } else {
6657                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6658                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6659                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6660                 }
6661                 
6662         default:
6663                 break;
6664         }
6665 }
6666
6667 /*-----------------------------------------------------------------*/
6668 /* shiftR1Left2Result - shift right one byte from left to result   */
6669 /*-----------------------------------------------------------------*/
6670 static void shiftR1Left2Result (operand *left, int offl,
6671                                                                 operand *result, int offr,
6672                                                                 int shCount, int sign)
6673 {
6674         int same;
6675         
6676         FENTRY;
6677         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6678         
6679         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6680         
6681         /* Copy the msb into the carry if signed. */
6682         if(sign) {
6683                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6684                 return;
6685         }
6686         
6687         
6688         
6689         switch(shCount) {
6690         case 1:
6691                 emitCLRC;
6692                 if(same) 
6693                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6694                 else {
6695                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6696                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6697                 }
6698                 break;
6699         case 2:
6700                 emitCLRC;
6701                 if(same) {
6702                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6703                 } else {
6704                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6705                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6706                 }
6707                 emitCLRC;
6708                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6709                 
6710                 break;
6711         case 3:
6712                 if(same)
6713                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6714                 else {
6715                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6716                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6717                 }
6718                 
6719                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6720                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6721                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6722                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723                 break;
6724                 
6725         case 4:
6726                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6727                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6728                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6729                 break;
6730                 
6731         case 5:
6732                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6733                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6734                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6735                 emitCLRC;
6736                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6737                 
6738                 break;
6739         case 6:
6740                 
6741                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6742                 emitpcode(POC_ANDLW, popGetLit(0x80));
6743                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6745                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6746                 break;
6747                 
6748         case 7:
6749                 
6750                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6751                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6752                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6753                 
6754                 break;
6755                 
6756         default:
6757                 break;
6758         }
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* shiftL1Left2Result - shift left one byte from left to result    */
6763 /*-----------------------------------------------------------------*/
6764 static void shiftL1Left2Result (operand *left, int offl,
6765                                                                 operand *result, int offr, int shCount)
6766 {
6767         int same;
6768         
6769         //    char *l;
6770         FENTRY;
6771         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6772         
6773         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6774         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6775         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6776         //    MOVA(l);
6777         /* shift left accumulator */
6778         //AccLsh(shCount); // don't comment out just yet...
6779         //    aopPut(AOP(result),"a",offr);
6780         
6781         switch(shCount) {
6782         case 1:
6783                 /* Shift left 1 bit position */
6784                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6785                 if(same) {
6786                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6787                 } else {
6788                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6789                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6790                 }
6791                 break;
6792         case 2:
6793                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6794                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6795                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6796                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6797                 break;
6798         case 3:
6799                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6800                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6801                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6802                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6803                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6804                 break;
6805         case 4:
6806                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6807                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6808                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6809                 break;
6810         case 5:
6811                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6812                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6813                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6814                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6815                 break;
6816         case 6:
6817                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6818                 emitpcode(POC_ANDLW, popGetLit(0x30));
6819                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6820                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6821                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6822                 break;
6823         case 7:
6824                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6825                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6826                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6827                 break;
6828                 
6829         default:
6830                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6831         }
6832         
6833 }
6834 #endif
6835
6836 /*-----------------------------------------------------------------*/
6837 /* movLeft2Result - move byte from left to result                  */
6838 /*-----------------------------------------------------------------*/
6839 static void movLeft2Result (operand *left, int offl,
6840                                                         operand *result, int offr)
6841 {
6842         char *l;
6843         FENTRY;
6844         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6845         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6846                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6847                 
6848                 if (*l == '@' && (IS_AOP_PREG(result))) {
6849                         pic14_emitcode("mov","a,%s",l);
6850                         aopPut(AOP(result),"a",offr);
6851                 } else {
6852                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6853                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6854                 }
6855         }
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* shiftLeft_Left2ResultLit - shift left by known count            */
6860 /*-----------------------------------------------------------------*/
6861
6862 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6863 {
6864         int size, same, offr, i;
6865
6866         size = AOP_SIZE(left);
6867         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6868         
6869         same = pic14_sameRegs (AOP(left), AOP(result));
6870         
6871         offr = shCount / 8;
6872         shCount = shCount & 0x07;
6873
6874         size -= offr;
6875
6876         switch (shCount)
6877         {
6878         case 0: /* takes 0 or 2N cycles (for offr==0) */
6879                 if (!same || offr) {
6880                         for (i=size-1; i >= 0; i--)
6881                                 movLeft2Result (left, i, result, offr + i);
6882                 } // if
6883                 break;
6884                 
6885         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6886                 if (same && offr) {
6887                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6888                         shiftLeft_Left2ResultLit (result, result, shCount);
6889                         return; /* prevent clearing result again */
6890                 } else {
6891                         emitCLRC;
6892                         for (i=0; i < size; i++) {
6893                                 if (same && !offr) {
6894                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6895                                 } else {
6896                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6897                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6898                                 } // if
6899                         } // for
6900                 } // if (offr)
6901                 break;
6902                 
6903         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6904                 /* works in-place/with offr as well */
6905                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6906                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6907                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6908
6909                 for (i = size - 2; i >= 0; i--)
6910                 {
6911                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6912                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6913                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6914                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6915                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6916                 } // for i
6917                 break;
6918                 
6919         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6920                 /* works in-place/with offr as well */
6921                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6922                 for (i = size-2; i >= 0; i--) {
6923                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6924                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6925                 } // for i
6926                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6927                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6928                 break;
6929         
6930         default:
6931                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6932                 shiftLeft_Left2ResultLit (result, result, 1);
6933                 return; /* prevent clearing result again */
6934                 break;
6935         } // switch
6936
6937         while (0 < offr--)
6938         {
6939                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6940         } // while
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRight_Left2ResultLit - shift right by known count          */
6945 /*-----------------------------------------------------------------*/
6946
6947 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6948 {
6949         int size, same, offr, i;
6950
6951         size = AOP_SIZE(left);
6952         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6953         
6954         same = pic14_sameRegs (AOP(left), AOP(result));
6955         
6956         offr = shCount / 8;
6957         shCount = shCount & 0x07;
6958
6959         size -= offr;
6960
6961         if (size)
6962         {
6963                 switch (shCount)
6964                 {
6965                 case 0: /* takes 0 or 2N cycles (for offr==0) */
6966                         if (!same || offr) {
6967                                 for (i=0; i < size; i++)
6968                                         movLeft2Result (left, i + offr, result, i);
6969                         } // if
6970                         break;
6971                         
6972                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6973                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6974                         if (same && offr) {
6975                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6976                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
6977                                 return; /* prevent sign-extending result again */
6978                         } else {
6979                                 emitCLRC;
6980                                 if (sign) {
6981                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6982                                         emitSETC;
6983                                 }
6984                                 for (i = size-1; i >= 0; i--) {
6985                                         if (same && !offr) {
6986                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
6987                                         } else {
6988                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6989                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6990                                         }
6991                                 } // for i
6992                         } // if (offr)
6993                         break;
6994                         
6995                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6996                         /* works in-place/with offr as well */
6997                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6998                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6999                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7000
7001                         for (i = 1; i < size; i++)
7002                         {
7003                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7004                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7005                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7006                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7007                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7008                         } // for i
7009
7010                         if (sign)
7011                         {
7012                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7013                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7014                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7015                         } // if
7016                         break;
7017                         
7018                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7019                         /* works in-place/with offr as well */
7020                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7021                         for (i = 0; i < size-1; i++) {
7022                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7023                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7024                         } // for i
7025                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7026                         if (!sign) {
7027                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7028                         } else {
7029                                 emitSKPNC;
7030                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7031                         }
7032                         break;
7033                 
7034                 default:
7035                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7036                         shiftRight_Left2ResultLit (result, result, 1, sign);
7037                         return; /* prevent sign extending result again */
7038                         break;
7039                 } // switch
7040         } // if
7041
7042         addSign (result, size, sign);
7043 }
7044
7045 #if 0
7046 /*-----------------------------------------------------------------*/
7047 /* shiftL2Left2Result - shift left two bytes from left to result   */
7048 /*-----------------------------------------------------------------*/
7049 static void shiftL2Left2Result (operand *left, int offl,
7050                                                                 operand *result, int offr, int shCount)
7051 {
7052         FENTRY;
7053         
7054         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7055         
7056         if(pic14_sameRegs(AOP(result), AOP(left))) {
7057                 switch(shCount) {
7058                 case 0:
7059                         break;
7060                 case 1:
7061                 case 2:
7062                 case 3:
7063                         
7064                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7065                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7066                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7067                         
7068                         while(--shCount) {
7069                                 emitCLRC;
7070                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7071                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7072                         }
7073                         
7074                         break;
7075                 case 4:
7076                 case 5:
7077                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7078                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7079                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7080                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7081                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7082                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7083                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7084                         if(shCount >=5) {
7085                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7086                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7087                         }
7088                         break;
7089                 case 6:
7090                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7091                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7092                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7093                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7094                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7095                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7096                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7097                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7098                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7099                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7100                         break;
7101                 case 7:
7102                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7103                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7104                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7105                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7106                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7107                 }
7108                 
7109         } else {
7110                 switch(shCount) {
7111                 case 0:
7112                         break;
7113                 case 1:
7114                 case 2:
7115                 case 3:
7116                 /* note, use a mov/add for the shift since the mov has a
7117                         chance of getting optimized out */
7118                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7119                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7120                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7121                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7122                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7123                         
7124                         while(--shCount) {
7125                                 emitCLRC;
7126                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7127                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7128                         }
7129                         break;
7130                         
7131                 case 4:
7132                 case 5:
7133                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7134                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7135                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7136                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7137                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7138                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7139                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7140                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7141                         
7142                         
7143                         if(shCount == 5) {
7144                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7145                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7146                         }
7147                         break;
7148                 case 6:
7149                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7150                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7151                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7152                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7153                         
7154                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7155                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7156                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7157                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7158                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7159                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7160                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7161                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7162                         break;
7163                 case 7:
7164                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7165                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7166                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7167                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7168                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7169                 }
7170         }
7171         
7172 }
7173
7174 /*-----------------------------------------------------------------*/
7175 /* shiftR2Left2Result - shift right two bytes from left to result  */
7176 /*-----------------------------------------------------------------*/
7177 static void shiftR2Left2Result (operand *left, int offl,
7178                                                                 operand *result, int offr,
7179                                                                 int shCount, int sign)
7180 {
7181         int same=0;
7182         
7183         FENTRY;
7184         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7185         same = pic14_sameRegs(AOP(result), AOP(left));
7186         
7187         if(same && ((offl + MSB16) == offr)){
7188                 same=1;
7189                 /* don't crash result[offr] */
7190                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7191                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7192         }
7193         /* else {
7194         movLeft2Result(left,offl, result, offr);
7195         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7196         }
7197         */
7198         /* a:x >> shCount (x = lsb(result))*/
7199         /*
7200         if(sign)
7201         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7202         else {
7203         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7204         */
7205         switch(shCount) {
7206         case 0:
7207                 break;
7208         case 1:
7209         case 2:
7210         case 3:
7211                 if(sign)
7212                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7213                 else
7214                         emitCLRC;
7215                 
7216                 if(same) {
7217                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7218                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7219                 } else {
7220                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7221                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7222                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7223                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7224                 }
7225                 
7226                 while(--shCount) {
7227                         if(sign)
7228                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7229                         else
7230                                 emitCLRC;
7231                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7232                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7233                 }
7234                 break;
7235         case 4:
7236         case 5:
7237                 if(same) {
7238                         
7239                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7240                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7241                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7242                         
7243                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7244                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7245                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7246                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7247                 } else {
7248                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7249                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7250                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7251                         
7252                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7253                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7254                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7255                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7256                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7257                 }
7258                 
7259                 if(shCount >=5) {
7260                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7261                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7262                 }
7263                 
7264                 if(sign) {
7265                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7266                         emitpcode(POC_BTFSC, 
7267                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7268                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7269                 }
7270                 
7271                 break;
7272                 
7273         case 6:
7274                 if(same) {
7275                         
7276                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7277                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7278                         
7279                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7280                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7281                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7282                         emitpcode(POC_ANDLW,popGetLit(0x03));
7283                         if(sign) {
7284                                 emitpcode(POC_BTFSC, 
7285                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7286                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7287                         }
7288                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7289                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7290                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7291                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7292                 } else {
7293                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7294                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7295                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7296                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7297                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7298                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7299                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7300                         emitpcode(POC_ANDLW,popGetLit(0x03));
7301                         if(sign) {
7302                                 emitpcode(POC_BTFSC, 
7303                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7304                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7305                         }
7306                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7307                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7308                         
7309                         
7310                 }
7311                 
7312                 break;
7313         case 7:
7314                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7315                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7316                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7318                 if(sign) {
7319                         emitSKPNC;
7320                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7321                 } else 
7322                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7323   }
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7328 /*-----------------------------------------------------------------*/
7329 static void shiftLLeftOrResult (operand *left, int offl,
7330                                                                 operand *result, int offr, int shCount)
7331 {
7332         FENTRY;
7333         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7334         
7335         /* shift left accumulator */
7336         AccLsh(left,offl,shCount);
7337         /* or with result */
7338         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7339         assert ( !"broken (modifies left, fails for left==result))" );
7340 }
7341
7342 /*-----------------------------------------------------------------*/
7343 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7344 /*-----------------------------------------------------------------*/
7345 static void shiftRLeftOrResult (operand *left, int offl,
7346                                                                 operand *result, int offr, int shCount)
7347 {
7348         FENTRY;
7349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7350         
7351         /* shift right accumulator */
7352         AccRsh(left,offl,shCount);
7353         /* or with result */
7354         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7355         assert ( !"broken (modifies left, fails for left==result))" );
7356 }
7357
7358 /*-----------------------------------------------------------------*/
7359 /* genlshOne - left shift a one byte quantity by known count       */
7360 /*-----------------------------------------------------------------*/
7361 static void genlshOne (operand *result, operand *left, int shCount)
7362 {       
7363         FENTRY;
7364         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7365         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7366 }
7367
7368 /*-----------------------------------------------------------------*/
7369 /* genlshTwo - left shift two bytes by known amount != 0           */
7370 /*-----------------------------------------------------------------*/
7371 static void genlshTwo (operand *result,operand *left, int shCount)
7372 {
7373         int size;
7374         
7375         FENTRY;
7376         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7377         size = pic14_getDataSize(result);
7378         
7379         /* if shCount >= 8 */
7380         if (shCount >= 8) {
7381                 shCount -= 8 ;
7382                 
7383                 if (size > 1){
7384                         if (shCount)
7385                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7386                         else 
7387                                 movLeft2Result(left, LSB, result, MSB16);
7388                 }
7389                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7390         }
7391         
7392         /*  1 <= shCount <= 7 */
7393         else {  
7394                 if(size == 1)
7395                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7396                 else 
7397                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7398         }
7399 }
7400
7401 /*-----------------------------------------------------------------*/
7402 /* shiftLLong - shift left one long from left to result            */
7403 /* offl = LSB or MSB16                                             */
7404 /*-----------------------------------------------------------------*/
7405 static void shiftLLong (operand *left, operand *result, int offr )
7406 {
7407         char *l;
7408         int size = AOP_SIZE(result);
7409         
7410         FENTRY;
7411         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7412         if(size >= LSB+offr){
7413                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7414                 MOVA(l);
7415                 pic14_emitcode("add","a,acc");
7416                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7417                         size >= MSB16+offr && offr != LSB )
7418                         pic14_emitcode("xch","a,%s",
7419                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7420                 else      
7421                         aopPut(AOP(result),"a",LSB+offr);
7422         }
7423         
7424         if(size >= MSB16+offr){
7425                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7426                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7427                         MOVA(l);
7428                 }
7429                 pic14_emitcode("rlc","a");
7430                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7431                         size >= MSB24+offr && offr != LSB)
7432                         pic14_emitcode("xch","a,%s",
7433                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7434                 else      
7435                         aopPut(AOP(result),"a",MSB16+offr);
7436         }
7437         
7438         if(size >= MSB24+offr){
7439                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7440                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7441                         MOVA(l);
7442                 }
7443                 pic14_emitcode("rlc","a");
7444                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7445                         size >= MSB32+offr && offr != LSB )
7446                         pic14_emitcode("xch","a,%s",
7447                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7448                 else      
7449                         aopPut(AOP(result),"a",MSB24+offr);
7450         }
7451         
7452         if(size > MSB32+offr){
7453                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7454                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7455                         MOVA(l);  
7456                 }
7457                 pic14_emitcode("rlc","a");
7458                 aopPut(AOP(result),"a",MSB32+offr);
7459         }
7460         if(offr != LSB)
7461                 aopPut(AOP(result),zero,LSB);       
7462 }
7463
7464 /*-----------------------------------------------------------------*/
7465 /* genlshFour - shift four byte by a known amount != 0             */
7466 /*-----------------------------------------------------------------*/
7467 static void genlshFour (operand *result, operand *left, int shCount)
7468 {
7469         int size;
7470         
7471         FENTRY;
7472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7473         size = AOP_SIZE(result);
7474         
7475         /* if shifting more that 3 bytes */
7476         if (shCount >= 24 ) {
7477                 shCount -= 24;
7478                 if (shCount)
7479                 /* lowest order of left goes to the highest
7480                 order of the destination */
7481                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7482                 else
7483                         movLeft2Result(left, LSB, result, MSB32);
7484                 aopPut(AOP(result),zero,LSB);
7485                 aopPut(AOP(result),zero,MSB16);
7486                 aopPut(AOP(result),zero,MSB32);
7487                 return;
7488         }
7489         
7490         /* more than two bytes */
7491         else if ( shCount >= 16 ) {
7492                 /* lower order two bytes goes to higher order two bytes */
7493                 shCount -= 16;
7494                 /* if some more remaining */
7495                 if (shCount)
7496                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7497                 else {
7498                         movLeft2Result(left, MSB16, result, MSB32);
7499                         movLeft2Result(left, LSB, result, MSB24);
7500                 }
7501                 aopPut(AOP(result),zero,MSB16);
7502                 aopPut(AOP(result),zero,LSB);
7503                 return;
7504         }    
7505         
7506         /* if more than 1 byte */
7507         else if ( shCount >= 8 ) {
7508                 /* lower order three bytes goes to higher order  three bytes */
7509                 shCount -= 8;
7510                 if(size == 2){
7511                         if(shCount)
7512                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7513                         else
7514                                 movLeft2Result(left, LSB, result, MSB16);
7515                 }
7516                 else{   /* size = 4 */
7517                         if(shCount == 0){
7518                                 movLeft2Result(left, MSB24, result, MSB32);
7519                                 movLeft2Result(left, MSB16, result, MSB24);
7520                                 movLeft2Result(left, LSB, result, MSB16);
7521                                 aopPut(AOP(result),zero,LSB);
7522                         }
7523                         else if(shCount == 1)
7524                                 shiftLLong(left, result, MSB16);
7525                         else{
7526                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7527                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7528                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7529                                 aopPut(AOP(result),zero,LSB);
7530                         }
7531                 }
7532         }
7533         
7534         /* 1 <= shCount <= 7 */
7535         else if(shCount <= 2){
7536                 shiftLLong(left, result, LSB);
7537                 if(shCount == 2)
7538                         shiftLLong(result, result, LSB);
7539         }
7540         /* 3 <= shCount <= 7, optimize */
7541         else{
7542                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7543                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7544                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7545         }
7546 }
7547 #endif
7548
7549 #if 0
7550 /*-----------------------------------------------------------------*/
7551 /* genLeftShiftLiteral - left shifting by known count              */
7552 /*-----------------------------------------------------------------*/
7553 static void genLeftShiftLiteral (operand *left,
7554                                                                  operand *right,
7555                                                                  operand *result,
7556                                                                  iCode *ic)
7557 {    
7558         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7559         //int size;
7560         
7561         FENTRY;
7562         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7563         freeAsmop(right,NULL,ic,TRUE);
7564         
7565         aopOp(left,ic,FALSE);
7566         aopOp(result,ic,FALSE);
7567
7568         size = getSize(operandType(result));
7569         
7570 #if VIEW_SIZE
7571         pic14_emitcode("; shift left ","result %d, left %d",size,
7572                 AOP_SIZE(left));
7573 #endif
7574         
7575         /* I suppose that the left size >= result size */
7576         if(shCount == 0){
7577                 while(size--){
7578                         movLeft2Result(left, size, result, size);
7579                 }
7580         }
7581         
7582         else if(shCount >= (size * 8))
7583                 while(size--)
7584                         aopPut(AOP(result),zero,size);
7585                 else{
7586                         switch (size) {
7587                         case 1:
7588                                 genlshOne (result,left,shCount);
7589                                 break;
7590                                 
7591                         case 2:
7592                         case 3:
7593                                 genlshTwo (result,left,shCount);
7594                                 break;
7595                                 
7596                         case 4:
7597                                 genlshFour (result,left,shCount);
7598                                 break;
7599                         }
7600                 }
7601                 freeAsmop(left,NULL,ic,TRUE);
7602                 freeAsmop(result,NULL,ic,TRUE);
7603 }
7604 #endif
7605
7606 /*-----------------------------------------------------------------*
7607 * genMultiAsm - repeat assembly instruction for size of register.
7608 * if endian == 1, then the high byte (i.e base address + size of 
7609 * register) is used first else the low byte is used first;
7610 *-----------------------------------------------------------------*/
7611 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7612 {
7613         
7614         int offset = 0;
7615         
7616         FENTRY;
7617         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7618         
7619         if(!reg)
7620                 return;
7621         
7622         if(!endian) {
7623                 endian = 1;
7624         } else {
7625                 endian = -1;
7626                 offset = size-1;
7627         }
7628         
7629         while(size--) {
7630                 emitpcode(poc,    popGet(AOP(reg),offset));
7631                 offset += endian;
7632         }
7633         
7634 }
7635
7636 #if 0
7637 /*-----------------------------------------------------------------*/
7638 /* genLeftShift - generates code for left shifting                 */
7639 /*-----------------------------------------------------------------*/
7640 static void genLeftShift (iCode *ic)
7641 {
7642         operand *left,*right, *result;
7643         int size, offset;
7644         unsigned long lit = 0L;
7645         char *l;
7646         symbol *tlbl , *tlbl1;
7647         pCodeOp *pctemp;
7648         
7649         FENTRY;
7650         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7651         
7652         right = IC_RIGHT(ic);
7653         left  = IC_LEFT(ic);
7654         result = IC_RESULT(ic);
7655         
7656         aopOp(right,ic,FALSE);
7657         aopOp(left,ic,FALSE);
7658         aopOp(result,ic,FALSE);
7659         
7660         
7661         /* if the shift count is known then do it 
7662         as efficiently as possible */
7663         if (AOP_TYPE(right) == AOP_LIT) {
7664                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7665                 return ;
7666         }
7667         
7668         /* shift count is unknown then we have to form 
7669         a loop get the loop count in B : Note: we take
7670         only the lower order byte since shifting
7671         more that 32 bits make no sense anyway, ( the
7672         largest size of an object can be only 32 bits ) */  
7673         
7674         /* this code fails for RIGHT == RESULT */
7675         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7676         
7677         /* now move the left to the result if they are not the
7678         same */
7679         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7680                 AOP_SIZE(result) > 1) {
7681                 
7682                 size = AOP_SIZE(result);
7683                 offset=0;
7684                 while (size--) {
7685                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7686                         if (*l == '@' && (IS_AOP_PREG(result))) {
7687                                 
7688                                 pic14_emitcode("mov","a,%s",l);
7689                                 aopPut(AOP(result),"a",offset);
7690                         } else {
7691                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7692                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7693                                 //aopPut(AOP(result),l,offset);
7694                         }
7695                         offset++;
7696                 }
7697         }
7698         
7699         if(AOP_TYPE(left) == AOP_LIT)
7700                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7701
7702         size = AOP_SIZE(result);
7703         
7704         /* if it is only one byte then */
7705         if (size == 1) {
7706                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7707                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7708                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7709                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7710                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7711                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7712                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7713                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7714                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7715                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7716                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7717                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7718                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7719                 } else {
7720                         
7721                         tlbl = newiTempLabel(NULL);
7722                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7723                                 mov2w (AOP(left), 0);
7724                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7725                         }
7726                         
7727                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7728                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7729                         emitpLabel(tlbl->key);
7730                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7731                         emitpcode(POC_ADDLW,  popGetLit(1));
7732                         emitSKPC;
7733                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7734                 }
7735                 goto release ;
7736         }
7737         
7738         if (pic14_sameRegs(AOP(left),AOP(result))) {
7739                 
7740                 tlbl = newiTempLabel(NULL);
7741                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7742                 genMultiAsm(POC_RRF, result, size,1);
7743                 emitpLabel(tlbl->key);
7744                 genMultiAsm(POC_RLF, result, size,0);
7745                 emitpcode(POC_ADDLW,  popGetLit(1));
7746                 emitSKPC;
7747                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7748                 goto release;
7749         }
7750         
7751         //tlbl = newiTempLabel(NULL);
7752         //offset = 0 ;   
7753         //tlbl1 = newiTempLabel(NULL);
7754         
7755         //reAdjustPreg(AOP(result));    
7756         
7757         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7758         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7759         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7760         //MOVA(l);
7761         //pic14_emitcode("add","a,acc");         
7762         //aopPut(AOP(result),"a",offset++);
7763         //while (--size) {
7764         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7765         //  MOVA(l);
7766         //  pic14_emitcode("rlc","a");         
7767         //  aopPut(AOP(result),"a",offset++);
7768         //}
7769         //reAdjustPreg(AOP(result));
7770         
7771         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7772         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7773         
7774         
7775         tlbl = newiTempLabel(NULL);
7776         tlbl1= newiTempLabel(NULL);
7777         
7778         size = AOP_SIZE(result);
7779         offset = 1;
7780         
7781         pctemp = popGetTempReg();  /* grab a temporary working register. */
7782         
7783         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7784         
7785         /* offset should be 0, 1 or 3 */
7786         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7787         emitSKPNZ;
7788         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7789         
7790         emitpcode(POC_MOVWF, pctemp);
7791         
7792         
7793         emitpLabel(tlbl->key);
7794         
7795         emitCLRC;
7796         emitpcode(POC_RLF,  popGet(AOP(result),0));
7797         while(--size)
7798                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7799         
7800         emitpcode(POC_DECFSZ,  pctemp);
7801         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7802         emitpLabel(tlbl1->key);
7803         
7804         popReleaseTempReg(pctemp);
7805         
7806         
7807 release:
7808         freeAsmop (right,NULL,ic,TRUE);
7809         freeAsmop(left,NULL,ic,TRUE);
7810         freeAsmop(result,NULL,ic,TRUE);
7811 }
7812 #endif
7813
7814 #if 0
7815 /*-----------------------------------------------------------------*/
7816 /* genrshOne - right shift a one byte quantity by known count      */
7817 /*-----------------------------------------------------------------*/
7818 static void genrshOne (operand *result, operand *left,
7819                                            int shCount, int sign)
7820 {
7821         FENTRY;
7822         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7823         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7824 }
7825
7826 /*-----------------------------------------------------------------*/
7827 /* genrshTwo - right shift two bytes by known amount != 0          */
7828 /*-----------------------------------------------------------------*/
7829 static void genrshTwo (operand *result,operand *left,
7830                                            int shCount, int sign)
7831 {
7832         FENTRY;
7833         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7834         /* if shCount >= 8 */
7835         if (shCount >= 8) {
7836                 shCount -= 8 ;
7837                 if (shCount)
7838                         shiftR1Left2Result(left, MSB16, result, LSB,
7839                         shCount, sign);
7840                 else
7841                         movLeft2Result(left, MSB16, result, LSB);
7842                 
7843                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7844                 
7845                 if(sign) {
7846                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7847                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7848                 }
7849         }
7850         
7851         /*  1 <= shCount <= 7 */
7852         else
7853                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* shiftRLong - shift right one long from left to result           */
7858 /* offl = LSB or MSB16                                             */
7859 /*-----------------------------------------------------------------*/
7860 static void shiftRLong (operand *left, int offl,
7861                                                 operand *result, int sign)
7862 {
7863         int size, same;
7864         
7865         FENTRY;
7866         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7867         
7868         size = AOP_SIZE(left);
7869         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7870         
7871         if (sign)
7872                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7873         else
7874                 emitCLRC;
7875
7876         assert (offl >= 0 && offl < size);
7877
7878         same = pic14_sameRegs (AOP(left), AOP(result));
7879
7880         /* perform the shift */
7881         while (size--)
7882         {
7883                 if (same && !offl) {
7884                         emitpcode (POC_RRF, popGet (AOP(result), size));
7885                 } else {
7886                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7887                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7888                 }
7889         } // while
7890
7891         addSign (result, AOP_SIZE(left) - offl, sign);
7892 }
7893
7894 /*-----------------------------------------------------------------*/
7895 /* genrshFour - shift four byte by a known amount != 0             */
7896 /*-----------------------------------------------------------------*/
7897 static void genrshFour (operand *result, operand *left,
7898                                                 int shCount, int sign)
7899 {
7900         FENTRY;
7901         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7902         /* if shifting more that 3 bytes */
7903         if(shCount >= 24 ) {
7904                 shCount -= 24;
7905                 if(shCount)
7906                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7907                 else
7908                         movLeft2Result(left, MSB32, result, LSB);
7909                 
7910                 addSign(result, MSB16, sign);
7911         }
7912         else if(shCount >= 16){
7913                 shCount -= 16;
7914                 if(shCount)
7915                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7916                 else{
7917                         movLeft2Result(left, MSB24, result, LSB);
7918                         movLeft2Result(left, MSB32, result, MSB16);
7919                 }
7920                 addSign(result, MSB24, sign);
7921         }
7922         else if(shCount >= 8){
7923                 shCount -= 8;
7924                 if(shCount == 1)
7925                         shiftRLong(left, MSB16, result, sign);
7926                 else if(shCount == 0){
7927                         movLeft2Result(left, MSB16, result, LSB);
7928                         movLeft2Result(left, MSB24, result, MSB16);
7929                         movLeft2Result(left, MSB32, result, MSB24);
7930                         addSign(result, MSB32, sign);
7931                 }
7932                 else{
7933                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7934                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7935                         /* the last shift is signed */
7936                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7937                         addSign(result, MSB32, sign);
7938                 }
7939         }
7940         else{   /* 1 <= shCount <= 7 */
7941                 if(shCount <= 2){
7942                         shiftRLong(left, LSB, result, sign);
7943                         if(shCount == 2)
7944                                 shiftRLong(result, LSB, result, sign);
7945                 }
7946                 else{
7947                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7948                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7949                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7950                 }
7951         }
7952 }
7953
7954 /*-----------------------------------------------------------------*/
7955 /* genRightShiftLiteral - right shifting by known count            */
7956 /*-----------------------------------------------------------------*/
7957 static void genRightShiftLiteral (operand *left,
7958                                                                   operand *right,
7959                                                                   operand *result,
7960                                                                   iCode *ic,
7961                                                                   int sign)
7962 {    
7963         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7964         int lsize,res_size;
7965         
7966         FENTRY;
7967         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7968         freeAsmop(right,NULL,ic,TRUE);
7969         
7970         aopOp(left,ic,FALSE);
7971         aopOp(result,ic,FALSE);
7972         
7973 #if VIEW_SIZE
7974         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7975                 AOP_SIZE(left));
7976 #endif
7977         
7978         lsize = pic14_getDataSize(left);
7979         res_size = pic14_getDataSize(result);
7980         /* test the LEFT size !!! */
7981         
7982         /* I suppose that the left size >= result size */
7983         if(shCount == 0){
7984                 while(res_size--)
7985                         movLeft2Result(left, res_size, result, res_size);
7986         }
7987         
7988         else if(shCount >= (lsize * 8)){
7989                 
7990                 if(res_size == 1) {
7991                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7992                         if(sign) {
7993                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7994                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7995                         }
7996                 } else {
7997                         
7998                         if(sign) {
7999                                 emitpcode(POC_MOVLW, popGetLit(0));
8000                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8001                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8002                                 while(res_size--)
8003                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8004                                 
8005                         } else {
8006                                 
8007                                 while(res_size--)
8008                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8009                         }
8010                 }
8011         } else {
8012                 
8013                 switch (res_size) {
8014                 case 1:
8015                         genrshOne (result,left,shCount,sign);
8016                         break;
8017                         
8018                 case 2:
8019                         genrshTwo (result,left,shCount,sign);
8020                         break;
8021                         
8022                 case 4:
8023                         genrshFour (result,left,shCount,sign);
8024                         break;
8025                 default :
8026                         break;
8027                 }
8028                 
8029         }
8030
8031         freeAsmop(left,NULL,ic,TRUE);
8032         freeAsmop(result,NULL,ic,TRUE);
8033 }
8034 #endif
8035
8036 #if 0
8037 /*-----------------------------------------------------------------*/
8038 /* genSignedRightShift - right shift of signed number              */
8039 /*-----------------------------------------------------------------*/
8040 static void genSignedRightShift (iCode *ic)
8041 {
8042         operand *right, *left, *result;
8043         int size, offset;
8044         //  char *l;
8045         symbol *tlbl, *tlbl1 ;
8046         pCodeOp *pctemp;
8047         
8048         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8049         
8050         /* we do it the hard way put the shift count in b
8051         and loop thru preserving the sign */
8052         FENTRY;
8053         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054         
8055         right = IC_RIGHT(ic);
8056         left  = IC_LEFT(ic);
8057         result = IC_RESULT(ic);
8058         
8059         aopOp(right,ic,FALSE);  
8060         aopOp(left,ic,FALSE);
8061         aopOp(result,ic,FALSE);
8062         
8063         
8064         if ( AOP_TYPE(right) == AOP_LIT) {
8065                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8066                 //genRightShiftLiteral (left,right,result,ic,1);
8067                 return ;
8068         }
8069         /* shift count is unknown then we have to form 
8070         a loop get the loop count in B : Note: we take
8071         only the lower order byte since shifting
8072         more that 32 bits make no sense anyway, ( the
8073         largest size of an object can be only 32 bits ) */  
8074         
8075         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8076         //pic14_emitcode("inc","b");
8077         //freeAsmop (right,NULL,ic,TRUE);
8078         //aopOp(left,ic,FALSE);
8079         //aopOp(result,ic,FALSE);
8080         
8081         /* now move the left to the result if they are not the
8082         same */
8083         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8084                 AOP_SIZE(result) > 1) {
8085                 
8086                 size = AOP_SIZE(result);
8087                 offset=0;
8088                 while (size--) { 
8089                         /*
8090                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8091                         if (*l == '@' && IS_AOP_PREG(result)) {
8092                                 pic14_emitcode("mov","a,%s",l);
8093                                 aopPut(AOP(result),"a",offset);
8094                         } else
8095                         aopPut(AOP(result),l,offset);
8096                         */
8097                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8098                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8099                         
8100                         offset++;
8101                 }
8102         }
8103         
8104         /* mov the highest order bit to OVR */    
8105         tlbl = newiTempLabel(NULL);
8106         tlbl1= newiTempLabel(NULL);
8107         
8108         size = AOP_SIZE(result);
8109         offset = size - 1;
8110         
8111         pctemp = popGetTempReg();  /* grab a temporary working register. */
8112         
8113         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8114         
8115         /* offset should be 0, 1 or 3 */
8116         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8117         emitSKPNZ;
8118         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8119         
8120         emitpcode(POC_MOVWF, pctemp);
8121         
8122         
8123         emitpLabel(tlbl->key);
8124         
8125         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8126         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8127         
8128         while(--size) {
8129                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8130         }
8131         
8132         emitpcode(POC_DECFSZ,  pctemp);
8133         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8134         emitpLabel(tlbl1->key);
8135         
8136         popReleaseTempReg(pctemp);
8137 #if 0
8138         size = AOP_SIZE(result);
8139         offset = size - 1;
8140         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8141         pic14_emitcode("rlc","a");
8142         pic14_emitcode("mov","ov,c");
8143         /* if it is only one byte then */
8144         if (size == 1) {
8145                 l = aopGet(AOP(left),0,FALSE,FALSE);
8146                 MOVA(l);
8147                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8148                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8149                 pic14_emitcode("mov","c,ov");
8150                 pic14_emitcode("rrc","a");
8151                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8152                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8153                 aopPut(AOP(result),"a",0);
8154                 goto release ;
8155         }
8156         
8157         reAdjustPreg(AOP(result));
8158         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8159         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8160         pic14_emitcode("mov","c,ov");
8161         while (size--) {
8162                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8163                 MOVA(l);
8164                 pic14_emitcode("rrc","a");         
8165                 aopPut(AOP(result),"a",offset--);
8166         }
8167         reAdjustPreg(AOP(result));
8168         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8169         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8170         
8171 release:
8172 #endif
8173         
8174         freeAsmop(left,NULL,ic,TRUE);
8175         freeAsmop(result,NULL,ic,TRUE);
8176         freeAsmop(right,NULL,ic,TRUE);
8177 }
8178 #endif
8179
8180 /*-----------------------------------------------------------------*/
8181 /* loadSignToC - load the operand's sign bit into CARRY            */
8182 /*-----------------------------------------------------------------*/
8183
8184 static void loadSignToC (operand *op)
8185 {
8186         FENTRY;
8187         assert (op && AOP(op) && AOP_SIZE(op));
8188
8189         emitCLRC;
8190         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8191         emitSETC;
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genRightShift - generate code for right shifting                */
8196 /*-----------------------------------------------------------------*/
8197 static void genGenericShift (iCode *ic, int shiftRight)
8198 {
8199         operand *right, *left, *result;
8200         sym_link *retype ;
8201         int size;
8202         symbol *tlbl, *tlbl1, *inverselbl;
8203         
8204         FENTRY;
8205         /* if signed then we do it the hard way preserve the
8206         sign bit moving it inwards */
8207         retype = getSpec(operandType(IC_RESULT(ic)));
8208         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8209         
8210         /* signed & unsigned types are treated the same : i.e. the
8211         signed is NOT propagated inwards : quoting from the
8212         ANSI - standard : "for E1 >> E2, is equivalent to division
8213         by 2**E2 if unsigned or if it has a non-negative value,
8214         otherwise the result is implementation defined ", MY definition
8215         is that the sign does not get propagated */
8216         
8217         right = IC_RIGHT(ic);
8218         left  = IC_LEFT(ic);
8219         result = IC_RESULT(ic);
8220         
8221         aopOp(right,ic,FALSE);
8222         aopOp(left,ic,FALSE);
8223         aopOp(result,ic,FALSE);
8224         
8225         /* if the shift count is known then do it 
8226         as efficiently as possible */
8227         if (AOP_TYPE(right) == AOP_LIT) {
8228                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8229                 if (lit < 0)
8230                 {
8231                         lit = -lit;
8232                         shiftRight = !shiftRight;
8233                 }
8234                 
8235                 if (shiftRight)
8236                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8237                 else
8238                         shiftLeft_Left2ResultLit (left, result, lit);
8239                 //genRightShiftLiteral (left,right,result,ic, 0);
8240                 return ;
8241         }
8242         
8243         /* shift count is unknown then we have to form 
8244         a loop get the loop count in B : Note: we take
8245         only the lower order byte since shifting
8246         more that 32 bits make no sense anyway, ( the
8247         largest size of an object can be only 32 bits ) */  
8248
8249         /* we must not overwrite the shift counter */
8250         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8251         
8252         /* now move the left to the result if they are not the
8253         same */
8254         if (!pic14_sameRegs(AOP(left),AOP(result)))
8255         {
8256                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8257                 while (size--) {
8258                         mov2w(AOP(left), size);
8259                         movwf(AOP(result), size);
8260                 }
8261                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8262         }
8263         
8264         tlbl = newiTempLabel(NULL);
8265         tlbl1= newiTempLabel(NULL);
8266         inverselbl = NULL;
8267         size = AOP_SIZE(result);
8268
8269         mov2w(AOP(right),0);
8270         if (!SPEC_USIGN(operandType(right)))
8271         {
8272                 inverselbl = newiTempLabel(NULL);
8273                 /* signed shift count -- invert shift direction for c<0 */
8274                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8275                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8276         } // if
8277         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8278         /* check for `a = b >> c' with `-c == 0' */
8279         emitSKPNZ;
8280         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8281         emitpLabel(tlbl->key);
8282         /* propagate the sign bit inwards for SIGNED result */
8283         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8284         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8285         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8286         emitSKPC;
8287         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8288
8289         if (!SPEC_USIGN(operandType(right)))
8290         {
8291                 symbol *inv_loop = newiTempLabel(NULL);
8292
8293                 shiftRight = !shiftRight;       /* invert shift direction */
8294                 
8295                 /* we came here from the code above -- we are done */
8296                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8297                 
8298                 /* emit code for shifting N<0 steps, count is already in W */
8299                 emitpLabel(inverselbl->key);
8300                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8301                 emitpLabel(inv_loop->key);
8302                 /* propagate the sign bit inwards for SIGNED result */
8303                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8304                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8305                 emitpcode(POC_ADDLW, popGetLit(1));
8306                 emitSKPC;
8307                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8308         } // if
8309         
8310         emitpLabel(tlbl1->key);
8311         
8312         freeAsmop(left,NULL,ic,TRUE);
8313         freeAsmop (right,NULL,ic,TRUE);
8314         freeAsmop(result,NULL,ic,TRUE);
8315 }
8316
8317 static void genRightShift (iCode *ic)
8318 {
8319         genGenericShift(ic, 1);
8320 }
8321
8322 static void genLeftShift (iCode *ic)
8323 {
8324         genGenericShift(ic, 0);
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* SetIrp - Set IRP bit                                            */
8329 /*-----------------------------------------------------------------*/
8330 void SetIrp(operand *result) {
8331         FENTRY;
8332         if (AOP_TYPE(result) == AOP_LIT) {
8333                 unsigned lit = (unsigned)operandLitValue(result);
8334                 if (lit&0x100)
8335                         emitSETIRP;
8336                 else
8337                         emitCLRIRP;
8338         } else {
8339                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8340                         int addrs = PCOL(AOP(result))->lit;
8341                         if (addrs & 0x100)
8342                                 emitSETIRP;
8343                         else
8344                                 emitCLRIRP;
8345                 } else {
8346                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8347                         if(AOP_SIZE(result) > 1) {
8348                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8349                                 emitSETIRP;
8350                         }
8351                 }
8352         }
8353 }
8354
8355 static void
8356 setup_fsr (operand *ptr)
8357 {
8358   mov2w_op(ptr, 0);
8359   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8360
8361   /* also setup-up IRP */
8362   SetIrp (ptr);
8363 }
8364
8365 /*-----------------------------------------------------------------*/
8366 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8367 /*                  arbitrary pointer (__code, __data, generic)    */
8368 /*-----------------------------------------------------------------*/
8369 static void
8370 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8371 {
8372     FENTRY;
8373     switch (p_type)
8374     {
8375     case POINTER:
8376     case FPOINTER:
8377       if (!alreadyAddressed) setup_fsr (src);
8378       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8379       break;
8380     
8381     case CPOINTER:
8382       assert( AOP_SIZE(src) == 2 );
8383       mov2w_op(src, 0);
8384       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8385       mov2w_op(src, 1);
8386       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8387       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8388       call_libraryfunc ("__gptrget1");
8389       break;
8390     
8391     case GPOINTER:
8392       assert( AOP_SIZE(src) == 3 );
8393       mov2w_op(src, 0);
8394       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8395       mov2w_op(src, 1);
8396       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8397       mov2w_op(src, 2);
8398       call_libraryfunc ("__gptrget1");
8399       break;
8400     
8401     default:
8402       assert( !"unhandled pointer type" );
8403       break;
8404     }
8405 }
8406
8407 /*-----------------------------------------------------------------*/
8408 /* emitPtrByteSet - emits code to set a byte from src through a    */
8409 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8410 /*-----------------------------------------------------------------*/
8411 static void
8412 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8413 {
8414     FENTRY;
8415     switch (p_type)
8416     {
8417     case POINTER:
8418     case FPOINTER:
8419       if (!alreadyAddressed) setup_fsr (dst);
8420       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8421       break;
8422     
8423     case CPOINTER:
8424       assert( !"trying to assign to __code pointer" );
8425       break;
8426     
8427     case GPOINTER:
8428       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8429       mov2w_op(dst, 0);
8430       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8431       mov2w_op(dst, 1);
8432       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8433       mov2w_op(dst, 2);
8434       call_libraryfunc ("__gptrput1");
8435       break;
8436
8437     default:
8438       assert( !"unhandled pointer type" );
8439       break;
8440     }
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* genUnpackBits - generates code for unpacking bits               */
8445 /*-----------------------------------------------------------------*/
8446 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8447 {    
8448   int rsize;            /* result size */
8449   sym_link *etype;      /* bitfield type information */
8450   int blen;             /* bitfield length */
8451   int bstr;             /* bitfield starting bit within byte */
8452
8453   FENTRY;
8454   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8455   etype = getSpec(operandType(result));
8456   rsize = getSize (operandType (result));
8457   blen = SPEC_BLEN (etype);
8458   bstr = SPEC_BSTR (etype);
8459
8460   /* single bit field case */
8461   if (blen == 1) {
8462     if (ifx) { /* that is for an if statement */
8463       pCodeOp *pcop;
8464       resolvedIfx rIfx;
8465       resolveIfx(&rIfx,ifx);
8466       if (ptype == -1) /* direct */
8467         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8468       else
8469         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8470       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8471       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8472       ifx->generated=1;
8473     } else {
8474       int i;
8475       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8476       for (i=0; i < AOP_SIZE(result); i++)
8477         emitpcode (POC_CLRF, popGet (AOP(result), i));
8478
8479       switch (ptype)
8480       {
8481       case -1:
8482         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8483         /* adjust result below */
8484         break;
8485         
8486       case POINTER:
8487       case FPOINTER:
8488       case GPOINTER:
8489       case CPOINTER:
8490         emitPtrByteGet (left, ptype, FALSE);
8491         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8492         emitSKPZ;
8493         /* adjust result below */
8494         break;
8495         
8496       default:
8497         assert( !"unhandled pointer type" );
8498       } // switch
8499
8500       /* move sign-/zero extended bit to result */
8501       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8502         emitpcode (POC_INCF, popGet (AOP(result), 0));
8503       } else {
8504         emitpcode (POC_DECF, popGet (AOP(result), 0));
8505       }
8506       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8507     }
8508     return;
8509   }
8510   else if (blen <= 8 && ((blen + bstr) <= 8))
8511   {
8512     /* blen > 1 */
8513     int i;
8514
8515     for (i=0; i < AOP_SIZE(result); i++)
8516       emitpcode (POC_CLRF, popGet (AOP(result), i));
8517
8518     switch (ptype)
8519     {
8520     case -1:
8521       mov2w(AOP(left), 0);
8522       break;
8523       
8524     case POINTER:
8525     case FPOINTER:
8526     case GPOINTER:
8527     case CPOINTER:
8528       emitPtrByteGet (left, ptype, FALSE);
8529       break;
8530       
8531     default:
8532       assert( !"unhandled pointer type" );
8533     } // switch
8534
8535     if (blen < 8)
8536       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8537     movwf(AOP(result), 0);
8538     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8539
8540     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8541     {
8542       /* signed bitfield */
8543       assert (bstr + blen > 0);
8544       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8545       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8546       emitpcode(POC_IORWF, popGet(AOP(result),0));
8547     }
8548     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8549     return;
8550   }
8551
8552   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8553 }
8554
8555 #if 1
8556 /*-----------------------------------------------------------------*/
8557 /* genDataPointerGet - generates code when ptr offset is known     */
8558 /*-----------------------------------------------------------------*/
8559 static void genDataPointerGet (operand *left, 
8560         operand *result, 
8561         iCode *ic)
8562 {
8563         int size , offset = 0;
8564                 
8565         FENTRY;
8566         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8567         
8568         
8569         /* optimization - most of the time, left and result are the same
8570         * address, but different types. for the pic code, we could omit
8571         * the following
8572         */
8573         aopOp(result,ic,TRUE);
8574         
8575         if (pic14_sameRegs (AOP(left), AOP(result)))
8576                 return;
8577         
8578         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8579         
8580         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8581         
8582         size = AOP_SIZE(result);
8583         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8584         
8585         offset = 0;
8586         while (size--) {
8587                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8588                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8589                 offset++;
8590         }
8591         
8592         freeAsmop(left,NULL,ic,TRUE);
8593         freeAsmop(result,NULL,ic,TRUE);
8594 }
8595 #endif
8596
8597 /*-----------------------------------------------------------------*/
8598 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8599 /*-----------------------------------------------------------------*/
8600 static void genNearPointerGet (operand *left, 
8601                                                            operand *result, 
8602                                                            iCode *ic)
8603 {
8604         asmop *aop = NULL;
8605         sym_link *ltype = operandType(left);
8606         sym_link *rtype = operandType(result);
8607         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8608         int direct = 0;
8609
8610         FENTRY;
8611         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8612         
8613         
8614         aopOp(left,ic,FALSE);
8615         
8616         /* if left is rematerialisable and
8617         result is not bit variable type and
8618         the left is pointer to data space i.e
8619         lower 128 bytes of space */
8620         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8621                 !IS_BITVAR(retype)         &&
8622                 PIC_IS_DATA_PTR(ltype)) {
8623                 genDataPointerGet (left,result,ic);
8624                 return ;
8625         }
8626         
8627         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8628         aopOp (result,ic,FALSE);
8629         
8630         /* Check if can access directly instead of via a pointer */
8631         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8632                 && AOP_SIZE(result) == 1)
8633         {
8634                 direct = 1;
8635         }
8636
8637         if (IS_BITFIELD(getSpec(operandType(result)))) 
8638         {
8639                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8640                 goto release;
8641         }
8642         
8643         /* If the pointer value is not in a the FSR then need to put it in */
8644         /* Must set/reset IRP bit for use with FSR. */
8645         if (!direct)
8646           setup_fsr (left);
8647         
8648 //      sym_link *etype;
8649         /* if bitfield then unpack the bits */
8650         {
8651                 /* we have can just get the values */
8652                 int size = AOP_SIZE(result);
8653                 int offset = 0 ;  
8654                 
8655                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8656                 
8657                 while(size--) {
8658                         if (direct)
8659                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8660                         else
8661                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8662                         if (AOP_TYPE(result) == AOP_LIT) {
8663                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8664                         } else {
8665                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8666                         }
8667                         if (size && !direct)
8668                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8669                         offset++;
8670                 }
8671         }
8672         
8673         /* now some housekeeping stuff */
8674         if (aop) {
8675                 /* we had to allocate for this iCode */
8676                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8677                 freeAsmop(NULL,aop,ic,TRUE);
8678         } else { 
8679                 /* we did not allocate which means left
8680                 already in a pointer register, then
8681                 if size > 0 && this could be used again
8682                 we have to point it back to where it 
8683                 belongs */
8684                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8685                 if (AOP_SIZE(result) > 1 &&
8686                         !OP_SYMBOL(left)->remat &&
8687                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8688                         ic->depth )) {
8689                         int size = AOP_SIZE(result) - 1;
8690                         while (size--)
8691                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8692                 }
8693         }
8694         
8695 release:
8696         /* done */
8697         freeAsmop(left,NULL,ic,TRUE);
8698         freeAsmop(result,NULL,ic,TRUE);
8699
8700 }
8701
8702 #if 0
8703 /*-----------------------------------------------------------------*/
8704 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8705 /*-----------------------------------------------------------------*/
8706 static void genPagedPointerGet (operand *left, 
8707                                                                 operand *result, 
8708                                                                 iCode *ic)
8709 {
8710         asmop *aop = NULL;
8711         regs *preg = NULL ;
8712         char *rname ;
8713         sym_link *rtype, *retype;    
8714         
8715         FENTRY;
8716         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8717         
8718         rtype = operandType(result);
8719         retype= getSpec(rtype);
8720         
8721         aopOp(left,ic,FALSE);
8722         
8723         /* if the value is already in a pointer register
8724         then don't need anything more */
8725         if (!AOP_INPREG(AOP(left))) {
8726                 /* otherwise get a free pointer register */
8727                 aop = newAsmop(0);
8728                 preg = getFreePtr(ic,&aop,FALSE);
8729                 pic14_emitcode("mov","%s,%s",
8730                         preg->name,
8731                         aopGet(AOP(left),0,FALSE,TRUE));
8732                 rname = preg->name ;
8733         } else
8734                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8735         
8736         freeAsmop(left,NULL,ic,TRUE);
8737         aopOp (result,ic,FALSE);
8738         
8739         /* if bitfield then unpack the bits */
8740         if (IS_BITFIELD(retype)) 
8741                 genUnpackBits (result,left,rname,PPOINTER,0);
8742         else {
8743                 /* we have can just get the values */
8744                 int size = AOP_SIZE(result);
8745                 int offset = 0 ;  
8746                 
8747                 while (size--) {
8748                         
8749                         pic14_emitcode("movx","a,@%s",rname);
8750                         aopPut(AOP(result),"a",offset);
8751                         
8752                         offset++ ;
8753                         
8754                         if (size)
8755                                 pic14_emitcode("inc","%s",rname);
8756                 }
8757         }
8758         
8759         /* now some housekeeping stuff */
8760         if (aop) {
8761                 /* we had to allocate for this iCode */
8762                 freeAsmop(NULL,aop,ic,TRUE);
8763         } else { 
8764         /* we did not allocate which means left
8765         already in a pointer register, then
8766         if size > 0 && this could be used again
8767         we have to point it back to where it 
8768                 belongs */
8769                 if (AOP_SIZE(result) > 1 &&
8770                         !OP_SYMBOL(left)->remat &&
8771                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8772                         ic->depth )) {
8773                         int size = AOP_SIZE(result) - 1;
8774                         while (size--)
8775                                 pic14_emitcode("dec","%s",rname);
8776                 }
8777         }
8778         
8779         /* done */
8780         freeAsmop(result,NULL,ic,TRUE);
8781         
8782         
8783 }
8784
8785 /*-----------------------------------------------------------------*/
8786 /* genFarPointerGet - gget value from far space                    */
8787 /*-----------------------------------------------------------------*/
8788 static void genFarPointerGet (operand *left,
8789                                                           operand *result, iCode *ic)
8790 {
8791         int size, offset ;
8792         sym_link *retype = getSpec(operandType(result));
8793         
8794         FENTRY;
8795         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8796         
8797         aopOp(left,ic,FALSE);
8798         
8799         /* if the operand is already in dptr 
8800         then we do nothing else we move the value to dptr */
8801         if (AOP_TYPE(left) != AOP_STR) {
8802                 /* if this is remateriazable */
8803                 if (AOP_TYPE(left) == AOP_IMMD)
8804                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8805                 else { /* we need to get it byte by byte */
8806                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8807                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8808                         if (options.model == MODEL_FLAT24)
8809                         {
8810                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8811                         }
8812                 }
8813         }
8814         /* so dptr know contains the address */
8815         freeAsmop(left,NULL,ic,TRUE);
8816         aopOp(result,ic,FALSE);
8817         
8818         /* if bit then unpack */
8819         if (IS_BITFIELD(retype)) 
8820                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8821         else {
8822                 size = AOP_SIZE(result);
8823                 offset = 0 ;
8824                 
8825                 while (size--) {
8826                         pic14_emitcode("movx","a,@dptr");
8827                         aopPut(AOP(result),"a",offset++);
8828                         if (size)
8829                                 pic14_emitcode("inc","dptr");
8830                 }
8831         }
8832         
8833         freeAsmop(result,NULL,ic,TRUE);
8834 }
8835 #endif
8836
8837 #if 0
8838 /*-----------------------------------------------------------------*/
8839 /* genCodePointerGet - get value from code space                  */
8840 /*-----------------------------------------------------------------*/
8841 static void genCodePointerGet (operand *left,
8842                                                            operand *result, iCode *ic)
8843 {
8844         int size, offset ;
8845         sym_link *retype = getSpec(operandType(result));
8846         
8847         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848         
8849         aopOp(left,ic,FALSE);
8850         
8851         /* if the operand is already in dptr 
8852         then we do nothing else we move the value to dptr */
8853         if (AOP_TYPE(left) != AOP_STR) {
8854                 /* if this is remateriazable */
8855                 if (AOP_TYPE(left) == AOP_IMMD)
8856                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8857                 else { /* we need to get it byte by byte */
8858                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8859                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8860                         if (options.model == MODEL_FLAT24)
8861                         {
8862                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8863                         }
8864                 }
8865         }
8866         /* so dptr know contains the address */
8867         freeAsmop(left,NULL,ic,TRUE);
8868         aopOp(result,ic,FALSE);
8869         
8870         /* if bit then unpack */
8871         if (IS_BITFIELD(retype)) 
8872                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8873         else {
8874                 size = AOP_SIZE(result);
8875                 offset = 0 ;
8876                 
8877                 while (size--) {
8878                         pic14_emitcode("clr","a");
8879                         pic14_emitcode("movc","a,@a+dptr");
8880                         aopPut(AOP(result),"a",offset++);
8881                         if (size)
8882                                 pic14_emitcode("inc","dptr");
8883                 }
8884         }
8885         
8886         freeAsmop(result,NULL,ic,TRUE);
8887 }
8888 #endif
8889 /*-----------------------------------------------------------------*/
8890 /* genGenPointerGet - gget value from generic pointer space        */
8891 /*-----------------------------------------------------------------*/
8892 static void genGenPointerGet (operand *left,
8893                                                           operand *result, iCode *ic)
8894 {
8895         FENTRY;
8896         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8897         aopOp(left,ic,FALSE);
8898         aopOp(result,ic,FALSE);
8899         
8900         
8901         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8902
8903         if (IS_BITFIELD(getSpec(operandType(result))))
8904         {
8905           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8906           return;
8907         }
8908
8909         {
8910           /* emit call to __gptrget */
8911           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8912           int size = AOP_SIZE(result);
8913           int idx = 0;
8914
8915           assert (size > 0 && size <= 4);
8916
8917           /* pass arguments */
8918           assert (AOP_SIZE(left) == 3);
8919           mov2w(AOP(left), 0);
8920           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8921           mov2w(AOP(left), 1);
8922           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8923           mov2w(AOP(left), 2);
8924           call_libraryfunc (func[size]);
8925           
8926           /* save result */
8927           movwf (AOP(result), --size);
8928           while (size--) {
8929             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8930             movwf (AOP(result), size);
8931           } // while
8932         }
8933         
8934         freeAsmop(left,NULL,ic,TRUE);
8935         freeAsmop(result,NULL,ic,TRUE);
8936         
8937 }
8938
8939 /*-----------------------------------------------------------------*/
8940 /* genConstPointerGet - get value from const generic pointer space */
8941 /*-----------------------------------------------------------------*/
8942 static void genConstPointerGet (operand *left,
8943                                                                 operand *result, iCode *ic)
8944 {
8945         //sym_link *retype = getSpec(operandType(result));
8946         #if 0
8947         symbol *albl, *blbl;//, *clbl;
8948         pCodeOp *pcop;
8949         #endif
8950         PIC_OPCODE poc;
8951         int i, size, lit;
8952         
8953         FENTRY;
8954         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8955         aopOp(left,ic,FALSE);
8956         aopOp(result,ic,FALSE);
8957         
8958         size = AOP_SIZE(result);
8959         
8960         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8961         
8962         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8963
8964         lit = op_isLitLike (left);
8965         poc = lit ? POC_MOVLW : POC_MOVFW;
8966
8967         if (IS_BITFIELD(getSpec(operandType(result))))
8968         {
8969                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8970                 goto release;
8971         }
8972
8973         {
8974                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8975                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
8976                 assert (size > 0 && size <= 4);
8977                 
8978                 mov2w_op(left, 0);
8979                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8980                 mov2w_op(left, 1);
8981                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8982                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8983                 call_libraryfunc (func[size]);
8984
8985                 movwf(AOP(result),size-1);
8986                 for (i = 1; i < size; i++)
8987                 {
8988                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
8989                         movwf(AOP(result),size - 1 - i);
8990                 } // for
8991         }
8992         
8993 release:
8994         freeAsmop(left,NULL,ic,TRUE);
8995         freeAsmop(result,NULL,ic,TRUE);
8996         
8997 }
8998 /*-----------------------------------------------------------------*/
8999 /* genPointerGet - generate code for pointer get                   */
9000 /*-----------------------------------------------------------------*/
9001 static void genPointerGet (iCode *ic)
9002 {
9003         operand *left, *result ;
9004         sym_link *type, *etype;
9005         int p_type = -1;
9006         
9007         FENTRY;
9008         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9009         
9010         left = IC_LEFT(ic);
9011         result = IC_RESULT(ic) ;
9012         
9013         /* depending on the type of pointer we need to
9014         move it to the correct pointer register */
9015         type = operandType(left);
9016         etype = getSpec(type);
9017         
9018         if (IS_PTR_CONST(type))
9019                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9020         
9021         /* if left is of type of pointer then it is simple */
9022         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9023                 p_type = DCL_TYPE(type);
9024         else {
9025                 /* we have to go by the storage class */
9026                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9027                 
9028                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9029                 
9030                 if (SPEC_OCLS(etype)->codesp ) {
9031                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9032                         //p_type = CPOINTER ; 
9033                 }
9034                 else
9035                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9036                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9037                         /*p_type = FPOINTER ;*/ 
9038                         else
9039                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9040                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9041                                 /*        p_type = PPOINTER; */
9042                                 else
9043                                         if (SPEC_OCLS(etype) == idata )
9044                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9045                                         /*      p_type = IPOINTER; */
9046                                         else
9047                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9048                                         /*      p_type = POINTER ; */
9049         }
9050         
9051         /* now that we have the pointer type we assign
9052         the pointer values */
9053         switch (p_type) {
9054                 
9055         case POINTER: 
9056         case FPOINTER:
9057         //case IPOINTER:
9058                 genNearPointerGet (left,result,ic);
9059                 break;
9060 /*
9061         case PPOINTER:
9062                 genPagedPointerGet(left,result,ic);
9063                 break;
9064                 
9065         case FPOINTER:
9066                 genFarPointerGet (left,result,ic);
9067                 break;
9068 */              
9069         case CPOINTER:
9070                 genConstPointerGet (left,result,ic);
9071                 break;
9072                 
9073         case GPOINTER:
9074                 genGenPointerGet (left,result,ic);
9075                 break;
9076         default:
9077                 assert ( !"unhandled pointer type" );
9078                 break;
9079         }
9080         
9081 }
9082
9083 /*-----------------------------------------------------------------*/
9084 /* genPackBits - generates code for packed bit storage             */
9085 /*-----------------------------------------------------------------*/
9086 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9087 {
9088   int blen;             /* bitfield length */
9089   int bstr;             /* bitfield starting bit within byte */
9090   int litval;           /* source literal value (if AOP_LIT) */
9091   unsigned char mask;   /* bitmask within current byte */
9092
9093   FENTRY;
9094   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9095
9096   blen = SPEC_BLEN (etype);
9097   bstr = SPEC_BSTR (etype);
9098
9099   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9100   if ((blen <= 8) && ((bstr + blen) <= 8))
9101   {
9102     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9103             (unsigned char) (0xFF >> (8 - bstr)));
9104
9105     if (AOP_TYPE (right) == AOP_LIT)
9106     {
9107       /* Case with a bitfield length <8 and literal source */
9108       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9109       if (blen == 1) {
9110         pCodeOp *pcop;
9111         
9112         switch (p_type)
9113         {
9114         case -1:
9115           if (AOP(result)->type == AOP_PCODE)
9116             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9117           else
9118             pcop = popGet(AOP(result),0);
9119           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9120           break;
9121         
9122         case POINTER:
9123         case FPOINTER:
9124           setup_fsr (result);
9125           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9126           break;
9127         
9128         case CPOINTER:
9129           assert( !"trying to assign to bitfield via pointer to __code space" );
9130           break;
9131         
9132         case GPOINTER:
9133           emitPtrByteGet(result, p_type, FALSE);
9134           if (lit) {
9135             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9136           } else {
9137             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9138           }
9139           emitPtrByteSet(result, p_type, TRUE);
9140           break;
9141         
9142         default:
9143           assert( !"unhandled pointer type" );
9144           break;
9145         } // switch (p_type)
9146       } else {
9147         /* blen > 1 */
9148         litval = lit << bstr;
9149         litval &= (~mask) & 0x00ff;
9150         
9151         switch (p_type)
9152         {
9153         case -1:
9154           mov2w (AOP(result), 0);
9155           if ((litval|mask) != 0x00ff)
9156             emitpcode(POC_ANDLW, popGetLit (mask));
9157           if (litval != 0x00)
9158             emitpcode(POC_IORLW, popGetLit (litval));
9159           movwf (AOP(result), 0);
9160           break;
9161         
9162         case POINTER:
9163         case FPOINTER:
9164         case GPOINTER:
9165           emitPtrByteGet(result, p_type, FALSE);
9166           if ((litval|mask) != 0x00ff)
9167             emitpcode(POC_ANDLW, popGetLit (mask));
9168           if (litval != 0x00)
9169             emitpcode(POC_IORLW, popGetLit (litval));
9170           emitPtrByteSet(result, p_type, TRUE);
9171           break;
9172         
9173         case CPOINTER:
9174           assert( !"trying to assign to bitfield via pointer to __code space" );
9175           break;
9176         
9177         default:
9178           assert( !"unhandled pointer type" );
9179           break;
9180         } // switch
9181       } // if (blen > 1)
9182     }
9183     else
9184     {
9185       /* right is no literal */
9186       if (blen==1) {
9187         switch (p_type)
9188         {
9189         case -1:
9190           /* Note more efficient code, of pre clearing bit then only setting it if required,
9191            * can only be done if it is known that the result is not a SFR */
9192           emitpcode(POC_RRFW,popGet(AOP(right),0));
9193           emitSKPC;
9194           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9195           emitSKPNC;
9196           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9197           break;
9198         
9199         case POINTER:
9200         case FPOINTER:
9201         case GPOINTER:
9202           emitPtrByteGet (result, p_type, FALSE);
9203           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9204           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9205           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9206           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9207           emitPtrByteSet (result, p_type, TRUE);
9208           break;
9209         
9210         case CPOINTER:
9211           assert( !"trying to assign to bitfield via pointer to __code space" );
9212           break;
9213         
9214         default:
9215           assert( !"unhandled pointer type" );
9216           break;
9217         } // switch
9218         return;
9219       } else {
9220         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9221         pCodeOp *temp = popGetTempReg ();
9222
9223         mov2w (AOP(right), 0);
9224         if (blen < 8) {
9225           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9226         }
9227         emitpcode(POC_MOVWF, temp);
9228         if (bstr) {
9229           AccLsh (temp, bstr);
9230         }
9231         
9232         switch (p_type)
9233         {
9234         case -1:
9235           mov2w (AOP(result), 0);
9236           emitpcode(POC_ANDLW, popGetLit (mask));
9237           emitpcode(POC_IORFW, temp);
9238           movwf (AOP(result), 0);
9239           break;
9240         
9241         case POINTER:
9242         case FPOINTER:
9243         case GPOINTER:
9244           emitPtrByteGet (result, p_type, FALSE);
9245           emitpcode(POC_ANDLW, popGetLit (mask));
9246           emitpcode(POC_IORFW, temp);
9247           emitPtrByteSet (result, p_type, TRUE);
9248           break;
9249         
9250         case CPOINTER:
9251           assert( !"trying to assign to bitfield via pointer to __code space" );
9252           break;
9253         
9254         default:
9255           assert( !"unhandled pointer type" );
9256           break;
9257         } // switch
9258
9259         popReleaseTempReg (temp);
9260       } // if (blen > 1)
9261     } // if (AOP(right)->type != AOP_LIT)
9262     return;
9263   } // if (blen <= 8 && ((blen + bstr) <= 8))
9264
9265   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9266 }
9267
9268 /*-----------------------------------------------------------------*/
9269 /* genDataPointerSet - remat pointer to data space                 */
9270 /*-----------------------------------------------------------------*/
9271 static void genDataPointerSet(operand *right,
9272         operand *result,
9273         iCode *ic)
9274 {
9275         int size, offset = 0 ;
9276         int ressize;
9277         
9278         FENTRY;
9279         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9280         aopOp(right,ic,FALSE);
9281         aopOp(result,ic,FALSE);
9282         
9283         assert (IS_SYMOP(result));
9284         assert (IS_PTR(OP_SYM_TYPE(result)));
9285         
9286         if (AOP_TYPE(right) == AOP_LIT)
9287           size = 4;
9288         else
9289           size = AOP_SIZE(right);
9290         ressize = getSize(OP_SYM_ETYPE(result));
9291         if (size > ressize) size = ressize;
9292         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9293         
9294         //assert( !"what's going on here?" );
9295
9296         /*
9297         if ( AOP_TYPE(result) == AOP_PCODE) {
9298         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9299         AOP(result)->aopu.pcop->name,
9300         PCOI(AOP(result)->aopu.pcop)->offset);
9301         }
9302         */
9303         
9304         // tsd, was l+1 - the underline `_' prefix was being stripped
9305         while (size--) {
9306                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9307                 
9308                 if (AOP_TYPE(right) == AOP_LIT) {
9309                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9310                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9311                         if(lit&0xff) {
9312                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9313                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9314                         } else {
9315                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9316                         }
9317                 } else {
9318                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9319                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9320                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9321                 }
9322                 
9323                 offset++;
9324         }
9325         
9326         freeAsmop(right,NULL,ic,TRUE);
9327         freeAsmop(result,NULL,ic,TRUE);
9328 }
9329
9330 /*-----------------------------------------------------------------*/
9331 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9332 /*-----------------------------------------------------------------*/
9333 static void genNearPointerSet (operand *right,
9334                                                            operand *result, 
9335                                                            iCode *ic)
9336 {
9337         asmop *aop = NULL;
9338         sym_link *ptype = operandType(result);
9339         sym_link *retype = getSpec(operandType(right));
9340         sym_link *letype = getSpec(ptype);
9341         int direct = 0;
9342         
9343         
9344         FENTRY;
9345         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346         aopOp(result,ic,FALSE);
9347         
9348 #if 1
9349         /* if the result is rematerializable &
9350         in data space & not a bit variable */
9351         //if (AOP_TYPE(result) == AOP_IMMD &&
9352         if (AOP_TYPE(result) == AOP_PCODE &&
9353                 PIC_IS_DATA_PTR(ptype) &&
9354                 !IS_BITVAR (retype) &&
9355                 !IS_BITVAR (letype)) {
9356                 genDataPointerSet (right,result,ic);
9357                 freeAsmop(result,NULL,ic,TRUE);
9358                 return;
9359         }
9360 #endif
9361
9362         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9363         aopOp(right,ic,FALSE);
9364         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9365         
9366         /* Check if can access directly instead of via a pointer */
9367         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9368                 direct = 1;
9369         }
9370         
9371         if (IS_BITFIELD (letype))
9372         {
9373           genPackBits (letype, result, right, direct?-1:POINTER);
9374           return;
9375         }
9376         
9377         /* If the pointer value is not in a the FSR then need to put it in */
9378         /* Must set/reset IRP bit for use with FSR. */
9379         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9380         if (!direct)
9381                 setup_fsr (result);
9382
9383         {
9384                 /* we have can just get the values */
9385                 int size = AOP_SIZE(right);
9386                 int offset = 0 ;    
9387                 
9388                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9389                 while (size--) {
9390                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9391                         if (*l == '@' ) {
9392                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9393                         } else {
9394                                 if (AOP_TYPE(right) == AOP_LIT) {
9395                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9396                                 } else {
9397                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9398                                 }
9399                                 if (direct)
9400                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9401                                 else
9402                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9403                         }
9404                         if (size && !direct)
9405                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9406                         offset++;
9407                 }
9408         }
9409         
9410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9411         /* now some housekeeping stuff */
9412         if (aop) {
9413                 /* we had to allocate for this iCode */
9414                 freeAsmop(NULL,aop,ic,TRUE);
9415         } else { 
9416                 /* we did not allocate which means left
9417                 already in a pointer register, then
9418                 if size > 0 && this could be used again
9419                 we have to point it back to where it 
9420                 belongs */
9421                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9422                 if (AOP_SIZE(right) > 1 &&
9423                         !OP_SYMBOL(result)->remat &&
9424                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9425                         ic->depth )) {
9426                         int size = AOP_SIZE(right) - 1;
9427                         while (size--)
9428                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9429                 }
9430         }
9431         
9432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433         /* done */
9434
9435         freeAsmop(right,NULL,ic,TRUE);
9436         freeAsmop(result,NULL,ic,TRUE);
9437 }
9438
9439 #if 0
9440 /*-----------------------------------------------------------------*/
9441 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9442 /*-----------------------------------------------------------------*/
9443 static void genPagedPointerSet (operand *right,
9444                                                                 operand *result, 
9445                                                                 iCode *ic)
9446 {
9447         asmop *aop = NULL;
9448         regs *preg = NULL ;
9449         char *rname , *l;
9450         sym_link *retype;
9451         
9452         FENTRY;
9453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9454         
9455         retype= getSpec(operandType(right));
9456         
9457         aopOp(result,ic,FALSE);
9458         
9459         /* if the value is already in a pointer register
9460         then don't need anything more */
9461         if (!AOP_INPREG(AOP(result))) {
9462                 /* otherwise get a free pointer register */
9463                 aop = newAsmop(0);
9464                 preg = getFreePtr(ic,&aop,FALSE);
9465                 pic14_emitcode("mov","%s,%s",
9466                         preg->name,
9467                         aopGet(AOP(result),0,FALSE,TRUE));
9468                 rname = preg->name ;
9469         } else
9470                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9471         
9472         freeAsmop(result,NULL,ic,TRUE);
9473         aopOp (right,ic,FALSE);
9474         
9475         /* if bitfield then unpack the bits */
9476         if (IS_BITFIELD(retype)) 
9477                 genPackBits (retype,result,right,rname,PPOINTER);
9478         else {
9479                 /* we have can just get the values */
9480                 int size = AOP_SIZE(right);
9481                 int offset = 0 ;  
9482                 
9483                 while (size--) {
9484                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9485                         
9486                         MOVA(l);
9487                         pic14_emitcode("movx","@%s,a",rname);
9488                         
9489                         if (size)
9490                                 pic14_emitcode("inc","%s",rname);
9491                         
9492                         offset++;
9493                 }
9494         }
9495         
9496         /* now some housekeeping stuff */
9497         if (aop) {
9498                 /* we had to allocate for this iCode */
9499                 freeAsmop(NULL,aop,ic,TRUE);
9500         } else { 
9501         /* we did not allocate which means left
9502         already in a pointer register, then
9503         if size > 0 && this could be used again
9504         we have to point it back to where it 
9505                 belongs */
9506                 if (AOP_SIZE(right) > 1 &&
9507                         !OP_SYMBOL(result)->remat &&
9508                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9509                         ic->depth )) {
9510                         int size = AOP_SIZE(right) - 1;
9511                         while (size--)
9512                                 pic14_emitcode("dec","%s",rname);
9513                 }
9514         }
9515         
9516         /* done */
9517         freeAsmop(right,NULL,ic,TRUE);
9518         
9519         
9520 }
9521
9522 /*-----------------------------------------------------------------*/
9523 /* genFarPointerSet - set value from far space                     */
9524 /*-----------------------------------------------------------------*/
9525 static void genFarPointerSet (operand *right,
9526                                                           operand *result, iCode *ic)
9527 {
9528         int size, offset ;
9529         sym_link *retype = getSpec(operandType(right));
9530         
9531         FENTRY;
9532         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533         aopOp(result,ic,FALSE);
9534         
9535         /* if the operand is already in dptr 
9536         then we do nothing else we move the value to dptr */
9537         if (AOP_TYPE(result) != AOP_STR) {
9538                 /* if this is remateriazable */
9539                 if (AOP_TYPE(result) == AOP_IMMD)
9540                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9541                 else { /* we need to get it byte by byte */
9542                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9543                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9544                         if (options.model == MODEL_FLAT24)
9545                         {
9546                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9547                         }
9548                 }
9549         }
9550         /* so dptr know contains the address */
9551         freeAsmop(result,NULL,ic,TRUE);
9552         aopOp(right,ic,FALSE);
9553         
9554         /* if bit then unpack */
9555         if (IS_BITFIELD(retype)) 
9556                 genPackBits(retype,result,right,"dptr",FPOINTER);
9557         else {
9558                 size = AOP_SIZE(right);
9559                 offset = 0 ;
9560                 
9561                 while (size--) {
9562                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9563                         MOVA(l);
9564                         pic14_emitcode("movx","@dptr,a");
9565                         if (size)
9566                                 pic14_emitcode("inc","dptr");
9567                 }
9568         }
9569         
9570         freeAsmop(right,NULL,ic,TRUE);
9571 }
9572 #endif
9573
9574 /*-----------------------------------------------------------------*/
9575 /* genGenPointerSet - set value from generic pointer space         */
9576 /*-----------------------------------------------------------------*/
9577 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9578 {
9579         sym_link *retype = getSpec(operandType(result));
9580         
9581         FENTRY;
9582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9583         aopOp(right,ic,FALSE);
9584         aopOp(result,ic,FALSE);
9585
9586         
9587         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9588
9589         if (IS_BITFIELD(retype))
9590         {
9591           genPackBits (retype, result, right, GPOINTER);
9592           return;
9593         }
9594
9595         {
9596           /* emit call to __gptrput */
9597           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9598           int size = AOP_SIZE(right);
9599           int idx = 0;
9600
9601           /* The following assertion fails for
9602            *   struct foo { char a; char b; } bar;
9603            *   void demo(struct foo *dst, char c) { dst->b = c; }
9604            * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9605            * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9606            * of size 2.
9607            * The frontend seems to guarantee that IC_LEFT has the correct size,
9608            * it works fine both for larger and smaller types of `char c'.
9609            * */
9610           //assert (size == getSize(OP_SYM_ETYPE(result)));
9611           assert (size > 0 && size <= 4);
9612
9613           /* pass arguments */
9614           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9615           {
9616             int off = size;
9617             idx = 2;
9618             while (off--)
9619             {
9620               mov2w_op (right, off);
9621               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9622             }
9623             idx = 0;
9624           }
9625           /* - address */
9626           assert (AOP_SIZE(result) == 3);
9627           mov2w(AOP(result), 0);
9628           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9629           mov2w(AOP(result), 1);
9630           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9631           mov2w(AOP(result), 2);
9632           call_libraryfunc (func[size]);
9633         }
9634         
9635         freeAsmop(right,NULL,ic,TRUE);
9636         freeAsmop(result,NULL,ic,TRUE);
9637 }
9638
9639 /*-----------------------------------------------------------------*/
9640 /* genPointerSet - stores the value into a pointer location        */
9641 /*-----------------------------------------------------------------*/
9642 static void genPointerSet (iCode *ic)
9643 {    
9644         operand *right, *result ;
9645         sym_link *type, *etype;
9646         int p_type;
9647         
9648         FENTRY;
9649         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9650         
9651         right = IC_RIGHT(ic);
9652         result = IC_RESULT(ic) ;
9653         
9654         /* depending on the type of pointer we need to
9655         move it to the correct pointer register */
9656         type = operandType(result);
9657         etype = getSpec(type);
9658         /* if left is of type of pointer then it is simple */
9659         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9660                 p_type = DCL_TYPE(type);
9661         }
9662         else {
9663                 /* we have to go by the storage class */
9664                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9665                 
9666                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9667                 /*      p_type = CPOINTER ;  */
9668                 /*  } */
9669                 /*  else */
9670                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9671                 /*    p_type = FPOINTER ; */
9672                 /*      else */
9673                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9674                 /*        p_type = PPOINTER ; */
9675                 /*    else */
9676                 /*        if (SPEC_OCLS(etype) == idata ) */
9677                 /*      p_type = IPOINTER ; */
9678                 /*        else */
9679                 /*      p_type = POINTER ; */
9680         }
9681         
9682         /* now that we have the pointer type we assign
9683         the pointer values */
9684         switch (p_type) {
9685                 
9686         case POINTER:
9687         case FPOINTER:
9688         //case IPOINTER:
9689                 genNearPointerSet (right,result,ic);
9690                 break;
9691 /*
9692         case PPOINTER:
9693                 genPagedPointerSet (right,result,ic);
9694                 break;
9695                 
9696         case FPOINTER:
9697                 genFarPointerSet (right,result,ic);
9698                 break;
9699 */
9700         case GPOINTER:
9701                 genGenPointerSet (right,result,ic);
9702                 break;
9703                 
9704         default:
9705                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9706                         "genPointerSet: illegal pointer type");
9707         }
9708 }
9709
9710 /*-----------------------------------------------------------------*/
9711 /* genIfx - generate code for Ifx statement                        */
9712 /*-----------------------------------------------------------------*/
9713 static void genIfx (iCode *ic, iCode *popIc)
9714 {
9715         operand *cond = IC_COND(ic);
9716         int isbit =0;
9717         
9718         FENTRY;
9719         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9720         
9721         aopOp(cond,ic,FALSE);
9722         
9723         /* get the value into acc */
9724         if (AOP_TYPE(cond) != AOP_CRY)
9725                 pic14_toBoolean(cond);
9726         else
9727                 isbit = 1;
9728         
9729         /* if there was something to be popped then do it */
9730         if (popIc)
9731                 genIpop(popIc);
9732         
9733         if (isbit)
9734         {
9735                 /* This assumes that CARRY is set iff cond is true */
9736                 if (IC_TRUE(ic))
9737                 {
9738                         assert (!IC_FALSE(ic));
9739                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9740                         //emitSKPNC;
9741                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9742                 } else {
9743                         assert (IC_FALSE(ic));
9744                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9745                         //emitSKPC;
9746                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9747                 }
9748                 if (0)
9749                 {
9750                         static int hasWarned = 0;
9751                         if (!hasWarned)
9752                         {
9753                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9754                                 hasWarned = 1;
9755                         }
9756                 }
9757         }
9758         else
9759         {
9760                 /* now Z is set iff !cond */
9761                 if (IC_TRUE(ic))
9762                 {
9763                         assert (!IC_FALSE(ic));
9764                         emitSKPZ;
9765                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9766                 } else {
9767                         emitSKPNZ;
9768                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9769                 }
9770         }
9771         
9772         ic->generated = 1;
9773         
9774         /* the result is now in the accumulator */
9775         freeAsmop(cond,NULL,ic,TRUE);
9776 }
9777
9778 /*-----------------------------------------------------------------*/
9779 /* genAddrOf - generates code for address of                       */
9780 /*-----------------------------------------------------------------*/
9781 static void genAddrOf (iCode *ic)
9782 {
9783         operand *right, *result, *left;
9784         int size, offset ;
9785         
9786         FENTRY;
9787         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9788         
9789         
9790         //aopOp(IC_RESULT(ic),ic,FALSE);
9791         
9792         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9793         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9794         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9795         
9796         DEBUGpic14_AopType(__LINE__,left,right,result);
9797         assert (IS_SYMOP (left));
9798         
9799         /* sanity check: generic pointers to code space are not yet supported,
9800          * pionters to codespace must not be assigned addresses of __data values. */
9801  #if 0
9802         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9803         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)));
9804         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)));
9805         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)));
9806         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)));
9807 #endif
9808
9809         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9810           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9811                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9812                 OP_SYMBOL(left)->name);
9813         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9814           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9815                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9816                 OP_SYMBOL(left)->name);
9817         }
9818         
9819         size = AOP_SIZE(IC_RESULT(ic));
9820         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9821                 /* strip tag */
9822                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9823         }
9824         offset = 0;
9825         
9826         while (size--) {
9827                 /* fixing bug #863624, reported from (errolv) */
9828                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9829                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9830                 
9831 #if 0
9832                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9833                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9834 #endif
9835                 offset++;
9836         }
9837
9838         if (IS_GENPTR(OP_SYM_TYPE(result)))
9839         {
9840                 /* provide correct tag */
9841                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9842                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9843                 movwf (AOP(result), 2);
9844         }
9845         
9846         freeAsmop(left,NULL,ic,FALSE);
9847         freeAsmop(result,NULL,ic,TRUE);
9848         
9849 }
9850
9851 #if 0
9852 /*-----------------------------------------------------------------*/
9853 /* genFarFarAssign - assignment when both are in far space         */
9854 /*-----------------------------------------------------------------*/
9855 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9856 {
9857         int size = AOP_SIZE(right);
9858         int offset = 0;
9859         char *l ;
9860         /* first push the right side on to the stack */
9861         while (size--) {
9862                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9863                 MOVA(l);
9864                 pic14_emitcode ("push","acc");
9865         }
9866         
9867         freeAsmop(right,NULL,ic,FALSE);
9868         /* now assign DPTR to result */
9869         aopOp(result,ic,FALSE);
9870         size = AOP_SIZE(result);
9871         while (size--) {
9872                 pic14_emitcode ("pop","acc");
9873                 aopPut(AOP(result),"a",--offset);
9874         }
9875         freeAsmop(result,NULL,ic,FALSE);
9876         
9877 }
9878 #endif
9879
9880 /*-----------------------------------------------------------------*/
9881 /* genAssign - generate code for assignment                        */
9882 /*-----------------------------------------------------------------*/
9883 static void genAssign (iCode *ic)
9884 {
9885         operand *result, *right;
9886         int size, offset,know_W;
9887         unsigned long lit = 0L;
9888         
9889         result = IC_RESULT(ic);
9890         right  = IC_RIGHT(ic) ;
9891         
9892         FENTRY;
9893         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9894         
9895         /* if they are the same */
9896         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9897                 return ;
9898         
9899         aopOp(right,ic,FALSE);
9900         aopOp(result,ic,TRUE);
9901         
9902         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9903         
9904         /* if they are the same registers */
9905         if (pic14_sameRegs(AOP(right),AOP(result)))
9906                 goto release;
9907
9908         /* special case: assign from __code */
9909         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9910                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9911                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9912                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9913                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9914         {
9915           emitpComment ("genAssign from CODESPACE");
9916           genConstPointerGet (right, result, ic);
9917           goto release;
9918         }
9919         
9920         /* just for symmetry reasons... */
9921         if (!IS_ITEMP(result)
9922                 && IS_SYMOP (result)
9923                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9924         {
9925           assert ( !"cannot write to CODESPACE" );
9926         }
9927
9928         /* if the result is a bit */
9929         if (AOP_TYPE(result) == AOP_CRY) {
9930                 
9931         /* if the right size is a literal then
9932                 we know what the value is */
9933                 if (AOP_TYPE(right) == AOP_LIT) {
9934                         
9935                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9936                                 popGet(AOP(result),0));
9937                         
9938                         if (((int) operandLitValue(right))) 
9939                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9940                                 AOP(result)->aopu.aop_dir,
9941                                 AOP(result)->aopu.aop_dir);
9942                         else
9943                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9944                                 AOP(result)->aopu.aop_dir,
9945                                 AOP(result)->aopu.aop_dir);
9946                         goto release;
9947                 }
9948                 
9949                 /* the right is also a bit variable */
9950                 if (AOP_TYPE(right) == AOP_CRY) {
9951                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9952                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9953                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9954                         
9955                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9956                                 AOP(result)->aopu.aop_dir,
9957                                 AOP(result)->aopu.aop_dir);
9958                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9959                                 AOP(right)->aopu.aop_dir,
9960                                 AOP(right)->aopu.aop_dir);
9961                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9962                                 AOP(result)->aopu.aop_dir,
9963                                 AOP(result)->aopu.aop_dir);
9964                         goto release ;
9965                 }
9966                 
9967                 /* we need to or */
9968                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9969                 pic14_toBoolean(right);
9970                 emitSKPZ;
9971                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9972                 //aopPut(AOP(result),"a",0);
9973                 goto release ;
9974         }
9975         
9976         /* bit variables done */
9977         /* general case */
9978         size = AOP_SIZE(result);
9979         offset = 0 ;
9980         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9981                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9982                 if(aopIdx(AOP(result),0) == 4) {
9983                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9984                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9985                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9986                         goto release;
9987                 } else
9988                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9989         }
9990         
9991         know_W=-1;
9992         while (size--) {
9993         
9994                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9995                 if(AOP_TYPE(right) == AOP_LIT) {
9996                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
9997                         if(lit&0xff) {
9998                                 if(know_W != (int)(lit&0xff))
9999                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10000                                 know_W = lit&0xff;
10001                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10002                         } else
10003                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10004                         
10005                 } else if (AOP_TYPE(right) == AOP_CRY) {
10006                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10007                         if(offset == 0) {
10008                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10009                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10010                         }
10011                 } else {
10012                         mov2w_op (right, offset);
10013                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10014                 }
10015                 
10016                 offset++;
10017         }
10018         
10019         
10020 release:
10021         freeAsmop (right,NULL,ic,FALSE);
10022         freeAsmop (result,NULL,ic,TRUE);
10023 }   
10024
10025 /*-----------------------------------------------------------------*/
10026 /* genJumpTab - genrates code for jump table                       */
10027 /*-----------------------------------------------------------------*/
10028 static void genJumpTab (iCode *ic)
10029 {
10030         symbol *jtab;
10031         char *l;
10032         
10033         FENTRY;
10034         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10035         
10036         aopOp(IC_JTCOND(ic),ic,FALSE);
10037         /* get the condition into accumulator */
10038         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10039         MOVA(l);
10040         /* multiply by three */
10041         pic14_emitcode("add","a,acc");
10042         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10043         
10044         jtab = newiTempLabel(NULL);
10045         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10046         pic14_emitcode("jmp","@a+dptr");
10047         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10048         
10049         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10050         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10051         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10052         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10053         emitSKPNC;
10054         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10055         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10056         emitpLabel(jtab->key);
10057         
10058         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10059         
10060         /* now generate the jump labels */
10061         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10062         jtab = setNextItem(IC_JTLABELS(ic))) {
10063                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10064                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10065                 
10066         }
10067         
10068 }
10069
10070 /*-----------------------------------------------------------------*/
10071 /* genMixedOperation - gen code for operators between mixed types  */
10072 /*-----------------------------------------------------------------*/
10073 /*
10074 TSD - Written for the PIC port - but this unfortunately is buggy.
10075 This routine is good in that it is able to efficiently promote 
10076 types to different (larger) sizes. Unfortunately, the temporary
10077 variables that are optimized out by this routine are sometimes
10078 used in other places. So until I know how to really parse the 
10079 iCode tree, I'm going to not be using this routine :(.
10080 */
10081 static int genMixedOperation (iCode *ic)
10082 {
10083         FENTRY;
10084 #if 0
10085         operand *result = IC_RESULT(ic);
10086         sym_link *ctype = operandType(IC_LEFT(ic));
10087         operand *right = IC_RIGHT(ic);
10088         int ret = 0;
10089         int big,small;
10090         int offset;
10091         
10092         iCode *nextic;
10093         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10094         
10095         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10096         
10097         nextic = ic->next;
10098         if(!nextic)
10099                 return 0;
10100         
10101         nextright = IC_RIGHT(nextic);
10102         nextleft  = IC_LEFT(nextic);
10103         nextresult = IC_RESULT(nextic);
10104         
10105         aopOp(right,ic,FALSE);
10106         aopOp(result,ic,FALSE);
10107         aopOp(nextright,  nextic, FALSE);
10108         aopOp(nextleft,   nextic, FALSE);
10109         aopOp(nextresult, nextic, FALSE);
10110         
10111         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10112                 
10113                 operand *t = right;
10114                 right = nextright;
10115                 nextright = t; 
10116                 
10117                 pic14_emitcode(";remove right +","");
10118                 
10119         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10120         /*
10121         operand *t = right;
10122         right = nextleft;
10123         nextleft = t; 
10124                 */
10125                 pic14_emitcode(";remove left +","");
10126         } else
10127                 return 0;
10128         
10129         big = AOP_SIZE(nextleft);
10130         small = AOP_SIZE(nextright);
10131         
10132         switch(nextic->op) {
10133                 
10134         case '+':
10135                 pic14_emitcode(";optimize a +","");
10136                 /* if unsigned or not an integral type */
10137                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10138                         pic14_emitcode(";add a bit to something","");
10139                 } else {
10140                         
10141                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10142                         
10143                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10144                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10145                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10146                         } else
10147                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10148                         
10149                         offset = 0;
10150                         while(--big) {
10151                                 
10152                                 offset++;
10153                                 
10154                                 if(--small) {
10155                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10156                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10157                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10158                                         }
10159                                         
10160                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10161                                         emitSKPNC;
10162                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10163                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10164                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10165                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10166                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10167                                         
10168                                 } else {
10169                                         pic14_emitcode("rlf","known_zero,w");
10170                                         
10171                                         /*
10172                                         if right is signed
10173                                         btfsc  right,7
10174                                         addlw ff
10175                                         */
10176                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10177                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10178                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10179                                         } else {
10180                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10181                                         }
10182                                 }
10183                         }
10184                         ret = 1;
10185                 }
10186         }
10187         ret = 1;
10188         
10189 release:
10190         freeAsmop(right,NULL,ic,TRUE);
10191         freeAsmop(result,NULL,ic,TRUE);
10192         freeAsmop(nextright,NULL,ic,TRUE);
10193         freeAsmop(nextleft,NULL,ic,TRUE);
10194         if(ret)
10195                 nextic->generated = 1;
10196         
10197         return ret;
10198 #else
10199         return 0;
10200 #endif
10201 }
10202 /*-----------------------------------------------------------------*/
10203 /* genCast - gen code for casting                                  */
10204 /*-----------------------------------------------------------------*/
10205 static void genCast (iCode *ic)
10206 {
10207         operand *result = IC_RESULT(ic);
10208         sym_link *restype = operandType(result);
10209         sym_link *rtype = operandType(IC_RIGHT(ic));
10210         operand *right = IC_RIGHT(ic);
10211         int size, offset ;
10212         
10213         FENTRY;
10214         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10215         /* if they are equivalent then do nothing */
10216         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10217                 return ;
10218         
10219         aopOp(right,ic,FALSE) ;
10220         aopOp(result,ic,FALSE);
10221         
10222         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10223         
10224         /* if the result is a bit */
10225         if (AOP_TYPE(result) == AOP_CRY) {
10226                 assert(!"assigning to bit variables is not supported");
10227         }
10228         
10229         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10230                 int offset = 1;
10231                 size = AOP_SIZE(result);
10232                 
10233                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10234                 
10235                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10236                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10237                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10238                 
10239                 while (size--)
10240                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10241                 
10242                 goto release;
10243         }
10244         
10245         if (IS_PTR(restype))
10246         {
10247           operand *result = IC_RESULT(ic);
10248           //operand *left = IC_LEFT(ic);
10249           operand *right = IC_RIGHT(ic);
10250           int tag = 0xff;
10251           
10252           /* copy common part */
10253           int max, size = AOP_SIZE(result);
10254           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10255           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10256
10257           /* warn if we discard generic opinter tag */
10258           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10259           {
10260             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10261           } // if
10262
10263           max = size;
10264           while (size--)
10265           {
10266             mov2w_op (right, size);
10267             movwf (AOP(result), size);
10268           } // while
10269
10270           /* upcast into generic pointer type? */
10271           if (IS_GENPTR(restype)
10272                 && (size < AOP_SIZE(result))
10273                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10274           {
10275             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10276             if (IS_PTR(rtype))
10277             {
10278               switch (DCL_TYPE(rtype))
10279               {
10280               case POINTER:     /* __data */
10281               case FPOINTER:    /* __data */
10282                 assert (AOP_SIZE(right) == 2);
10283                 tag = GPTRTAG_DATA;
10284                 break;
10285
10286               case CPOINTER:    /* __code */
10287                 assert (AOP_SIZE(right) == 2);
10288                 tag = GPTRTAG_CODE;
10289                 break;
10290                 
10291               case GPOINTER:    /* unknown destination, __data or __code */
10292                 /* assume __data space (address of immediate) */
10293                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10294                 if (AOP(right)->code)
10295                   tag = GPTRTAG_CODE;
10296                 else
10297                   tag = GPTRTAG_DATA;
10298                 break;
10299                 
10300               default:
10301                 assert (!"unhandled pointer type");
10302               } // switch
10303             } else {
10304               /* convert other values into pointers to __data space */
10305               tag = GPTRTAG_DATA;
10306             }
10307
10308             assert (AOP_SIZE(result) == 3);
10309             if (tag == 0) {
10310               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10311             } else {
10312               emitpcode(POC_MOVLW, popGetLit(tag));
10313               movwf(AOP(result), 2);
10314             }
10315           } else {
10316             addSign(result, max, 0);
10317           } // if
10318           goto release;
10319         }
10320         
10321         /* if they are the same size : or less */
10322         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10323                 
10324                 /* if they are in the same place */
10325                 if (pic14_sameRegs(AOP(right),AOP(result)))
10326                         goto release;
10327                 
10328                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10329                 if (IS_PTR_CONST(rtype))
10330                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10331                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10332                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10333                 
10334                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10335                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10336                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10337                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10338                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10339                         if(AOP_SIZE(result) <2)
10340                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10341                         
10342                 } else {
10343                         
10344                         /* if they in different places then copy */
10345                         size = AOP_SIZE(result);
10346                         offset = 0 ;
10347                         while (size--) {
10348                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10349                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10350                                 
10351                                 //aopPut(AOP(result),
10352                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10353                                 // offset);
10354                                 
10355                                 offset++;
10356                         }
10357                 }
10358                 goto release;
10359         }
10360         
10361         /* so we now know that the size of destination is greater
10362         than the size of the source.
10363         Now, if the next iCode is an operator then we might be
10364         able to optimize the operation without performing a cast.
10365         */
10366         if(0 && genMixedOperation(ic)) {
10367                 /* XXX: cannot optimize: must copy regs! */
10368                 goto release;
10369         }
10370         
10371         /* we move to result for the size of source */
10372         size = AOP_SIZE(right);
10373         offset = 0 ;
10374         while (size--) {
10375                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10376                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10377                 offset++;
10378         }
10379
10380         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10381
10382 release:
10383         freeAsmop(right,NULL,ic,TRUE);
10384         freeAsmop(result,NULL,ic,TRUE);
10385         
10386 }
10387
10388 /*-----------------------------------------------------------------*/
10389 /* genDjnz - generate decrement & jump if not zero instrucion      */
10390 /*-----------------------------------------------------------------*/
10391 static int genDjnz (iCode *ic, iCode *ifx)
10392 {
10393         symbol *lbl, *lbl1;
10394         FENTRY;
10395         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10396         
10397         if (!ifx)
10398                 return 0;
10399         
10400                 /* if the if condition has a false label
10401         then we cannot save */
10402         if (IC_FALSE(ifx))
10403                 return 0;
10404         
10405                 /* if the minus is not of the form 
10406         a = a - 1 */
10407         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10408                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10409                 return 0;
10410         
10411         if (operandLitValue(IC_RIGHT(ic)) != 1)
10412                 return 0;
10413         
10414                 /* if the size of this greater than one then no
10415         saving */
10416         if (getSize(operandType(IC_RESULT(ic))) > 1)
10417                 return 0;
10418         
10419         /* otherwise we can save BIG */
10420         lbl = newiTempLabel(NULL);
10421         lbl1= newiTempLabel(NULL);
10422         
10423         aopOp(IC_RESULT(ic),ic,FALSE);
10424         
10425         if (IS_AOP_PREG(IC_RESULT(ic))) {
10426                 pic14_emitcode("dec","%s",
10427                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10428                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10429                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10430         } else {  
10431                 
10432                 
10433                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10434                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10435                 
10436                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10437                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10438                 
10439         }
10440         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10441         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10442         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10443         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10444         
10445         
10446         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10447         ifx->generated = 1;
10448         return 1;
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genReceive - generate code for a receive iCode                  */
10453 /*-----------------------------------------------------------------*/
10454 static void genReceive (iCode *ic)
10455 {
10456         FENTRY;
10457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10458         
10459         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10460                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10461                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10462                 
10463                 int size = getSize(operandType(IC_RESULT(ic)));
10464                 int offset =  fReturnSizePic - size;
10465                 while (size--) {
10466                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10467                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10468                         offset++;
10469                 }
10470                 aopOp(IC_RESULT(ic),ic,FALSE);
10471                 size = AOP_SIZE(IC_RESULT(ic));
10472                 offset = 0;
10473                 while (size--) {
10474                         pic14_emitcode ("pop","acc");
10475                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10476                 }
10477                 
10478         } else {
10479                 _G.accInUse++;
10480                 aopOp(IC_RESULT(ic),ic,FALSE);
10481                 _G.accInUse--;
10482                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10483                 assignResultValue(IC_RESULT(ic));
10484         }
10485         
10486         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10487 }
10488
10489 /*-----------------------------------------------------------------*/
10490 /* genDummyRead - generate code for dummy read of volatiles        */
10491 /*-----------------------------------------------------------------*/
10492 static void
10493 genDummyRead (iCode * ic)
10494 {
10495         FENTRY;
10496         pic14_emitcode ("; genDummyRead","");
10497         pic14_emitcode ("; not implemented","");
10498         
10499         ic = ic;
10500 }
10501
10502 /*-----------------------------------------------------------------*/
10503 /* genpic14Code - generate code for pic14 based controllers        */
10504 /*-----------------------------------------------------------------*/
10505 /*
10506 * At this point, ralloc.c has gone through the iCode and attempted
10507 * to optimize in a way suitable for a PIC. Now we've got to generate
10508 * PIC instructions that correspond to the iCode.
10509 *
10510 * Once the instructions are generated, we'll pass through both the
10511 * peep hole optimizer and the pCode optimizer.
10512 *-----------------------------------------------------------------*/
10513
10514 void genpic14Code (iCode *lic)
10515 {
10516         iCode *ic;
10517         int cln = 0;
10518         const char *cline;
10519         
10520         FENTRY;
10521         lineHead = lineCurr = NULL;
10522         
10523         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10524         addpBlock(pb);
10525         
10526         /* if debug information required */
10527         if (options.debug && debugFile && currFunc) { 
10528                 debugFile->writeFunction (currFunc, lic);
10529         }
10530         
10531         
10532         for (ic = lic ; ic ; ic = ic->next ) {
10533                 
10534                 //DEBUGpic14_emitcode(";ic","");
10535                 //fprintf (stderr, "in ic loop\n");
10536                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10537                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10538                 
10539                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10540                   cln = ic->lineno;
10541                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10542                   cline = printCLine (ic->filename, ic->lineno);
10543                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10544                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10545                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10546                 }
10547                 
10548                 if (options.iCodeInAsm) {
10549                   char *iLine = printILine(ic);
10550                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10551                   dbuf_free(iLine);
10552                 }
10553                 /* if the result is marked as
10554                 spilt and rematerializable or code for
10555                 this has already been generated then
10556                 do nothing */
10557                 if (resultRemat(ic) || ic->generated ) 
10558                         continue ;
10559                 
10560                 /* depending on the operation */
10561                 switch (ic->op) {
10562                 case '!' :
10563                         genNot(ic);
10564                         break;
10565                         
10566                 case '~' :
10567                         genCpl(ic);
10568                         break;
10569                         
10570                 case UNARYMINUS:
10571                         genUminus (ic);
10572                         break;
10573                         
10574                 case IPUSH:
10575                         genIpush (ic);
10576                         break;
10577                         
10578                 case IPOP:
10579                         /* IPOP happens only when trying to restore a 
10580                         spilt live range, if there is an ifx statement
10581                         following this pop then the if statement might
10582                         be using some of the registers being popped which
10583                         would destory the contents of the register so
10584                         we need to check for this condition and handle it */
10585                         if (ic->next            && 
10586                                 ic->next->op == IFX &&
10587                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10588                                 genIfx (ic->next,ic);
10589                         else
10590                                 genIpop (ic);
10591                         break; 
10592                         
10593                 case CALL:
10594                         genCall (ic);
10595                         break;
10596                         
10597                 case PCALL:
10598                         genPcall (ic);
10599                         break;
10600                         
10601                 case FUNCTION:
10602                         genFunction (ic);
10603                         break;
10604                         
10605                 case ENDFUNCTION:
10606                         genEndFunction (ic);
10607                         break;
10608                         
10609                 case RETURN:
10610                         genRet (ic);
10611                         break;
10612                         
10613                 case LABEL:
10614                         genLabel (ic);
10615                         break;
10616                         
10617                 case GOTO:
10618                         genGoto (ic);
10619                         break;
10620                         
10621                 case '+' :
10622                         genPlus (ic) ;
10623                         break;
10624                         
10625                 case '-' :
10626                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10627                                 genMinus (ic);
10628                         break;
10629                         
10630                 case '*' :
10631                         genMult (ic);
10632                         break;
10633                         
10634                 case '/' :
10635                         genDiv (ic) ;
10636                         break;
10637                         
10638                 case '%' :
10639                         genMod (ic);
10640                         break;
10641                         
10642                 case '>' :
10643                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10644                         break;
10645                         
10646                 case '<' :
10647                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10648                         break;
10649                         
10650                 case LE_OP:
10651                 case GE_OP:
10652                 case NE_OP:
10653                         
10654                         /* note these two are xlated by algebraic equivalence
10655                         during parsing SDCC.y */
10656                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10657                                 "got '>=' or '<=' shouldn't have come here");
10658                         break;  
10659                         
10660                 case EQ_OP:
10661                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10662                         break;      
10663                         
10664                 case AND_OP:
10665                         genAndOp (ic);
10666                         break;
10667                         
10668                 case OR_OP:
10669                         genOrOp (ic);
10670                         break;
10671                         
10672                 case '^' :
10673                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10674                         break;
10675                         
10676                 case '|' :
10677                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10678                         break;
10679                         
10680                 case BITWISEAND:
10681                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10682                         break;
10683                         
10684                 case INLINEASM:
10685                         genInline (ic);
10686                         break;
10687                         
10688                 case RRC:
10689                         genRRC (ic);
10690                         break;
10691                         
10692                 case RLC:
10693                         genRLC (ic);
10694                         break;
10695                         
10696                 case GETHBIT:
10697                         genGetHbit (ic);
10698                         break;
10699                         
10700                 case LEFT_OP:
10701                         genLeftShift (ic);
10702                         break;
10703                         
10704                 case RIGHT_OP:
10705                         genRightShift (ic);
10706                         break;
10707                         
10708                 case GET_VALUE_AT_ADDRESS:
10709                         genPointerGet(ic);
10710                         break;
10711                         
10712                 case '=' :
10713                         if (POINTER_SET(ic))
10714                                 genPointerSet(ic);
10715                         else
10716                                 genAssign(ic);
10717                         break;
10718                         
10719                 case IFX:
10720                         genIfx (ic,NULL);
10721                         break;
10722                         
10723                 case ADDRESS_OF:
10724                         genAddrOf (ic);
10725                         break;
10726                         
10727                 case JUMPTABLE:
10728                         genJumpTab (ic);
10729                         break;
10730                         
10731                 case CAST:
10732                         genCast (ic);
10733                         break;
10734                         
10735                 case RECEIVE:
10736                         genReceive(ic);
10737                         break;
10738                         
10739                 case SEND:
10740                         addSet(&_G.sendSet,ic);
10741                         break;
10742                         
10743                 case DUMMY_READ_VOLATILE:
10744                         genDummyRead (ic);
10745                         break;
10746                         
10747                 default :
10748                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10749                         ic = ic;
10750                         break;
10751                 }
10752         }
10753
10754         
10755         /* now we are ready to call the
10756         peep hole optimizer */
10757         if (!options.nopeep) {
10758                 peepHole (&lineHead);
10759         }
10760         /* now do the actual printing */
10761         printLine (lineHead,codeOutBuf);
10762         
10763 #ifdef PCODE_DEBUG
10764         DFPRINTF((stderr,"printing pBlock\n\n"));
10765         printpBlock(stdout,pb);
10766 #endif
10767         
10768         return;
10769 }
10770
10771 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10772  * (meaning: representing its own address) or not (referencing its contents).
10773  * This can only be decided based on the operand's type. */
10774 int
10775 aop_isLitLike (asmop *aop)
10776 {
10777   assert (aop);
10778   if (aop->type == AOP_LIT) return 1;
10779 if (aop->type == AOP_IMMD) return 1;
10780   if ((aop->type == AOP_PCODE) &&
10781                 ((aop->aopu.pcop->type == PO_LITERAL)))
10782   {
10783     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10784      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10785     return 1;
10786   }
10787   return 0;
10788 }
10789
10790 int
10791 op_isLitLike (operand *op)
10792 {
10793   assert (op);
10794   if (aop_isLitLike (AOP(op))) return 1;
10795   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10796   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10797   return 0;
10798 }
10799